forked from MagicBane/Server
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
555 lines
22 KiB
555 lines
22 KiB
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . |
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· |
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ |
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ |
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ |
|
// Magicbane Emulator Project © 2013 - 2022 |
|
// www.magicbane.com |
|
|
|
package engine.gameManager; |
|
|
|
import engine.InterestManagement.WorldGrid; |
|
import engine.loot.WorkOrder; |
|
import engine.math.Quaternion; |
|
import engine.math.Vector3f; |
|
import engine.math.Vector3fImmutable; |
|
import engine.mbEnums; |
|
import engine.net.Dispatch; |
|
import engine.net.DispatchMessage; |
|
import engine.net.client.ClientConnection; |
|
import engine.net.client.msg.ErrorPopupMsg; |
|
import engine.net.client.msg.PetMsg; |
|
import engine.objects.*; |
|
import engine.powers.EffectsBase; |
|
import engine.powers.RuneSkillAdjustEntry; |
|
import engine.server.MBServerStatics; |
|
import org.pmw.tinylog.Logger; |
|
|
|
import java.util.ArrayList; |
|
import java.util.HashMap; |
|
import java.util.concurrent.ConcurrentHashMap; |
|
import java.util.concurrent.ThreadLocalRandom; |
|
import java.util.concurrent.TimeUnit; |
|
|
|
import static engine.math.FastMath.acos; |
|
|
|
public enum NPCManager { |
|
|
|
NPC_MANAGER; |
|
public static HashMap<Integer, ArrayList<Integer>> _runeSetMap = new HashMap<>(); |
|
|
|
public static void dismissNecroPet(Mob necroPet, boolean updateOwner) { |
|
|
|
necroPet.setCombatTarget(null); |
|
necroPet.hasLoot = false; |
|
|
|
if (necroPet.parentZone != null) |
|
necroPet.parentZone.zoneMobSet.remove(necroPet); |
|
|
|
try { |
|
necroPet.clearEffects(); |
|
} catch (Exception e) { |
|
Logger.error(e.getMessage()); |
|
} |
|
necroPet.playerAgroMap.clear(); |
|
WorldGrid.RemoveWorldObject(necroPet); |
|
|
|
DbManager.removeFromCache(necroPet); |
|
|
|
|
|
PlayerCharacter petOwner = (PlayerCharacter) necroPet.guardCaptain; |
|
|
|
if (petOwner != null) { |
|
|
|
necroPet.guardCaptain = null; |
|
petOwner.setPet(null); |
|
|
|
if (updateOwner == false) |
|
return; |
|
|
|
PetMsg petMsg = new PetMsg(5, null); |
|
Dispatch dispatch = Dispatch.borrow(petOwner, petMsg); |
|
DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.PRIMARY); |
|
} |
|
} |
|
|
|
public static void auditNecroPets(PlayerCharacter player) { |
|
int removeIndex = 0; |
|
while (player.necroPets.size() >= 10) { |
|
|
|
|
|
if (removeIndex == player.necroPets.size()) |
|
break; |
|
|
|
Mob necroPet = player.necroPets.get(removeIndex); |
|
|
|
if (necroPet == null) { |
|
removeIndex++; |
|
continue; |
|
} |
|
dismissNecroPet(necroPet, true); |
|
player.necroPets.remove(necroPet); |
|
removeIndex++; |
|
|
|
|
|
} |
|
} |
|
|
|
public static void resetNecroPets(PlayerCharacter player) { |
|
|
|
for (Mob necroPet : player.necroPets) |
|
if (necroPet.isPet()) |
|
necroPet.agentType = mbEnums.AIAgentType.MOBILE; |
|
} |
|
|
|
public static void spawnNecroPet(PlayerCharacter playerCharacter, Mob mob) { |
|
|
|
if (mob == null) |
|
return; |
|
|
|
if (mob.getMobBaseID() != 12021 && mob.getMobBaseID() != 12022) |
|
return; |
|
|
|
auditNecroPets(playerCharacter); |
|
resetNecroPets(playerCharacter); |
|
|
|
playerCharacter.necroPets.add(mob); |
|
} |
|
|
|
public static void dismissNecroPets(PlayerCharacter playerCharacter) { |
|
|
|
|
|
if (playerCharacter.necroPets.isEmpty()) |
|
return; |
|
|
|
for (Mob necroPet : playerCharacter.necroPets) { |
|
|
|
try { |
|
dismissNecroPet(necroPet, true); |
|
} catch (Exception e) { |
|
Logger.error(e); |
|
} |
|
} |
|
playerCharacter.necroPets.clear(); |
|
} |
|
|
|
public static void loadAllPirateNames() { |
|
|
|
DbManager.NPCQueries.LOAD_PIRATE_NAMES(); |
|
} |
|
|
|
public static String getPirateName(int mobBaseID) { |
|
|
|
ArrayList<String> nameList = null; |
|
|
|
// If we cannot find name for this mobbase then |
|
// fallback to human male |
|
|
|
if (NPC._pirateNames.containsKey(mobBaseID)) |
|
nameList = NPC._pirateNames.get(mobBaseID); |
|
else |
|
nameList = NPC._pirateNames.get(2111); |
|
|
|
if (nameList == null) { |
|
Logger.error("Null name list for 2111!"); |
|
} |
|
|
|
return nameList.get(ThreadLocalRandom.current().nextInt(nameList.size())); |
|
|
|
} |
|
|
|
public static ArrayList<Building> getProtectedBuildings(NPC npc) { |
|
|
|
ArrayList<Building> protectedBuildings = new ArrayList<>(); |
|
|
|
if (npc.building == null) |
|
return protectedBuildings; |
|
|
|
if (npc.building.getCity() == null) |
|
return protectedBuildings; |
|
|
|
for (Building b : npc.building.getCity().getParent().zoneBuildingSet) { |
|
|
|
if (b.getBlueprint() == null) |
|
continue; |
|
|
|
if (b.getProtectionState().equals(mbEnums.ProtectionState.CONTRACT)) |
|
protectedBuildings.add(b); |
|
|
|
if (b.getProtectionState().equals(mbEnums.ProtectionState.PENDING)) |
|
protectedBuildings.add(b); |
|
} |
|
|
|
return protectedBuildings; |
|
} |
|
|
|
public static int slotCharacterInBuilding(AbstractCharacter abstractCharacter) { |
|
|
|
int buildingSlot; |
|
|
|
if (abstractCharacter.building == null) |
|
return -1; |
|
|
|
// Get next available slot for this NPC and use it |
|
// to add the NPC to the building's hireling list |
|
// Account for R8's having slots reversed. |
|
|
|
if (abstractCharacter.building.getBlueprint() != null && abstractCharacter.building.getBlueprint().getBuildingGroup().equals(mbEnums.BuildingGroup.TOL) && abstractCharacter.building.getRank() == 8) |
|
buildingSlot = BuildingManager.getLastAvailableSlot(abstractCharacter.building); |
|
else |
|
buildingSlot = BuildingManager.getAvailableSlot(abstractCharacter.building); |
|
|
|
// Override slot for siege engines |
|
|
|
if (abstractCharacter.getObjectType().equals(mbEnums.GameObjectType.Mob) && ((Mob) abstractCharacter).behaviourType.equals(mbEnums.MobBehaviourType.SiegeEngine)) { |
|
Mob siegeMobile = (Mob) abstractCharacter; |
|
buildingSlot = siegeMobile.guardCaptain.minions.size() + 2; |
|
} |
|
|
|
if (buildingSlot == -1) |
|
Logger.error("No available slot for NPC: " + abstractCharacter.getObjectUUID()); |
|
|
|
// Pets are regular mobiles not hirelings (Siege engines) |
|
if (abstractCharacter.contract != null) |
|
abstractCharacter.building.getHirelings().put(abstractCharacter, buildingSlot); |
|
|
|
// Override bind and location for this npc derived |
|
// from BuildingManager slot location data. |
|
|
|
Vector3fImmutable slotLocation = BuildingManager.getSlotLocation(abstractCharacter.building, buildingSlot).getLocation(); |
|
|
|
abstractCharacter.bindLoc = abstractCharacter.building.getLoc().add(slotLocation); |
|
|
|
// Rotate slot position by the building rotation |
|
|
|
abstractCharacter.bindLoc = Vector3fImmutable.rotateAroundPoint(abstractCharacter.building.getLoc(), abstractCharacter.bindLoc, abstractCharacter.building.getBounds().getQuaternion().angleY); |
|
|
|
abstractCharacter.loc = new Vector3fImmutable(abstractCharacter.bindLoc); |
|
|
|
// Rotate NPC rotation by the building's rotation |
|
|
|
Quaternion slotRotation = new Quaternion().fromAngles(0, acos(abstractCharacter.getRot().y) * 2, 0); |
|
slotRotation = slotRotation.mult(abstractCharacter.building.getBounds().getQuaternion()); |
|
abstractCharacter.setRot(new Vector3f(0, slotRotation.y, 0)); |
|
|
|
// Configure region and floor/level for this NPC |
|
|
|
abstractCharacter.region = BuildingManager.GetRegion(abstractCharacter.building, abstractCharacter.bindLoc.x, abstractCharacter.bindLoc.y, abstractCharacter.bindLoc.z); |
|
|
|
return buildingSlot; |
|
} |
|
|
|
public static void AssignPatrolPoints(Mob mob) { |
|
mob.patrolPoints = new ArrayList<>(); |
|
|
|
for (int i = 0; i < 5; ++i) { |
|
float patrolRadius = mob.getSpawnRadius(); |
|
|
|
if (patrolRadius > 256) |
|
patrolRadius = 256; |
|
|
|
if (patrolRadius < 60) |
|
patrolRadius = 60; |
|
|
|
Vector3fImmutable newPatrolPoint = Vector3fImmutable.getRandomPointInCircle(mob.getBindLoc(), patrolRadius); |
|
mob.patrolPoints.add(newPatrolPoint); |
|
|
|
if (i == 1) { |
|
mob.setLoc(newPatrolPoint); |
|
mob.endLoc = newPatrolPoint; |
|
} |
|
} |
|
} |
|
|
|
public static void applyGuardStanceModifiers(Mob guard) { |
|
float damageModifier = 1; |
|
float attackRatingModifier = 1; |
|
float defenseModifier = 1; |
|
float attackSpeedModifier = 1; |
|
float powerDamageModifier = 1; |
|
//handle stance modifiers for guard mob |
|
if (guard.agentType.equals(mbEnums.AIAgentType.GUARDWALLARCHER)) { |
|
//apply rogue bonuses |
|
attackRatingModifier += 0.5f; |
|
defenseModifier += 0.5f; |
|
damageModifier += 0.5f; |
|
attackSpeedModifier -= 0.36f; |
|
} else { |
|
Integer contractID; |
|
if (guard.agentType.equals(mbEnums.AIAgentType.GUARDMINION)) { |
|
contractID = guard.guardCaptain.contract.getContractID(); |
|
} else { |
|
contractID = guard.contract.getContractID(); |
|
} |
|
if (mbEnums.MinionType.ContractToMinionMap.get(contractID) != null && mbEnums.MinionType.ContractToMinionMap.get(contractID).isMage()) { |
|
//apply mage offensive Stance |
|
powerDamageModifier += 0.5f; |
|
} else { |
|
//apply fighter offensive stance |
|
damageModifier += 0.5f; |
|
attackSpeedModifier -= 0.36f; |
|
} |
|
} |
|
guard.minDamageHandOne *= damageModifier; |
|
guard.minDamageHandTwo *= damageModifier; |
|
guard.maxDamageHandOne *= damageModifier; |
|
guard.maxDamageHandTwo *= damageModifier; |
|
guard.atrHandOne *= attackRatingModifier; |
|
guard.atrHandTwo *= attackRatingModifier; |
|
guard.defenseRating *= defenseModifier; |
|
guard.speedHandOne *= attackSpeedModifier; |
|
guard.speedHandTwo *= attackSpeedModifier; |
|
|
|
//TODO figure out how to apply +50% powerdamage to mage guards |
|
} |
|
|
|
public static void setDamageAndSpeedForGuard(Mob guard) { |
|
|
|
float rankModifier = 1 + (guard.getRank() * 0.1f); |
|
int primaryStat = 0; |
|
if (guard.charItemManager.equipped.isEmpty()) { |
|
guard.minDamageHandOne = (int) ((guard.mobBase.getDamageMin()) * rankModifier); |
|
guard.maxDamageHandOne = (int) ((guard.mobBase.getDamageMax()) * rankModifier); |
|
guard.speedHandOne = 30.0f; |
|
} else { |
|
if (guard.charItemManager.equipped.containsKey(mbEnums.EquipSlotType.RHELD)) { |
|
//has main hand weapon |
|
Item weapon = guard.charItemManager.equipped.get(mbEnums.EquipSlotType.RHELD); |
|
|
|
if (weapon.template.item_primary_attr.equals(mbEnums.AttributeType.Strength)) |
|
primaryStat = guard.getStatStrCurrent(); |
|
else |
|
primaryStat = guard.getStatDexCurrent(); |
|
|
|
guard.minDamageHandOne = (int) ((guard.mobBase.getDamageMin() + weapon.template.item_weapon_damage.values().iterator().next()[0]) * rankModifier) + primaryStat; |
|
guard.maxDamageHandOne = (int) ((guard.mobBase.getDamageMax() + weapon.template.item_weapon_damage.values().iterator().next()[1]) * rankModifier) + primaryStat; |
|
guard.speedHandOne = weapon.template.item_weapon_wepspeed; |
|
guard.rangeHandOne = weapon.template.item_weapon_max_range; |
|
} else if (guard.charItemManager.equipped.containsKey(mbEnums.EquipSlotType.LHELD) && !ItemManager.isShield(guard.charItemManager.equipped.get(mbEnums.EquipSlotType.LHELD).template)) { |
|
//has off hand weapon |
|
Item weapon = guard.charItemManager.equipped.get(mbEnums.EquipSlotType.LHELD); |
|
if (weapon.template.item_primary_attr.equals(mbEnums.AttributeType.Strength)) |
|
primaryStat = guard.getStatStrCurrent(); |
|
else |
|
primaryStat = guard.getStatDexCurrent(); |
|
guard.minDamageHandOne = (int) ((guard.mobBase.getDamageMin() + weapon.template.item_weapon_damage.values().iterator().next()[0]) * rankModifier) + primaryStat; |
|
guard.maxDamageHandOne = (int) ((guard.mobBase.getDamageMax() + weapon.template.item_weapon_damage.values().iterator().next()[1]) * rankModifier) + primaryStat; |
|
guard.speedHandOne = weapon.template.item_weapon_wepspeed; |
|
guard.rangeHandOne = weapon.template.item_weapon_max_range; |
|
} else { |
|
primaryStat = guard.getStatStrCurrent(); |
|
guard.minDamageHandOne = (int) ((guard.mobBase.getDamageMin()) * rankModifier) + primaryStat; |
|
guard.maxDamageHandOne = (int) ((guard.mobBase.getDamageMax()) * rankModifier) + primaryStat; |
|
guard.speedHandOne = 30.0f; |
|
guard.rangeHandOne = 3; |
|
} |
|
} |
|
} |
|
|
|
public static void setDefenseForGuard(Mob guard) { |
|
int dexterity = guard.getStatDexCurrent(); |
|
if (dexterity < 1) |
|
dexterity = 1; |
|
int baseDef = guard.mobBase.getDefenseRating(); |
|
int armorDefense = 0; |
|
for (Item equipped : guard.charItemManager.equipped.values()) |
|
if (equipped.template.item_type.equals(mbEnums.ItemType.ARMOR) || ItemManager.isShield(equipped.template)) |
|
armorDefense += equipped.template.item_defense_rating; |
|
guard.defenseRating = dexterity + baseDef + armorDefense; |
|
} |
|
|
|
public static void setAttackRatingForGuard(Mob guard) { |
|
int strength = guard.getStatStrCurrent(); |
|
int baseAtr = guard.mobBase.getAttackRating(); |
|
if (guard.charItemManager.equipped.get(mbEnums.EquipSlotType.RHELD) != null) |
|
guard.atrHandOne = baseAtr + (int) ((strength * 0.5f) + ((int) guard.charItemManager.equipped.get(mbEnums.EquipSlotType.RHELD).template.item_skill_required.values().toArray()[0] * 4) + ((int) guard.charItemManager.equipped.get(mbEnums.EquipSlotType.RHELD).template.item_skill_required.values().toArray()[0] * 3)); |
|
else if (guard.charItemManager.equipped.get(mbEnums.EquipSlotType.LHELD) != null && !ItemManager.isShield(guard.charItemManager.equipped.get(mbEnums.EquipSlotType.LHELD).template)) |
|
guard.atrHandTwo = baseAtr + (int) ((strength * 0.5f) + ((int) guard.charItemManager.equipped.get(mbEnums.EquipSlotType.LHELD).template.item_skill_required.values().toArray()[0] * 4) + ((int) guard.charItemManager.equipped.get(mbEnums.EquipSlotType.LHELD).template.item_skill_required.values().toArray()[0] * 3)); |
|
else |
|
guard.atrHandOne = baseAtr; |
|
} |
|
|
|
public static void setMaxHealthForGuard(Mob guard) { |
|
//values derived fom reading memory address for health on client when selecting player guards |
|
switch (guard.getRank()) { |
|
default: |
|
guard.healthMax = 750; //rank 1 |
|
break; |
|
case 2: |
|
guard.healthMax = 2082; |
|
break; |
|
case 3: |
|
guard.healthMax = 2740; |
|
break; |
|
case 4: |
|
guard.healthMax = 3414; |
|
break; |
|
case 5: |
|
guard.healthMax = 4080; |
|
break; |
|
case 6: |
|
guard.healthMax = 4746; |
|
break; |
|
case 7: |
|
guard.healthMax = 5412; |
|
break; |
|
} |
|
guard.setHealth(guard.healthMax); |
|
} |
|
|
|
public static void applyMobbaseEffects(Mob mob) { |
|
EffectsBase effectsBase; |
|
for (MobBaseEffects mbe : mob.mobBase.effectsList) { |
|
|
|
effectsBase = PowersManager.getEffectByToken(mbe.getToken()); |
|
|
|
if (effectsBase == null) { |
|
Logger.info("Mob: " + mob.getObjectUUID() + " EffectsBase Null for Token " + mbe.getToken()); |
|
continue; |
|
} |
|
|
|
//check to upgrade effects if needed. |
|
if (mob.effects.containsKey(Integer.toString(effectsBase.getUUID()))) { |
|
|
|
if (mbe.getReqLvl() > (int) mob.level) |
|
continue; |
|
|
|
Effect eff = mob.effects.get(Integer.toString(effectsBase.getUUID())); |
|
|
|
if (eff == null) |
|
continue; |
|
|
|
//Current effect is a higher rank, dont apply. |
|
if (eff.getTrains() > mbe.getRank()) |
|
continue; |
|
|
|
//new effect is of a higher rank. remove old effect and apply new one. |
|
eff.cancelJob(); |
|
mob.addEffectNoTimer(Integer.toString(effectsBase.getUUID()), effectsBase, mbe.getRank(), true); |
|
} else { |
|
|
|
if (mbe.getReqLvl() > (int) mob.level) |
|
continue; |
|
|
|
mob.addEffectNoTimer(Integer.toString(effectsBase.getUUID()), effectsBase, mbe.getRank(), true); |
|
} |
|
|
|
} |
|
} |
|
|
|
public static void applyEquipmentResists(Mob mob) { |
|
|
|
if (mob.charItemManager.equipped.isEmpty()) |
|
return; |
|
|
|
for (Item equipped : mob.charItemManager.equipped.values()) { |
|
if (equipped.template.item_type.equals(mbEnums.ItemType.ARMOR)) { |
|
mob.resists.setResist(mbEnums.DamageType.SLASHING, mob.resists.getResist(mbEnums.DamageType.SLASHING, 0) + equipped.template.combat_attack_resist.get("SLASHING")); |
|
mob.resists.setResist(mbEnums.DamageType.CRUSHING, mob.resists.getResist(mbEnums.DamageType.CRUSHING, 0) + equipped.template.combat_attack_resist.get("CRUSHING")); |
|
mob.resists.setResist(mbEnums.DamageType.PIERCING, mob.resists.getResist(mbEnums.DamageType.PIERCING, 0) + equipped.template.combat_attack_resist.get("PIERCING")); |
|
} |
|
} |
|
} |
|
|
|
public static void applyMobbaseSkill(Mob mob) { |
|
SkillsBase baseSkill = DbManager.SkillsBaseQueries.GET_BASE_BY_TOKEN(mob.mobBase.getMobBaseStats().getBaseSkill()); |
|
if (baseSkill != null) |
|
mob.getSkills().put(baseSkill.getName(), new CharacterSkill(baseSkill, mob, mob.mobBase.getMobBaseStats().getBaseSkillAmount())); |
|
} |
|
|
|
public static void applyRuneSkills(Mob mob, int runeID) { |
|
//load mob skill adjustments from mobbase rune |
|
if (PowersManager._allRuneSkillAdjusts.containsKey(runeID)) |
|
for (RuneSkillAdjustEntry entry : PowersManager._allRuneSkillAdjusts.get(runeID)) { |
|
if (SkillsBase.getFromCache(entry.skill_type) == null) |
|
SkillsBase.putInCache(DbManager.SkillsBaseQueries.GET_BASE_BY_NAME(entry.skill_type)); |
|
SkillsBase skillBase = SkillsBase.getFromCache(entry.skill_type); |
|
if (skillBase == null) |
|
continue; |
|
if (entry.level <= mob.level) |
|
if (mob.skills.containsKey(entry.name) == false) |
|
mob.skills.put(entry.skill_type, new CharacterSkill(skillBase, mob, entry.rank)); |
|
else |
|
mob.skills.put(entry.skill_type, new CharacterSkill(skillBase, mob, entry.rank + mob.skills.get(entry.skill_type).getNumTrains())); |
|
} |
|
} |
|
|
|
public static void applyRunesForNPC(NPC npc) { |
|
npc.runes = new ArrayList<>(); |
|
RuneBase shopkeeperBase = RuneBase.getRuneBase(252620); |
|
CharacterRune shopkeeper = new CharacterRune(shopkeeperBase, npc.getObjectUUID()); |
|
npc.runes.add(shopkeeper); |
|
if (NPCManager._runeSetMap.containsKey(npc.runeSetID)) { |
|
for (int runeID : _runeSetMap.get(npc.runeSetID)) { |
|
RuneBase rb = RuneBase.getRuneBase(runeID); |
|
if (rb != null) { |
|
CharacterRune toApply = new CharacterRune(rb, npc.getObjectUUID()); |
|
npc.runes.add(toApply); |
|
} |
|
} |
|
} |
|
} |
|
|
|
public static Boolean NPCVaultBankRangeCheck(PlayerCharacter pc, ClientConnection origin, String bankorvault) { |
|
|
|
if (pc == null) |
|
return false; |
|
|
|
NPC npc = pc.getLastNPCDialog(); |
|
|
|
if (npc == null) |
|
return false; |
|
|
|
// System.out.println(npc.getContract().getName()); |
|
// last npc must be either a banker or vault keeper |
|
|
|
if (bankorvault.equals("vault")) { |
|
if (npc.getContract().getContractID() != 861) |
|
return false; |
|
} else |
|
// assuming banker |
|
|
|
if (!npc.getContract().getName().equals("Bursar")) |
|
return false; |
|
|
|
if (pc.getLoc().distanceSquared2D(npc.getLoc()) > MBServerStatics.NPC_TALK_RANGE * MBServerStatics.NPC_TALK_RANGE) { |
|
ErrorPopupMsg.sendErrorPopup(pc, 14); |
|
return false; |
|
} else |
|
return true; |
|
|
|
} |
|
|
|
public static ArrayList<Item> getAllCookingForVendor(NPC npc) { |
|
|
|
ArrayList<Item> itemList = new ArrayList<>(); |
|
|
|
ConcurrentHashMap.KeySetView<WorkOrder, Boolean> vendorWorkOrders = ForgeManager.vendorWorkOrderLookup.get(npc); |
|
|
|
for (WorkOrder workOrder : vendorWorkOrders) |
|
itemList.addAll(workOrder.cooking); |
|
|
|
return itemList; |
|
} |
|
|
|
public static long calcRollingDuration(NPC vendor, int templateID) { |
|
|
|
ItemTemplate template = ItemTemplate.templates.get(templateID); |
|
float rollingDuration; |
|
|
|
if (template == null) |
|
return 0; |
|
|
|
if (template.item_bane_rank > 0) |
|
return (long) (template.item_bane_rank * 60 * 60 * 3 * 1000 * Float.parseFloat(ConfigManager.MB_PRODUCTION_RATE.getValue())); |
|
|
|
if (vendor.building == null) |
|
return 600; |
|
|
|
rollingDuration = vendor.getBuilding().getRank() * -5L + 40; |
|
rollingDuration = TimeUnit.MINUTES.toMillis((long) rollingDuration); |
|
rollingDuration *= Float.parseFloat(ConfigManager.MB_PRODUCTION_RATE.getValue()); |
|
|
|
return (long) rollingDuration; |
|
} |
|
}
|
|
|