Final commit for combat mode

This commit is contained in:
Jules 2023-02-22 23:56:51 +01:00
parent 14c015645d
commit afa4a0467e
9 changed files with 303 additions and 152 deletions

View File

@ -44,13 +44,13 @@ public class PvpModeCommand extends RegisteredCommand {
// Toggling on when in PVP region // Toggling on when in PVP region
if (playerData.getCombat().isInPvpMode() && if (playerData.getCombat().isInPvpMode() &&
MythicLib.plugin.getFlags().isFlagAllowed(playerData.getPlayer(), CustomFlag.PVP_MODE)) { MythicLib.plugin.getFlags().isFlagAllowed(playerData.getPlayer(), CustomFlag.PVP_MODE)) {
playerData.getCombat().preventPvp(); playerData.getCombat().setInvulnerable(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeCommand);
MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.toggle.on-invulnerable", "time", MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.toggle.on-invulnerable", "time",
MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerability)).send(playerData.getPlayer()); MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeCommand)).send(playerData.getPlayer());
// Just send message otherwise // Just send message otherwise
} else } else
MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.toggle." + (playerData.getCombat().isInPvpMode() ? "on" : "off")).send((Player) sender); MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.toggle." + (playerData.getCombat().isInPvpMode() ? "on" : "off") + "-safe").send((Player) sender);
return true; return true;
} }
} }

View File

@ -0,0 +1,63 @@
package net.Indyuce.mmocore.comp.region.pvpmode;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.session.MoveType;
import com.sk89q.worldguard.session.Session;
import com.sk89q.worldguard.session.handler.FlagValueChangeHandler;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class MMOCoreFlagHandler extends FlagValueChangeHandler<StateFlag.State> {
@NotNull
protected PlayerData playerData;
protected long lastMessage;
protected static final long MESSAGE_TIMEOUT = 3 * 1000;
public MMOCoreFlagHandler(Session session, Flag<StateFlag.State> flag) {
super(session, flag);
}
/**
* Triggered when WorldGuard initializes the value for the first time,
* on player login or world change for instance.
*/
@Override
protected void onInitialValue(LocalPlayer player, ApplicableRegionSet set, StateFlag.State value) {
try {
playerData = PlayerData.get(player.getUniqueId());
} catch (Exception exception) {
// Citizens.
}
}
public abstract StateFlag.State getDefaultState();
/**
* Triggered when WorldGuard does not find a region setting the value of the flag.
* In that case, put PvP mode to its default setting that is OFF.
*/
@Override
protected boolean onAbsentValue(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, StateFlag.State lastValue, MoveType moveType) {
return onSetValue(player, from, to, toSet, getDefaultState(), lastValue, moveType);
}
protected boolean isInvalid() {
return playerData == null;
}
protected boolean toBoolean(@Nullable StateFlag.State state) {
return state == StateFlag.State.ALLOW;
}
protected boolean canSendMessage() {
return System.currentTimeMillis() > lastMessage + MESSAGE_TIMEOUT;
}
}

View File

@ -0,0 +1,59 @@
package net.Indyuce.mmocore.comp.region.pvpmode;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.StateFlag.State;
import com.sk89q.worldguard.session.MoveType;
import com.sk89q.worldguard.session.Session;
import io.lumine.mythic.lib.MythicLib;
import net.Indyuce.mmocore.MMOCore;
public class PvPFlagHandler extends MMOCoreFlagHandler {
public static final Factory FACTORY = new Factory() {
@Override
public PvPFlagHandler create(Session session) {
return new PvPFlagHandler(session, Flags.PVP);
}
};
public PvPFlagHandler(Session session, StateFlag flag) {
super(session, flag);
}
@Override
public State getDefaultState() {
return State.ALLOW;
}
/**
* Triggered when a player changes region and finds a new value for that flag.
* In that case, apply the new setting and display messages if needed.
*/
@Override
protected boolean onSetValue(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, State currentValue, State lastValue, MoveType moveType) {
if (isInvalid())
return true;
boolean newPvp = toBoolean(currentValue);
boolean lastPvp = toBoolean(lastValue);
if (newPvp && !lastPvp) {
// Apply invulnerability
playerData.getCombat().setInvulnerable(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeRegionChange);
// Send message
if (canSendMessage()) {
lastMessage = System.currentTimeMillis();
MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.enter.pvp-mode-on", "time",
MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeRegionChange)).send(playerData.getPlayer());
}
}
return true;
}
}

