Compare commits

..

15 Commits

  1. 61
      src/engine/devcmd/cmds/SetCampLevelCmd.java
  2. 1
      src/engine/gameManager/DevCmdManager.java
  3. 23
      src/engine/gameManager/LootManager.java
  4. 78
      src/engine/mobileAI/Threads/MobRespawnThread.java
  5. 11
      src/engine/objects/Mine.java
  6. 36
      src/engine/objects/Mob.java
  7. 35
      src/engine/objects/Zone.java
  8. 1
      src/engine/server/world/WorldServer.java
  9. 84
      src/engine/util/ZoneLevel.java
  10. 10
      src/engine/workthreads/HourlyJobThread.java

61
src/engine/devcmd/cmds/SetCampLevelCmd.java

@ -0,0 +1,61 @@
package engine.devcmd.cmds;
import engine.devcmd.AbstractDevCmd;
import engine.gameManager.PowersManager;
import engine.gameManager.ZoneManager;
import engine.objects.*;
public class SetCampLevelCmd extends AbstractDevCmd {
public SetCampLevelCmd() { super("setcamplevel"); }
@Override
protected void _doCmd(PlayerCharacter pcSender, String[] args, AbstractGameObject target) {
if (args.length > 1)
{
this.sendUsage(pcSender);
}
int targetLevel = 0;
if (args.length == 1) {
try {
targetLevel = Integer.parseInt(args[0]);
} catch (NumberFormatException nfe) {
throwbackError(pcSender, "Argument MUST be integer. Received: " + args[0]);
} catch (Exception e) {
throwbackError(pcSender, "Unknown command parsing provided camp level: " + args[0]);
}
}
if ((target instanceof Mob))
{
// Get the camp that owns the targeted Mob
Zone campZone = ((Mob) target).parentZone;
// Make sure that the zone we're targeting is valid for action
if (campZone == null ||
campZone.zoneMobSet.isEmpty() ||
campZone.isPlayerCity()) {
throwbackError(pcSender, "Current zone must own mobs, and NOT be a city.");
return;
}
campZone.setCampLvl(targetLevel);
}
else if (target instanceof PlayerCharacter)
{
PlayerCharacter pc = (PlayerCharacter)target;
PowersManager.applyPower(pc, pc, pc.getLoc(), "CMP-001", targetLevel, false);
}
}
@Override
protected String _getUsageString() {
return "Sets the level of the currently occupied camp to the desired level";
}
@Override
protected String _getHelpString() {
return "'./setcamplevel levelNum'";
}
}

1
src/engine/gameManager/DevCmdManager.java

@ -143,6 +143,7 @@ public enum DevCmdManager {
DevCmdManager.registerDevCmd(new ApplyBonusCmd()); DevCmdManager.registerDevCmd(new ApplyBonusCmd());
DevCmdManager.registerDevCmd(new AuditFailedItemsCmd()); DevCmdManager.registerDevCmd(new AuditFailedItemsCmd());
DevCmdManager.registerDevCmd(new SlotTestCmd()); DevCmdManager.registerDevCmd(new SlotTestCmd());
DevCmdManager.registerDevCmd(new SetCampLevelCmd());
} }

23
src/engine/gameManager/LootManager.java

