diff --git a/src/main/java/io/redspace/ironsspellbooks/api/registry/SpellRegistry.java b/src/main/java/io/redspace/ironsspellbooks/api/registry/SpellRegistry.java index 9ae2883e8..2273eba68 100644 --- a/src/main/java/io/redspace/ironsspellbooks/api/registry/SpellRegistry.java +++ b/src/main/java/io/redspace/ironsspellbooks/api/registry/SpellRegistry.java @@ -122,6 +122,7 @@ public static AbstractSpell getSpell(ResourceLocation resourceLocation) { public static final RegistryObject MAGMA_BOMB_SPELL = registerSpell(new MagmaBombSpell()); public static final RegistryObject WALL_OF_FIRE_SPELL = registerSpell(new WallOfFireSpell()); public static final RegistryObject HEAT_SURGE_SPELL = registerSpell(new HeatSurgeSpell()); + public static final RegistryObject FLAMING_STRIKE = registerSpell(new FlamingStrikeSpell()); // HOLY public static final RegistryObject ANGEL_WINGS_SPELL = registerSpell(new AngelWingsSpell()); diff --git a/src/main/java/io/redspace/ironsspellbooks/api/util/Utils.java b/src/main/java/io/redspace/ironsspellbooks/api/util/Utils.java index 4d9ab239d..13adada1a 100644 --- a/src/main/java/io/redspace/ironsspellbooks/api/util/Utils.java +++ b/src/main/java/io/redspace/ironsspellbooks/api/util/Utils.java @@ -604,4 +604,18 @@ public static void loadAllItems(CompoundTag pTag, NonNullList pList, } } } + + public static float getWeaponDamage(LivingEntity entity, MobType entityForDamageBonus) { + if (entity != null) { + float weapon = (float) (entity.getAttributeValue(Attributes.ATTACK_DAMAGE)); + float fist = (float) (entity.getAttributeBaseValue(Attributes.ATTACK_DAMAGE)); + if (weapon == fist) { + //Remove fist damage if they are not using a melee weapon + weapon -= fist; + } + float enchant = EnchantmentHelper.getDamageBonus(entity.getMainHandItem(),entityForDamageBonus); + return weapon + enchant; + } + return 0; + } } diff --git a/src/main/java/io/redspace/ironsspellbooks/entity/spells/flame_strike/FlameStrike.java b/src/main/java/io/redspace/ironsspellbooks/entity/spells/flame_strike/FlameStrike.java index 00b65ef95..b60c26dcd 100644 --- a/src/main/java/io/redspace/ironsspellbooks/entity/spells/flame_strike/FlameStrike.java +++ b/src/main/java/io/redspace/ironsspellbooks/entity/spells/flame_strike/FlameStrike.java @@ -13,6 +13,7 @@ import net.minecraft.world.level.Level; import net.minecraftforge.network.NetworkHooks; +//TODO: well, this really could've been a particle. However, it already works. public class FlameStrike extends AoeEntity { public FlameStrike(EntityType pEntityType, Level pLevel) { super(pEntityType, pLevel); @@ -20,19 +21,12 @@ public FlameStrike(EntityType pEntityType, Level pLevel) { LivingEntity target; - public FlameStrike(Level level, LivingEntity owner, LivingEntity target) { + public FlameStrike(Level level) { this(EntityRegistry.FLAME_STRIKE.get(), level); - setOwner(owner); - this.target = target; } @Override public void applyEffect(LivingEntity target) { - if (target == this.target) { - if (DamageSources.applyDamage(target, getDamage(), SpellRegistry.DEVOUR_SPELL.get().getDamageSource(this, getOwner())) && getOwner() instanceof LivingEntity livingOwner) { - - } - } } public final int ticksPerFrame = 2; diff --git a/src/main/java/io/redspace/ironsspellbooks/entity/spells/flame_strike/FlameStrikeRenderer.java b/src/main/java/io/redspace/ironsspellbooks/entity/spells/flame_strike/FlameStrikeRenderer.java index 4f4402c9e..cd151eef0 100644 --- a/src/main/java/io/redspace/ironsspellbooks/entity/spells/flame_strike/FlameStrikeRenderer.java +++ b/src/main/java/io/redspace/ironsspellbooks/entity/spells/flame_strike/FlameStrikeRenderer.java @@ -35,7 +35,7 @@ public void render(FlameStrike entity, float yaw, float partialTicks, PoseStack Pose pose = poseStack.last(); Matrix4f poseMatrix = pose.pose(); Matrix3f normalMatrix = pose.normal(); - poseStack.mulPose(Vector3f.YP.rotationDegrees(Mth.lerp(partialTicks, entity.yRotO, entity.getYRot()))); + poseStack.mulPose(Vector3f.YP.rotationDegrees(90 - Mth.lerp(partialTicks, entity.yRotO, entity.getYRot()))); poseStack.mulPose(Vector3f.XP.rotationDegrees(-Mth.lerp(partialTicks, entity.xRotO, entity.getXRot()))); // poseStack.mulPose(Vector3f.ZP.rotationDegrees(((entity.animationSeed % 30) - 15) * (float) Math.sin(entity.animationTime * .015))); diff --git a/src/main/java/io/redspace/ironsspellbooks/spells/fire/FlamingStrikeSpell.java b/src/main/java/io/redspace/ironsspellbooks/spells/fire/FlamingStrikeSpell.java new file mode 100644 index 000000000..d9db1e35a --- /dev/null +++ b/src/main/java/io/redspace/ironsspellbooks/spells/fire/FlamingStrikeSpell.java @@ -0,0 +1,148 @@ +package io.redspace.ironsspellbooks.spells.fire; + +import io.redspace.ironsspellbooks.IronsSpellbooks; +import io.redspace.ironsspellbooks.api.config.DefaultConfig; +import io.redspace.ironsspellbooks.api.magic.MagicData; +import io.redspace.ironsspellbooks.api.registry.SchoolRegistry; +import io.redspace.ironsspellbooks.api.spells.*; +import io.redspace.ironsspellbooks.api.util.AnimationHolder; +import io.redspace.ironsspellbooks.api.util.CameraShakeData; +import io.redspace.ironsspellbooks.api.util.CameraShakeManager; +import io.redspace.ironsspellbooks.api.util.Utils; +import io.redspace.ironsspellbooks.capabilities.magic.MagicManager; +import io.redspace.ironsspellbooks.damage.DamageSources; +import io.redspace.ironsspellbooks.damage.ISpellDamageSource; +import io.redspace.ironsspellbooks.entity.spells.flame_strike.FlameStrike; +import io.redspace.ironsspellbooks.particle.ShockwaveParticleOptions; +import io.redspace.ironsspellbooks.registries.SoundRegistry; +import io.redspace.ironsspellbooks.util.ParticleHelper; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.MobType; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Optional; + +@AutoSpellConfig +public class FlamingStrikeSpell extends AbstractSpell { + private final ResourceLocation spellId = new ResourceLocation(IronsSpellbooks.MODID, "flaming_strike"); + + @Override + public List getUniqueInfo(int spellLevel, LivingEntity caster) { + return List.of(Component.translatable("ui.irons_spellbooks.damage", getDamageText(spellLevel, caster))); + } + + private final DefaultConfig defaultConfig = new DefaultConfig() + .setMinRarity(SpellRarity.COMMON) + .setSchoolResource(SchoolRegistry.HOLY_RESOURCE) + .setMaxLevel(5) + .setCooldownSeconds(15) + .build(); + + public FlamingStrikeSpell() { + this.manaCostPerLevel = 15; + this.baseSpellPower = 5; + this.spellPowerPerLevel = 3; + this.castTime = 16; + this.baseManaCost = 30; + } + + @Override + public boolean canBeInterrupted(Player player) { + return false; + } + + @Override + public int getEffectiveCastTime(int spellLevel, @Nullable LivingEntity entity) { + //due to melee animation timing, we do not want cast time attribute to affect this spell + return getCastTime(spellLevel); + } + + @Override + public CastType getCastType() { + return CastType.LONG; + } + + @Override + public DefaultConfig getDefaultConfig() { + return defaultConfig; + } + + @Override + public ResourceLocation getSpellResource() { + return spellId; + } + + @Override + public Optional getCastStartSound() { + return Optional.of(SoundRegistry.DIVINE_SMITE_WINDUP.get()); + } + + @Override + public Optional getCastFinishSound() { + return Optional.of(SoundRegistry.DIVINE_SMITE_CAST.get()); + } + + @Override + public void onCast(Level level, int spellLevel, LivingEntity entity, MagicData playerMagicData) { + float radius = 2.5f; + Vec3 hitLocation = entity.position().add(0, entity.getBbHeight() * .4f, 0).add(entity.getForward().multiply(1.45f, 0, 1.45f)); + var entities = level.getEntities(entity, AABB.ofSize(hitLocation, radius * 2, radius, radius * 2)); + for (Entity targetEntity : entities) { + if (entity.distanceTo(targetEntity) < radius && Utils.hasLineOfSight(level, hitLocation, targetEntity.getBoundingBox().getCenter(), true)) { + if (DamageSources.applyDamage(targetEntity, getDamage(spellLevel, entity), this.getDamageSource(entity))) { + MagicManager.spawnParticles(level, ParticleHelper.EMBERS, targetEntity.getX(), targetEntity.getY() + targetEntity.getBbHeight() * .5f, targetEntity.getZ(), 50, targetEntity.getBbWidth() * .5f, targetEntity.getBbHeight() * .5f, targetEntity.getBbWidth() * .5f, .03, false); + } + } + } + FlameStrike flameStrike = new FlameStrike(level); + flameStrike.moveTo(hitLocation); + flameStrike.setYRot(entity.getYRot()); + level.addFreshEntity(flameStrike); + super.onCast(level, spellLevel, entity, playerMagicData); + } + + @Override + public DamageSource getDamageSource(@Nullable Entity projectile, Entity attacker) { + return ((ISpellDamageSource) super.getDamageSource(projectile, attacker)).setFireTime(3).get(); + } + + private float getDamage(int spellLevel, LivingEntity entity) { + return getSpellPower(spellLevel, entity) + Utils.getWeaponDamage(entity, MobType.UNDEFINED); + } + + + private String getDamageText(int spellLevel, LivingEntity entity) { + if (entity != null) { + float weaponDamage = Utils.getWeaponDamage(entity, MobType.UNDEFINED); + String plus = ""; + if (weaponDamage > 0) { + plus = String.format(" (+%s)", Utils.stringTruncation(weaponDamage, 1)); + } + String damage = Utils.stringTruncation(getDamage(spellLevel, entity), 1); + return damage + plus; + } + return "" + getSpellPower(spellLevel, entity); + } + + @Override + public AnimationHolder getCastStartAnimation() { + return SpellAnimations.OVERHEAD_MELEE_SWING_ANIMATION; + } + + @Override + public AnimationHolder getCastFinishAnimation() { + return AnimationHolder.pass(); + } +} diff --git a/src/main/java/io/redspace/ironsspellbooks/spells/holy/DivineSmiteSpell.java b/src/main/java/io/redspace/ironsspellbooks/spells/holy/DivineSmiteSpell.java index 23676ef63..bd79e7c63 100644 --- a/src/main/java/io/redspace/ironsspellbooks/spells/holy/DivineSmiteSpell.java +++ b/src/main/java/io/redspace/ironsspellbooks/spells/holy/DivineSmiteSpell.java @@ -95,7 +95,7 @@ public Optional getCastFinishSound() { @Override public void onCast(Level level, int spellLevel, LivingEntity entity, MagicData playerMagicData) { float radius = 1.75f; - Vec3 smiteLocation = Utils.moveToRelativeGroundLevel(level, entity.getEyePosition().add(entity.getForward().multiply(1, 0, 1).normalize().scale(1.35f)), 2); + Vec3 smiteLocation = Utils.moveToRelativeGroundLevel(level, entity.getEyePosition().add(entity.getForward().multiply(1.35f, 0, 1.35f)), 1); MagicManager.spawnParticles(level, new ShockwaveParticleOptions(SchoolRegistry.HOLY.get().getTargetingColor(), radius * 2, true), smiteLocation.x, smiteLocation.y + .15f, smiteLocation.z, 1, 0, 0, 0, 0, true); MagicManager.spawnParticles(level, ParticleTypes.ELECTRIC_SPARK, smiteLocation.x, smiteLocation.y + .15f, smiteLocation.z, 50, 0, 0, 0, 1, false); CameraShakeManager.addCameraShake(new CameraShakeData(10, smiteLocation, 10)); @@ -110,28 +110,14 @@ public void onCast(Level level, int spellLevel, LivingEntity entity, MagicData p } private float getDamage(int spellLevel, LivingEntity entity) { - //IronsSpellbooks.LOGGER.debug("SmitingStrikeSpell.getDamage {} + {} + {}", getSpellPower(spellLevel, entity), base, enchant); - return getSpellPower(spellLevel, entity) + getWeaponDamage(entity); + //Setting mob type to undead means the smite enchantment also adds to the spell's damage. Seems fitting. + return getSpellPower(spellLevel, entity) + Utils.getWeaponDamage(entity, MobType.UNDEAD); } - private float getWeaponDamage(LivingEntity entity) { - if (entity != null) { - float weapon = (float) (entity.getAttributeValue(Attributes.ATTACK_DAMAGE)); - float fist = (float) (entity.getAttributeBaseValue(Attributes.ATTACK_DAMAGE)); - if (weapon == fist) { - //Remove fist damage if they are not using a melee weapon - weapon -= fist; - } - //Setting mob type to undead means the smite enchantment also adds to the spell's damage. Seems fitting. - float enchant = EnchantmentHelper.getDamageBonus(entity.getMainHandItem(), MobType.UNDEAD); - return weapon + enchant; - } - return 0; - } private String getDamageText(int spellLevel, LivingEntity entity) { if (entity != null) { - float weaponDamage = getWeaponDamage(entity); + float weaponDamage = Utils.getWeaponDamage(entity, MobType.UNDEAD); String plus = ""; if (weaponDamage > 0) { plus = String.format(" (+%s)", Utils.stringTruncation(weaponDamage, 1));