View File

@ -3,33 +3,23 @@ package net.Indyuce.mmocore.comp.region.pvpmode;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldguard.LocalPlayer; import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.protection.ApplicableRegionSet; import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.StateFlag; import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.StateFlag.State; import com.sk89q.worldguard.protection.flags.StateFlag.State;
import com.sk89q.worldguard.session.MoveType; import com.sk89q.worldguard.session.MoveType;
import com.sk89q.worldguard.session.Session; import com.sk89q.worldguard.session.Session;
import com.sk89q.worldguard.session.handler.FlagValueChangeHandler;
import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.comp.flags.CustomFlag; import io.lumine.mythic.lib.comp.flags.CustomFlag;
import io.lumine.mythic.lib.comp.flags.WorldGuardFlags; import io.lumine.mythic.lib.comp.flags.WorldGuardFlags;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.PvpModeCommand; import net.Indyuce.mmocore.command.PvpModeCommand;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects; import java.util.Objects;
public class PvPModeHandler extends FlagValueChangeHandler<State> { public class PvPModeHandler extends MMOCoreFlagHandler {
@NotNull
private PlayerData playerData;
private long lastMessage;
private static final long MESSAGE_TIMEOUT = 3 * 1000;
public static final Factory FACTORY = new Factory() { public static final Factory FACTORY = new Factory() {
public final WorldGuardFlags wgFlags = Objects.requireNonNull(MythicLib.plugin.getFlags().getHandler(WorldGuardFlags.class), "Could not reach ML compatibility class for WG"); final WorldGuardFlags wgFlags = Objects.requireNonNull(MythicLib.plugin.getFlags().getHandler(WorldGuardFlags.class), "Could not reach ML compatibility class for WG");
@Override @Override
public PvPModeHandler create(Session session) { public PvPModeHandler create(Session session) {
@ -41,29 +31,10 @@ public class PvPModeHandler extends FlagValueChangeHandler<State> {
super(session, flag); super(session, flag);
} }
/**
* Triggered when WorldGuard initializes the value for the first time,
* on player login or world change for instance.
*/
@Override @Override
protected void onInitialValue(LocalPlayer player, ApplicableRegionSet set, State value) { public State getDefaultState() {
try { return State.ALLOW;
playerData = PlayerData.get(player.getUniqueId());
} catch (Exception exception) {
// Citizens.
} }
}
/**
* Triggered when WorldGuard does not find a region setting the value of the flag.
* In that case, put PvP mode to its default setting that is OFF.
*/
@Override
protected boolean onAbsentValue(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, StateFlag.State lastValue, MoveType moveType) {
return onSetValue(player, from, to, toSet, DEFAULT_STATE, lastValue, moveType);
}
public static final StateFlag.State DEFAULT_STATE = StateFlag.State.DENY;
/** /**
* Triggered when a player changes region and finds a new value for that flag. * Triggered when a player changes region and finds a new value for that flag.
@ -71,11 +42,12 @@ public class PvPModeHandler extends FlagValueChangeHandler<State> {
*/ */
@Override @Override
protected boolean onSetValue(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, StateFlag.State currentValue, StateFlag.State lastValue, MoveType moveType) { protected boolean onSetValue(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, StateFlag.State currentValue, StateFlag.State lastValue, MoveType moveType) {
boolean newPvpMode = toBoolean(currentValue);
boolean lastPvpMode = toBoolean(lastValue);
if (isInvalid()) if (isInvalid())
return true; return true;
boolean newPvpMode = toBoolean(currentValue);
boolean lastPvpMode = toBoolean(lastValue);
if (!newPvpMode && lastPvpMode) { if (!newPvpMode && lastPvpMode) {
// Apply cooldown // Apply cooldown
@ -83,10 +55,16 @@ public class PvPModeHandler extends FlagValueChangeHandler<State> {
// Send message // Send message
if (canSendMessage()) { if (canSendMessage()) {
final String msgPath = (playerData.getCombat().isInPvpMode() && !playerData.getCombat().canQuitPvpMode()) ? "allowed" : "denied";
// Leave combat when joining safe zone
final boolean pvpFlag = toSet.queryState(null, Flags.PVP) != StateFlag.State.DENY;
if (playerData.getCombat().isInPvpMode() && !pvpFlag)
playerData.getCombat().close();
final boolean pvpEnabled = playerData.getCombat().isInPvpMode() && !playerData.getCombat().canQuitPvpMode() && pvpFlag;
lastMessage = System.currentTimeMillis(); lastMessage = System.currentTimeMillis();
final double remaining = (playerData.getCombat().getLastHit() + MMOCore.plugin.configManager.pvpModeCombatTimeout * 1000.0D - System.currentTimeMillis()) / 1000.0D; final double remaining = (playerData.getCombat().getLastHit() + MMOCore.plugin.configManager.pvpModeCombatTimeout * 1000.0D - System.currentTimeMillis()) / 1000.0D;
MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.leave.pvp-" + msgPath, "remaining", MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.leave.pvp-" + (pvpEnabled ? "allowed" : "denied"), "remaining",
(MythicLib.plugin.getMMOConfig()).decimal.format(remaining)).send(playerData.getPlayer()); (MythicLib.plugin.getMMOConfig()).decimal.format(remaining)).send(playerData.getPlayer());
} }
} else if (newPvpMode && !lastPvpMode) { } else if (newPvpMode && !lastPvpMode) {
@ -97,27 +75,15 @@ public class PvPModeHandler extends FlagValueChangeHandler<State> {
// Apply invulnerability // Apply invulnerability
final boolean applyInvulnerability = playerData.getCombat().isInPvpMode() && playerData.getCombat().canQuitPvpMode(); final boolean applyInvulnerability = playerData.getCombat().isInPvpMode() && playerData.getCombat().canQuitPvpMode();
if (applyInvulnerability) if (applyInvulnerability)
playerData.getCombat().preventPvp(); playerData.getCombat().setInvulnerable(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeRegionChange);
// Send message // Send message
if (canSendMessage()) { if (canSendMessage()) {
lastMessage = System.currentTimeMillis(); lastMessage = System.currentTimeMillis();
MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.enter.pvp-mode-" + (applyInvulnerability ? "on" : "off"), "time", MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.enter.pvp-mode-" + (applyInvulnerability ? "on" : "off"), "time",
MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerability)).send(playerData.getPlayer()); MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeRegionChange)).send(playerData.getPlayer());
} }
} }
return true; return true;
} }
private boolean isInvalid() {
return playerData == null;
}
private boolean toBoolean(@Nullable State state) {
return state == State.ALLOW;
}
private boolean canSendMessage() {
return System.currentTimeMillis() > lastMessage + MESSAGE_TIMEOUT;
}
} }

