develop-bloodmoon #10

Merged
MineTec merged 17 commits from develop-bloodmoon into master 2025-11-23 14:03:07 +00:00
7 changed files with 164 additions and 61 deletions
Showing only changes of commit e14c87c2fb - Show all commits

View File

@@ -38,7 +38,8 @@ public class Settings extends Appliance {
BorderWarning, BorderWarning,
LocatorBar, LocatorBar,
InfoBars, InfoBars,
CoordinateDisplay CoordinateDisplay,
Bloodmoon
} }
public static Settings instance() { public static Settings instance() {

View File

@@ -1,75 +1,80 @@
package eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon; package eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon;
import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.settings.Settings;
import eu.mhsl.craftattack.spawn.core.appliance.Appliance; import eu.mhsl.craftattack.spawn.core.appliance.Appliance;
import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand; import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand;
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.commands.BloodmoonCommand; import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.commands.BloodmoonCommand;
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener.BloodmoonEntityDamageListener;
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener.BloodmoonMonsterDeathListener; import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener.BloodmoonMonsterDeathListener;
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener.BloodmoonPlayerJoinListener; import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener.BloodmoonPlayerJoinListener;
import net.kyori.adventure.bossbar.BossBar;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.boss.BarColor; import org.bukkit.entity.Entity;
import org.bukkit.boss.BarFlag;
import org.bukkit.boss.BarStyle;
import org.bukkit.boss.BossBar;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
public class Bloodmoon extends Appliance { public class Bloodmoon extends Appliance {
// für alle Dimensionen? einstellbar machen? // für alle Dimensionen? einstellbar machen?
public final Map<EntityType, PotionEffect[]> affectedMobEffectMap = Map.of( public final Map<EntityType, Set<MobEffect>> affectedMobEffectMap = Map.of(
EntityType.ZOMBIE, new PotionEffect[]{ EntityType.ZOMBIE, Set.of(
new PotionEffect(PotionEffectType.WITHER, 7 * 20, 1) new MobEffect.PotionMobEffect(PotionEffectType.WITHER, 7, 1)
}, ),
EntityType.SKELETON, new PotionEffect[]{ EntityType.SKELETON, Set.of(
Pupsi marked this conversation as resolved Outdated

?

?
new PotionEffect(PotionEffectType.SLOWNESS, (int) (3.5 * 20), 1) new MobEffect.PotionMobEffect(PotionEffectType.SLOWNESS, 3.5, 1)
}, ),
EntityType.SPIDER, new PotionEffect[]{ EntityType.SPIDER, Set.of(
new PotionEffect(PotionEffectType.POISON, 4 * 20, 1), new MobEffect.PotionMobEffect(PotionEffectType.POISON, 4, 1),
new PotionEffect(PotionEffectType.NAUSEA, 6 * 20, 10) new MobEffect.PotionMobEffect(PotionEffectType.NAUSEA, 6, 10)
}, ),
EntityType.CREEPER, new PotionEffect[]{ EntityType.CREEPER, Set.of(
new LightningPotionEffect() new MobEffect.LightningMobEffect()
}, ),
EntityType.HUSK, new PotionEffect[]{ EntityType.HUSK, Set.of(
new PotionEffect(PotionEffectType.WITHER, 7 * 20, 1) new MobEffect.PotionMobEffect(PotionEffectType.WITHER, 7, 1)
}, ),
EntityType.DROWNED, new PotionEffect[]{ EntityType.DROWNED, Set.of(
new PotionEffect(PotionEffectType.WITHER, 7 * 20, 1) new MobEffect.PotionMobEffect(PotionEffectType.WITHER, 7, 1)
}, ),
EntityType.WITCH, new PotionEffect[]{}, EntityType.WITCH, Set.of(),
Pupsi marked this conversation as resolved Outdated

stray?

stray?
EntityType.ZOMBIE_VILLAGER, new PotionEffect[]{ EntityType.ZOMBIE_VILLAGER, Set.of(
new PotionEffect(PotionEffectType.WITHER, 7 * 20, 1) new MobEffect.PotionMobEffect(PotionEffectType.WITHER, 7, 1)
}, ),
EntityType.PHANTOM, new PotionEffect[]{ EntityType.PHANTOM, Set.of(
new PotionEffect(PotionEffectType.LEVITATION, (int) (1.5 * 20), 3) new MobEffect.PotionMobEffect(PotionEffectType.LEVITATION, 1.5, 3)
}, ),
MineTec marked this conversation as resolved Outdated

wenn keine Effekte, wozu der Eintrag?

wenn keine Effekte, wozu der Eintrag?
Outdated
Review

Damit Hexen trotzdem mehr Schaden machen und mehr Leben haben.

Damit Hexen trotzdem mehr Schaden machen und mehr Leben haben.
EntityType.ENDERMAN, new PotionEffect[]{ EntityType.ENDERMAN, Set.of(
new PotionEffect(PotionEffectType.SLOWNESS, (int) (2.5 * 20), 2) new MobEffect.PotionMobEffect(PotionEffectType.SLOWNESS, 2.5, 2)
} )
); );
public final int expMultiplier = 4; public final int expMultiplier = 4;
public final boolean lightningsActive = true; public final boolean lightningsActive = true;
public final double mobDamageMultipier = 2;
public final double mobHealthMultiplier = 3;
private boolean isActive = false; private boolean isActive = false;
private final BossBar bossBar = Bukkit.createBossBar( private final BossBar bossBar = BossBar.bossBar(
"Bloodmoon", Component.text("Blutmond", NamedTextColor.DARK_RED),
BarColor.RED, 1f,
BarStyle.SEGMENTED_12, BossBar.Color.RED,
BarFlag.CREATE_FOG, BossBar.Overlay.NOTCHED_12,
BarFlag.DARKEN_SKY Set.of(BossBar.Flag.CREATE_WORLD_FOG, BossBar.Flag.DARKEN_SCREEN)
); );
private final int bloodMoonLegth = 12000; private final int bloodmoonLegth = 12000;
private final int bloodmoonStartTime = 12000;
private final int daysBetweenBloodmoons = 1; private final int daysBetweenBloodmoons = 1;
private final int minBonusDrops = 1; private final int minBonusDrops = 1;
private final int maxBonusDrops = 4; private final int maxBonusDrops = 4;
@@ -81,22 +86,40 @@ public class Bloodmoon extends Appliance {
new ItemStack(Material.GOLD_BLOCK, 1), 2 new ItemStack(Material.GOLD_BLOCK, 1), 2
); );
@Override
public void onEnable() {
Settings.instance().declareSetting(BloodmoonSetting.class);
}
Pupsi marked this conversation as resolved Outdated

WeakHashMap implementierung verwenden

WeakHashMap implementierung verwenden
public boolean bloodmoonIsActive() { public boolean bloodmoonIsActive() {
return this.isActive; return this.isActive;
} }
public void startBloodmoon() { public void startBloodmoon() {
this.isActive = true; this.isActive = true;
Bukkit.getOnlinePlayers().forEach(player -> this.bossBar.addPlayer(player)); Bukkit.getOnlinePlayers().forEach(this::addPlayerToBossBar);
} }
public void stopBloodmoon() { public void stopBloodmoon() {
this.isActive = false; this.isActive = false;
this.bossBar.removeAll(); Bukkit.getOnlinePlayers().forEach(player -> player.hideBossBar(this.bossBar));
} }
public void addPlayerToBossBar(Player p) { public void addPlayerToBossBar(Player player) {
this.bossBar.addPlayer(p); if(!this.getBloodmoonSetting(player)) return;
player.showBossBar(this.bossBar);
}
public boolean isAffectedMob(Entity entity) {
return this.affectedMobEffectMap.containsKey(entity.getType());
}
public boolean getBloodmoonSetting(Player player) {
return Settings.instance().getSetting(
player,
Settings.Key.Bloodmoon,
Boolean.class
);
} }
public List<ItemStack> getRandomBonusDrops() { public List<ItemStack> getRandomBonusDrops() {
@@ -123,7 +146,8 @@ public class Bloodmoon extends Appliance {
protected @NotNull List<Listener> listeners() { protected @NotNull List<Listener> listeners() {
return List.of( return List.of(
new BloodmoonMonsterDeathListener(), new BloodmoonMonsterDeathListener(),
new BloodmoonPlayerJoinListener() new BloodmoonPlayerJoinListener(),
new BloodmoonEntityDamageListener()
); );
} }

View File

@@ -0,0 +1,46 @@
package eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon;
import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.settings.CategorizedSetting;
import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.settings.SettingCategory;
import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.settings.Settings;
import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.settings.datatypes.BoolSetting;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
public class BloodmoonSetting extends BoolSetting implements CategorizedSetting {
public BloodmoonSetting() {
super(Settings.Key.Bloodmoon);
}
@Override
public SettingCategory category() {
return SettingCategory.Misc;
}
@Override
protected String title() {
return "Blutmond";
}
@Override
protected String description() {
return "Kämpfe während dem Blutmond mit stärkeren Monstern, um mit besseren Drops belohnt zu werden.";
}
@Override
protected Material icon() {
return Material.CLOCK;
}
@Override
protected Boolean defaultValue() {
Pupsi marked this conversation as resolved Outdated

mMn. würde hier ein Skeleton-Skull oder auch eine ominous potion besser als icon passen

mMn. würde hier ein Skeleton-Skull oder auch eine ominous potion besser als icon passen
return false;
}
// TODO: only change when bloodmoon is not active
@Override
protected void change(Player player, ClickType clickType) {
super.change(player, clickType);
}
}

View File

@@ -1,10 +0,0 @@
package eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
public class LightningPotionEffect extends PotionEffect {
public LightningPotionEffect() {
super(PotionEffectType.SLOWNESS, 0, 0);
}
}

View File

@@ -0,0 +1,29 @@
package eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon;
import net.kyori.adventure.util.Ticks;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
public abstract class MobEffect {
public abstract void apply(Player p);
public static class PotionMobEffect extends MobEffect {
private final PotionEffect effect;
public PotionMobEffect(PotionEffectType type, double seconds, int amplifier) {
this.effect = new PotionEffect(type, (int) (seconds * Ticks.TICKS_PER_SECOND), amplifier);
}
@Override
public void apply(Player p) {
p.addPotionEffect(this.effect);
}
}
public static class LightningMobEffect extends MobEffect {
@Override
public void apply(Player p) {
p.getWorld().strikeLightning(p.getLocation());
}
}
}

View File

@@ -4,6 +4,7 @@ import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener;
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.Bloodmoon; import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.Bloodmoon;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile; import org.bukkit.entity.Projectile;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent;
@@ -20,6 +21,15 @@ public class BloodmoonEntityDamageListener extends ApplianceListener<Bloodmoon>
if(!(damagerEntity instanceof LivingEntity damager && event.getEntity() instanceof LivingEntity receiver)) return; if(!(damagerEntity instanceof LivingEntity damager && event.getEntity() instanceof LivingEntity receiver)) return;
if(event.getFinalDamage() == 0) return; if(event.getFinalDamage() == 0) return;
// TODO: damage increase / reduction and effects if(this.getAppliance().isAffectedMob(damager) && receiver instanceof Player player) {
if(!this.getAppliance().getBloodmoonSetting(player)) return;
event.setDamage(event.getDamage() * this.getAppliance().mobDamageMultipier);
this.getAppliance().affectedMobEffectMap.get(damager.getType()).forEach(mobEffect -> mobEffect.apply(player));
return;
}
if(this.getAppliance().isAffectedMob(receiver) && damager instanceof Player player) {
if(!this.getAppliance().getBloodmoonSetting(player)) return;
event.setDamage(event.getDamage() / this.getAppliance().mobHealthMultiplier);
}
} }
} }

View File

@@ -3,6 +3,7 @@ package eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.list
import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener; import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener;
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.Bloodmoon; import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.Bloodmoon;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityDeathEvent;
@@ -10,11 +11,13 @@ public class BloodmoonMonsterDeathListener extends ApplianceListener<Bloodmoon>
@EventHandler @EventHandler
public void onMonsterDeath(EntityDeathEvent event) { public void onMonsterDeath(EntityDeathEvent event) {
if(!this.getAppliance().bloodmoonIsActive()) return; if(!this.getAppliance().bloodmoonIsActive()) return;
if(!(event.getDamageSource().getCausingEntity() instanceof Player player)) return;
if(!this.getAppliance().getBloodmoonSetting(player)) return;
LivingEntity entity = event.getEntity(); LivingEntity entity = event.getEntity();
if(!this.getAppliance().affectedMobEffectMap.containsKey(entity.getType())) return; if(!this.getAppliance().isAffectedMob(entity)) return;
event.setDroppedExp(event.getDroppedExp() * this.getAppliance().expMultiplier); event.setDroppedExp(event.getDroppedExp() * this.getAppliance().expMultiplier);
event.getDrops().addAll(this.getAppliance().getRandomBonusDrops()); event.getDrops().addAll(this.getAppliance().getRandomBonusDrops());
if(this.getAppliance().lightningsActive) event.getEntity().getWorld().strikeLightningEffect(event.getEntity().getLocation()); if(this.getAppliance().lightningsActive) entity.getWorld().strikeLightningEffect(entity.getLocation());
} }
} }