diff --git a/TwosideKeeper.jar b/TwosideKeeper.jar index c8f6bde..3a226eb 100644 Binary files a/TwosideKeeper.jar and b/TwosideKeeper.jar differ diff --git a/src/plugin.yml b/src/plugin.yml index a326e0c..85b05e9 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -1,6 +1,6 @@ name: TwosideKeeper main: sig.plugin.TwosideKeeper.TwosideKeeper -version: 3.11.1g +version: 3.12.0 loadbefore: [aPlugin] commands: money: @@ -182,4 +182,9 @@ commands: description: Declare PvP to a player. usage: /pvp permission: TwosideKeeper.money + permission-message: No permissions! + fb: + description: Determine if a player is a fresh blood player or not. + usage: /fb + permission: TwosideKeeper.money permission-message: No permissions! \ No newline at end of file diff --git a/src/sig/plugin/TwosideKeeper/Buff.java b/src/sig/plugin/TwosideKeeper/Buff.java index fccc88a..506572b 100644 --- a/src/sig/plugin/TwosideKeeper/Buff.java +++ b/src/sig/plugin/TwosideKeeper/Buff.java @@ -225,6 +225,9 @@ public class Buff { public static void addBuff(LivingEntity l, String name, Buff buff, boolean stacking) { if (l instanceof Player) { Player p = (Player)l; + if (PVP.isPvPing(p)) { + buff.setDuration((int)((buff.expireTime-TwosideKeeper.getServerTickTime()) / 2)); + } PlayerStructure pd = PlayerStructure.GetPlayerStructure(p); int oldlv = 0; long oldduration = 0; diff --git a/src/sig/plugin/TwosideKeeper/CustomDamage.java b/src/sig/plugin/TwosideKeeper/CustomDamage.java index c5e5650..20da749 100644 --- a/src/sig/plugin/TwosideKeeper/CustomDamage.java +++ b/src/sig/plugin/TwosideKeeper/CustomDamage.java @@ -4176,14 +4176,13 @@ public class CustomDamage { double mult = 0.0; if (target!=null && shooter!=null && isBackstab(target,shooter) && (shooter instanceof Player) && PlayerMode.getPlayerMode((Player)shooter)==PlayerMode.SLAYER) { - if (!PVP.isPvPing((Player)shooter)) { - if (ItemSet.meetsSlayerSwordConditions(ItemSet.ASSASSIN, 27, 3, (Player)shooter)) { - mult+=5.0; - } else { - mult+=2.0; - } + if (ItemSet.meetsSlayerSwordConditions(ItemSet.ASSASSIN, 27, 3, (Player)shooter)) { + mult+=5.0; } else { - mult += 0.5; + mult+=2.0; + } + if (PVP.isPvPing((Player)shooter)) { + mult /= 4.0; } if (ItemSet.meetsSlayerSwordConditions(ItemSet.ASSASSIN, 18, 2, (Player)shooter)) { Material name = ((Player)shooter).getEquipment().getItemInMainHand().getType(); diff --git a/src/sig/plugin/TwosideKeeper/GlobalLoot.java b/src/sig/plugin/TwosideKeeper/GlobalLoot.java index 1eb46a4..544d242 100644 --- a/src/sig/plugin/TwosideKeeper/GlobalLoot.java +++ b/src/sig/plugin/TwosideKeeper/GlobalLoot.java @@ -22,6 +22,7 @@ import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.TextComponent; import sig.plugin.TwosideKeeper.HelperStructures.WorldShop; import sig.plugin.TwosideKeeper.HelperStructures.Common.GenericFunctions; +import sig.plugin.TwosideKeeper.HelperStructures.Utils.InventoryUtils; import sig.plugin.TwosideKeeper.HelperStructures.Utils.ItemUtils; import sig.plugin.TwosideKeeper.HelperStructures.Utils.TextUtils; @@ -67,8 +68,9 @@ public class GlobalLoot { for (Player p : players) { if (p.getOpenInventory().getType()==InventoryType.CRAFTING && drop_inventories.containsKey(p.getUniqueId())) { - if (!last_opened_loot.containsKey(p.getUniqueId()) || - last_opened_loot.get(p.getUniqueId())+100<=TwosideKeeper.getServerTickTime()) { + if ((!last_opened_loot.containsKey(p.getUniqueId()) || + last_opened_loot.get(p.getUniqueId())+100<=TwosideKeeper.getServerTickTime()) && + !InventoryUtils.hasEmptyInventory(drop_inventories.get(p.getUniqueId()))) { last_opened_loot.put(p.getUniqueId(), TwosideKeeper.getServerTickTime()); //Bukkit.dispatchCommand(Bukkit.getConsoleSender(),"tellraw @a [\"\",{\"text\":\"<"+p.getName()+"> \"},{\"text\":\""+ChatColor.GREEN+"A "+item.getCustomName()+" is nearby! "+ChatColor.BOLD+"[\"},{\"text\":\"[Click Here]"+ChatColor.RESET+ChatColor.GREEN+"\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\""+GenericFunctions.GetItemName(ev.getPlayer().getEquipment().getItemInMainHand())+""+WorldShop.GetItemInfo(ev.getPlayer().getEquipment().getItemInMainHand()).replace("\"", "\\\"")+"\"}},{\"text\":\""+ev.getMessage().substring(pos)+"\"}]"); TextComponent tc = new TextComponent(ChatColor.GREEN+"A "+item.getCustomName()+ChatColor.RESET+ChatColor.GREEN+" is nearby! "); @@ -80,11 +82,11 @@ public class GlobalLoot { p.spigot().sendMessage(tc); //p.openInventory(drop_inventories.get(p.getUniqueId())); } - } else { + }/* else { if (!drop_inventories.containsKey(p.getUniqueId())) { TwosideKeeper.log("WARNING! Could not find UUID "+p.getUniqueId()+". UUID List: "+TextUtils.outputHashmap(drop_inventories), 1); } - } + }*/ } return true; } else { @@ -113,7 +115,8 @@ public class GlobalLoot { } public void openDropInventory(Player p) { - if (drop_inventories.containsKey(p.getUniqueId())) { + if (drop_inventories.containsKey(p.getUniqueId()) && + !InventoryUtils.hasEmptyInventory(drop_inventories.get(p.getUniqueId()))) { p.openInventory(drop_inventories.get(p.getUniqueId())); } else { TwosideKeeper.log("WARNING! Drop Inventory for Player with UUID <"+p.getUniqueId()+"> does not have an associated inventory with Global Loot <"+item.getUniqueId()+">. THIS SHOULD NOT BE HAPPENING!!", 1); diff --git a/src/sig/plugin/TwosideKeeper/HelperStructures/CustomItem.java b/src/sig/plugin/TwosideKeeper/HelperStructures/CustomItem.java index e5a952e..5d85769 100644 --- a/src/sig/plugin/TwosideKeeper/HelperStructures/CustomItem.java +++ b/src/sig/plugin/TwosideKeeper/HelperStructures/CustomItem.java @@ -140,6 +140,28 @@ public class CustomItem { return token.clone(); } + public static ItemStack BattleToken() { + ItemStack token = new ItemStack(Material.COMMAND); + ItemUtils.setDisplayName(token, ChatColor.GRAY+"| "+ChatColor.DARK_RED+ChatColor.BOLD+"Battle Token"+ChatColor.RESET+ChatColor.GRAY+" |"); + ItemUtils.addLore(token, ChatColor.GOLD+"Given to the fiercest of warriors in"); + ItemUtils.addLore(token, ChatColor.GOLD+"the world. This token is a symbol of"); + ItemUtils.addLore(token, ChatColor.GOLD+"recognition and can be used to obtain"); + ItemUtils.addLore(token, ChatColor.GOLD+"special items exclusively from battling."); + token.addUnsafeEnchantment(Enchantment.LUCK, 1); + ItemUtils.hideEnchantments(token); + return token.clone(); + } + + public static boolean isBattleToken(ItemStack item) { + if (ItemUtils.isValidLoreItem(item) && + item.containsEnchantment(Enchantment.LUCK) && + item.getType()==Material.COMMAND) { + return true; + } else { + return false; + } + } + public static boolean isDailyToken(ItemStack item) { if (ItemUtils.isValidLoreItem(item) && item.containsEnchantment(Enchantment.LUCK) && diff --git a/src/sig/plugin/TwosideKeeper/HelperStructures/Utils/ArrayUtils.java b/src/sig/plugin/TwosideKeeper/HelperStructures/Utils/ArrayUtils.java index bec0503..0ee38a8 100644 --- a/src/sig/plugin/TwosideKeeper/HelperStructures/Utils/ArrayUtils.java +++ b/src/sig/plugin/TwosideKeeper/HelperStructures/Utils/ArrayUtils.java @@ -44,7 +44,7 @@ public class ArrayUtils { lookingfor = ' '; } else { collective = collective + " " + args[i]; - TwosideKeeper.log(collective, 0); + //TwosideKeeper.log(collective, 0); } } else { newargs.add(args[i]); diff --git a/src/sig/plugin/TwosideKeeper/HelperStructures/Utils/InventoryUtils.java b/src/sig/plugin/TwosideKeeper/HelperStructures/Utils/InventoryUtils.java index edd5538..72ab487 100644 --- a/src/sig/plugin/TwosideKeeper/HelperStructures/Utils/InventoryUtils.java +++ b/src/sig/plugin/TwosideKeeper/HelperStructures/Utils/InventoryUtils.java @@ -202,7 +202,7 @@ public class InventoryUtils { ItemStack[] inventory = inv.getContents(); for (ItemStack i : inventory) { if (i!=null && i.getType()!=Material.AIR) { - TwosideKeeper.log("Item is "+i, 0); + TwosideKeeper.log("Item is "+i, 5); return false; } } diff --git a/src/sig/plugin/TwosideKeeper/PVP.java b/src/sig/plugin/TwosideKeeper/PVP.java index 3719a72..253dcc4 100644 --- a/src/sig/plugin/TwosideKeeper/PVP.java +++ b/src/sig/plugin/TwosideKeeper/PVP.java @@ -1,5 +1,6 @@ package sig.plugin.TwosideKeeper; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -16,6 +17,7 @@ import org.bukkit.boss.BarFlag; import org.bukkit.boss.BarStyle; import org.bukkit.boss.BossBar; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import com.google.common.collect.ImmutableList; @@ -23,6 +25,8 @@ import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.ComponentBuilder; import net.md_5.bungee.api.chat.HoverEvent; import net.md_5.bungee.api.chat.TextComponent; +import sig.plugin.TwosideKeeper.HelperStructures.ArtifactItem; +import sig.plugin.TwosideKeeper.HelperStructures.CustomItem; import sig.plugin.TwosideKeeper.HelperStructures.Common.GenericFunctions; import sig.plugin.TwosideKeeper.HelperStructures.Utils.DebugUtils; import sig.plugin.TwosideKeeper.HelperStructures.Utils.TextUtils; @@ -47,6 +51,7 @@ public class PVP { BossBar matchTimer = null; int duration = 0; boolean isTeamMatch=false; + String freshBloodPlayer; //NEUTRAL team //Team1 @@ -55,15 +60,72 @@ public class PVP { public PVP(Player...players) { for (Player p : players) { this.players.put(p.getName(),new PVPPlayer()); + findFreshBloodPlayer(); //Bukkit.getServer().broadcastMessage(ChatColor.GREEN+"Waiting for any additional players to join the PVP Match..."); //Bukkit.getServer().broadcastMessage(ChatColor.GREEN+"Players must click on "+getParticipants()+" to join in."); p.sendMessage(ChatColor.GREEN+"Waiting for any additional players to join the PVP Match..."); } Bukkit.getServer().broadcastMessage(ChatColor.GREEN+"A new PvP Match Request is underway. Click on "+getParticipants(true)+" to join in."); + announceFreshBloodPlayer(true); + showReadyChoice(); state = CHOICEENGINE.WAITFORPLAYERS; timer = TwosideKeeper.getServerTickTime(); } + private void showReadyChoice() { + for (String s : players.keySet()) { + showReadyChoice(s); + } + } + + private void showReadyChoice(String player) { + TextComponent tca = new TextComponent(" "); + TextComponent tc = new TextComponent(ChatColor.GREEN+"[Ready]"); + tc.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND,"/pvp _READY_ YES")); + tc.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,new ComponentBuilder("Click to ready up for the match. All players must be "+ChatColor.GREEN+"READY"+ChatColor.RESET+" to continue.").create())); + tc.addExtra(" "); + TextComponent tc2 = new TextComponent(ChatColor.RED+"[Leave]"); + tc2.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND,"/pvp _READY_ NO")); + tc2.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,new ComponentBuilder("Click to leave the match.").create())); + tc.addExtra(tc2); + tca.addExtra(tc); + Player p = Bukkit.getPlayer(player); + if (p!=null && p.isOnline()) { + p.spigot().sendMessage(tca); + } + } + + private void announceFreshBloodPlayer(boolean announce) { + if (freshBloodPlayer!=null) { + if (announce) { + Bukkit.getServer().broadcastMessage(ChatColor.GRAY+""+ChatColor.ITALIC+" This match features a Fresh Blood Player, doubling the drop rate."); + } else { + for (String s : players.keySet()) { + Player p = Bukkit.getPlayer(s); + if (p!=null && p.isOnline()) { + Bukkit.getServer().broadcastMessage(ChatColor.YELLOW+""+ChatColor.ITALIC+" "+freshBloodPlayer+ChatColor.GRAY+" is a Fresh Blood player, doubling the drop rate of this match."); + } + } + } + } + } + + private void findFreshBloodPlayer() { + if (freshBloodPlayer==null) { + for (String s : players.keySet()) { + Player p = Bukkit.getPlayer(s); + if (p!=null && p.isOnline()) { + PlayerStructure pd = PlayerStructure.GetPlayerStructure(p); + if (pd.freshBlood) { + pd.freshBlood=false; + freshBloodPlayer=s; + break; + } + } + } + } + } + public void joinMatch(Player p) { if (!players.containsKey(p.getName())) { players.put(p.getName(), new PVPPlayer()); @@ -71,6 +133,8 @@ public class PVP { Player pl = Bukkit.getPlayer(s); if (pl!=null && pl.isValid() && pl.isOnline()) { pl.sendMessage(ChatColor.YELLOW+p.getName()+" has joined the match. Current Participants: "+ChatColor.YELLOW+getParticipants()); + findFreshBloodPlayer(); + announceFreshBloodPlayer(false); } else { //pl.sendMessage(ChatColor.YELLOW+s+ChatColor.GOLD+" has left the PVP Match..."); leaveMatch(s); @@ -81,12 +145,21 @@ public class PVP { } private void leaveMatch(String s) { - TwosideKeeper.ScheduleRemoval(players,s); - for (String ss : players.keySet()) { - Player pl = Bukkit.getPlayer(ss); - if (pl!=null && pl.isValid() && pl.isOnline() && !s.equalsIgnoreCase(ss)) { - pl.sendMessage(ChatColor.YELLOW+ss+" has left the match. Current Participants: "+ChatColor.YELLOW+getParticipants()); + if (players.containsKey(s)) { + TwosideKeeper.ScheduleRemoval(players,s); + Player p = Bukkit.getPlayer(s); + if (p!=null && p.isOnline()) { + p.sendMessage(ChatColor.YELLOW+s+" has left the match."); } + players.remove(s); + Bukkit.getScheduler().runTaskLater(TwosideKeeper.plugin,()->{ + for (String ss : players.keySet()) { + Player pl = Bukkit.getPlayer(ss); + if (pl!=null && pl.isValid() && pl.isOnline() && !s.equalsIgnoreCase(ss)) { + pl.sendMessage(ChatColor.YELLOW+s+" has left the match. Current Participants: "+ChatColor.YELLOW+getParticipants()); + } + } + },2); } } @@ -99,17 +172,21 @@ public class PVP { int count=0; for (String s : players.keySet()) { if (sb.length()==0) { + sb.append((freshBloodPlayer!=null && freshBloodPlayer.equalsIgnoreCase(s)?"*":"")); sb.append(s); } else { if (players.size()==2) { sb.append(" "+(OR?"or":"and")+" "); + sb.append((freshBloodPlayer!=null && freshBloodPlayer.equalsIgnoreCase(s)?"*":"")); sb.append(s); } else { if (count+1==players.size()) { sb.append(", "+(OR?"or":"and")+" "); + sb.append((freshBloodPlayer!=null && freshBloodPlayer.equalsIgnoreCase(s)?"*":"")); sb.append(s); } else { sb.append(", "); + sb.append((freshBloodPlayer!=null && freshBloodPlayer.equalsIgnoreCase(s)?"*":"")); sb.append(s); } } @@ -130,7 +207,8 @@ public class PVP { } }break;*/ case WAITFORPLAYERS:{ - if (timer+200<=TwosideKeeper.getServerTickTime()) { + //if (timer+200<=TwosideKeeper.getServerTickTime()) { + if (everyoneIsReady()) { if (players.size()>=2) { state = CHOICEENGINE.WAITFORROUNDCHOICES; timer=TwosideKeeper.getServerTickTime(); @@ -146,6 +224,7 @@ public class PVP { return false; //Cancelled. } } + //} }break; case WAITFORROUNDCHOICES:{ if (timer+400<=TwosideKeeper.getServerTickTime() || allPlayersPicked()) { @@ -289,7 +368,7 @@ public class PVP { aPlugin.API.discordSendRaw("```"+sb.toString()+"```"); } computeWinner(); - TwosideKeeper.log("Players: "+players, 1); + //TwosideKeeper.log("Players: "+players, 1); announceWinner(); resetTeams(); if (matchTimer!=null) { @@ -311,6 +390,16 @@ public class PVP { return true; } + private boolean everyoneIsReady() { + for (String s : players.keySet()) { + PVPPlayer pp = players.get(s); + if (!pp.isReady) { + return false; + } + } + return true; + } + private void movePlayersOutsideArenaBackIn() { if (currentArena!=null) { for (String s : players.keySet()) { @@ -323,6 +412,30 @@ public class PVP { } } } + } else { + Location anchorpos = null; + for (String s : players.keySet()) { + if (anchorpos==null) { + Player p = Bukkit.getPlayer(s); + if (p!=null && p.isOnline()) { + anchorpos=p.getLocation().clone(); + } + } + if (anchorpos!=null) { + PVPPlayer pp = players.get(s); + Player p = Bukkit.getPlayer(s); + if (p!=null && pp.isAlive) { + if (!anchorpos.getWorld().equals(p.getWorld()) || anchorpos.distanceSquared(p.getLocation())>1024) { + p.teleport(anchorpos.add(Math.random()*32-16,0,Math.random()*32-16)); + Chunk c = anchorpos.getChunk(); + ChunkSnapshot cs = c.getChunkSnapshot(); + int highestY = cs.getHighestBlockYAt(Math.floorMod(anchorpos.getBlockX(),16), Math.floorMod(anchorpos.getBlockZ(),16)); + p.teleport(anchorpos.add(0, highestY-anchorpos.getBlockY()+2, 0)); + p.sendMessage(ChatColor.RED+"You cannot leave the arena!"); + } + } + } + } } } @@ -330,6 +443,8 @@ public class PVP { for (String s : players.keySet()) { Player p = Bukkit.getPlayer(s); if (p!=null && p.getGameMode()==GameMode.SPECTATOR) { + //p.setFlying(true); + //p.setAllowFlight(true); //This is a spectator. Verify if they are watching an alive target. if (p.getSpectatorTarget()!=null && p.getSpectatorTarget() instanceof Player) { @@ -528,6 +643,7 @@ public class PVP { TwosideKeeper.setPlayerMaxHealth(p, p.getHealth()/p.getMaxHealth(), true); p.teleport(pd.locBeforeInstance); pd.locBeforeInstance=null; + pd.lastplayerHitBy=null; GenericFunctions.RevivePlayer(p, p.getMaxHealth()); } }, 5); @@ -541,6 +657,7 @@ public class PVP { PlayerStructure pd = PlayerStructure.GetPlayerStructure(p); TwosideKeeper.setPlayerMaxHealth(p, p.getHealth()/p.getMaxHealth(), true); p.teleport(pd.locBeforeInstance); + pd.lastplayerHitBy=null; pd.locBeforeInstance=null; GenericFunctions.RevivePlayer(p, p.getMaxHealth()); } @@ -584,6 +701,128 @@ public class PVP { } } + private void RewardLoot(PVPOption matchStyle, boolean freshBlood, String player, boolean winner) { + Player p = Bukkit.getPlayer(player); + if (p!=null && p.isOnline()) { + HashMap rewards = new HashMap(); + final ItemStack mysterious_essence = Artifact.createArtifactItem(ArtifactItem.MYSTERIOUS_ESSENCE); + final ItemStack artifact_essence = Artifact.createArtifactItem(ArtifactItem.ARTIFACT_ESSENCE); + final ItemStack artifact_core = Artifact.createArtifactItem(ArtifactItem.ARTIFACT_CORE); + final ItemStack artifact_base = Artifact.createArtifactItem(ArtifactItem.ARTIFACT_BASE); + final ItemStack battle_token = CustomItem.BattleToken(); + double moneymult = 1.0/(winner?1.0:2.0); + switch (matchStyle) { + case ROUNDS3:{ + if (winner) { + addReward(rewards,mysterious_essence,1); + } else { + addReward(rewards,mysterious_essence,0.33); + } + }break; + case ROUNDS5: + case MIN3:{ + if (winner) { + addReward(rewards,mysterious_essence,1); + addReward(rewards,artifact_essence,0.25); + } else { + addReward(rewards,mysterious_essence,0.33); + } + moneymult = 1.2; + }break; + case ROUNDS7: + case MIN5:{ + if (winner) { + addReward(rewards,mysterious_essence,2); + addReward(rewards,artifact_essence,0.5); + addReward(rewards,artifact_core,0.25); + } else { + addReward(rewards,mysterious_essence,0.75); + } + moneymult = 1.4; + }break; + case ROUNDS15: + case MIN10:{ + if (winner) { + addReward(rewards,mysterious_essence,3); + addReward(rewards,artifact_essence,1); + addReward(rewards,artifact_core,0.50); + addReward(rewards,artifact_base,0.25); + } else { + addReward(rewards,mysterious_essence,1); + } + moneymult = 2; + }break; + default:{ + if (winner) { + addReward(rewards,mysterious_essence,1); + } else { + addReward(rewards,mysterious_essence,0.33); + } + TwosideKeeper.log("WARNING! Undefined rewards for PVP Style "+matchStyle.name()+". Giving default rewards.", 1); + } + } + PlayerStructure pd = PlayerStructure.GetPlayerStructure(p); + applyFreshBloodMultiplier(rewards); + if (pd.firstPVPMatch) { + pd.firstPVPMatch=false; + } else { + applyAlreadyPlayedMultiplier(rewards); + } + if (winner) { + addReward(rewards,battle_token,1); + } + List rewardItems = new ArrayList(); + giveRewards(rewards,rewardItems); + if (rewardItems.size()>0) { + GlobalLoot box = GlobalLoot.spawnGlobalLoot(pd.locBeforeInstance, ChatColor.RED+""+ChatColor.BOLD+"Battle Reward Chest"); + box.addNewDropInventory(p.getUniqueId(), rewardItems.toArray(new ItemStack[rewardItems.size()])); + } else { + double moneyEarned = Math.round(((((int)Math.random()*2)+2)*(players.size()+losers.size()))*moneymult); + DecimalFormat df = new DecimalFormat("0.00"); + TwosideKeeperAPI.givePlayerMoney(p, moneyEarned); + p.sendMessage(ChatColor.ITALIC+"You did not earn any loot this round, but you did earn $"+ChatColor.GREEN+df.format(moneyEarned)+ChatColor.RESET+"."); + } + } + } + + private void applyAlreadyPlayedMultiplier(HashMap rewards) { + for (ItemStack i : rewards.keySet()) { + rewards.put(i, rewards.get(i)*0.25); + } + } + + private void giveRewards(HashMap rewards, List rewardItems) { + for (ItemStack i : rewards.keySet()) { + double amt = rewards.get(i); + if (amt>=1) { + ItemStack rewardItem = i.clone(); + rewardItem.setAmount((int)amt); + rewardItems.add(rewardItem); + } + if (Math.random()<=(amt % 1)) { + ItemStack rewardItem = i.clone(); + rewardItem.setAmount(1); + rewardItems.add(rewardItem); + } + } + } + + private void applyFreshBloodMultiplier(HashMap rewards) { + if (freshBloodPlayer!=null) { + for (ItemStack i : rewards.keySet()) { + rewards.put(i, rewards.get(i)*2); + } + } + } + + private void addReward(HashMap rewards, ItemStack reward, double reward_amt) { + if (rewards.containsKey(reward)) { + rewards.put(reward, rewards.get(reward)+reward_amt); + } else { + rewards.put(reward, reward_amt); + } + } + private boolean conditionsToWin() { if (scorematch) { return (team1score>=scorelimit || team2score>=scorelimit) || (players.size()==2 && PlayerHasReachedScoreLimit()); @@ -605,6 +844,12 @@ public class PVP { private void announceWinner() { String firstPlayer = null; determineWinnerByEliminatingLosers(); + for (String s : players.keySet()) { + RewardLoot(style,freshBloodPlayer!=null,s,true); + } + for (String s : losers) { + RewardLoot(style,freshBloodPlayer!=null,s,false); + } TwosideKeeper.log("Players: "+players, 1); for (String s : players.keySet()) { firstPlayer = s; @@ -615,7 +860,7 @@ public class PVP { List winners = PVP.getTeammates(p); List winnernames = new ArrayList(); for (Player pl : winners) { - TwosideKeeper.log("Adding "+pl.getName()+" to winners.", 1); + //TwosideKeeper.log("Adding "+pl.getName()+" to winners.", 1); winnernames.add(pl.getName()); } StringBuilder sb = new StringBuilder(ChatColor.GREEN+"Congratulations to "+ChatColor.YELLOW); @@ -936,7 +1181,11 @@ public class PVP { for (String s : players.keySet()) { PVPPlayer pp = players.get(s); if (pp.team==i) { - teams.add(s); + if (freshBloodPlayer!=null && freshBloodPlayer.equalsIgnoreCase(s)) { + teams.add("*"+s); + } else { + teams.add(s); + } } } return teams; @@ -1138,12 +1387,19 @@ public class PVP { } myself.isAlive=false; p.setGameMode(GameMode.SPECTATOR); + p.setFallDistance(0.0f); p.setSpectatorTarget(Bukkit.getPlayer(killedByPlayer)); p.sendMessage(" Killed by "+ChatColor.RED+killedByPlayer+ChatColor.RESET+"."); Player killerp = Bukkit.getPlayer(pd.lastplayerHitBy); if (killerp!=null) { killerp.sendMessage(" Killed "+ChatColor.GREEN+p.getName()+ChatColor.RESET+"."); } + } else { + if (players.containsKey(p.getName())) { + if (currentArena!=null) { + p.teleport(currentArena.pickRandomLocation()); + } + } } /*if (getPlayersInTeam(1).contains(killer)) { team1score++; @@ -1151,6 +1407,29 @@ public class PVP { team2score++; }*/ } + + public void addReadyChoice(Player p, String string) { + if (string.equalsIgnoreCase("YES")) { + if (players.containsKey(p.getName())) { + PVPPlayer pp = players.get(p.getName()); + if (!pp.isReady) { + pp.isReady=true; + for (String s : players.keySet()) { + PVPPlayer pp2 = players.get(s); + Player p2 = Bukkit.getPlayer(s); + if (p2!=null && p2.isOnline()) { + p2.sendMessage(" "+ChatColor.YELLOW+((freshBloodPlayer!=null && freshBloodPlayer.equalsIgnoreCase(p.getName()))?"*":"")+p.getName()+ChatColor.RESET+" is "+ChatColor.GREEN+"READY"+ChatColor.RESET+"."); + if (!pp2.isReady) { + showReadyChoice(s); + } + } + } + } + } + } else { + leaveMatch(p.getName()); + } + } } class PVPPlayer { @@ -1162,6 +1441,7 @@ class PVPPlayer { int team; boolean isAlive; long respawnTimer; + boolean isReady; PVPPlayer() { score=0; @@ -1172,6 +1452,7 @@ class PVPPlayer { isAlive=true; respawnTimer=0; arenaChoice=-1; + isReady=false; } } @@ -1203,7 +1484,7 @@ enum PVPOption { MIN3(5,ChatColor.WHITE+"3 Min Deathmatch","The player that gets the highest score within 3 minutes wins the duel. "+ChatColor.GREEN+"+1 Point per Kill"+ChatColor.RESET+", "+ChatColor.RED+"-1 Point per Death",20*60*3), MIN5(6,ChatColor.GRAY+"5 Min Deathmatch","The player that gets the highest score within 5 minutes wins the duel. "+ChatColor.GREEN+"+1 Point per Kill"+ChatColor.RESET+", "+ChatColor.RED+"-1 Point per Death",20*60*5), MIN10(7,ChatColor.WHITE+"10 Min Deathmatch","The player that gets the highest score within 10 minutes wins the duel. "+ChatColor.GREEN+"+1 Point per Kill"+ChatColor.RESET+", "+ChatColor.RED+"-1 Point per Death",20*60*10), - OPENWORLD(1,ChatColor.WHITE+"Open World","Fight in the current location you are located at."+ChatColor.RED+"\n NOTE: "+ChatColor.WHITE+"You may not wander more than 32 blocks away from your starting battle location."), + OPENWORLD(1,ChatColor.WHITE+"Open World","Fight in the current location you are located at."+ChatColor.RED+"\n NOTE: "+ChatColor.WHITE+"You may not wander more than 16 blocks away from your starting battle location."), SMALLBATTLEFIELD(2,ChatColor.GRAY+"Small Battlefield","Fight in a small, instanced battlefield"), AQUATICFORT(3,ChatColor.WHITE+"Aquatic Fort","Fight in a small, decorated fort with a moat surrounding the area."), NETHERFORTRESS(4,ChatColor.GRAY+"Nether Fortress","Fight in a medium-sized fortress sitting upon the fiery flames of hell."), diff --git a/src/sig/plugin/TwosideKeeper/PVPArena.java b/src/sig/plugin/TwosideKeeper/PVPArena.java index 021b30f..a6cafd1 100644 --- a/src/sig/plugin/TwosideKeeper/PVPArena.java +++ b/src/sig/plugin/TwosideKeeper/PVPArena.java @@ -1,5 +1,8 @@ package sig.plugin.TwosideKeeper; +import java.util.ArrayList; +import java.util.List; + import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.util.Vector; @@ -14,12 +17,14 @@ public class PVPArena { Location endCorner; String name; String desc; + List safelocs; public PVPArena(Location startCorner, Location endCorner, String arenaName, String desc) { this.startCorner = new Location(startCorner.getWorld(),Math.min(startCorner.getBlockX(), endCorner.getBlockX()),Math.min(startCorner.getBlockY(), endCorner.getBlockY()),Math.min(startCorner.getBlockZ(), endCorner.getBlockZ())); this.endCorner = new Location(startCorner.getWorld(),Math.max(startCorner.getBlockX(), endCorner.getBlockX()),Math.max(startCorner.getBlockY(), endCorner.getBlockY()),Math.max(startCorner.getBlockZ(), endCorner.getBlockZ())); this.name=arenaName; this.desc=desc; + this.safelocs = new ArrayList(); } public Location getStartCorner() { @@ -42,18 +47,18 @@ public class PVPArena { public Location pickRandomLocation() { //Pick a random point. - int tries=50; //Number of tries before we give up and drop them in. + int tries=400; //Number of tries before we give up and drop them in. int randomx = ((int)(Math.random()*(endCorner.getBlockX()-startCorner.getBlockX()))) + 1; int randomz = ((int)(Math.random()*(endCorner.getBlockZ()-startCorner.getBlockZ()))) + 1; - int y = endCorner.getBlockY()-startCorner.getBlockY()-1; + int y = endCorner.getBlockY()-startCorner.getBlockY()-2; Location finalloc = null; while (tries>0) { //Find a safe Y Location int ytries=50; while (ytries>0) { - Block testBlock = startCorner.clone().add(randomx,y-1,randomz).getBlock(); - if (testBlock.isLiquid() || !testBlock.getType().isSolid()) { + Block testBlock = startCorner.clone().add(randomx+0.5,y-1,randomz+0.5).getBlock(); + if (testBlock.isLiquid() || !testBlock.getType().isOccluding()) { y--; ytries--; } else { @@ -61,11 +66,17 @@ public class PVPArena { } } finalloc = new Location(startCorner.getWorld(), - startCorner.getBlockX()+randomx, + startCorner.getBlockX()+randomx+0.5, startCorner.getBlockY()+y, - startCorner.getBlockZ()+randomz); + startCorner.getBlockZ()+randomz+0.5); if (!finalloc.getBlock().isLiquid() && insideBounds(finalloc)) { + /*TwosideKeeper.log("Final Block is "+finalloc.getBlock(), 1); + TwosideKeeper.log("Final Block Above is "+finalloc.getBlock().getRelative(0, 1, 0), 1); + TwosideKeeper.log("Final Block Below is "+finalloc.getBlock().getRelative(0, -1, 0), 1);*/ + if (safelocs.size()<20) { + safelocs.add(finalloc.clone()); + } return finalloc.clone(); } else { tries--; @@ -74,7 +85,11 @@ public class PVPArena { y = endCorner.getBlockX()-startCorner.getBlockX()-1; } } - TwosideKeeper.log("WARNING! Could not find a safe random location. Dropping them in with what we got...", 1); + if (safelocs.size()>0) { + finalloc = safelocs.get((int)(Math.random()*safelocs.size())); + } else { + TwosideKeeper.log("WARNING! Could not find a safe random location. Dropping them in with what we got...", 1); + } return finalloc.clone(); } @@ -88,4 +103,46 @@ public class PVPArena { tc.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,new ComponentBuilder(desc).create())); return tc; } + + public String getDataString() { + StringBuilder sb = new StringBuilder(""); + sb.append(startCorner.getWorld().getName()); + sb.append(","); + sb.append(startCorner.getX()); + sb.append(","); + sb.append(startCorner.getY()); + sb.append(","); + sb.append(startCorner.getZ()); + sb.append(","); + sb.append(endCorner.getWorld().getName()); + sb.append(","); + sb.append(endCorner.getX()); + sb.append(","); + sb.append(endCorner.getY()); + sb.append(","); + sb.append(endCorner.getZ()); + sb.append(","); + sb.append(name); + sb.append(","); + sb.append(desc); + return sb.toString(); + } + + public String toString() { + StringBuilder sb = new StringBuilder(""); + sb.append("PVPArena{"); + sb.append("name="); + sb.append(name); + sb.append(","); + sb.append("desc="); + sb.append(desc); + sb.append(","); + sb.append("startCorner="); + sb.append(startCorner); + sb.append(","); + sb.append("endCorner="); + sb.append(endCorner); + sb.append("}"); + return sb.toString(); + } } diff --git a/src/sig/plugin/TwosideKeeper/PlayerStructure.java b/src/sig/plugin/TwosideKeeper/PlayerStructure.java index 99ef5e3..6cc4381 100644 --- a/src/sig/plugin/TwosideKeeper/PlayerStructure.java +++ b/src/sig/plugin/TwosideKeeper/PlayerStructure.java @@ -176,6 +176,8 @@ public class PlayerStructure { public boolean temporaryPVP=false; //Used for /stats PVP emulation. public Location arenaLocRef=null; public Location playerLocRef=null; + public boolean freshBlood=true; + public boolean firstPVPMatch=true; /*State 1 * 1: Best of 3 Rounds * 2: Best of 5 Rounds @@ -525,6 +527,8 @@ public class PlayerStructure { workable.set("averageAdjustmentsMadeCount", averageAdjustmentsMadeCount); workable.set("averageAdjustmentsMade", averageAdjustmentsMade); workable.set("tooConsistentAdjustments", tooConsistentAdjustments); + workable.set("freshBlood", freshBlood); + workable.set("firstPVPMatch", firstPVPMatch); int buffcounter=0; for (String key : buffs.keySet()) { Buff b = buffs.get(key); @@ -641,6 +645,8 @@ public class PlayerStructure { workable.addDefault("averageAdjustmentsMadeCount",averageAdjustmentsMadeCount); workable.addDefault("averageAdjustmentsMade",averageAdjustmentsMade); workable.addDefault("tooConsistentAdjustments",tooConsistentAdjustments); + workable.addDefault("freshBlood",freshBlood); + workable.addDefault("firstPVPMatch",firstPVPMatch); workable.options().copyDefaults(); @@ -715,6 +721,8 @@ public class PlayerStructure { this.averageAdjustmentsMade = workable.getDouble("averageAdjustmentsMade"); this.tooConsistentAdjustments = workable.getBoolean("tooConsistentAdjustments"); String tempworld = workable.getString("restartloc_world"); + this.freshBlood = workable.getBoolean("freshBlood"); + this.firstPVPMatch = workable.getBoolean("firstPVPMatch"); if (!workable.getString("instanceloc_world").equalsIgnoreCase("null")) { locBeforeInstance = new Location( Bukkit.getWorld(workable.getString("instanceloc_world")), diff --git a/src/sig/plugin/TwosideKeeper/TwosideKeeper.java b/src/sig/plugin/TwosideKeeper/TwosideKeeper.java index 6561946..c00b785 100644 --- a/src/sig/plugin/TwosideKeeper/TwosideKeeper.java +++ b/src/sig/plugin/TwosideKeeper/TwosideKeeper.java @@ -1221,8 +1221,6 @@ public class TwosideKeeper extends JavaPlugin implements Listener { habitat_data = new Habitation(); habitat_data.loadLocationHashesFromConfig(); - PVP.arenas = new ArrayList(); - LastClearStructureTime = getServerTickTime(); TwosideRecyclingCenter = new RecyclingCenter(); @@ -1668,6 +1666,13 @@ public class TwosideKeeper extends JavaPlugin implements Listener { session.addChoice(p,args[1]); } }break; + case "_READY_":{ + Player p = (Player)sender; + PVP session = PVP.getMatch(p); + if (session!=null) { + session.addReadyChoice(p,args[1]); + } + }break; } } return true; @@ -1685,6 +1690,39 @@ public class TwosideKeeper extends JavaPlugin implements Listener { return false; } else + if (cmd.getName().equalsIgnoreCase("fb")) { + if (args.length==1) { + Player p = Bukkit.getPlayer(args[0]); + if (p!=null && p.isOnline()) { + PlayerStructure pd = PlayerStructure.GetPlayerStructure(p); + if (pd.freshBlood) { + sender.sendMessage("Fresh Blood is currently "+ChatColor.YELLOW+"ACTIVE"+ChatColor.RESET+" on Player "+ChatColor.YELLOW+p.getName()+ChatColor.RESET+"."); + } else { + sender.sendMessage("Fresh Blood is currently "+ChatColor.RED+"INACTIVE"+ChatColor.RESET+" on Player "+ChatColor.YELLOW+p.getName()+ChatColor.RESET+"."); + } + } else { + sender.sendMessage("Could not find player "+ChatColor.YELLOW+args[0]+ChatColor.RESET+"!"); + } + } else { + StringBuilder sb = new StringBuilder(ChatColor.RED+"Online Fresh Blood Players:"); + boolean freshblood=false; + for (Player p : Bukkit.getOnlinePlayers()) { + PlayerStructure pd = PlayerStructure.GetPlayerStructure(p); + if (pd.freshBlood) { + sb.append(ChatColor.RESET+"\n - "+ChatColor.GREEN+"*"+p.getName()); + freshblood=true; + } + } + if (!freshblood) { + sender.sendMessage("No Fresh Blood Players online!"); + } else { + sender.sendMessage(sb.toString()); + } + return true; + } + return false; + } + else if (cmd.getName().equalsIgnoreCase("stats")) { if (args.length>=1) { if (args.length>=2) { @@ -2514,8 +2552,23 @@ public class TwosideKeeper extends JavaPlugin implements Listener { p.sendMessage("/fix ARTIFACTTIER "); } }break; + case "REMOVEARENA":{ + if (args.length==2) { + List removals = new ArrayList(); + for (PVPArena arena : PVP.arenas) { + if (ChatColor.stripColor(arena.getArenaName()).equalsIgnoreCase(ChatColor.stripColor(args[1]))) { + removals.add(arena); + p.sendMessage("Successfully removed Arena "+ChatColor.YELLOW+arena.getArenaName()+ChatColor.RESET+"."); + break; + } + } + PVP.arenas.removeAll(removals); + //p.sendMessage("Remaining arenas: "+PVP.arenas); + } + }break; case "DEFINEARENA":{ PlayerStructure pd = PlayerStructure.GetPlayerStructure(p); + //TwosideKeeper.log("Args are "+Arrays.toString(args), 3); if (pd.arenaLocRef==null) { Set types = null; pd.arenaLocRef = p.getTargetBlock(types, 100).getLocation().clone(); @@ -2525,7 +2578,7 @@ public class TwosideKeeper extends JavaPlugin implements Listener { if (args.length==3) { Set types = null; PVPArena arena = new PVPArena(pd.arenaLocRef,p.getTargetBlock(types, 100).getLocation().clone(), - args[1],args[2]); + ChatColor.translateAlternateColorCodes('§', args[1]),ChatColor.translateAlternateColorCodes('§', args[1])); PVP.arenas.add(arena); p.sendMessage(ChatColor.LIGHT_PURPLE+"Set Ref Location of Arena corner 2 to "+p.getTargetBlock(types, 100).getLocation().clone()); p.sendMessage(ChatColor.YELLOW+"Successfully created Arena "+arena.getArenaName()+" with Description "+arena.getDescription()); @@ -3375,7 +3428,7 @@ public class TwosideKeeper extends JavaPlugin implements Listener { @EventHandler(priority=EventPriority.LOW,ignoreCancelled = true) public void onPlayerFlight(PlayerToggleFlightEvent ev) { Player p = ev.getPlayer(); - if (ev.isFlying() && PVP.isPvPing(p)) { + if (ev.isFlying() && PVP.isPvPing(p) && p.getGameMode()==GameMode.SURVIVAL) { ev.setCancelled(true); } } @@ -5330,7 +5383,8 @@ public class TwosideKeeper extends JavaPlugin implements Listener { ev.setCancelled(true); return; } - if (CustomItem.isDailyToken(ev.getItemInHand())) { + if (CustomItem.isDailyToken(ev.getItemInHand()) || + CustomItem.isBattleToken(ev.getItemInHand())) { ev.setCancelled(true); return; } @@ -10824,6 +10878,11 @@ public class TwosideKeeper extends JavaPlugin implements Listener { getConfig().set("ELITE_LOCATION_X", ELITE_LOCATION.getBlockX()); getConfig().set("ELITE_LOCATION_Z", ELITE_LOCATION.getBlockZ()); } + int count=0; + for (PVPArena arenas : PVP.arenas) { + getConfig().set("ARENA"+(count++)+"_data", arenas.getDataString()); + } + getConfig().set("ARENA_COUNT", PVP.arenas.size()); //getConfig().set("MOTD", MOTD); //It makes no sense to save the MOTD as it will never be modified in-game. saveConfig(); @@ -10895,6 +10954,7 @@ public class TwosideKeeper extends JavaPlugin implements Listener { getConfig().addDefault("LAST_SPECIAL_SPAWN", LAST_SPECIAL_SPAWN); getConfig().addDefault("LAST_WEEKLY_RESET", LAST_WEEKLY_RESET); getConfig().addDefault("ROOM_ID", ROOM_ID); + getConfig().addDefault("ARENA_COUNT", 0); getConfig().options().copyDefaults(true); saveConfig(); SERVERTICK = getConfig().getLong("SERVERTICK"); @@ -10949,6 +11009,24 @@ public class TwosideKeeper extends JavaPlugin implements Listener { } },20); } + PVP.arenas = new ArrayList(); + for (int i=0;i{ if (ent!=null && Buff.hasBuff(ent, "Poison")) { CustomDamage.ApplyDamage(Buff.getBuff(ent, "Poison").getAmplifier(), null, ent, null, "POISON", CustomDamage.IGNOREDODGE|CustomDamage.TRUEDMG|CustomDamage.IGNORE_DAMAGE_TICK); - pd.lastPoisonTick=TwosideKeeper.getServerTickTime(); + pd.lastPoisonTick=TwosideKeeper.getServerTickTime()+(PVP.isPvPing(p)?(int)getPoisonTickDelay(ent):0); } }, (int)(Math.random()*10)); } @@ -536,7 +552,7 @@ final public class runServerHeartbeat implements Runnable { Bukkit.getScheduler().runTaskLater(TwosideKeeper.plugin, ()->{ if (ent!=null && Buff.hasBuff(ent, "SHRAPNEL")) { CustomDamage.ApplyDamage((Buff.getBuff(ent, "SHRAPNEL").getAmplifier()*2)*(1d-CustomDamage.getFireResistance(ent)), null, ent, null, "Shrapnel", CustomDamage.IGNOREDODGE|CustomDamage.TRUEDMG|CustomDamage.IGNORE_DAMAGE_TICK); - pd.lastShrapnelTick=TwosideKeeper.getServerTickTime(); + pd.lastShrapnelTick=TwosideKeeper.getServerTickTime()+(PVP.isPvPing(p)?20:0); SoundUtils.playLocalSound((Player)ent, Sound.ENTITY_GENERIC_EXTINGUISH_FIRE, 1.0f, 1.0f); ent.getWorld().spawnParticle(Particle.LAVA, ent.getEyeLocation(), CustomDamage.GetHeartAmount(Buff.getBuff(ent, "SHRAPNEL").getAmplifier())*5); } @@ -546,7 +562,7 @@ final public class runServerHeartbeat implements Runnable { Bukkit.getScheduler().runTaskLater(TwosideKeeper.plugin, ()->{ if (ent!=null && Buff.hasBuff(ent, "BLEEDING")) { CustomDamage.ApplyDamage((Buff.getBuff(ent, "BLEEDING").getAmplifier()), null, ent, null, "Bleeding", CustomDamage.IGNOREDODGE|CustomDamage.TRUEDMG|CustomDamage.IGNORE_DAMAGE_TICK); - pd.lastBleedingTick=TwosideKeeper.getServerTickTime(); + pd.lastBleedingTick=TwosideKeeper.getServerTickTime()+(PVP.isPvPing(p)?20:0); //SoundUtils.playLocalSound((Player)ent, Sound.ENTITY_GENERIC_EXTINGUISH_FIRE, 1.0f, 1.0f); //ent.getWorld().spawnParticle(Particle.LAVA, ent.getEyeLocation(), CustomDamage.GetHeartAmount(Buff.getBuff(ent, "SHRAPNEL").getAmplifier())*5); Bukkit.getScheduler().runTaskLater(TwosideKeeper.plugin, ()->{ @@ -561,7 +577,7 @@ final public class runServerHeartbeat implements Runnable { Bukkit.getScheduler().runTaskLater(TwosideKeeper.plugin, ()->{ if (ent!=null && Buff.hasBuff(ent, "INFECTION")) { CustomDamage.ApplyDamage(Buff.getBuff(ent, "INFECTION").getAmplifier(), null, ent, null, "Infection", CustomDamage.IGNOREDODGE|CustomDamage.TRUEDMG|CustomDamage.IGNORE_DAMAGE_TICK); - pd.lastInfectionTick=TwosideKeeper.getServerTickTime(); + pd.lastInfectionTick=TwosideKeeper.getServerTickTime()+(PVP.isPvPing(p)?20:0); infectNearbyPlayers(ent,pd.buffs); } }, (int)(Math.random()*10)); @@ -580,7 +596,7 @@ final public class runServerHeartbeat implements Runnable { if (ent!=null && Buff.hasBuff(ent, "BURN")) { CustomDamage.ApplyDamage(Buff.getBuff(ent, "BURN").getAmplifier(), null, ent, null, "Burn", CustomDamage.IGNOREDODGE|CustomDamage.TRUEDMG|CustomDamage.IGNORE_DAMAGE_TICK); SoundUtils.playLocalSound((Player)ent, Sound.ENTITY_GENERIC_EXTINGUISH_FIRE, 1.0f, 1.0f); - pd.lastBurnTick=TwosideKeeper.getServerTickTime(); + pd.lastBurnTick=TwosideKeeper.getServerTickTime()+(PVP.isPvPing(p)?20:0); } }, (int)(Math.random()*10)); }