View File

@ -1,42 +1,80 @@
package net.Indyuce.mmocore.comp.region.pvpmode; package net.Indyuce.mmocore.comp.region.pvpmode;
import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.protection.events.DisallowedPVPEvent; import com.sk89q.worldguard.session.handler.Handler;
import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.comp.flags.CustomFlag; import io.lumine.mythic.lib.comp.flags.CustomFlag;
import io.lumine.mythic.lib.comp.interaction.InteractionType;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import javax.annotation.Nullable;
public class PvPModeListener implements Listener { public class PvPModeListener implements Listener {
public PvPModeListener() { public PvPModeListener() {
Validate.isTrue(WorldGuard.getInstance().getPlatform().getSessionManager().registerHandler(PvPModeHandler.FACTORY, null), "Could not register WG handler for PvP mode"); Validate.isTrue(registerHandler(PvPModeHandler.FACTORY), "Could not register WG handler for PvP mode");
if (MMOCore.plugin.getConfig().getBoolean("pvp_mode.invulnerability.apply_to_pvp_flag"))
Validate.isTrue(registerHandler(PvPFlagHandler.FACTORY), "Could not register WG handler for PvP");
} }
private boolean registerHandler(Handler.Factory factory) {
return WorldGuard.getInstance().getPlatform().getSessionManager().registerHandler(factory, null);
}
/**
* Runs after MythicLib interaction checks. This listener
* takes care of PVP inside of PvP-mode regions.
*/
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void unblockPvp(DisallowedPVPEvent event) { public void a(EntityDamageByEntityEvent event) {
PlayerData defender, attacker; if (!UtilityMethods.isRealPlayer(event.getEntity()))
if (!(attacker = PlayerData.get(event.getAttacker())).getCombat().isInPvpMode() || !(defender = PlayerData.get(event.getDefender())).getCombat().isInPvpMode())
return; return;
// If defender is out of combat final @Nullable Player source = UtilityMethods.getPlayerDamager(event);
if (!defender.getCombat().canPvp()) if (source == null)
return; return;
// If attacker cannot deal damage yet // Check for target's invulnerability BEFORE pvp-mode flag because it can also
if (!MMOCore.plugin.configManager.pvpModeInvulnerabilityCanDamage && !attacker.getCombat().canPvp()) // happen when the option pvp_mode.invulnerability.apply_to_pvp_flag is on
return; final Player target = (Player) event.getEntity();
final PlayerData targetData = PlayerData.get(target);
// Defender is still fighting and cannot leave PvP mode if (targetData.getCombat().isInvulnerable()) {
if (!defender.getCombat().canQuitPvpMode()) final long left = targetData.getCombat().getInvulnerableTill() - System.currentTimeMillis();
MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.invulnerable-target",
"left", MythicLib.plugin.getMMOConfig().decimal.format(left / 1000d)).send(source);
event.setCancelled(true); event.setCancelled(true);
return;
}
// Enable PvP if accepted // If attacker is still invulnerable and cannot deal damage
else if (MythicLib.plugin.getFlags().isFlagAllowed(event.getDefender().getLocation(), CustomFlag.PVP_MODE) && final PlayerData sourceData = PlayerData.get(source);
MythicLib.plugin.getEntities().checkPvpInteractionRules(event.getAttacker(), event.getDefender(), InteractionType.OFFENSE_ACTION, true)) if (!MMOCore.plugin.configManager.pvpModeInvulnerabilityCanDamage && sourceData.getCombat().isInvulnerable()) {
final long left = sourceData.getCombat().getInvulnerableTill() - System.currentTimeMillis();
MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.invulnerable-self",
"left", MythicLib.plugin.getMMOConfig().decimal.format(left / 1000d)).send(source);
event.setCancelled(true); event.setCancelled(true);
return;
}
// Checks for PvP mode on target location
if (!MythicLib.plugin.getFlags().isFlagAllowed(target.getLocation(), CustomFlag.PVP_MODE))
return;
// Defender has not enabled PvP mode
if (!targetData.getCombat().isInPvpMode()) {
event.setCancelled(true);
MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.pvp-mode-disabled-target").send(source);
}
// Attacker has not enabled PvP mode
else if (!sourceData.getCombat().isInPvpMode()) {
event.setCancelled(true);
MMOCore.plugin.configManager.getSimpleMessage("pvp-mode.cannot-hit.pvp-mode-disabled-self").send(source);
}
} }
} }

