Skip to content

Commit

Permalink
Merge pull request #875 from JasperLorelai/main
Browse files Browse the repository at this point in the history
Config-based projectile interactions
  • Loading branch information
Chronoken authored Apr 3, 2024
2 parents 868d45a + 94526a0 commit 09f372c
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 107 deletions.
56 changes: 32 additions & 24 deletions core/src/main/java/com/nisovin/magicspells/MagicSpells.java
Original file line number Diff line number Diff line change
Expand Up @@ -547,26 +547,6 @@ public void load() {
log("...xp system loaded");
}

// Load in-game spell names, incantations, and initialize spells
log("Initializing spells...");
for (Spell spell : spells.values()) {
spellNames.put(Util.getPlainString(Util.getMiniMessage(spell.getName().toLowerCase())), spell);
String[] aliases = spell.getAliases();
if (aliases != null) {
for (String alias : aliases) {
if (!spellNames.containsKey(alias.toLowerCase())) spellNames.put(alias.toLowerCase(), spell);
}
}
List<String> incs = spell.getIncantations();
if (incs != null && !incs.isEmpty()) {
for (String s : incs) {
incantations.put(s.toLowerCase(), spell);
}
}
spell.initialize();
}
log("...done");

// Load player data using a storage handler
log("Initializing storage handler...");
storageHandler = new TXTFileStorage(plugin);
Expand Down Expand Up @@ -667,9 +647,40 @@ public void load() {
Bukkit.getScheduler().runTaskLater(this, this::loadExternalData, 1);
}

private void initializeSpells() {
log("Initializing spells...");
for (Spell spell : new ArrayList<>(spells.values())) {
DependsOn dependsOn = spell.getClass().getAnnotation(DependsOn.class);
if (dependsOn != null && !Util.checkPluginsEnabled(dependsOn.value())) {
spells.remove(spell.getInternalName().toLowerCase());
spellsOrdered.remove(spell);

MagicSpells.error(spell.getClass().getSimpleName() + " '" + spell.internalName + "' could not be loaded.");
continue;
}

spellNames.put(Util.getPlainString(Util.getMiniMessage(spell.getName().toLowerCase())), spell);
String[] aliases = spell.getAliases();
if (aliases != null) {
for (String alias : aliases) {
if (!spellNames.containsKey(alias.toLowerCase())) spellNames.put(alias.toLowerCase(), spell);
}
}
List<String> incs = spell.getIncantations();
if (incs != null && !incs.isEmpty()) {
for (String s : incs) {
incantations.put(s.toLowerCase(), spell);
}
}
spell.initialize();
}
log("...done");
}

