diff --git a/src/main/java/dev/pgm/community/mutations/Mutation.java b/src/main/java/dev/pgm/community/mutations/Mutation.java index c60aa87c..2a7f44ab 100644 --- a/src/main/java/dev/pgm/community/mutations/Mutation.java +++ b/src/main/java/dev/pgm/community/mutations/Mutation.java @@ -3,6 +3,7 @@ import static net.kyori.adventure.text.Component.text; import dev.pgm.community.mutations.options.MutationOption; +import java.util.Collection; import java.util.Set; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.HoverEvent; @@ -38,7 +39,7 @@ public interface Mutation { * * @return a set of {@link MutationOption} */ - Set getOptions(); + Collection getOptions(); /** * Gets whether it is safe to enable current mutation Ex. If map is rage, don't allow rage diff --git a/src/main/java/dev/pgm/community/mutations/MutationBase.java b/src/main/java/dev/pgm/community/mutations/MutationBase.java index 86954640..00194184 100644 --- a/src/main/java/dev/pgm/community/mutations/MutationBase.java +++ b/src/main/java/dev/pgm/community/mutations/MutationBase.java @@ -3,7 +3,7 @@ import com.google.common.collect.Sets; import dev.pgm.community.Community; import dev.pgm.community.mutations.options.MutationOption; -import java.util.Set; +import java.util.Collection; import javax.annotation.Nullable; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; @@ -43,7 +43,7 @@ public void disable() { } @Override - public Set getOptions() { + public Collection getOptions() { return Sets.newHashSet(); } diff --git a/src/main/java/dev/pgm/community/mutations/MutationType.java b/src/main/java/dev/pgm/community/mutations/MutationType.java index dc6064bb..124f930e 100644 --- a/src/main/java/dev/pgm/community/mutations/MutationType.java +++ b/src/main/java/dev/pgm/community/mutations/MutationType.java @@ -36,7 +36,11 @@ public enum MutationType { FIREBALL_BOW("Fireball Bow", "All projectiles are fireballs", Material.FIREBALL), CANNON_SUPPLIES("Cannon Supplies", "Supplies for making TNT cannons", Material.REDSTONE), GRAPPLING_HOOK("Grappling Hook", "Everyone can use a grappling hook", Material.FISHING_ROD), - NO_SPAWN_KIT("No Spawn Kit", "No Spawn Kits!", Material.BARRIER); + NO_SPAWN_KIT("No Spawn Kit", "No Spawn Kits!", Material.BARRIER), + PROXIMITY_EFFECT( + "Proximity Effects", + "Give potion effects based on distance to Objectives", + Material.GLASS_BOTTLE); String displayName; String description; diff --git a/src/main/java/dev/pgm/community/mutations/feature/MutationFeature.java b/src/main/java/dev/pgm/community/mutations/feature/MutationFeature.java index 26ec5dee..0ddbaf2b 100644 --- a/src/main/java/dev/pgm/community/mutations/feature/MutationFeature.java +++ b/src/main/java/dev/pgm/community/mutations/feature/MutationFeature.java @@ -27,6 +27,7 @@ import dev.pgm.community.mutations.types.items.GrapplingHookMutation; import dev.pgm.community.mutations.types.items.NoSpawnKitMutation; import dev.pgm.community.mutations.types.items.PotionMutation; +import dev.pgm.community.mutations.types.mapdev.ProximityEffectsMutation; import dev.pgm.community.mutations.types.mechanics.BlindMutation; import dev.pgm.community.mutations.types.mechanics.DoubleJumpMutation; import dev.pgm.community.mutations.types.mechanics.FlyMutation; @@ -206,6 +207,8 @@ private Mutation getNewMutation(MutationType type) { return new GrapplingHookMutation(getMatch()); case NO_SPAWN_KIT: return new NoSpawnKitMutation(getMatch()); + case PROXIMITY_EFFECT: + return new ProximityEffectsMutation(getMatch()); default: logger.warning(type.getDisplayName() + " has not been implemented yet"); } diff --git a/src/main/java/dev/pgm/community/mutations/menu/MutationOptionsMenu.java b/src/main/java/dev/pgm/community/mutations/menu/MutationOptionsMenu.java index b71e543f..3d959506 100644 --- a/src/main/java/dev/pgm/community/mutations/menu/MutationOptionsMenu.java +++ b/src/main/java/dev/pgm/community/mutations/menu/MutationOptionsMenu.java @@ -2,6 +2,7 @@ import static tc.oc.pgm.util.bukkit.BukkitUtils.colorize; +import dev.pgm.community.mutations.Mutation; import dev.pgm.community.mutations.feature.MutationFeature; import dev.pgm.community.mutations.options.MutationBooleanOption; import dev.pgm.community.mutations.options.MutationListOption; @@ -41,7 +42,7 @@ private void render(Player player, InventoryContents contents) { List options = mutations.getMutations().stream() - .map(mt -> mt.getOptions()) + .map(Mutation::getOptions) .flatMap(mo -> mo.stream()) .collect(Collectors.toList()); diff --git a/src/main/java/dev/pgm/community/mutations/types/arrows/WebSlingersMutation.java b/src/main/java/dev/pgm/community/mutations/types/arrows/WebSlingersMutation.java index d4fc945c..3985f34c 100644 --- a/src/main/java/dev/pgm/community/mutations/types/arrows/WebSlingersMutation.java +++ b/src/main/java/dev/pgm/community/mutations/types/arrows/WebSlingersMutation.java @@ -10,6 +10,7 @@ import dev.pgm.community.mutations.options.MutationRangeOption; import dev.pgm.community.mutations.types.BowMutation; import dev.pgm.community.mutations.types.KitMutationBase; +import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; @@ -52,7 +53,7 @@ public WebSlingersMutation(Match match) { } @Override - public Set getOptions() { + public Collection getOptions() { return Sets.newHashSet(WEB_LIFE); } diff --git a/src/main/java/dev/pgm/community/mutations/types/gameplay/BlitzMutation.java b/src/main/java/dev/pgm/community/mutations/types/gameplay/BlitzMutation.java index ade03f29..8e29640a 100644 --- a/src/main/java/dev/pgm/community/mutations/types/gameplay/BlitzMutation.java +++ b/src/main/java/dev/pgm/community/mutations/types/gameplay/BlitzMutation.java @@ -6,6 +6,7 @@ import dev.pgm.community.mutations.MutationType; import dev.pgm.community.mutations.options.MutationOption; import dev.pgm.community.mutations.options.MutationRangeOption; +import java.util.Collection; import java.util.Set; import org.bukkit.Material; import org.bukkit.event.HandlerList; @@ -29,7 +30,7 @@ public BlitzMutation(Match match) { } @Override - public Set getOptions() { + public Collection getOptions() { return Sets.newHashSet(BLITZ_LIVES); } diff --git a/src/main/java/dev/pgm/community/mutations/types/items/ExplosionMutation.java b/src/main/java/dev/pgm/community/mutations/types/items/ExplosionMutation.java index 40e1f58f..74aa401d 100644 --- a/src/main/java/dev/pgm/community/mutations/types/items/ExplosionMutation.java +++ b/src/main/java/dev/pgm/community/mutations/types/items/ExplosionMutation.java @@ -12,6 +12,7 @@ import dev.pgm.community.mutations.options.MutationOption; import dev.pgm.community.mutations.options.MutationRangeOption; import dev.pgm.community.mutations.types.KitMutationBase; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Random; @@ -108,7 +109,7 @@ public ExplosionMutation(Match match) { } @Override - public Set getOptions() { + public Collection getOptions() { return Sets.newHashSet(FIREBALL_POWER, FIREBALL_FIRE, LAUNCH_COOLDOWN, MYSTERY_TNT, TNT_SIZE); } diff --git a/src/main/java/dev/pgm/community/mutations/types/items/NoSpawnKitMutation.java b/src/main/java/dev/pgm/community/mutations/types/items/NoSpawnKitMutation.java index 8c60761f..233f4ab4 100644 --- a/src/main/java/dev/pgm/community/mutations/types/items/NoSpawnKitMutation.java +++ b/src/main/java/dev/pgm/community/mutations/types/items/NoSpawnKitMutation.java @@ -6,6 +6,7 @@ import dev.pgm.community.mutations.MutationType; import dev.pgm.community.mutations.options.MutationBooleanOption; import dev.pgm.community.mutations.options.MutationOption; +import java.util.Collection; import java.util.Set; import org.bukkit.Material; import org.bukkit.event.EventHandler; @@ -37,7 +38,7 @@ public NoSpawnKitMutation(Match match) { } @Override - public Set getOptions() { + public Collection getOptions() { return Sets.newHashSet(CLEAR_ITEMS_OPTION, CLEAR_ARMOR_OPTION, CLEAR_EFFECTS_OPTION); } diff --git a/src/main/java/dev/pgm/community/mutations/types/mapdev/ProximityEffectsMutation.java b/src/main/java/dev/pgm/community/mutations/types/mapdev/ProximityEffectsMutation.java new file mode 100644 index 00000000..8520b5f4 --- /dev/null +++ b/src/main/java/dev/pgm/community/mutations/types/mapdev/ProximityEffectsMutation.java @@ -0,0 +1,266 @@ +package dev.pgm.community.mutations.types.mapdev; + +import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; +import dev.pgm.community.mutations.Mutation; +import dev.pgm.community.mutations.MutationType; +import dev.pgm.community.mutations.options.MutationListOption; +import dev.pgm.community.mutations.options.MutationOption; +import dev.pgm.community.mutations.options.MutationRangeOption; +import dev.pgm.community.mutations.types.ScheduledMutationBase; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import org.bukkit.Material; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; +import tc.oc.pgm.api.match.Match; +import tc.oc.pgm.api.player.MatchPlayer; +import tc.oc.pgm.core.Core; +import tc.oc.pgm.core.CoreMatchModule; +import tc.oc.pgm.destroyable.Destroyable; +import tc.oc.pgm.destroyable.DestroyableMatchModule; +import tc.oc.pgm.flag.FlagMatchModule; +import tc.oc.pgm.flag.Post; +import tc.oc.pgm.kits.PotionKit; +import tc.oc.pgm.points.PointProvider; +import tc.oc.pgm.teams.Team; +import tc.oc.pgm.teams.TeamFactory; +import tc.oc.pgm.teams.TeamMatchModule; +import tc.oc.pgm.util.Pair; +import tc.oc.pgm.wool.MonumentWool; +import tc.oc.pgm.wool.WoolMatchModule; + +public class ProximityEffectsMutation extends ScheduledMutationBase { + + MutationListOption attackerDistanceOption = + new MutationListOption<>( + "Attacker Distance", + "Radius where potion effects are applied", + Material.COMPASS, + true, + Lists.newArrayList(0, 5, 10, 15, 20, 30, 40, 50, 75, 100, 150, 200)); + MutationListOption defenderDistanceOption = + new MutationListOption<>( + "Defender Distance", + "Radius where potion effects are applied", + Material.EMPTY_MAP, + true, + Lists.newArrayList(0, 5, 10, 15, 20, 30, 40, 50, 75, 100, 150, 200)); + + Map attackerOptions; + Map defenderOptions; + + public ProximityEffectsMutation(Match match) { + super(match, MutationType.PROXIMITY_EFFECT, 2); + attackerOptions = buildOptions("Attacker"); + defenderOptions = buildOptions("Defender"); + } + + @Override + public Collection getOptions() { + List options = new ArrayList<>(); + + options.add(attackerDistanceOption); + options.addAll(attackerOptions.values()); + options.add(defenderDistanceOption); + options.addAll(defenderOptions.values()); + + return options; + } + + @Override + public boolean canEnable(Set existingMutations) { + return match.hasModule(TeamMatchModule.class); + } + + static Map buildOptions(String prefix) { + HashMap effectOptionMap = new HashMap<>(); + + effectOptionMap.put( + PotionEffectType.FAST_DIGGING, + new MutationRangeOption( + prefix + " Haste", prefix + " Haste Amount", Material.DIAMOND_PICKAXE, true, 0, 0, 5)); + effectOptionMap.put( + PotionEffectType.SPEED, + new MutationRangeOption( + prefix + " Speed", prefix + " Speed Amount", Material.SUGAR, true, 0, 0, 5)); + effectOptionMap.put( + PotionEffectType.INCREASE_DAMAGE, + new MutationRangeOption( + prefix + " Strength", + prefix + " Strength Amount", + Material.DIAMOND_SWORD, + true, + 0, + 0, + 5)); + effectOptionMap.put( + PotionEffectType.JUMP, + new MutationRangeOption( + prefix + " Jump Boost", + prefix + " Jump Boost Amount", + Material.RABBIT_FOOT, + true, + 0, + 0, + 5)); + effectOptionMap.put( + PotionEffectType.REGENERATION, + new MutationRangeOption( + prefix + " Regeneration", + prefix + " Regeneration Amount", + Material.GHAST_TEAR, + true, + 0, + 0, + 5)); + effectOptionMap.put( + PotionEffectType.SLOW_DIGGING, + new MutationRangeOption( + prefix + " Mining Fatigue", + prefix + " Mining Fatigue Amount", + Material.WOOD_PICKAXE, + true, + 0, + 0, + 5)); + effectOptionMap.put( + PotionEffectType.SLOW, + new MutationRangeOption( + prefix + " Slowness", prefix + " Slowness Amount", Material.WEB, true, 0, 0, 5)); + effectOptionMap.put( + PotionEffectType.WEAKNESS, + new MutationRangeOption( + prefix + " Weakness", prefix + " Weakness Amount", Material.WOOD_SWORD, true, 0, 0, 5)); + + return effectOptionMap; + } + + @Override + public void run() { + List> ownedLocationsMap = new ArrayList<>(); + List> attackingLocationsMap = new ArrayList<>(); + + findADLocations(attackingLocationsMap, ownedLocationsMap); + + Set attackers = new HashSet<>(); + Set defenders = new HashSet<>(); + + int defenderDistance = defenderDistanceOption.getValue(); + int attackerDistance = attackerDistanceOption.getValue(); + + for (MatchPlayer player : match.getPlayers()) { + fillPlayerSets( + ownedLocationsMap, defenders, attackers, player, defenderDistance, attackerDistance); + fillPlayerSets( + attackingLocationsMap, attackers, defenders, player, attackerDistance, defenderDistance); + } + + defenders.removeAll(attackers); + + applyPotionEffects(attackers, attackerOptions); + applyPotionEffects(defenders, defenderOptions); + } + + private void findADLocations( + List> attackingLocationsMap, List> ownedLocationsMap) { + TeamMatchModule teamMatchModule = match.moduleRequire(TeamMatchModule.class); + Optional woolMatchModule = match.moduleOptional(WoolMatchModule.class); + Optional destroyableMatchModule = + match.moduleOptional(DestroyableMatchModule.class); + Optional coreMatchModule = match.moduleOptional(CoreMatchModule.class); + Optional flagMatchModule = match.moduleOptional(FlagMatchModule.class); + // Optional controlPointMatchModule = + // match.moduleOptional(ControlPointMatchModule.class); + // TODO: Control points not currently accessible + + if (woolMatchModule.isPresent()) { + Multimap wools = woolMatchModule.get().getWools(); + for (Map.Entry entry : wools.entries()) { + MonumentWool wool = entry.getValue(); + if (!wool.isCompleted()) { + attackingLocationsMap.add( + new Pair<>(entry.getValue().getDefinition().getLocation(), entry.getKey())); + } + } + } + + if (destroyableMatchModule.isPresent()) { + for (Destroyable destroyable : destroyableMatchModule.get().getDestroyables()) { + if (!destroyable.isCompleted()) { + ownedLocationsMap.add( + new Pair<>( + destroyable.getBlockRegion().getBounds().getCenterPoint(), + destroyable.getOwner())); + } + } + } + + if (coreMatchModule.isPresent()) { + for (Core core : coreMatchModule.get().getCores()) { + if (!core.isCompleted()) { + ownedLocationsMap.add( + new Pair<>(core.getCasingRegion().getBounds().getCenterPoint(), core.getOwner())); + } + } + } + + if (flagMatchModule.isPresent()) { + for (Post post : flagMatchModule.get().getPosts()) { + TeamFactory ownerFactory = post.getOwner(); + if (ownerFactory != null) { + Team owner = teamMatchModule.getTeam(ownerFactory); + for (PointProvider returnPoint : post.getReturnPoints()) { + ownedLocationsMap.add( + new Pair<>(returnPoint.getRegion().getBounds().getCenterPoint(), owner)); + } + } + } + } + } + + private void applyPotionEffects( + Set players, Map options) { + for (Map.Entry entry : options.entrySet()) { + int level = entry.getValue().getValue(); + if (level > 0) { + PotionKit potionKit = + new PotionKit( + Collections.singleton(new PotionEffect(entry.getKey(), 5 * 20, level - 1))); + for (MatchPlayer defender : players) { + defender.applyKit(potionKit, true); + } + } + } + } + + private static void fillPlayerSets( + List> attackingLocationsMap, + Set attackers, + Set defenders, + MatchPlayer player, + int attackerDistance, + int defenderDistance) { + for (Pair teamVectorEntry : attackingLocationsMap) { + if (teamVectorEntry.getRight().getPlayers().contains(player)) { + if (player.getLocation().toVector().distance(teamVectorEntry.getLeft()) + < attackerDistance) { + attackers.add(player); + } + } else { + if (player.getLocation().toVector().distance(teamVectorEntry.getLeft()) + < defenderDistance) { + defenders.add(player); + } + } + } + } +} diff --git a/src/main/java/dev/pgm/community/mutations/types/mechanics/DoubleJumpMutation.java b/src/main/java/dev/pgm/community/mutations/types/mechanics/DoubleJumpMutation.java index c7bf5980..a6323f57 100644 --- a/src/main/java/dev/pgm/community/mutations/types/mechanics/DoubleJumpMutation.java +++ b/src/main/java/dev/pgm/community/mutations/types/mechanics/DoubleJumpMutation.java @@ -6,6 +6,7 @@ import dev.pgm.community.mutations.options.MutationOption; import dev.pgm.community.mutations.options.MutationRangeOption; import dev.pgm.community.mutations.types.KitMutationBase; +import java.util.Collection; import java.util.Set; import org.bukkit.entity.EntityType; import org.bukkit.event.EventHandler; @@ -29,7 +30,7 @@ public DoubleJumpMutation(Match match) { } @Override - public Set getOptions() { + public Collection getOptions() { return Sets.newHashSet(JUMP_POWER); } diff --git a/src/main/java/dev/pgm/community/mutations/types/mechanics/FlyMutation.java b/src/main/java/dev/pgm/community/mutations/types/mechanics/FlyMutation.java index b9f18044..3ecf9926 100644 --- a/src/main/java/dev/pgm/community/mutations/types/mechanics/FlyMutation.java +++ b/src/main/java/dev/pgm/community/mutations/types/mechanics/FlyMutation.java @@ -12,6 +12,7 @@ import dev.pgm.community.mutations.options.MutationRangeOption; import dev.pgm.community.mutations.types.KitMutationBase; import dev.pgm.community.utils.BroadcastUtils; +import java.util.Collection; import java.util.Set; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -49,7 +50,7 @@ public FlyMutation(Match match) { } @Override - public Set getOptions() { + public Collection getOptions() { return Sets.newHashSet(FLY_DISABLE_DELAY, FLY_SPEED); } diff --git a/src/main/java/dev/pgm/community/mutations/types/mechanics/MobMutation.java b/src/main/java/dev/pgm/community/mutations/types/mechanics/MobMutation.java index 8327aa3d..34b5cdd9 100644 --- a/src/main/java/dev/pgm/community/mutations/types/mechanics/MobMutation.java +++ b/src/main/java/dev/pgm/community/mutations/types/mechanics/MobMutation.java @@ -8,6 +8,7 @@ import dev.pgm.community.mutations.options.MutationListOption; import dev.pgm.community.mutations.options.MutationOption; import dev.pgm.community.mutations.types.ScheduledMutationBase; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; @@ -51,7 +52,7 @@ public MobMutation(Match match) { } @Override - public Set getOptions() { + public Collection getOptions() { return Sets.newHashSet(TOTAL_MOBS); } diff --git a/src/main/java/dev/pgm/community/mutations/types/world/BlockDecayMutation.java b/src/main/java/dev/pgm/community/mutations/types/world/BlockDecayMutation.java index ca0bab65..f4704270 100644 --- a/src/main/java/dev/pgm/community/mutations/types/world/BlockDecayMutation.java +++ b/src/main/java/dev/pgm/community/mutations/types/world/BlockDecayMutation.java @@ -7,6 +7,7 @@ import dev.pgm.community.mutations.options.MutationOption; import dev.pgm.community.mutations.options.MutationRangeOption; import dev.pgm.community.mutations.types.ScheduledMutationBase; +import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; @@ -39,7 +40,7 @@ public BlockDecayMutation(Match match) { } @Override - public Set getOptions() { + public Collection getOptions() { return Sets.newHashSet(DECAY_SECONDS); }