Skip to content

Commit

Permalink
thunderstorm spell functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
iron431 committed May 13, 2024
1 parent 61a6076 commit 000c8a6
Show file tree
Hide file tree
Showing 13 changed files with 217 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ public static void onConfigReload() {
public static final RegistryObject<AbstractSpell> LIGHTNING_LANCE_SPELL = registerSpell(new LightningLanceSpell());
//public static final RegistryObject<AbstractSpell> THUNDER_STEP_SPELL = registerSpell(new ThunderStepSpell());
public static final RegistryObject<AbstractSpell> SHOCKWAVE_SPELL = registerSpell(new ShockwaveSpell());
public static final RegistryObject<AbstractSpell> THUNDERSTORM_SPELL = registerSpell(new ThunderstormSpell());

// NATURE
public static final RegistryObject<AbstractSpell> ACID_ORB_SPELL = registerSpell(new AcidOrbSpell());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.redspace.ironsspellbooks.effect;

import io.redspace.ironsspellbooks.api.registry.SpellRegistry;
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.EchoingStrikeEntity;
import io.redspace.ironsspellbooks.entity.spells.LightningStrike;
import io.redspace.ironsspellbooks.registries.MobEffectRegistry;
import io.redspace.ironsspellbooks.util.ParticleHelper;
import net.minecraft.world.effect.MobEffectCategory;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

import javax.annotation.Nullable;

@Mod.EventBusSubscriber
public class ThunderstormEffect extends MagicMobEffect {
public ThunderstormEffect(MobEffectCategory pCategory, int pColor) {
super(pCategory, pColor);
}

@Override
public boolean isDurationEffectTick(int pDuration, int pAmplifier) {
return pDuration % 40 == 0;
}

@Override
public void applyEffectTick(LivingEntity entity, int pAmplifier) {
var radiusSqr = 400; //20
entity.level.getEntitiesOfClass(LivingEntity.class, entity.getBoundingBox().inflate(20, 12, 20),
livingEntity -> livingEntity != entity &&
horizontalDistanceSqr(livingEntity, entity) < radiusSqr &&
livingEntity.isPickable() &&
!livingEntity.isSpectator() &&
!DamageSources.isFriendlyFireBetween(livingEntity, entity) &&
Utils.hasLineOfSight(entity.level, entity, livingEntity, false)
)
.forEach(targetEntity -> {
LightningStrike lightningStrike = new LightningStrike(entity.level);
lightningStrike.setOwner(entity);
lightningStrike.setDamage(getDamageFromAmplifier(pAmplifier, entity));
lightningStrike.setPos(targetEntity.position());
entity.level.addFreshEntity(lightningStrike);
});
}

private float horizontalDistanceSqr(LivingEntity livingEntity, LivingEntity entity2) {
var dx = livingEntity.getX() - entity2.getX();
var dz = livingEntity.getZ() - entity2.getZ();
return (float) (dx * dx + dz * dz);
}

public static float getDamageFromAmplifier(int effectAmplifier, @Nullable LivingEntity caster) {
var power = caster == null ? 1 : SpellRegistry.THUNDERSTORM_SPELL.get().getEntityPowerMultiplier(caster);
return (((effectAmplifier - 7) * power) + 7);
}
}
Original file line number Diff line number Diff line change
@@ -1,40 +1,65 @@
package io.redspace.ironsspellbooks.entity.spells;

import io.redspace.ironsspellbooks.api.registry.SchoolRegistry;
import io.redspace.ironsspellbooks.api.registry.SpellRegistry;
import io.redspace.ironsspellbooks.api.util.Utils;
import io.redspace.ironsspellbooks.capabilities.magic.MagicManager;
import io.redspace.ironsspellbooks.damage.DamageSources;
import io.redspace.ironsspellbooks.particle.ShockwaveParticleOptions;
import io.redspace.ironsspellbooks.particle.SparkParticleOptions;
import io.redspace.ironsspellbooks.particle.ZapParticleOption;
import io.redspace.ironsspellbooks.registries.EntityRegistry;
import io.redspace.ironsspellbooks.registries.SoundRegistry;
import io.redspace.ironsspellbooks.util.ParticleHelper;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;

import java.util.Optional;

public class LightningStrike extends AoeEntity {
public LightningStrike(EntityType<? extends Projectile> pEntityType, Level pLevel) {
super(pEntityType, pLevel);
setRadius(3);
setCircular();
}

public LightningStrike(Level level) {
this(EntityRegistry.LIGHTNING_STRIKE.get(), level);
}

static final int chargeTime = 20;
static final int vfxHeight = 15;
@Override
public void tick() {
if (level.isClientSide) {
return;
}
if (tickCount == 1) {
int total = 5;
int light = Utils.random.nextInt(total);
Vec3 location = this.position().add(0, vfxHeight, 0);
MagicManager.spawnParticles(level, ParticleHelper.FOG_THUNDER_LIGHT, location.x, location.y, location.z, light, 1, 1, 1, 1, true);
MagicManager.spawnParticles(level, ParticleHelper.FOG_THUNDER_DARK, location.x, location.y, location.z, total - light, 1, 1, 1, 1, true);
MagicManager.spawnParticles(level, new ShockwaveParticleOptions(SchoolRegistry.LIGHTNING.get().getTargetingColor(), chargeTime * -1.5f * .05f, true), getX(), getY(), getZ(), 1, 0, 0, 0, 0, true);
}
if (tickCount == chargeTime) {
checkHits();
MagicManager.spawnParticles(level, ParticleHelper.ELECTRIC_SPARKS, getX(), getY(), getZ(), 25, .2f, .2f, .2f, .25, true);
MagicManager.spawnParticles(level, ParticleHelper.FIERY_SPARKS, getX(), getY(), getZ(), 5, .2f, .2f, .2f, .125, true);
MagicManager.spawnParticles(level, new ZapParticleOption(this.position().add(0, 20, 0)), getX(), getY(), getZ(), 1, 0, 0, 0, 0, true);
playSound(SoundRegistry.CHAIN_LIGHTNING_CHAIN.get(),2f,.5f+random.nextFloat());
MagicManager.spawnParticles(level, ParticleHelper.ELECTRIC_SPARKS, getX(), getY(), getZ(), 25, .2f, .2f, .2f, .25, true);
MagicManager.spawnParticles(level, ParticleHelper.FIERY_SPARKS, getX(), getY(), getZ(), 5, .2f, .2f, .2f, .125, true);
Vec3 bottom = this.position();
Vec3 top = bottom.add(0, vfxHeight, 0);
Vec3 middle = bottom.add(Utils.getRandomScaled(2), Utils.random.nextIntBetweenInclusive(3, vfxHeight - 3), Utils.getRandomScaled(2));
MagicManager.spawnParticles(level, new ZapParticleOption(top), middle.x, middle.y, middle.z, 1, 0, 0, 0, 0, true);
MagicManager.spawnParticles(level, new ZapParticleOption(middle), getX(), getY(), getZ(), 1, 0, 0, 0, 0, true);
if (Utils.random.nextFloat() < .3f) {
Vec3 split = middle.add(Utils.getRandomScaled(2), -Math.abs(Utils.getRandomScaled(2)), Utils.getRandomScaled(2));
MagicManager.spawnParticles(level, new ZapParticleOption(middle), split.x, split.y, split.z, 1, 0, 0, 0, 0, true);
}
playSound(SoundRegistry.SMALL_LIGHTNING_STRIKE.get(), 2f, .8f + random.nextFloat() * .5f);
}
if (this.tickCount > chargeTime) {
discard();
Expand All @@ -43,7 +68,7 @@ public void tick() {

@Override
public void applyEffect(LivingEntity target) {

DamageSources.applyDamage(target, getDamage(), SpellRegistry.THUNDERSTORM_SPELL.get().getDamageSource(this, getOwner()));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -485,11 +485,12 @@ public static void register(IEventBus eventBus) {
.clientTrackingRange(64)
.build(new ResourceLocation(IronsSpellbooks.MODID, "stomp_aoe").toString()));

// public static final RegistryObject<EntityType<LightningStrike>> LIGHTNING_STRIKE =
// ENTITIES.register("lightning_strike", () -> EntityType.Builder.<LightningStrike>of(LightningStrike::new, MobCategory.MISC)
// .sized(1f, 1f)
// .clientTrackingRange(64)
// .build(new ResourceLocation(IronsSpellbooks.MODID, "lightning_strike").toString()));
public static final RegistryObject<EntityType<LightningStrike>> LIGHTNING_STRIKE =
ENTITIES.register("lightning_strike", () -> EntityType.Builder.<LightningStrike>of(LightningStrike::new, MobCategory.MISC)
.sized(1f, 1f)
.clientTrackingRange(64)
.build(new ResourceLocation(IronsSpellbooks.MODID, "lightning_strike").toString()));

public static final RegistryObject<EntityType<ApothecaristEntity>> APOTHECARIST =
ENTITIES.register("apothecarist", () -> EntityType.Builder.of(ApothecaristEntity::new, MobCategory.MONSTER)
.sized(.6f, 1.8f)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@ public static void register(IEventBus eventBus) {
public static final RegistryObject<MobEffect> BURNING_DASH = MOB_EFFECT_DEFERRED_REGISTER.register("burning_dash", () -> new BurningDashEffect(MobEffectCategory.BENEFICIAL, 0xd0f9ff));
public static final RegistryObject<MobEffect> GLUTTONY = MOB_EFFECT_DEFERRED_REGISTER.register("gluttony", () -> new GluttonyEffect(MobEffectCategory.BENEFICIAL, 0xd0f9ff));
public static final RegistryObject<MobEffect> ECHOING_STRIKES = MOB_EFFECT_DEFERRED_REGISTER.register("echoing_strikes", () -> new EchoingStrikesEffect(MobEffectCategory.BENEFICIAL, 0x9f0be3));
public static final RegistryObject<MobEffect> THUNDERSTORM = MOB_EFFECT_DEFERRED_REGISTER.register("thunderstorm", () -> new ThunderstormEffect(MobEffectCategory.BENEFICIAL, 0x9f0be3));
//public static final RegistryObject<MobEffect> ENCHANTED_WARD = MOB_EFFECT_DEFERRED_REGISTER.register("enchanted_ward", () -> new EnchantedWardEffect(MobEffectCategory.HARMFUL, 3311322));
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ public static void register(IEventBus eventBus) {
public static RegistryObject<SoundEvent> SCORCH_PREPARE = registerSoundEvent("spell.scorch.prepare");
public static RegistryObject<SoundEvent> FIERY_EXPLOSION = registerSoundEvent("entity.generic.fiery_explosion");
public static RegistryObject<SoundEvent> ECHOING_STRIKE = registerSoundEvent("entity.echoing_strike.echoing_strike");
public static RegistryObject<SoundEvent> SMALL_LIGHTNING_STRIKE = registerSoundEvent("entity.lightning_strike.strike");
public static RegistryObject<SoundEvent> THUNDERSTORM_PREPARE = registerSoundEvent("spell.thunderstorm.prepare");

public static RegistryObject<SoundEvent> DEAD_KING_SWING = registerSoundEvent("entity.dead_king.attack_swing");
public static RegistryObject<SoundEvent> DEAD_KING_SLAM = registerSoundEvent("entity.dead_king.attack_slam");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ public static void rendererRegister(EntityRenderersEvent.RegisterRenderers event
event.registerEntityRenderer(EntityRegistry.ARROW_VOLLEY_ENTITY.get(), NoopRenderer::new);
event.registerEntityRenderer(EntityRegistry.STOMP_AOE.get(), NoopRenderer::new);
event.registerEntityRenderer(EntityRegistry.ECHOING_STRIKE.get(), NoopRenderer::new);
// event.registerEntityRenderer(EntityRegistry.LIGHTNING_STRIKE.get(), NoopRenderer::new);
event.registerEntityRenderer(EntityRegistry.LIGHTNING_STRIKE.get(), NoopRenderer::new);

event.registerBlockEntityRenderer(BlockRegistry.SCROLL_FORGE_TILE.get(), ScrollForgeRenderer::new);
event.registerBlockEntityRenderer(BlockRegistry.PEDESTAL_TILE.get(), PedestalRenderer::new);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package io.redspace.ironsspellbooks.spells.lightning;

import com.mojang.math.Vector3f;
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.effect.ThunderstormEffect;
import io.redspace.ironsspellbooks.particle.BlastwaveParticleOptions;
import io.redspace.ironsspellbooks.particle.ZapParticleOption;
import io.redspace.ironsspellbooks.registries.MobEffectRegistry;
import io.redspace.ironsspellbooks.registries.SoundRegistry;
import io.redspace.ironsspellbooks.util.ParticleHelper;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LightningBolt;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.monster.Creeper;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;

import java.util.List;
import java.util.Optional;

@AutoSpellConfig
public class ThunderstormSpell extends AbstractSpell {
private final ResourceLocation spellId = new ResourceLocation(IronsSpellbooks.MODID, "thunderstorm");

@Override
public List<MutableComponent> getUniqueInfo(int spellLevel, LivingEntity caster) {
return List.of(
Component.translatable("ui.irons_spellbooks.damage", Utils.stringTruncation(ThunderstormEffect.getDamageFromAmplifier(getAmplifierForLevel(spellLevel, caster), caster), 2)),
Component.translatable("ui.irons_spellbooks.radius", 20),
Component.translatable("ui.irons_spellbooks.effect_length", Utils.timeFromTicks(getDurationTicks(spellLevel, caster), 1))
);
}

private final DefaultConfig defaultConfig = new DefaultConfig()
.setMinRarity(SpellRarity.RARE)
.setSchoolResource(SchoolRegistry.LIGHTNING_RESOURCE)
.setMaxLevel(8)
.setCooldownSeconds(120)
.build();

public ThunderstormSpell() {
this.manaCostPerLevel = 10;
this.baseSpellPower = 8;
this.spellPowerPerLevel = 1;
this.castTime = 40;
this.baseManaCost = 70;
}

@Override
public CastType getCastType() {
return CastType.LONG;
}

@Override
public DefaultConfig getDefaultConfig() {
return defaultConfig;
}

@Override
public ResourceLocation getSpellResource() {
return spellId;
}

@Override
public Optional<SoundEvent> getCastStartSound() {
return Optional.of(SoundRegistry.THUNDERSTORM_PREPARE.get());
}

@Override
public void onCast(Level level, int spellLevel, LivingEntity entity, CastSource castSource, MagicData playerMagicData) {
entity.addEffect(new MobEffectInstance(MobEffectRegistry.THUNDERSTORM.get(), getDurationTicks(spellLevel, entity), getAmplifierForLevel(spellLevel, entity), false, false, true));
super.onCast(level, spellLevel, entity, castSource, playerMagicData);
}

private int getAmplifierForLevel(int spellLevel, LivingEntity caster) {
return 8 + (int) ((spellLevel - 1) * getEntityPowerMultiplier(caster));
}

public int getDurationTicks(int spellLevel, LivingEntity caster) {
return (int) ((20 + (2 * (spellLevel - 1) * getEntityPowerMultiplier(caster))) * 20);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class ParticleHelper {
public static final ParticleOptions VOID_TENTACLE_FOG = new FogParticleOptions(new Vector3f(0.0f, 0.075f, .13f), 2);
public static final ParticleOptions ROOT_FOG = new FogParticleOptions(new Vector3f(61 / 255f, 40 / 255f, 18 / 255f), .4f);
public static final ParticleOptions COMET_FOG = new FogParticleOptions(new Vector3f(.75f, .55f, 1f), 1.5f);
public static final ParticleOptions FOG_THUNDER_LIGHT = new FogParticleOptions(new Vector3f(.5f, .5f, .5f), 1.5f);
public static final ParticleOptions FOG_THUNDER_DARK = new FogParticleOptions(new Vector3f(.4f, .4f, .4f), 1.5f);
public static final ParticleOptions POISON_CLOUD = new FogParticleOptions(new Vector3f(.08f, 0.64f, .16f), 1f);
public static final ParticleOptions ICY_FOG = new FogParticleOptions(new Vector3f(208 / 255f, 249 / 255f, 255 / 255f), 0.6f);
public static final ParticleOptions SUNBEAM = new FogParticleOptions(new Vector3f(0.95f, 0.97f, 0.36f), 1f);
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/assets/irons_spellbooks/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@
"spell.irons_spellbooks.echoing_strikes": "Echoing Strikes",
"spell.irons_spellbooks.wololo": "Wololo",
"spell.irons_spellbooks.scorch": "Scorch",
"spell.irons_spellbooks.thunderstorm": "Thunderstorm",

"spell.irons_spellbooks.none.guide": "Nothing to see here!",
"spell.irons_spellbooks.fireball.guide": "Manifest and throw a ball of fire, exploding and dealing massive damage on impact.",
Expand Down Expand Up @@ -578,6 +579,7 @@
"spell.irons_spellbooks.echoing_strikes.guide": "While under the effects of the spell, non-magical attacks will leave an echo of ender energy behind, shortly thereafter exploding with an echo of the original attack's damage.",
"spell.irons_spellbooks.wololo.guide": "Wololo!",
"spell.irons_spellbooks.scorch.guide": "In a targeted area, erupt a scorch of fiery magic, damaging and inviting creatures in the zone.",
"spell.irons_spellbooks.thunderstorm.guide": "Cast to conjure a thunderstorm centered around yourself, which strikes nearby creatures with a small bolt of lightning every 2 seconds for the spell's duration.",

"death.attack.blood_magic": "%1$s blood magic 1",
"death.attack.blood_magic.item": "%1$s blood magic 2",
Expand Down
10 changes: 10 additions & 0 deletions src/main/resources/assets/irons_spellbooks/sounds.json
Original file line number Diff line number Diff line change
Expand Up @@ -603,5 +603,15 @@
"sounds": [
"irons_spellbooks:echoing_strike"
]
},
"entity.lightning_strike.strike": {
"sounds": [
"irons_spellbooks:small_lightning"
]
},
"spell.thunderstorm.prepare": {
"sounds": [
"irons_spellbooks:thunderstorm_prepare"
]
}
}
Binary file not shown.
Binary file not shown.

0 comments on commit 000c8a6

Please sign in to comment.