diff --git a/src/main/java/emu/lunarcore/game/battle/Battle.java b/src/main/java/emu/lunarcore/game/battle/Battle.java index f16a8ee..8b00200 100644 --- a/src/main/java/emu/lunarcore/game/battle/Battle.java +++ b/src/main/java/emu/lunarcore/game/battle/Battle.java @@ -121,6 +121,10 @@ public class Battle { return buff; } + public boolean hasBuff(int buffId) { + return this.buffs.stream().filter(buff -> buff.getId() == buffId).findFirst().isPresent(); + } + public void clearBuffs() { this.buffs.clear(); } diff --git a/src/main/java/emu/lunarcore/game/battle/BattleService.java b/src/main/java/emu/lunarcore/game/battle/BattleService.java index 40cff57..128ae9f 100644 --- a/src/main/java/emu/lunarcore/game/battle/BattleService.java +++ b/src/main/java/emu/lunarcore/game/battle/BattleService.java @@ -64,13 +64,13 @@ public class BattleService extends BaseGameService { } } - // Give the client an error if no attacked entities detected + // Skip if no attacked entities detected if (targetEntities.size() == 0) { - player.sendPacket(new PacketSceneCastSkillScRsp()); + player.sendPacket(new PacketSceneCastSkillScRsp(attackedGroupId)); return; } - // Monster list + // Separate entities into monster list List monsters = new ArrayList<>(); // Destroy props @@ -85,6 +85,15 @@ public class BattleService extends BaseGameService { player.getScene().removeEntity(entity); } } + + // Check if we are using a skill that doesnt trigger a battle + if (castedSkill != null && !castedSkill.isTriggerBattle()) { + // Apply buffs to monsters + castedSkill.onAttack(player.getCurrentLeaderAvatar(), monsters); + // Skip battle if our technique does not trigger a battle + player.sendPacket(new PacketSceneCastSkillScRsp(attackedGroupId)); + return; + } // Start battle if (monsters.size() > 0) { @@ -109,11 +118,16 @@ public class BattleService extends BaseGameService { Battle battle = new Battle(player, player.getLineupManager().getCurrentLineup(), stages); // Add npc monsters - for (var npcMonster : monsters) { - battle.getNpcMonsters().add(npcMonster); + for (var monster : monsters) { + battle.getNpcMonsters().add(monster); - if (npcMonster.getOverrideLevel() > 0) { - battle.setLevelOverride(npcMonster.getOverrideLevel()); + // Handle monster buffs + // TODO handle multiple waves properly + monster.applyBuffs(battle); + + // Override level + if (monster.getOverrideLevel() > 0) { + battle.setLevelOverride(monster.getOverrideLevel()); } } diff --git a/src/main/java/emu/lunarcore/game/battle/MazeBuff.java b/src/main/java/emu/lunarcore/game/battle/MazeBuff.java index 28a6264..1c8fc9e 100644 --- a/src/main/java/emu/lunarcore/game/battle/MazeBuff.java +++ b/src/main/java/emu/lunarcore/game/battle/MazeBuff.java @@ -1,6 +1,7 @@ package emu.lunarcore.game.battle; import emu.lunarcore.data.excel.MazeBuffExcel; +import emu.lunarcore.game.scene.entity.GameEntity; import emu.lunarcore.proto.BattleBuffOuterClass.BattleBuff; import emu.lunarcore.proto.BattleBuffOuterClass.BattleBuff.DynamicValuesEntry; import it.unimi.dsi.fastutil.ints.IntArrayList; @@ -9,6 +10,7 @@ import it.unimi.dsi.fastutil.objects.Object2DoubleMap; import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; import lombok.AccessLevel; import lombok.Getter; +import lombok.Setter; @Getter public class MazeBuff { @@ -19,7 +21,10 @@ public class MazeBuff { private IntList targetIndex; @Getter(AccessLevel.NONE) - private Object2DoubleMap dynamicValues; + private Object2DoubleMap dynamicValues; + + @Setter + private transient GameEntity owner; public MazeBuff(MazeBuffExcel excel, int ownerIndex, int waveFlag) { this(excel.getBuffId(), excel.getLv(), ownerIndex, waveFlag); @@ -52,9 +57,12 @@ public class MazeBuff { var proto = BattleBuff.newInstance() .setId(this.getId()) .setLevel(this.getLevel()) - .setOwnerId(this.getOwnerIndex()) .setWaveFlag(this.getWaveFlag()); + if (this.ownerIndex != 0) { + proto.setOwnerId(this.getOwnerIndex()); + } + if (this.targetIndex != null) { for (int index : this.targetIndex) { proto.addTargetIndexList(index); 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 f7ef773..240972a 100644 --- a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkill.java +++ b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkill.java @@ -6,6 +6,7 @@ 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.EntityMonster; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; import lombok.Getter; import lombok.Setter; @@ -44,4 +45,13 @@ public class MazeSkill { action.onAttack(caster, battle); } } + + // Triggered when player attacks an enemy + public void onAttack(GameAvatar caster, List monsters) { + if (this.getAttackActions().size() == 0) return; + + for (var action : this.getAttackActions()) { + action.onAttack(caster, monsters); + } + } } 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 22296c9..195aa23 100644 --- a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillAction.java +++ b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillAction.java @@ -1,7 +1,10 @@ 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.EntityMonster; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; public abstract class MazeSkillAction { @@ -10,4 +13,6 @@ public abstract class MazeSkillAction { public abstract void onAttack(GameAvatar caster, Battle battle); + public abstract void onAttack(GameAvatar caster, List monsters); + } 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 5c6bddb..772922a 100644 --- a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillAddBuff.java +++ b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillAddBuff.java @@ -1,7 +1,10 @@ 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.EntityMonster; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; import lombok.Getter; @@ -29,5 +32,12 @@ public class MazeSkillAddBuff extends MazeSkillAction { battle.addBuff(buffId, battle.getLineup().getLeader(), 1 << i); } } + + @Override + public void onAttack(GameAvatar caster, List monsters) { + for (EntityMonster monster : monsters) { + monster.addBuff(caster.getAvatarId(), buffId, duration); + } + } } 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 a3a32bb..7872a57 100644 --- a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillModifyHP.java +++ b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillModifyHP.java @@ -1,7 +1,10 @@ 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.EntityMonster; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; public class MazeSkillModifyHP extends MazeSkillAction { @@ -21,4 +24,9 @@ public class MazeSkillModifyHP extends MazeSkillAction { } + @Override + public void onAttack(GameAvatar caster, List monsters) { + + } + } 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 a12ca81..1e6e807 100644 --- a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillModifySP.java +++ b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillModifySP.java @@ -1,7 +1,10 @@ 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.EntityMonster; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; public class MazeSkillModifySP extends MazeSkillAction { @@ -24,4 +27,9 @@ public class MazeSkillModifySP extends MazeSkillAction { } + @Override + public void onAttack(GameAvatar caster, List monsters) { + + } + } 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 3c43acc..ae9cdd8 100644 --- a/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillSummonUnit.java +++ b/src/main/java/emu/lunarcore/game/battle/skills/MazeSkillSummonUnit.java @@ -1,7 +1,10 @@ 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.EntityMonster; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; public class MazeSkillSummonUnit extends MazeSkillAction { @@ -16,4 +19,9 @@ public class MazeSkillSummonUnit extends MazeSkillAction { // TODO Auto-generated method stub } + @Override + public void onAttack(GameAvatar caster, List monsters) { + // TODO Auto-generated method stub + } + } diff --git a/src/main/java/emu/lunarcore/game/player/lineup/PlayerLineup.java b/src/main/java/emu/lunarcore/game/player/lineup/PlayerLineup.java index 61cd675..215846d 100644 --- a/src/main/java/emu/lunarcore/game/player/lineup/PlayerLineup.java +++ b/src/main/java/emu/lunarcore/game/player/lineup/PlayerLineup.java @@ -128,6 +128,10 @@ public class PlayerLineup { } } + public int indexOf(int ownerId) { + return this.getAvatars().indexOf(ownerId); + } + /** * Checks if the slot contains an avatar * @param slot The slot we are checking for diff --git a/src/main/java/emu/lunarcore/game/scene/SceneEntityBuff.java b/src/main/java/emu/lunarcore/game/scene/SceneEntityBuff.java new file mode 100644 index 0000000..82afe55 --- /dev/null +++ b/src/main/java/emu/lunarcore/game/scene/SceneEntityBuff.java @@ -0,0 +1,16 @@ +package emu.lunarcore.game.scene; + +import lombok.Getter; + +@Getter +public class SceneEntityBuff { + private int owner; // Owner avatar id + private int id; + private long expiry; + + public SceneEntityBuff(int owner, int id, long duration) { + this.owner = owner; + this.id = id; + this.expiry = System.currentTimeMillis() + (duration * 1000); + } +} 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 5d4953b..bbdde02 100644 --- a/src/main/java/emu/lunarcore/game/scene/entity/EntityMonster.java +++ b/src/main/java/emu/lunarcore/game/scene/entity/EntityMonster.java @@ -3,12 +3,16 @@ package emu.lunarcore.game.scene.entity; import emu.lunarcore.data.config.GroupInfo; import emu.lunarcore.data.config.MonsterInfo; import emu.lunarcore.data.excel.NpcMonsterExcel; +import emu.lunarcore.game.battle.Battle; import emu.lunarcore.game.scene.Scene; +import emu.lunarcore.game.scene.SceneEntityBuff; import emu.lunarcore.game.scene.triggers.PropTriggerType; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; import emu.lunarcore.proto.SceneEntityInfoOuterClass.SceneEntityInfo; import emu.lunarcore.proto.SceneNpcMonsterInfoOuterClass.SceneNpcMonsterInfo; import emu.lunarcore.util.Position; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import lombok.Getter; import lombok.Setter; @@ -25,6 +29,7 @@ public class EntityMonster implements GameEntity { private final Position pos; private final Position rot; + private Int2ObjectMap buffs; private int farmElementId; @Setter private int overrideStageId; @Setter private int overrideLevel; @@ -51,6 +56,39 @@ public class EntityMonster implements GameEntity { } } + public void addBuff(int caster, int buffId, int duration) { + if (this.buffs == null) { + this.buffs = new Int2ObjectOpenHashMap<>(); + } + + this.buffs.put(buffId, new SceneEntityBuff(caster, buffId, duration)); + } + + public void applyBuffs(Battle battle) { + if (this.buffs == null) return; + + for (var entry : this.buffs.int2ObjectEntrySet()) { + // Check expiry for buff + if (entry.getValue().getExpiry() < battle.getTimestamp()) { + continue; + } + + // Dont add duplicate buffs + if (battle.hasBuff(entry.getIntKey())) { + continue; + } + + // Get owner index + int ownerIndex = battle.getLineup().indexOf(entry.getValue().getOwner()); + + // Add buff to battle if owner exists + if (ownerIndex != -1) { + // TODO handle multiple waves properly + battle.addBuff(entry.getIntKey(), ownerIndex, 1); + } + } + } + @Override public void onRemove() { // Try to fire any triggers 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 cb0ded0..8244d4f 100644 --- a/src/main/java/emu/lunarcore/server/packet/recv/HandlerSceneCastSkillCsReq.java +++ b/src/main/java/emu/lunarcore/server/packet/recv/HandlerSceneCastSkillCsReq.java @@ -57,14 +57,8 @@ public class HandlerSceneCastSkillCsReq extends PacketHandler { req.getHitTargetIdList().forEach(targets::add); req.getAssistMonsterIdList().forEach(targets::add); - // Check if we can start a battle - if (skill != null && !skill.isTriggerBattle()) { - // Skip battle if our technique does not trigger a battle - session.send(new PacketSceneCastSkillScRsp(req.getAttackedGroupId())); - } else { - // Start battle normally - session.getServer().getBattleService().startBattle(player, req.getCasterId(), req.getAttackedGroupId(), skill, targets); - } + // Start battle + session.getServer().getBattleService().startBattle(player, req.getCasterId(), req.getAttackedGroupId(), skill, targets); } else { // We had no targets for some reason session.send(new PacketSceneCastSkillScRsp(req.getAttackedGroupId()));