@ -14,6 +14,7 @@ import engine.net.DispatchMessage;
import engine.net.client.msg.ErrorPopupMsg; import engine.net.client.msg.ErrorPopupMsg;
import engine.net.client.msg.chat.ChatSystemMsg; import engine.net.client.msg.chat.ChatSystemMsg;
import engine.objects.*; import engine.objects.*;
import engine.util.ZoneLevel;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.util.ArrayList; import java.util.ArrayList;
@ -100,6 +101,16 @@ public enum LootManager {
boolean hotzoneWasRan = false; boolean hotzoneWasRan = false;
float dropRate = 1.0f; float dropRate = 1.0f;
if (mob.getSafeZone() == false)
dropRate = LootManager.NORMAL_DROP_RATE;
if (inHotzone == true)
dropRate = LootManager.HOTZONE_DROP_RATE;
// Adjust for camp scaling
Zone camp = mob.getParentZone();
dropRate = dropRate * ZoneLevel.getLootDropModifier(camp);
// Iterate all entries in this bootySet and process accordingly // Iterate all entries in this bootySet and process accordingly
for (BootySetEntry bse : entries) { for (BootySetEntry bse : entries) {
@ -109,12 +120,6 @@ public enum LootManager {
break; break;
case "LOOT": case "LOOT":
if (mob.getSafeZone() == false)
dropRate = LootManager.NORMAL_DROP_RATE;
if (inHotzone == true)
dropRate = LootManager.HOTZONE_DROP_RATE;
if (ThreadLocalRandom.current().nextInt(1, 100 + 1) < (bse.dropChance * dropRate)) if (ThreadLocalRandom.current().nextInt(1, 100 + 1) < (bse.dropChance * dropRate))
GenerateLootDrop(mob, bse.genTable, false); //generate normal loot drop GenerateLootDrop(mob, bse.genTable, false); //generate normal loot drop
@ -196,6 +201,9 @@ public enum LootManager {
Logger.error("Failed to GenerateSuffix for item: " + outItem.getName()); Logger.error("Failed to GenerateSuffix for item: " + outItem.getName());
} }
} }
// We don't want to bother with identifying gear
outItem.setIsID(true);
return outItem; return outItem;
} }
@ -306,6 +314,9 @@ public enum LootManager {
else else
gold = (int) (gold * NORMAL_GOLD_RATE); gold = (int) (gold * NORMAL_GOLD_RATE);
Zone camp = mob.getParentZone();
gold = (int) (gold * ZoneLevel.getGoldDropModifier(camp));
if (gold > 0) { if (gold > 0) {
MobLoot goldAmount = new MobLoot(mob, gold); MobLoot goldAmount = new MobLoot(mob, gold);
mob.getCharItemManager().addItemToInventory(goldAmount); mob.getCharItemManager().addItemToInventory(goldAmount);

78
src/engine/mobileAI/Threads/MobRespawnThread.java

@ -11,6 +11,7 @@ package engine.mobileAI.Threads;
import engine.gameManager.ZoneManager; import engine.gameManager.ZoneManager;
import engine.objects.Mob; import engine.objects.Mob;
import engine.objects.Zone; import engine.objects.Zone;
import engine.util.ZoneLevel;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
/** /**
@ -25,7 +26,6 @@ import org.pmw.tinylog.Logger;
public class MobRespawnThread implements Runnable { public class MobRespawnThread implements Runnable {
public MobRespawnThread() { public MobRespawnThread() {
Logger.info(" MobRespawnThread thread has started!"); Logger.info(" MobRespawnThread thread has started!");
@ -34,23 +34,85 @@ public class MobRespawnThread implements Runnable {
@Override @Override
public void run() { public void run() {
long startTime = System.currentTimeMillis();
long rollingKeepFraction = (Zone.rollingAvgMobsAliveDepth - 1) / Zone.rollingAvgMobsAliveDepth;
long rollingAddFraction = 1 / Zone.rollingAvgMobsAliveDepth;
while (true) { while (true) {
try { try {
for (Zone zone : ZoneManager.getAllZones()) { for (Zone zone : ZoneManager.getAllZones()) {
if (zone.respawnQue.isEmpty() == false && zone.lastRespawn + 100 < System.currentTimeMillis()) { /*
if (zone.respawnQue.size() > ZoneLevel.queueLengthToLevelUp) {
zone.setCampLvl(zone.getCamplvl() + 1);
}
else if (zone.respawnQue.isEmpty() &&
(zone.lastRespawn + ZoneLevel.msToLevelDown < System.currentTimeMillis()) &&
zone.getCamplvl() > 0) {
zone.setCampLvl(zone.getCamplvl() - 1);
}
*/
int aliveCount = 0;
int deadCount = 0;
for (Mob mob : zone.zoneMobSet) {
if (mob.isAlive()) {
aliveCount = aliveCount + 1;
}
else {
deadCount = deadCount + 1;
}
}
zone.rollingAvgMobsAlive =
((zone.rollingAvgMobsAlive * (Zone.rollingAvgMobsAliveDepth - 1) + aliveCount) / Zone.rollingAvgMobsAliveDepth);
Mob respawner = zone.respawnQue.iterator().next(); /*
if (startTime + ZoneLevel.msDelayToCampLevel < System.currentTimeMillis()) {
if (aliveCount > Math.floor(zone.zoneMobSet.size() / 2.0)) {
if (zone.levelUpTimer == 0) {
zone.levelUpTimer = System.currentTimeMillis();
} else if (zone.levelUpTimer + ZoneLevel.msTolevelUp < System.currentTimeMillis()) {
zone.setCampLvl(zone.getCampLvl() + 1);
if (respawner == null) zone.levelUpTimer = 0;
continue; }
} else if (aliveCount == 0) {
respawner.respawn(); if (zone.levelDownTimer == 0) {
zone.respawnQue.remove(respawner); zone.levelDownTimer = System.currentTimeMillis();
zone.lastRespawn = System.currentTimeMillis(); } else if (zone.levelDownTimer + ZoneLevel.msToLevelDown < System.currentTimeMillis()) {
if (zone.getCampLvl() > 0) {
zone.setCampLvl(zone.getCampLvl() + 1);
zone.levelDownTimer = 0;
}
}
} else {
zone.levelUpTimer = 0;
zone.levelDownTimer = 0;
}
} }
*/
} }
// --------------------------------------------------------------------------------------------------------------------
// Manage mob respawn
// --------------------------------------------------------------------------------------------------------------------
if (!Zone.respawnQue.isEmpty() && Zone.lastRespawn + 100 < System.currentTimeMillis()) {
Mob respawner = Zone.respawnQue.iterator().next();
if (respawner == null)
continue;
respawner.respawn();
Zone.respawnQue.remove(respawner);
Zone.lastRespawn = System.currentTimeMillis();
}
} catch (Exception e) { } catch (Exception e) {
Logger.error(e); Logger.error(e);
} }

