Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,22 @@ fair, heart-pounding battles that keep players on their toes. Here’s a rundown
- **Combat Logging**
No more dodging fights by logging out! Once players are in combat, they’re committed until the showdown ends. Watch it
in action:
![Combat log anti logout feature](https://github.com/EternalCodeTeam/EternalCombat/blob/master/assets/combatlog.gif?raw=true)
<img alt="Combat log anti logout feature" src="https://github.com/EternalCodeTeam/EternalCombat/blob/master/assets/combatlog.gif?raw=true" width="420">

- **Customize combat experience**
Add custom effects to players in combat or death. Everything should be configurable and user-friendly:
![Lightning strikes when players die](https://github.com/EternalCodeTeam/EternalCombat/blob/master/assets/lightning.gif?raw=true)
<img alt="lightning strikes when players die" src="https://github.com/EternalCodeTeam/EternalCombat/blob/master/assets/lightning.gif?raw=true" width="420">
<img alt="Flare signalises players death location" src="https://github.com/EternalCodeTeam/EternalCombat/blob/master/assets/flare.gif?raw=true" width="420">

- **Spawn Protection (Configurable)**
Stop players from fleeing to safety! Block access to spawn or safe zones during combat – tweak it to fit your server’s
rules. See how it works:
![Border around protected region](https://github.com/EternalCodeTeam/EternalCombat/blob/master/assets/border.gif?raw=true)
<img alt="Border around protected region" src="https://github.com/EternalCodeTeam/EternalCombat/blob/master/assets/border.gif?raw=true" width="420">

- **Crystal PvP support**
Engage in intense Crystal PvP battles without worrying about players logging out mid-fight! EternalCombat keeps
everyone in the game until the last anchor hit. Check it out:
![Crystal PvP showcase](https://github.com/EternalCodeTeam/EternalCombat/blob/master/assets/crystals.gif?raw=true)
everyone in the game until the last anchor hit. Check it out:
<img alt="Crystal PvP showcase" src="https://github.com/EternalCodeTeam/EternalCombat/blob/master/assets/crystals.gif?raw=true" width="420">

- **Fully Customizable Combat**
Tailor the combat experience to your liking with a ton of options! From disabling elytra to setting drop rates for
Expand Down
Binary file added assets/flare.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ object Versions {
const val OKAERI_CONFIGS_SERDES_COMMONS = "5.0.13"
const val OKAERI_CONFIGS_SERDES_BUKKIT = "5.0.13"

const val XSERIES = "13.6.0"

const val CAFFEINE = "3.2.3"

const val B_STATS_BUKKIT = "3.1.0"
Expand Down
6 changes: 5 additions & 1 deletion eternalcombat-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ dependencies {
implementation("eu.okaeri:okaeri-configs-serdes-commons:${Versions.OKAERI_CONFIGS_SERDES_COMMONS}")
implementation("eu.okaeri:okaeri-configs-serdes-bukkit:${Versions.OKAERI_CONFIGS_SERDES_BUKKIT}")

// XSeries
implementation("com.github.cryptomorin:XSeries:${Versions.XSERIES}")

// bstats
implementation("org.bstats:bstats-bukkit:${Versions.B_STATS_BUKKIT}")

Expand Down Expand Up @@ -126,7 +129,8 @@ tasks.shadowJar {
"com.github.benmanes.caffeine",
"com.eternalcode.commons",
"com.eternalcode.multification",
"io.papermc.lib"
"com.github.cryptomorin",
"io.papermc.lib",
).forEach { pack ->
relocate(pack, "$prefix.$pack")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
import com.eternalcode.combat.fight.controller.FightBypassCreativeController;
import com.eternalcode.combat.fight.controller.FightBypassPermissionController;
import com.eternalcode.combat.fight.controller.FightInventoryController;
import com.eternalcode.combat.fight.death.DeathEffectController;
import com.eternalcode.combat.fight.death.DeathFlareController;
import com.eternalcode.combat.fight.death.DeathLightningController;
import com.eternalcode.combat.fight.drop.DropKeepInventoryService;
import com.eternalcode.combat.fight.FightManager;
import com.eternalcode.combat.fight.drop.DropService;
Expand Down Expand Up @@ -182,7 +183,8 @@ public void onEnable() {
new FightBypassCreativeController(server, pluginConfig),
new FightActionBlockerController(this.fightManager, noticeService, pluginConfig, server),
new FightPearlController(pluginConfig.pearl, noticeService, this.fightManager, this.fightPearlService),
new DeathEffectController(pluginConfig),
new DeathFlareController(pluginConfig, server, scheduler),
new DeathLightningController(pluginConfig, server),
new UpdaterNotificationController(updaterService, pluginConfig, this.audienceProvider, miniMessage),
new KnockbackRegionController(noticeService, this.regionProvider, this.fightManager, knockbackService, server),
new FightEffectController(pluginConfig.effect, this.fightEffectService, this.fightManager, server),
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package com.eternalcode.combat.fight.death;

import com.eternalcode.combat.config.implementation.PluginConfig;
import com.eternalcode.combat.fight.event.CauseOfUnTag;
import com.eternalcode.combat.fight.event.FightUntagEvent;
import com.eternalcode.commons.scheduler.Scheduler;
import com.eternalcode.commons.scheduler.Task;
import java.time.Duration;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import org.bukkit.Color;
import org.bukkit.FireworkEffect;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Firework;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.inventory.meta.FireworkMeta;

public class DeathFlareController implements Listener {

private final PluginConfig pluginConfig;
private final Server server;
private final Scheduler scheduler;

public DeathFlareController(PluginConfig pluginConfig, Server server, Scheduler scheduler) {
this.pluginConfig = pluginConfig;
this.server = server;
this.scheduler = scheduler;
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onFightUntagEvent(FightUntagEvent event) {
CauseOfUnTag cause = event.getCause();
if (!cause.equals(CauseOfUnTag.DEATH) && !cause.equals(CauseOfUnTag.DEATH_BY_PLAYER)) {
return;
}

UUID uniqueId = event.getPlayer();
Player player = this.server.getPlayer(uniqueId);

if (player == null ) {
return;
}

if (this.pluginConfig.death.firework.inCombat && !this.pluginConfig.death.firework.afterEveryDeath) {
this.spawnFlare(player);
}
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onPlayerDeathEventLightning(PlayerDeathEvent event) {
Player player = event.getEntity();

if (this.pluginConfig.death.firework.afterEveryDeath) {
this.spawnFlare(player);
}
}

private void spawnFlare(Player player) {
Location deathLocation = player.getLocation();
World world = deathLocation.getWorld();

Firework flare = world.spawn(deathLocation, Firework.class);
FireworkMeta meta = flare.getFireworkMeta();

FireworkEffect effect = FireworkEffect.builder()
.with(this.pluginConfig.death.firework.fireworkType)
.withColor(Color.fromRGB(Integer.decode(this.pluginConfig.death.firework.primaryColor)))
.withFade(Color.fromRGB(Integer.decode(this.pluginConfig.death.firework.fadeColor)))
.trail(true)
.flicker(true)
.build();

meta.addEffect(effect);
meta.setPower(this.pluginConfig.death.firework.power);
flare.setFireworkMeta(meta);

if (this.pluginConfig.death.firework.enabled) {
AtomicReference<Task> taskRef = new AtomicReference<>();

Task task = this.scheduler.timerAsync(() -> {
if (flare.isDead() || !flare.isValid()) {
Task currentTask = taskRef.get();
if (currentTask != null) {
currentTask.cancel();
}
return;
}

this.spawnParticles(world, flare);

}, Duration.ZERO, Duration.ofMillis(50));

taskRef.set(task);
}
}

private void spawnParticles(World world, Firework flare) {
Location location = flare.getLocation();

world.spawnParticle(
this.pluginConfig.death.firework.mainParticle.get(),
location,
this.pluginConfig.death.firework.mainParticleCount,
0.05,
0.05,
0.05,
0.01
);

world.spawnParticle(
this.pluginConfig.death.firework.secondaryParticle.get(),
location,
this.pluginConfig.death.firework.secondaryParticleCount,
0.1,
0.1,
0.1,
0.01
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.eternalcode.combat.fight.death;

import com.eternalcode.combat.config.implementation.PluginConfig;
import com.eternalcode.combat.fight.event.CauseOfUnTag;
import com.eternalcode.combat.fight.event.FightUntagEvent;
import java.util.UUID;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;

public class DeathLightningController implements Listener {

private final PluginConfig pluginConfig;
private final Server server;

public DeathLightningController(PluginConfig pluginConfig, Server server) {
this.pluginConfig = pluginConfig;
this.server = server;
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onFightUntagEvent(FightUntagEvent event) {
CauseOfUnTag cause = event.getCause();
if (!cause.equals(CauseOfUnTag.DEATH) && !cause.equals(CauseOfUnTag.DEATH_BY_PLAYER)) {
return;
}

UUID uniqueId = event.getPlayer();
Player player = this.server.getPlayer(uniqueId);

if (player == null ) {
return;
}

if (this.pluginConfig.death.lightning.inCombat && !this.pluginConfig.death.lightning.afterEveryDeath) {
this.lightningStrike(player);
}
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onPlayerDeathEventLightning(PlayerDeathEvent event) {
Player player = event.getEntity();

if (this.pluginConfig.death.lightning.afterEveryDeath) {
lightningStrike(player);
}
}

private void lightningStrike(Player player) {
player.getWorld().strikeLightningEffect(player.getLocation());
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,77 @@
package com.eternalcode.combat.fight.death;

import com.cryptomorin.xseries.particles.XParticle;
import eu.okaeri.configs.OkaeriConfig;
import eu.okaeri.configs.annotation.Comment;
import org.bukkit.FireworkEffect;

public class DeathSettings extends OkaeriConfig {

@Comment("Should lightning strike when a player dies")
public boolean lightning = true;
@Comment({
"Settings related to lightning effect upon death",
"Setting afterEveryDeath and inCombat will disable this feature completely"
})
public LightningSettings lightning = new LightningSettings();

public static class LightningSettings extends OkaeriConfig {

@Comment("Should lightning spawn on every death?")
public boolean afterEveryDeath = false;

@Comment("Should lightning spawn on ONLY deaths in combat?")
public boolean inCombat = true;
}

@Comment({
"Settings for the Arc Raiders style flare (firework)",
"Setting afterEveryDeath and inCombat will disable this feature completely"
})
public FlareSettings firework = new FlareSettings();

public static class FlareSettings extends OkaeriConfig {

@Comment("Should firework (flare) spawn on every death?")
public boolean afterEveryDeath = false;

@Comment("Should firework (flare) spawn on ONLY deaths in combat?")
public boolean inCombat = true;

@Comment("Power of firework - how long till explosion")
public int power = 2;

@Comment({
"The firework (flare) effect type (BALL, BALL_LARGE, STAR, BURST, CREEPER)",
"Reference: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/FireworkEffect.Type.html"
})
public FireworkEffect.Type fireworkType = FireworkEffect.Type.BALL;

@Comment("Hex color for the firework (flare)")
public String primaryColor = "#a80022";

@Comment("Hex color for the fade of firework (flare)")
public String fadeColor = "#0a0a0a";

@Comment("Toggle on/off additional particles spawned in the firework (flare) path")
public boolean enabled = true;

@Comment({
"The main trail particle (e.g., CAMPFIRE_COSY_SMOKE, SMOKE_LARGE)",
"Reference: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Particle.html"
})
public XParticle mainParticle = XParticle.CAMPFIRE_COSY_SMOKE;

@Comment("Count of main particles spawned on each tick")
public int mainParticleCount = 3;

@Comment({
"The secondary trail particle (e.g., CAMPFIRE_COSY_SMOKE, SMOKE_LARGE)",
"Reference: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Particle.html"
})

public XParticle secondaryParticle = XParticle.SMALL_FLAME;

@Comment("Count of secondary particles spawned on each tick")
public int secondaryParticleCount = 3;

}
}