try to improve UX for dumbasses
This commit is contained in:
+1
-1
@@ -48,7 +48,7 @@ mod_name=Fretux's Skill Engine
|
|||||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||||
mod_license=All Rights Reserved
|
mod_license=All Rights Reserved
|
||||||
# The mod version. See https://semver.org/
|
# The mod version. See https://semver.org/
|
||||||
mod_version=1.4.3
|
mod_version=1.4.5
|
||||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||||
# This should match the base package used for the mod sources.
|
# This should match the base package used for the mod sources.
|
||||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||||
|
|||||||
@@ -69,7 +69,8 @@ public class AbilitySlotsScreen extends Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void drawSlotRow(GuiGraphics gfx, int x, int y, int slot, String label) {
|
private void drawSlotRow(GuiGraphics gfx, int x, int y, int slot, String label) {
|
||||||
gfx.drawString(font, label + ":", x, y + 6, 0xFFFFFF);
|
String slotLabel = label + ":";
|
||||||
|
gfx.drawString(font, slotLabel, x, y + 6, 0xFFFFFF);
|
||||||
ResourceLocation abilityId = SkilltreeClientState.getAbilityInSlot(slot);
|
ResourceLocation abilityId = SkilltreeClientState.getAbilityInSlot(slot);
|
||||||
String title = "Empty";
|
String title = "Empty";
|
||||||
ResourceLocation icon = null;
|
ResourceLocation icon = null;
|
||||||
@@ -83,11 +84,12 @@ public class AbilitySlotsScreen extends Screen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
gfx.blit(icon, x + 20, y - 2, 0, 0, 20, 20, 20, 20);
|
int iconX = x + font.width(slotLabel) + 6;
|
||||||
int textX = x + 46;
|
gfx.blit(icon, iconX, y - 2, 0, 0, 20, 20, 20, 20);
|
||||||
|
int textX = iconX + 26;
|
||||||
gfx.drawString(font, fitTitle(title, textX), textX, y + 6, 0xDDDDDD);
|
gfx.drawString(font, fitTitle(title, textX), textX, y + 6, 0xDDDDDD);
|
||||||
} else {
|
} else {
|
||||||
int textX = x + 20;
|
int textX = x + font.width(slotLabel) + 6;
|
||||||
gfx.drawString(font, fitTitle(title, textX), textX, y + 6, 0x888888);
|
gfx.drawString(font, fitTitle(title, textX), textX, y + 6, 0x888888);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ public class SkilltreeScreen extends Screen {
|
|||||||
private AbilityNode hoveredAbility = null;
|
private AbilityNode hoveredAbility = null;
|
||||||
private AbilityNode selectedAbility = null;
|
private AbilityNode selectedAbility = null;
|
||||||
private ResourceLocation activeTree = null;
|
private ResourceLocation activeTree = null;
|
||||||
|
private ResourceLocation highlightedNode = null;
|
||||||
|
private ResourceLocation highlightedAbility = null;
|
||||||
|
private boolean highlightSkillPoints = false;
|
||||||
|
private Component unlockFailureMessage = null;
|
||||||
|
|
||||||
public SkilltreeScreen() {
|
public SkilltreeScreen() {
|
||||||
super(Component.literal("Ascend Skilltree"));
|
super(Component.literal("Ascend Skilltree"));
|
||||||
@@ -132,6 +136,7 @@ public class SkilltreeScreen extends Screen {
|
|||||||
hoveredNode = findNodeAt(mouseX, mouseY);
|
hoveredNode = findNodeAt(mouseX, mouseY);
|
||||||
hoveredAbility = findAbilityAt(mouseX, mouseY);
|
hoveredAbility = findAbilityAt(mouseX, mouseY);
|
||||||
drawGraph(gfx);
|
drawGraph(gfx);
|
||||||
|
renderUnlockFailure(gfx);
|
||||||
if (hoveredNode != null && selectedNode == null && selectedAbility == null) {
|
if (hoveredNode != null && selectedNode == null && selectedAbility == null) {
|
||||||
renderNodeTooltip(gfx, hoveredNode, mouseX, mouseY);
|
renderNodeTooltip(gfx, hoveredNode, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
@@ -150,7 +155,13 @@ public class SkilltreeScreen extends Screen {
|
|||||||
.append(Component.literal(String.valueOf(remaining)).withStyle(ChatFormatting.GOLD));
|
.append(Component.literal(String.valueOf(remaining)).withStyle(ChatFormatting.GOLD));
|
||||||
int panelWidth = font.width(pointsText) + 16;
|
int panelWidth = font.width(pointsText) + 16;
|
||||||
gfx.fill(7, 6, 7 + panelWidth, 24, 0xAA080B10);
|
gfx.fill(7, 6, 7 + panelWidth, 24, 0xAA080B10);
|
||||||
gfx.fill(7, 6, 9, 24, 0xFFFFC857);
|
gfx.fill(7, 6, 9, 24, highlightSkillPoints ? 0xFFFF4545 : 0xFFFFC857);
|
||||||
|
if (highlightSkillPoints) {
|
||||||
|
gfx.fill(5, 4, 7 + panelWidth + 2, 6, 0xFFFF4545);
|
||||||
|
gfx.fill(5, 24, 7 + panelWidth + 2, 26, 0xFFFF4545);
|
||||||
|
gfx.fill(5, 4, 7, 26, 0xFFFF4545);
|
||||||
|
gfx.fill(7 + panelWidth, 4, 7 + panelWidth + 2, 26, 0xFFFF4545);
|
||||||
|
}
|
||||||
gfx.drawString(font, pointsText, 14, 11, 0xFFFFFF, true);
|
gfx.drawString(font, pointsText, 14, 11, 0xFFFFFF, true);
|
||||||
Component hint = Component.literal("Drag to pan • Scroll to zoom")
|
Component hint = Component.literal("Drag to pan • Scroll to zoom")
|
||||||
.withStyle(ChatFormatting.DARK_GRAY);
|
.withStyle(ChatFormatting.DARK_GRAY);
|
||||||
@@ -203,7 +214,9 @@ public class SkilltreeScreen extends Screen {
|
|||||||
int[] pos = worldToScreen(ability.getX(), ability.getY());
|
int[] pos = worldToScreen(ability.getX(), ability.getY());
|
||||||
boolean unlocked = SkilltreeClientState.isAbilityUnlocked(ability.getId());
|
boolean unlocked = SkilltreeClientState.isAbilityUnlocked(ability.getId());
|
||||||
int color;
|
int color;
|
||||||
if (ability == selectedAbility) {
|
if (ability.getId().equals(highlightedAbility)) {
|
||||||
|
color = 0xFFFF4545;
|
||||||
|
} else if (ability == selectedAbility) {
|
||||||
color = 0xFFAA8833;
|
color = 0xFFAA8833;
|
||||||
} else if (ability == hoveredAbility) {
|
} else if (ability == hoveredAbility) {
|
||||||
color = 0xFF8888AA;
|
color = 0xFF8888AA;
|
||||||
@@ -404,6 +417,12 @@ public class SkilltreeScreen extends Screen {
|
|||||||
boolean alreadyUnlocked = SkilltreeClientState.isUnlocked(selectedNode.getId());
|
boolean alreadyUnlocked = SkilltreeClientState.isUnlocked(selectedNode.getId());
|
||||||
if (!alreadyUnlocked) {
|
if (!alreadyUnlocked) {
|
||||||
addRenderableWidget(Button.builder(Component.literal("Unlock"), btn -> {
|
addRenderableWidget(Button.builder(Component.literal("Unlock"), btn -> {
|
||||||
|
if (!prepareSkillUnlock(selectedNode)) {
|
||||||
|
selectedNode = null;
|
||||||
|
clearWidgets();
|
||||||
|
rebuildTreeTabs();
|
||||||
|
return;
|
||||||
|
}
|
||||||
PacketHandler.CHANNEL.sendToServer(
|
PacketHandler.CHANNEL.sendToServer(
|
||||||
new ServerboundUnlockNodePacket(selectedNode.getId())
|
new ServerboundUnlockNodePacket(selectedNode.getId())
|
||||||
);
|
);
|
||||||
@@ -433,6 +452,12 @@ public class SkilltreeScreen extends Screen {
|
|||||||
boolean unlocked = SkilltreeClientState.isAbilityUnlocked(selectedAbility.getId());
|
boolean unlocked = SkilltreeClientState.isAbilityUnlocked(selectedAbility.getId());
|
||||||
if (!unlocked) {
|
if (!unlocked) {
|
||||||
addRenderableWidget(Button.builder(Component.literal("Unlock"), btn -> {
|
addRenderableWidget(Button.builder(Component.literal("Unlock"), btn -> {
|
||||||
|
if (!prepareAbilityUnlock(selectedAbility)) {
|
||||||
|
selectedAbility = null;
|
||||||
|
clearWidgets();
|
||||||
|
rebuildTreeTabs();
|
||||||
|
return;
|
||||||
|
}
|
||||||
PacketHandler.CHANNEL.sendToServer(
|
PacketHandler.CHANNEL.sendToServer(
|
||||||
new ServerboundUnlockNodePacket(selectedAbility.getId())
|
new ServerboundUnlockNodePacket(selectedAbility.getId())
|
||||||
);
|
);
|
||||||
@@ -491,7 +516,9 @@ public class SkilltreeScreen extends Screen {
|
|||||||
boolean unlocked = SkilltreeClientState.isUnlocked(node.getId());
|
boolean unlocked = SkilltreeClientState.isUnlocked(node.getId());
|
||||||
boolean lockedByExclusivity = isLockedByExclusivity(node);
|
boolean lockedByExclusivity = isLockedByExclusivity(node);
|
||||||
int color;
|
int color;
|
||||||
if (lockedByExclusivity) {
|
if (node.getId().equals(highlightedNode)) {
|
||||||
|
color = 0xFFFF4545;
|
||||||
|
} else if (lockedByExclusivity) {
|
||||||
color = 0xFFCC3333;
|
color = 0xFFCC3333;
|
||||||
} else if (node == selectedNode) {
|
} else if (node == selectedNode) {
|
||||||
color = 0xFF999933;
|
color = 0xFF999933;
|
||||||
@@ -514,6 +541,87 @@ public class SkilltreeScreen extends Screen {
|
|||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean prepareSkillUnlock(SkillNode target) {
|
||||||
|
clearUnlockHighlights();
|
||||||
|
for (ResourceLocation parentId : target.getLinks()) {
|
||||||
|
if (SkilltreeClientState.isUnlocked(parentId)) continue;
|
||||||
|
SkillNode parent = SkillNodeRegistry.get(parentId);
|
||||||
|
highlightedNode = parentId;
|
||||||
|
Component parentName = parent != null ? parent.getTitle() : Component.literal(parentId.toString());
|
||||||
|
unlockFailureMessage = Component.literal("Unlock ")
|
||||||
|
.append(parentName.copy().withStyle(ChatFormatting.YELLOW))
|
||||||
|
.append(Component.literal(" first — it is required for "))
|
||||||
|
.append(target.getTitle().copy().withStyle(ChatFormatting.WHITE));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!meetsClientAttributes(target)) {
|
||||||
|
highlightedNode = target.getId();
|
||||||
|
unlockFailureMessage = Component.literal("Attribute requirements are not met for ")
|
||||||
|
.append(target.getTitle().copy().withStyle(ChatFormatting.YELLOW));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (SkilltreeClientState.getCurrentSkillPoints() < Math.max(0, target.getCost())) {
|
||||||
|
highlightSkillPoints = true;
|
||||||
|
unlockFailureMessage = Component.literal("Not enough skill points to unlock ")
|
||||||
|
.append(target.getTitle().copy().withStyle(ChatFormatting.YELLOW));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean meetsClientAttributes(SkillNode node) {
|
||||||
|
if (node.getPrereqAttributes().isEmpty()) return true;
|
||||||
|
Minecraft minecraft = Minecraft.getInstance();
|
||||||
|
if (minecraft.player == null) return false;
|
||||||
|
return minecraft.player.getCapability(PlayerStatsProvider.PLAYER_STATS)
|
||||||
|
.map(stats -> node.getPrereqAttributes().entrySet().stream()
|
||||||
|
.allMatch(entry -> stats.getAttributeLevel(entry.getKey()) >= entry.getValue()))
|
||||||
|
.orElse(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean prepareAbilityUnlock(AbilityNode ability) {
|
||||||
|
clearUnlockHighlights();
|
||||||
|
for (ResourceLocation parentId : ability.getLinks()) {
|
||||||
|
if (SkilltreeClientState.isUnlocked(parentId)
|
||||||
|
|| SkilltreeClientState.isAbilityUnlocked(parentId)) continue;
|
||||||
|
SkillNode parentNode = SkillNodeRegistry.get(parentId);
|
||||||
|
if (parentNode != null) {
|
||||||
|
highlightedNode = parentId;
|
||||||
|
} else {
|
||||||
|
highlightedAbility = parentId;
|
||||||
|
}
|
||||||
|
Component parentName = parentNode != null
|
||||||
|
? parentNode.getTitle()
|
||||||
|
: AbilityNodeRegistry.get(parentId) != null
|
||||||
|
? AbilityNodeRegistry.get(parentId).getTitle()
|
||||||
|
: Component.literal(parentId.toString());
|
||||||
|
unlockFailureMessage = Component.literal("Unlock ")
|
||||||
|
.append(parentName.copy().withStyle(ChatFormatting.YELLOW))
|
||||||
|
.append(Component.literal(" first — it is required for "))
|
||||||
|
.append(ability.getTitle().copy().withStyle(ChatFormatting.WHITE));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearUnlockHighlights() {
|
||||||
|
highlightedNode = null;
|
||||||
|
highlightedAbility = null;
|
||||||
|
highlightSkillPoints = false;
|
||||||
|
unlockFailureMessage = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderUnlockFailure(GuiGraphics gfx) {
|
||||||
|
if (unlockFailureMessage == null) return;
|
||||||
|
int messageWidth = Math.min(width - 40, font.width(unlockFailureMessage) + 20);
|
||||||
|
int x = (width - messageWidth) / 2;
|
||||||
|
int y = height - 34;
|
||||||
|
gfx.fill(x - 2, y - 2, x + messageWidth + 2, y + 18, 0xCC000000);
|
||||||
|
gfx.fill(x, y, x + messageWidth, y + 16, 0xE0421717);
|
||||||
|
gfx.fill(x, y, x + 3, y + 16, 0xFFFF4545);
|
||||||
|
gfx.drawCenteredString(font, unlockFailureMessage, width / 2, y + 4, 0xFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
private void drawLine(GuiGraphics gfx, int x1, int y1, int x2, int y2, int color) {
|
private void drawLine(GuiGraphics gfx, int x1, int y1, int x2, int y2, int color) {
|
||||||
float dx = x2 - x1;
|
float dx = x2 - x1;
|
||||||
float dy = y2 - y1;
|
float dy = y2 - y1;
|
||||||
|
|||||||
Reference in New Issue
Block a user