11
src/engine/objects/Mine.java

@ -290,7 +290,9 @@ public class Mine extends AbstractGameObject {
if (treeRank < 1) if (treeRank < 1)
return false; return false;
if (guildUnderMineLimit(playerGuild.getNation(), treeRank) == false) { // We check the limit against only the player guild right now
// each guild (even within a nation) is limited by the nation tree
if (guildUnderMineLimit(playerGuild, treeRank) == false) {
ErrorPopupMsg.sendErrorMsg(playerCharacter, "Your nation cannot support another mine."); ErrorPopupMsg.sendErrorMsg(playerCharacter, "Your nation cannot support another mine.");
return false; return false;
} }
@ -304,10 +306,11 @@ public class Mine extends AbstractGameObject {
mineCnt += Mine.getMinesForGuild(playerGuild.getObjectUUID()).size(); mineCnt += Mine.getMinesForGuild(playerGuild.getObjectUUID()).size();
for (Guild guild : playerGuild.getSubGuildList()) // Only count mines for a specific guild
mineCnt += Mine.getMinesForGuild(guild.getObjectUUID()).size(); //for (Guild guild : playerGuild.getSubGuildList())
// mineCnt += Mine.getMinesForGuild(guild.getObjectUUID()).size();
return mineCnt <= tolRank; return mineCnt <= (tolRank * 2);
} }
public boolean changeProductionType(Resource resource) { public boolean changeProductionType(Resource resource) {

36
src/engine/objects/Mob.java

@ -31,6 +31,7 @@ import engine.net.client.msg.PlaceAssetMsg;
import engine.powers.EffectsBase; import engine.powers.EffectsBase;
import engine.powers.MobPowerEntry; import engine.powers.MobPowerEntry;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import engine.util.ZoneLevel;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
@ -101,6 +102,8 @@ public class Mob extends AbstractIntelligenceAgent {
private DateTime upgradeDateTime = null; private DateTime upgradeDateTime = null;
private boolean lootSync = false; private boolean lootSync = false;
private String originalFirstName;
private String originalLastName;
/** /**
* No Id Constructor * No Id Constructor
@ -129,6 +132,9 @@ public class Mob extends AbstractIntelligenceAgent {
this.lastName = "the " + contract.getName(); this.lastName = "the " + contract.getName();
} }
clearStatic(); clearStatic();
originalFirstName = this.firstName;
originalLastName = this.lastName;
} }
/** /**
@ -150,6 +156,9 @@ public class Mob extends AbstractIntelligenceAgent {
this.building = building; this.building = building;
initializeMob(false, false, false); initializeMob(false, false, false);
clearStatic(); clearStatic();
originalFirstName = this.firstName;
originalLastName = this.lastName;
} }
/** /**
@ -166,6 +175,9 @@ public class Mob extends AbstractIntelligenceAgent {
this.BehaviourType = Enum.MobBehaviourType.Pet1; this.BehaviourType = Enum.MobBehaviourType.Pet1;
initializeMob(true, false, false); initializeMob(true, false, false);
clearStatic(); clearStatic();
originalFirstName = this.firstName;
originalLastName = this.lastName;
} }
//SIEGE CONSTRUCTOR //SIEGE CONSTRUCTOR
@ -180,6 +192,9 @@ public class Mob extends AbstractIntelligenceAgent {
this.equip = new HashMap<>(); this.equip = new HashMap<>();
initializeMob(false, true, isPlayerGuard); initializeMob(false, true, isPlayerGuard);
clearStatic(); clearStatic();
originalFirstName = this.firstName;
originalLastName = this.lastName;
} }
/** /**
@ -288,6 +303,8 @@ public class Mob extends AbstractIntelligenceAgent {
Logger.error("Mobile:" + this.dbID + ": " + e); Logger.error("Mobile:" + this.dbID + ": " + e);
} }
originalFirstName = this.firstName;
originalLastName = this.lastName;
} }
public static void serializeMobForClientMsgOtherPlayer(Mob mob, ByteBufferWriter writer) throws SerializationException { public static void serializeMobForClientMsgOtherPlayer(Mob mob, ByteBufferWriter writer) throws SerializationException {
@ -1382,6 +1399,12 @@ public class Mob extends AbstractIntelligenceAgent {
NPCManager.applyRuneSetEffects(this); NPCManager.applyRuneSetEffects(this);
// Set Name based on parent zone level
Zone camp = this.getParentZone();
this.lastName = this.originalLastName + ZoneLevel.getNameSuffix(camp);
//PowersManager.applyPower(this, this, this.getLoc(), "CMP-001", camp.getCamplvl(), false);
this.recalculateStats(); this.recalculateStats();
this.setHealth(this.healthMax); this.setHealth(this.healthMax);
@ -1495,6 +1518,10 @@ public class Mob extends AbstractIntelligenceAgent {
s *= (1 + this.bonuses.getFloatPercentAll(ModType.StaminaFull, SourceType.None)); s *= (1 + this.bonuses.getFloatPercentAll(ModType.StaminaFull, SourceType.None));
} }
// Modify max health based on camp level - bad, we need to use effects for this
Zone camp = this.getParentZone();
h = h * ZoneLevel.getMaxHealthPctModifier(camp);
// Set max health, mana and stamina // Set max health, mana and stamina
if (h > 0) if (h > 0)
@ -1595,6 +1622,11 @@ public class Mob extends AbstractIntelligenceAgent {
Logger.error("Error: missing bonuses"); Logger.error("Error: missing bonuses");
defense = (defense < 1) ? 1 : defense; defense = (defense < 1) ? 1 : defense;
// Modify defense for camp level - bad, we need to use effects for this
Zone camp = this.getParentZone();
defense = defense * ZoneLevel.getDefPctModifier(camp);
this.defenseRating = (short) (defense + 0.5f); this.defenseRating = (short) (defense + 0.5f);
} catch (Exception e) { } catch (Exception e) {
Logger.info("Mobbase ID " + this.getMobBaseID() + " returned an error. Setting to Default Defense." + e.getMessage()); Logger.info("Mobbase ID " + this.getMobBaseID() + " returned an error. Setting to Default Defense." + e.getMessage());
@ -1796,6 +1828,10 @@ public class Mob extends AbstractIntelligenceAgent {
atr *= (1 + neg_Bonus); atr *= (1 + neg_Bonus);
} }
// Modify atr for camp level - bad, we need to use effects for this
Zone camp = this.getParentZone();
atr = atr * ZoneLevel.getAtrPctModifier(camp);
atr = (atr < 1) ? 1 : atr; atr = (atr < 1) ? 1 : atr;
// set atr // set atr

35
src/engine/objects/Zone.java

@ -18,7 +18,10 @@ import engine.math.Bounds;
import engine.math.Vector2f; import engine.math.Vector2f;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
import engine.net.ByteBufferWriter; import engine.net.ByteBufferWriter;
import engine.net.DispatchMessage;
import engine.net.client.msg.chat.ChatSystemMsg;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import engine.util.ZoneLevel;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.sql.ResultSet; import java.sql.ResultSet;
@ -61,6 +64,13 @@ public class Zone extends AbstractGameObject {
//public static ArrayList<Mob> respawnQue = new ArrayList<>(); //public static ArrayList<Mob> respawnQue = new ArrayList<>();
public static final Set<Mob> respawnQue = Collections.newSetFromMap(new ConcurrentHashMap<>()); public static final Set<Mob> respawnQue = Collections.newSetFromMap(new ConcurrentHashMap<>());
public static long lastRespawn = 0; public static long lastRespawn = 0;
private int campLvl = 0;
public long levelUpTimer = 0;
public long levelDownTimer = 0;
public int rollingAvgMobsAlive = 0;
public static final int rollingAvgMobsAliveDepth = 100;
/** /**
* ResultSet Constructor * ResultSet Constructor
*/ */
@ -100,8 +110,33 @@ public class Zone extends AbstractGameObject {
if (hash == null) if (hash == null)
setHash(); setHash();
}
public void setCampLvl(int level)
{
this.campLvl = level;
if (this.campLvl > ZoneLevel.campMaxLvl)
{
this.campLvl = ZoneLevel.campMaxLvl;
}
else if (this.campLvl < 0)
{
this.campLvl = 0;
}
//if (this.campLvl > ZoneLevel.campLvlAnnounceThreshold)
{
ChatSystemMsg chatMsg = new ChatSystemMsg(null, this.getName() + " has reached camp level " + this.campLvl + "! Will anyone contest?!");
chatMsg.setMessageType(2);
chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID());
DispatchMessage.dispatchMsgToAll(chatMsg);
}
}
public int getCampLvl()
{
return this.campLvl;
} }
public static void serializeForClientMsg(Zone zone, ByteBufferWriter writer) { public static void serializeForClientMsg(Zone zone, ByteBufferWriter writer) {

1
src/engine/server/world/WorldServer.java

@ -288,6 +288,7 @@ public class WorldServer {
private boolean init() { private boolean init() {
Logger.info("Server Code: [NovaTest] Branch");
Logger.info("MAGICBANE SERVER GREETING:"); Logger.info("MAGICBANE SERVER GREETING:");
Logger.info(ConfigManager.MB_WORLD_GREETING.getValue()); Logger.info(ConfigManager.MB_WORLD_GREETING.getValue());

84
src/engine/util/ZoneLevel.java

@ -0,0 +1,84 @@
package engine.util;
import engine.objects.Zone;
public class ZoneLevel {
private static final float healthPctPerLevel = (float)0.2;
private static final float atrPctPerLevel = (float)0.2;
private static final float defPctPerLevel = (float)0.2;
private static final float lootPctPerLevel = (float)0.1;
private static final float goldPctPerLevel = (float)0.2;
public static final int campLvlAnnounceThreshold = 5;
public static final int campMaxLvl = 10;
public static final int queueLengthToLevelUp = 5;
public static final int msToLevelDown = 60 * 1000;
public static final int msTolevelUp = 60 * 1000;
public static final long msDelayToCampLevel = 60 * 1000;
private static final String[] nameMap =
{
"",
" I",
" II",
" III",
" IV",
" V",
" VI",
" VII",
" VIII",
" IX",
" X"
};
public static String getNameSuffix(Zone zone)
{
try {
return nameMap[zone.getCampLvl()];
}
catch (Exception ignored)
{
}
return "";
}
public static float getMaxHealthPctModifier(Zone zone)
{
return getGenericModifier(zone, healthPctPerLevel);
}
public static float getAtrPctModifier(Zone zone)
{
return getGenericModifier(zone, atrPctPerLevel);
}
public static float getDefPctModifier(Zone zone)
{
return getGenericModifier(zone, defPctPerLevel);
}
public static float getLootDropModifier(Zone zone)
{
return getGenericModifier(zone, lootPctPerLevel);
}
public static float getGoldDropModifier(Zone zone)
{
return getGenericModifier(zone, goldPctPerLevel);
}
private static float getGenericModifier(Zone zone, float modifierPerLevel)
{
float modifier = (float)1.0;
if (zone != null)
{
modifier += zone.getCampLvl() * modifierPerLevel;
}
return modifier;
}
}

10
src/engine/workthreads/HourlyJobThread.java

@ -128,10 +128,12 @@ public class HourlyJobThread implements Runnable {
if (mine.isActive == false) if (mine.isActive == false)
return false; return false;
Logger.info(mine.getZoneName() + "'s Mine is now Closing");
Building mineBuilding = BuildingManager.getBuildingFromCache(mine.getBuildingID()); Building mineBuilding = BuildingManager.getBuildingFromCache(mine.getBuildingID());
if (mineBuilding == null) { if (mineBuilding == null) {
Logger.debug("Null mine building for Mine " + mine.getObjectUUID() + " Building " + mine.getBuildingID()); Logger.info("Null mine building for Mine " + mine.getObjectUUID() + " Building " + mine.getBuildingID());
return false; return false;
} }
@ -139,6 +141,8 @@ public class HourlyJobThread implements Runnable {
// We can early exit here. // We can early exit here.
if (mineBuilding.getRank() > 0) { if (mineBuilding.getRank() > 0) {
Logger.info("Mine still standing when closing window. Mine Object UUID: " + mine.getObjectUUID() + " Building Id: " + mine.getBuildingID());
mine.setActive(false); mine.setActive(false);
mine.lastClaimer = null; mine.lastClaimer = null;
return true; return true;
@ -149,6 +153,8 @@ public class HourlyJobThread implements Runnable {
// and keep the window open. // and keep the window open.
if (!Mine.validateClaimer(mine.lastClaimer)) { if (!Mine.validateClaimer(mine.lastClaimer)) {
Logger.info("Mine has no valid claimer when closing window. Mine Object UUID: " + mine.getObjectUUID() + " Building Id: " + mine.getBuildingID());
mine.lastClaimer = null; mine.lastClaimer = null;
mine.updateGuildOwner(null); mine.updateGuildOwner(null);
mine.setActive(true); mine.setActive(true);
@ -157,6 +163,8 @@ public class HourlyJobThread implements Runnable {
//Update ownership to map //Update ownership to map
Logger.info("Mine ownership changing when closing window. Mine Object UUID: " + mine.getObjectUUID() + " Building Id: " + mine.getBuildingID() + " new owning guild: " + mine.getOwningGuild().getObjectUUID());
mine.guildName = mine.getOwningGuild().getName(); mine.guildName = mine.getOwningGuild().getName();
mine.guildTag = mine.getOwningGuild().getGuildTag(); mine.guildTag = mine.getOwningGuild().getGuildTag();
Guild nation = mine.getOwningGuild().getNation(); Guild nation = mine.getOwningGuild().getNation();

Loading…
Cancel
Save