Compare commits

..

15 Commits

Author SHA1 Message Date
FatBoy 39638e4789 mob ai work 2025-01-08 18:08:38 -06:00
FatBoy 277bb14bab mob ai work 2025-01-08 17:55:06 -06:00
FatBoy 033f7c9ccf mob ai work 2025-01-08 17:53:46 -06:00
FatBoy b3026c9cab mob ai work 2025-01-08 17:46:59 -06:00
FatBoy a33ac85b21 mob ai work 2025-01-08 17:46:46 -06:00
FatBoy ff4010d652 mob ai work 2025-01-08 17:41:21 -06:00
FatBoy 9d46da8d07 mob ai work 2025-01-08 17:38:55 -06:00
FatBoy c581d19990 mob ai work 2025-01-08 17:36:51 -06:00
FatBoy 40c77df0fe mob ai work 2025-01-08 17:34:35 -06:00
FatBoy 789b3f3ffb mob ai work 2025-01-08 17:32:25 -06:00
FatBoy 83be9f4ec5 mob ai work 2025-01-08 17:28:19 -06:00
FatBoy 728db63024 mob ai work 2025-01-08 07:20:49 -06:00
FatBoy 2815bc74ad mob ai work 2025-01-07 21:56:34 -06:00
FatBoy 87d95e3c48 mob ai work 2025-01-07 21:48:18 -06:00
FatBoy 20f9d136b6 new mob AI 2025-01-06 21:14:05 -06:00
41 changed files with 1103 additions and 1101 deletions
-131
View File
@@ -1,131 +0,0 @@
package engine.QuestSystem;
import engine.InterestManagement.WorldGrid;
import engine.gameManager.ChatManager;
import engine.net.client.msg.ErrorPopupMsg;
import engine.objects.*;
import engine.server.MBServerStatics;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;
public class QuestManager {
public static HashMap<PlayerCharacter,QuestObject> acceptedQuests = new HashMap<>();
public static HashMap<PlayerCharacter,ArrayList<String>> completedQuests = new HashMap<>();
public static boolean grantsQuest(NPC npc){
if(npc == null)
return false;
if(npc.contract == null)
return false;
return npc.contract.getName().contains("ZoneLore") || npc.contract.getName().equals("Barrowlands Sentry");
}
public static void displayCurrentQuest(PlayerCharacter pc){
if(acceptedQuests.containsKey(pc)){
QuestObject obj = acceptedQuests.get(pc);
String output = "You have embarked on the noble quest: ";
output += obj.QuestName + ". ";
output += obj.description;
output += ". " + obj.objectiveCount + " / " + obj.objectiveCountRequired;
ErrorPopupMsg.sendErrorMsg(pc, output);
}else{
ErrorPopupMsg.sendErrorMsg(pc, "You have no active quest.");
}
}
public static void acceptQuest(PlayerCharacter pc, QuestObject obj){
if (completedQuests.containsKey(pc)) {
if(completedQuests.get(pc).contains(obj.QuestName)){
ErrorPopupMsg.sendErrorMsg(pc, "You have already completed the quest: " + obj.QuestName);
return;
}
}
if(acceptedQuests.containsKey(pc)){
if(acceptedQuests.get(pc)!= null){
ErrorPopupMsg.sendErrorMsg(pc, "You have already embarked on a noble quest.");
return;
}
}
acceptedQuests.put(pc,obj);
displayCurrentQuest(pc);
}
public static void completeQuest(PlayerCharacter pc, QuestObject obj){
if(obj.objectiveCount < obj.objectiveCountRequired) {
ChatManager.chatSystemInfo(pc, obj.QuestName + " Progress: " + obj.objectiveCount + " / " + obj.objectiveCountRequired);
return;
}
//notify the player they have completed their quest
ErrorPopupMsg.sendErrorMsg(pc, "You have completed the quest: " + obj.QuestName +"!");
//add completed quest to completion log
if (completedQuests.containsKey(pc)) {
completedQuests.get(pc).add(obj.QuestName);
}else{
ArrayList<String> completed = new ArrayList<>();
completed.add(obj.QuestName);
completedQuests.put(pc,completed);
}
//remove current quest from active log
if(acceptedQuests.containsKey(pc))
acceptedQuests.remove(pc);
//grant rewards
//only grant XP if level is below 75
if(pc.level < 75) {
int xpGrant = (int) (Experience.maxXPPerKill(pc.getLevel()) * 10);
pc.grantXP(xpGrant);
ChatManager.chatSystemInfo(pc, "Your Quest Has Granted you: " + xpGrant + " Experience Points");
}
int goldGrant = (int) Experience.maxXPPerKill(pc.getLevel());
pc.getCharItemManager().addGoldToInventory(goldGrant,false);
ChatManager.chatSystemInfo(pc, "Your Quest Has Granted you: " + goldGrant + " Gold Coins");
pc.getCharItemManager().updateInventory();
}
public static QuestObject getQuestForContract(NPC npc){
QuestObject obj = new QuestObject();
obj.QuestName = npc.getFirstName() + "'s Quest";
HashSet<AbstractWorldObject> mobs = WorldGrid.getObjectsInRangePartial(npc.loc,2048, MBServerStatics.MASK_MOB);
if (mobs.isEmpty())
return null; // Handle the case where the set is empty
// Convert HashSet to a List
ArrayList<AbstractWorldObject> mobList = new ArrayList<>(mobs);
Mob mob = null;
while(mob == null || Mob.discDroppers.contains(mob)) {
// Generate a random index
Random random = new Random();
int randomIndex = random.nextInt(mobList.size());
if (mobList.get(randomIndex) == null) {
continue;
}
mob = (Mob) mobList.get(randomIndex);
}
obj.progressionNames = new ArrayList<>();
obj.progressionNames.add(mob.getFirstName());
obj.objectiveCountRequired = 10;
obj.objectiveCount = 0;
obj.description = "These lands are plagued with " + mob.getFirstName() + " complete the quest by slaying 10 of them!";
return obj;
}
}
-27
View File
@@ -1,27 +0,0 @@
package engine.QuestSystem;
import engine.objects.ItemBase;
import engine.objects.NPC;
import engine.objects.PlayerCharacter;
import java.util.ArrayList;
public class QuestObject {
public String QuestName;
public String description;
public int objectiveCount;
public int objectiveCountRequired;
public ArrayList<String> progressionNames;
public PlayerCharacter owner;
public QuestObject(){
}
public void tryProgress(String option){
if(this.progressionNames.contains(option))
this.objectiveCount++;
else
return;
}
}
+6 -12
View File
@@ -15,12 +15,9 @@ import engine.Enum.GameObjectType;
import engine.Enum.TargetColor;
import engine.devcmd.AbstractDevCmd;
import engine.gameManager.BuildingManager;
import engine.gameManager.PowersManager;
import engine.gameManager.SessionManager;
import engine.math.Vector3fImmutable;
import engine.objects.*;
import engine.powers.EffectsBase;
import engine.powers.PowersBase;
import engine.server.MBServerStatics;
import engine.util.StringUtils;
@@ -497,16 +494,13 @@ public class InfoCmd extends AbstractDevCmd {
output += newline;
output += "No building found." + newline;
}
output += "Damage: " + targetMob.mobBase.getDamageMin() + " - " + targetMob.mobBase.getDamageMax() + newline;
output += "ATR: " + targetMob.mobBase.getAttackRating() + newline;
output += "DEF: " + targetMob.defenseRating + newline;
output += "RANGE: " + targetMob.getRange() + newline;
output += "Effects:" + newline;
for(MobBaseEffects mbe : targetMob.mobBase.mobbaseEffects){
EffectsBase eb = PowersManager.getEffectByToken(mbe.getToken());
output += eb.getName() + " " + eb.getIDString() + newline;
int max = (int)(4.882 * targetMob.level + 121.0);
if(max > 321){
max = 321;
}
int min = (int)(4.469 * targetMob.level - 3.469);
output += "Min Loot Roll = " + min;
output += "Max Loot Roll = " + max;
break;
case Item: //intentional passthrough
case MobLoot:
+1 -7
View File
@@ -14,7 +14,6 @@ import engine.Enum.GameObjectType;
import engine.Enum.ModType;
import engine.Enum.SourceType;
import engine.InterestManagement.WorldGrid;
import engine.QuestSystem.QuestManager;
import engine.db.archive.BaneRecord;
import engine.db.archive.PvpRecord;
import engine.net.Dispatch;
@@ -109,9 +108,9 @@ public enum ChatManager {
ChatManager.chatIC(pc, (ChatICMsg) msg);
return;
case LEADERCHANNELMESSAGE:
case GLOBALCHANNELMESSAGE:
ChatManager.chatGlobal(pc, msg.getMessage(), isFlood);
return;
case GLOBALCHANNELMESSAGE:
case CHATPVP:
case CHATCITY:
case CHATINFO:
@@ -200,11 +199,6 @@ public enum ChatManager {
return;
}
if(text.equalsIgnoreCase("show_quest()")){
QuestManager.displayCurrentQuest(pcSender);
return;
}
if (ChatManager.isVersionRequest(text) == true) {
sendSystemMessage(pcSender, ConfigManager.MB_WORLD_GREETING.getValue());
return;
+6 -34
View File
@@ -662,8 +662,9 @@ public enum CombatManager {
DeferredPowerJob dpj = null;
boolean hitLanded = LandHit((int)atr,(int)defense);
if (hitLanded) {
if (LandHit((int)atr,(int)defense)) {
if (ac.getObjectType().equals(GameObjectType.PlayerCharacter))
updateAttackTimers((PlayerCharacter) ac, target, true);
@@ -692,13 +693,7 @@ public enum CombatManager {
PlayerBonuses bonus = ac.getBonuses();
float attackRange = getWeaponRange(wb, bonus);
if(specialCaseHitRoll(dpj.getPowerToken())) {
if(hitLanded) {
dpj.attack(target, attackRange);
}
}else{
dpj.attack(target, attackRange);
}
dpj.attack(target, attackRange);
if (dpj.getPower() != null && (dpj.getPowerToken() == -1851459567 || dpj.getPowerToken() == -1851489518))
((PlayerCharacter) ac).setWeaponPower(dpj);
@@ -713,13 +708,7 @@ public enum CombatManager {
if (dpj != null && dpj.getPower() != null && (dpj.getPowerToken() == -1851459567 || dpj.getPowerToken() == -1851489518)) {
float attackRange = getWeaponRange(wb, bonuses);
if(specialCaseHitRoll(dpj.getPowerToken())) {
if(hitLanded) {
dpj.attack(target, attackRange);
}
}else{
dpj.attack(target, attackRange);
}
dpj.attack(target, attackRange);
}
}
@@ -927,13 +916,7 @@ public enum CombatManager {
if (wp.requiresHitRoll() == false) {
PlayerBonuses bonus = ac.getBonuses();
float attackRange = getWeaponRange(wb, bonus);
if(specialCaseHitRoll(dpj.getPowerToken())) {
if(hitLanded) {
dpj.attack(target, attackRange);
}
}else{
dpj.attack(target, attackRange);
}
dpj.attack(target, attackRange);
} else
((PlayerCharacter) ac).setWeaponPower(null);
}
@@ -1483,15 +1466,4 @@ public enum CombatManager {
return roll <= convertedChance;
}
public static boolean specialCaseHitRoll(int powerID){
switch(powerID) {
case 563200808: // Naargal's Bite
case 563205337: // Naargal's Dart
case 563205930: // Sword of Saint Malorn
return true;
default:
return false;
}
}
}
+2 -9
View File
@@ -75,11 +75,6 @@ public enum LootManager {
}
public static void GenerateMobLoot(Mob mob) {
if(mob == null){
return;
}
//determine if mob is in hotzone
boolean inHotzone = false;
@@ -185,16 +180,14 @@ public enum LootManager {
// Iterate all entries in this bootySet and process accordingly
Zone zone = ZoneManager.findSmallestZone(mob.loc);
for (BootySetEntry bse : entries) {
switch (bse.bootyType) {
case "GOLD":
if (zone != null && zone.getSafeZone() == (byte)1)
return; // no loot to drop in safezones
GenerateGoldDrop(mob, bse, inHotzone);
break;
case "LOOT":
if (zone != null && zone.getSafeZone() == (byte)1)
if (mob.getSafeZone())
return; // no loot to drop in safezones
dropRate = LootManager.NORMAL_DROP_RATE;
+11 -129
View File
@@ -349,10 +349,8 @@ public enum PowersManager {
msg.setNumTrains(trains);
}
//double stack point values for some useless disc spells
switch(pb.token){
case 429420458: // BH eyes
case 429601664: // huntsman skin the beast
msg.setNumTrains(msg.getNumTrains() * 2);
break;
}
@@ -604,12 +602,12 @@ public enum PowersManager {
}
// update cast (use skill) fail condition
if(pb.token != 429396028 && pb.breaksForm) {
if(pb.token != 429396028) {
playerCharacter.cancelOnCast();
}
// update castSpell (use spell) fail condition if spell
if (pb.isSpell() && pb.breaksForm)
if (pb.isSpell())
playerCharacter.cancelOnSpell();
// get cast time in ms.
@@ -750,11 +748,10 @@ public enum PowersManager {
// make person casting stand up if spell (unless they're casting a chant which does not make them stand up)
// update cast (use skill) fail condition
if(pb.breaksForm)
caster.cancelOnCast();
caster.cancelOnCast();
// update castSpell (use spell) fail condition if spell
if (pb.isSpell() && pb.breaksForm)
if (pb.isSpell())
caster.cancelOnSpell();
// get cast time in ms.
@@ -790,11 +787,13 @@ public enum PowersManager {
if (playerCharacter == null || msg == null)
return;
if(msg.getPowerUsedID() == 429005674){ //bard sprint
//use sprint instead of ballad of beregund the bold
//applyPower(playerCharacter,playerCharacter,playerCharacter.loc,429611355,msg.getNumTrains(),false);
msg.setPowerUsedID(429611355);
}
//if((msg.getPowerUsedID() == 429495514 || msg.getPowerUsedID() == 429407306) && playerCharacter.getRace().getName().toLowerCase().contains("shade")){
// //use sneak instead of hide
// PowersBase pb = PowersManager.getPowerByToken(429397210);
// int offsetTrains = (40 - msg.getNumTrains()) ;
// applyPower(playerCharacter,playerCharacter,playerCharacter.loc,429397210,msg.getNumTrains(),false);
// applyPower(playerCharacter,playerCharacter,playerCharacter.loc,427857146,offsetTrains,false);
//}
if(msg.getPowerUsedID() == 429494441) {//wildkins chase
playerCharacter.removeEffectBySource(EffectSourceType.Root,40,true);
playerCharacter.removeEffectBySource(EffectSourceType.Snare,40,true);
@@ -2845,123 +2844,6 @@ public enum PowersManager {
}
}
public static boolean breakForm(int token) {
switch (token) {
case 429505865:
case 429407561:
case 429492073:
case 429644123:
case 429393769:
case 429545819:
case 429426537:
case 429590377:
case 429508425:
case 429541193:
case 429573961:
case 427924330:
case 429402918:
case 429545688:
case 429005674:
case 429637823:
case 429590426:
case 428066972:
case 429441862:
case 431611756:
case 431578988:
case 429502506:
case 429398191:
case 429447384:
case 428892191:
case 431579167:
case 430977067:
case 429409100:
case 429441868:
case 429594877:
case 427908971:
case 683741153:
case 429770569:
case 429452379:
case 429605055:
case 429086971:
case 429443230:
case 429505400:
case 429492122:
case 429643992:
case 550062236:
case 429498252:
case 429611224:
case 429441834:
case 428918940:
case 429633739:
case 429633579:
case 429568043:
case 429048646:
case 428392639:
case 428425407:
case 429054168:
case 429021400:
case 428955864:
case 429119704:
case 428890328:
case 428923096:
case 429218008:
case 429086936:
case 428988632:
case 428688204:
case 429514603:
case 428924959:
case 429393818:
case 429720966:
case 428982463:
case 427933887:
case 429572287:
case 429501222:
case 430694431:
case 429436131:
case 430006124:
case 429611355:
case 428005600:
case 427935608:
case 428949695:
case 427988218:
case 429414616:
case 429496495:
case 429428796:
case 563795754:
case 428988217:
case 429432716:
case 428955899:
case 429393286:
case 550062220:
case 429495557:
case 429401278:
case 428377478:
case 429409094:
case 428191947:
case 429434474:
case 429403363:
case 429512920:
case 429419611:
case 429645676:
case 429602895:
case 429605071:
case 429592428:
case 429500010:
case 429406602:
case 429426586:
case 429633898:
case 550062212:
case 429994027:
case 430813227:
case 429928491:
case 430026795:
case 429517915:
case 431854842:
case 429767544:
return false;
}
return true;
}
}
+1 -1
View File
@@ -117,7 +117,7 @@ public abstract class AbstractEffectJob extends AbstractScheduleJob {
}
public void endEffect() {
if (this.eb == null || this.power == null)
if (this.eb == null)
return;
this.eb.endEffect(this.source, this.target, this.trains, this.power, this);
}
-14
View File
@@ -1,9 +1,7 @@
package engine.jobs;
import engine.gameManager.ZoneManager;
import engine.job.AbstractScheduleJob;
import engine.objects.Building;
import engine.objects.City;
import org.pmw.tinylog.Logger;
/*
@@ -43,18 +41,6 @@ public class UpgradeBuildingJob extends AbstractScheduleJob {
rankingBuilding.setRank(rankingBuilding.getRank() + 1);
if(rankingBuilding.getBlueprint().isWallPiece()){
City cityObject = ZoneManager.getCityAtLocation(rankingBuilding.loc);
if(cityObject.getTOL().getRank() == 8) {
if (rankingBuilding.getBlueprint() != null && rankingBuilding.getBlueprint().getBuildingGroup() != null && rankingBuilding.getBlueprint().isWallPiece()) {
float currentHealthRatio = rankingBuilding.getCurrentHitpoints() / rankingBuilding.healthMax;
float newMax = rankingBuilding.healthMax * 1.1f;
rankingBuilding.setMaxHitPoints(newMax);
rankingBuilding.setHealth(rankingBuilding.healthMax * currentHealthRatio);
}
}
}
// Reload the object
+30 -22
View File
@@ -9,6 +9,7 @@
package engine.mobileAI;
import engine.Enum;
import engine.Enum.DispatchChannel;
import engine.InterestManagement.WorldGrid;
import engine.gameManager.*;
import engine.math.Vector3f;
@@ -18,7 +19,7 @@ import engine.mobileAI.utilities.CombatUtilities;
import engine.mobileAI.utilities.MovementUtilities;
import engine.net.DispatchMessage;
import engine.net.client.msg.PerformActionMsg;
import engine.net.client.msg.UpdateStateMsg;
import engine.net.client.msg.PowerProjectileMsg;
import engine.objects.*;
import engine.powers.ActionsBase;
import engine.powers.PowersBase;
@@ -108,7 +109,7 @@ public class MobAI {
if (mob.BehaviourType.callsForHelp)
MobCallForHelp(mob);
if (MovementUtilities.outOfAggroRange(mob, target)) {
if (!MovementUtilities.inRangeDropAggro(mob, target)) {
mob.setCombatTarget(null);
return;
}
@@ -320,20 +321,20 @@ public class MobAI {
if (mob == null)
return false;
if(mob.isPlayerGuard){
if(mob.isPlayerGuard == true){
int contractID = 0;
int contractID;
if(mob.BehaviourType.equals(Enum.MobBehaviourType.GuardMinion) && mob.npcOwner != null)
if(mob.BehaviourType.equals(Enum.MobBehaviourType.GuardMinion))
contractID = mob.npcOwner.contract.getContractID();
else if(mob.contract != null)
else
contractID = mob.contract.getContractID();
if(Enum.MinionType.ContractToMinionMap.containsKey(contractID) && !Enum.MinionType.ContractToMinionMap.get(contractID).isMage())
if(Enum.MinionType.ContractToMinionMap.get(contractID).isMage() == false)
return false;
}
if (mob.mobPowers == null || mob.mobPowers.isEmpty())
if (mob.mobPowers.isEmpty())
return false;
if (!mob.canSee((PlayerCharacter) mob.getCombatTarget())) {
@@ -600,6 +601,23 @@ public class MobAI {
if (mob == null)
return;
boolean continueExecution = false;
switch(mob.BehaviourType){
case GuardCaptain:
case GuardMinion:
case Pet1:
case GuardWallArcher:
case HamletGuard:
case SimpleStandingGuard:
continueExecution = true;
break;
}
if(!continueExecution) {
MobAi2.runAI(mob);
return;
}
if(mob.isAlive())
if(!mob.getMovementLoc().equals(Vector3fImmutable.ZERO))
mob.setLoc(mob.getMovementLoc());
@@ -883,7 +901,6 @@ public class MobAI {
return;
}
}
return;
}
if(Mob.discDroppers.contains(aiAgent))
@@ -892,7 +909,7 @@ public class MobAI {
if(aiAgent.StrongholdGuardian || aiAgent.StrongholdEpic || aiAgent.StrongholdCommander)
return;
if (aiAgent.despawned && System.currentTimeMillis() > (aiAgent.deathTime + (aiAgent.spawnTime * 1000L))) {
if (System.currentTimeMillis() > (aiAgent.deathTime + (aiAgent.spawnTime * 1000L))) {
if (!Zone.respawnQue.contains(aiAgent)) {
Zone.respawnQue.add(aiAgent);
}
@@ -913,10 +930,8 @@ public class MobAI {
if (mob.getCombatTarget() == null)
return;
if(!mob.isCombat())
enterCombat(mob);
if (mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.PlayerCharacter) && MovementUtilities.inRangeDropAggro(mob, (PlayerCharacter) mob.getCombatTarget()) == false && mob.BehaviourType.ordinal() != Enum.MobBehaviourType.Pet1.ordinal()) {
if (mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.PlayerCharacter) && MovementUtilities.outOfAggroRange(mob, (PlayerCharacter) mob.getCombatTarget()) && mob.BehaviourType.ordinal() != Enum.MobBehaviourType.Pet1.ordinal()) {
mob.setCombatTarget(null);
return;
}
@@ -1068,8 +1083,8 @@ public class MobAI {
if(mob.combatTarget == null)
return;
//if(city._playerMemory.contains(mob.combatTarget.getObjectUUID()) && mob.combatTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter))
// mob.setCombatTarget(null);
if(city._playerMemory.contains(mob.combatTarget.getObjectUUID()) && mob.combatTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter))
mob.setCombatTarget(null);
}
public static void GuardCaptainLogic(Mob mob) {
@@ -1419,11 +1434,4 @@ public class MobAI {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: RecoverHealth" + " " + e.getMessage());
}
}
public static void enterCombat(Mob mob){
mob.setCombat(true);
UpdateStateMsg rwss = new UpdateStateMsg();
rwss.setPlayer(mob);
DispatchMessage.sendToAllInRange(mob, rwss);
}
}
+360
View File
@@ -0,0 +1,360 @@
package engine.mobileAI;
import engine.Enum;
import engine.InterestManagement.WorldGrid;
import engine.gameManager.*;
import engine.mobileAI.Threads.MobAIThread;
import engine.mobileAI.utilities.CombatUtilities;
import engine.mobileAI.utilities.MovementUtilities;
import engine.objects.*;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import java.util.HashSet;
import java.util.concurrent.ThreadLocalRandom;
public class MobAi2 {
public enum State
{
Idle,
Patrolling,
Attacking,
Dead
}
public static boolean Agressive(Mob mob){
return mob.BehaviourType.name().contains("Aggro");
}
public static boolean Caster(Mob mob){
return mob.BehaviourType.name().contains("Power");
}
public static boolean HelpResponder(Mob mob){
return mob.BehaviourType.name().contains("Helpee");
}
public static State getState(Mob mob){
if(!mob.isAlive())
return State.Dead;
if(mob.playerAgroMap.isEmpty())
return State.Idle;
if(mob.combatTarget != null)
return State.Attacking;
return State.Patrolling;
}
public static void runAI(Mob mob){
//these will be handled in special conditions later
switch(mob.BehaviourType){
case GuardCaptain:
case GuardMinion:
case Pet1:
case GuardWallArcher:
case HamletGuard:
case SimpleStandingGuard:
return;
}
switch(getState(mob)){
case Idle:
if(mob.isMoving())
mob.stopMovement(mob.loc);
if(mob.combatTarget != null) {
mob.setCombatTarget(null);
mob.setCombat(false);
}
return;
case Dead:
respawn(mob);
break;
case Patrolling:
patrol(mob);
break;
case Attacking:
attack(mob);
break;
}
}
//handles respawning and de-spawning for mobs and their corpses
public static void respawn(Mob mob){
//if mob doesn't have a death time somehow, set it to now
if (mob.deathTime == 0)
mob.setDeathTime(System.currentTimeMillis());
//only execute this logic is the mob hasn't de-spawned yet
if (!mob.despawned) {
//if the inventory is empty, the mob can disappear
if(mob.getInventory(true).isEmpty() && System.currentTimeMillis() > mob.deathTime + 10000L) {
mob.despawn();
mob.deathTime = System.currentTimeMillis();
return;
}
//if the mob has been dead for 10 seconds it can disappear
if (System.currentTimeMillis() > mob.deathTime + 10000L) {
mob.despawn();
mob.deathTime = System.currentTimeMillis();
return;
}
}
//disc dropper respawns are handled elsewhere
if(Mob.discDroppers.contains(mob))
return;
//if mob isn't queued for respawn, do so now
if (!Zone.respawnQue.contains(mob)) {
if (System.currentTimeMillis() > (mob.deathTime + (mob.spawnTime * 1000L))) {
Zone.respawnQue.add(mob);
}
}
}
//handles patrolling and looking for potential combat targets
public static void patrol(Mob mob){
if(Agressive(mob) && mob.combatTarget == null) {
HashSet<AbstractWorldObject> potentialTargets = WorldGrid.getObjectsInRangePartial(mob.loc, 50, MBServerStatics.MASK_PLAYER);
for (AbstractWorldObject awo : potentialTargets) {
PlayerCharacter target = (PlayerCharacter) awo;
if (mob.canSee(target))
mob.setCombatTarget(target);
if (mob.combatTarget != null) {
return;
}
}
}
if(mob.isMoving() || !mob.BehaviourType.canRoam)
return;
int patrolDelay = ThreadLocalRandom.current().nextInt((int) (MobAIThread.AI_PATROL_DIVISOR * 0.5f), MobAIThread.AI_PATROL_DIVISOR) + MobAIThread.AI_PATROL_DIVISOR;
if (mob.stopPatrolTime + (patrolDelay * 1000L) > System.currentTimeMillis())
return;
if (mob.lastPatrolPointIndex > mob.patrolPoints.size() - 1)
mob.lastPatrolPointIndex = 0;
mob.destination = mob.patrolPoints.get(mob.lastPatrolPointIndex);
mob.lastPatrolPointIndex += 1;
MovementUtilities.aiMove(mob, mob.destination, true);
}
public static void attack(Mob mob){
AbstractWorldObject target = mob.combatTarget;
if (target == null || !target.isAlive()) {
mob.setCombatTarget(null);
return;
}
if(!mob.isCombat())
mob.setCombat(true);
if (!CombatUtilities.inRangeToAttack(mob, target) && mob.BehaviourType.canRoam) {
if(mob.nextChaseUpdate < System.currentTimeMillis()) {
mob.nextChaseUpdate = System.currentTimeMillis() + 2500L;
MovementUtilities.aiMove(mob, target.loc, false);
}
return;
}
switch (target.getObjectType()) {
case PlayerCharacter:
PlayerCharacter targetPlayer = (PlayerCharacter) target;
AttackPlayer(mob, targetPlayer);
break;
case Building:
Building targetBuilding = (Building) target;
AttackBuilding(mob, targetBuilding);
break;
case Mob:
Mob targetMob = (Mob) target;
AttackMob(mob, targetMob);
break;
}
}
public static void AttackPlayer(Mob mob, PlayerCharacter target) {
try {
if (!mob.canSee(target)) {
mob.setCombatTarget(null);
return;
}
if (mob.BehaviourType.callsForHelp)
MobCallForHelp(mob);
if (!MovementUtilities.inRangeDropAggro(mob, target)) {
mob.setCombatTarget(null);
return;
}
if (CombatUtilities.inRange2D(mob, target, mob.getRange())) {
//no weapons, default mob attack speed 3 seconds.
if (System.currentTimeMillis() < mob.getLastAttackTime())
return;
// ranged mobs can't attack while running. skip until they finally stop.
if (mob.isMoving() && mob.getRange() > 20)
return;
// add timer for last attack.
ItemBase mainHand = mob.getWeaponItemBase(true);
ItemBase offHand = mob.getWeaponItemBase(false);
if (mainHand == null && offHand == null) {
CombatUtilities.combatCycle(mob, target, true, null);
int delay = 3000;
if (mob.isSiege())
delay = 11000;
mob.setLastAttackTime(System.currentTimeMillis() + delay);
} else if (mob.getWeaponItemBase(true) != null) {
int delay = 3000;
if (mob.isSiege())
delay = 11000;
CombatUtilities.combatCycle(mob, target, true, mob.getWeaponItemBase(true));
mob.setLastAttackTime(System.currentTimeMillis() + delay);
} else if (mob.getWeaponItemBase(false) != null) {
int attackDelay = 3000;
if (mob.isSiege())
attackDelay = 11000;
CombatUtilities.combatCycle(mob, target, false, mob.getWeaponItemBase(false));
mob.setLastAttackTime(System.currentTimeMillis() + attackDelay);
}
}
if (target.getPet() != null)
if (target.getPet().getCombatTarget() == null && target.getPet().assist)
target.getPet().setCombatTarget(mob);
} catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackPlayer" + " " + e.getMessage());
}
}
public static void AttackBuilding(Mob mob, Building target) {
try {
if(mob == null || target == null)
return;
if (target.getRank() == -1 || !target.isVulnerable() || BuildingManager.getBuildingFromCache(target.getObjectUUID()) == null) {
mob.setCombatTarget(null);
return;
}
City playerCity = ZoneManager.getCityAtLocation(mob.getLoc());
if (playerCity != null)
for (Mob guard : playerCity.getParent().zoneMobSet)
if (guard.BehaviourType != null && guard.BehaviourType.ordinal() == Enum.MobBehaviourType.GuardCaptain.ordinal())
if (guard.getCombatTarget() == null && guard.getGuild() != null && mob.getGuild() != null && !guard.getGuild().equals(mob.getGuild()))
guard.setCombatTarget(mob);
if (mob.isSiege())
MovementManager.sendRWSSMsg(mob);
ItemBase mainHand = mob.getWeaponItemBase(true);
ItemBase offHand = mob.getWeaponItemBase(false);
if (mainHand == null && offHand == null) {
CombatUtilities.combatCycle(mob, target, true, null);
int delay = 3000;
if (mob.isSiege())
delay = 15000;
mob.setLastAttackTime(System.currentTimeMillis() + delay);
} else if (mob.getWeaponItemBase(true) != null) {
int attackDelay = 3000;
if (mob.isSiege())
attackDelay = 15000;
CombatUtilities.combatCycle(mob, target, true, mob.getWeaponItemBase(true));
mob.setLastAttackTime(System.currentTimeMillis() + attackDelay);
} else if (mob.getWeaponItemBase(false) != null) {
int attackDelay = 3000;
if (mob.isSiege())
attackDelay = 15000;
CombatUtilities.combatCycle(mob, target, false, mob.getWeaponItemBase(false));
mob.setLastAttackTime(System.currentTimeMillis() + attackDelay);
}
} catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackBuilding" + " " + e.getMessage());
}
}
public static void AttackMob(Mob mob, Mob target) {
try {
if (mob.getRange() >= 30 && mob.isMoving())
return;
//no weapons, default mob attack speed 3 seconds.
ItemBase mainHand = mob.getWeaponItemBase(true);
ItemBase offHand = mob.getWeaponItemBase(false);
if (mainHand == null && offHand == null) {
CombatUtilities.combatCycle(mob, target, true, null);
int delay = 3000;
if (mob.isSiege())
delay = 11000;
mob.setLastAttackTime(System.currentTimeMillis() + delay);
} else if (mob.getWeaponItemBase(true) != null) {
int attackDelay = 3000;
if (mob.isSiege())
attackDelay = 11000;
CombatUtilities.combatCycle(mob, target, true, mob.getWeaponItemBase(true));
mob.setLastAttackTime(System.currentTimeMillis() + attackDelay);
} else if (mob.getWeaponItemBase(false) != null) {
int attackDelay = 3000;
if (mob.isSiege())
attackDelay = 11000;
CombatUtilities.combatCycle(mob, target, false, mob.getWeaponItemBase(false));
mob.setLastAttackTime(System.currentTimeMillis() + attackDelay);
if (target.getCombatTarget() == null) {
target.setCombatTarget(mob);
}
}
} catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackMob" + " " + e.getMessage());
}
}
public static void MobCallForHelp(Mob mob) {
if (mob.nextCallForHelp == 0)
mob.nextCallForHelp = System.currentTimeMillis();
if (mob.nextCallForHelp > System.currentTimeMillis())
return;
Zone mobCamp = mob.getParentZone();
for (Mob helper : mobCamp.zoneMobSet) {
if (HelpResponder(helper)) {
helper.setCombatTarget(mob.getCombatTarget());
break;
}
}
mob.nextCallForHelp = System.currentTimeMillis() + 30000L;
}
}
+9 -17
View File
@@ -28,26 +28,18 @@ public class MobAIThread implements Runnable{
AI_BASE_AGGRO_RANGE = (int)(60 * Float.parseFloat(ConfigManager.MB_AI_AGGRO_RANGE.getValue()));
while (true) {
for (Zone zone : ZoneManager.getAllZones()) {
if (zone != null && zone.zoneMobSet != null) {
synchronized (zone.zoneMobSet) {
for (Mob mob : zone.zoneMobSet) {
try {
if (mob != null) {
MobAI.DetermineAction(mob);
}
} catch (Exception e) {
Logger.error("Error processing Mob [Name: {}, UUID: {}]", mob.getName(), mob.getObjectUUID(), e);
}
}
for (Mob mob : zone.zoneMobSet) {
try {
if (mob != null)
MobAI.DetermineAction(mob);
} catch (Exception e) {
Logger.error("Mob: " + mob.getName() + " UUID: " + mob.getObjectUUID() + " ERROR: " + e);
e.printStackTrace();
}
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Logger.error("AI Thread interrupted", e);
Thread.currentThread().interrupt();
}
}
}
public static void startAIThread() {
@@ -8,14 +8,13 @@
package engine.mobileAI.Threads;
import engine.InterestManagement.InterestManager;
import engine.InterestManagement.WorldGrid;
import engine.gameManager.ZoneManager;
import engine.objects.Mob;
import engine.objects.Zone;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
import java.util.Collection;
/**
* Thread blocks until MagicBane dispatch messages are
* enqueued then processes them in FIFO order. The collection
@@ -28,48 +27,43 @@ import java.util.Collection;
public class MobRespawnThread implements Runnable {
private volatile boolean running = true;
private static final long RESPAWN_INTERVAL = 100; // Configurable interval
public MobRespawnThread() {
Logger.info("MobRespawnThread initialized.");
Logger.info(" MobRespawnThread thread has started!");
}
@Override
public void run() {
while (running) {
try {
Collection<Zone> zones = ZoneManager.getAllZones();
if (zones != null) {
for (Zone zone : zones) {
synchronized (zone) { // Optional: Synchronize on zone
if (!zone.respawnQue.isEmpty() &&
zone.lastRespawn + RESPAWN_INTERVAL < System.currentTimeMillis()) {
Mob respawner = zone.respawnQue.iterator().next();
if (respawner != null) {
respawner.respawn();
zone.respawnQue.remove(respawner);
zone.lastRespawn = System.currentTimeMillis();
}
}
}
while (true) {
try {
for (Zone zone : ZoneManager.getAllZones()) {
if (zone.respawnQue.isEmpty() == false && 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();
WorldGrid.updateObject(respawner);
InterestManager.setObjectDirty(respawner);
}
}
Thread.sleep(100); // Prevent busy-waiting
} catch (Exception e) {
Logger.error("Error in MobRespawnThread", e);
Logger.error(e);
}
}
Logger.info("MobRespawnThread stopped.");
}
public void stop() {
running = false;
}
public static void startRespawnThread() {
Thread respawnThread = new Thread(new MobRespawnThread());
Thread respawnThread;
respawnThread = new Thread(new MobRespawnThread());
respawnThread.setName("respawnThread");
respawnThread.start();
}
@@ -140,11 +140,7 @@ public class CombatUtilities {
public static boolean triggerDefense(Mob agent, AbstractWorldObject target) {
int defense = 0;
int atr = agent.mobBase.getAtr();
if(agent.getBonuses() != null){
atr += agent.getBonuses().getFloat(ModType.OCV,SourceType.None);
atr *= 1 + agent.getBonuses().getFloatPercentAll(ModType.OCV,SourceType.None);
}
int atr = agent.getAtrHandOne();
switch (target.getObjectType()) {
case PlayerCharacter:
defense = ((AbstractCharacter) target).getDefenseRating();
@@ -256,12 +252,12 @@ public class CombatUtilities {
if (agent.getEquip().get(1) != null && agent.getEquip().get(2) != null && agent.getEquip().get(2).getItemBase().isShield() == false) {
//mob is duel wielding and should conduct an attack for each hand
ItemBase weapon1 = agent.getEquip().get(1).getItemBase();
double range1 = getMaxDmg(agent) - getMinDmg(agent);
double damage1 = getMinDmg(agent) + ((ThreadLocalRandom.current().nextFloat() * range1) + (ThreadLocalRandom.current().nextFloat() * range1)) / 2;
double range1 = getMaxDmg(weapon1.getMinDamage(), agent, weapon1) - getMinDmg(weapon1.getMinDamage(), agent, weapon1);
double damage1 = getMinDmg(weapon1.getMinDamage(), agent, weapon1) + ((ThreadLocalRandom.current().nextFloat() * range1) + (ThreadLocalRandom.current().nextFloat() * range1)) / 2;
swingIsDamage(agent, target, (float) damage1, CombatManager.getSwingAnimation(weapon1, null, true));
ItemBase weapon2 = agent.getEquip().get(2).getItemBase();
double range2 = getMaxDmg(agent) - getMinDmg(agent);
double damage2 = getMinDmg(agent) + ((ThreadLocalRandom.current().nextFloat() * range2) + (ThreadLocalRandom.current().nextFloat() * range2)) / 2;
double range2 = getMaxDmg(weapon2.getMinDamage(), agent, weapon2) - getMinDmg(weapon2.getMinDamage(), agent, weapon2);
double damage2 = getMinDmg(weapon2.getMinDamage(), agent, weapon2) + ((ThreadLocalRandom.current().nextFloat() * range2) + (ThreadLocalRandom.current().nextFloat() * range2)) / 2;
swingIsDamage(agent, target, (float) damage2, CombatManager.getSwingAnimation(weapon1, null, false));
} else {
swingIsDamage(agent, target, determineDamage(agent), anim);
@@ -311,9 +307,9 @@ public class CombatUtilities {
float damage = 0;
DamageType dt = getDamageType(agent);
if (agent.BehaviourType.equals(MobBehaviourType.Pet1)) {
damage = calculateMobDamage(agent);
} else if (agent.isPlayerGuard()) {
if ((agent.agentType.equals(AIAgentType.PET)) == true || agent.isPet() == true || agent.isNecroPet() == true) {
damage = calculatePetDamage(agent);
} else if (agent.isPlayerGuard() == true) {
//damage = calculateGuardDamage(agent);
damage = calculateMobDamage(agent);
} else if (agent.getLevel() > 80) {
@@ -353,8 +349,8 @@ public class CombatUtilities {
float min = 40;
float max = 60;
float dmgMultiplier = 1 + agent.getBonuses().getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.None);
double minDmg = getMinDmg(agent);
double maxDmg = getMaxDmg(agent);
double minDmg = getMinDmg(min, agent, null);
double maxDmg = getMaxDmg(max, agent, null);
dmgMultiplier += agent.getLevel() * 0.1f;
range = (float) (maxDmg - minDmg);
damage = min + ((ThreadLocalRandom.current().nextFloat() * range) + (ThreadLocalRandom.current().nextFloat() * range)) / 2;
@@ -370,8 +366,8 @@ public class CombatUtilities {
double minDmg = weapon.getMinDamage();
double maxDmg = weapon.getMaxDamage();
double min = getMinDmg(agent);
double max = getMaxDmg(agent);
double min = getMinDmg(minDmg, agent, weapon);
double max = getMaxDmg(maxDmg, agent, weapon);
DamageType dt = weapon.getDamageType();
@@ -412,48 +408,92 @@ public class CombatUtilities {
}
public static int calculateMobDamage(Mob agent) {
double minDmg = getMinDmg(agent);
double maxDmg = getMaxDmg(agent);
DamageType dt = getDamageType(agent);
ItemBase weapon = null;
double minDmg;
double maxDmg;
DamageType dt;
//main hand or offhand damage
if (agent.getEquip().get(1) != null)
weapon = agent.getEquip().get(1).getItemBase();
else if (agent.getEquip().get(2) != null)
weapon = agent.getEquip().get(2).getItemBase();
if (weapon != null) {
minDmg = getMinDmg(weapon.getMinDamage(), agent, weapon);
maxDmg = getMaxDmg(weapon.getMaxDamage(), agent, weapon);
dt = weapon.getDamageType();
} else {
minDmg = agent.getMobBase().getDamageMin();
maxDmg = agent.getMobBase().getDamageMax();
dt = DamageType.Crush;
}
AbstractWorldObject target = agent.getCombatTarget();
double damage = ThreadLocalRandom.current().nextInt((int)minDmg,(int)maxDmg + 1);
float dmgMultiplier = 1 + agent.getBonuses().getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.None);
double range = maxDmg - minDmg;
double damage = minDmg + ((ThreadLocalRandom.current().nextFloat() * range) + (ThreadLocalRandom.current().nextFloat() * range)) / 2;
if (AbstractWorldObject.IsAbstractCharacter(target))
if (((AbstractCharacter) target).isSit())
damage *= 2.5f; //increase damage if sitting
if (AbstractWorldObject.IsAbstractCharacter(target))
return (int) (((AbstractCharacter) target).getResists().getResistedDamage(agent, (AbstractCharacter) target, dt, (float) damage, 0));
return (int) (((AbstractCharacter) target).getResists().getResistedDamage(agent, (AbstractCharacter) target, dt, (float) damage, 0) * dmgMultiplier);
return 0;
}
public static double getMinDmg(Mob agent) {
if(agent.getEquip() != null){
if(agent.getEquip().get(ItemSlotType.RHELD) != null){
return agent.minDamageHandOne;
}else if(agent.getEquip().get(ItemSlotType.LHELD) != null){
return agent.getMinDamageHandTwo();
}else{
return agent.minDamageHandOne;
public static double getMinDmg(double min, Mob agent, ItemBase weapon) {
int primary = agent.getStatStrCurrent();
int secondary = agent.getStatDexCurrent();
int focusLevel = 0;
int masteryLevel = 0;
if (weapon != null) {
if (weapon.isStrBased() == true) {
primary = agent.getStatStrCurrent();
secondary = agent.getStatDexCurrent();
} else {
primary = agent.getStatDexCurrent();
secondary = agent.getStatStrCurrent();
if (agent.getSkills().containsKey(weapon.getSkillRequired())) {
focusLevel = (int) agent.getSkills().get(weapon.getSkillRequired()).getModifiedAmount();
}
if (agent.getSkills().containsKey(weapon.getMastery())) {
masteryLevel = (int) agent.getSkills().get(weapon.getMastery()).getModifiedAmount();
}
}else{
return agent.minDamageHandOne;
}
}
return min * (pow(0.0048 * primary + .049 * (primary - 0.75), 0.5) + pow(0.0066 * secondary + 0.064 * (secondary - 0.75), 0.5) + +0.01 * (focusLevel + masteryLevel));
}
public static double getMaxDmg(Mob agent) {
if(agent.getEquip() != null){
if(agent.getEquip().get(ItemSlotType.RHELD) != null){
return agent.maxDamageHandOne;
}else if(agent.getEquip().get(ItemSlotType.LHELD) != null){
return agent.getMaxDamageHandTwo();
}else{
return agent.maxDamageHandOne;
}
}else{
return agent.maxDamageHandOne;
public static double getMaxDmg(double max, Mob agent, ItemBase weapon) {
int primary = agent.getStatStrCurrent();
int secondary = agent.getStatDexCurrent();
int focusLevel = 0;
int masteryLevel = 0;
if (weapon != null) {
if (weapon.isStrBased() == true) {
primary = agent.getStatStrCurrent();
secondary = agent.getStatDexCurrent();
} else {
primary = agent.getStatDexCurrent();
secondary = agent.getStatStrCurrent();
}
if (agent.getSkills().containsKey(weapon.getSkillRequired()))
focusLevel = (int) agent.getSkills().get(weapon.getSkillRequired()).getModifiedAmount();
if (agent.getSkills().containsKey(weapon.getSkillRequired()))
masteryLevel = (int) agent.getSkills().get(weapon.getMastery()).getModifiedAmount();
}
return max * (pow(0.0124 * primary + 0.118 * (primary - 0.75), 0.5) + pow(0.0022 * secondary + 0.028 * (secondary - 0.75), 0.5) + 0.0075 * (focusLevel + masteryLevel));
}
}
@@ -98,24 +98,20 @@ public class MovementUtilities {
}
public static boolean outOfAggroRange(Mob agent, AbstractCharacter target) {
public static boolean inRangeDropAggro(Mob agent, AbstractCharacter target) {
Vector3fImmutable sl = agent.getLoc();
Vector3fImmutable tl = target.getLoc();
float disSq = sl.distanceSquared(tl);
float distanceSquaredToTarget = sl.distanceSquared2D(tl) - sqr(agent.calcHitBox() + target.calcHitBox()); //distance to center of target
float range = agent.getRange() + 150;
//float distanceSquaredToTarget = sl.distanceSquared2D(tl) - sqr(agent.calcHitBox() + target.calcHitBox()); //distance to center of target
if (range > 200)
range = 200;
return disSq > (range * range);
return distanceSquaredToTarget < sqr(range);
}
+4 -4
View File
@@ -227,10 +227,10 @@ public class ClientConnection extends AbstractConnection {
SessionManager.remSession(
SessionManager.getSession(sessionID));
} catch (NullPointerException e) {
//Logger
//.error(
//"Tried to remove improperly initialized session. Skipping." +
//e);
Logger
.error(
"Tried to remove improperly initialized session. Skipping." +
e);
}
}
@@ -78,7 +78,7 @@ public class ActivateNPCMsgHandler extends AbstractClientMsgHandler {
return false;
}
if (building.getBlueprint().getMaxSlots() == building.getHirelings().size() && building.getRank() != 8)
if (building.getBlueprint().getMaxSlots() == building.getHirelings().size())
return false;
Item contractItem = Item.getFromCache(msg.getContractItem());
@@ -9,7 +9,6 @@
package engine.net.client.handlers;
import engine.Enum;
import engine.Enum.DispatchChannel;
import engine.exception.MsgSendException;
import engine.net.DispatchMessage;
@@ -43,9 +42,6 @@ public class ChangeAltitudeHandler extends AbstractClientMsgHandler {
if (!AbstractCharacter.CanFly(pc))
return false;
if(pc.getBonuses().getBool(Enum.ModType.Stunned, Enum.SourceType.None))
return false;
if (pc.isSwimming())
return false;
if (pc.region != null && !pc.region.isOutside())
@@ -346,6 +346,7 @@ public class ObjectActionMsgHandler extends AbstractClientMsgHandler {
pam.setY(loc.getY());
pam.setZ(loc.getZ() + 64); //offset grid from tol
pam.addPlacementInfo(ib.getUseID());
dispatch = Dispatch.borrow(player, pam);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
@@ -11,7 +11,6 @@ import engine.db.archive.DataWarehouse;
import engine.exception.MsgSendException;
import engine.gameManager.*;
import engine.math.Bounds;
import engine.math.Vector3f;
import engine.math.Vector3fImmutable;
import engine.net.Dispatch;
import engine.net.DispatchMessage;
@@ -139,7 +138,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
private static boolean validateBuildingPlacement(Zone serverZone, PlaceAssetMsg msg, ClientConnection origin, PlayerCharacter player, PlacementInfo placementInfo) {
if (serverZone.isPlayerCity() == false && !player.getName().equals("FatBoy")) {
if (serverZone.isPlayerCity() == false) {
PlaceAssetMsg.sendPlaceAssetError(origin, 52, player.getName());
return false;
}
@@ -330,24 +329,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
playerCharacter = SessionManager.getPlayerCharacter(origin);
if(playerCharacter.getAccount().status.equals(AccountStatus.ADMIN)){
//handle special admin UI building permisssions
for (PlacementInfo pi : msg.getPlacementInfo()) {
int ID = pi.getBlueprintUUID();
Zone zone = ZoneManager.findSmallestZone(pi.getLoc());
Blueprint blueprint = Blueprint.getBlueprint(ID);
Vector3fImmutable localLoc = ZoneManager.worldToLocal(pi.getLoc(), zone);
Building building = DbManager.BuildingQueries.CREATE_BUILDING(zone.getObjectUUID(), 0, blueprint.getName(), ID, localLoc, 1.0f, 0, ProtectionState.PROTECTED, 0, 1, null, ID, msg.getFirstPlacementInfo().getW(), msg.getFirstPlacementInfo().getRot().y);
building.setObjectTypeMask(MBServerStatics.MASK_BUILDING);
building.setRot(new Vector3f(pi.getRot().x, pi.getRot().y, pi.getRot().z));
building.setw(pi.getW());
WorldGrid.addObject(building, playerCharacter);
ChatManager.chatSayInfo(playerCharacter, "Building with ID " + building.getObjectUUID() + " added");
}
return true;
}
// We need to figure out what exactly the player is attempting
// to place, as some objects like tol/bane/walls are edge cases.
// So let's get the first item in their list.
@@ -1167,15 +1148,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
wallPiece.setProtectionState(ProtectionState.PROTECTED);
PlaceAssetMsg.sendPlaceAssetConfirmWall(origin, serverZone);
//walls in R8 city are immediately granted extra HP by 10%
if(cityObject.getTOL().getRank() == 8) {
if (wallPiece.getBlueprint() != null && wallPiece.getBlueprint().getBuildingGroup() != null && wallPiece.getBlueprint().isWallPiece()) {
float currentHealthRatio = wallPiece.getCurrentHitpoints() / wallPiece.healthMax;
float newMax = wallPiece.healthMax * 1.1f;
wallPiece.setMaxHitPoints(newMax);
wallPiece.setHealth(wallPiece.healthMax * currentHealthRatio);
}
}
}
// Deduct gold from character's inventory
+5 -11
View File
@@ -202,7 +202,7 @@ public class ApplyRuneMsg extends ClientNetMsg {
for (CharacterRune cr : runes) {
int runeBaseID = cr.getRuneBaseID();
//count number of discipline runes
if(isDiscipline(runeBaseID)){
if (runeBaseID > 3000 && runeBaseID < 3049) {
discCount++;
}
//see if rune is already applied
@@ -331,29 +331,23 @@ public class ApplyRuneMsg extends ClientNetMsg {
break;
}
//if discipline, check number applied
int discAllowed = 0;
if (isDiscipline(runeID)) {
switch(playerCharacter.getRank()){
case 1:
discAllowed = 0;
break;
case 2:
case 3:
case 4:
case 5:
case 6:
discAllowed = 3;
if(discCount > 3)
return false;
break;
case 7:
discAllowed = 4;
break;
case 8:
discAllowed = 5;
if(discCount > 5)
return false;
break;
}
if(discCount >= discAllowed)
return false;
}
//Everything succeeded. Let's apply the rune
//Attempt add rune to database
+10 -20
View File
@@ -11,7 +11,6 @@ package engine.net.client.msg;
import engine.Enum.DispatchChannel;
import engine.Enum.GuildHistoryType;
import engine.QuestSystem.QuestManager;
import engine.exception.MsgSendException;
import engine.gameManager.BuildingManager;
import engine.gameManager.DbManager;
@@ -126,22 +125,18 @@ public class VendorDialogMsg extends ClientNetMsg {
vd = Contract.HandleBaneCommanderOptions(msg.unknown03, npc, playerCharacter);
msg.updateMessage(3, vd);
}else {
if(QuestManager.grantsQuest(npc)){
vd = Contract.HandleQuestOptions(msg.unknown03, npc, playerCharacter);
msg.updateMessage(3, vd);
}else {
if (contract == null)
if (contract == null)
vd = VendorDialog.getHostileVendorDialog();
else if (npc.getBuilding() != null) {
if (npc.getBuilding() != null && BuildingManager.IsPlayerHostile(npc.getBuilding(), playerCharacter))
vd = VendorDialog.getHostileVendorDialog();
else if (npc.getBuilding() != null) {
if (npc.getBuilding() != null && BuildingManager.IsPlayerHostile(npc.getBuilding(), playerCharacter))
vd = VendorDialog.getHostileVendorDialog();
else
vd = contract.getVendorDialog();
} else
else
vd = contract.getVendorDialog();
if (vd == null)
vd = VendorDialog.getHostileVendorDialog();
}
} else
vd = contract.getVendorDialog();
if (vd == null)
vd = VendorDialog.getHostileVendorDialog();
if (msg.messageType == 1 || msg.unknown03 == vd.getObjectUUID()) {
msg.updateMessage(3, vd);
} else {
@@ -636,11 +631,6 @@ public class VendorDialogMsg extends ClientNetMsg {
.getObjectUUID(), true);
DispatchMessage.dispatchMsgToInterestArea(pc, arm, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
if(pc.getCharItemManager() != null && pc.getCharItemManager().getGoldInventory() != null && pc.getCharItemManager().getGoldInventory().getNumOfItems() < 1000) {
pc.getCharItemManager().addGoldToInventory(1000, false);
pc.getCharItemManager().addItemToInventory(new MobLoot(pc, ItemBase.getItemBase(980066), 1, false).promoteToItem(pc));
pc.getCharItemManager().updateInventory();
}
}
@@ -63,9 +63,6 @@ public class WhoResponseMsg extends ClientNetMsg {
public static void HandleResponse(int set, int filterType, String filter, ClientConnection origin) {
if (filter.equals("")) {
filter = "Saetor";
}
WhoResponseMsg msg = new WhoResponseMsg();
WhoResponseMsg.setWorldPop(SessionManager.getAllActivePlayerCharacters().size());
+9 -1
View File
@@ -500,6 +500,7 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
canFly = false;
}
return canFly;
}
@@ -1101,7 +1102,7 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
}
public final void setCombatTarget(final AbstractWorldObject value) {
if (this.getObjectTypeMask() == 2050) {//MOB?
if(this.getObjectTypeMask() == 2050) {//MOB?
if (value == null) {
if (this.isCombat()) {
this.setCombat(false);
@@ -1109,6 +1110,13 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
rwss.setPlayer(this);
DispatchMessage.sendToAllInRange(this, rwss);
}
}else {
if (!this.isCombat()) {
this.setCombat(true);
UpdateStateMsg rwss = new UpdateStateMsg();
rwss.setPlayer(this);
DispatchMessage.sendToAllInRange(this, rwss);
}
}
}
this.combatTarget = value;
+22 -14
View File
@@ -428,24 +428,32 @@ public final class Bane {
// Cache access
public void setDefaultTime() {
private void setDefaultTime() {
DateTime timeToSetDefault = new DateTime(this.placementDate);
timeToSetDefault = timeToSetDefault.plusDays(1);
if (DateTime.now().isAfter(timeToSetDefault)){
if(!this.capSet){
DbManager.BaneQueries.SET_BANE_CAP_NEW(20,this.getCityUUID());
this.capSet = true;
}
if(!this.daySet){
DbManager.BaneQueries.SET_BANE_DAY_NEW(3,this.getCityUUID());
this.daySet = true;
}
if(!this.timeSet){
DbManager.BaneQueries.SET_BANE_TIME_NEW(9,this.getCityUUID());
this.timeSet = true;
}
DateTime currentTime = DateTime.now();
DateTime defaultTime = new DateTime(this.placementDate);
defaultTime = defaultTime.plusDays(2);
defaultTime = defaultTime.hourOfDay().setCopy(22);
defaultTime = defaultTime.minuteOfHour().setCopy(0);
defaultTime = defaultTime.secondOfMinute().setCopy(0);
if (currentTime.isAfter(timeToSetDefault)){
DbManager.BaneQueries.SET_BANE_CAP_NEW(20,this.getCityUUID());
DbManager.BaneQueries.SET_BANE_TIME_NEW(9,this.getCityUUID());
DbManager.BaneQueries.SET_BANE_DAY_NEW(3,this.getCityUUID());
}
//this.setLiveDate(defaultTime);
else {
if (this.defaultTimeJob != null)
this.defaultTimeJob.cancelJob();
BaneDefaultTimeJob bdtj = new BaneDefaultTimeJob(this);
JobScheduler.getInstance().scheduleJob(bdtj, timeToSetDefault.getMillis());
this.defaultTimeJob = bdtj;
}
}
-4
View File
@@ -360,10 +360,6 @@ this.maxRank = rs.getInt("MaxRank");
return 3;
}
if(bg != null && bg.equals(BuildingGroup.TOL) && currentRank == 8){
return 5;
}
if (this.maxRank == 1 && currentRank == 1)
return getMaxSlots();
+7 -32
View File
@@ -160,16 +160,23 @@ public class Building extends AbstractWorldObject {
// in City resulting in a stack ovreflow.
if (blueprint != null) {
// Only switch mesh for player dropped structures
if (this.blueprintUUID != 0)
this.meshUUID = blueprint.getMeshForRank(rank);
this.healthMax = blueprint.getMaxHealth(this.rank);
// If this object has no blueprint but is a blueprint
// mesh then set it's current health to max health
if (this.blueprintUUID == 0)
this.setHealth(healthMax);
if (blueprint.getBuildingGroup().equals(BuildingGroup.BARRACK))
this.patrolPoints = DbManager.BuildingQueries.LOAD_PATROL_POINTS(this);
} else {
this.healthMax = 100000; // Structures with no blueprint mesh
this.setHealth(healthMax);
@@ -412,22 +419,6 @@ public class Building extends AbstractWorldObject {
this.healthMax = this.getBlueprint().getMaxHealth(this.rank);
this.setCurrentHitPoints(this.healthMax);
if(!this.ownerIsNPC && this.getBlueprint() != null && this.getBlueprint().isWallPiece()){
//add extra HP for city walls of R8 trees
City city = ZoneManager.getCityAtLocation(this.loc);
if(city != null){
Building ToL = city.getTOL();
if(ToL != null){
if(ToL.rank == 8){
float currentHealth = this.health.get();
float newHealth = (currentHealth/this.healthMax) * (this.healthMax * 1.1f);
this.healthMax *= 1.1f;
this.setHealth(newHealth);
}
}
}
}
if (this.getUpgradeDateTime() != null)
BuildingManager.setUpgradeDateTime(this, null, 0);
@@ -1137,22 +1128,6 @@ public class Building extends AbstractWorldObject {
}
}
if(!this.ownerIsNPC && this.getBlueprint() != null && this.getBlueprint().isWallPiece()){
//add extra HP for city walls of R8 trees
City city = ZoneManager.getCityAtLocation(this.loc);
if(city != null){
Building ToL = city.getTOL();
if(ToL != null){
if(ToL.rank == 8){
float currentHealth = this.health.get();
float newHealth = (currentHealth/this.healthMax) * (this.healthMax * 1.1f);
this.healthMax *= 1.1f;
this.setHealth(newHealth);
}
}
}
}
// Set bounds for this building
Bounds buildingBounds = Bounds.borrow();
-16
View File
@@ -11,7 +11,6 @@ package engine.objects;
import ch.claude_martin.enumbitset.EnumBitSet;
import engine.Enum;
import engine.QuestSystem.QuestManager;
import engine.gameManager.*;
import engine.net.Dispatch;
import engine.net.DispatchMessage;
@@ -478,21 +477,6 @@ public class Contract extends AbstractGameObject {
return vd;
}
public static VendorDialog HandleQuestOptions(int optionId, NPC npc, PlayerCharacter pc){
VendorDialog vd = new VendorDialog(npc.contract.getVendorDialog().getDialogType(),npc.contract.getVendorDialog().getIntro(),-1);
//vd.getOptions().clear();
switch(optionId) {
default:
MenuOption optionAcceptQuest = new MenuOption(25020401, "Accept Quest", 25020401);
vd.getOptions().add(optionAcceptQuest);
break;
case 25020401:
QuestManager.acceptQuest(pc,QuestManager.getQuestForContract(npc));
break;
}
return vd;
}
public ArrayList<Integer> getNPCMenuOptions() {
return this.npcMenuOptions;
}
-3
View File
@@ -349,9 +349,6 @@ public class Experience {
if(killer.equals(mob))
return;
if(killer.pvpKills.contains(mob.getObjectUUID()))
return;
double grantedExperience = 0.0;
if (g != null) { // Do group EXP stuff
+236 -113
View File
@@ -14,7 +14,6 @@ import engine.Enum;
import engine.Enum.*;
import engine.InterestManagement.InterestManager;
import engine.InterestManagement.WorldGrid;
import engine.QuestSystem.QuestManager;
import engine.exception.SerializationException;
import engine.gameManager.*;
import engine.job.JobScheduler;
@@ -25,6 +24,7 @@ import engine.math.Quaternion;
import engine.math.Vector3f;
import engine.math.Vector3fImmutable;
import engine.mobileAI.Threads.MobAIThread;
import engine.mobileAI.utilities.MovementUtilities;
import engine.net.ByteBufferWriter;
import engine.net.Dispatch;
import engine.net.DispatchMessage;
@@ -84,6 +84,7 @@ public class Mob extends AbstractIntelligenceAgent {
public int lastPatrolPointIndex = 0;
public long stopPatrolTime = 0;
public City guardedCity;
public long nextChaseUpdate = 0;
protected int dbID; //the database ID
protected int loadID;
protected float spawnRadius;
@@ -1272,15 +1273,6 @@ public class Mob extends AbstractIntelligenceAgent {
// Give XP, now handled inside the Experience Object
if (!this.isPet() && !this.isNecroPet() && !(this.agentType.equals(AIAgentType.PET)) && !this.isPlayerGuard)
Experience.doExperience((PlayerCharacter) attacker, this, g);
//handle quest updates
PlayerCharacter pc = (PlayerCharacter)attacker;
if(QuestManager.acceptedQuests.containsKey(pc)){
QuestManager.acceptedQuests.get(pc).tryProgress(this.firstName);
QuestManager.completeQuest(pc,QuestManager.acceptedQuests.get(pc));
}
} else if (attacker.getObjectType().equals(GameObjectType.Mob)) {
Mob mobAttacker = (Mob) attacker;
@@ -1452,14 +1444,23 @@ public class Mob extends AbstractIntelligenceAgent {
loadInventory();
this.updateLocation();
this.stopPatrolTime = 0;
this.lastPatrolPointIndex = 0;
reloadAgroMap(this);
}
private static void reloadAgroMap(Mob mob){
mob.playerAgroMap.clear();
for(AbstractWorldObject obj : WorldGrid.getObjectsInRangePartial(mob.loc,MBServerStatics.CHARACTER_LOAD_RANGE,1)){
if(!mob.playerAgroMap.containsKey(obj.getObjectUUID())){
mob.playerAgroMap.put(obj.getObjectUUID(),false);
}
}
}
public void despawn() {
this.despawned = true;
this.stopPatrolTime = System.currentTimeMillis();
WorldGrid.RemoveWorldObject(this);
this.charItemManager.clearInventory();
@@ -1648,66 +1649,66 @@ public class Mob extends AbstractIntelligenceAgent {
this.defenseRating = defense;
this.atrHandOne = atr;
return;
}else {
if (this.charItemManager == null || this.equip == null) {
Logger.error("Player " + currentID + " missing skills or equipment");
defaultAtrAndDamage(true);
defaultAtrAndDamage(false);
this.defenseRating = 0;
return;
}
try {
calculateAtrDamageForWeapon(this.equip.get(MBServerStatics.SLOT_MAINHAND), true);
} catch (Exception e) {
this.atrHandOne = GetAttackRating(this.mobBase.getAttackRating(), this);
this.minDamageHandOne = (short) this.mobBase.getDamageMin();
this.maxDamageHandOne = (short) this.mobBase.getDamageMax();
this.rangeHandOne = 6.5f;
this.speedHandOne = 20;
Logger.info("Mobbase ID " + this.getMobBaseID() + " returned an error. setting to default ATR and Damage." + e.getMessage());
}
try {
calculateAtrDamageForWeapon(this.equip.get(MBServerStatics.SLOT_OFFHAND), false);
} catch (Exception e) {
this.atrHandTwo = GetAttackRating(this.mobBase.getAttackRating(), this);
this.minDamageHandTwo = (short) this.mobBase.getDamageMin();
this.maxDamageHandTwo = (short) this.mobBase.getDamageMax();
this.rangeHandTwo = 6.5f;
this.speedHandTwo = 20;
Logger.info("Mobbase ID " + this.getMobBaseID() + " returned an error. setting to default ATR and Damage." + e.getMessage());
}
try {
float defense = this.mobBase.getDefenseRating();
defense += getShieldDefense(equip.get(MBServerStatics.SLOT_OFFHAND));
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_HELMET));
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_CHEST));
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_ARMS));
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_GLOVES));
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_LEGGINGS));
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_FEET));
defense += getWeaponDefense(equip);
// TODO add error log here
if (this.bonuses != null) {
defense = GetDefense((int) defense, this);
} else
Logger.error("Error: missing bonuses");
defense = (defense < 1) ? 1 : defense;
this.defenseRating = (short) (defense + 0.5f);
} catch (Exception e) {
Logger.info("Mobbase ID " + this.getMobBaseID() + " returned an error. Setting to Default Defense." + e.getMessage());
this.defenseRating = (short) this.mobBase.getDefense();
}
// calculate defense for equipment
}
if (this.charItemManager == null || this.equip == null) {
Logger.error("Player " + currentID + " missing skills or equipment");
defaultAtrAndDamage(true);
defaultAtrAndDamage(false);
this.defenseRating = 0;
return;
}
try {
calculateAtrDamageForWeapon(this.equip.get(MBServerStatics.SLOT_MAINHAND), true);
} catch (Exception e) {
this.atrHandOne = GetAttackRating(this.mobBase.getAttackRating(), this);
this.minDamageHandOne = (short) this.mobBase.getMinDmg();
this.maxDamageHandOne = (short) this.mobBase.getMaxDmg();
this.rangeHandOne = 6.5f;
this.speedHandOne = 20;
Logger.info("Mobbase ID " + this.getMobBaseID() + " returned an error. setting to default ATR and Damage." + e.getMessage());
}
try {
calculateAtrDamageForWeapon(this.equip.get(MBServerStatics.SLOT_OFFHAND), false);
} catch (Exception e) {
this.atrHandTwo = GetAttackRating(this.mobBase.getAttackRating(), this);
this.minDamageHandTwo = (short) this.mobBase.getMinDmg();
this.maxDamageHandTwo = (short) this.mobBase.getMaxDmg();
this.rangeHandTwo = 6.5f;
this.speedHandTwo = 20;
Logger.info("Mobbase ID " + this.getMobBaseID() + " returned an error. setting to default ATR and Damage." + e.getMessage());
}
try {
float defense = this.mobBase.getDefenseRating();
defense += getShieldDefense(equip.get(MBServerStatics.SLOT_OFFHAND));
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_HELMET));
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_CHEST));
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_ARMS));
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_GLOVES));
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_LEGGINGS));
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_FEET));
defense += getWeaponDefense(equip);
// TODO add error log here
if (this.bonuses != null) {
defense = GetDefense((int)defense, this);
} else
Logger.error("Error: missing bonuses");
defense = (defense < 1) ? 1 : defense;
this.defenseRating = (short) (defense + 0.5f);
} catch (Exception e) {
Logger.info("Mobbase ID " + this.getMobBaseID() + " returned an error. Setting to Default Defense." + e.getMessage());
this.defenseRating = (short) this.mobBase.getDefense();
}
// calculate defense for equipment
if(this.isDropper || Mob.discDroppers.contains(this)){
this.defenseRating *= 2;
this.atrHandOne *= 2;
@@ -1852,46 +1853,168 @@ public class Mob extends AbstractIntelligenceAgent {
private void calculateAtrDamageForWeapon(MobEquipment weapon, boolean mainHand) {
if(mainHand){
int min = (int)this.mobBase.getDamageMin();
int max = (int)this.mobBase.getDamageMax();
int atr = this.mobBase.getAtr();
if(this.bonuses != null){
min *= 1 + this.bonuses.getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.None);
max *= 1 + this.bonuses.getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.None);
atr *= 1 + this.bonuses.getFloatPercentAll(ModType.OCV,SourceType.None);
atr += this.bonuses.getFloat(ModType.OCV,SourceType.None);
}
this.minDamageHandOne = min;
this.maxDamageHandOne = max;
this.atrHandOne = atr;
if(weapon == null){
int baseStrength = 0;
float skillPercentage, masteryPercentage;
float mastDam;
// make sure weapon exists
boolean noWeapon = false;
ItemBase wb = null;
if (weapon == null)
noWeapon = true;
else {
ItemBase ib = weapon.getItemBase();
if (ib == null)
noWeapon = true;
else if (ib.getType().equals(ItemType.WEAPON) == false) {
defaultAtrAndDamage(mainHand);
return;
} else
wb = ib;
}
float min, max;
float speed;
boolean strBased = false;
// get skill percentages and min and max damage for weapons
if (noWeapon) {
if (mainHand)
this.rangeHandOne = this.mobBase.getAttackRange();
this.speedHandTwo = 20.0f;
}else{
this.rangeHandOne = weapon.getItemBase().getRange();
this.speedHandTwo = weapon.getItemBase().getSpeed();
}
}else{
int min = (int)this.mobBase.getDamageMin();
int max = (int)this.mobBase.getDamageMax();
int atr = this.mobBase.getAtr();
if(this.bonuses != null){
min *= 1 + this.bonuses.getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.None);
max *= 1 + this.bonuses.getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.None);
atr *= 1 + this.bonuses.getFloatPercentAll(ModType.OCV,SourceType.None);
atr += this.bonuses.getFloat(ModType.OCV,SourceType.None);
}
this.minDamageHandTwo = min;
this.maxDamageHandTwo = max;
this.atrHandTwo = atr;
if(weapon == null){
this.rangeHandTwo = this.mobBase.getAttackRange();
this.speedHandTwo = 20.0f;
}else{
this.rangeHandTwo = weapon.getItemBase().getRange();
this.speedHandTwo = weapon.getItemBase().getSpeed();
}
else
this.rangeHandTwo = -1; // set to do not attack
skillPercentage = getModifiedAmount(this.skills.get("Unarmed Combat"));
masteryPercentage = getModifiedAmount(this.skills.get("Unarmed Combat Mastery"));
if (masteryPercentage == 0f)
mastDam = CharacterSkill.getQuickMastery(this, "Unarmed Combat Mastery");
else
mastDam = masteryPercentage;
// TODO Correct these
min = this.mobBase.getMinDmg();
max = this.mobBase.getMaxDmg();
} else {
if (mainHand)
this.rangeHandOne = weapon.getItemBase().getRange() * (1 + (baseStrength / 600.0f));
else
this.rangeHandTwo = weapon.getItemBase().getRange() * (1 + (baseStrength / 600.0f));
skillPercentage = getModifiedAmount(this.skills.get(wb.getSkillRequired()));
masteryPercentage = getModifiedAmount(this.skills.get(wb.getMastery()));
if (masteryPercentage == 0f)
mastDam = 0f;
else
mastDam = masteryPercentage;
min = wb.getMinDamage();
max = wb.getMaxDamage();
strBased = wb.isStrBased();
}
// calculate atr
float atr = this.mobBase.getAttackRating();
if (this.statStrCurrent > this.statDexCurrent)
atr += statStrCurrent * .5;
else
atr += statDexCurrent * .5;
// add in any bonuses to atr
if (this.bonuses != null) {
atr += this.bonuses.getFloat(ModType.OCV, SourceType.None);
// Finally use any multipliers. DO THIS LAST!
float pos_Bonus = 1 + this.bonuses.getFloatPercentPositive(ModType.OCV, SourceType.None);
atr *= pos_Bonus;
//and negative percent modifiers
//TODO DO DEBUFFS AFTER?? wILL TEst when finished
float neg_Bonus = this.bonuses.getFloatPercentNegative(ModType.OCV, SourceType.None);
atr *= (1 + neg_Bonus);
}
atr = (atr < 1) ? 1 : atr;
// set atr
if (mainHand)
this.atrHandOne = (short) (atr + 0.5f);
else
this.atrHandTwo = (short) (atr + 0.5f);
//calculate speed
if (wb != null)
speed = wb.getSpeed();
else
speed = 20f; //unarmed attack speed
if (this.bonuses != null && this.bonuses.getFloat(ModType.AttackDelay, SourceType.None) != 0f) //add effects speed bonus
speed *= (1 + this.bonuses.getFloatPercentAll(ModType.AttackDelay, SourceType.None));
if (speed < 10)
speed = 10;
//add min/max damage bonuses for weapon **REMOVED
//if duel wielding, cut damage by 30%
// calculate damage
float minDamage;
float maxDamage;
float pri = (strBased) ? (float) this.statStrCurrent : (float) this.statDexCurrent;
float sec = (strBased) ? (float) this.statDexCurrent : (float) this.statStrCurrent;
minDamage = (float) (min * ((0.0315f * Math.pow(pri, 0.75f)) + (0.042f * Math.pow(sec, 0.75f)) + (0.01f * ((int) skillPercentage + (int) mastDam))));
maxDamage = (float) (max * ((0.0785f * Math.pow(pri, 0.75f)) + (0.016f * Math.pow(sec, 0.75f)) + (0.0075f * ((int) skillPercentage + (int) mastDam))));
minDamage = (float) ((int) (minDamage + 0.5f)); //round to nearest decimal
maxDamage = (float) ((int) (maxDamage + 0.5f)); //round to nearest decimal
//add Base damage last.
float minDamageMod = this.mobBase.getDamageMin();
float maxDamageMod = this.mobBase.getDamageMax();
minDamage += minDamageMod;
maxDamage += maxDamageMod;
// add in any bonuses to damage
if (this.bonuses != null) {
// Add any base bonuses
minDamage += this.bonuses.getFloat(ModType.MinDamage, SourceType.None);
maxDamage += this.bonuses.getFloat(ModType.MaxDamage, SourceType.None);
// Finally use any multipliers. DO THIS LAST!
minDamage *= (1 + this.bonuses.getFloatPercentAll(ModType.MinDamage, SourceType.None));
maxDamage *= (1 + this.bonuses.getFloatPercentAll(ModType.MaxDamage, SourceType.None));
}
// set damages
if (mainHand) {
this.minDamageHandOne = (short) minDamage;
this.maxDamageHandOne = (short) maxDamage;
this.speedHandOne = 30;
} else {
this.minDamageHandTwo = (short) minDamage;
this.maxDamageHandTwo = (short) maxDamage;
this.speedHandTwo = 30;
}
}
@@ -2005,7 +2128,6 @@ public class Mob extends AbstractIntelligenceAgent {
try {
NPCManager.applyRuneSetEffects(this);
MobBase.applyMobbaseEffects(this);
recalculateStats();
this.setHealth(this.healthMax);
@@ -2038,8 +2160,9 @@ public class Mob extends AbstractIntelligenceAgent {
Vector3fImmutable newPatrolPoint = Vector3fImmutable.getRandomPointInCircle(this.getBindLoc(), patrolRadius);
this.patrolPoints.add(newPatrolPoint);
if (i == 1)
MovementManager.translocate(this, newPatrolPoint, null);
if (i == 1) {
MovementUtilities.aiMove(this,newPatrolPoint,true);
}
}
}
+1 -22
View File
@@ -13,11 +13,8 @@ import ch.claude_martin.enumbitset.EnumBitSet;
import engine.Enum;
import engine.gameManager.DbManager;
import engine.gameManager.LootManager;
import engine.gameManager.PowersManager;
import engine.loot.BootySetEntry;
import engine.powers.EffectsBase;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -57,8 +54,6 @@ public class MobBase extends AbstractGameObject {
private float walkCombat = 0;
private float runCombat = 0;
public ArrayList<MobBaseEffects> mobbaseEffects;
/**
* ResultSet Constructor
*/
@@ -113,7 +108,6 @@ public class MobBase extends AbstractGameObject {
this.mobBaseStats = DbManager.MobBaseQueries.LOAD_STATS(this.loadID);
DbManager.MobBaseQueries.LOAD_ALL_MOBBASE_SPEEDS(this);
this.mobbaseEffects = DbManager.MobBaseQueries.GET_RUNEBASE_EFFECTS(this.getObjectUUID());
}
@@ -260,7 +254,7 @@ public class MobBase extends AbstractGameObject {
}
public int getAtr() {
return attackRating;
return atr;
}
public void setAtr(int atr) {
@@ -307,19 +301,4 @@ public class MobBase extends AbstractGameObject {
return runCombat;
}
public static void applyMobbaseEffects(Mob mob){
for(MobBaseEffects mbe : mob.mobBase.mobbaseEffects){
if(mob.level >= mbe.getReqLvl()){
try {
//PowersManager.applyPower(mob, mob, mob.loc, mbe.getToken(), mbe.getRank(), false);
EffectsBase effectsBase = PowersManager.getEffectByToken(mbe.getToken());
if(effectsBase != null)
mob.addEffectNoTimer(Integer.toString(effectsBase.getUUID()), effectsBase, mbe.getRank(), true);
}catch(Exception e){
Logger.error("NULL POWER FOR MOB: " + mob.getObjectUUID() + ", POWER TOKEN: " + mbe.getToken());
}
}
}
}
}
+249 -265
View File
@@ -2925,9 +2925,6 @@ public class PlayerCharacter extends AbstractCharacter {
}
public synchronized void grantXP(int xp) {
int groupSize = 1;
if(GroupManager.getGroup(this)!= null)
groupSize = GroupManager.getGroup(this).members.size();
if(this.promotionClass == null && this.level == 10){
this.setOverFlowEXP(0);
this.update(false);
@@ -3078,14 +3075,6 @@ public class PlayerCharacter extends AbstractCharacter {
SetObjectValueMsg upm = new SetObjectValueMsg(this, 9);
DispatchMessage.dispatchMsgToInterestArea(this, upm, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
checkGuildStatus();
//give gold for level up if level is under or equal to 20 and over 10
if(!this.isBoxed && this.level > 10 && this.level <= 20) {
int gold = (int) ((100000 * (this.level - 10) / 55.0) );
this.charItemManager.addGoldToInventory(gold, false);
this.charItemManager.updateInventory();
}
} else {
this.exp += remainingXP;
@@ -3133,8 +3122,26 @@ public class PlayerCharacter extends AbstractCharacter {
public void calculateSpeedMod() {
// get base race speed modifer
//this is retarded. *** Refactor
// if (this.race != null) {
// int ID = this.race.getObjectUUID();
// if (ID == 2004 || ID == 2005)
// this.raceRunMod = 1.21f; // centaur run bonus 22%
//// else if (ID == 2017)
//// this.raceRunMod = 1.14f; // mino run bonus 15%
// else
// this.raceRunMod = 1;
// } else
// this.raceRunMod = 1;
float bonus = 1f;
// // TODO: hardcoded, as didnt have time to introduce DB column to base object
// if (baseClass.getName().equals("Fighter") || baseClass.getName().equals("Rogue"))
// bonus += .05f;
// get running skill
if (this.skills != null) {
CharacterSkill running = this.skills.get("Running");
@@ -3187,6 +3194,14 @@ public class PlayerCharacter extends AbstractCharacter {
return this.follow;
}
public int getLastGroupToInvite() {
return this.lastGroupToInvite;
}
public void setLastGroupToInvite(int value) {
this.lastGroupToInvite = value;
}
@Override
public float getAltitude() {
if (this.altitude < 0)
@@ -3235,6 +3250,10 @@ public class PlayerCharacter extends AbstractCharacter {
return this.loadedStaticObjects;
}
public void setLoadedStaticObjects(HashSet<AbstractWorldObject> value) {
this.loadedStaticObjects = value;
}
public boolean isTeleportMode() {
return teleportMode;
}
@@ -3242,6 +3261,20 @@ public class PlayerCharacter extends AbstractCharacter {
public void setTeleportMode(boolean teleportMode) {
this.teleportMode = teleportMode;
}
// public ConcurrentHashMap<Integer, FinishRecycleTimeJob>
// getRecycleTimers() {
// return this.recycleTimers;
// }
// public UsePowerJob getLastPower() {
// return this.lastPower;
// }
// public void setLastPower(UsePowerJob value) {
// this.lastPower = value;
// }
// public void clearLastPower() {
// this.lastPower = null;
// }
public long chatFloodTime(int chatOpcode, long chatTimeMilli, int qtyToSave) {
if (qtyToSave < 1)
return 0L; // disabled
@@ -3755,6 +3788,22 @@ public class PlayerCharacter extends AbstractCharacter {
return this.statStrCurrent - this.race.getStrStart() - this.baseClass.getStrMod();
}
public int getDexForClient() {
return this.statDexCurrent - this.race.getDexStart() - this.baseClass.getDexMod();
}
public int getConForClient() {
return this.statConCurrent - this.race.getConStart() - this.baseClass.getConMod();
}
public int getIntForClient() {
return this.statIntCurrent - this.race.getIntStart() - this.baseClass.getIntMod();
}
public int getSpiForClient() {
return this.statSpiCurrent - this.race.getSpiStart() - this.baseClass.getSpiMod();
}
public int getTrainsAvailable() {
return this.trainsAvailable.get();
}
@@ -3792,6 +3841,15 @@ public class PlayerCharacter extends AbstractCharacter {
}
ConcurrentHashMap<Integer, Item> equipped = this.charItemManager.getEquipped();
// // Reset passives
// if (this.bonuses != null) {
// this.bonuses.setBool("Block", false);
// this.bonuses.setBool("Parry", false);
// if (this.baseClass != null && this.baseClass.getUUID() == 2502)
// this.bonuses.setBool("Dodge", true);
// else
// this.bonuses.setBool("Dodge", false);
// }
// calculate atr and damage for each hand
calculateAtrDamageForWeapon(equipped.get(MBServerStatics.SLOT_MAINHAND), true, equipped.get(MBServerStatics.SLOT_OFFHAND));
calculateAtrDamageForWeapon(equipped.get(MBServerStatics.SLOT_OFFHAND), false, equipped.get(MBServerStatics.SLOT_MAINHAND));
@@ -3844,7 +3902,7 @@ public class PlayerCharacter extends AbstractCharacter {
// make sure weapon exists
boolean noWeapon = false;
ItemBase weaponBase = null;
ItemBase wb = null;
if (weapon == null)
noWeapon = true;
else {
@@ -3855,7 +3913,7 @@ public class PlayerCharacter extends AbstractCharacter {
defaultAtrAndDamage(mainHand);
return;
} else
weaponBase = ib;
wb = ib;
}
float skillPercentage, masteryPercentage;
float mastDam;
@@ -3905,17 +3963,28 @@ public class PlayerCharacter extends AbstractCharacter {
this.rangeHandTwo *= range_bonus;
}
skillPercentage = getModifiedAmount(this.skills.get(weaponBase.getSkillRequired()));
masteryPercentage = getModifiedAmount(this.skills.get(weaponBase.getMastery()));
skillPercentage = getModifiedAmount(this.skills.get(wb.getSkillRequired()));
masteryPercentage = getModifiedAmount(this.skills.get(wb.getMastery()));
if (masteryPercentage == 0f)
mastDam = 0f;
// mastDam = CharacterSkill.getQuickMastery(this, weaponBase.getMastery());
// mastDam = CharacterSkill.getQuickMastery(this, wb.getMastery());
else
mastDam = masteryPercentage;
min = (float) weaponBase.getMinDamage();
max = (float) weaponBase.getMaxDamage();
strBased = weaponBase.isStrBased();
min = (float) wb.getMinDamage();
max = (float) wb.getMaxDamage();
strBased = wb.isStrBased();
//
// Add parry bonus for weapon and allow parry if needed
// // Only Fighters and Thieves can Parry
// if ((this.baseClass != null && this.baseClass.getUUID() == 2500)
// || (this.promotionClass != null && this.promotionClass.getUUID() == 2520)) {
// if (wbMain == null || wbMain.getRange() < MBServerStatics.RANGED_WEAPON_RANGE)
// if (wbOff == null || wbOff.getRange() < MBServerStatics.RANGED_WEAPON_RANGE)
// this.bonuses.setBool("Parry", true);
// }
// }
}
if (this.effects != null && this.effects.containsKey("DeathShroud"))
@@ -3926,18 +3995,13 @@ public class PlayerCharacter extends AbstractCharacter {
this.atrHandTwo = (short) 0;
else {
// calculate atr
//(Primary Stat / 2) + (Weapon Skill * 4) + (Weapon Mastery * 3) + (ATR Enchantments) * 1.stance modifier
float atr = 0;
int primaryStat;
int dexMod = this.getDexMod();
int strMod = this.getStrMod();
if(weaponBase != null && weaponBase.isStrBased()){
primaryStat = this.statStrCurrent;
}else{
primaryStat = this.statDexCurrent;
}
atr = (primaryStat * 0.5f) + (skillPercentage * 4) + (masteryPercentage * 3);
atr += (int) skillPercentage * 4f; //<-round down skill% -
atr += (int) masteryPercentage * 3f;
if (this.statStrCurrent > this.statDexCurrent)
atr += statStrCurrent / 2;
else
atr += statDexCurrent / 2;
// add in any bonuses to atr
if (this.bonuses != null) {
@@ -3948,6 +4012,10 @@ public class PlayerCharacter extends AbstractCharacter {
float pos_Bonus = (1 + this.bonuses.getFloatPercentPositive(ModType.OCV, SourceType.None));
atr *= pos_Bonus;
// next precise
//runes will have their own bonuses.
// atr *= (1 + ((float) this.bonuses.getShort("rune.Attack") / 100));
//and negative percent modifiers
float neg_Bonus = this.bonuses.getFloatPercentNegative(ModType.OCV, SourceType.None);
@@ -3964,8 +4032,8 @@ public class PlayerCharacter extends AbstractCharacter {
}
//calculate speed
if (weaponBase != null)
speed = weaponBase.getSpeed();
if (wb != null)
speed = wb.getSpeed();
else
speed = 20f; //unarmed attack speed
if (weapon != null)
@@ -4400,6 +4468,36 @@ public class PlayerCharacter extends AbstractCharacter {
return (amount - attackerLevel + this.getLevel()) / 4;
}
public float getPassiveChance1(ModType modType, SourceType sourceType, int attackerLevel, boolean fromCombat) {
if (this.skills == null || this.bonuses == null)
return 0f;
// must be allowed to use this passive
if (!this.bonuses.getBool(modType, sourceType))
return 0f;
// must not be stunned
if (this.bonuses.getBool(ModType.Stunned, SourceType.None))
return 0f;
// Get base skill amount
CharacterSkill sk = this.skills.get(sourceType.name());
float amount;
if (sk == null)
amount = CharacterSkill.getQuickMastery(this, modType.name());
else
amount = sk.getModifiedAmount();
// Add bonuses
amount += this.bonuses.getFloat(modType, sourceType);
// Add item bonuses and return
if (sourceType.equals(SourceType.Dodge) && !fromCombat)
return ((amount / 4) - attackerLevel + this.getLevel()) / 4;
else
return (amount - attackerLevel + this.getLevel()) / 4;
}
public float getRegenModifier(ModType type) {
float regen = 1f;
@@ -4484,6 +4582,10 @@ public class PlayerCharacter extends AbstractCharacter {
super.removeFromCache();
}
public void storeIgnoreListDB() {
}
public void updateSkillsAndPowersToDatabase() {
if (this.skills != null)
for (CharacterSkill skill : this.skills.values()) {
@@ -4538,7 +4640,7 @@ public class PlayerCharacter extends AbstractCharacter {
tmpLevel = targetLevel;
tmpLevel = (short) Math.min(tmpLevel, MBServerStatics.LEVELCAP);
tmpLevel = (short) Math.min(tmpLevel, 75);
while (this.level < tmpLevel) {
grantXP(Experience.getBaseExperience(tmpLevel) - this.exp);
@@ -4652,6 +4754,17 @@ public class PlayerCharacter extends AbstractCharacter {
return true;
}
// Method is called by Server Heartbeat simulation tick.
// Stat regen and transform updates should go in here.
public boolean isNoTeleScreen() {
return noTeleScreen;
}
public void setNoTeleScreen(boolean noTeleScreen) {
this.noTeleScreen = noTeleScreen;
}
private double getDeltaTime() {
return (System.currentTimeMillis() - lastUpdateTime) * .001f;
@@ -4693,6 +4806,30 @@ public class PlayerCharacter extends AbstractCharacter {
return false;
}
public boolean isSwimming(Vector3fImmutable currentLoc) {
// If char is flying they aren't quite swimming
try {
float localAltitude = HeightMap.getWorldHeight(currentLoc);
Zone zone = ZoneManager.findSmallestZone(currentLoc);
if (zone.getSeaLevel() != 0) {
if (localAltitude < zone.getSeaLevel())
return true;
} else {
if (localAltitude < 0)
return true;
}
} catch (Exception e) {
Logger.info(this.getName() + e);
}
return false;
}
private static void forceRespawn(PlayerCharacter sourcePlayer) throws MsgSendException {
if (sourcePlayer == null)
@@ -4749,6 +4886,11 @@ public class PlayerCharacter extends AbstractCharacter {
while (this.level < 10) {
grantXP(Experience.getBaseExperience(this.level + 1) - this.exp);
}
if(this.charItemManager != null && this.charItemManager.getGoldInventory() != null && this.charItemManager.getGoldInventory().getNumOfItems() < 1000) {
this.getCharItemManager().addGoldToInventory(1000, false);
this.getCharItemManager().addItemToInventory(new MobLoot(this, ItemBase.getItemBase(980066), 1, false).promoteToItem(this));
this.getCharItemManager().updateInventory();
}
}
if(this.isBoxed && !this.containsEffect(1672601862)) {
@@ -4761,22 +4903,6 @@ public class PlayerCharacter extends AbstractCharacter {
GroundPlayer(this);
//ChatManager.chatSystemInfo(this, "You Cannot Fly While Having A MovementBuff");
}
if(!this.timestamps.containsKey("StunGrounded"))
this.timestamps.put("StunGrounded",System.currentTimeMillis() - 1000L);
if(this.bonuses.getBool(ModType.Stunned, SourceType.None) && this.timestamps.get("StunGrounded") < System.currentTimeMillis()){
boolean isFlyMoving = this.getDesiredAltitude() != this.altitude;
if(!isFlyMoving && this.bonuses.getBool(ModType.Stunned, SourceType.None)){
this.setDesiredAltitude(this.altitude - 10);
this.setTakeOffTime(System.currentTimeMillis());
ChangeAltitudeMsg msg = new ChangeAltitudeMsg(this.getObjectType().ordinal(), this.getObjectUUID(), false, this.getAltitude(), this.getDesiredAltitude(), this.getAltitude());
// force a landing
DispatchMessage.dispatchMsgToInterestArea(this, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
this.timestamps.put("StunGrounded",System.currentTimeMillis() + 1500L);
ChatManager.chatSystemInfo(this,"Applying 1 Tier Ground");
}
}
}
} catch (Exception e) {
@@ -4911,6 +5037,7 @@ public class PlayerCharacter extends AbstractCharacter {
ChatManager.chatSystemInfo(this,
"Arrived at End location. " + this.getEndLoc());
return;
//Next upda
}
setLoc(newLoc);
@@ -4922,6 +5049,11 @@ public class PlayerCharacter extends AbstractCharacter {
if (this.getStamina() < 10)
MovementManager.sendOOS(this);
// if (MBServerStatics.MOVEMENT_SYNC_DEBUG || this.getDebug(1))
// Logger.info("MovementManager", "Updating movement current loc:" + this.getLoc().getX() + " " + this.getLoc().getZ()
// + " end loc: " + this.getEndLoc().getX() + " " + this.getEndLoc().getZ() + " distance " + this.getEndLoc().distance2D(this.getLoc()));
}
@Override
@@ -4987,9 +5119,6 @@ public class PlayerCharacter extends AbstractCharacter {
@Override
public void updateRegen() {
if(true)
return;
float healthRegen = 0f;
float manaRegen = 0f;
float stamRegen = 0f;
@@ -5014,7 +5143,7 @@ public class PlayerCharacter extends AbstractCharacter {
if (this.walkMode)
manaRegen = ((this.manaMax * MBServerStatics.MANA_REGEN_IDLE) * getRegenModifier(ModType.ManaRecoverRate));
else if (!this.isCasting() && !this.isItemCasting())
manaRegen = ((this.manaMax * MBServerStatics.MANA_REGEN_RUN) * getRegenModifier(ModType.ManaRecoverRate));
manaRegen = ((this.manaMax * MBServerStatics.MANA_REGEN_IDLE) * getRegenModifier(ModType.ManaRecoverRate));
else
manaRegen = 0;
@@ -5298,11 +5427,23 @@ public class PlayerCharacter extends AbstractCharacter {
return movementState;
}
public boolean isHasAnniversery() {
return hasAnniversery;
}
public void setHasAnniversery(boolean hasAnniversery) {
DbManager.PlayerCharacterQueries.SET_ANNIVERSERY(this, hasAnniversery);
this.hasAnniversery = hasAnniversery;
}
public int getSpamCount() {
return spamCount;
}
public void setSpamCount(int spamCount) {
this.spamCount = spamCount;
}
public String getHash() {
return hash;
}
@@ -5328,6 +5469,10 @@ public class PlayerCharacter extends AbstractCharacter {
this.lastRealmID = lastRealmID;
}
public int getSubRaceID() {
return subRaceID;
}
public void setSubRaceID(int subRaceID) {
this.subRaceID = subRaceID;
}
@@ -5340,6 +5485,29 @@ public class PlayerCharacter extends AbstractCharacter {
this.guildHistory = guildHistory;
}
public void moveTo(Vector3fImmutable endLoc) {
this.setInBuilding(-1);
this.setInFloorID(-1);
MoveToPointMsg moveToMsg = new MoveToPointMsg();
moveToMsg.setStartCoord(this.getLoc());
moveToMsg.setEndCoord(endLoc);
moveToMsg.setInBuilding(-1);
moveToMsg.setUnknown01(-1);
moveToMsg.setSourceType(GameObjectType.PlayerCharacter.ordinal());
moveToMsg.setSourceID(this.getObjectUUID());
Dispatch dispatch = Dispatch.borrow(this, moveToMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
try {
MovementManager.movement(moveToMsg, this);
} catch (MsgSendException e) {
// TODO Auto-generated catch block
Logger.error("Player.MoveTo", this.getName() + " tripped error " + e.getMessage());
}
}
public void updateScaleHeight() {
float strengthScale = 0;
@@ -5376,6 +5544,10 @@ public class PlayerCharacter extends AbstractCharacter {
this.overFlowEXP = overFlowEXP;
}
public MovementState getLastMovementState() {
return lastMovementState;
}
public void setLastMovementState(MovementState lastMovementState) {
this.lastMovementState = lastMovementState;
}
@@ -5397,16 +5569,20 @@ public class PlayerCharacter extends AbstractCharacter {
public void resetRegenUpdateTime() {
this.lastUpdateTime = System.currentTimeMillis();
this.lastStamUpdateTime = System.currentTimeMillis();
this.timestamps.put("LastRegenHealth", System.currentTimeMillis());
this.timestamps.put("LastRegenMana", System.currentTimeMillis());
this.timestamps.put("LastRegenStamina", System.currentTimeMillis());
this.timestamps.put("LastConsumeStamina", System.currentTimeMillis());
}
public float getCharacterHeight() {
return characterHeight;
}
public void setCharacterHeight(float characterHeight) {
this.characterHeight = characterHeight;
}
public void setCenterHeight(float centerHeight) {
this.centerHeight = centerHeight;
}
public boolean isEnteredWorld() {
return enteredWorld;
}
@@ -5415,10 +5591,26 @@ public class PlayerCharacter extends AbstractCharacter {
this.enteredWorld = enteredWorld;
}
public long getChannelMute() {
return channelMute;
}
public void setChannelMute(long channelMute) {
this.channelMute = channelMute;
}
public boolean isLastSwimming() {
return lastSwimming;
}
public boolean isTeleporting() {
return isTeleporting;
}
public void setTeleporting(boolean isTeleporting) {
this.isTeleporting = isTeleporting;
}
@Override
public final void teleport(final Vector3fImmutable targetLoc) {
@@ -5467,212 +5659,4 @@ public class PlayerCharacter extends AbstractCharacter {
this.dirtyLoad = dirtyLoad;
dirtyLock.writeLock().unlock();
}
public void doRegen(){
if(!this.timestamps.containsKey("SyncClient"))
this.timestamps.put("SyncClient",System.currentTimeMillis());
if (this.updateLock.writeLock().tryLock()) {
try {
if(!this.isAlive() || !this.enteredWorld || !this.isActive) {
this.resetRegenUpdateTime();
return;
}
this.updateMovementState();
boolean updateHealth = this.regenerateHealth();
boolean updateMana = this.regenerateMana();
boolean updateStamina = this.regenerateStamina();
boolean consumeStamina = this.consumeStamina();
if(this.timestamps.get("SyncClient") + 5000L > System.currentTimeMillis())
if(updateHealth || updateMana || updateStamina || consumeStamina)
this.syncClient();
} catch (Exception e) {
Logger.error(e);
} finally {
this.updateLock.writeLock().unlock();
}
}
}
public boolean regenerateHealth(){
Long regenTime;
Long currentTime = System.currentTimeMillis();
regenTime = this.timestamps.getOrDefault("LastRegenHealth", currentTime);
float secondsPassed = (currentTime - regenTime) / 1000f;
float onePercent = this.healthMax * 0.01f;
float rate = 1.0f / RecoveryType.getRecoveryType(this).healthRate;
rate *= this.getRegenModifier(ModType.HealthRecoverRate);
if(this.isMoving() && !this.walkMode)
rate = 0.0f;
float healthRegenerated = onePercent * rate * secondsPassed;
//ChatManager.chatSystemInfo(this,"HEALTH REGENERATED: " + healthRegenerated + " SECONDS PASSED: " + secondsPassed);
boolean workedHealth = false;
float old = this.health.get();
float mod = old + healthRegenerated;
while(!workedHealth) {
if (mod > this.healthMax)
mod = healthMax;
else if (mod <= 0) {
if (this.isAlive.compareAndSet(true, false))
killCharacter("Water");
return false;
}
workedHealth = this.health.compareAndSet(old, mod);
}
this.timestamps.put("LastRegenHealth",currentTime);
return mod > old;
}
public boolean regenerateMana(){
Long regenTime;
Long currentTime = System.currentTimeMillis();
regenTime = this.timestamps.getOrDefault("LastRegenMana", currentTime);
float secondsPassed = (currentTime - regenTime) / 1000f;
float onePercent = this.manaMax * 0.01f;
float rate = 1.0f / RecoveryType.getRecoveryType(this).manaRate;
rate *= this.getRegenModifier(ModType.ManaRecoverRate);
if(this.isMoving() && !this.walkMode)
rate = 0.0f;
float manaRegenerated = onePercent * secondsPassed * rate;
boolean workedMana = false;
float old = this.mana.get();
float mod = old + manaRegenerated;
while(!workedMana) {
if (mod > this.manaMax)
mod = manaMax;
else if (mod < 0)
mod = 0;
workedMana = this.mana.compareAndSet(old, mod);
}
this.timestamps.put("LastRegenMana",currentTime);
return mod > old;
}
public boolean regenerateStamina(){
Long currentTime = System.currentTimeMillis();
if(this.isMoving() || this.isFlying() || !this.canBreathe) {
this.timestamps.put("LastRegenStamina",currentTime);
return false;
}
Long regenTime;
regenTime = this.timestamps.getOrDefault("LastRegenStamina", currentTime);
float secondsPassed = (currentTime - regenTime) / 1000f;
float secondsToRecover1 = RecoveryType.getRecoveryType(this).staminaRate;
float ratio = secondsPassed / secondsToRecover1;
//rate *= this.getRegenModifier(ModType.StaminaRecoverRate); // Adjust rate with modifiers
//float staminaRegenerated = secondsPassed / rate; // Stamina regenerates 1 point per `rate` seconds
float staminaRegenerated = secondsPassed * ratio; // Stamina regenerates 1 point per `rate` seconds
boolean workedStamina = false;
float old = this.stamina.get();
float mod = old + staminaRegenerated;
while (!workedStamina) {
if (mod > this.staminaMax)
mod = staminaMax;
else if (mod < 0)
mod = 0;
workedStamina = this.stamina.compareAndSet(old, mod);
}
//ChatManager.chatSystemInfo(this, "STAM: " + this.stamina.get() + " / " + this.staminaMax);
this.timestamps.put("LastRegenStamina", currentTime);
return mod > old;
}
public boolean consumeStamina(){
Long regenTime;
Long currentTime = System.currentTimeMillis();
regenTime = this.timestamps.getOrDefault("LastConsumeStamina", currentTime);
float secondsPassed = (currentTime - regenTime) / 1000f;
float consumption;
if(!this.isMoving() && !this.isFlying() && this.canBreathe) {
this.timestamps.put("LastConsumeStamina",currentTime);
return false;
}
if(!this.combat){
consumption = 0.4f * secondsPassed;
}else{
consumption = 0.65f * secondsPassed;
}
if(this.movementState.equals(MovementState.SWIMMING))
consumption = 1.5f * secondsPassed;
else if(this.isFlying())
consumption = 2.0f * secondsPassed;
boolean workedStamina = false;
float old = this.stamina.get();
float mod = old - consumption;
while (!workedStamina) {
if (mod <= 0)
mod = 0;
workedStamina = this.stamina.compareAndSet(old, mod);
}
//ChatManager.chatSystemInfo(this, "STAM: " + this.stamina.get() + " / " + this.staminaMax);
this.timestamps.put("LastConsumeStamina",currentTime);
if(this.stamina.get() == 0){
return this.consumeHealth(secondsPassed);
}
return mod < old;
}
public boolean consumeHealth(float secondsPassed){
float consumption = 2.0f * secondsPassed;
boolean workedHealth = false;
float old = this.health.get();
float mod = old - consumption;
while(!workedHealth) {
if (mod > this.healthMax)
mod = healthMax;
else if (mod <= 0) {
if (this.isAlive.compareAndSet(true, false))
killCharacter("Water");
return true;
}
workedHealth = this.health.compareAndSet(old, mod);
}
return mod < old;
}
enum RecoveryType{
//Values for health and mana are in terms of the number of seconds it takes to recover 1% of max pool
//Values for stamina are in terms of the number of seconds it takes to recover 1 point
RESTING(3.0f,1.2f,0.5f), //sitting
IDLING(15.0f,6.0f,5.0f), //standing not moving
WALKING(20.0f,8.0f,0.0f), // moving in walk mode
RUNNING(0.0f,0.0f,0.0f); // moving in run mode
public float healthRate;
public float manaRate;
public float staminaRate;
RecoveryType(float health, float mana, float stamina) {
this.healthRate = health;
this.manaRate = mana;
this.staminaRate = stamina;
}
public static RecoveryType getRecoveryType(PlayerCharacter pc){
if (pc.isMoving()) {
if(pc.walkMode){
return RecoveryType.WALKING;
}else{
return RecoveryType.RUNNING;
}
}else if(pc.isSit()){
return RecoveryType.RESTING;
}else{
return RecoveryType.IDLING;
}
}
}
}
-25
View File
@@ -10,14 +10,10 @@
package engine.objects;
import engine.Enum;
import engine.InterestManagement.InterestManager;
import engine.InterestManagement.RealmMap;
import engine.InterestManagement.WorldGrid;
import engine.db.archive.DataWarehouse;
import engine.db.archive.RealmRecord;
import engine.gameManager.BuildingManager;
import engine.gameManager.DbManager;
import engine.gameManager.NPCManager;
import engine.gameManager.PowersManager;
import engine.net.ByteBufferWriter;
import engine.powers.PowersBase;
@@ -383,16 +379,6 @@ public class Realm {
public void abandonRealm() {
for(AbstractWorldObject awo : WorldGrid.getObjectsInRangePartial(this.getRulingCity().loc,1750,MBServerStatics.MASK_BUILDING)){
Building wall = (Building)awo;
if(wall.getBlueprint() != null && wall.getBlueprint().getBuildingGroup() != null && wall.getBlueprint().isWallPiece()){
float currentHealthRatio = wall.getCurrentHitpoints()/wall.healthMax;
float newMax = wall.getBlueprint().getMaxHealth(1);
wall.setMaxHitPoints(newMax);
wall.setHealth(wall.healthMax * currentHealthRatio);
}
}
// Push event to warehouse
RealmRecord realmRecord = RealmRecord.borrow(this, Enum.RecordEventType.LOST);
@@ -420,17 +406,6 @@ public class Realm {
this.configure();
this.updateDatabase();
for(AbstractWorldObject awo : WorldGrid.getObjectsInRangePartial(city.loc,1750,MBServerStatics.MASK_BUILDING)){
Building wall = (Building)awo;
if(wall.getBlueprint() != null && wall.getBlueprint().getBuildingGroup() != null && wall.getBlueprint().isWallPiece()){
float currentHealthRatio = wall.getCurrentHitpoints()/wall.healthMax;
float newMax = wall.healthMax * 1.1f;
wall.setMaxHitPoints(newMax);
wall.setHealth(wall.healthMax * currentHealthRatio);
}
}
// Push event to warehouse
RealmRecord realmRecord = RealmRecord.borrow(this, Enum.RecordEventType.CAPTURE);
-5
View File
@@ -11,7 +11,6 @@ package engine.powers;
import engine.Enum.PowerCategoryType;
import engine.Enum.PowerTargetType;
import engine.gameManager.PowersManager;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
@@ -110,8 +109,6 @@ public class PowersBase {
public PowerCategoryType powerCategory;
public String description;
public boolean breaksForm = true;
/**
* No Table ID Constructor
*/
@@ -328,8 +325,6 @@ public class PowersBase {
ct = rs.getString("monsterTypeRestrict3").trim();
if (!ct.isEmpty())
this.monsterTypeRestrictions.add(ct);
this.breaksForm = PowersManager.breakForm(this.token);
}
@@ -130,7 +130,7 @@ public class ApplyEffectPowerAction extends AbstractPowerAction {
((Mob) awo).setCombatTarget(source);
ChatSystemMsg msg = ChatManager.CombatInfo(source, awo);
DispatchMessage.sendToAllInRange(source, msg);
//((Mob)awo).refresh();
((Mob)awo).refresh();
}
}
if (awo != null && awo.getObjectType() == GameObjectType.Mob) {
+4 -4
View File
@@ -312,10 +312,10 @@ public class MBServerStatics {
public static final float HEALTH_REGEN_SWIM_NOSTAMINA_STATIC = 0f; // 100%
// weapon
public static final float MANA_REGEN_STATIC = 0.16666666666666666666666666666667f;
public static final float MANA_REGEN_SIT = 0.8333333f; // 1% every 1.2 seconds
public static final float MANA_REGEN_IDLE = 0.1666667f; // 1% every 6 seconds
public static final float MANA_REGEN_WALK = 0.125f; // 1% every 8 seconds
public static final float MANA_REGEN_RUN = 0.0f; // No regeneration while running
public static final float MANA_REGEN_SIT = 0.008333333f; // 100% in 2
public static final float MANA_REGEN_IDLE = 0.00166667f; // 100% in 10
public static final float MANA_REGEN_WALK = 0.00125f; // 100% in 13.333
public static final float MANA_REGEN_RUN = 0f;
public static final float STAMINA_REGEN_SIT = 2f; // 2 per second
public static final float STAMINA_REGEN_IDLE = 0.2f; // 1 per 5 seconds
public static final float STAMINA_REGEN_WALK = 0f;
+2 -2
View File
@@ -450,7 +450,7 @@ public class LoginServer {
objectUUID = rs.getInt("UID");
objectType = rs.getString("type");
//Logger.info("INVALIDATED : " + objectType + " UUID: " + objectUUID);
Logger.info("INVALIDATED : " + objectType + " UUID: " + objectUUID);
switch (objectType) {
@@ -462,7 +462,7 @@ public class LoginServer {
PlayerCharacter player = (PlayerCharacter) DbManager.getObject(Enum.GameObjectType.PlayerCharacter, objectUUID);
PlayerCharacter.initializePlayer(player);
player.getAccount().characterMap.replace(player.getObjectUUID(), player);
//Logger.info("Player active state is : " + player.isActive());
Logger.info("Player active state is : " + player.isActive());
break;
}
+2 -2
View File
@@ -517,8 +517,8 @@ public class WorldServer {
Logger.info("Starting Bane Thread");
BaneThread.startBaneThread();
Logger.info("Starting Player Regen Thread");
UpdateThread.startUpdateThread();
//Logger.info("Starting Player Update Thread");
//UpdateThread.startUpdateThread();
printThreads();
+7 -16
View File
@@ -27,8 +27,8 @@ import java.util.ArrayList;
public class BaneThread implements Runnable {
private volatile Long lastRun;
public static final Long instancedelay = 1000L;
public Long lastRun;
public static int instancedelay = 10000;
public BaneThread() {
Logger.info(" BaneThread thread has started!");
}
@@ -37,16 +37,14 @@ public class BaneThread implements Runnable {
public void processBanesWindow() {
try {
synchronized (Bane.banes) {
for (int baneId : Bane.banes.keySet()) {
Bane bane = Bane.banes.get(baneId);
if (bane != null && bane.getSiegePhase().equals(Enum.SiegePhase.WAR)) {
bane.applyZergBuffs();
}
for(int baneId : Bane.banes.keySet()){
Bane bane = Bane.banes.get(baneId);
if(bane.getSiegePhase().equals(Enum.SiegePhase.WAR)){
bane.applyZergBuffs();
}
}
} catch (Exception e) {
Logger.error("BANE ERROR",e);
Logger.error("BANE ERROR");
}
@@ -58,13 +56,6 @@ public class BaneThread implements Runnable {
if (System.currentTimeMillis() >= lastRun + instancedelay) { // Correct condition
this.processBanesWindow();
lastRun = System.currentTimeMillis(); // Update lastRun after processing
}else {
try {
Thread.sleep(100); // Pause for 100ms to reduce CPU usage
} catch (InterruptedException e) {
Logger.error("Thread interrupted", e);
Thread.currentThread().interrupt();
}
}
}
}
@@ -88,11 +88,5 @@ public class HourlyJobThread implements Runnable {
Logger.info(SimulationManager.getPopulationString());
Logger.info(MessageDispatcher.getNetstatString());
Logger.info(PurgeOprhans.recordsDeleted.toString() + "orphaned items deleted");
for (Bane bane : Bane.banes.values()){
if(bane.getSiegePhase().equals(Enum.SiegePhase.CHALLENGE)){
bane.setDefaultTime();
}
}
}
}
+4 -14
View File
@@ -18,9 +18,8 @@ import org.pmw.tinylog.Logger;
public class UpdateThread implements Runnable {
private volatile Long lastRun;
public static final Long instancedelay = 1000L;
public Long lastRun;
public static int instancedelay = 1000;
public UpdateThread() {
Logger.info(" UpdateThread thread has started!");
}
@@ -30,12 +29,10 @@ public class UpdateThread implements Runnable {
try {
for(PlayerCharacter player : SessionManager.getAllActivePlayerCharacters()){
if (player != null) {
player.doRegen();
}
player.update(true);
}
} catch (Exception e) {
Logger.error("UPDATE ERROR",e);
Logger.error("UPDATE ERROR");
}
@@ -47,13 +44,6 @@ public class UpdateThread implements Runnable {
if (System.currentTimeMillis() >= lastRun + instancedelay) { // Correct condition
this.processPlayerUpdate();
lastRun = System.currentTimeMillis(); // Update lastRun after processing
}else {
try {
Thread.sleep(100); // Pause for 10ms to reduce CPU usage
} catch (InterruptedException e) {
Logger.error("Thread interrupted", e);
Thread.currentThread().interrupt();
}
}
}
}