From 246b5e0340698ba41abe9654979fe7ccea9f605e Mon Sep 17 00:00:00 2001 From: Melledy <121644117+Melledy@users.noreply.github.com> Date: Fri, 15 Dec 2023 08:11:16 -0800 Subject: [PATCH] Handle debuff techniques better Using a single target debuff technique on a group of monsters should only debuff the monster wave(s) from the attacked monster --- .../lunarcore/data/config/SummonUnitInfo.java | 2 +- .../emu/lunarcore/game/battle/Battle.java | 4 -- .../lunarcore/game/battle/BattleService.java | 66 ++++++++++--------- .../game/battle/skills/MazeSkill.java | 21 +++--- .../game/battle/skills/MazeSkillAction.java | 13 ++-- .../game/battle/skills/MazeSkillAddBuff.java | 17 ++--- .../game/battle/skills/MazeSkillHitProp.java | 14 +--- .../game/battle/skills/MazeSkillModifyHP.java | 14 ---- .../game/battle/skills/MazeSkillModifySP.java | 8 +-- .../battle/skills/MazeSkillSummonUnit.java | 14 ---- .../java/emu/lunarcore/game/scene/Scene.java | 2 +- .../emu/lunarcore/game/scene/SceneBuff.java | 21 ++++-- .../game/scene/entity/EntityMonster.java | 44 +++++++++---- .../recv/HandlerSceneCastSkillCsReq.java | 23 ++++--- 14 files changed, 129 insertions(+), 134 deletions(-) diff --git a/src/main/java/emu/lunarcore/data/config/SummonUnitInfo.java b/src/main/java/emu/lunarcore/data/config/SummonUnitInfo.java index 9a8f064..ddde255 100644 --- a/src/main/java/emu/lunarcore/data/config/SummonUnitInfo.java +++ b/src/main/java/emu/lunarcore/data/config/SummonUnitInfo.java @@ -62,7 +62,7 @@ public class SummonUnitInfo { for (var task : this.OnTriggerEnter) { if (task.getType().contains("AddMazeBuff")) { // TODO get duration from params if buff duration is dynamic - var actionAddBuff = new MazeSkillAddBuff(task.getID(), 15); + var actionAddBuff = new MazeSkillAddBuff(task.getID(), 5); actionAddBuff.setSendBuffPacket(true); actions.add(actionAddBuff); diff --git a/src/main/java/emu/lunarcore/game/battle/Battle.java b/src/main/java/emu/lunarcore/game/battle/Battle.java index 9edcbc5..f13d2a6 100644 --- a/src/main/java/emu/lunarcore/game/battle/Battle.java +++ b/src/main/java/emu/lunarcore/game/battle/Battle.java @@ -130,10 +130,6 @@ public class Battle { return this.turnSnapshotList; } - public int getMonsterWaveCount() { - return this.getWaves().size(); - } - public void setCustomLevel(int level) { for (var wave : this.getWaves()) { wave.setCustomLevel(level); diff --git a/src/main/java/emu/lunarcore/game/battle/BattleService.java b/src/main/java/emu/lunarcore/game/battle/BattleService.java index 073ad1d..ec338a7 100644 --- a/src/main/java/emu/lunarcore/game/battle/BattleService.java +++ b/src/main/java/emu/lunarcore/game/battle/BattleService.java @@ -2,7 +2,6 @@ package emu.lunarcore.game.battle; import java.util.ArrayList; import java.util.List; -import java.util.Set; import emu.lunarcore.GameConstants; import emu.lunarcore.data.GameData; @@ -24,6 +23,7 @@ import emu.lunarcore.server.packet.send.PacketReEnterLastElementStageScRsp; import emu.lunarcore.server.packet.send.PacketSceneCastSkillScRsp; import emu.lunarcore.server.packet.send.PacketStartCocoonStageScRsp; import emu.lunarcore.server.packet.send.PacketSyncLineupNotify; +import it.unimi.dsi.fastutil.ints.IntSet; public class BattleService extends BaseGameService { @@ -31,15 +31,18 @@ public class BattleService extends BaseGameService { super(server); } - public void startBattle(Player player, int casterId, int attackedGroupId, MazeSkill castedSkill, Set targets) { + public void startBattle(Player player, int casterId, int attackedGroupId, MazeSkill castedSkill, IntSet hitTargets, IntSet assistMonsters) { // Setup variables List targetEntities = new ArrayList<>(); - boolean isPlayerCaster = player.getScene().getAvatarEntityIds().contains(casterId); + GameAvatar castingAvatar = null; // Check if attacker is the player or not - if (isPlayerCaster) { - // Player is the attacker - for (int entityId : targets) { + if (player.getScene().getAvatarEntityIds().contains(casterId)) { + // Get casting avatar + castingAvatar = player.getCurrentLeaderAvatar(); + + // Player is the attacker, add hit targets to the battle + for (int entityId : hitTargets) { GameEntity entity = player.getScene().getEntities().get(entityId); if (entity != null) { @@ -53,15 +56,6 @@ public class BattleService extends BaseGameService { if (entity != null) { targetEntities.add(entity); } - - // Add any assisting monsters from target list - for (int entityId : targets) { - entity = player.getScene().getEntities().get(entityId); - - if (entity != null) { - targetEntities.add(entity); - } - } } // Skip if no attacked entities detected @@ -83,6 +77,8 @@ public class BattleService extends BaseGameService { } else if (entity instanceof EntityProp prop) { it.remove(); player.getScene().destroyProp(prop); + } else { + it.remove(); } } @@ -93,10 +89,24 @@ public class BattleService extends BaseGameService { // Skip battle if our technique does not trigger a battle player.sendPacket(new PacketSceneCastSkillScRsp(attackedGroupId)); return; - } - + } + + // Add any assisting monsters from monster assist list + for (int entityId : assistMonsters) { + GameEntity entity = player.getScene().getEntities().get(entityId); + + if (entity != null && entity instanceof EntityMonster monster) { + monsters.add(monster); + } + } + // Start battle if (monsters.size() > 0) { + // Maze skill attack event + if (castedSkill != null && castingAvatar != null) { + castedSkill.onAttack(castingAvatar, targetEntities); + } + // Create battle and add npc monsters to it Battle battle = new Battle(player, player.getLineupManager().getCurrentLineup(), monsters); @@ -107,23 +117,15 @@ public class BattleService extends BaseGameService { } // Add buffs to battle - if (isPlayerCaster) { - GameAvatar avatar = player.getCurrentLeaderAvatar(); - - if (avatar != null) { - // Maze skill attack event - if (castedSkill != null) { - castedSkill.onAttack(avatar, battle); - } - // Add elemental weakness buff to enemies - MazeBuff buff = battle.addBuff(avatar.getExcel().getDamageType().getEnterBattleBuff(), battle.getLineup().getLeader()); - if (buff != null) { - buff.addTargetIndex(battle.getLineup().getLeader()); - buff.addDynamicValue("SkillIndex", castedSkill.getIndex()); - } + if (castingAvatar != null) { + // Add elemental weakness debuff to enemies + MazeBuff buff = battle.addBuff(castingAvatar.getExcel().getDamageType().getEnterBattleBuff(), battle.getLineup().getLeader()); + if (buff != null) { + buff.addTargetIndex(battle.getLineup().getLeader()); + buff.addDynamicValue("SkillIndex", castedSkill.getIndex()); } } else { - // Ambush buff (for monsters) + // Ambush debuff (from monsters) battle.addBuff(GameConstants.BATTLE_AMBUSH_BUFF_ID, -1, 1); } diff --git a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkill.java b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkill.java index 677e7f3..60df6f5 100644 --- a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkill.java +++ b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkill.java @@ -5,7 +5,6 @@ import java.util.List; import emu.lunarcore.data.excel.AvatarExcel; import emu.lunarcore.game.avatar.GameAvatar; -import emu.lunarcore.game.battle.Battle; import emu.lunarcore.game.scene.entity.GameEntity; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; import lombok.Getter; @@ -28,7 +27,9 @@ public class MazeSkill { this.attackActions = new ArrayList<>(); } - // Triggered when player casts a skill + /** + * Triggered when player casts a skill + */ public void onCast(GameAvatar caster, MotionInfo castPosition) { if (this.getCastActions().size() == 0) return; @@ -37,21 +38,25 @@ public class MazeSkill { } } - // Triggered when player attacks an enemy - public void onAttack(GameAvatar caster, Battle battle) { + /** + * Triggered when player casts a skill and it hits entities + */ + public void onCastHit(GameAvatar caster, List entities) { if (this.getAttackActions().size() == 0) return; for (var action : this.getAttackActions()) { - action.onAttack(caster, battle); + action.onCastHit(caster, entities); } } - // Triggered when player attacks an enemy - public void onAttack(GameAvatar caster, List entities) { + /** + * Triggered when player attacks an enemy + */ + public void onAttack(GameAvatar caster, List targets) { if (this.getAttackActions().size() == 0) return; for (var action : this.getAttackActions()) { - action.onAttack(caster, entities); + action.onAttack(caster, targets); } } } diff --git a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillAction.java b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillAction.java index 04eb62a..9314ff1 100644 --- a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillAction.java +++ b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillAction.java @@ -3,16 +3,21 @@ package emu.lunarcore.game.battle.skills; import java.util.List; import emu.lunarcore.game.avatar.GameAvatar; -import emu.lunarcore.game.battle.Battle; import emu.lunarcore.game.scene.entity.GameEntity; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; public abstract class MazeSkillAction { - public abstract void onCast(GameAvatar caster, MotionInfo castPosition); + public void onCast(GameAvatar caster, MotionInfo castPosition) { + + } - public abstract void onAttack(GameAvatar caster, Battle battle); + public void onCastHit(GameAvatar caster, List entities) { + + } - public abstract void onAttack(GameAvatar caster, List entities); + public void onAttack(GameAvatar caster, List targets) { + + } } diff --git a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillAddBuff.java b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillAddBuff.java index d193ca9..6632674 100644 --- a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillAddBuff.java +++ b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillAddBuff.java @@ -3,7 +3,7 @@ package emu.lunarcore.game.battle.skills; import java.util.List; import emu.lunarcore.game.avatar.GameAvatar; -import emu.lunarcore.game.battle.Battle; +import emu.lunarcore.game.scene.SceneBuff; import emu.lunarcore.game.scene.entity.EntityMonster; import emu.lunarcore.game.scene.entity.GameEntity; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; @@ -30,17 +30,18 @@ public class MazeSkillAddBuff extends MazeSkillAction { } @Override - public void onAttack(GameAvatar caster, Battle battle) { - // Get amount of monster waves in battle - int waveCount = battle.getMonsterWaveCount(); - // Add buff for each wave id - for (int i = 0; i < waveCount; i++) { - battle.addBuff(buffId, battle.getLineup().getLeader(), 1 << i); + public void onAttack(GameAvatar caster, List targets) { + // Add debuff to monsters + for (GameEntity target : targets) { + if (target instanceof EntityMonster monster) { + // Set as temp buff + monster.setTempBuff(new SceneBuff(caster.getAvatarId(), buffId)); + } } } @Override - public void onAttack(GameAvatar caster, List entities) { + public void onCastHit(GameAvatar caster, List entities) { for (GameEntity entity : entities) { if (entity instanceof EntityMonster monster) { // Add buff to monster diff --git a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillHitProp.java b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillHitProp.java index 7ebed06..d9d99c0 100644 --- a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillHitProp.java +++ b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillHitProp.java @@ -3,27 +3,15 @@ package emu.lunarcore.game.battle.skills; import java.util.List; import emu.lunarcore.game.avatar.GameAvatar; -import emu.lunarcore.game.battle.Battle; import emu.lunarcore.game.scene.entity.EntityProp; import emu.lunarcore.game.scene.entity.GameEntity; -import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; import lombok.Getter; @Getter public class MazeSkillHitProp extends MazeSkillAction { @Override - public void onCast(GameAvatar caster, MotionInfo castPosition) { - // Skip - } - - @Override - public void onAttack(GameAvatar caster, Battle battle) { - // Skip - } - - @Override - public void onAttack(GameAvatar caster, List entities) { + public void onCastHit(GameAvatar caster, List entities) { for (GameEntity entity : entities) { if (entity instanceof EntityProp prop) { caster.getScene().destroyProp(prop); diff --git a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillModifyHP.java b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillModifyHP.java index 6747ef0..4a1a1ee 100644 --- a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillModifyHP.java +++ b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillModifyHP.java @@ -1,10 +1,6 @@ package emu.lunarcore.game.battle.skills; -import java.util.List; - import emu.lunarcore.game.avatar.GameAvatar; -import emu.lunarcore.game.battle.Battle; -import emu.lunarcore.game.scene.entity.GameEntity; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; public class MazeSkillModifyHP extends MazeSkillAction { @@ -19,14 +15,4 @@ public class MazeSkillModifyHP extends MazeSkillAction { caster.getOwner().getCurrentLineup().heal(this.amount, false); } - @Override - public void onAttack(GameAvatar caster, Battle battle) { - - } - - @Override - public void onAttack(GameAvatar caster, List entities) { - - } - } diff --git a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillModifySP.java b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillModifySP.java index d1b754f..9a027a9 100644 --- a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillModifySP.java +++ b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillModifySP.java @@ -3,7 +3,6 @@ package emu.lunarcore.game.battle.skills; import java.util.List; import emu.lunarcore.game.avatar.GameAvatar; -import emu.lunarcore.game.battle.Battle; import emu.lunarcore.game.scene.entity.GameEntity; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; @@ -23,12 +22,7 @@ public class MazeSkillModifySP extends MazeSkillAction { } @Override - public void onAttack(GameAvatar caster, Battle battle) { - - } - - @Override - public void onAttack(GameAvatar caster, List entities) { + public void onCastHit(GameAvatar caster, List entities) { } diff --git a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillSummonUnit.java b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillSummonUnit.java index 3dfb1c0..d4df7be 100644 --- a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillSummonUnit.java +++ b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillSummonUnit.java @@ -1,11 +1,7 @@ package emu.lunarcore.game.battle.skills; -import java.util.List; - import emu.lunarcore.data.excel.SummonUnitExcel; import emu.lunarcore.game.avatar.GameAvatar; -import emu.lunarcore.game.battle.Battle; -import emu.lunarcore.game.scene.entity.GameEntity; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; import emu.lunarcore.util.Position; import lombok.Getter; @@ -25,14 +21,4 @@ public class MazeSkillSummonUnit extends MazeSkillAction { caster.getScene().summonUnit(caster, excel, new Position(castPosition.getPos()), new Position(castPosition.getRot()), duration); } - @Override - public void onAttack(GameAvatar caster, Battle battle) { - // Skip - } - - @Override - public void onAttack(GameAvatar caster, List entities) { - // Skip - } - } diff --git a/src/main/java/emu/lunarcore/game/scene/Scene.java b/src/main/java/emu/lunarcore/game/scene/Scene.java index e632bc1..7894c33 100644 --- a/src/main/java/emu/lunarcore/game/scene/Scene.java +++ b/src/main/java/emu/lunarcore/game/scene/Scene.java @@ -261,7 +261,7 @@ public class Scene implements Tickable { // Handle task actions for (var action : trigger.getActions()) { - action.onAttack(summonUnit.getCaster(), targets); + action.onCastHit(summonUnit.getCaster(), targets); } // Send packet diff --git a/src/main/java/emu/lunarcore/game/scene/SceneBuff.java b/src/main/java/emu/lunarcore/game/scene/SceneBuff.java index dd261d1..c09100b 100644 --- a/src/main/java/emu/lunarcore/game/scene/SceneBuff.java +++ b/src/main/java/emu/lunarcore/game/scene/SceneBuff.java @@ -8,17 +8,28 @@ public class SceneBuff { private int casterAvatarId; // Owner avatar id private int buffId; private int buffLevel; - private int duration; + private float duration; private long createTime; private long expiry; - public SceneBuff(int casterAvatarId, int buffId, int seconds) { - this.casterAvatarId = casterAvatarId; + public SceneBuff(int buffId) { this.buffId = buffId; this.buffLevel = 1; this.createTime = System.currentTimeMillis(); + this.duration = -1; + } + + public SceneBuff(int casterAvatarId, int buffId) { + this(buffId); + this.casterAvatarId = casterAvatarId; + this.expiry = Long.MAX_VALUE; + } + + public SceneBuff(int casterAvatarId, int buffId, int seconds) { + this(buffId); + this.casterAvatarId = casterAvatarId; this.duration = seconds * 1000; - this.expiry = this.createTime + duration; + this.expiry = this.createTime + (long) duration; } public boolean isExpired(long timestamp) { @@ -33,7 +44,7 @@ public class SceneBuff { .setLevel(this.getBuffLevel()) .setBaseAvatarId(this.getCasterAvatarId()) .setAddTimeMs(this.getCreateTime()) - .setLifeTime(this.getDuration() / 10) + .setLifeTime(this.getDuration()) .setCount(1); return proto; diff --git a/src/main/java/emu/lunarcore/game/scene/entity/EntityMonster.java b/src/main/java/emu/lunarcore/game/scene/entity/EntityMonster.java index 04a4032..fb49dd6 100644 --- a/src/main/java/emu/lunarcore/game/scene/entity/EntityMonster.java +++ b/src/main/java/emu/lunarcore/game/scene/entity/EntityMonster.java @@ -32,6 +32,8 @@ public class EntityMonster implements GameEntity, Tickable { private final Position rot; private Int2ObjectMap buffs; + @Setter private SceneBuff tempBuff; + private int farmElementId; @Setter private int customStageId; @Setter private int customLevel; @@ -72,22 +74,36 @@ public class EntityMonster implements GameEntity, Tickable { } public synchronized void applyBuffs(Battle battle, int waveIndex) { - if (this.buffs == null) return; - - for (var entry : this.buffs.int2ObjectEntrySet()) { - // Check expiry for buff - if (entry.getValue().isExpired(battle.getTimestamp())) { - continue; - } - - // Get owner index - int ownerIndex = battle.getLineup().indexOf(entry.getValue().getCasterAvatarId()); - - // Add buff to battle if owner exists - if (ownerIndex != -1) { - battle.addBuff(entry.getIntKey(), ownerIndex, 1 << waveIndex); + if (this.buffs != null) { + for (var entry : this.buffs.int2ObjectEntrySet()) { + // Check expiry for buff + if (entry.getValue().isExpired(battle.getTimestamp())) { + continue; + } + + // Add buff to battle + this.applyBuff(battle, entry.getValue(), waveIndex); } } + + if (this.getTempBuff() != null) { + this.applyBuff(battle, this.getTempBuff(), waveIndex); + this.tempBuff = null; + } + } + + private boolean applyBuff(Battle battle, SceneBuff buff, int waveIndex) { + // Get index of owner in lineup + int ownerIndex = battle.getLineup().indexOf(buff.getCasterAvatarId()); + + // Add buff to battle if owner exists + if (ownerIndex != -1) { + battle.addBuff(buff.getBuffId(), ownerIndex, 1 << waveIndex); + return true; + } + + // Failure + return false; } @Override 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 8244d4f..0b0d86e 100644 --- a/src/main/java/emu/lunarcore/server/packet/recv/HandlerSceneCastSkillCsReq.java +++ b/src/main/java/emu/lunarcore/server/packet/recv/HandlerSceneCastSkillCsReq.java @@ -1,8 +1,5 @@ package emu.lunarcore.server.packet.recv; -import java.util.LinkedHashSet; -import java.util.Set; - import emu.lunarcore.game.avatar.GameAvatar; import emu.lunarcore.game.battle.skills.MazeSkill; import emu.lunarcore.game.player.Player; @@ -13,10 +10,12 @@ import emu.lunarcore.server.packet.Opcodes; import emu.lunarcore.server.packet.PacketHandler; import emu.lunarcore.server.packet.send.PacketSceneCastSkillMpUpdateScNotify; import emu.lunarcore.server.packet.send.PacketSceneCastSkillScRsp; +import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; @Opcodes(CmdId.SceneCastSkillCsReq) public class HandlerSceneCastSkillCsReq extends PacketHandler { - + @Override public void handle(GameSession session, byte[] data) throws Exception { var req = SceneCastSkillCsReq.parseFrom(data); @@ -52,13 +51,19 @@ public class HandlerSceneCastSkillCsReq extends PacketHandler { } if (req.hasHitTargetIdList()) { - // Create target list - Set targets = new LinkedHashSet<>(); - req.getHitTargetIdList().forEach(targets::add); - req.getAssistMonsterIdList().forEach(targets::add); + // Parse targets efficiently (skips integer boxing) + IntSet hitTargets = new IntLinkedOpenHashSet(); + for (int i = 0; i < req.getHitTargetIdList().length(); i++) { + hitTargets.add(req.getHitTargetIdList().get(i)); + } + + IntSet assistMonsters = new IntLinkedOpenHashSet(); + for (int i = 0; i < req.getAssistMonsterIdList().length(); i++) { + assistMonsters.add(req.getAssistMonsterIdList().get(i)); + } // Start battle - session.getServer().getBattleService().startBattle(player, req.getCasterId(), req.getAttackedGroupId(), skill, targets); + session.getServer().getBattleService().startBattle(player, req.getCasterId(), req.getAttackedGroupId(), skill, hitTargets, assistMonsters); } else { // We had no targets for some reason session.send(new PacketSceneCastSkillScRsp(req.getAttackedGroupId()));