Block skill refines that break a trained power's skill requirement

The old check looked up power requirements by power id instead of rune id,
so it never ran. Refining a skill below a trained power's requirement let
calculatePowers delete the power and its trains.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MagicBotandClaude Opus 5.5 committed 2026-10-26 11:41:23 -04:00
1 parent 17d82066d6
commit 24e91cc0a9
2 files changed
+46 -11

No files matched your search

@@ -88,6 +88,9 @@ public class RefineMsgHandler extends AbstractClientMsgHandler {
public static boolean refineSkill(ClientConnection origin, PlayerCharacter pc, int token, RefineMsg msg) {
CharacterSkill skill = null;
ConcurrentHashMap<String, CharacterSkill> skills = pc.getSkills();
int refinedAmount;
int requiredAmount;
for (CharacterSkill sk : skills.values()) {
if (sk == null)
continue;
@@ -106,17 +109,16 @@ public class RefineMsgHandler extends AbstractClientMsgHandler {
//TODO verify if any skills have this as prereq
//TODO verify if any powers have this as a prereq
//get all players powers
// Dropping below a trained power's skill requirement would make calculatePowers delete the power and its trains
refinedAmount = Math.round(skill.getBaseAmountBeforeMods() + skill.calculateAmountAfterTrains(skill.getNumTrains() - 1));
for (CharacterPower power : pc.getPowers().values()) {
ArrayList<PowerReq> reqs = PowerReq.getPowerReqsForRune(power.getPowerID());
for (PowerReq req : reqs) {
ConcurrentHashMap<String, CharacterSkill> playerSkills = pc.getSkills();
CharacterSkill playerSkill = playerSkills.get(token);
int currentSkillLevel = playerSkill.getTotalSkillPercet();
if (token == req.getToken() && req.getLevel() == currentSkillLevel) {
return false;
}
if (power.getTrains() < 1)
continue;
requiredAmount = getRequiredSkillAmount(pc, power.getPower().getToken(), token);
if (refinedAmount < requiredAmount) {
ErrorPopupMsg.sendErrorMsg(pc, "You must refine " + power.getPower().getName() + " to 0 before refining any more from this skill.");
return false;
}
}
@@ -124,6 +126,36 @@ public class RefineMsgHandler extends AbstractClientMsgHandler {
return skill.refine(pc);
}
private static int getRequiredSkillAmount(PlayerCharacter pc, int powerToken, int skillToken) {
int requiredAmount = 0;
if (pc.race != null)
requiredAmount = Math.max(requiredAmount, getRequiredSkillAmount(pc.race.getPowersGranted(), powerToken, skillToken));
if (pc.baseClass != null)
requiredAmount = Math.max(requiredAmount, getRequiredSkillAmount(pc.baseClass.getPowersGranted(), powerToken, skillToken));
if (pc.promotionClass != null)
requiredAmount = Math.max(requiredAmount, getRequiredSkillAmount(pc.promotionClass.getPowersGranted(), powerToken, skillToken));
if (pc.getRunes() != null)
for (CharacterRune rune : pc.getRunes())
requiredAmount = Math.max(requiredAmount, getRequiredSkillAmount(rune.getPowersGranted(), powerToken, skillToken));
return requiredAmount;
}
private static int getRequiredSkillAmount(ArrayList<PowerReq> powersGranted, int powerToken, int skillToken) {
Byte requiredAmount;
for (PowerReq powerReq : powersGranted) {
if (powerReq.getToken() != powerToken)
continue;
requiredAmount = powerReq.getSkillReqs().get(skillToken);
if (requiredAmount != null)
return requiredAmount;
}
return 0;
}
public static boolean refinePower(ClientConnection origin, PlayerCharacter pc, int token, RefineMsg msg) {
CharacterPower power = null;
ConcurrentHashMap<Integer, CharacterPower> powers = pc.getPowers();
+4 -1
View File
@@ -1136,9 +1136,12 @@ public class CharacterSkill extends AbstractGameObject {
Logger.error("SkillsBase not found for skill " + this.getObjectUUID());
this.modifiedAmount = this.baseAmount;
}
return calculateAmountAfterTrains(this.numTrains.get());
}
public float calculateAmountAfterTrains(int trains) {
int amount;
int trains = this.numTrains.get();
if (trains < 10)
amount = (trains * 2);
else if (trains < 90)