Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 943a4c8926 | |||
| e257f0a591 | |||
| 76bb31be84 | |||
| 15bea0df04 | |||
| 7f3d37e4f7 | |||
| 4c49575bc7 | |||
| a3ffd53f53 | |||
| e6e1cab715 | |||
| 0b5c3c7c9b | |||
| da42e2baf4 | |||
| 9ec95b974f | |||
| 49ea9e50cf | |||
| 456edce9fc | |||
| 537512ed5d | |||
| d0efd08a84 | |||
| bb7ba9a6df | |||
| 09695d97db | |||
| 4fe4835c29 | |||
| 86435a3563 | |||
| bc84c7537b | |||
| 29736f9c8f | |||
| 99a9cd297c | |||
| e86749febd | |||
| 4b86fbb12c | |||
| 4c342c9b9a | |||
| d2e0b7b95c | |||
| 53fe763764 | |||
| 86d7233aa4 | |||
| d19ea0968a | |||
| 7eb49446c1 | |||
| 01a88c85a6 | |||
| 5492374f2c | |||
| 9ca00be694 | |||
| 23d9807fe3 | |||
| 8a3e3ae866 | |||
| 117646cda4 | |||
| 6cf502c4bb | |||
| 1bb99127c4 | |||
| 8aeccd35c9 | |||
| c90b94d1ec | |||
| 031fd24842 | |||
| e1c07deb52 | |||
| 5f10c24f03 | |||
| f643caacbe | |||
| cb5ab26924 | |||
| 94c9e92553 | |||
| 507638594d | |||
| e72c4886e8 | |||
| 5ba11a6238 | |||
| 2fc7671051 | |||
| d142097b0f | |||
| 4330bb3ecd | |||
| 2e1dd27332 | |||
| 4f08d7286e | |||
| 7f8fb13552 | |||
| 93e0d119b0 | |||
| a9bc44f19b | |||
| 83bc09f34b | |||
| 4386e1c828 | |||
| 72b2e54331 | |||
| e912c24025 | |||
| c9c1f6ba1c | |||
| abda30fc25 | |||
| 62c188c5c7 | |||
| 67f7b6f3f8 | |||
| f04ccb9403 | |||
| b71bb60669 | |||
| 5eab1ad1c0 | |||
| f96d0caf3c | |||
| 3e6655a199 | |||
| 386cdc8c18 | |||
| 63b40c27a5 | |||
| 6985dffda4 |
@@ -0,0 +1,131 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,12 @@ 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;
|
||||
|
||||
@@ -494,13 +497,16 @@ public class InfoCmd extends AbstractDevCmd {
|
||||
output += newline;
|
||||
output += "No building found." + newline;
|
||||
}
|
||||
int max = (int)(4.882 * targetMob.level + 121.0);
|
||||
if(max > 321){
|
||||
max = 321;
|
||||
|
||||
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 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:
|
||||
|
||||
@@ -14,6 +14,7 @@ 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;
|
||||
@@ -108,9 +109,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:
|
||||
@@ -199,6 +200,11 @@ 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;
|
||||
|
||||
@@ -662,9 +662,8 @@ public enum CombatManager {
|
||||
|
||||
DeferredPowerJob dpj = null;
|
||||
|
||||
|
||||
|
||||
if (LandHit((int)atr,(int)defense)) {
|
||||
boolean hitLanded = LandHit((int)atr,(int)defense);
|
||||
if (hitLanded) {
|
||||
|
||||
if (ac.getObjectType().equals(GameObjectType.PlayerCharacter))
|
||||
updateAttackTimers((PlayerCharacter) ac, target, true);
|
||||
@@ -693,7 +692,13 @@ public enum CombatManager {
|
||||
|
||||
PlayerBonuses bonus = ac.getBonuses();
|
||||
float attackRange = getWeaponRange(wb, bonus);
|
||||
dpj.attack(target, attackRange);
|
||||
if(specialCaseHitRoll(dpj.getPowerToken())) {
|
||||
if(hitLanded) {
|
||||
dpj.attack(target, attackRange);
|
||||
}
|
||||
}else{
|
||||
dpj.attack(target, attackRange);
|
||||
}
|
||||
|
||||
if (dpj.getPower() != null && (dpj.getPowerToken() == -1851459567 || dpj.getPowerToken() == -1851489518))
|
||||
((PlayerCharacter) ac).setWeaponPower(dpj);
|
||||
@@ -708,7 +713,13 @@ public enum CombatManager {
|
||||
|
||||
if (dpj != null && dpj.getPower() != null && (dpj.getPowerToken() == -1851459567 || dpj.getPowerToken() == -1851489518)) {
|
||||
float attackRange = getWeaponRange(wb, bonuses);
|
||||
dpj.attack(target, attackRange);
|
||||
if(specialCaseHitRoll(dpj.getPowerToken())) {
|
||||
if(hitLanded) {
|
||||
dpj.attack(target, attackRange);
|
||||
}
|
||||
}else{
|
||||
dpj.attack(target, attackRange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -916,7 +927,13 @@ public enum CombatManager {
|
||||
if (wp.requiresHitRoll() == false) {
|
||||
PlayerBonuses bonus = ac.getBonuses();
|
||||
float attackRange = getWeaponRange(wb, bonus);
|
||||
dpj.attack(target, attackRange);
|
||||
if(specialCaseHitRoll(dpj.getPowerToken())) {
|
||||
if(hitLanded) {
|
||||
dpj.attack(target, attackRange);
|
||||
}
|
||||
}else{
|
||||
dpj.attack(target, attackRange);
|
||||
}
|
||||
} else
|
||||
((PlayerCharacter) ac).setWeaponPower(null);
|
||||
}
|
||||
@@ -1466,4 +1483,15 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,8 +76,7 @@ public enum LootManager {
|
||||
|
||||
public static void GenerateMobLoot(Mob mob) {
|
||||
|
||||
//no loot for safezones
|
||||
if(mob == null || mob.getSafeZone()){
|
||||
if(mob == null){
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -186,14 +185,16 @@ 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 (mob.getSafeZone())
|
||||
if (zone != null && zone.getSafeZone() == (byte)1)
|
||||
return; // no loot to drop in safezones
|
||||
|
||||
dropRate = LootManager.NORMAL_DROP_RATE;
|
||||
|
||||
@@ -349,8 +349,10 @@ 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;
|
||||
}
|
||||
@@ -602,12 +604,12 @@ public enum PowersManager {
|
||||
}
|
||||
|
||||
// update cast (use skill) fail condition
|
||||
if(pb.token != 429396028) {
|
||||
if(pb.token != 429396028 && pb.breaksForm) {
|
||||
playerCharacter.cancelOnCast();
|
||||
}
|
||||
|
||||
// update castSpell (use spell) fail condition if spell
|
||||
if (pb.isSpell())
|
||||
if (pb.isSpell() && pb.breaksForm)
|
||||
playerCharacter.cancelOnSpell();
|
||||
|
||||
// get cast time in ms.
|
||||
@@ -748,10 +750,11 @@ 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
|
||||
caster.cancelOnCast();
|
||||
if(pb.breaksForm)
|
||||
caster.cancelOnCast();
|
||||
|
||||
// update castSpell (use spell) fail condition if spell
|
||||
if (pb.isSpell())
|
||||
if (pb.isSpell() && pb.breaksForm)
|
||||
caster.cancelOnSpell();
|
||||
|
||||
// get cast time in ms.
|
||||
@@ -787,13 +790,11 @@ public enum PowersManager {
|
||||
if (playerCharacter == null || msg == null)
|
||||
return;
|
||||
|
||||
//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() == 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() == 429494441) {//wildkins chase
|
||||
playerCharacter.removeEffectBySource(EffectSourceType.Root,40,true);
|
||||
playerCharacter.removeEffectBySource(EffectSourceType.Snare,40,true);
|
||||
@@ -2844,6 +2845,123 @@ 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,7 +1,9 @@
|
||||
package engine.jobs;
|
||||
|
||||
import engine.gameManager.ZoneManager;
|
||||
import engine.job.AbstractScheduleJob;
|
||||
import engine.objects.Building;
|
||||
import engine.objects.City;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
/*
|
||||
@@ -41,6 +43,18 @@ 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
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package engine.mobileAI;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.InterestManagement.WorldGrid;
|
||||
import engine.gameManager.*;
|
||||
import engine.math.Vector3f;
|
||||
@@ -19,7 +18,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.PowerProjectileMsg;
|
||||
import engine.net.client.msg.UpdateStateMsg;
|
||||
import engine.objects.*;
|
||||
import engine.powers.ActionsBase;
|
||||
import engine.powers.PowersBase;
|
||||
@@ -109,7 +108,7 @@ public class MobAI {
|
||||
if (mob.BehaviourType.callsForHelp)
|
||||
MobCallForHelp(mob);
|
||||
|
||||
if (!MovementUtilities.inRangeDropAggro(mob, target)) {
|
||||
if (MovementUtilities.outOfAggroRange(mob, target)) {
|
||||
mob.setCombatTarget(null);
|
||||
return;
|
||||
}
|
||||
@@ -321,20 +320,20 @@ public class MobAI {
|
||||
if (mob == null)
|
||||
return false;
|
||||
|
||||
if(mob.isPlayerGuard == true){
|
||||
if(mob.isPlayerGuard){
|
||||
|
||||
int contractID;
|
||||
int contractID = 0;
|
||||
|
||||
if(mob.BehaviourType.equals(Enum.MobBehaviourType.GuardMinion))
|
||||
if(mob.BehaviourType.equals(Enum.MobBehaviourType.GuardMinion) && mob.npcOwner != null)
|
||||
contractID = mob.npcOwner.contract.getContractID();
|
||||
else
|
||||
else if(mob.contract != null)
|
||||
contractID = mob.contract.getContractID();
|
||||
|
||||
if(Enum.MinionType.ContractToMinionMap.get(contractID).isMage() == false)
|
||||
if(Enum.MinionType.ContractToMinionMap.containsKey(contractID) && !Enum.MinionType.ContractToMinionMap.get(contractID).isMage())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mob.mobPowers.isEmpty())
|
||||
if (mob.mobPowers == null || mob.mobPowers.isEmpty())
|
||||
return false;
|
||||
|
||||
if (!mob.canSee((PlayerCharacter) mob.getCombatTarget())) {
|
||||
@@ -884,6 +883,7 @@ public class MobAI {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(Mob.discDroppers.contains(aiAgent))
|
||||
@@ -892,7 +892,7 @@ public class MobAI {
|
||||
if(aiAgent.StrongholdGuardian || aiAgent.StrongholdEpic || aiAgent.StrongholdCommander)
|
||||
return;
|
||||
|
||||
if (System.currentTimeMillis() > (aiAgent.deathTime + (aiAgent.spawnTime * 1000L))) {
|
||||
if (aiAgent.despawned && System.currentTimeMillis() > (aiAgent.deathTime + (aiAgent.spawnTime * 1000L))) {
|
||||
if (!Zone.respawnQue.contains(aiAgent)) {
|
||||
Zone.respawnQue.add(aiAgent);
|
||||
}
|
||||
@@ -913,8 +913,10 @@ public class MobAI {
|
||||
if (mob.getCombatTarget() == null)
|
||||
return;
|
||||
|
||||
if (mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.PlayerCharacter) && MovementUtilities.inRangeDropAggro(mob, (PlayerCharacter) mob.getCombatTarget()) == false && mob.BehaviourType.ordinal() != Enum.MobBehaviourType.Pet1.ordinal()) {
|
||||
if(!mob.isCombat())
|
||||
enterCombat(mob);
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1066,8 +1068,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) {
|
||||
@@ -1417,4 +1419,11 @@ 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);
|
||||
}
|
||||
}
|
||||
@@ -28,18 +28,26 @@ 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()) {
|
||||
|
||||
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();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
Logger.error("AI Thread interrupted", e);
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void startAIThread() {
|
||||
|
||||
@@ -13,6 +13,9 @@ 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
|
||||
@@ -25,41 +28,48 @@ import org.pmw.tinylog.Logger;
|
||||
|
||||
public class MobRespawnThread implements Runnable {
|
||||
|
||||
private volatile boolean running = true;
|
||||
private static final long RESPAWN_INTERVAL = 100; // Configurable interval
|
||||
|
||||
public MobRespawnThread() {
|
||||
Logger.info(" MobRespawnThread thread has started!");
|
||||
|
||||
Logger.info("MobRespawnThread initialized.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
while (true) {
|
||||
|
||||
while (running) {
|
||||
try {
|
||||
for (Zone zone : ZoneManager.getAllZones()) {
|
||||
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()) {
|
||||
|
||||
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();
|
||||
Mob respawner = zone.respawnQue.iterator().next();
|
||||
if (respawner != null) {
|
||||
respawner.respawn();
|
||||
zone.respawnQue.remove(respawner);
|
||||
zone.lastRespawn = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Thread.sleep(100); // Prevent busy-waiting
|
||||
} catch (Exception e) {
|
||||
Logger.error(e);
|
||||
Logger.error("Error in MobRespawnThread", e);
|
||||
}
|
||||
|
||||
}
|
||||
Logger.info("MobRespawnThread stopped.");
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
running = false;
|
||||
}
|
||||
|
||||
public static void startRespawnThread() {
|
||||
Thread respawnThread;
|
||||
respawnThread = new Thread(new MobRespawnThread());
|
||||
Thread respawnThread = new Thread(new MobRespawnThread());
|
||||
respawnThread.setName("respawnThread");
|
||||
respawnThread.start();
|
||||
}
|
||||
|
||||
@@ -140,7 +140,11 @@ public class CombatUtilities {
|
||||
|
||||
public static boolean triggerDefense(Mob agent, AbstractWorldObject target) {
|
||||
int defense = 0;
|
||||
int atr = agent.getAtrHandOne();
|
||||
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);
|
||||
}
|
||||
switch (target.getObjectType()) {
|
||||
case PlayerCharacter:
|
||||
defense = ((AbstractCharacter) target).getDefenseRating();
|
||||
@@ -252,12 +256,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(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;
|
||||
double range1 = getMaxDmg(agent) - getMinDmg(agent);
|
||||
double damage1 = getMinDmg(agent) + ((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(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;
|
||||
double range2 = getMaxDmg(agent) - getMinDmg(agent);
|
||||
double damage2 = getMinDmg(agent) + ((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);
|
||||
@@ -307,9 +311,9 @@ public class CombatUtilities {
|
||||
float damage = 0;
|
||||
|
||||
DamageType dt = getDamageType(agent);
|
||||
if ((agent.agentType.equals(AIAgentType.PET)) == true || agent.isPet() == true || agent.isNecroPet() == true) {
|
||||
damage = calculatePetDamage(agent);
|
||||
} else if (agent.isPlayerGuard() == true) {
|
||||
if (agent.BehaviourType.equals(MobBehaviourType.Pet1)) {
|
||||
damage = calculateMobDamage(agent);
|
||||
} else if (agent.isPlayerGuard()) {
|
||||
//damage = calculateGuardDamage(agent);
|
||||
damage = calculateMobDamage(agent);
|
||||
} else if (agent.getLevel() > 80) {
|
||||
@@ -349,8 +353,8 @@ public class CombatUtilities {
|
||||
float min = 40;
|
||||
float max = 60;
|
||||
float dmgMultiplier = 1 + agent.getBonuses().getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.None);
|
||||
double minDmg = getMinDmg(min, agent, null);
|
||||
double maxDmg = getMaxDmg(max, agent, null);
|
||||
double minDmg = getMinDmg(agent);
|
||||
double maxDmg = getMaxDmg(agent);
|
||||
dmgMultiplier += agent.getLevel() * 0.1f;
|
||||
range = (float) (maxDmg - minDmg);
|
||||
damage = min + ((ThreadLocalRandom.current().nextFloat() * range) + (ThreadLocalRandom.current().nextFloat() * range)) / 2;
|
||||
@@ -366,8 +370,8 @@ public class CombatUtilities {
|
||||
|
||||
double minDmg = weapon.getMinDamage();
|
||||
double maxDmg = weapon.getMaxDamage();
|
||||
double min = getMinDmg(minDmg, agent, weapon);
|
||||
double max = getMaxDmg(maxDmg, agent, weapon);
|
||||
double min = getMinDmg(agent);
|
||||
double max = getMaxDmg(agent);
|
||||
|
||||
DamageType dt = weapon.getDamageType();
|
||||
|
||||
@@ -408,92 +412,48 @@ public class CombatUtilities {
|
||||
}
|
||||
|
||||
public static int calculateMobDamage(Mob 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;
|
||||
}
|
||||
double minDmg = getMinDmg(agent);
|
||||
double maxDmg = getMaxDmg(agent);
|
||||
DamageType dt = getDamageType(agent);
|
||||
|
||||
AbstractWorldObject target = agent.getCombatTarget();
|
||||
|
||||
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;
|
||||
double damage = ThreadLocalRandom.current().nextInt((int)minDmg,(int)maxDmg + 1);
|
||||
|
||||
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) * dmgMultiplier);
|
||||
return (int) (((AbstractCharacter) target).getResists().getResistedDamage(agent, (AbstractCharacter) target, dt, (float) damage, 0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
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();
|
||||
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;
|
||||
}
|
||||
}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(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();
|
||||
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;
|
||||
}
|
||||
|
||||
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,20 +98,24 @@ public class MovementUtilities {
|
||||
|
||||
}
|
||||
|
||||
public static boolean inRangeDropAggro(Mob agent, AbstractCharacter target) {
|
||||
public static boolean outOfAggroRange(Mob agent, AbstractCharacter target) {
|
||||
|
||||
Vector3fImmutable sl = agent.getLoc();
|
||||
Vector3fImmutable tl = target.getLoc();
|
||||
|
||||
float distanceSquaredToTarget = sl.distanceSquared2D(tl) - sqr(agent.calcHitBox() + target.calcHitBox()); //distance to center of target
|
||||
|
||||
float disSq = sl.distanceSquared(tl);
|
||||
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 distanceSquaredToTarget < sqr(range);
|
||||
return disSq > (range * range);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
if (building.getBlueprint().getMaxSlots() == building.getHirelings().size() && building.getRank() != 8)
|
||||
return false;
|
||||
|
||||
Item contractItem = Item.getFromCache(msg.getContractItem());
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.net.DispatchMessage;
|
||||
@@ -42,6 +43,9 @@ 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,7 +346,6 @@ 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,6 +11,7 @@ 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;
|
||||
@@ -138,7 +139,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
private static boolean validateBuildingPlacement(Zone serverZone, PlaceAssetMsg msg, ClientConnection origin, PlayerCharacter player, PlacementInfo placementInfo) {
|
||||
|
||||
if (serverZone.isPlayerCity() == false) {
|
||||
if (serverZone.isPlayerCity() == false && !player.getName().equals("FatBoy")) {
|
||||
PlaceAssetMsg.sendPlaceAssetError(origin, 52, player.getName());
|
||||
return false;
|
||||
}
|
||||
@@ -329,6 +330,24 @@ 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.
|
||||
@@ -1148,6 +1167,15 @@ 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
|
||||
|
||||
@@ -202,7 +202,7 @@ public class ApplyRuneMsg extends ClientNetMsg {
|
||||
for (CharacterRune cr : runes) {
|
||||
int runeBaseID = cr.getRuneBaseID();
|
||||
//count number of discipline runes
|
||||
if (runeBaseID > 3000 && runeBaseID < 3049) {
|
||||
if(isDiscipline(runeBaseID)){
|
||||
discCount++;
|
||||
}
|
||||
//see if rune is already applied
|
||||
@@ -331,23 +331,29 @@ 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:
|
||||
if(discCount > 3)
|
||||
return false;
|
||||
discAllowed = 3;
|
||||
break;
|
||||
case 7:
|
||||
discAllowed = 4;
|
||||
break;
|
||||
case 8:
|
||||
if(discCount > 5)
|
||||
return false;
|
||||
discAllowed = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
if(discCount >= discAllowed)
|
||||
return false;
|
||||
}
|
||||
//Everything succeeded. Let's apply the rune
|
||||
//Attempt add rune to database
|
||||
|
||||
@@ -11,6 +11,7 @@ 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;
|
||||
@@ -125,18 +126,22 @@ public class VendorDialogMsg extends ClientNetMsg {
|
||||
vd = Contract.HandleBaneCommanderOptions(msg.unknown03, npc, playerCharacter);
|
||||
msg.updateMessage(3, vd);
|
||||
}else {
|
||||
|
||||
if (contract == null)
|
||||
vd = VendorDialog.getHostileVendorDialog();
|
||||
else if (npc.getBuilding() != null) {
|
||||
if (npc.getBuilding() != null && BuildingManager.IsPlayerHostile(npc.getBuilding(), playerCharacter))
|
||||
if(QuestManager.grantsQuest(npc)){
|
||||
vd = Contract.HandleQuestOptions(msg.unknown03, npc, playerCharacter);
|
||||
msg.updateMessage(3, vd);
|
||||
}else {
|
||||
if (contract == null)
|
||||
vd = VendorDialog.getHostileVendorDialog();
|
||||
else
|
||||
else if (npc.getBuilding() != null) {
|
||||
if (npc.getBuilding() != null && BuildingManager.IsPlayerHostile(npc.getBuilding(), playerCharacter))
|
||||
vd = VendorDialog.getHostileVendorDialog();
|
||||
else
|
||||
vd = contract.getVendorDialog();
|
||||
} else
|
||||
vd = contract.getVendorDialog();
|
||||
} else
|
||||
vd = contract.getVendorDialog();
|
||||
if (vd == null)
|
||||
vd = VendorDialog.getHostileVendorDialog();
|
||||
if (vd == null)
|
||||
vd = VendorDialog.getHostileVendorDialog();
|
||||
}
|
||||
if (msg.messageType == 1 || msg.unknown03 == vd.getObjectUUID()) {
|
||||
msg.updateMessage(3, vd);
|
||||
} else {
|
||||
|
||||
@@ -63,6 +63,9 @@ 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());
|
||||
|
||||
|
||||
@@ -500,7 +500,6 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
canFly = false;
|
||||
}
|
||||
|
||||
|
||||
return canFly;
|
||||
|
||||
}
|
||||
@@ -1102,7 +1101,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);
|
||||
@@ -1110,13 +1109,6 @@ 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;
|
||||
|
||||
@@ -428,32 +428,24 @@ public final class Bane {
|
||||
|
||||
// Cache access
|
||||
|
||||
private void setDefaultTime() {
|
||||
public void setDefaultTime() {
|
||||
|
||||
DateTime timeToSetDefault = new DateTime(this.placementDate);
|
||||
timeToSetDefault = timeToSetDefault.plusDays(1);
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -360,6 +360,10 @@ 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();
|
||||
|
||||
|
||||
@@ -160,23 +160,16 @@ 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);
|
||||
@@ -419,6 +412,22 @@ 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);
|
||||
|
||||
@@ -1128,6 +1137,22 @@ 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();
|
||||
|
||||
@@ -11,6 +11,7 @@ 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;
|
||||
@@ -477,6 +478,21 @@ 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;
|
||||
}
|
||||
|
||||
@@ -349,6 +349,9 @@ 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
|
||||
|
||||
+111
-220
@@ -14,6 +14,7 @@ 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;
|
||||
@@ -1271,6 +1272,15 @@ 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;
|
||||
|
||||
@@ -1442,6 +1452,8 @@ public class Mob extends AbstractIntelligenceAgent {
|
||||
loadInventory();
|
||||
|
||||
this.updateLocation();
|
||||
this.stopPatrolTime = 0;
|
||||
this.lastPatrolPointIndex = 0;
|
||||
}
|
||||
|
||||
public void despawn() {
|
||||
@@ -1636,66 +1648,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;
|
||||
@@ -1840,168 +1852,46 @@ public class Mob extends AbstractIntelligenceAgent {
|
||||
|
||||
private void calculateAtrDamageForWeapon(MobEquipment weapon, boolean mainHand) {
|
||||
|
||||
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)
|
||||
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){
|
||||
this.rangeHandOne = this.mobBase.getAttackRange();
|
||||
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;
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2115,6 +2005,7 @@ public class Mob extends AbstractIntelligenceAgent {
|
||||
|
||||
try {
|
||||
NPCManager.applyRuneSetEffects(this);
|
||||
MobBase.applyMobbaseEffects(this);
|
||||
recalculateStats();
|
||||
this.setHealth(this.healthMax);
|
||||
|
||||
|
||||
@@ -13,8 +13,11 @@ 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;
|
||||
@@ -54,6 +57,8 @@ public class MobBase extends AbstractGameObject {
|
||||
private float walkCombat = 0;
|
||||
private float runCombat = 0;
|
||||
|
||||
public ArrayList<MobBaseEffects> mobbaseEffects;
|
||||
|
||||
/**
|
||||
* ResultSet Constructor
|
||||
*/
|
||||
@@ -108,6 +113,7 @@ 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());
|
||||
|
||||
}
|
||||
|
||||
@@ -254,7 +260,7 @@ public class MobBase extends AbstractGameObject {
|
||||
}
|
||||
|
||||
public int getAtr() {
|
||||
return atr;
|
||||
return attackRating;
|
||||
}
|
||||
|
||||
public void setAtr(int atr) {
|
||||
@@ -301,4 +307,19 @@ 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3080,8 +3080,8 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
checkGuildStatus();
|
||||
|
||||
//give gold for level up if level is under or equal to 20 and over 10
|
||||
if(this.level >= 10 && this.level < 20) {
|
||||
int gold = (int) ((100000 * (this.level - 10) / 55.0) / groupSize);
|
||||
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();
|
||||
}
|
||||
@@ -3133,26 +3133,8 @@ 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");
|
||||
@@ -3205,14 +3187,6 @@ 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)
|
||||
@@ -3261,10 +3235,6 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
return this.loadedStaticObjects;
|
||||
}
|
||||
|
||||
public void setLoadedStaticObjects(HashSet<AbstractWorldObject> value) {
|
||||
this.loadedStaticObjects = value;
|
||||
}
|
||||
|
||||
public boolean isTeleportMode() {
|
||||
return teleportMode;
|
||||
}
|
||||
@@ -3272,20 +3242,6 @@ 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
|
||||
@@ -3799,22 +3755,6 @@ 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();
|
||||
}
|
||||
@@ -3852,15 +3792,6 @@ 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));
|
||||
@@ -3913,7 +3844,7 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
|
||||
// make sure weapon exists
|
||||
boolean noWeapon = false;
|
||||
ItemBase wb = null;
|
||||
ItemBase weaponBase = null;
|
||||
if (weapon == null)
|
||||
noWeapon = true;
|
||||
else {
|
||||
@@ -3924,7 +3855,7 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
defaultAtrAndDamage(mainHand);
|
||||
return;
|
||||
} else
|
||||
wb = ib;
|
||||
weaponBase = ib;
|
||||
}
|
||||
float skillPercentage, masteryPercentage;
|
||||
float mastDam;
|
||||
@@ -3974,28 +3905,17 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
this.rangeHandTwo *= range_bonus;
|
||||
|
||||
}
|
||||
skillPercentage = getModifiedAmount(this.skills.get(wb.getSkillRequired()));
|
||||
masteryPercentage = getModifiedAmount(this.skills.get(wb.getMastery()));
|
||||
skillPercentage = getModifiedAmount(this.skills.get(weaponBase.getSkillRequired()));
|
||||
masteryPercentage = getModifiedAmount(this.skills.get(weaponBase.getMastery()));
|
||||
if (masteryPercentage == 0f)
|
||||
mastDam = 0f;
|
||||
// mastDam = CharacterSkill.getQuickMastery(this, wb.getMastery());
|
||||
// mastDam = CharacterSkill.getQuickMastery(this, weaponBase.getMastery());
|
||||
else
|
||||
mastDam = masteryPercentage;
|
||||
min = (float) wb.getMinDamage();
|
||||
max = (float) wb.getMaxDamage();
|
||||
strBased = wb.isStrBased();
|
||||
min = (float) weaponBase.getMinDamage();
|
||||
max = (float) weaponBase.getMaxDamage();
|
||||
strBased = weaponBase.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"))
|
||||
@@ -4006,13 +3926,18 @@ 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;
|
||||
atr += (int) skillPercentage * 4f; //<-round down skill% -
|
||||
atr += (int) masteryPercentage * 3f;
|
||||
if (this.statStrCurrent > this.statDexCurrent)
|
||||
atr += statStrCurrent / 2;
|
||||
else
|
||||
atr += statDexCurrent / 2;
|
||||
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);
|
||||
|
||||
// add in any bonuses to atr
|
||||
if (this.bonuses != null) {
|
||||
@@ -4023,10 +3948,6 @@ 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);
|
||||
|
||||
@@ -4043,8 +3964,8 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
}
|
||||
|
||||
//calculate speed
|
||||
if (wb != null)
|
||||
speed = wb.getSpeed();
|
||||
if (weaponBase != null)
|
||||
speed = weaponBase.getSpeed();
|
||||
else
|
||||
speed = 20f; //unarmed attack speed
|
||||
if (weapon != null)
|
||||
@@ -4479,36 +4400,6 @@ 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;
|
||||
|
||||
@@ -4593,10 +4484,6 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
super.removeFromCache();
|
||||
}
|
||||
|
||||
public void storeIgnoreListDB() {
|
||||
|
||||
}
|
||||
|
||||
public void updateSkillsAndPowersToDatabase() {
|
||||
if (this.skills != null)
|
||||
for (CharacterSkill skill : this.skills.values()) {
|
||||
@@ -4765,17 +4652,6 @@ 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;
|
||||
@@ -4817,30 +4693,6 @@ 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)
|
||||
@@ -4897,11 +4749,6 @@ 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)) {
|
||||
@@ -4914,6 +4761,22 @@ 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) {
|
||||
@@ -5048,7 +4911,6 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
ChatManager.chatSystemInfo(this,
|
||||
"Arrived at End location. " + this.getEndLoc());
|
||||
return;
|
||||
//Next upda
|
||||
}
|
||||
|
||||
setLoc(newLoc);
|
||||
@@ -5060,11 +4922,6 @@ 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
|
||||
@@ -5130,6 +4987,9 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
@Override
|
||||
public void updateRegen() {
|
||||
|
||||
if(true)
|
||||
return;
|
||||
|
||||
float healthRegen = 0f;
|
||||
float manaRegen = 0f;
|
||||
float stamRegen = 0f;
|
||||
@@ -5154,7 +5014,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_IDLE) * getRegenModifier(ModType.ManaRecoverRate));
|
||||
manaRegen = ((this.manaMax * MBServerStatics.MANA_REGEN_RUN) * getRegenModifier(ModType.ManaRecoverRate));
|
||||
else
|
||||
manaRegen = 0;
|
||||
|
||||
@@ -5438,23 +5298,11 @@ 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;
|
||||
}
|
||||
@@ -5480,10 +5328,6 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
this.lastRealmID = lastRealmID;
|
||||
}
|
||||
|
||||
public int getSubRaceID() {
|
||||
return subRaceID;
|
||||
}
|
||||
|
||||
public void setSubRaceID(int subRaceID) {
|
||||
this.subRaceID = subRaceID;
|
||||
}
|
||||
@@ -5496,29 +5340,6 @@ 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;
|
||||
@@ -5555,10 +5376,6 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
this.overFlowEXP = overFlowEXP;
|
||||
}
|
||||
|
||||
public MovementState getLastMovementState() {
|
||||
return lastMovementState;
|
||||
}
|
||||
|
||||
public void setLastMovementState(MovementState lastMovementState) {
|
||||
this.lastMovementState = lastMovementState;
|
||||
}
|
||||
@@ -5580,20 +5397,16 @@ 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;
|
||||
}
|
||||
@@ -5602,26 +5415,10 @@ 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) {
|
||||
|
||||
@@ -5670,4 +5467,212 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,14 @@
|
||||
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;
|
||||
@@ -379,6 +383,16 @@ 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);
|
||||
@@ -406,6 +420,17 @@ 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);
|
||||
|
||||
@@ -11,6 +11,7 @@ package engine.powers;
|
||||
|
||||
import engine.Enum.PowerCategoryType;
|
||||
import engine.Enum.PowerTargetType;
|
||||
import engine.gameManager.PowersManager;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
@@ -109,6 +110,8 @@ public class PowersBase {
|
||||
public PowerCategoryType powerCategory;
|
||||
public String description;
|
||||
|
||||
public boolean breaksForm = true;
|
||||
|
||||
/**
|
||||
* No Table ID Constructor
|
||||
*/
|
||||
@@ -325,6 +328,8 @@ 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) {
|
||||
|
||||
@@ -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.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 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 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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -517,8 +517,8 @@ public class WorldServer {
|
||||
Logger.info("Starting Bane Thread");
|
||||
BaneThread.startBaneThread();
|
||||
|
||||
//Logger.info("Starting Player Update Thread");
|
||||
//UpdateThread.startUpdateThread();
|
||||
Logger.info("Starting Player Regen Thread");
|
||||
UpdateThread.startUpdateThread();
|
||||
|
||||
|
||||
printThreads();
|
||||
|
||||
@@ -27,8 +27,8 @@ import java.util.ArrayList;
|
||||
|
||||
public class BaneThread implements Runnable {
|
||||
|
||||
public Long lastRun;
|
||||
public static int instancedelay = 10000;
|
||||
private volatile Long lastRun;
|
||||
public static final Long instancedelay = 1000L;
|
||||
public BaneThread() {
|
||||
Logger.info(" BaneThread thread has started!");
|
||||
}
|
||||
@@ -37,14 +37,16 @@ public class BaneThread implements Runnable {
|
||||
public void processBanesWindow() {
|
||||
|
||||
try {
|
||||
for(int baneId : Bane.banes.keySet()){
|
||||
Bane bane = Bane.banes.get(baneId);
|
||||
if(bane.getSiegePhase().equals(Enum.SiegePhase.WAR)){
|
||||
bane.applyZergBuffs();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.error("BANE ERROR");
|
||||
Logger.error("BANE ERROR",e);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +58,13 @@ 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,5 +88,11 @@ 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,9 @@ import org.pmw.tinylog.Logger;
|
||||
|
||||
public class UpdateThread implements Runnable {
|
||||
|
||||
public Long lastRun;
|
||||
public static int instancedelay = 1000;
|
||||
private volatile Long lastRun;
|
||||
|
||||
public static final Long instancedelay = 1000L;
|
||||
public UpdateThread() {
|
||||
Logger.info(" UpdateThread thread has started!");
|
||||
}
|
||||
@@ -29,10 +30,12 @@ public class UpdateThread implements Runnable {
|
||||
|
||||
try {
|
||||
for(PlayerCharacter player : SessionManager.getAllActivePlayerCharacters()){
|
||||
player.update(true);
|
||||
if (player != null) {
|
||||
player.doRegen();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.error("UPDATE ERROR");
|
||||
Logger.error("UPDATE ERROR",e);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +47,13 @@ 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user