private void loadExternalData() {
log("Loading external data...");

initializeSpells();
loadVariables();
loadSpellEffects();
loadConditions();
Expand Down Expand Up @@ -817,9 +828,6 @@ private void loadSpells(Map<String, Boolean> permGrantChildren, Map<String, Bool
continue;
}

DependsOn dependsOn = spellClass.getAnnotation(DependsOn.class);
if (dependsOn != null && !Util.checkPluginsEnabled(dependsOn.value())) continue;

try {
constructor = spellClass.getConstructor(MagicConfig.class, String.class);
} catch (NoSuchMethodException e) {
Expand Down Expand Up @@ -874,7 +882,7 @@ private void loadSpells(Map<String, Boolean> permGrantChildren, Map<String, Bool

finalElapsed = System.currentTimeMillis() - startTimePre;
if (lastReloadTime != 0) getLogger().warning("Loaded in " + finalElapsed + "ms (previously " + lastReloadTime + " ms)");
getLogger().warning("Need help? Check out our discord: discord.gg/6bYqnNy");
getLogger().warning("Need help? Check out our discord: https://discord.magicspells.dev/");
lastReloadTime = finalElapsed;
}

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/com/nisovin/magicspells/Spell.java
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ public Spell(MagicConfig config, String spellName) {
ignoreGlobalCooldown = config.getBoolean(internalKey + "ignore-global-cooldown", false);
charges = config.getInt(internalKey + "charges", 0);
rechargeSound = config.getString(internalKey + "recharge-sound", "");
nextCast = new WeakHashMap<>();
nextCast = new HashMap<>();
chargesConsumed = new IntMap<>();
nextCastServer = 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ public static void onResetCD(CommandIssuer issuer, String[] args) {
if (player == null) s.getCooldowns().clear();
else s.setCooldown(player, 0, false);
}
issuer.sendMessage(MagicSpells.getTextColor() + "Cooldowns reset" + (player == null ? "" : " for " + player.getName()) + (spell == null ? "" : " for spell " + Util.getMiniMessage(spell.getName())) + ".");
issuer.sendMessage(MagicSpells.getTextColor() + "Cooldowns reset" + (player == null ? "" : " for " + player.getName()) + (spell == null ? "" : " for spell " + Util.getLegacyFromMiniMessage(spell.getName())));
}

@Subcommand("mana")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.util.Set;
import java.util.List;
import java.util.HashSet;
import java.util.HashMap;

import org.bukkit.Location;
import org.bukkit.Material;
Expand All @@ -19,6 +18,7 @@
import com.nisovin.magicspells.spells.InstantSpell;
import com.nisovin.magicspells.util.config.ConfigData;
import com.nisovin.magicspells.spelleffects.SpellEffect;
import com.nisovin.magicspells.util.trackers.Interaction;
import com.nisovin.magicspells.castmodifiers.ModifierSet;
import com.nisovin.magicspells.spells.TargetedEntitySpell;
import com.nisovin.magicspells.spelleffects.EffectPosition;
Expand Down Expand Up @@ -94,9 +94,9 @@ public class ParticleProjectileSpell extends InstantSpell implements TargetedLoc
private final ConfigData<FluidCollisionMode> fluidCollisionMode;

private ModifierSet projModifiers;
private final List<?> interactionData;
private List<Interaction> interactions;
private List<String> projModifiersStrings;
private final List<String> interactions;
private final Map<String, Subspell> interactionSpells;

private Subspell airSpell;
private Subspell selfSpell;
Expand Down Expand Up @@ -218,8 +218,7 @@ public ParticleProjectileSpell(MagicConfig config, String spellName) {
validTargetList.enforce(ValidTargetList.TargetingElement.TARGET_NONPLAYERS, hitNonPlayers);

projModifiersStrings = getConfigStringList("projectile-modifiers", null);
interactions = getConfigStringList("interactions", null);
interactionSpells = new HashMap<>();
interactionData = getConfigList("interactions", null);

// Compatibility
defaultSpellName = getConfigString("spell", "");
Expand Down Expand Up @@ -311,31 +310,8 @@ public void initialize() {

defaultSpellName = null;

if (interactions != null && !interactions.isEmpty()) {
for (String str : interactions) {
String[] params = str.split(" ");
if (params[0] == null) continue;

Subspell projectile = new Subspell(params[0]);
if (!projectile.process() || !(projectile.getSpell() instanceof ParticleProjectileSpell)) {
MagicSpells.error(prefix + " has an interaction with '" + params[0] + "' but that's not a valid particle projectile!");
continue;
}

if (params.length == 1) {
interactionSpells.put(params[0], null);
continue;
}

if (params[1] == null) continue;
Subspell collisionSpell = new Subspell(params[1]);
if (!collisionSpell.process()) {
MagicSpells.error(prefix + " has an interaction with '" + params[0] + "' and their spell on collision '" + params[1] + "' is not a valid spell!");
continue;
}
interactionSpells.put(params[0], collisionSpell);
}
}
if (interactionData == null || interactionData.isEmpty()) return;
interactions = Interaction.read(this, interactionData);
}

@Override
Expand Down Expand Up @@ -501,7 +477,7 @@ private void setupTracker(ParticleProjectileTracker tracker, SpellData data) {

tracker.setTargetList(validTargetList);
tracker.setProjectileModifiers(projModifiers);
tracker.setInteractionSpells(interactionSpells);
tracker.setInteractions(interactions);

tracker.setAirSpell(airSpell);
tracker.setTickSpell(tickSpell);
Expand All @@ -525,8 +501,8 @@ public ModifierSet getProjectileModifiers() {
return projModifiers;
}

public Map<String, Subspell> getInteractionSpells() {
return interactionSpells;
public List<Interaction> getInteractions() {
return interactions;
}

public Subspell getAirSpell() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.nisovin.magicspells.spells.targeted;

import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.*;
import java.util.function.Predicate;

import org.bukkit.Location;
Expand All @@ -11,15 +9,16 @@
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.LivingEntity;

import com.nisovin.magicspells.util.*;
import io.papermc.paper.entity.TeleportFlag;

import com.nisovin.magicspells.util.*;
import com.nisovin.magicspells.Subspell;
import com.nisovin.magicspells.MagicSpells;
import com.nisovin.magicspells.spells.TargetedSpell;
import com.nisovin.magicspells.util.config.ConfigData;
import com.nisovin.magicspells.events.SpellTargetEvent;
import com.nisovin.magicspells.spelleffects.SpellEffect;
import com.nisovin.magicspells.util.trackers.Interaction;
import com.nisovin.magicspells.spells.TargetedEntitySpell;
import com.nisovin.magicspells.spelleffects.EffectPosition;
import com.nisovin.magicspells.spells.TargetedLocationSpell;
Expand Down Expand Up @@ -59,6 +58,9 @@ public class OrbitSpell extends TargetedSpell implements TargetedEntitySpell, Ta
private final String groundSpellName;
private final String entitySpellName;

private final List<?> interactionData;
private List<Interaction> interactions;

private Subspell orbitSpell;
private Subspell groundSpell;
private Subspell entitySpell;
Expand Down Expand Up @@ -94,6 +96,8 @@ public OrbitSpell(MagicConfig config, String spellName) {
orbitSpellName = getConfigString("spell", "");
groundSpellName = getConfigString("spell-on-hit-ground", "");
entitySpellName = getConfigString("spell-on-hit-entity", "");

interactionData = getConfigList("interactions", null);
}

@Override
Expand All @@ -110,6 +114,9 @@ public void initialize() {
entitySpell = initSubspell(entitySpellName,
error.formatted("spell-on-hit-entity"),
true);

if (interactionData == null || interactionData.isEmpty()) return;
interactions = Interaction.read(this, interactionData);
}

@Override
Expand Down Expand Up @@ -177,6 +184,7 @@ public void removeOrbits(LivingEntity target) {
private class OrbitTracker implements Runnable {

private SpellData data;
private boolean stopped = false;

private final BoundingBox box;
private final Vector currentDirection;
Expand Down Expand Up @@ -270,26 +278,26 @@ public void run() {
return;
}

Location loc = getLocation();
data = data.location(loc);
move();
data = data.location(currentLocation);

if (!transparent.test(loc)) {
if (!transparent.test(currentLocation)) {
if (groundSpell != null) groundSpell.subcast(data.noTarget());
if (stopOnHitGround) {
stop(true);
return;
}
}

playSpellEffects(EffectPosition.SPECIAL, loc, data);
playSpellEffects(EffectPosition.SPECIAL, currentLocation, data);

if (effectSet != null) {
Effect effect;
Location effectLoc;
for (EffectlibSpellEffect spellEffect : effectSet) {
effect = spellEffect.getEffect();

effectLoc = spellEffect.getSpellEffect().applyOffsets(loc.clone(), data);
effectLoc = spellEffect.getSpellEffect().applyOffsets(currentLocation.clone(), data);
effect.setLocation(effectLoc);

if (effect instanceof ModifiedEffect) {
Expand All @@ -301,19 +309,19 @@ public void run() {

if (armorStandSet != null) {
for (ArmorStand armorStand : armorStandSet) {
armorStand.teleport(loc, TeleportFlag.EntityState.RETAIN_PASSENGERS, TeleportFlag.EntityState.RETAIN_VEHICLE);
armorStand.teleport(currentLocation, TeleportFlag.EntityState.RETAIN_PASSENGERS, TeleportFlag.EntityState.RETAIN_VEHICLE);
}
}

if (entityMap != null) {
for (var entry : entityMap.entrySet()) {
entry.getValue().teleport(entry.getKey().applyOffsets(loc.clone()), TeleportFlag.EntityState.RETAIN_PASSENGERS, TeleportFlag.EntityState.RETAIN_VEHICLE);
entry.getValue().teleport(entry.getKey().applyOffsets(currentLocation.clone()), TeleportFlag.EntityState.RETAIN_PASSENGERS, TeleportFlag.EntityState.RETAIN_VEHICLE);
}
}

if (orbitSpell != null) orbitSpell.subcast(data.noTarget());

box.setCenter(loc);
box.setCenter(currentLocation);

for (LivingEntity e : data.caster().getWorld().getLivingEntities()) {
if (!e.isValid() || immune.contains(e) || !box.contains(e)) continue;
Expand All @@ -328,20 +336,61 @@ public void run() {
if (entitySpell != null) entitySpell.subcast(subData.noLocation());

playSpellEffects(EffectPosition.TARGET, event.getTarget(), subData);
playSpellEffectsTrail(loc, event.getTarget().getLocation(), subData);
playSpellEffectsTrail(currentLocation, event.getTarget().getLocation(), subData);

if (stopOnHitEntity) {
stop(true);
return;
}
}

if (interactions == null || interactions.isEmpty()) return;
Set<OrbitTracker> toRemove = new HashSet<>();
Set<OrbitTracker> trackers = new HashSet<>(trackerSet);
for (OrbitTracker collisionTracker : trackers) {
for (Interaction interaction : interactions) {
if (!canInteractWith(collisionTracker)) continue;
if (!interaction.interactsWith().check(collisionTracker.getOrbitSpell())) continue;

if (interaction.canInteractList() != null && !interaction.canInteractList().canTarget(data.caster(), collisionTracker.data.caster()))
continue;

if (interaction.collisionSpell() != null) {
Location middleLoc = currentLocation.clone().add(collisionTracker.currentLocation).multiply(0.5);
interaction.collisionSpell().subcast(data.retarget(null, middleLoc));
}

if (interaction.stopCausing()) {
toRemove.add(collisionTracker);
collisionTracker.stop(false);
}

if (interaction.stopWith()) {
toRemove.add(this);
stop(false);
}
}
}

trackerSet.removeAll(toRemove);
toRemove.clear();
trackers.clear();
}

private boolean canInteractWith(OrbitTracker collisionTracker) {
if (collisionTracker == null) return false;
if (stopped || collisionTracker.stopped) return false;
if (!data.hasCaster() || !collisionTracker.data.hasCaster()) return false;
if (collisionTracker.equals(this)) return false;
if (!collisionTracker.currentLocation.getWorld().equals(currentLocation.getWorld())) return false;
return collisionTracker.box.contains(currentLocation) || box.contains(collisionTracker.currentLocation);
}

private OrbitSpell getOrbitSpell() {
return OrbitSpell.this;
}

private Location getLocation() {
private void move() {
if (data.hasTarget()) {
data.target().getLocation(currentLocation);

Expand All @@ -360,12 +409,12 @@ private Location getLocation() {
else perp = new Vector(-currentDirection.getZ(), 0, currentDirection.getX());

currentDirection.add(perp.multiply(distancePerTick)).normalize();

return currentLocation.clone().add(0, yOffset, 0).add(currentDirection.clone().multiply(orbitRadius)).setDirection(perp);
currentLocation.add(0, yOffset, 0).add(currentDirection.clone().multiply(orbitRadius)).setDirection(perp);
}

private void stop(boolean removeTracker) {
playSpellEffects(EffectPosition.DELAYED, getLocation(), data);
stopped = true;
playSpellEffects(EffectPosition.DELAYED, currentLocation, data);

MagicSpells.cancelTask(taskId);
MagicSpells.cancelTask(repeatingHorizTaskId);
Expand Down
Loading

0 comments on commit 09f372c

Please sign in to comment.