Skip to content

等级与职业 ​

等级给玩家"成长感",职业给玩家"差异感"。这是网游留客的核心系统之一。

等级系统 ​

数据结构 ​

每个玩家存:等级、经验、累计经验。

java
public class PlayerData {
    private int level = 1;
    private double exp = 0;
    // getter/setter
}

经验进度条 = 当前经验 / 升级所需经验。

升级公式 ​

升级所需经验随等级增长,常见公式:

java
public int expToNext(int level) {
    return 100 + level * 50; // 1级升2级要150,2升3要200...
}

加经验 + 自动升级 ​

java
public void addExp(UUID id, double amount) {
    PlayerData data = getData(id);
    data.setExp(data.getExp() + amount);

    // 检查升级
    while (data.getExp() >= expToNext(data.getLevel())) {
        data.setExp(data.getExp() - expToNext(data.getLevel()));
        data.setLevel(data.getLevel() + 1);
        onLevelUp(id, data.getLevel());
    }
}

private void onLevelUp(UUID id, int newLevel) {
    Player p = Bukkit.getPlayer(id);
    if (p != null) {
        p.playSound(p.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1, 1);
        p.sendTitle(ChatColor.GOLD + "升级!", "Lv." + newLevel, 10, 40, 10);
        // 升级奖励:给金币、解锁技能
    }
}

经验来源 ​

  • 打怪(EntityDeathEvent,按怪物类型给经验)
  • 采集(BlockBreakEvent,按方块给)
  • 任务、签到、成就

显示经验条 ​

用玩家的经验条(XP bar)直观显示等级进度:

java
public void refreshXpBar(Player p) {
    PlayerData data = getData(p.getUniqueId());
    int need = expToNext(data.getLevel());
    float progress = (float) (data.getExp() / need);
    p.setLevel(data.getLevel());           // 等级显示在经验条数字
    p.setExp(Math.min(progress, 1f));       // 进度条填充
}

原版经验会被覆盖

用 XP 条显示自定义等级,会覆盖原版经验(附魔、钓鱼掉的经验)。若服务器不用原版附魔系统,无所谓;要兼顾得另想显示方式(BossBar、ActionBar)。

职业系统 ​

数据结构 ​

玩家选一个职业,职业决定可用技能、属性加成:

java
public enum JobType {
    WARRIOR, MAGE, ARCHER;
}

public class PlayerData {
    private JobType job; // null 表示未选职业
    // ...
}

选职流程 ​

新手进服引导选职(用箱子 GUI 做选择界面):

java
@EventHandler
public void onChoose(InventoryClickEvent e) {
    if (!e.getView().getTitle().equals("选择职业")) return;
    e.setCancelled(true);
    Player p = (Player) e.getWhoClicked();
    int slot = e.getRawSlot();
    JobType chosen = slot == 0 ? JobType.WARRIOR
                   : slot == 4 ? JobType.MAGE
                   : slot == 8 ? JobType.ARCHER : null;
    if (chosen == null) return;
    getData(p.getUniqueId()).setJob(chosen);
    p.sendMessage("你选择了 " + chosen.name());
    p.closeInventory();
    applyJobBonus(p, chosen);
}

职业差异 ​

让职业有实际区别,而不只是名字:

  • 属性:战士血厚、法师脆但伤害高
  • 技能:各职业独有技能(命令或物品触发)
  • 装备:限制装备(法师不能穿重甲)

属性加成示例:

java
public void applyJobBonus(Player p, JobType job) {
    switch (job) {
        case WARRIOR:
            p.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(30); // 30 血
            break;
        case MAGE:
            p.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(20);
            break;
        // ...
    }
}

转职 / 多职业 ​

  • 转职:达到等级后可换职业(重置技能,保留等级)
  • 多职业:玩家可同时拥有多职业,切换激活

别一开始就做多职业

单职业先做透——技能树、平衡性都够你调的。多职业是后期内容扩展。

技能树(进阶) ​

技能按树状解锁,前置技能点满才能学下一层。数据结构:

java
public class SkillTree {
    private Map<String, Integer> learned = new HashMap<>(); // 技能ID -> 等级
    private int skillPoints = 0; // 可用技能点(升级获得)
}

升级给技能点,玩家花点学技能。

常见坑 ​

  • 平衡性:职业强弱难调,需要长期数据反馈。先做明显差异,再微调
  • 重置数据:玩家要求洗点、换职——要有安全的数据重置流程,别直接改内存不留痕
  • 离线玩家:升级奖励给离线玩家要记到数据里,等上线再发(别在离线时调 Player API)

下一篇公会与组队。