package in.twizmwaz.cardinal.module.modules.hill; import in.twizmwaz.cardinal.GameHandler; import in.twizmwaz.cardinal.event.PlayerChangeTeamEvent; import in.twizmwaz.cardinal.event.objective.ObjectiveCompleteEvent; import in.twizmwaz.cardinal.event.objective.ObjectiveProximityEvent; import in.twizmwaz.cardinal.event.objective.ObjectiveUncompleteEvent; import in.twizmwaz.cardinal.module.GameObjective; import in.twizmwaz.cardinal.module.TaskedModule; import in.twizmwaz.cardinal.module.modules.filter.FilterModule; import in.twizmwaz.cardinal.module.modules.filter.FilterState; import in.twizmwaz.cardinal.module.modules.matchTimer.MatchTimer; import in.twizmwaz.cardinal.module.modules.observers.ObserverModule; import in.twizmwaz.cardinal.module.modules.proximity.GameObjectiveProximityHandler; import in.twizmwaz.cardinal.module.modules.regions.RegionModule; import in.twizmwaz.cardinal.module.modules.score.ScoreModule; import in.twizmwaz.cardinal.module.modules.scoreboard.GameObjectiveScoreboardHandler; import in.twizmwaz.cardinal.module.modules.team.TeamModule; import in.twizmwaz.cardinal.util.Fireworks; import in.twizmwaz.cardinal.util.MiscUtil; import in.twizmwaz.cardinal.util.Teams; import org.apache.commons.lang3.tuple.Pair; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.util.BlockVector; import org.bukkit.util.Vector; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; public class HillObjective implements TaskedModule, GameObjective { private String name, id; private int captureTime, points, pointsGrowth; private double timeMultiplier; private CaptureRule captureRule; private boolean showProgress, neutralState, incremental, permanent, show, required; private FilterModule visualMaterials, captureFilter, playerFilter; private Set<Player> capturingPlayers; private TeamModule team, capturingTeam; private int controlTime; private GameObjectiveScoreboardHandler scoreboardHandler; private GameObjectiveProximityHandler proximityHandler; private int seconds = 1; private RegionModule capture, progress, captured; private RegionSave oldProgress, oldCaptured; private long lastUpdate = 0; protected HillObjective(final TeamModule team, final String name, final String id, final double captureTime, final int points, final int pointsGrowth, final CaptureRule captureRule, final double timeMultiplier, final boolean showProgress, final boolean neutralState, final boolean incremental, final boolean permanent, final boolean show, final boolean required, final RegionModule capture, final RegionModule progress, final RegionModule captured, final FilterModule visualMaterials, final FilterModule captureFilter, final FilterModule playerFilter) { this.team = team; this.name = name; this.id = id; this.captureTime = (int) Math.round(captureTime * 1000); this.points = points; this.pointsGrowth = pointsGrowth; this.captureRule = captureRule; this.timeMultiplier = timeMultiplier; this.showProgress = showProgress; this.neutralState = neutralState; this.incremental = incremental; this.permanent = permanent; this.show = show; this.required = required; this.capture = capture; this.progress = progress; this.oldProgress = progress == null ? null : new RegionSave(progress); this.captured = captured; this.oldCaptured = captured == null ? null : new RegionSave(captured); this.visualMaterials = visualMaterials; this.captureFilter = captureFilter; this.playerFilter = playerFilter; this.capturingTeam = null; this.controlTime = 0; scoreboardHandler = new GameObjectiveScoreboardHandler(this); this.capturingPlayers = new HashSet<>(); renderBlocks(); renderCaptured(); } @EventHandler public void onPlayerMove(PlayerMoveEvent event) { if (ObserverModule.testObserverOrDead(event.getPlayer())) return; if (capture.contains(event.getTo()) && !capturingPlayers.contains(event.getPlayer())) capturingPlayers.add(event.getPlayer()); if (!capture.contains(event.getTo()) && capturingPlayers.contains(event.getPlayer())) capturingPlayers.remove(event.getPlayer()); } @EventHandler public void onPlayerDeath(PlayerDeathEvent event) { if (capturingPlayers.contains(event.getEntity())) capturingPlayers.remove(event.getEntity()); } @EventHandler public void onPlayerLeave(PlayerQuitEvent event) { if (capturingPlayers.contains(event.getPlayer())) capturingPlayers.remove(event.getPlayer()); } @EventHandler public void onPlayerLeave(PlayerKickEvent event) { if (capturingPlayers.contains(event.getPlayer())) capturingPlayers.remove(event.getPlayer()); } @EventHandler public void onPlayerChangeTeam(PlayerChangeTeamEvent event) { if (capturingPlayers.contains(event.getPlayer())) capturingPlayers.remove(event.getPlayer()); } @Override public TeamModule getTeam() { return this.team; } @Override public String getName() { return this.name; } @Override public String getId() { return this.id; } @Override public boolean isTouched() { return this.controlTime != 0; } @Override public boolean isComplete() { return team != null && controlTime == 0; } @Override public boolean showOnScoreboard() { return show; } @Override public boolean isRequired() { return required; } @Override public void unload() { HandlerList.unregisterAll(this); capturingPlayers.clear(); } @Override public GameObjectiveScoreboardHandler getScoreboardHandler() { return scoreboardHandler; } @Override public GameObjectiveProximityHandler getProximityHandler(TeamModule team) { return null; } public int getPointsGrowth() { return pointsGrowth; } public int getPoints() { return points; } public int getCaptureTime() { return captureTime; } public boolean showProgress() { return showProgress; } public TeamModule getCapturingTeam() { return capturingTeam; } public int getPercent() { return Math.min(100, Math.max(0, (controlTime * 100) / captureTime)); } @Override public void run() { if (GameHandler.getGameHandler().getMatch().isRunning()) { if (lastUpdate == 0) lastUpdate = System.currentTimeMillis(); int diff = (int)(System.currentTimeMillis() - lastUpdate); if (diff < 100) return; lastUpdate = System.currentTimeMillis(); if (pointsGrowth != 0) { int matchSeconds = (int)MatchTimer.getTimeInSeconds(); if (seconds != matchSeconds && matchSeconds % pointsGrowth == 0) { seconds = matchSeconds; points *= 2; } } if (team != null) { if (ScoreModule.matchHasScoring()) { for (ScoreModule score : GameHandler.getGameHandler().getMatch().getModules().getModules(ScoreModule.class)) { if (score.getTeam() == team) score.addScore((double)points * diff / 1000); } } } tick(diff); } } public void tick(int time) { if (capturingPlayers.size() == 0) { if (!incremental && controlTime != 0) update(null, time); return; } Map<TeamModule, Integer> playerCounts = new HashMap<>(); for (TeamModule team : Teams.getTeams()) { if (team.isObserver()) continue; playerCounts.put(team, 0); } TeamModule team1 = null, team2 = null; int allowedPlayers = 0; for(Player player : capturingPlayers) { if (!playerFilter.evaluate(player).equals(FilterState.ALLOW)) continue; allowedPlayers++; TeamModule team = Teams.getTeamByPlayer(player).get(); int playerCount = playerCounts.get(team) + 1; playerCounts.put(team, playerCount); if(team != team1) { if(team1 == null || playerCount > playerCounts.get(team1)) { team2 = team1; team1 = team; } else if(team != team2 && (team2 == null || playerCount > playerCounts.get(team2))) { team2 = team; } } } int team1Players = team1 == null ? 0 : playerCounts.get(team1); int otherPlayers = allowedPlayers - team1Players; if (captureRule.equals(CaptureRule.EXCLUSIVE) && otherPlayers > 0) team1Players = 0; if (captureRule.equals(CaptureRule.MAJORITY)) team1Players -= otherPlayers; if (captureRule.equals(CaptureRule.LEAD) && team2 != null) team1Players -= playerCounts.get(team2); if(team1Players > 0) { time += team1Players * timeMultiplier * time; update(team1, time); } else if (!incremental && controlTime != 0) { update(null, time); } } private void update(TeamModule team, int time) { TeamModule oldOwningTeam = this.team; progress(team, time); Bukkit.getServer().getPluginManager().callEvent(new ObjectiveProximityEvent(this, null, 0, 0)); renderBlocks(); if(oldOwningTeam != this.team) { if (this.team != null) { Bukkit.getServer().getPluginManager().callEvent(new ObjectiveCompleteEvent(this, null)); } else { Bukkit.getServer().getPluginManager().callEvent(new ObjectiveUncompleteEvent(this, oldOwningTeam)); } renderCaptured(); } } private void renderBlocks() { if (progress == null) return; byte color1 = capturingTeam != null ? MiscUtil.convertChatColorToDyeColor(capturingTeam.getColor()).getWoolData() : -1; byte color2 = team != null ? MiscUtil.convertChatColorToDyeColor(team.getColor()).getWoolData() : -1; Vector center = progress.getCenterBlock().getVector(); double x = center.getX(); double z = center.getZ(); double percent = Math.toRadians(getPercent() * 3.6); for(Block block : progress.getBlocks()) { if (!visualMaterials.evaluate(block).equals(FilterState.ALLOW)) continue; double dx = block.getX() - x; double dz = block.getZ() - z; double angle = Math.atan2(dz, dx); if(angle < 0) angle += 2 * Math.PI; byte color = angle < percent ? color1 : color2; if (color == -1) { Pair<Material,Byte> oldBlock = oldProgress.getBlockAt(new BlockVector(block.getLocation().position())); if (oldBlock.getLeft().equals(block.getType())) color = oldBlock.getRight(); } if (color != -1) block.setData(color); } } private void renderCaptured() { if (captured == null) return; for(Block block : captured.getBlocks()) { if (!visualMaterials.evaluate(block).equals(FilterState.ALLOW)) continue; byte color = team != null ? MiscUtil.convertChatColorToDyeColor(team.getColor()).getWoolData() : -1; if (color == -1) { Pair<Material,Byte> oldBlock = oldCaptured.getBlockAt(new BlockVector(block.getLocation().position())); if (oldBlock.getLeft().equals(block.getType())) color = oldBlock.getRight(); } if (color != -1) block.setData(color); } } private void progress(TeamModule team, int time) { if((permanent && this.team != null) || time <= 0) return; if(this.team != null && neutralState) { if(team == this.team) { if(incremental && controlTime > time) { controlTime = controlTime - time; return; } controlTime = 0; capturingTeam = null; } else if(team != null) { controlTime += time; if(controlTime >= captureTime) { time = controlTime - captureTime; controlTime = 0; this.team = null; progress(team, time); } } else if(!incremental) { controlTime = 0; } } else if (capturingTeam != null) { if(team == capturingTeam) { controlTime = controlTime + time; if(controlTime >= captureTime) { controlTime = 0; this.team = capturingTeam; capturingTeam = null; } } else if(team != null) { if(incremental && controlTime > time) { controlTime = controlTime - time; return; } else if (incremental) time -= controlTime; controlTime = 0; capturingTeam = null; progress(team, time); } else if(!incremental) { controlTime = 0; capturingTeam = null; } } else if(team != null && team != this.team && captureFilter.evaluate(team).equals(FilterState.ALLOW)) { capturingTeam = team; progress(team, time); } } @EventHandler public void onHillCapture(ObjectiveCompleteEvent event) { if (event.getObjective().equals(this) && this.team != null && showOnScoreboard()) { Fireworks.spawnFireworks(capture.getCenterBlock().getAlignedVector(), (capture.getMax().minus(capture.getMin()).length()) * 0.55 + 1, 6, MiscUtil.convertChatColorToColor(team.getColor()), 1); } } }