Merge branch 'lakebane-jobs' into lakebane

# Conflicts:
#	src/engine/gameManager/CombatManager.java
#	src/engine/gameManager/PowersManager.java
#	src/engine/mobileAI/MobAI.java
#	src/engine/objects/Experience.java
#	src/engine/objects/PlayerCharacter.java
#	src/engine/objects/PlayerCombatStats.java
#	src/engine/util/KeyCloneAudit.java
#	src/engine/workthreads/UpdateThread.java
This commit is contained in:
2025-03-03 18:42:25 -06:00
49 changed files with 1909 additions and 627 deletions
+18 -18
View File
@@ -1187,13 +1187,13 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
public final float modifyHealth(float value, final AbstractCharacter attacker, final boolean fromCost) {
if(attacker != null && attacker.getObjectType().equals(GameObjectType.PlayerCharacter)){
value *= ((PlayerCharacter)attacker).ZergMultiplier;
} // Health modifications are modified by the ZergMechanic
//if(attacker != null && attacker.getObjectType().equals(GameObjectType.PlayerCharacter)){
// value *= ((PlayerCharacter)attacker).ZergMultiplier;
//} // Health modifications are modified by the ZergMechanic
if(attacker != null && attacker.getObjectType().equals(GameObjectType.Mob) && ((Mob)attacker).getOwner() != null){
value *= ((Mob)attacker).getOwner().ZergMultiplier;
}// Health modifications from pets are modified by the owner's ZergMechanic
//if(attacker != null && attacker.getObjectType().equals(GameObjectType.Mob) && ((Mob)attacker).getOwner() != null){
// value *= ((Mob)attacker).getOwner().ZergMultiplier;
//}// Health modifications from pets are modified by the owner's ZergMechanic
try {
@@ -1262,13 +1262,13 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
final boolean fromCost
) {
if(attacker != null && attacker.getObjectType().equals(GameObjectType.PlayerCharacter)){
value *= ((PlayerCharacter)attacker).ZergMultiplier;
} // Health modifications are modified by the ZergMechanic
//if(attacker != null && attacker.getObjectType().equals(GameObjectType.PlayerCharacter)){
// value *= ((PlayerCharacter)attacker).ZergMultiplier;
//} // Health modifications are modified by the ZergMechanic
if(attacker != null && attacker.getObjectType().equals(GameObjectType.Mob) && ((Mob)attacker).getOwner() != null){
value *= ((Mob)attacker).getOwner().ZergMultiplier;
}// Health modifications from pets are modified by the owner's ZergMechanic
//if(attacker != null && attacker.getObjectType().equals(GameObjectType.Mob) && ((Mob)attacker).getOwner() != null){
// value *= ((Mob)attacker).getOwner().ZergMultiplier;
//}// Health modifications from pets are modified by the owner's ZergMechanic
if (!this.isAlive()) {
return 0f;
@@ -1309,13 +1309,13 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
final boolean fromCost
) {
if(attacker != null && attacker.getObjectType().equals(GameObjectType.PlayerCharacter)){
value *= ((PlayerCharacter)attacker).ZergMultiplier;
} // Health modifications are modified by the ZergMechanic
//if(attacker != null && attacker.getObjectType().equals(GameObjectType.PlayerCharacter)){
// value *= ((PlayerCharacter)attacker).ZergMultiplier;
//} // Health modifications are modified by the ZergMechanic
if(attacker != null && attacker.getObjectType().equals(GameObjectType.Mob) && ((Mob)attacker).getOwner() != null){
value *= ((Mob)attacker).getOwner().ZergMultiplier;
}// Health modifications from pets are modified by the owner's ZergMechanic
//if(attacker != null && attacker.getObjectType().equals(GameObjectType.Mob) && ((Mob)attacker).getOwner() != null){
// value *= ((Mob)attacker).getOwner().ZergMultiplier;
//}// Health modifications from pets are modified by the owner's ZergMechanic
if (!this.isAlive()) {
return 0f;
+28 -7
View File
@@ -15,6 +15,7 @@ import engine.Enum.GameObjectType;
import engine.Enum.GridObjectType;
import engine.InterestManagement.HeightMap;
import engine.InterestManagement.WorldGrid;
import engine.gameManager.ZoneManager;
import engine.job.AbstractScheduleJob;
import engine.job.JobContainer;
import engine.job.JobScheduler;
@@ -175,11 +176,11 @@ public abstract class AbstractWorldObject extends AbstractGameObject {
}
//set players new altitude to region lerp altitude.
if (region != null)
if (region.center.y == region.highLerp.y)
worldObject.loc = worldObject.loc.setY(region.center.y + worldObject.getAltitude());
else
worldObject.loc = worldObject.loc.setY(region.lerpY(worldObject) + worldObject.getAltitude());
//if (region != null)
// if (region.center.y == region.highLerp.y)
// worldObject.loc = worldObject.loc.setY(region.center.y + worldObject.getAltitude());
// else
// worldObject.loc = worldObject.loc.setY(region.lerpY(worldObject) + worldObject.getAltitude());
return region;
}
@@ -500,8 +501,28 @@ public abstract class AbstractWorldObject extends AbstractGameObject {
if (loc.x > MBServerStatics.MAX_WORLD_WIDTH || loc.z < MBServerStatics.MAX_WORLD_HEIGHT)
return;
this.lastLoc = new Vector3fImmutable(this.loc);
this.loc = loc;
this.loc = this.loc.setY(HeightMap.getWorldHeight(this) + this.getAltitude());
if(AbstractCharacter.IsAbstractCharacter(this)){
float y;
float worldHeight = HeightMap.getWorldHeight(loc);
Zone zone = ZoneManager.findSmallestZone(loc);
if(zone != null && zone.isPlayerCity()){
worldHeight = zone.getWorldAltitude();
}
if(this.region != null){
float regionAlt = this.region.lerpY(this);
float altitude = this.getAltitude();
y = regionAlt + altitude + worldHeight;
}else{
y = HeightMap.getWorldHeight(loc) + this.getAltitude();
}
Vector3fImmutable newLoc = new Vector3fImmutable(loc.x,y,loc.z);
this.loc = newLoc;
WorldGrid.addObject(this, newLoc.x, newLoc.z);
return;
}else{
this.loc = loc;
}
//this.loc = this.loc.setY(HeightMap.getWorldHeight(this) + this.getAltitude());
//lets not add mob to world grid if he is currently despawned.
if (this.getObjectType().equals(GameObjectType.Mob) && ((Mob) this).despawned)
@@ -1058,6 +1058,7 @@ public class CharacterItemManager {
i.addToCache();
try {
i.stripCastableEnchants();
this.updateInventory();
}catch(Exception ignored){
Logger.error("FAILED TO STRIP CASTABLE ENCHANTS: Move Item To Bank");
}
@@ -1203,6 +1204,7 @@ public class CharacterItemManager {
try {
i.stripCastableEnchants();
this.updateInventory();
}catch(Exception ignored){
Logger.error("FAILED TO STRIP CASTABLE ENCHANTS: Move Item To Vault");
}
@@ -2448,6 +2450,9 @@ public class CharacterItemManager {
public void damageItem(Item item, int amount) {
if (item == null || amount < 1 || amount > 5)
return;
if(item.getItemBase().isGlass()){
amount = 1;
}
//verify the item is equipped by this player
int slot = item.getEquipSlot();
+1 -1
View File
@@ -455,7 +455,7 @@ public class City extends AbstractWorldObject {
if (!BuildingManager.IsPlayerHostile(city.getTOL(), pc))
cities.add(city); //verify nation or guild is same
} else if (Guild.sameNationExcludeErrant(city.getGuild(), pcG))
} else if (city.open && Guild.sameNationExcludeErrant(city.getGuild(), pcG))
cities.add(city);
} else if (city.isNpc == 1) {
+38 -8
View File
@@ -16,6 +16,7 @@ import engine.net.Dispatch;
import engine.net.DispatchMessage;
import engine.net.client.msg.CityDataMsg;
import engine.net.client.msg.ErrorPopupMsg;
import engine.net.client.msg.VendorDialogMsg;
import org.joda.time.DateTime;
import org.pmw.tinylog.Logger;
@@ -323,6 +324,12 @@ public class Contract extends AbstractGameObject {
pc.charItemManager.updateInventory();
}
public static boolean isClassTrainer(int id){
if(id >= 5 && id <= 30)
return true;
return false;
}
public static VendorDialog HandleBaneCommanderOptions(int optionId, NPC npc, PlayerCharacter pc){
pc.setLastNPCDialog(npc);
VendorDialog vd = new VendorDialog(VendorDialog.getHostileVendorDialog().getDialogType(),VendorDialog.getHostileVendorDialog().getIntro(),-1);//VendorDialog.getHostileVendorDialog();
@@ -580,6 +587,19 @@ public class Contract extends AbstractGameObject {
}
}
if(this.getObjectUUID() == 1502050){
for(MobEquipment me : this.sellInventory){
switch(me.getItemBase().getUUID()) {
case 971070:
me.magicValue = 3000000;
break;
case 971012:
me.magicValue = 1000000;
break;
}
}
}
if(this.getObjectUUID() == 1202){ //rune merchant
for(MobEquipment me : this.sellInventory){
switch(me.getItemBase().getUUID()){
@@ -588,52 +608,62 @@ public class Contract extends AbstractGameObject {
case 250019:
case 250028:
case 250037:
me.magicValue = 3000000;
me.magicValue = 1000000;
break;
case 250002: //10 stats
case 250011:
case 250020:
case 250029:
case 250038:
me.magicValue = 4000000;
me.magicValue = 2000000;
break;
case 250003: //15 stats
case 250012:
case 250021:
case 250030:
case 250039:
me.magicValue = 5000000;
me.magicValue = 3000000;
break;
case 250004: //20 stats
case 250013:
case 250022:
case 250031:
case 250040:
me.magicValue = 6000000;
me.magicValue = 4000000;
break;
case 250005: //25 stats
case 250014:
case 250023:
case 250032:
case 250041:
me.magicValue = 7000000;
me.magicValue = 5000000;
break;
case 250006: //30 stats
case 250015:
case 250024:
case 250033:
case 250042:
me.magicValue = 8000000;
me.magicValue = 6000000;
break;
case 250007: //35 stats
case 250016:
case 250025:
case 250034:
case 250043:
me.magicValue = 9000000;
me.magicValue = 7000000;
break;
case 250008: //40 stats
case 250017:
case 250026:
case 250035:
case 250044:
me.magicValue = 10000000;
break;
case 252127:
me.magicValue = 5000000;
break;
default:
me.magicValue = 10000000;
me.magicValue = 1000000;
break;
}
}
+120 -42
View File
@@ -11,7 +11,6 @@ package engine.objects;
import engine.Enum;
import engine.Enum.TargetColor;
import engine.gameManager.LootManager;
import engine.gameManager.ZoneManager;
import engine.math.Vector3fImmutable;
import engine.server.MBServerStatics;
@@ -24,7 +23,7 @@ import static engine.gameManager.LootManager.LOOTMANAGER;
public class Experience {
private static final TreeMap<Integer, Integer> ExpToLevel;
private static final int[] LevelToExp = {Integer.MIN_VALUE, // Pad
public static final int[] LevelToExp = {Integer.MIN_VALUE, // Pad
// everything
// over 1
@@ -122,6 +121,8 @@ public class Experience {
190585732, // Level 77
201714185, // Level 78
213319687, // Level 79
// R8
225415457, // Level 80
238014819 // Level 81
@@ -303,7 +304,7 @@ public class Experience {
case Cyan:
return 0.9;
case Green:
return 0.7;
return 0.8;
default:
return 0;
}
@@ -353,66 +354,143 @@ public class Experience {
if(killer.pvpKills.contains(mob.getObjectUUID()))
return;
double baseXP;
if(true){
if(killer.combatStats == null)
killer.combatStats = new PlayerCombatStats(killer);
if(g != null) {
//group experience
PlayerCharacter leader = g.getGroupLead();
float leadership = 0.0f;
if(leader.skills.containsKey("Leadership"))
leadership = leader.skills.get("Leadership").getModifiedAmount();
killer.combatStats.grantExperience(mob,g);
return;
}
for(PlayerCharacter member : g.members){
double grantedExperience = 0.0;
if (member.getLevel() >= MBServerStatics.LEVELCAP)
continue;
if (g != null) { // Do group EXP stuff
if(member.level >= 75 && !mob.getObjectType().equals(Enum.GameObjectType.PlayerCharacter))
continue; // cannot PVE higher than level 75
int leadership = 0;
int highestLevel = 0;
double penalty = 0.0;
float range = member.loc.distanceSquared(killer.loc);
if(range <= (MBServerStatics.CHARACTER_LOAD_RANGE * MBServerStatics.CHARACTER_LOAD_RANGE)){
baseXP = LootManager.NORMAL_EXP_RATE * maxXPPerKill(member.getLevel());
double mod = getConMod(member, mob);
ArrayList<PlayerCharacter> giveEXPTo = new ArrayList<>();
if(leadership > 0 && mod != 0)
mod += (leadership * 0.01f);
// Check if leader is within range of kill and then get leadership
// skill
baseXP *= mod;
Vector3fImmutable killLoc = mob.getLoc();
if(baseXP < 1)
baseXP = 1;
if (killLoc.distanceSquared2D(g.getGroupLead().getLoc()) < (MBServerStatics.EXP_RANGE * MBServerStatics.EXP_RANGE)) {
CharacterSkill leaderskill = g.getGroupLead().skills
.get("Leadership");
baseXP *= (1.0f / g.members.size()+0.9f);
if (leaderskill != null)
leadership = leaderskill.getNumTrains();
if (leadership > 90)
leadership = 90; // leadership caps at 90%
}
member.grantXP((int) baseXP);
// Check every group member for distance to see if they get xp
for (PlayerCharacter pc : g.getMembers()) {
if (pc.isAlive()) { // Skip if the player is dead.
// Check within range
if (killLoc.distanceSquared2D(pc.getLoc()) < (MBServerStatics.EXP_RANGE * MBServerStatics.EXP_RANGE)) {
giveEXPTo.add(pc);
// Track highest level character
if (pc.getLevel() > highestLevel)
highestLevel = pc.getLevel();
}
}
}
}else{
//solo no group
// Process every player in the group getting XP
for (PlayerCharacter playerCharacter : giveEXPTo) {
if (playerCharacter.getLevel() >= MBServerStatics.LEVELCAP)
continue;
if(playerCharacter.level >= 75 && !mob.getObjectType().equals(Enum.GameObjectType.PlayerCharacter))
continue; // cannot PVE higher than level 75
// Sets Max XP with server exp mod taken into account.
grantedExperience = (double) LOOTMANAGER.NORMAL_EXP_RATE * maxXPPerKill(playerCharacter.getLevel());
// Adjust XP for Mob Level
grantedExperience *= getConMod(playerCharacter, mob);
// Process XP for this member
penalty = getGroupMemberPenalty(leadership, playerCharacter, giveEXPTo,
highestLevel);
// Leadership Penalty Reduction
if (leadership > 0)
penalty -= ((leadership) * 0.01) * penalty;
// Modify for hotzone
if (grantedExperience != 0)
if (ZoneManager.inHotZone(mob.getLoc()))
grantedExperience *= LOOTMANAGER.HOTZONE_EXP_RATE;
// Check for 0 XP due to white mob, otherwise subtract penalty
// xp
if (grantedExperience == 0)
grantedExperience = 1;
else {
grantedExperience -= (penalty * 0.01) * grantedExperience;
// Errant Penalty Calculation
if (playerCharacter.getGuild().isEmptyGuild())
grantedExperience *= 0.6;
}
if (grantedExperience == 0)
grantedExperience = 1;
//scaling
grantedExperience *= (1 / giveEXPTo.size()+0.9);
// Grant the player the EXP
playerCharacter.grantXP((int) Math.floor(grantedExperience));
}
} else { // Give EXP to a single character
//if (!killer.isAlive()) // Skip if the player is dead.
// return;
if (killer.getLevel() >= MBServerStatics.LEVELCAP)
return;
if(killer.level >= 75 && !mob.getObjectType().equals(Enum.GameObjectType.PlayerCharacter))
return; // cannot PVE higher than level 75
return;
baseXP = LootManager.NORMAL_EXP_RATE * maxXPPerKill(killer.getLevel());
double mod = getConMod(killer, mob);
float leadership = 0.0f;
if(killer.skills.containsKey("Leadership"))
leadership = killer.skills.get("Leadership").getModifiedAmount();
if(leadership > 0 && mod != 0){
mod += (leadership * 0.01f);
// Get XP and adjust for Mob Level with world xp modifier taken into account
grantedExperience = (double) LOOTMANAGER.NORMAL_EXP_RATE * maxXPPerKill(killer.getLevel());
grantedExperience *= getConMod(killer, mob);
// Modify for hotzone
if (ZoneManager.inHotZone(mob.getLoc()))
grantedExperience *= LOOTMANAGER.HOTZONE_EXP_RATE;
// Errant penalty
if (grantedExperience != 1) {
if (killer.getGuild().isEmptyGuild())
grantedExperience *= 0.6f;
}
baseXP *= mod;
if(baseXP < 1)
baseXP = 1;
//bonus for no group
grantedExperience *= 1.9f;
baseXP *= 1.9f;
killer.grantXP((int) baseXP);
// Grant XP
killer.grantXP((int) Math.floor(grantedExperience));
}
}
}
+56 -6
View File
@@ -818,15 +818,65 @@ public class Item extends AbstractWorldObject {
}
public void stripCastableEnchants(){
ArrayList<Effect> ToRemove = new ArrayList<>();
for(Effect eff : this.effects.values()){
if(eff.getJobContainer() != null && !eff.getJobContainer().noTimer()){
try {
//strip EnchantWeapon
if(this.effects.get("EnchantWeapon") != null){
this.effects.remove("EnchantWeapon");
Effect eff = this.effects.get("EnchantWeapon");
eff.endEffectNoPower();
eff.getJobContainer().cancelJob();
ToRemove.add(eff);
}
//strip FGM-003
if(this.effects.get("1000") != null){
this.effects.remove("1000");
Effect eff = this.effects.get("1000");
eff.endEffectNoPower();
}
//strip FGM-001
if(this.effects.get("996") != null){
this.effects.remove("996");
Effect eff = this.effects.get("996");
eff.endEffectNoPower();
}
//strip ENC-001
if(this.effects.get("957") != null){
this.effects.remove("957");
Effect eff = this.effects.get("957");
eff.endEffectNoPower();
}
if(this.effects.get("958") != null){
this.effects.remove("958");
Effect eff = this.effects.get("958");
eff.endEffectNoPower();
}
if(this.effects.get("959") != null){
this.effects.remove("959");
Effect eff = this.effects.get("959");
eff.endEffectNoPower();
}
if(this.effects.get("960") != null){
this.effects.remove("960");
Effect eff = this.effects.get("960");
eff.endEffectNoPower();
}
if(this.effects.get("961") != null){
this.effects.remove("961");
Effect eff = this.effects.get("961");
eff.endEffectNoPower();
}
if(this.effects.get("962") != null){
this.effects.remove("962");
Effect eff = this.effects.get("962");
eff.endEffectNoPower();
}
this.applyAllBonuses();
//this.effects.values().removeAll(ToRemove);
}catch(Exception ignored){
}
this.effects.values().removeAll(ToRemove);
}
//Only to be used for trading
public void setOwnerID(int ownerID) {
+10 -8
View File
@@ -259,51 +259,53 @@ public class ItemBase {
case 250019:
case 250028:
case 250037:
return 3000000;
return 1000000;
case 250002: //10 stats
case 250011:
case 250020:
case 250029:
case 250038:
return 4000000;
return 2000000;
case 250003: //15 stats
case 250012:
case 250021:
case 250030:
case 250039:
return 5000000;
return 3000000;
case 250004: //20 stats
case 250013:
case 250022:
case 250031:
case 250040:
return 6000000;
return 4000000;
case 250005: //25 stats
case 250014:
case 250023:
case 250032:
case 250041:
return 7000000;
return 5000000;
case 250006: //30 stats
case 250015:
case 250024:
case 250033:
case 250042:
return 8000000;
return 6000000;
case 250007: //35 stats
case 250016:
case 250025:
case 250034:
case 250043:
return 9000000;
return 7000000;
case 250008: //40 stats
case 250017:
case 250026:
case 250035:
case 250044:
return 10000000;
case 252127:
return 5000000;
}
return 10000000;
return 1000000;
}
/*
+25 -17
View File
@@ -705,9 +705,13 @@ public class ItemFactory {
int rollPrefix = ThreadLocalRandom.current().nextInt(1, 100 + 1);
if (rollPrefix < 80) {
if (rollPrefix < vendor.getLevel() + 30) {
int randomPrefix = TableRoll(vendor.getLevel());
if(vendor.contract.getName().contains("Heavy") || vendor.contract.getName().contains("Medium") || vendor.contract.getName().contains("Leather"))
randomPrefix += vendor.level * 0.5f;
if(randomPrefix > 320)
randomPrefix = 320;
prefixEntry = ModTableEntry.rollTable(prefixTypeTable.modTableID, randomPrefix);
if (prefixEntry != null)
@@ -720,9 +724,13 @@ public class ItemFactory {
// Always have at least one mod on a magic rolled item.
// Suffix will be our backup plan.
if (rollSuffix < 80 || prefixEntry == null) {
if (rollSuffix < vendor.getLevel() + 30) {
int randomSuffix = TableRoll(vendor.getLevel());
if(vendor.contract.getName().contains("Heavy") || vendor.contract.getName().contains("Medium") || vendor.contract.getName().contains("Leather"))
randomSuffix += vendor.level * 0.25f;
if(randomSuffix > 320)
randomSuffix = 320;
suffixEntry = ModTableEntry.rollTable(suffixTypeTable.modTableID, randomSuffix);
if (suffixEntry != null)
@@ -776,31 +784,31 @@ public class ItemFactory {
public static int TableRoll(int vendorLevel) {
// Calculate min and max based on mobLevel
int min = 60;
int max = 120;
int min = 100;
int max = 160;
switch(vendorLevel){
case 20:
min = 70;
max = 140;
break;
case 30:
min = 80;
max = 160;
break;
case 40:
min = 90;
min = 120;
max = 180;
break;
case 50:
min = 100;
case 30:
min = 140;
max = 200;
break;
case 40:
min = 160;
max = 220;
break;
case 50:
min = 180;
max = 240;
break;
case 60:
min = 175;
min = 200;
max = 260;
break;
case 70:
min = 220;
min = 240;
max = 320;
break;
}
+29 -4
View File
@@ -65,6 +65,7 @@ public class Mine extends AbstractGameObject {
public boolean isStronghold = false;
public ArrayList<Mob> strongholdMobs;
public HashMap<Integer,Integer> oldBuildings;
public HashMap<Integer, Long> mineAttendees = new HashMap<>();
/**
* ResultSet Constructor
@@ -622,7 +623,7 @@ public class Mine extends AbstractGameObject {
// Gather current list of players within the zone bounds
HashSet<AbstractWorldObject> currentPlayers = WorldGrid.getObjectsInRangePartial(tower.loc, Enum.CityBoundsType.GRID.extents, MBServerStatics.MASK_PLAYER);
HashSet<AbstractWorldObject> currentPlayers = WorldGrid.getObjectsInRangePartial(tower.loc, MBServerStatics.CHARACTER_LOAD_RANGE * 3, MBServerStatics.MASK_PLAYER);
HashMap<Guild,ArrayList<PlayerCharacter>> charactersByNation = new HashMap<>();
ArrayList<Guild> updatedNations = new ArrayList<>();
for (AbstractWorldObject playerObject : currentPlayers) {
@@ -637,6 +638,7 @@ public class Mine extends AbstractGameObject {
if(!this._playerMemory.contains(player.getObjectUUID())){
this._playerMemory.add(player.getObjectUUID());
ChatManager.chatSystemInfo(player,"You Have Entered an Active Mine Area");
}
Guild nation = player.guild.getNation();
if(charactersByNation.containsKey(nation)){
@@ -655,6 +657,19 @@ public class Mine extends AbstractGameObject {
}
}
}
for(Integer id : this.mineAttendees.keySet()){
PlayerCharacter attendee = PlayerCharacter.getPlayerCharacter(id);
if(attendee == null)
continue;
if(charactersByNation.containsKey(attendee.guild.getNation())){
if(!charactersByNation.get(attendee.guild.getNation()).contains(attendee)){
charactersByNation.get(attendee.guild.getNation()).add(attendee);
}
}
}
for(Guild nation : updatedNations){
float multiplier = ZergManager.getCurrentMultiplier(charactersByNation.get(nation).size(),this.capSize);
for(PlayerCharacter player : charactersByNation.get(nation)){
@@ -676,18 +691,28 @@ public class Mine extends AbstractGameObject {
if(tower == null)
return;
ArrayList<Integer>toRemove = new ArrayList<>();
HashSet<AbstractWorldObject> currentPlayers = WorldGrid.getObjectsInRangePartial(tower.loc, Enum.CityBoundsType.GRID.extents, MBServerStatics.MASK_PLAYER);
HashSet<AbstractWorldObject> currentPlayers = WorldGrid.getObjectsInRangePartial(tower.loc, MBServerStatics.CHARACTER_LOAD_RANGE * 3, MBServerStatics.MASK_PLAYER);
for(Integer id : currentMemory){
PlayerCharacter pc = PlayerCharacter.getPlayerCharacter(id);
if(currentPlayers.contains(pc) == false){
toRemove.add(id);
if(!currentPlayers.contains(pc)){
if(this.mineAttendees.containsKey(id)){
long timeGone = System.currentTimeMillis() - this.mineAttendees.get(id).longValue();
if (timeGone > 180000L) { // 3 minutes
toRemove.add(id); // Mark for removal
}
}
pc.ZergMultiplier = 1.0f;
} else {
this.mineAttendees.put(id,System.currentTimeMillis());
}
}
// Remove players from city memory
_playerMemory.removeAll(toRemove);
for(int id : toRemove){
this.mineAttendees.remove(id);
}
}
public static Building getTower(Mine mine){
Building tower = BuildingManager.getBuildingFromCache(mine.buildingID);
+3
View File
@@ -111,6 +111,8 @@ public class Mob extends AbstractIntelligenceAgent {
public boolean StrongholdEpic = false;
public boolean isDropper = false;
public HashMap<PlayerCharacter,Float> hate_values;
/**
* No Id Constructor
@@ -1450,6 +1452,7 @@ public class Mob extends AbstractIntelligenceAgent {
this.stopPatrolTime = 0;
this.lastPatrolPointIndex = 0;
InterestManager.setObjectDirty(this);
this.hate_values = new HashMap<>();
}
public void despawn() {
+2 -2
View File
@@ -278,14 +278,14 @@ public class MobEquipment extends AbstractGameObject {
EffectsBase effect = PowersManager.getEffectByToken(token);
AbstractPowerAction apa = PowersManager.getPowerActionByIDString(effect.getIDString());
if (apa.getEffectsBase() != null)
if (apa != null && apa.getEffectsBase() != null)
if (apa.getEffectsBase().getValue() > 0) {
//System.out.println(apa.getEffectsBase().getValue());
value += apa.getEffectsBase().getValue();
}
if (apa.getEffectsBase2() != null)
if (apa != null && apa.getEffectsBase2() != null)
value += apa.getEffectsBase2().getValue();
}
+5
View File
@@ -876,6 +876,11 @@ public class NPC extends AbstractCharacter {
// zone collection
this.parentZone = ZoneManager.getZoneByUUID(this.parentZoneUUID);
if(this.parentZone == null) {
Logger.error("PARENT ZONE NOT IDENTIFIED FOR NPC : " + this.getObjectUUID());
return;
}
this.parentZone.zoneNPCSet.remove(this);
this.parentZone.zoneNPCSet.add(this);
+95 -49
View File
@@ -41,11 +41,11 @@ import engine.server.MBServerStatics;
import engine.server.login.LoginServer;
import engine.server.login.LoginServerMsgHandler;
import engine.server.world.WorldServer;
import engine.util.KeyCloneAudit;
import engine.util.MiscUtils;
import org.joda.time.DateTime;
import org.pmw.tinylog.Logger;
import javax.swing.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
@@ -183,6 +183,8 @@ public class PlayerCharacter extends AbstractCharacter {
public PlayerCombatStats combatStats;
public Integer selectedUUID = 0;
/**
* No Id Constructor
*/
@@ -1534,25 +1536,48 @@ public class PlayerCharacter extends AbstractCharacter {
return true;
Zone zone = ZoneManager.findSmallestZone(breather.getLoc());
if(zone == null)
return true;
if(zone.isPlayerCity())
return true;
float seaLevel = zone.getSeaLevel();
if (zone.getSeaLevel() != 0) {
Zone parent = zone.getParent();
if(parent != null && parent.isMacroZone()){
float parentLevel = parent.getSeaLevel();
seaLevel -= parentLevel;
}
if(seaLevel == 0)
return true;
float localAltitude = breather.getLoc().y;
float characterHeight = breather.characterHeight;
if (localAltitude + breather.characterHeight < zone.getSeaLevel() - 2)
if (localAltitude + characterHeight < seaLevel - 2) {
//ChatManager.chatSystemInfo(breather, "YOU CANNOT BREATHE!");
return false;
}
if (breather.isMoving()) {
if (localAltitude + breather.characterHeight < zone.getSeaLevel())
if (localAltitude + breather.characterHeight < zone.getSeaLevel()) {
//ChatManager.chatSystemInfo(breather, "YOU CANNOT BREATHE!");
return false;
}
}
} else {
if (breather.getLoc().y + breather.characterHeight < -2)
if (breather.getLoc().y + breather.characterHeight < -2) {
//ChatManager.chatSystemInfo(breather, "YOU CANNOT BREATHE!");
return false;
}
if (breather.isMoving()) {
if (breather.getLoc().y + breather.characterHeight < 0)
if (breather.getLoc().y + breather.characterHeight < 0) {
//ChatManager.chatSystemInfo(breather, "YOU CANNOT BREATHE!");
return false;
}
}
}
@@ -1845,6 +1870,11 @@ public class PlayerCharacter extends AbstractCharacter {
message += " was killed by " + att.getFirstName();
if (att.guild != null && (!(att.guild.getName().equals("Errant"))))
message += " of " + att.guild.getName();
Zone killZone = ZoneManager.findSmallestZone(this.loc);
if(killZone != null){
message += " in " + killZone.getName();
}
message += "!";
@@ -1964,8 +1994,7 @@ public class PlayerCharacter extends AbstractCharacter {
this.altitude = (float) 0;
// Release Mine Claims
Mine.releaseMineClaims(this);
//Mine.releaseMineClaims(this);
this.getCharItemManager().closeTradeWindow();
@@ -2929,6 +2958,7 @@ public class PlayerCharacter extends AbstractCharacter {
}
public synchronized void grantXP(int xp) {
xp *= LootManager.NORMAL_EXP_RATE;
int groupSize = 1;
if(GroupManager.getGroup(this)!= null)
groupSize = GroupManager.getGroup(this).members.size();
@@ -3084,7 +3114,7 @@ public class PlayerCharacter extends AbstractCharacter {
checkGuildStatus();
//give gold for level up if level is under or equal to 20 and over 10
if(!this.isBoxed && this.level > 10 && this.level <= 20 && this.safeZone) {
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();
@@ -4705,7 +4735,7 @@ public class PlayerCharacter extends AbstractCharacter {
ModType modType = ModType.GetModType(type);
// must be allowed to use this passive
if (!this.bonuses.getBool(modType, SourceType.None))
if (!this.bonuses.getBool(modType, SourceType.None) && this.getRaceID() != 1999)
return 0f;
// must not be stunned
@@ -4754,13 +4784,13 @@ public class PlayerCharacter extends AbstractCharacter {
if(this.bonuses != null)
blockChance *= 1 + this.bonuses.getFloatPercentAll(ModType.Block, SourceType.None);
return blockChance;
case "Parry":
if(!fromCombat)
return 0;
if(mainHand == null && this.getRaceID() != 1999) // saetors can always parry using their horns
return 0;
int parryBonus = 0;
if(mainHand != null && offHand != null && !offHand.getItemBase().isShield())
@@ -5078,6 +5108,12 @@ public class PlayerCharacter extends AbstractCharacter {
Zone zone = ZoneManager.findSmallestZone(this.getLoc());
if(zone == null)
return false;
if(zone.isPlayerCity())
return false;
if (zone.getSeaLevel() != 0) {
float localAltitude = this.getLoc().y + this.centerHeight;
@@ -5109,38 +5145,31 @@ public class PlayerCharacter extends AbstractCharacter {
@Override
public void update(Boolean newSystem) {
this.updateLocation();
if(!newSystem)
this.updateLocation();
this.updateMovementState();
if(!newSystem)
return;
this.updateLocation();
this.updateMovementState();
try {
if (this.updateLock.writeLock().tryLock()) {
try {
if (!this.isAlive() && this.isEnteredWorld()) {
if (!this.timestamps.containsKey("DeathTime")) {
this.timestamps.put("DeathTime", System.currentTimeMillis());
} else if ((System.currentTimeMillis() - this.timestamps.get("DeathTime")) > 600000)
forceRespawn(this);
return;
}
if (this.isAlive() && this.isActive && this.enteredWorld) {
this.updateMovementState();
if (this.combatStats == null) {
this.combatStats = new PlayerCombatStats(this);
} else {
this.combatStats.update();
try {
this.combatStats.update();
}catch(Exception ignored){
}
}
this.doRegen();
//this.combatStats.regenerate();
}
if (this.getStamina() < 10) {
@@ -5153,24 +5182,26 @@ public class PlayerCharacter extends AbstractCharacter {
this.updateBlessingMessage();
this.safeZone = this.isInSafeZone();
if (!this.timestamps.containsKey("nextBoxCheck"))
this.timestamps.put("nextBoxCheck", System.currentTimeMillis() + 10000);
if (!this.isBoxed && this.timestamps.get("nextBoxCheck") < System.currentTimeMillis()) {
this.isBoxed = checkIfBoxed(this);
this.timestamps.put("nextBoxCheck", System.currentTimeMillis() + 10000);
}
if(this.isActive && this.enteredWorld) {
if (!this.timestamps.containsKey("nextBoxCheck"))
this.timestamps.put("nextBoxCheck", System.currentTimeMillis() + 10000);
if (this.level < 10 && this.enteredWorld) {
while (this.level < 10) {
grantXP(Experience.getBaseExperience(this.level + 1) - this.exp);
if (!this.isBoxed && this.timestamps.get("nextBoxCheck") < System.currentTimeMillis()) {
this.isBoxed = checkIfBoxed(this);
this.timestamps.put("nextBoxCheck", System.currentTimeMillis() + 10000);
}
if (this.level < 10 && this.enteredWorld) {
while (this.level < 10) {
grantXP(Experience.getBaseExperience(this.level + 1) - this.exp);
}
}
if (this.isBoxed && !this.containsEffect(1672601862)) {
PowersManager.applyPower(this, this, Vector3fImmutable.ZERO, 1672601862, 40, false);
}
}
if (this.isBoxed && !this.containsEffect(1672601862)) {
PowersManager.applyPower(this, this, Vector3fImmutable.ZERO, 1672601862, 40, false);
}
if (this.isFlying()) {
if (this.effects.containsKey("MoveBuff")) {
GroundPlayer(this);
@@ -5338,9 +5369,11 @@ public class PlayerCharacter extends AbstractCharacter {
return;
}
setLoc(newLoc);
this.region = AbstractWorldObject.GetRegionByWorldObject(this);
setLoc(newLoc);
if (this.getDebug(1))
ChatManager.chatSystemInfo(this,
"Distance to target " + this.getEndLoc().distance2D(this.getLoc()) + " speed " + this.getSpeed());
@@ -5637,6 +5670,8 @@ public class PlayerCharacter extends AbstractCharacter {
}
public void setEnteredWorld(boolean enteredWorld) {
if(enteredWorld)
this.timestamps.put("nextBoxCheck", System.currentTimeMillis() + 10000);
this.enteredWorld = enteredWorld;
}
@@ -5742,10 +5777,15 @@ public class PlayerCharacter extends AbstractCharacter {
} else {
healthRegen = 0;
manaRegen = 0;
if (this.combat == true)
stamRegen = MBServerStatics.STAMINA_REGEN_RUN_COMBAT;
else
stamRegen = MBServerStatics.STAMINA_REGEN_RUN_NONCOMBAT;
if(this.containsEffect(441156479) || this.containsEffect(441156455)) {
stamRegen = MBServerStatics.STAMINA_REGEN_WALK;
}else {
if (this.combat == true)
stamRegen = MBServerStatics.STAMINA_REGEN_RUN_COMBAT;
else
stamRegen = MBServerStatics.STAMINA_REGEN_RUN_NONCOMBAT;
}
}
break;
case FLYING:
@@ -5876,10 +5916,16 @@ public class PlayerCharacter extends AbstractCharacter {
// Reset this char's frame time.
this.lastUpdateTime = System.currentTimeMillis();
this.lastStamUpdateTime = System.currentTimeMillis();
//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()) {
this.syncClient();
this.timestamps.put("SyncClient", System.currentTimeMillis());
//if (updateHealth || updateMana || updateStamina || consumeStamina) {
this.syncClient();
this.timestamps.put("SyncClient", System.currentTimeMillis());
//}
}
}
+322 -219
View File
@@ -1,21 +1,17 @@
package engine.objects;
import engine.Enum;
import engine.gameManager.ChatManager;
import engine.math.Vector2f;
import engine.math.Vector3fImmutable;
import engine.jobs.DeferredPowerJob;
import engine.powers.EffectsBase;
import engine.powers.PowersBase;
import engine.powers.effectmodifiers.AbstractEffectModifier;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import javax.swing.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class PlayerCombatStats {
@@ -26,7 +22,7 @@ public class PlayerCombatStats {
public float attackSpeedHandOne;
public float rangeHandOne;
public float atrHandOne;
//off hand data
//offhand data
public int minDamageHandTwo;
public int maxDamageHandTwo;
public float attackSpeedHandTwo;
@@ -254,18 +250,6 @@ public class PlayerCombatStats {
HIT_VALUE_MAP.put(2.50f, 100f);
}
//Values for health and mana are in terms of the number of seconds it takes to recover 1%
//Values for stamina are in terms of the number of seconds it takes to recover 1 point
//HEALTH//MANA//STAMINA
private static Vector3fImmutable resting = new Vector3fImmutable(3.0f,1.2f,0.5f);
private static Vector3fImmutable idling = new Vector3fImmutable(15.0f,6.0f,5.0f);
private static Vector3fImmutable walking = new Vector3fImmutable(20.0f,8.0f,0.0f);
private static Vector3fImmutable running = new Vector3fImmutable(0.0f,0.0f,0.0f);
//#Values for how fast mana is consumed. The first is how fast when player is not in combat
//#mode, the second is when he IS in combat mode. This is in Stamina reduction per second.
private static Vector2f consumption = new Vector2f(0.4f,0.65f);
public PlayerCombatStats(PlayerCharacter pc) {
this.owner = pc;
this.update();
@@ -368,20 +352,29 @@ public class PlayerCombatStats {
float masteryLevel = 0;
if(this.owner.skills.containsKey(skill)) {
skillLevel = this.owner.skills.get(skill).getModifiedAmount();//calculateBuffedSkillLevel(skill,this.owner);//this.owner.skills.get(skill).getTotalSkillPercet();
skillLevel = this.owner.skills.get(skill).getModifiedAmount();
}
if(this.owner.skills.containsKey(mastery))
masteryLevel = this.owner.skills.get(mastery).getModifiedAmount();//calculateBuffedSkillLevel(mastery,this.owner);//this.owner.skills.get(mastery).getTotalSkillPercet();
masteryLevel = this.owner.skills.get(mastery).getModifiedAmount();
float stanceValue = 0.0f;
float atrEnchants = 0;
float healerDefStance = 0.0f;
for(String effID : this.owner.effects.keySet()) {
if (effID.contains("Stance")) {
Effect effect = this.owner.effects.get(effID);
EffectsBase eb = effect.getEffectsBase();
if(eb.getIDString().equals("STC-H-DA"))
if(eb.getIDString().equals("STC-H-DA")){
for (AbstractEffectModifier mod : this.owner.effects.get(effID).getEffectModifiers()) {
if (mod.modType.equals(Enum.ModType.OCV)) {
float percent = mod.getPercentMod();
int trains = this.owner.effects.get(effID).getTrains();
float modValue = percent + (trains * mod.getRamp());
healerDefStance += modValue * 0.01f;
}
}
continue;
}
for (AbstractEffectModifier mod : this.owner.effects.get(effID).getEffectModifiers()) {
if (mod.modType.equals(Enum.ModType.OCV)) {
float percent = mod.getPercentMod();
@@ -432,7 +425,7 @@ public class PlayerCombatStats {
preciseRune += 0.05f;
}
atr = primaryStat / 2;
atr = primaryStat / 2.0f;
atr += skillLevel * 4;
atr += masteryLevel * 3;
atr += prefixValues;
@@ -441,18 +434,22 @@ public class PlayerCombatStats {
atr *= 1.0f + stanceValue;
if(this.owner.bonuses != null) {
float positivePercentBonuses = this.owner.bonuses.getFloatPercentPositive(Enum.ModType.OCV, Enum.SourceType.None);
float positivePercentBonuses = this.owner.bonuses.getFloatPercentPositive(Enum.ModType.OCV, Enum.SourceType.None) - stanceValue;
float negativePercentBonuses = this.owner.bonuses.getFloatPercentNegative(Enum.ModType.OCV, Enum.SourceType.None);
float modifier = 1 + (positivePercentBonuses + negativePercentBonuses);
if(preciseRune > 1.0f)
modifier -= 0.05f;
if(stanceValue > 1.0f){
modifier -= (stanceValue - 1.0f);
if(stanceValue > 0.0f){
modifier -= (stanceValue);
}
modifier -= healerDefStance;
atr *= modifier;
}
atr = (float) Math.round(atr);
if(atr < 0)
atr = 0;
if(mainHand){
this.atrHandOne = atr;
}else{
@@ -490,7 +487,6 @@ public class PlayerCombatStats {
skill = weapon.getItemBase().getSkillRequired();
mastery = weapon.getItemBase().getMastery();
if (weapon.getItemBase().isStrBased()) {
//primaryStat = this.owner.statStrCurrent;
//secondaryStat = specialDex;//getDexAfterPenalty(this.owner);
primaryStat = this.owner.statStrCurrent;
secondaryStat = this.owner.statDexCurrent;
@@ -521,6 +517,7 @@ public class PlayerCombatStats {
);
if(this.owner.bonuses != null){
minDMG += this.owner.bonuses.getFloat(Enum.ModType.MinDamage, Enum.SourceType.None);
minDMG += this.owner.bonuses.getFloat(Enum.ModType.MeleeDamageModifier, Enum.SourceType.None);
minDMG *= 1 + this.owner.bonuses.getFloatPercentAll(Enum.ModType.MeleeDamageModifier, Enum.SourceType.None);
}
@@ -536,11 +533,13 @@ public class PlayerCombatStats {
this.minDamageHandOne = roundedMin;
} else {
this.minDamageHandTwo = roundedMin;
if(this.owner.charItemManager.getEquipped(1) == null && this.owner.charItemManager.getEquipped(2) != null){
if(!this.owner.charItemManager.getEquipped(2).getItemBase().isShield())
this.minDamageHandOne = 0;
}else if(this.owner.charItemManager.getEquipped(2) == null && this.owner.charItemManager.getEquipped(1) != null){
this.minDamageHandTwo = 0;
if(this.owner.charItemManager != null) {
if (this.owner.charItemManager.getEquipped(1) == null && this.owner.charItemManager.getEquipped(2) != null) {
if (!this.owner.charItemManager.getEquipped(2).getItemBase().isShield())
this.minDamageHandOne = 0;
} else if (this.owner.charItemManager.getEquipped(2) == null && this.owner.charItemManager.getEquipped(1) != null) {
this.minDamageHandTwo = 0;
}
}
}
}
@@ -599,6 +598,7 @@ public class PlayerCombatStats {
if(this.owner.bonuses != null){
maxDMG += this.owner.bonuses.getFloat(Enum.ModType.MaxDamage, Enum.SourceType.None);
maxDMG += this.owner.bonuses.getFloat(Enum.ModType.MeleeDamageModifier, Enum.SourceType.None);
maxDMG *= 1 + this.owner.bonuses.getFloatPercentAll(Enum.ModType.MeleeDamageModifier, Enum.SourceType.None);
}
@@ -612,13 +612,15 @@ public class PlayerCombatStats {
if(mainHand){
this.maxDamageHandOne = roundedMax;
}else{
this.maxDamageHandTwo = roundedMax;
if(this.owner.charItemManager.getEquipped(1) == null && this.owner.charItemManager.getEquipped(2) != null){
if(!this.owner.charItemManager.getEquipped(2).getItemBase().isShield())
this.maxDamageHandOne = 0;
}else if(this.owner.charItemManager.getEquipped(2) == null && this.owner.charItemManager.getEquipped(1) != null){
this.maxDamageHandTwo = 0;
}else {
if (this.owner.charItemManager != null) {
this.maxDamageHandTwo = roundedMax;
if (this.owner.charItemManager.getEquipped(1) == null && this.owner.charItemManager.getEquipped(2) != null) {
if (!this.owner.charItemManager.getEquipped(2).getItemBase().isShield())
this.maxDamageHandOne = 0;
} else if (this.owner.charItemManager.getEquipped(2) == null && this.owner.charItemManager.getEquipped(1) != null) {
this.maxDamageHandTwo = 0;
}
}
}
}
@@ -689,9 +691,9 @@ public class PlayerCombatStats {
}
float bonusValues = 1 + this.owner.bonuses.getFloatPercentAll(Enum.ModType.AttackDelay,Enum.SourceType.None);//1.0f;
bonusValues -= stanceValue + delayExtra; // take away stance modifier from alac bonus values
bonusValues -= stanceValue + delayExtra; // take away stance modifier from alacrity bonus values
speed *= 1 + stanceValue; // apply stance bonus
speed *= bonusValues; // apply alac bonuses without stance mod
speed *= bonusValues; // apply alacrity bonuses without stance mod
if(speed < 10.0f)
speed = 10.0f;
@@ -745,23 +747,23 @@ public class PlayerCombatStats {
float armorSkill = 0.0f;
float armorDefense = 0.0f;
ArrayList<String> armorsUsed = new ArrayList<>();
int itemdef = 0;
int itemDef;
for(Item equipped : this.owner.charItemManager.getEquipped().values()){
ItemBase ib = equipped.getItemBase();
if(ib.isHeavyArmor() || ib.isMediumArmor() || ib.isLightArmor() || ib.isClothArmor()){
itemdef = ib.getDefense();
itemDef = ib.getDefense();
for(Effect eff : equipped.effects.values()){
for(AbstractEffectModifier mod : eff.getEffectModifiers()){
if(mod.modType.equals(Enum.ModType.DR)){
itemdef += mod.minMod + (mod.getRamp() * eff.getTrains());
itemDef += mod.minMod + (mod.getRamp() * eff.getTrains());
}
}
}
if(!ib.isClothArmor() && !armorsUsed.contains(ib.getSkillRequired())) {
armorsUsed.add(ib.getSkillRequired());
}
armorDefense += itemdef;
armorDefense += itemDef;
}
}
for(String armorUsed : armorsUsed){
@@ -777,16 +779,20 @@ public class PlayerCombatStats {
blockSkill = this.owner.skills.get("Block").getModifiedAmount();
float shieldDefense = 0.0f;
if(this.owner.charItemManager.getEquipped(2) != null && this.owner.charItemManager.getEquipped(2).getItemBase().isShield()){
Item shield = this.owner.charItemManager.getEquipped(2);
shieldDefense += shield.getItemBase().getDefense();
for(Effect eff : shield.effects.values()){
for(AbstractEffectModifier mod : eff.getEffectModifiers()){
if(mod.modType.equals(Enum.ModType.DR)){
shieldDefense += mod.minMod + (mod.getRamp() * eff.getTrains());
try {
if (this.owner.charItemManager.getEquipped(2) != null && this.owner.charItemManager.getEquipped(2).getItemBase().isShield()) {
Item shield = this.owner.charItemManager.getEquipped(2);
shieldDefense += shield.getItemBase().getDefense();
for (Effect eff : shield.effects.values()) {
for (AbstractEffectModifier mod : eff.getEffectModifiers()) {
if (mod.modType.equals(Enum.ModType.DR)) {
shieldDefense += mod.minMod + (mod.getRamp() * eff.getTrains());
}
}
}
}
}catch(Exception ignore){
}
float weaponSkill = 0.0f;
@@ -846,10 +852,76 @@ public class PlayerCombatStats {
}
}
}
if(this.owner.charItemManager.getEquipped(2) == null)
blockSkill = 0;
else if(this.owner.charItemManager != null && this.owner.charItemManager.getEquipped(2) != null && !this.owner.charItemManager.getEquipped(2).getItemBase().isShield())
blockSkill = 0;
//right ring
if(this.owner.charItemManager != null){
try{
if(this.owner.charItemManager.getEquipped(7) != null){
for(String effID : this.owner.charItemManager.getEquipped(7).effects.keySet()) {
for (AbstractEffectModifier mod : this.owner.charItemManager.getEquipped(7).effects.get(effID).getEffectModifiers()) {
if (mod.modType.equals(Enum.ModType.DCV)) {
if (mod.getPercentMod() == 0) {
float value = mod.getMinMod();
int trains = this.owner.effects.get(effID).getTrains();
float modValue = value + (trains * mod.getRamp());
flatBonuses += modValue;
}
}
}
}
}
}catch(Exception e){
}
//left ring
try {
if (this.owner.charItemManager.getEquipped(8) != null) {
for (String effID : this.owner.charItemManager.getEquipped(8).effects.keySet()) {
for (AbstractEffectModifier mod : this.owner.charItemManager.getEquipped(8).effects.get(effID).getEffectModifiers()) {
if (mod.modType.equals(Enum.ModType.DCV)) {
if (mod.getPercentMod() == 0) {
float value = mod.getMinMod();
int trains = this.owner.effects.get(effID).getTrains();
float modValue = value + (trains * mod.getRamp());
flatBonuses += modValue;
}
}
}
}
}
}catch(Exception e){
}
//necklace
try{
if(this.owner.charItemManager.getEquipped(9) != null){
for(String effID : this.owner.charItemManager.getEquipped(9).effects.keySet()) {
for (AbstractEffectModifier mod : this.owner.charItemManager.getEquipped(9).effects.get(effID).getEffectModifiers()) {
if (mod.modType.equals(Enum.ModType.DCV)) {
if (mod.getPercentMod() == 0) {
float value = mod.getMinMod();
int trains = this.owner.effects.get(effID).getTrains();
float modValue = value + (trains * mod.getRamp());
flatBonuses += modValue;
}
}
}
}
}
}catch(Exception e){
}
try{
if(this.owner.charItemManager.getEquipped(2) == null)
blockSkill = 0;
else if(this.owner.charItemManager != null && this.owner.charItemManager.getEquipped(2) != null && !this.owner.charItemManager.getEquipped(2).getItemBase().isShield())
blockSkill = 0;
}catch(Exception e){
}
}
float defense = (1 + armorSkill / 50) * armorDefense;
defense += (1 + blockSkill / 100) * shieldDefense;
@@ -868,6 +940,9 @@ public class PlayerCombatStats {
}
defense = Math.round(defense);
if(defense < 0)
defense = 0;
this.defense = (int) defense;
} // PERFECT DO NOT TOUCH
@@ -877,7 +952,7 @@ public class PlayerCombatStats {
if(def == 0)
return 100.0f;
float key = (float)((float)atr / def);
float key = ((float)atr / def);
BigDecimal bd = new BigDecimal(key).setScale(2, RoundingMode.HALF_UP);
key = bd.floatValue(); // handles rounding for mandatory 2 decimal places
if(key < 0.40f)
@@ -887,184 +962,212 @@ public class PlayerCombatStats {
return HIT_VALUE_MAP.get(key);
}
public static float getSpellAtr(PlayerCharacter pc, PowersBase pb) {
public void regenerate(){
if(!this.owner.effects.containsKey("Stunned")) {
// healthRegen(this.owner);
//manaRegen(this.owner);
//staminaRegen(this.owner);
this.owner.doRegen();
this.owner.syncClient();
}
//staminaConsume(this.owner);
//this.owner.syncClient();
}
public static void healthRegen(PlayerCharacter pc){
if(!pc.timestamps.containsKey("LASTHEALTHREGEN"))
pc.timestamps.put("LASTHEALTHREGEN",System.currentTimeMillis());
if (pc == null)
return 0f;
double current = pc.health.get();
if (Double.isNaN(current))
current = 0.0;
if(pb == null)
return 0.0f;
double recovered = pc.healthMax * (0.01f / getRecoveryType(pc).health);
double mod = current + recovered;
if(pc.bonuses != null)
mod *= 1 + pc.bonuses.getFloatPercentAll(Enum.ModType.HealthRecoverRate, Enum.SourceType.None);
boolean worked = false;
if(mod > pc.healthMax)
mod = pc.healthMax;
while (!worked) {
worked = pc.health.compareAndSet((float) current, (float) mod);
float modifiedFocusLine = 0.0f;
if(pc.skills.containsKey(pb.skillName)){
modifiedFocusLine = pc.skills.get(pb.skillName).getModifiedAmount();
}
pc.timestamps.put("LASTHEALTHREGEN",System.currentTimeMillis());
}
float modifiedDexterity = pc.statDexCurrent;
public static void manaRegen(PlayerCharacter pc){
if(!pc.timestamps.containsKey("LASTMANAREGEN"))
pc.timestamps.put("LASTMANAREGEN",System.currentTimeMillis());
if(pc.isCasting){
pc.timestamps.put("LASTMANAREGEN",System.currentTimeMillis());
return;
}
double current = pc.mana.get();
if (Double.isNaN(current)) {
current = 0.0;
}
double recovered = pc.manaMax * (0.01f / getRecoveryType(pc).mana);
double mod = current + recovered;
if(pc.bonuses != null)
mod *= 1 + pc.bonuses.getFloatPercentAll(Enum.ModType.ManaRecoverRate, Enum.SourceType.None);
boolean worked = false;
if(mod > pc.manaMax)
mod = pc.manaMax;
while (!worked) {
worked = pc.mana.compareAndSet((float) current, (float) mod);
}
pc.timestamps.put("LASTMANAREGEN",System.currentTimeMillis());
}
public static void staminaRegen(PlayerCharacter pc){
//cannot regen is moving, swimming or flying
if(pc.isFlying() || pc.isSwimming() || pc.isMoving()) {
pc.timestamps.put("LASTSTAMINAREGEN",System.currentTimeMillis());
return;
}
if(!pc.timestamps.containsKey("LASTSTAMINAREGEN"))
pc.timestamps.put("LASTSTAMINAREGEN",System.currentTimeMillis());
float stateMultiplier = 1.0f;
if(pc.isSit())
stateMultiplier = 2.0f;
long deltaTime = System.currentTimeMillis() - pc.timestamps.get("LASTSTAMINAREGEN");
float current = pc.stamina.get();
float properDelay = (deltaTime / getRecoveryType(pc).stamina) * 0.001f;
float mod = current + (properDelay * stateMultiplier);
if(pc.bonuses != null)
mod *= 1 + pc.bonuses.getFloatPercentAll(Enum.ModType.StaminaRecoverRate, Enum.SourceType.None);
boolean worked = false;
if(mod > pc.staminaMax)
mod = pc.staminaMax;
while (!worked) {
worked = pc.stamina.compareAndSet(current, mod);
}
pc.timestamps.put("LASTSTAMINAREGEN",System.currentTimeMillis());
}
public static void staminaConsume(PlayerCharacter pc){
//no natural consumption if not moving, swimming or flying
if(!pc.isFlying() && !pc.isSwimming() && !pc.isMoving()) {
pc.timestamps.put("LASTSTAMINACONSUME",System.currentTimeMillis());
return;
}
//no stamina consumption for TravelStance
if(pc.containsEffect(441156479) || pc.containsEffect(441156455)) {
pc.timestamps.put("LASTSTAMINACONSUME",System.currentTimeMillis());
return;
}
float stateMultiplier = 1.0f;
if(pc.isSwimming() || pc.isFlying())
stateMultiplier = 2.5f;
if(!pc.timestamps.containsKey("LASTSTAMINACONSUME"))
pc.timestamps.put("LASTSTAMINACONSUME",System.currentTimeMillis());
long deltaTime = System.currentTimeMillis() - pc.timestamps.get("LASTSTAMINACONSUME");
float current = pc.stamina.get();
float consumed = ((deltaTime * 0.001f) * 0.6f * stateMultiplier);
float mod = current - consumed;
boolean worked = false;
if(mod <= 0)
mod = 0;
if(mod == 0){
healthConsume(pc, (int) (consumed * 2.5f));
}else {
while (!worked) {
worked = pc.stamina.compareAndSet(current,mod);
float weaponATR1 = 0.0f;
if(pc.charItemManager != null && pc.charItemManager.getEquipped(1) != null){
for(Effect eff : pc.charItemManager.getEquipped(1).effects.values()){
for (AbstractEffectModifier mod : eff.getEffectModifiers()){
if(mod.modType.equals(Enum.ModType.OCV)){
float base = mod.minMod;
float ramp = mod.getRamp();
int trains = eff.getTrains();
weaponATR1 = base + (ramp * trains);
}
}
}
}
pc.timestamps.put("LASTSTAMINACONSUME",System.currentTimeMillis());
float weaponATR2 = 0.0f;
if(pc.charItemManager != null && pc.charItemManager.getEquipped(2) != null){
for(Effect eff : pc.charItemManager.getEquipped(2).effects.values()){
for (AbstractEffectModifier mod : eff.getEffectModifiers()){
if(mod.modType.equals(Enum.ModType.OCV)){
float base = mod.minMod;
float ramp = mod.getRamp();
int trains = eff.getTrains();
weaponATR2 = base + (ramp * trains);
}
}
}
}
float precise = 1.0f;
for(CharacterRune rune : pc.runes){
if(rune.getRuneBase().getName().equals("Precise"))
precise += 0.05f;
}
float stanceMod = 1.0f;
float atrBuffs = 0.0f;
float healerDefStance = 0.0f;
for(String effID : pc.effects.keySet()) {
if (effID.contains("Stance")) {
Effect effect = pc.effects.get(effID);
EffectsBase eb = effect.getEffectsBase();
if(eb.getIDString().equals("STC-H-DA")){
for (AbstractEffectModifier mod : pc.effects.get(effID).getEffectModifiers()) {
if (mod.modType.equals(Enum.ModType.OCV)) {
float percent = mod.getPercentMod();
int trains = pc.effects.get(effID).getTrains();
float modValue = percent + (trains * mod.getRamp());
healerDefStance += modValue * 0.01f;
}
}
continue;
}
for (AbstractEffectModifier mod : pc.effects.get(effID).getEffectModifiers()) {
if (mod.modType.equals(Enum.ModType.OCV)) {
float percent = mod.getPercentMod();
int trains = pc.effects.get(effID).getTrains();
float modValue = percent + (trains * mod.getRamp());
stanceMod += modValue * 0.01f;
}
}
} else {
for (AbstractEffectModifier mod : pc.effects.get(effID).getEffectModifiers()) {
if (mod.modType.equals(Enum.ModType.OCV)) {
if(mod.getPercentMod() == 0) {
float value = mod.getMinMod();
int trains = pc.effects.get(effID).getTrains();
float modValue = value + (trains * mod.getRamp());
atrBuffs += modValue;
}
}
}
}
}
float atr = 7 * modifiedFocusLine;
atr += (modifiedDexterity * 0.5f) + weaponATR1 + weaponATR2;
atr *= precise;
atr += atrBuffs;
if(pc.getWeaponPower() != null){
DeferredPowerJob dpj = pc.getWeaponPower();
dpj.endEffect();
}
if(pc.bonuses != null)
atr *= 1 + (pc.bonuses.getFloatPercentAll(Enum.ModType.OCV, Enum.SourceType.None) - (stanceMod - 1) - (precise - 1) - healerDefStance);
atr *= stanceMod;
return atr;
}
public static void healthConsume(PlayerCharacter pc, int amount){
boolean worked = false;
float current = pc.health.get();
float mod = current - amount;
if(mod <= 0){
if (pc.isAlive.compareAndSet(true, false))
pc.killCharacter("Water");
public void grantExperience(AbstractCharacter killed, Group group){
if(killed == null)
return;
}
while(!worked){
worked = pc.health.compareAndSet(current,mod);
double grantedXP;
if(group != null){
for(PlayerCharacter member : group.members){
//white mob, early exit
if(Experience.getConMod(member,killed) <= 0)
continue;
//can only get XP over level 75 for player kills
if(member.level >= 75 && !killed.getObjectType().equals(Enum.GameObjectType.PlayerCharacter))
continue;
//cannot gain xp while dead
if(!member.isAlive())
continue;
//out of XP range
if(member.loc.distanceSquared(killed.loc) > MBServerStatics.CHARACTER_LOAD_RANGE * MBServerStatics.CHARACTER_LOAD_RANGE)
continue;
float mod;
switch(group.members.size()){
default:
mod = 1.0f;
break;
case 2:
mod = 0.8f;
break;
case 3:
mod = 0.73f;
break;
case 4:
mod = 0.69f;
break;
case 5:
mod = 0.65f;
break;
case 6:
mod = 0.58f;
break;
case 7:
mod = 0.54f;
break;
case 8:
mod = 0.50f;
break;
case 9:
mod = 0.47f;
break;
case 10:
mod = 0.45f;
break;
}
double xp = getXP(member) * mod;
member.grantXP((int) xp);
}
}else{
//Solo XP
//white mob, early exit
if(Experience.getConMod(this.owner,killed) <= 0)
return;
//can only get XP over level 75 for player kills
if(this.owner.level >= 75 && !killed.getObjectType().equals(Enum.GameObjectType.PlayerCharacter))
return;
//cannot gain xp while dead
if(!this.owner.isAlive())
return;
this.owner.grantXP(getXP(this.owner));
}
}
private enum recoveryType{
RESTING(3.0f,1.25f,0.5f),
IDLING(15.0f,6.0f,5.0f),
WALKING(20.0f,8.0f,0.0f),
RUNNING(0.0f,0.0f,0.0f);
public float health;
public float mana;
public float stamina;
public static int getXP(PlayerCharacter pc){
double xp = 0;
float mod = 0.10f;
recoveryType(float health,float mana, float stamina){
this.health = health;
this.mana = mana;
this.stamina = stamina;
if (pc.level >= 26 && pc.level <= 75)
{
mod = 0.10f - (0.001f * (pc.level - 24));
}
else if (pc.level > 75)
{
mod = 0.05f;
}
}
public static recoveryType getRecoveryType(PlayerCharacter pc){
if(pc.sit)
return recoveryType.RESTING;
else if(!pc.isMoving() && !pc.isFlying())
return recoveryType.IDLING;
else
if(pc.walkMode)
return recoveryType.WALKING;
else
return recoveryType.RUNNING;
float levelFull = Experience.LevelToExp[pc.level + 1] - Experience.LevelToExp[pc.level];
xp = levelFull * mod;
return (int) xp;
}
}
+1 -1
View File
@@ -21,7 +21,7 @@ public class VendorDialog extends AbstractGameObject {
private static VendorDialog vd;
private final String dialogType;
private final String intro;
private ArrayList<MenuOption> options = new ArrayList<>();
ArrayList<MenuOption> options = new ArrayList<>();
public VendorDialog(String dialogType, String intro, int UUID) {
super(UUID);