From 1db30e3c6b96b769d2604ac6f44f952bc84dcbfa Mon Sep 17 00:00:00 2001
From: FatBoy-DOTC <justin.chucksinsulating@gmail.com>
Date: Fri, 23 Feb 2024 20:36:19 -0600
Subject: [PATCH] bane mechanic for zerg measures

---
 src/engine/gameManager/SimulationManager.java |   2 +-
 src/engine/gameManager/ZergManager.java       |  37 +++-
 src/engine/objects/Bane.java                  |  12 +-
 src/engine/objects/City.java                  | 200 ++++++++++++------
 src/engine/objects/Mine.java                  |   6 +-
 5 files changed, 175 insertions(+), 82 deletions(-)

diff --git a/src/engine/gameManager/SimulationManager.java b/src/engine/gameManager/SimulationManager.java
index 6a7a6773..8e1c5017 100644
--- a/src/engine/gameManager/SimulationManager.java
+++ b/src/engine/gameManager/SimulationManager.java
@@ -239,7 +239,7 @@ public enum SimulationManager {
         for (AbstractGameObject mineObject : mineList) {
             mine = (Mine) mineObject;
             if(mine.isActive)
-                mine.onEnter();
+                mine.onEnterZerg();
         }
 
         _minePulseTime = System.currentTimeMillis() + CITY_PULSE;
diff --git a/src/engine/gameManager/ZergManager.java b/src/engine/gameManager/ZergManager.java
index c1729d93..855b7962 100644
--- a/src/engine/gameManager/ZergManager.java
+++ b/src/engine/gameManager/ZergManager.java
@@ -1,11 +1,15 @@
 package engine.gameManager;
 
+import engine.objects.Bane;
+import engine.objects.Guild;
+
 public class ZergManager {
     public static float getMultiplier5Man(int count){
         float multiplier = 1.0f;
         switch(count){
             case 1:
             case 2:
+            case 5:
                 multiplier += 0.0f;
                 break;
             case 3:
@@ -14,9 +18,6 @@ public class ZergManager {
             case 4:
                 multiplier += 0.2f;
                 break;
-            case 5:
-                multiplier += 0.0f;
-                break;
             case 6:
                 multiplier -= 0.2f;
                 break;
@@ -163,4 +164,34 @@ public class ZergManager {
         }
         return multiplier;
     }
+
+    public static int getBaneCapSize(Bane bane){
+        Guild defender = bane.getCity().getGuild();
+        int treesInNation = defender.getNation().getSubGuildList().size() + 1;
+        int capSize;
+        switch(treesInNation){
+            case 1:
+            case 2:
+            case 3:
+            case 4:
+            case 5:
+            case 6:
+                capSize = 20;
+                break;
+            case 7:
+            case 8:
+            case 9:
+            case 10:
+                capSize = 30;
+                break;
+            case 11:
+            case 12:
+            case 13:
+            case 14:
+                capSize = 40;
+                break;
+            default: capSize = 9999999;
+        }
+        return capSize;
+    }
 }
diff --git a/src/engine/objects/Bane.java b/src/engine/objects/Bane.java
index 5b98aaa4..0d1d8051 100644
--- a/src/engine/objects/Bane.java
+++ b/src/engine/objects/Bane.java
@@ -17,10 +17,7 @@ import engine.InterestManagement.HeightMap;
 import engine.InterestManagement.WorldGrid;
 import engine.db.archive.BaneRecord;
 import engine.db.archive.DataWarehouse;
-import engine.gameManager.BuildingManager;
-import engine.gameManager.ChatManager;
-import engine.gameManager.DbManager;
-import engine.gameManager.ZoneManager;
+import engine.gameManager.*;
 import engine.job.JobScheduler;
 import engine.jobs.ActivateBaneJob;
 import engine.jobs.BaneDefaultTimeJob;
@@ -52,6 +49,8 @@ public final class Bane {
     // Internal cache for banes
     private ActivateBaneJob activateBaneJob;
 
+    public int capSize;
+
     /**
      * ResultSet Constructor
      */
@@ -106,6 +105,8 @@ public final class Bane {
 
         if (this.liveDate == null)
             setDefaultTime();
+
+        this.capSize = ZergManager.getBaneCapSize(this);
     }
 
     public static boolean summonBanestone(PlayerCharacter player, ClientConnection origin, int rank) {
@@ -266,6 +267,7 @@ public final class Bane {
         BaneRecord baneRecord = BaneRecord.borrow(bane, Enum.RecordEventType.PENDING);
         DataWarehouse.pushToWarehouse(baneRecord);
 
+        bane.capSize = ZergManager.getBaneCapSize(bane);
         return true;
     }
 
@@ -341,7 +343,7 @@ public final class Bane {
         }
 
         newBane = DbManager.BaneQueries.LOAD_BANE(city.getObjectUUID());
-
+        newBane.capSize = ZergManager.getBaneCapSize(newBane);
         return newBane;
     }
 
diff --git a/src/engine/objects/City.java b/src/engine/objects/City.java
index 765d2b37..07ac2636 100644
--- a/src/engine/objects/City.java
+++ b/src/engine/objects/City.java
@@ -32,6 +32,7 @@ import engine.server.MBServerStatics;
 import engine.server.world.WorldServer;
 import engine.workthreads.DestroyCityThread;
 import engine.workthreads.TransferCityThread;
+import org.joda.time.DateTime;
 import org.pmw.tinylog.Logger;
 
 import java.sql.ResultSet;
@@ -39,6 +40,7 @@ import java.sql.SQLException;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.concurrent.ConcurrentHashMap;
@@ -88,6 +90,9 @@ public class City extends AbstractWorldObject {
     private boolean reverseKOS = false;
     private String hash;
 
+    public final HashMap<Integer,Long> _recentMemory = new HashMap<>();
+    HashMap<Guild,ArrayList<Integer>> dividedPlayers;
+    public Integer totalPlayers;
     /**
      * ResultSet Constructor
      */
@@ -980,23 +985,14 @@ public class City extends AbstractWorldObject {
 
     public void onEnter() {
 
-        HashSet<AbstractWorldObject> currentPlayers;
-        HashSet<Integer> currentMemory;
-        PlayerCharacter player;
-
-        // Gather current list of players within the zone bounds
+        this.onEnterZerg();
 
-        currentPlayers = WorldGrid.getObjectsInRangePartial(this.location, CityBoundsType.ZONE.extents * 2, MBServerStatics.MASK_PLAYER);
-        currentMemory = new HashSet<>();
+        for (Integer id : this._playerMemory) {
 
-        for (AbstractWorldObject playerObject : currentPlayers) {
-
-            if (playerObject == null)
+            PlayerCharacter player = PlayerCharacter.getFromCache(id);
+            if (player == null)
                 continue;
 
-            player = (PlayerCharacter) playerObject;
-            currentMemory.add(player.getObjectUUID());
-
             // Player is already in our memory
 
             if (_playerMemory.contains(player.getObjectUUID()))
@@ -1012,64 +1008,7 @@ public class City extends AbstractWorldObject {
             //add spire effects.
             if (this.getEffects().size() > 0)
                 this.applyAllCityEffects(player);
-
-            // Add player to our city's memory
-
-            _playerMemory.add(player.getObjectUUID());
-
-            // ***For debugging
-            // Logger.info("PlayerMemory for ", this.getCityName() + ": " + _playerMemory.size());
-        }
-        try {
-            onExit(currentMemory);
-        } catch (Exception e) {
-            Logger.error(e.getMessage());
         }
-        PowersManager.applyZergBuff(this);
-    }
-
-    private void onExit(HashSet<Integer> currentMemory) {
-
-        PlayerCharacter player;
-        int playerUUID = 0;
-        HashSet<Integer> toRemove = new HashSet<>();
-        Iterator<Integer> iter = _playerMemory.iterator();
-
-        while (iter.hasNext()) {
-
-            playerUUID = iter.next();
-
-
-            player = PlayerCharacter.getFromCache(playerUUID);
-
-            if (this.isLocationWithinSiegeBounds(player.getLoc()))
-                continue;
-
-            // Remove players safezone status if warranted
-            // they can assumed to be not on the citygrid at
-            // this point.
-
-
-            player.setSafeZone(false);
-
-            this.removeAllCityEffects(player, false);
-
-            // We will remove this player after iteration is complete
-            // so store it in a temporary collection
-
-            toRemove.add(playerUUID);
-            // ***For debugging
-            // Logger.info("PlayerMemory for ", this.getCityName() + ": " + _playerMemory.size());
-        }
-
-        // Remove players from city memory
-
-        _playerMemory.removeAll(toRemove);
-        for (Integer removalUUID : toRemove) {
-            if (this.cityOutlaws.contains(removalUUID))
-                this.cityOutlaws.remove(removalUUID);
-        }
-        PowersManager.removeZergBuff(toRemove);
     }
 
     public int getWarehouseBuildingID() {
@@ -1442,4 +1381,125 @@ public class City extends AbstractWorldObject {
         return true;
 
     }
+    public void onEnterZerg() {
+
+        if(this.getBane() == null || this.getBane().getLiveDate().dayOfWeek() != DateTime.now().dayOfWeek() || this.getBane().getLiveDate().hourOfDay().get() < DateTime.now().hourOfDay().get() - 1)
+            return;
+        HashSet<AbstractWorldObject> currentPlayers;
+        PlayerCharacter player;
+
+        // Gather current list of players within the zone bounds
+        Building tower = this.getTOL();
+        currentPlayers = WorldGrid.getObjectsInRangePartial(tower.loc, Enum.CityBoundsType.GRID.extents * 2, MBServerStatics.MASK_PLAYER);
+        boolean updated = false;
+
+        for (AbstractWorldObject playerObject : currentPlayers) {
+
+            if (playerObject == null)
+                continue;
+
+            player = (PlayerCharacter) playerObject;
+
+            // Player is already in our memory
+            if (_recentMemory.containsKey(player.getObjectUUID()))
+                _recentMemory.remove(player.getObjectUUID());
+
+            if (_playerMemory.contains(player.getObjectUUID()))
+                continue;
+
+            // Add player to our city's memory
+
+            _playerMemory.add(player.getObjectUUID());
+            updated = true;
+
+            // ***For debugging
+            // Logger.info("PlayerMemory for ", this.getCityName() + ": " + _playerMemory.size());
+        }
+        this.totalPlayers = this._playerMemory.size();
+        try {
+            if(onExitZerg(currentPlayers)){
+                updated = true;
+            }
+        } catch (Exception e) {
+            Logger.error(e.getMessage());
+        }
+        this.dividedPlayers = new HashMap<>();
+        for(Integer playerID : this._playerMemory){
+            player = PlayerCharacter.getFromCache(playerID);
+            Guild nation = player.getGuild().getNation(); Guild entry;
+            if(this.dividedPlayers.containsKey(nation)){
+                this.dividedPlayers.get(nation).add(playerID);
+            }else{
+                ArrayList<Integer> newEntry = new ArrayList<>();
+                newEntry.add(playerID);
+                this.dividedPlayers.put(nation,newEntry);
+            }
+        }
+        if(updated == true){
+            for(Integer playerID : this._playerMemory){
+                player = PlayerCharacter.getFromCache(playerID);
+                if(this.dividedPlayers.containsKey(player.getGuild().getNation())){
+                    int count = this.dividedPlayers.get(player.getGuild().getNation()).size();
+                    switch(this.getBane().capSize){
+                        case 5:
+                            player.ZergMultiplier = ZergManager.getMultiplier5Man(count);
+                            break;
+                        case 10:
+                            player.ZergMultiplier = ZergManager.getMultiplier10Man(count);
+                            break;
+                        case 20:
+                            player.ZergMultiplier = ZergManager.getMultiplier20Man(count);
+                            break;
+                    }
+                } else{
+                    player.ZergMultiplier = 1.0f; //something went wrong reset to default until next cycle
+                }
+            }
+        }
+    }
+
+    private Boolean onExitZerg(HashSet<AbstractWorldObject> currentPlayers) {
+
+        PlayerCharacter player;
+        int playerUUID = 0;
+        HashSet<Integer> toRemove = new HashSet<>();
+        Iterator<Integer> iter = _playerMemory.iterator();
+        while (iter.hasNext()) {
+
+            playerUUID = iter.next();
+
+
+            player = PlayerCharacter.getFromCache(playerUUID);
+
+            if (currentPlayers.contains(player))
+                continue;
+
+            toRemove.add(playerUUID);
+            if(_recentMemory.containsKey(playerUUID) == false) {
+                _recentMemory.put(playerUUID, System.currentTimeMillis());
+            }
+            player.ZergMultiplier = 1.0f; // reset damage modifier to 1.0
+            this.removeAllCityEffects(player, false);
+            if (this.cityOutlaws.contains(playerUUID))
+                this.cityOutlaws.remove(playerUUID);
+        }
+
+        // Remove players from mine memory
+
+        //_playerMemory.removeAll(toRemove);
+        HashSet<Integer> purge = new HashSet<>();
+        for(Integer id : _recentMemory.keySet()){
+            if(System.currentTimeMillis() > _recentMemory.get(playerUUID) + 60000){
+                purge.add(id);
+            }
+        }
+        for(Integer id : purge){
+            _recentMemory.remove(id);
+        }
+        if(toRemove.isEmpty()){
+            return false;
+        }else{
+            return true;
+        }
+    }
 }
diff --git a/src/engine/objects/Mine.java b/src/engine/objects/Mine.java
index baacb51f..cf78b83d 100644
--- a/src/engine/objects/Mine.java
+++ b/src/engine/objects/Mine.java
@@ -582,7 +582,7 @@ public class Mine extends AbstractGameObject {
             amount = amount / value;
         return (int) amount;
     }
-    public void onEnter() {
+    public void onEnterZerg() {
 
         HashSet<AbstractWorldObject> currentPlayers;
         PlayerCharacter player;
@@ -616,7 +616,7 @@ public class Mine extends AbstractGameObject {
         }
         this.totalPlayers = this._playerMemory.size();
         try {
-            if(onExit(currentPlayers)){
+            if(onExitZerg(currentPlayers)){
                 updated = true;
             }
         } catch (Exception e) {
@@ -657,7 +657,7 @@ public class Mine extends AbstractGameObject {
         }
     }
 
-    private Boolean onExit(HashSet<AbstractWorldObject> currentPlayers) {
+    private Boolean onExitZerg(HashSet<AbstractWorldObject> currentPlayers) {
 
         PlayerCharacter player;
         int playerUUID = 0;