Improve UI and Update README
This commit is contained in:
@@ -0,0 +1,35 @@
|
|||||||
|
# Ascend: SbA (Stats by Actions) — short overview
|
||||||
|
|
||||||
|
**Ascend** turns vanilla Minecraft into a lightweight, persistent RPG: train attributes by doing things in-game, gain Ascend levels, spend points to boost combat, movement, magic and social skills, and watch those choices change how your character performs.
|
||||||
|
|
||||||
|
## What it does (quick)
|
||||||
|
|
||||||
|
* Adds an **Ascend level & XP** system (max level **20**, **15 points per level**).
|
||||||
|
* Players earn XP from actions: killing mobs, mining certain blocks, taking damage, crafting/smelting, using potions, trading with villagers, using weapons, and periodic checks for risky situations (low health, debuffs, darkness).
|
||||||
|
* Spend earned points on 10+ attributes (strength, agility, fortitude, intelligence, willpower, charisma, and weapon/magic scaling stats).
|
||||||
|
* Attribute points apply **live** via attribute modifiers and event hooks (damage, health, movement speed, enchant/potion interactions, trade discounts, etc.).
|
||||||
|
* Client UI: press **V** (configurable keybind) to open a compact stats screen and spend points. Server-authoritative with packet sync.
|
||||||
|
|
||||||
|
## Key mechanics & examples
|
||||||
|
|
||||||
|
* **Strength**: +attack damage, +knockback, and armor-bypass bonus calculated on hit.
|
||||||
|
* **Agility**: small movement speed bonus; XP for agile actions (sprinting, climbing, jumping).
|
||||||
|
* **Fortitude**: increases max health, knockback resistance, chance to resist/cleanse harmful effects.
|
||||||
|
* **Intelligence**: increases mana (and integrates with Iron’s Spellbooks if present), lengthens beneficial potion effects, reduces enchantment costs/effects.
|
||||||
|
* **Willpower**: reduces sanity drain and increases tempo/stamina gains (API helpers available).
|
||||||
|
* **Charisma**: grants trade discounts by adjusting merchant offers when opening trades.
|
||||||
|
* **Scaling stats**: light/medium/heavy weapon scaling and magic scaling multiply damage based on attack speed or magic damage type.
|
||||||
|
|
||||||
|
## Compatibility & tech notes
|
||||||
|
|
||||||
|
* Designed for **Forge 1.20.1** (example build uses Forge 47.4.0) and **Java 17** toolchain.
|
||||||
|
* Optional compat with **Iron’s Spellbooks** (adds mana/spell-power hooks). Also prepared to play nicely with Geckolib, Caelus, Curios, Player Animator (as declared in the build).
|
||||||
|
* Uses a capability (`PlayerStats`) for persistent storage and network packets to sync server → client. Attributes are capped (per-mod caps and MAX_ATTRIBUTE_POINTS = 100).
|
||||||
|
|
||||||
|
## Playstyle & design goal
|
||||||
|
|
||||||
|
Ascend is built to be unobtrusive and organic: your playstyle trains the corresponding attributes. Want a heavy-hitter who tanks? Smash armor and spend in Strength/Fortitude. Prefer spellcasting? Farm XP and invest in Intelligence and Magic Scaling. It’s about emergent progression — no grindy menus, just meaningful choices.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Short, modular, and ready to extend — Ascend gives you an RPG progression layer without changing world generation or requiring a new economy. Want a longer description, a Steam-like blurb, or a README-ready install/FAQ section? I can write that next.
|
||||||
-46
@@ -1,46 +0,0 @@
|
|||||||
|
|
||||||
Source installation information for modders
|
|
||||||
-------------------------------------------
|
|
||||||
This code follows the Minecraft Forge installation methodology. It will apply
|
|
||||||
some small patches to the vanilla MCP source code, giving you and it access
|
|
||||||
to some of the data and functions you need to build a successful mod.
|
|
||||||
|
|
||||||
Note also that the patches are built against "un-renamed" MCP source code (aka
|
|
||||||
SRG Names) - this means that you will not be able to read them directly against
|
|
||||||
normal code.
|
|
||||||
|
|
||||||
Setup Process:
|
|
||||||
==============================
|
|
||||||
|
|
||||||
Step 1: Open your command-line and browse to the folder where you extracted the zip file.
|
|
||||||
|
|
||||||
Step 2: You're left with a choice.
|
|
||||||
If you prefer to use Eclipse:
|
|
||||||
1. Run the following command: `./gradlew genEclipseRuns`
|
|
||||||
2. Open Eclipse, Import > Existing Gradle Project > Select Folder
|
|
||||||
or run `gradlew eclipse` to generate the project.
|
|
||||||
|
|
||||||
If you prefer to use IntelliJ:
|
|
||||||
1. Open IDEA, and import project.
|
|
||||||
2. Select your build.gradle file and have it import.
|
|
||||||
3. Run the following command: `./gradlew genIntellijRuns`
|
|
||||||
4. Refresh the Gradle Project in IDEA if required.
|
|
||||||
|
|
||||||
If at any point you are missing libraries in your IDE, or you've run into problems you can
|
|
||||||
run `gradlew --refresh-dependencies` to refresh the local cache. `gradlew clean` to reset everything
|
|
||||||
(this does not affect your code) and then start the process again.
|
|
||||||
|
|
||||||
Mapping Names:
|
|
||||||
=============================
|
|
||||||
By default, the MDK is configured to use the official mapping names from Mojang for methods and fields
|
|
||||||
in the Minecraft codebase. These names are covered by a specific license. All modders should be aware of this
|
|
||||||
license, if you do not agree with it you can change your mapping names to other crowdsourced names in your
|
|
||||||
build.gradle. For the latest license text, refer to the mapping file itself, or the reference copy here:
|
|
||||||
https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md
|
|
||||||
|
|
||||||
Additional Resources:
|
|
||||||
=========================
|
|
||||||
Community Documentation: https://docs.minecraftforge.net/en/1.20.1/gettingstarted/
|
|
||||||
LexManos' Install Video: https://youtu.be/8VEdtQLuLO0
|
|
||||||
Forge Forums: https://forums.minecraftforge.net/
|
|
||||||
Forge Discord: https://discord.minecraftforge.net/
|
|
||||||
@@ -31,6 +31,45 @@ public class StatsScreen extends Screen {
|
|||||||
|
|
||||||
private final Map<String, Button> plusButtons = new HashMap<>();
|
private final Map<String, Button> plusButtons = new HashMap<>();
|
||||||
|
|
||||||
|
// --- Tooltips for attributes ---
|
||||||
|
private static final Map<String, Component> ATTRIBUTE_TOOLTIPS = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
ATTRIBUTE_TOOLTIPS.put("strength", Component.literal(
|
||||||
|
"Strength: Increases melee damage, knockback and armor penetration."
|
||||||
|
));
|
||||||
|
ATTRIBUTE_TOOLTIPS.put("agility", Component.literal(
|
||||||
|
"Agility: Increases movement speed and mobility."
|
||||||
|
));
|
||||||
|
ATTRIBUTE_TOOLTIPS.put("fortitude", Component.literal(
|
||||||
|
"Fortitude: Increases max health and knockback resistance."
|
||||||
|
));
|
||||||
|
ATTRIBUTE_TOOLTIPS.put("intelligence", Component.literal(
|
||||||
|
"Intelligence: Boosts mana, spell power, mana regen & cooldown reduction (with Iron's Spellbooks)."
|
||||||
|
));
|
||||||
|
ATTRIBUTE_TOOLTIPS.put("willpower", Component.literal(
|
||||||
|
"Willpower: Reduces sanity drain and improves stamina/tempo in harsh conditions."
|
||||||
|
));
|
||||||
|
ATTRIBUTE_TOOLTIPS.put("charisma", Component.literal(
|
||||||
|
"Charisma: Increases max mana and improves trade deals."
|
||||||
|
));
|
||||||
|
ATTRIBUTE_TOOLTIPS.put("light_scaling", Component.literal(
|
||||||
|
"Light Scaling: Increases damage with light weapons that scale with this stat."
|
||||||
|
));
|
||||||
|
ATTRIBUTE_TOOLTIPS.put("medium_scaling", Component.literal(
|
||||||
|
"Medium Scaling: Increases damage with medium weapons that scale with this stat."
|
||||||
|
));
|
||||||
|
ATTRIBUTE_TOOLTIPS.put("heavy_scaling", Component.literal(
|
||||||
|
"Heavy Scaling: Increases damage with heavy weapons that scale with this stat."
|
||||||
|
));
|
||||||
|
ATTRIBUTE_TOOLTIPS.put("magic_scaling", Component.literal(
|
||||||
|
"Magic Scaling: Increases spell power, mana regen & cooldown reduction for scaling spells."
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// which attribute label the mouse is currently over (for tooltip)
|
||||||
|
private String hoveredAttributeKey = null;
|
||||||
|
|
||||||
public StatsScreen() {
|
public StatsScreen() {
|
||||||
super(Component.literal("Ascend Stats"));
|
super(Component.literal("Ascend Stats"));
|
||||||
}
|
}
|
||||||
@@ -40,8 +79,10 @@ public class StatsScreen extends Screen {
|
|||||||
super.init();
|
super.init();
|
||||||
this.leftPos = (this.width - WIDTH) / 2;
|
this.leftPos = (this.width - WIDTH) / 2;
|
||||||
this.topPos = (this.height - HEIGHT) / 2;
|
this.topPos = (this.height - HEIGHT) / 2;
|
||||||
|
|
||||||
this.plusButtons.clear();
|
this.plusButtons.clear();
|
||||||
this.clearWidgets();
|
this.clearWidgets();
|
||||||
|
|
||||||
int y = topPos + 55;
|
int y = topPos + 55;
|
||||||
for (String attr : ATTRIBUTES) {
|
for (String attr : ATTRIBUTES) {
|
||||||
final String key = attr;
|
final String key = attr;
|
||||||
@@ -54,6 +95,7 @@ public class StatsScreen extends Screen {
|
|||||||
this.plusButtons.put(key, plus);
|
this.plusButtons.put(key, plus);
|
||||||
y += 16;
|
y += 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
Button done = Button.builder(Component.translatable("gui.done"), (btn) -> onClose())
|
Button done = Button.builder(Component.translatable("gui.done"), (btn) -> onClose())
|
||||||
.bounds(leftPos + WIDTH / 2 - 40, topPos + HEIGHT - 24, 80, 20)
|
.bounds(leftPos + WIDTH / 2 - 40, topPos + HEIGHT - 24, 80, 20)
|
||||||
.build();
|
.build();
|
||||||
@@ -67,6 +109,7 @@ public class StatsScreen extends Screen {
|
|||||||
gui.fill(leftPos - 4, topPos - 4, leftPos + WIDTH + 4, topPos + HEIGHT + 4, 0xAA000000);
|
gui.fill(leftPos - 4, topPos - 4, leftPos + WIDTH + 4, topPos + HEIGHT + 4, 0xAA000000);
|
||||||
RenderSystem.disableBlend();
|
RenderSystem.disableBlend();
|
||||||
gui.drawCenteredString(this.font, this.title, this.width / 2, topPos + 8, 0xFFFFFF);
|
gui.drawCenteredString(this.font, this.title, this.width / 2, topPos + 8, 0xFFFFFF);
|
||||||
|
hoveredAttributeKey = null;
|
||||||
if (mc.player != null) {
|
if (mc.player != null) {
|
||||||
mc.player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
mc.player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
|
||||||
int level = stats.getAscendLevel();
|
int level = stats.getAscendLevel();
|
||||||
@@ -88,13 +131,11 @@ public class StatsScreen extends Screen {
|
|||||||
int y = topPos + 55;
|
int y = topPos + 55;
|
||||||
for (String key : ATTRIBUTES) {
|
for (String key : ATTRIBUTES) {
|
||||||
int attrLevel = stats.getAttributeLevel(key);
|
int attrLevel = stats.getAttributeLevel(key);
|
||||||
int sourceXP = stats.getAscendXP();
|
|
||||||
int cost = stats.getCostToUpgrade(key);
|
int cost = stats.getCostToUpgrade(key);
|
||||||
String niceName = formatAttributeName(key);
|
String niceName = formatAttributeName(key);
|
||||||
gui.drawString(font,
|
String label = niceName + ": " + attrLevel;
|
||||||
niceName + ": " + attrLevel,
|
int labelX = leftPos + 10;
|
||||||
leftPos + 10, y,
|
gui.drawString(font, label, labelX, y, 0xFFFFFF);
|
||||||
0xFFFFFF);
|
|
||||||
Button plus = plusButtons.get(key);
|
Button plus = plusButtons.get(key);
|
||||||
if (plus != null) {
|
if (plus != null) {
|
||||||
plus.setX(leftPos + WIDTH - 40);
|
plus.setX(leftPos + WIDTH - 40);
|
||||||
@@ -102,13 +143,23 @@ public class StatsScreen extends Screen {
|
|||||||
plus.active = (unspent >= cost);
|
plus.active = (unspent >= cost);
|
||||||
plus.setMessage(Component.literal("+" + cost));
|
plus.setMessage(Component.literal("+" + cost));
|
||||||
}
|
}
|
||||||
|
int labelWidth = font.width(label);
|
||||||
|
int labelHeight = font.lineHeight;
|
||||||
|
if (mouseX >= labelX && mouseX <= labelX + labelWidth
|
||||||
|
&& mouseY >= y && mouseY <= y + labelHeight) {
|
||||||
|
hoveredAttributeKey = key;
|
||||||
|
}
|
||||||
y += 16;
|
y += 16;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
super.render(gui, mouseX, mouseY, partialTicks);
|
super.render(gui, mouseX, mouseY, partialTicks);
|
||||||
|
if (hoveredAttributeKey != null) {
|
||||||
|
Component tooltip = ATTRIBUTE_TOOLTIPS.get(hoveredAttributeKey);
|
||||||
|
if (tooltip != null) {
|
||||||
|
gui.renderTooltip(this.font, tooltip, mouseX, mouseY);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String formatAttributeName(String key) {
|
private String formatAttributeName(String key) {
|
||||||
|
|||||||
Reference in New Issue
Block a user