Replace talents by sub type and rank, cap talents at 8
Follows the client's ArcCharacter_AddRune (0x4695D0, specs/RuneRequirements.md): a talent replaces a held talent with the same non-zero rune_sub_type when its rank is 0 or higher than the held rank; otherwise the apply fails. With no talent to replace, a new talent needs fewer than 8 held talents. RuneBase gets runeType, a sub type token (SBStringHash(rune_sub_type), or the stored hash) and rank from the rune. It no longer copies the static_rune_runereq type 5 overwrite list, and ApplyRuneMsg no longer reads it. Value changes: - Stat chains (*MaxIncrease) replace the same ranks as before; the DB typos go away (250026 listed 250019 twice and missed 250018) - Talents in the same group now replace each other when applied from a runestone (e.g. Bloodline sub-race talents); before, both were added - Limit: 8 talents instead of more than 12 runes of any kind - Rank-0 downgrade (decided: follow the client) takes effect in the next commit, when the DB stat-chain blocks leave the discipline map Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8f87778c43
commit
c3f1861cf7
2 files changed
+57
-12
No files matched your search
@@ -26,6 +26,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ApplyRuneMsg extends ClientNetMsg {
|
||||
|
||||
// Client ArcCharacter_AddRune (0x4695D0)
|
||||
private static final int MAX_TALENTS = 8;
|
||||
|
||||
private int targetType;
|
||||
private int targetID;
|
||||
private int removeRuneBase;
|
||||
@@ -158,6 +161,31 @@ public class ApplyRuneMsg extends ClientNetMsg {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Client 0x4695D0: a talent replaces a held one with the same sub type when its rank is 0 or higher
|
||||
CharacterRune replacedRune = null;
|
||||
|
||||
if (rb.getRuneType() == mbEnums.RuneType.TALENT) {
|
||||
int talentCount = 0;
|
||||
|
||||
for (CharacterRune cr : runes) {
|
||||
RuneBase heldRuneBase = cr.getRuneBase();
|
||||
|
||||
if (heldRuneBase == null || heldRuneBase.getRuneType() != mbEnums.RuneType.TALENT)
|
||||
continue;
|
||||
|
||||
talentCount++;
|
||||
|
||||
if (rb.getSubTypeToken() != 0 && heldRuneBase.getSubTypeToken() == rb.getSubTypeToken())
|
||||
replacedRune = cr;
|
||||
}
|
||||
|
||||
if (replacedRune != null) {
|
||||
if (rb.getRank() != 0 && rb.getRank() <= replacedRune.getRuneBase().getRank())
|
||||
return false;
|
||||
} else if (talentCount >= MAX_TALENTS)
|
||||
return false;
|
||||
}
|
||||
|
||||
int strTotal = 0;
|
||||
int dexTotal = 0;
|
||||
int conTotal = 0;
|
||||
@@ -227,11 +255,6 @@ public class ApplyRuneMsg extends ClientNetMsg {
|
||||
}
|
||||
}
|
||||
|
||||
//Check if max number runes already reached
|
||||
if (runes.size() > 12) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//if discipline, check number applied
|
||||
if (isDiscipline(runeID)) {
|
||||
if (playerCharacter.getLevel() < 70) {
|
||||
@@ -259,13 +282,10 @@ public class ApplyRuneMsg extends ClientNetMsg {
|
||||
return false;
|
||||
}
|
||||
|
||||
//remove any overridden runes from player
|
||||
ArrayList<Integer> overwrite = rb.getOverwrite();
|
||||
//remove the replaced talent from player
|
||||
CharacterRune toRemove = null;
|
||||
if (overwrite.size() > 0) {
|
||||
for (int overwriteID : overwrite) {
|
||||
toRemove = playerCharacter.removeRune(overwriteID);
|
||||
}
|
||||
if (replacedRune != null) {
|
||||
toRemove = playerCharacter.removeRune(replacedRune.getRuneBaseID());
|
||||
}
|
||||
|
||||
//add rune to player
|
||||
|
||||
Reference in new issue
Block a user