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.
355 lines
14 KiB
355 lines
14 KiB
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . |
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· |
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ |
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ |
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ |
|
// Magicbane Emulator Project © 2013 - 2022 |
|
// www.magicbane.com |
|
|
|
|
|
package engine.net.client.msg; |
|
|
|
import engine.Enum; |
|
import engine.Enum.ProtectionState; |
|
import engine.exception.MsgSendException; |
|
import engine.gameManager.ChatManager; |
|
import engine.gameManager.DbManager; |
|
import engine.gameManager.PowersManager; |
|
import engine.gameManager.SessionManager; |
|
import engine.net.*; |
|
import engine.net.client.ClientConnection; |
|
import engine.net.client.Protocol; |
|
import engine.objects.*; |
|
import engine.powers.PowersBase; |
|
import engine.server.MBServerStatics; |
|
import org.pmw.tinylog.Logger; |
|
|
|
import java.util.concurrent.ConcurrentHashMap; |
|
|
|
|
|
public class TrainMsg extends ClientNetMsg { |
|
|
|
private int npcType; |
|
private int npcID; |
|
private int unknown01 = 1; |
|
private int trainCost01; //why two trainer costs? |
|
private int trainCost02; //why two trainer costs? |
|
private boolean isSkill; //true: skill; false: power |
|
private int token; |
|
private boolean unknown02 = true; |
|
private String ok = ""; |
|
private int unknown03 = 0; |
|
|
|
/** |
|
* This is the general purpose constructor. |
|
*/ |
|
public TrainMsg() { |
|
super(Protocol.TRAINSKILL); |
|
} |
|
|
|
/** |
|
* This constructor is used by NetMsgFactory. It attempts to deserialize the |
|
* ByteBuffer into a message. If a BufferUnderflow occurs (based on reading |
|
* past the limit) then this constructor Throws that Exception to the |
|
* caller. |
|
*/ |
|
public TrainMsg(AbstractConnection origin, ByteBufferReader reader) { |
|
super(Protocol.TRAINSKILL, origin, reader); |
|
} |
|
|
|
public static void train(TrainMsg msg, ClientConnection origin) throws MsgSendException { |
|
origin.getPlayerCharacter().recalculate(); |
|
PlayerCharacter playerCharacter = SessionManager.getPlayerCharacter(origin); |
|
Dispatch dispatch; |
|
|
|
if (playerCharacter == null) |
|
return; |
|
|
|
NPC npc = NPC.getFromCache(msg.npcID); |
|
|
|
if (npc == null) |
|
return; |
|
|
|
if (origin.trainLock.tryLock()) { |
|
try { |
|
Item gold = playerCharacter.getCharItemManager().getGoldInventory(); |
|
|
|
if (gold == null) |
|
return; |
|
|
|
if (!gold.validForInventory(origin, playerCharacter, playerCharacter.getCharItemManager())) |
|
return; |
|
|
|
boolean canTrain = false; |
|
if (msg.isSkill) { |
|
|
|
//Get skill |
|
SkillsBase sb = DbManager.SkillsBaseQueries.GET_BASE_BY_TOKEN(msg.token); |
|
ConcurrentHashMap<String, CharacterSkill> skills = playerCharacter.getSkills(); |
|
|
|
if (sb == null || skills == null) |
|
return; |
|
|
|
CharacterSkill sk = skills.get(sb.getName()); |
|
|
|
if (sk == null) |
|
return; |
|
|
|
if (sk.getSkillsBase().getToken() == 40661438) { |
|
int maxValue = 15; |
|
|
|
|
|
if (MaxSkills.MaxSkillsSet.get(252647) != null) |
|
for (MaxSkills maxSkills : MaxSkills.MaxSkillsSet.get(252647)) { |
|
if (maxSkills.getSkillToken() != sk.getToken()) |
|
continue; |
|
|
|
if (maxSkills.getSkillLevel() > npc.getLevel()) |
|
continue; |
|
maxValue += maxSkills.getMaxSkillPercent(); |
|
} |
|
if (maxValue > sk.getModifiedAmountBeforeMods()) { |
|
canTrain = true; |
|
} |
|
|
|
} |
|
if (canTrain == false) |
|
if (npc.getContract() != null && npc.getContract().getExtraRune() != 0) { |
|
int maxValue = 15; |
|
|
|
|
|
if (MaxSkills.MaxSkillsSet.get(npc.getContract().getExtraRune()) != null) |
|
for (MaxSkills maxSkills : MaxSkills.MaxSkillsSet.get(npc.getContract().getExtraRune())) { |
|
if (maxSkills.getSkillToken() != sk.getToken()) |
|
continue; |
|
|
|
if (maxSkills.getSkillLevel() > npc.getLevel()) |
|
continue; |
|
maxValue += maxSkills.getMaxSkillPercent(); |
|
} |
|
if (maxValue > sk.getModifiedAmountBeforeMods()) { |
|
canTrain = true; |
|
} |
|
|
|
|
|
} |
|
if (canTrain == false) { |
|
int maxValue = 15; |
|
if (MaxSkills.MaxSkillsSet.get(npc.getContractID()) != null) |
|
for (MaxSkills maxSkills : MaxSkills.MaxSkillsSet.get(npc.getContractID())) { |
|
if (maxSkills.getSkillToken() != sk.getToken()) |
|
continue; |
|
|
|
if (maxSkills.getSkillLevel() > npc.getLevel()) |
|
continue; |
|
maxValue += maxSkills.getMaxSkillPercent(); |
|
} |
|
if (maxValue > sk.getModifiedAmountBeforeMods()) { |
|
canTrain = true; |
|
} |
|
} |
|
|
|
if (canTrain == false) { |
|
int maxValue = 15; |
|
if (MaxSkills.MaxSkillsSet.get(npc.getContract().getClassID()) != null) |
|
for (MaxSkills maxSkills : MaxSkills.MaxSkillsSet.get(npc.getContract().getClassID())) { |
|
if (maxSkills.getSkillToken() != sk.getToken()) |
|
continue; |
|
|
|
if (maxSkills.getSkillLevel() > npc.getLevel()) |
|
continue; |
|
maxValue += maxSkills.getMaxSkillPercent(); |
|
} |
|
if (maxValue > sk.getModifiedAmountBeforeMods()) { |
|
canTrain = true; |
|
} |
|
} |
|
|
|
if (canTrain == false) { |
|
int maxValue = 15; |
|
if (MaxSkills.MaxSkillsSet.get(npc.extraRune2) != null) |
|
for (MaxSkills maxSkills : MaxSkills.MaxSkillsSet.get(npc.getContract().getClassID())) { |
|
if (maxSkills.getSkillToken() != sk.getToken()) |
|
continue; |
|
|
|
if (maxSkills.getSkillLevel() > npc.getLevel()) |
|
continue; |
|
maxValue += maxSkills.getMaxSkillPercent(); |
|
} |
|
if (maxValue > sk.getModifiedAmountBeforeMods()) { |
|
canTrain = true; |
|
} |
|
} |
|
|
|
if (canTrain == false) { |
|
ChatManager.chatSystemError(playerCharacter, "NPC cannot train that skill any higher"); |
|
return; |
|
} |
|
|
|
float cost = sk.getTrainingCost(playerCharacter, npc); |
|
float profitCost = cost * npc.getSellPercent(playerCharacter); |
|
|
|
profitCost += .5f; |
|
if (profitCost > playerCharacter.getCharItemManager().getGoldInventory().getNumOfItems()) |
|
return; |
|
Building b = npc.getBuilding(); |
|
if (b != null && b.getProtectionState().equals(ProtectionState.NPC)) |
|
b = null; |
|
|
|
if (b != null && b.getStrongboxValue() + (profitCost - cost) > b.getMaxGold()) { |
|
ErrorPopupMsg.sendErrorPopup(playerCharacter, 206); |
|
return; |
|
} |
|
|
|
if (playerCharacter.getCharItemManager().getGoldInventory().getNumOfItems() - profitCost < 0) |
|
return; |
|
|
|
if (playerCharacter.getCharItemManager().getGoldInventory().getNumOfItems() - profitCost > MBServerStatics.PLAYER_GOLD_LIMIT) |
|
return; |
|
|
|
|
|
//attempt to train |
|
if (sk.train(playerCharacter)) { |
|
playerCharacter.getCharItemManager().buyFromNPC(b, (int) profitCost, (int) (profitCost - cost)); |
|
|
|
dispatch = Dispatch.borrow(playerCharacter, msg); |
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); |
|
|
|
//update trainer window |
|
|
|
if (npc != null) { |
|
TrainerInfoMsg tim = new TrainerInfoMsg(msg.npcType, msg.npcID, npc.getSellPercent(playerCharacter)); |
|
tim.setTrainPercent(npc.getSellPercent(playerCharacter)); |
|
dispatch = Dispatch.borrow(playerCharacter, tim); |
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); |
|
} |
|
} |
|
|
|
} else { |
|
//Get Power |
|
int token = msg.token; |
|
|
|
if (MBServerStatics.POWERS_DEBUG) { |
|
ChatManager.chatSayInfo(playerCharacter, "Training Power: " + |
|
Integer.toHexString(msg.token) + " (" + msg.token + ')'); |
|
System.out.println("Training Power: " + |
|
Integer.toHexString(msg.token) + " (" + msg.token + ')'); |
|
} |
|
|
|
PowersBase pb = PowersManager.getPowerByToken(token); |
|
ConcurrentHashMap<Integer, CharacterPower> powers = playerCharacter.getPowers(); |
|
if (pb == null || powers == null) |
|
return; |
|
|
|
if (pb.isWeaponPower) |
|
return; |
|
CharacterPower cp = null; |
|
if (powers.containsKey(token)) |
|
cp = powers.get(token); |
|
if (cp == null) |
|
return; |
|
|
|
//attempt to train |
|
float cost = (int) cp.getTrainingCost(playerCharacter, npc); |
|
float profitCost = cost * npc.getSellPercent(playerCharacter); |
|
profitCost += .5f; |
|
if (profitCost > playerCharacter.getCharItemManager().getGoldInventory().getNumOfItems()) { |
|
// ChatManager.chatSystemError(pc, "You do not have enough gold to train this skill."); |
|
return; |
|
} |
|
|
|
Building b = npc.getBuilding(); |
|
|
|
if (b != null && b.getProtectionState().equals(ProtectionState.NPC)) |
|
b = null; |
|
|
|
if (b != null && b.getStrongboxValue() + (profitCost - cost) > b.getMaxGold()) { |
|
ErrorPopupMsg.sendErrorPopup(playerCharacter, 206); |
|
return; |
|
} |
|
if (cp.train(playerCharacter)) { |
|
|
|
if (!playerCharacter.getCharItemManager().buyFromNPC(b, (int) profitCost, (int) (profitCost - cost))) |
|
ChatManager.chatSystemError(playerCharacter, "Failed to Withdrawl gold from inventory. Contact CCR"); |
|
|
|
//train succeeded |
|
|
|
dispatch = Dispatch.borrow(playerCharacter, msg); |
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); |
|
|
|
//update trainer window |
|
|
|
if (npc != null) { |
|
TrainerInfoMsg tim = new TrainerInfoMsg(msg.npcType, msg.npcID, npc.getSellPercent(playerCharacter)); |
|
tim.setTrainPercent(npc.getSellPercent(playerCharacter)); |
|
dispatch = Dispatch.borrow(playerCharacter, tim); |
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); |
|
} |
|
} |
|
} |
|
} catch (Exception e) { |
|
Logger.error(e); |
|
} finally { |
|
origin.trainLock.unlock(); |
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
public static float getTrainPercent(NPC npc) { |
|
return 0f; |
|
} |
|
|
|
/** |
|
* Serializes the subclass specific items to the supplied NetMsgWriter. |
|
*/ |
|
@Override |
|
protected void _serialize(ByteBufferWriter writer) { |
|
writer.putInt(this.npcType); |
|
writer.putInt(this.npcID); |
|
writer.putInt(this.unknown01); |
|
writer.putInt(trainCost01); |
|
writer.putInt(trainCost02); |
|
writer.put((this.isSkill == true) ? (byte) 0x01 : (byte) 0x00); |
|
writer.putInt(this.token); |
|
writer.put((this.unknown02 == true) ? (byte) 0x01 : (byte) 0x00); |
|
writer.putString(this.ok); |
|
writer.putInt(this.unknown03); |
|
} |
|
|
|
/** |
|
* Deserializes the subclass specific items from the supplied NetMsgReader. |
|
*/ |
|
@Override |
|
protected void _deserialize(ByteBufferReader reader) { |
|
this.npcType = reader.getInt(); |
|
this.npcID = reader.getInt(); |
|
this.unknown01 = reader.getInt(); |
|
this.trainCost01 = reader.getInt(); |
|
this.trainCost02 = reader.getInt(); |
|
this.isSkill = (reader.get() == (byte) 0x01) ? true : false; |
|
this.token = reader.getInt(); |
|
this.unknown02 = (reader.get() == (byte) 0x01) ? true : false; |
|
this.ok = reader.getString(); |
|
this.unknown03 = reader.getInt(); |
|
} |
|
|
|
public int getToken() { |
|
return this.token; |
|
} |
|
|
|
public boolean isSkill() { |
|
return this.isSkill; |
|
} |
|
|
|
public int getNpcType() { |
|
return this.npcType; |
|
} |
|
|
|
public int getNpcID() { |
|
return this.npcID; |
|
} |
|
}
|
|
|