From d52a2d2fe49dcec9076bcb14bd189604e04f7d1c Mon Sep 17 00:00:00 2001 From: Melledy <121644117+Melledy@users.noreply.github.com> Date: Tue, 17 Oct 2023 05:28:40 -0700 Subject: [PATCH] Implement `/avatar` command --- .../emu/lunarcore/command/CommandArgs.java | 10 ++- .../command/commands/AvatarCommand.java | 84 +++++++++++++++++++ .../emu/lunarcore/data/excel/AvatarExcel.java | 4 + .../data/excel/AvatarSkillTreeExcel.java | 7 +- .../lunarcore/game/battle/BattleService.java | 2 +- .../lunarcore/game/player/LineupManager.java | 2 +- .../emu/lunarcore/game/player/Player.java | 9 ++ .../recv/HandlerSceneCastSkillCsReq.java | 2 +- 8 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 src/main/java/emu/lunarcore/command/commands/AvatarCommand.java diff --git a/src/main/java/emu/lunarcore/command/CommandArgs.java b/src/main/java/emu/lunarcore/command/CommandArgs.java index 7d6a7d0..07f51bf 100644 --- a/src/main/java/emu/lunarcore/command/CommandArgs.java +++ b/src/main/java/emu/lunarcore/command/CommandArgs.java @@ -13,10 +13,11 @@ public class CommandArgs { private Player target; private int targetUid; - private int level; private int amount; - private int rank; - private int promotion; + private int level = -1; + private int rank = -1; + private int promotion = -1; + private int stage = -1; private static String EMPTY_STRING = ""; @@ -46,6 +47,9 @@ public class CommandArgs { } else if (arg.startsWith("p")) { this.promotion = Utils.parseSafeInt(arg.substring(1)); it.remove(); + } else if (arg.startsWith("s")) { + this.stage = Utils.parseSafeInt(arg.substring(1)); + it.remove(); } } } catch (Exception e) { diff --git a/src/main/java/emu/lunarcore/command/commands/AvatarCommand.java b/src/main/java/emu/lunarcore/command/commands/AvatarCommand.java new file mode 100644 index 0000000..e0317af --- /dev/null +++ b/src/main/java/emu/lunarcore/command/commands/AvatarCommand.java @@ -0,0 +1,84 @@ +package emu.lunarcore.command.commands; + +import emu.lunarcore.command.Command; +import emu.lunarcore.command.CommandArgs; +import emu.lunarcore.command.CommandHandler; +import emu.lunarcore.data.GameData; +import emu.lunarcore.game.avatar.GameAvatar; +import emu.lunarcore.game.player.Player; +import emu.lunarcore.server.packet.send.PacketPlayerSyncScNotify; + +@Command(label = "avatar", aliases = {"a"}, permission = "player.avatar", desc = "/avatar lv(level) p(ascension) r(eidolon) s(skill levels). Sets the current avatar's properties") +public class AvatarCommand implements CommandHandler { + + @Override + public void execute(Player sender, CommandArgs args) { + // Check target + if (args.getTarget() == null) { + this.sendMessage(sender, "Error: Targeted player not found or offline"); + return; + } + + // Get current leader avatar + GameAvatar avatar = args.getTarget().getCurrentLeaderAvatar(); + if (avatar == null) { + // No leader! + return; + } + + boolean hasChanged = false; + + // Try to set level + if (args.getLevel() > 0) { + avatar.setLevel(args.getLevel()); + hasChanged = true; + } + + // Try to set level + if (args.getLevel() > 0) { + avatar.setLevel(Math.min(args.getLevel(), 80)); + hasChanged = true; + } + + // Try to set promotion (ascension level) + if (args.getPromotion() >= 0) { + avatar.setPromotion(Math.min(args.getPromotion(), avatar.getExcel().getMaxPromotion())); + hasChanged = true; + } + + // Try to set rank (eidolons) + if (args.getRank() >= 0) { + avatar.setRank(Math.min(args.getRank(), avatar.getExcel().getMaxRank())); + hasChanged = true; + } + + // Try to set skill trees + if (args.getStage() > 0) { + for (int pointId : avatar.getExcel().getSkillTreeIds()) { + var skillTree = GameData.getAvatarSkillTreeExcel(pointId, 1); + if (skillTree == null) continue; + + int minLevel = skillTree.isDefaultUnlock() ? 1 : 0; + int pointLevel = Math.max(Math.min(args.getStage(), skillTree.getMaxLevel()), minLevel); + + avatar.getSkills().put(pointId, pointLevel); + } + hasChanged = true; + } + + // Done + if (hasChanged) { + // Save avatar + avatar.save(); + + // Send packet + args.getTarget().sendPacket(new PacketPlayerSyncScNotify(avatar)); + + // Send message + sender.sendMessage("Set avatar properties successfully"); + } else { + sender.sendMessage("No avatar properties to change"); + } + } + +} diff --git a/src/main/java/emu/lunarcore/data/excel/AvatarExcel.java b/src/main/java/emu/lunarcore/data/excel/AvatarExcel.java index 72a8c88..3043119 100644 --- a/src/main/java/emu/lunarcore/data/excel/AvatarExcel.java +++ b/src/main/java/emu/lunarcore/data/excel/AvatarExcel.java @@ -11,6 +11,8 @@ import emu.lunarcore.data.ResourceType; import emu.lunarcore.game.battle.skills.MazeSkill; import emu.lunarcore.game.enums.AvatarBaseType; import emu.lunarcore.game.enums.DamageType; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; @@ -35,6 +37,7 @@ public class AvatarExcel extends GameResource { @Getter(AccessLevel.NONE) private transient AvatarPromotionExcel[] promotionData; private transient List defaultSkillTrees; + private transient IntSet skillTreeIds; private transient String nameKey; private transient int maxSp; @@ -45,6 +48,7 @@ public class AvatarExcel extends GameResource { public AvatarExcel() { this.defaultSkillTrees = new ArrayList<>(); + this.skillTreeIds = new IntOpenHashSet(); } @Override diff --git a/src/main/java/emu/lunarcore/data/excel/AvatarSkillTreeExcel.java b/src/main/java/emu/lunarcore/data/excel/AvatarSkillTreeExcel.java index 7d8397a..27335e3 100644 --- a/src/main/java/emu/lunarcore/data/excel/AvatarSkillTreeExcel.java +++ b/src/main/java/emu/lunarcore/data/excel/AvatarSkillTreeExcel.java @@ -12,6 +12,7 @@ import emu.lunarcore.data.ResourceType.LoadPriority; import emu.lunarcore.data.common.ItemParam; import it.unimi.dsi.fastutil.ints.IntArrayList; import lombok.Getter; +import net.bytebuddy.asm.Advice.This; @Getter @ResourceType(name = {"AvatarSkillTreeConfig.json"}, loadPriority = LoadPriority.LOW) @@ -53,11 +54,15 @@ public class AvatarSkillTreeExcel extends GameResource { } // Load to excel - AvatarExcel excel = GameData.getAvatarExcelMap().get(AvatarID); + AvatarExcel excel = GameData.getAvatarExcelMap().get(this.AvatarID); if (excel == null) return; + // Add to default avatar skills if (this.isDefaultUnlock()) { excel.getDefaultSkillTrees().add(this); } + + // Add point id to avatar excel + excel.getSkillTreeIds().add(this.getPointID()); } } diff --git a/src/main/java/emu/lunarcore/game/battle/BattleService.java b/src/main/java/emu/lunarcore/game/battle/BattleService.java index 412e8fe..ee271c1 100644 --- a/src/main/java/emu/lunarcore/game/battle/BattleService.java +++ b/src/main/java/emu/lunarcore/game/battle/BattleService.java @@ -118,7 +118,7 @@ public class BattleService extends BaseGameService { // Add buffs to battle if (isPlayerCaster) { - GameAvatar avatar = player.getLineupManager().getCurrentLeaderAvatar(); + GameAvatar avatar = player.getCurrentLeaderAvatar(); if (avatar != null) { // Maze skill attack event if (castedSkill) { // Dont need to null check maze skill since we already did it in HandlerSceneCastSkillCsReq diff --git a/src/main/java/emu/lunarcore/game/player/LineupManager.java b/src/main/java/emu/lunarcore/game/player/LineupManager.java index 5a932c1..73be3d7 100644 --- a/src/main/java/emu/lunarcore/game/player/LineupManager.java +++ b/src/main/java/emu/lunarcore/game/player/LineupManager.java @@ -16,7 +16,7 @@ public class LineupManager { private transient Player player; private PlayerLineup[] lineups; - private int currentIndex; + private int currentIndex; // Team index private int currentLeader; private int mp; diff --git a/src/main/java/emu/lunarcore/game/player/Player.java b/src/main/java/emu/lunarcore/game/player/Player.java index 4ca22ea..14f7f0c 100644 --- a/src/main/java/emu/lunarcore/game/player/Player.java +++ b/src/main/java/emu/lunarcore/game/player/Player.java @@ -243,6 +243,15 @@ public class Player { public PlayerLineup getCurrentLineup() { return this.getLineupManager().getCurrentLineup(); } + + public GameAvatar getCurrentLeaderAvatar() { + try { + int avatarId = getCurrentLineup().getAvatars().get(this.getLineupManager().getCurrentLeader()); + return this.getAvatarById(avatarId); + } catch (Exception e) { + return null; + } + } private void initUid() { if (this.uid > 0) return; diff --git a/src/main/java/emu/lunarcore/server/packet/recv/HandlerSceneCastSkillCsReq.java b/src/main/java/emu/lunarcore/server/packet/recv/HandlerSceneCastSkillCsReq.java index d9b0075..abb1bfd 100644 --- a/src/main/java/emu/lunarcore/server/packet/recv/HandlerSceneCastSkillCsReq.java +++ b/src/main/java/emu/lunarcore/server/packet/recv/HandlerSceneCastSkillCsReq.java @@ -29,7 +29,7 @@ public class HandlerSceneCastSkillCsReq extends PacketHandler { session.getPlayer().getCurrentLineup().removeMp(1); session.send(new PacketSceneCastSkillMpUpdateScNotify(req.getAttackedGroupId(), session.getPlayer().getLineupManager().getMp())); // Cast skill effects - GameAvatar caster = session.getPlayer().getLineupManager().getCurrentLeaderAvatar(); + GameAvatar caster = session.getPlayer().getCurrentLeaderAvatar(); if (caster != null && caster.getExcel().getMazeSkill() != null) { MazeSkill skill = caster.getExcel().getMazeSkill(); skill.onCast(caster, req.getTargetMotion());