View File

@ -27,12 +27,13 @@ import java.util.logging.Level;
public class ConfigManager { public class ConfigManager {
public final CommandVerbose commandVerbose = new CommandVerbose(); public final CommandVerbose commandVerbose = new CommandVerbose();
public boolean overrideVanillaExp, canCreativeCast, passiveSkillNeedBound, cobbleGeneratorXP, saveDefaultClassInfo, attributesAsClassInfo, splitProfessionExp, disableQuestBossBar, pvpModeEnabled, pvpModeInvulnerabilityCanDamage; public boolean overrideVanillaExp, canCreativeCast, passiveSkillNeedBound, cobbleGeneratorXP, saveDefaultClassInfo, attributesAsClassInfo, splitProfessionExp, disableQuestBossBar,
pvpModeEnabled, pvpModeInvulnerabilityCanDamage;
public String partyChatPrefix, noSkillBoundPlaceholder; public String partyChatPrefix, noSkillBoundPlaceholder;
public ChatColor staminaFull, staminaHalf, staminaEmpty; public ChatColor staminaFull, staminaHalf, staminaEmpty;
public long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown, globalSkillCooldown; public long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown, globalSkillCooldown;
public double lootChestsChanceWeight, dropItemsChanceWeight, fishingDropsChanceWeight, partyMaxExpSplitRange, pvpModeToggleOnCooldown, pvpModeToggleOffCooldown, pvpModeCombatCooldown, pvpModeCombatTimeout, pvpModeInvulnerability, public double lootChestsChanceWeight, dropItemsChanceWeight, fishingDropsChanceWeight, partyMaxExpSplitRange, pvpModeToggleOnCooldown, pvpModeToggleOffCooldown, pvpModeCombatCooldown,
pvpModeRegionEnterCooldown, pvpModeRegionLeaveCooldown; pvpModeCombatTimeout, pvpModeInvulnerabilityTimeRegionChange, pvpModeInvulnerabilityTimeCommand, pvpModeRegionEnterCooldown, pvpModeRegionLeaveCooldown;
public int maxPartyLevelDifference, maxBoundActiveSkills, maxBoundPassiveSkills; public int maxPartyLevelDifference, maxBoundActiveSkills, maxBoundPassiveSkills;
public final List<EntityDamageEvent.DamageCause> combatLogDamageCauses = new ArrayList<>(); public final List<EntityDamageEvent.DamageCause> combatLogDamageCauses = new ArrayList<>();
@ -140,7 +141,8 @@ public class ConfigManager {
pvpModeRegionEnterCooldown = config.getDouble("pvp_mode.cooldown.region_enter"); pvpModeRegionEnterCooldown = config.getDouble("pvp_mode.cooldown.region_enter");
pvpModeRegionLeaveCooldown = config.getDouble("pvp_mode.cooldown.region_leave"); pvpModeRegionLeaveCooldown = config.getDouble("pvp_mode.cooldown.region_leave");
pvpModeCombatTimeout = config.getDouble("pvp_mode.combat_timeout"); pvpModeCombatTimeout = config.getDouble("pvp_mode.combat_timeout");
pvpModeInvulnerability = config.getDouble("pvp_mode.invulnerability.time"); pvpModeInvulnerabilityTimeCommand = config.getDouble("pvp_mode.invulnerability.time.command");
pvpModeInvulnerabilityTimeRegionChange = config.getDouble("pvp_mode.invulnerability.time.region_change");
pvpModeInvulnerabilityCanDamage = config.getBoolean("pvp_mode.invulnerability.can_damage"); pvpModeInvulnerabilityCanDamage = config.getBoolean("pvp_mode.invulnerability.can_damage");
// Resources // Resources

View File

@ -14,7 +14,7 @@ public class CombatHandler implements Closable {
private final PlayerData player; private final PlayerData player;
private final long firstHit = System.currentTimeMillis(); private final long firstHit = System.currentTimeMillis();
private long lastHit = System.currentTimeMillis(), lastToggle; private long lastHit = System.currentTimeMillis(), invulnerableTill;
private boolean pvpMode; private boolean pvpMode;
@ -27,7 +27,7 @@ public class CombatHandler implements Closable {
public void update() { public void update() {
lastHit = System.currentTimeMillis(); lastHit = System.currentTimeMillis();
lastToggle = 0; invulnerableTill = 0;
player.getMMOPlayerData().getCooldownMap().applyCooldown(PvpModeCommand.COOLDOWN_KEY, MMOCore.plugin.configManager.pvpModeCombatCooldown); player.getMMOPlayerData().getCooldownMap().applyCooldown(PvpModeCommand.COOLDOWN_KEY, MMOCore.plugin.configManager.pvpModeCombatCooldown);
// Simply refreshing // Simply refreshing
@ -58,6 +58,10 @@ public class CombatHandler implements Closable {
return firstHit; return firstHit;
} }
public long getInvulnerableTill() {
return invulnerableTill;
}
/** /**
* Simply checks if there is a scheduled task. * Simply checks if there is a scheduled task.
* *
@ -74,12 +78,12 @@ public class CombatHandler implements Closable {
* *
* @return If the player is inert i.e if he CAN hit/take damage * @return If the player is inert i.e if he CAN hit/take damage
*/ */
public boolean canPvp() { public boolean isInvulnerable() {
return System.currentTimeMillis() > lastToggle + MMOCore.plugin.configManager.pvpModeInvulnerability * 1000; return System.currentTimeMillis() < invulnerableTill;
} }
public void preventPvp() { public void setInvulnerable(double time) {
lastToggle = System.currentTimeMillis(); invulnerableTill = System.currentTimeMillis() + (long) (time * 1000);
} }
public boolean canQuitPvpMode() { public boolean canQuitPvpMode() {
@ -108,5 +112,10 @@ public class CombatHandler implements Closable {
public void close() { public void close() {
if (isInCombat()) if (isInCombat())
quit(true); quit(true);
// Necessary steps when entering a town.
lastHit = 0;
invulnerableTill = 0;
player.getMMOPlayerData().getCooldownMap().resetCooldown(PvpModeCommand.COOLDOWN_KEY);
} }
} }

View File

@ -303,12 +303,19 @@ pvp_mode:
# - entering a PvP region with PvP mode turned on. # - entering a PvP region with PvP mode turned on.
# - using the /pvpmode command inside of a PvP region. # - using the /pvpmode command inside of a PvP region.
invulnerability: invulnerability:
time: 60 time:
region_change: 60
command: 30
# When enabled, players can damage other players # When enabled, players can damage other players
# to end this invulnerable time period. # to end this invulnerable time period.
can_damage: false can_damage: false
# When enabled, leaving a no-PVP zone and entering a PVP zone
# will apply the SAME invulnerability time.
# Requires /reload when changed
apply_to_pvp_flag: false
cooldown: cooldown:
# Cooldown before being able to use the /pvpmode # Cooldown before being able to use the /pvpmode

View File

@ -1,45 +1,52 @@
# Level & Experience # Level & Experience
level-up: level-up:
- '' - ''
- '&eCongratulations, you reached level &6{level}&e!' - '&eCongratulations, you reached level &6{level}&e!'
- '&eUse &6/p &eto see your new statistics!' - '&eUse &6/p &eto see your new statistics!'
- '' - ''
profession-level-up: profession-level-up:
- '&eYou are now level &6{level}&e in &6{profession}&e!' - '&eYou are now level &6{level}&e in &6{profession}&e!'
exp-notification: '%&f{profession} &e{progress} &e{ratio}%' exp-notification: '%&f{profession} &e{progress} &e{ratio}%'
exp-hologram: '&e+{exp} EXP!' exp-hologram: '&e+{exp} EXP!'
class-select: '&eYou are now a &6{class}&e!' class-select: '&eYou are now a &6{class}&e!'
already-on-class: '&cYou are already a {class}.' already-on-class: '&cYou are already a {class}.'
death-exp-loss: death-exp-loss:
- '' - ''
- '&4You died and lost {loss} experience.' - '&4You died and lost {loss} experience.'
- '' - ''
# General # General
not-enough-perms: '&cYou do not have enough permissions.' not-enough-perms: '&cYou do not have enough permissions.'
# Experience boosters # Experience boosters
booster-main: booster-main:
- '&e' - '&e'
- '&eA &6{multiplier}x&e EXP multiplier is now active!' - '&eA &6{multiplier}x&e EXP multiplier is now active!'
- '&e' - '&e'
booster-skill: booster-skill:
- '&e' - '&e'
- '&eA &6{multiplier}x&e &6{profession} &eEXP multiplier is now active!' - '&eA &6{multiplier}x&e &6{profession} &eEXP multiplier is now active!'
- '&e' - '&e'
booster-expired: '&cExpired!' booster-expired: '&cExpired!'
# PvP Mode # PvP Mode
pvp-mode: pvp-mode:
cooldown: '&cPlease wait {remaining} seconds to use this command again.' cooldown: '&cPlease wait {remaining} seconds to use this command again.'
# When you cannot hit another player
cannot-hit:
pvp-mode-disabled-target: '&cThis player has not toggled on PvP.'
pvp-mode-disabled-self: '&cYou have not toggled on PvP.'
invulnerable-self: '&cYou are still out of combat for {left} seconds.'
invulnerable-target: '&cThis player is out of combat for {left} seconds.'
# When using /pvpmode # When using /pvpmode
toggle: toggle:
on: '&aPvP Mode on.' on-safe: '&aYou will now be able to fight other players in dedicated areas.'
on-invulnerable: '&aPvP Mode on. You are now invulnerable for {time} seconds.' on-invulnerable: '&aYou will be able to fight other players in {time} seconds.'
off: '&cPvP Mode off.' off-safe: '&cYou can no longer fight other players.'
# Entering/leaving regions with specific flag value # Entering/leaving regions
leave: leave:
pvp-allowed: '&cYou left a PVP zone but are still vulnerable for {remaining} seconds!' pvp-allowed: '&cYou left a PVP zone but are still vulnerable for {remaining} seconds!'
pvp-denied: '&cYou left the PVP zone.' pvp-denied: '&cYou left the PVP zone.'
@ -118,20 +125,20 @@ friend-request-cooldown: '&cPlease wait {cooldown}.'
cant-request-to-yourself: '&cYou can''t send a request to yourself.' cant-request-to-yourself: '&cYou can''t send a request to yourself.'
already-friends: '&cYou are already friends with {player}.' already-friends: '&cYou are already friends with {player}.'
friend-request: friend-request:
- '{"text":""}' - '{"text":""}'
- '{"text":"&6{player} &ejust sent you a friend request!"}' - '{"text":"&6{player} &ejust sent you a friend request!"}'
- '[{"text":" ","hoverEvent":{}},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/friends accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r ","hoverEvent":{}},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/friends deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]' - '[{"text":" ","hoverEvent":{}},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/friends accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r ","hoverEvent":{}},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/friends deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]'
- '{"text":""}' - '{"text":""}'
# Parties # Parties
party-chat: '&5[Party] {player}: {message}' party-chat: '&5[Party] {player}: {message}'
sent-party-invite: '&eYou sent a party invite to &6{player}&e.' sent-party-invite: '&eYou sent a party invite to &6{player}&e.'
already-in-party: '&c{player} is already in your party.' already-in-party: '&c{player} is already in your party.'
party-invite: party-invite:
- '{"text":""}' - '{"text":""}'
- '{"text":"&6{player} &ehas invited you to their party!"}' - '{"text":"&6{player} &ehas invited you to their party!"}'
- '[{"text":" "},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/party accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r "},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/party deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]' - '[{"text":" "},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/party accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r "},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/party deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]'
- '{"text":""}' - '{"text":""}'
party-is-full: '&cSorry, your party is full.' party-is-full: '&cSorry, your party is full.'
party-joined: '&eYou successfully joined &6{owner}&e''s party.' party-joined: '&eYou successfully joined &6{owner}&e''s party.'
party-joined-other: '&6{player}&e joined your party!' party-joined-other: '&6{player}&e joined your party!'
@ -145,10 +152,10 @@ guild-chat: '&a[{tag}] {player}: {message}'
sent-guild-invite: '&eYou sent a guild invite to &6{player}&e.' sent-guild-invite: '&eYou sent a guild invite to &6{player}&e.'
already-in-guild: '&c{player} is already in your guild.' already-in-guild: '&c{player} is already in your guild.'
guild-invite: guild-invite:
- '{"text":""}' - '{"text":""}'
- '{"text":"&6{player} &ehas invited you to their guild!"}' - '{"text":"&6{player} &ehas invited you to their guild!"}'
- '[{"text":" "},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/guild accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r "},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/guild deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]' - '[{"text":" "},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/guild accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r "},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/guild deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]'
- '{"text":""}' - '{"text":""}'
#guild-is-full: '&cSorry, your guild is full.' -Unused right now #guild-is-full: '&cSorry, your guild is full.' -Unused right now
guild-joined: '&eYou successfully joined &6{owner}&e''s guild.' guild-joined: '&eYou successfully joined &6{owner}&e''s guild.'
guild-joined-other: '&6{player}&e joined your guild!' guild-joined-other: '&6{player}&e joined your guild!'