Fix most attack/buff avatar techniques not working

This commit is contained in:
Melledy
2023-10-02 23:27:13 -07:00
parent 653047784d
commit 1e165ddde7
11 changed files with 113 additions and 60 deletions

View File

@@ -233,6 +233,6 @@ public class ResourceLoader {
} }
// Done // Done
LunarRail.getLogger().info("Loaded " + count + " maze abilities for avatars"); LunarRail.getLogger().info("Loaded " + count + " maze abilities for avatars.");
} }
} }

View File

@@ -20,37 +20,44 @@ public class SkillAbilityInfo {
// Look for MazeSkill // Look for MazeSkill
for (AbilityInfo ability : AbilityList) { for (AbilityInfo ability : AbilityList) {
//
List<MazeSkillAction> actionList = null;
// Skip if not a maze skill // Skip if not a maze skill
if (!ability.getName().contains("MazeSkill")) { if (ability.getName().contains("MazeSkill")) {
skill = new MazeSkill(avatarExcel);
avatarExcel.setMazeSkill(skill);
actionList = skill.getCastActions();
} else if (ability.getName().contains("NormalAtk")) {
skill = new MazeSkill(avatarExcel);
avatarExcel.setMazeAttack(skill);
actionList = skill.getAttackActions();
} else {
continue; continue;
} }
// Create maze skill
skill = new MazeSkill();
// Parse tasks // Parse tasks
for (TaskInfo task : ability.getOnStart()) { for (TaskInfo task : ability.getOnStart()) {
parseTask(skill, skill.getCastActions(), task); parseTask(skill, actionList, task);
} }
} }
// Set skill for avatar return true;
if (skill != null) {
avatarExcel.setMazeSkill(skill);
return true;
}
return false;
} }
// "Simple" way to parse maze attacks/skills
private void parseTask(MazeSkill skill, List<MazeSkillAction> actionList, TaskInfo task) { private void parseTask(MazeSkill skill, List<MazeSkillAction> actionList, TaskInfo task) {
if (task.getType().contains("AddMazeBuff")) { if (task.getType().contains("AddMazeBuff")) {
actionList.add(new MazeSkillAddBuff(task.getID(), 15)); actionList.add(new MazeSkillAddBuff(task.getID(), 15));
} else if (task.getType().contains("RemoveMazeBuff")) {
actionList.removeIf(action -> action instanceof MazeSkillAddBuff actionAdd && actionAdd.getBuffId() == task.getID());
} else if (task.getType().contains("CreateSummonUnit")) { } else if (task.getType().contains("CreateSummonUnit")) {
} else if (task.getSuccessTaskList() != null) { } else if (task.getSuccessTaskList() != null) {
for (TaskInfo t : task.getSuccessTaskList()) { for (TaskInfo t : task.getSuccessTaskList()) {
parseTask(skill, skill.getCastActions(), t); parseTask(skill, actionList, t);
} }
} else if (task.getOnAttack() != null) { } else if (task.getOnAttack() != null) {
if (task.getType().contains("AdventureTriggerAttack")) { if (task.getType().contains("AdventureTriggerAttack")) {

View File

@@ -13,6 +13,7 @@ import emu.lunarcore.game.enums.AvatarBaseType;
import emu.lunarcore.game.enums.DamageType; import emu.lunarcore.game.enums.DamageType;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
@Getter @Getter
@ResourceType(name = {"AvatarConfig.json"}) @ResourceType(name = {"AvatarConfig.json"})
@@ -35,9 +36,11 @@ public class AvatarExcel extends GameResource {
private transient AvatarPromotionExcel[] promotionData; private transient AvatarPromotionExcel[] promotionData;
private transient List<AvatarSkillTreeExcel> defaultSkillTrees; private transient List<AvatarSkillTreeExcel> defaultSkillTrees;
private transient String nameKey; private transient String nameKey;
private transient MazeSkill mazeSkill;
private transient int maxSp; private transient int maxSp;
@Setter private transient MazeSkill mazeAttack;
@Setter private transient MazeSkill mazeSkill;
private static Pattern namePattern = Pattern.compile("(?<=Avatar_)(.*?)(?=_Config)"); private static Pattern namePattern = Pattern.compile("(?<=Avatar_)(.*?)(?=_Config)");
public AvatarExcel() { public AvatarExcel() {
@@ -49,10 +52,6 @@ public class AvatarExcel extends GameResource {
return AvatarID; return AvatarID;
} }
public void setMazeSkill(MazeSkill skill) {
this.mazeSkill = skill;
}
public AvatarPromotionExcel getPromotionData(int i) { public AvatarPromotionExcel getPromotionData(int i) {
return this.promotionData[i]; return this.promotionData[i];
} }

View File

@@ -58,15 +58,15 @@ public class Battle {
} }
public MazeBuff addBuff(int buffId) { public MazeBuff addBuff(int buffId, int ownerIndex) {
return addBuff(buffId, 0, 0xffffffff); return addBuff(buffId, ownerIndex, 0xffffffff);
} }
public MazeBuff addBuff(int buffId, int ownerId, int waveFlag) { public MazeBuff addBuff(int buffId, int ownerIndex, int waveFlag) {
MazeBuffExcel excel = GameData.getMazeBuffExcel(buffId, 1); MazeBuffExcel excel = GameData.getMazeBuffExcel(buffId, 1);
if (excel == null) return null; if (excel == null) return null;
MazeBuff buff = new MazeBuff(excel, ownerId, waveFlag); MazeBuff buff = new MazeBuff(excel, ownerIndex, waveFlag);
this.buffs.add(buff); this.buffs.add(buff);
return buff; return buff;
@@ -83,11 +83,16 @@ public class Battle {
.setLogicRandomSeed(Utils.randomRange(1, Short.MAX_VALUE)) .setLogicRandomSeed(Utils.randomRange(1, Short.MAX_VALUE))
.setWorldLevel(player.getWorldLevel()); .setWorldLevel(player.getWorldLevel());
// Init variables
int waveId = 0;
// Add monster waves from stages // Add monster waves from stages
for (StageExcel stage : stages) { for (StageExcel stage : stages) {
// Build monster waves // Build monster waves
for (IntList sceneMonsterWave : stage.getMonsterWaves()) { for (IntList sceneMonsterWave : stage.getMonsterWaves()) {
var wave = SceneMonsterWave.newInstance().setStageId(stage.getId()); var wave = SceneMonsterWave.newInstance()
.setWaveId(++waveId)
.setStageId(stage.getId());
for (int monsterId : sceneMonsterWave) { for (int monsterId : sceneMonsterWave) {
var monster = SceneMonster.newInstance().setMonsterId(monsterId); var monster = SceneMonster.newInstance().setMonsterId(monsterId);
@@ -115,8 +120,13 @@ public class Battle {
if (avatar.getBuffs().size() > 0) { if (avatar.getBuffs().size() > 0) {
for (var buffEntry : avatar.getBuffs().int2LongEntrySet()) { for (var buffEntry : avatar.getBuffs().int2LongEntrySet()) {
// Check expiry for buff // Check expiry for buff
if (buffEntry.getLongValue() >= this.timestamp) { if (buffEntry.getLongValue() < this.timestamp) {
this.addBuff(buffEntry.getIntKey()); continue;
}
MazeBuff buff = this.addBuff(buffEntry.getIntKey(), i);
if (buff != null) {
buff.addTargetIndex(i);
} }
} }
} }

View File

@@ -7,7 +7,6 @@ import emu.lunarcore.data.GameData;
import emu.lunarcore.data.excel.CocoonExcel; import emu.lunarcore.data.excel.CocoonExcel;
import emu.lunarcore.data.excel.StageExcel; import emu.lunarcore.data.excel.StageExcel;
import emu.lunarcore.game.avatar.GameAvatar; import emu.lunarcore.game.avatar.GameAvatar;
import emu.lunarcore.game.battle.skills.MazeSkill;
import emu.lunarcore.game.enums.StageType; import emu.lunarcore.game.enums.StageType;
import emu.lunarcore.game.player.Player; import emu.lunarcore.game.player.Player;
import emu.lunarcore.game.scene.entity.EntityMonster; import emu.lunarcore.game.scene.entity.EntityMonster;
@@ -32,10 +31,10 @@ public class BattleService extends BaseGameService {
super(server); super(server);
} }
public void startBattle(Player player, int attackerId, MazeSkill castedSkill, RepeatedInt attackedList) { public void startBattle(Player player, int attackerId, int attackedGroupId, boolean castedSkill, RepeatedInt attackedList) {
// Sanity check to make sure player isnt in a battle // Sanity check to make sure player isnt in a battle
if (player.isInBattle()) { if (player.isInBattle()) {
player.sendPacket(new PacketSceneCastSkillScRsp(1)); player.sendPacket(new PacketSceneCastSkillScRsp());
return; return;
} }
@@ -68,7 +67,7 @@ public class BattleService extends BaseGameService {
// Give the client an error if no attacked entities detected // Give the client an error if no attacked entities detected
if (entities.size() == 0) { if (entities.size() == 0) {
player.sendPacket(new PacketSceneCastSkillScRsp(1)); player.sendPacket(new PacketSceneCastSkillScRsp());
return; return;
} }
@@ -100,7 +99,7 @@ public class BattleService extends BaseGameService {
if (stages.size() == 0) { if (stages.size() == 0) {
// An error has occurred while trying to get stage data // An error has occurred while trying to get stage data
player.sendPacket(new PacketSceneCastSkillScRsp(1)); player.sendPacket(new PacketSceneCastSkillScRsp());
return; return;
} }
@@ -112,26 +111,29 @@ public class BattleService extends BaseGameService {
if (isPlayerCaster) { if (isPlayerCaster) {
GameAvatar avatar = player.getLineupManager().getCurrentLeaderAvatar(); GameAvatar avatar = player.getLineupManager().getCurrentLeaderAvatar();
if (avatar != null) { if (avatar != null) {
// Add elemental weakness buff to enemies // Maze skill attack event
MazeBuff buff = battle.addBuff(avatar.getExcel().getDamageType().getEnterBattleBuff()); if (castedSkill) { // Dont need to null check maze skill since we already did it in HandlerSceneCastSkillCsReq
if (buff != null) { avatar.getExcel().getMazeSkill().onAttack(avatar, battle);
buff.addDynamicValue("SkillIndex", 1); } else if (avatar.getExcel().getMazeAttack() != null) {
avatar.getExcel().getMazeAttack().onAttack(avatar, battle);
} }
// Maze skill handlers // Add elemental weakness buff to enemies
if (castedSkill != null) { MazeBuff buff = battle.addBuff(avatar.getExcel().getDamageType().getEnterBattleBuff(), player.getLineupManager().getCurrentLeader());
castedSkill.onAttack(avatar, battle); if (buff != null) {
buff.addTargetIndex(player.getLineupManager().getCurrentLeader());
buff.addDynamicValue("SkillIndex", castedSkill ? 2 : 1);
} }
} }
} }
// Set battle and send rsp packet // Set battle and send rsp packet
player.setBattle(battle); player.setBattle(battle);
player.sendPacket(new PacketSceneCastSkillScRsp(battle)); player.sendPacket(new PacketSceneCastSkillScRsp(battle, attackedGroupId));
return; return;
} }
// Send packet // Send packet
player.sendPacket(new PacketSceneCastSkillScRsp(0)); player.sendPacket(new PacketSceneCastSkillScRsp(attackedGroupId));
} }
public void startCocoon(Player player, int cocoonId, int worldLevel, int wave) { public void startCocoon(Player player, int cocoonId, int worldLevel, int wave) {

View File

@@ -3,6 +3,8 @@ package emu.lunarcore.game.battle;
import emu.lunarcore.data.excel.MazeBuffExcel; import emu.lunarcore.data.excel.MazeBuffExcel;
import emu.lunarcore.proto.BattleBuffOuterClass.BattleBuff; import emu.lunarcore.proto.BattleBuffOuterClass.BattleBuff;
import emu.lunarcore.proto.BattleBuffOuterClass.BattleBuff.DynamicValuesEntry; import emu.lunarcore.proto.BattleBuffOuterClass.BattleBuff.DynamicValuesEntry;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.objects.Object2DoubleMap; import it.unimi.dsi.fastutil.objects.Object2DoubleMap;
import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap;
import lombok.AccessLevel; import lombok.AccessLevel;
@@ -11,18 +13,27 @@ import lombok.Getter;
@Getter @Getter
public class MazeBuff { public class MazeBuff {
private MazeBuffExcel excel; private MazeBuffExcel excel;
private int ownerEntityId; private int ownerIndex;
private int waveFlag; private int waveFlag;
private IntList targetIndex;
@Getter(AccessLevel.NONE) @Getter(AccessLevel.NONE)
private Object2DoubleMap<String> dynamicValues; private Object2DoubleMap<String> dynamicValues;
public MazeBuff(MazeBuffExcel excel, int ownerEntityId, int waveFlag) { public MazeBuff(MazeBuffExcel excel, int ownerIndex, int waveFlag) {
this.excel = excel; this.excel = excel;
this.ownerEntityId = ownerEntityId; this.ownerIndex = ownerIndex;
this.waveFlag = waveFlag; this.waveFlag = waveFlag;
} }
public void addTargetIndex(int index) {
if (this.targetIndex == null) {
this.targetIndex = new IntArrayList();
}
this.targetIndex.add(index);
}
public void addDynamicValue(String key, double value) { public void addDynamicValue(String key, double value) {
if (this.dynamicValues == null) { if (this.dynamicValues == null) {
this.dynamicValues = new Object2DoubleOpenHashMap<>(); this.dynamicValues = new Object2DoubleOpenHashMap<>();
@@ -35,9 +46,15 @@ public class MazeBuff {
var proto = BattleBuff.newInstance() var proto = BattleBuff.newInstance()
.setId(excel.getBuffId()) .setId(excel.getBuffId())
.setLevel(excel.getLv()) .setLevel(excel.getLv())
.setOwnerId(this.getOwnerEntityId()) .setOwnerId(this.getOwnerIndex())
.setWaveFlag(this.getWaveFlag()); .setWaveFlag(this.getWaveFlag());
if (this.targetIndex != null) {
for (int index : this.targetIndex) {
proto.addTargetIndexList(index);
}
}
if (this.dynamicValues != null) { if (this.dynamicValues != null) {
for (var entry : this.dynamicValues.object2DoubleEntrySet()) { for (var entry : this.dynamicValues.object2DoubleEntrySet()) {
var dynamicValue = DynamicValuesEntry.newInstance() var dynamicValue = DynamicValuesEntry.newInstance()

View File

@@ -3,6 +3,7 @@ package emu.lunarcore.game.battle.skills;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import emu.lunarcore.data.excel.AvatarExcel;
import emu.lunarcore.game.avatar.GameAvatar; import emu.lunarcore.game.avatar.GameAvatar;
import emu.lunarcore.game.battle.Battle; import emu.lunarcore.game.battle.Battle;
import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
@@ -10,10 +11,12 @@ import lombok.Getter;
@Getter @Getter
public class MazeSkill { public class MazeSkill {
private int id;
private List<MazeSkillAction> castActions; private List<MazeSkillAction> castActions;
private List<MazeSkillAction> attackActions; private List<MazeSkillAction> attackActions;
public MazeSkill() { public MazeSkill(AvatarExcel excel) {
this.id = excel.getAvatarID();
this.castActions = new ArrayList<>(); this.castActions = new ArrayList<>();
this.attackActions = new ArrayList<>(); this.attackActions = new ArrayList<>();
} }

View File

@@ -3,10 +3,9 @@ package emu.lunarcore.game.battle.skills;
import emu.lunarcore.game.avatar.GameAvatar; import emu.lunarcore.game.avatar.GameAvatar;
import emu.lunarcore.game.battle.Battle; import emu.lunarcore.game.battle.Battle;
import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
@Getter(AccessLevel.PRIVATE) @Getter
public class MazeSkillAddBuff extends MazeSkillAction { public class MazeSkillAddBuff extends MazeSkillAction {
private int buffId; private int buffId;
private int duration; private int duration;
@@ -23,7 +22,8 @@ public class MazeSkillAddBuff extends MazeSkillAction {
@Override @Override
public void onAttack(GameAvatar caster, Battle battle) { public void onAttack(GameAvatar caster, Battle battle) {
battle.addBuff(buffId); // TODO add buff for each monster wave
battle.addBuff(buffId, caster.getOwner().getLineupManager().getCurrentLeader(), 1);
} }
} }

View File

@@ -36,7 +36,7 @@ public class PlayerLineup {
// Set team name if not an extra lineup // Set team name if not an extra lineup
if (!this.isExtraLineup()) { if (!this.isExtraLineup()) {
this.name = "Squad " + (index + 1); this.name = "Team " + (index + 1);
} else { } else {
this.name = ""; this.name = "";
} }

View File

@@ -17,7 +17,7 @@ public class HandlerSceneCastSkillCsReq extends PacketHandler {
public void handle(GameSession session, byte[] header, byte[] data) throws Exception { public void handle(GameSession session, byte[] header, byte[] data) throws Exception {
var req = SceneCastSkillCsReq.parseFrom(data); var req = SceneCastSkillCsReq.parseFrom(data);
MazeSkill castedSkill = null; boolean castedSkill = false;
// Check if player casted a maze skill // Check if player casted a maze skill
if (req.getSkillIndex() > 0 && session.getPlayer().getScene().getAvatarEntityIds().contains(req.getAttackerId())) { if (req.getSkillIndex() > 0 && session.getPlayer().getScene().getAvatarEntityIds().contains(req.getAttackerId())) {
@@ -27,15 +27,17 @@ public class HandlerSceneCastSkillCsReq extends PacketHandler {
// Cast skill effects // Cast skill effects
GameAvatar caster = session.getPlayer().getLineupManager().getCurrentLeaderAvatar(); GameAvatar caster = session.getPlayer().getLineupManager().getCurrentLeaderAvatar();
if (caster != null && caster.getExcel().getMazeSkill() != null) { if (caster != null && caster.getExcel().getMazeSkill() != null) {
castedSkill = caster.getExcel().getMazeSkill(); MazeSkill skill = caster.getExcel().getMazeSkill();
castedSkill.onCast(caster, req.getTargetMotion()); skill.onCast(caster, req.getTargetMotion());
// Set flag
castedSkill = true;
} }
} }
if (req.hasAttackedEntityIdList()) { if (req.hasAttackedEntityIdList()) {
session.getServer().getBattleService().startBattle(session.getPlayer(), req.getAttackerId(), castedSkill, req.getAttackedEntityIdList()); session.getServer().getBattleService().startBattle(session.getPlayer(), req.getAttackerId(), req.getAttackedGroupId(), castedSkill, req.getAttackedEntityIdList());
} else { } else {
session.send(new PacketSceneCastSkillScRsp()); session.send(new PacketSceneCastSkillScRsp(req.getAttackedGroupId()));
} }
} }

View File

@@ -7,24 +7,37 @@ import emu.lunarcore.server.packet.CmdId;
public class PacketSceneCastSkillScRsp extends BasePacket { public class PacketSceneCastSkillScRsp extends BasePacket {
/**
* Returns an error to the client
*/
public PacketSceneCastSkillScRsp() { public PacketSceneCastSkillScRsp() {
this(0);
}
public PacketSceneCastSkillScRsp(int retcode) {
super(CmdId.SceneCastSkillScRsp); super(CmdId.SceneCastSkillScRsp);
var data = SceneCastSkillScRsp.newInstance() var data = SceneCastSkillScRsp.newInstance()
.setRetcode(retcode); .setRetcode(1);
this.setData(data); this.setData(data);
} }
public PacketSceneCastSkillScRsp(Battle battle) { /**
* No battle was started, but we still want to send the attacked group id to the client
* @param attackedGroupId
*/
public PacketSceneCastSkillScRsp(int attackedGroupId) {
super(CmdId.SceneCastSkillScRsp);
var data = SceneCastSkillScRsp.newInstance()
.setAttackedGroupId(attackedGroupId);
this.setData(data);
}
public PacketSceneCastSkillScRsp(Battle battle, int attackedGroupId) {
super(CmdId.SceneCastSkillScRsp); super(CmdId.SceneCastSkillScRsp);
// Build data // Build data
var data = SceneCastSkillScRsp.newInstance() var data = SceneCastSkillScRsp.newInstance()
.setAttackedGroupId(attackedGroupId)
.setBattleInfo(battle.toProto()); .setBattleInfo(battle.toProto());
this.setData(data); this.setData(data);