mirror of
https://github.com/Anime-Game-Servers/AGSLunarCore.git
synced 2024-11-23 12:29:53 +00:00
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
This commit is contained in:
parent
3b2633f78f
commit
246b5e0340
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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<Integer> targets) {
|
||||
public void startBattle(Player player, int casterId, int attackedGroupId, MazeSkill castedSkill, IntSet hitTargets, IntSet assistMonsters) {
|
||||
// Setup variables
|
||||
List<GameEntity> 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);
|
||||
}
|
||||
|
||||
|
@ -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<? extends GameEntity> 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<? extends GameEntity> entities) {
|
||||
/**
|
||||
* Triggered when player attacks an enemy
|
||||
*/
|
||||
public void onAttack(GameAvatar caster, List<? extends GameEntity> targets) {
|
||||
if (this.getAttackActions().size() == 0) return;
|
||||
|
||||
for (var action : this.getAttackActions()) {
|
||||
action.onAttack(caster, entities);
|
||||
action.onAttack(caster, targets);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<? extends GameEntity> entities) {
|
||||
|
||||
}
|
||||
|
||||
public abstract void onAttack(GameAvatar caster, List<? extends GameEntity> entities);
|
||||
public void onAttack(GameAvatar caster, List<? extends GameEntity> targets) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<? extends GameEntity> 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<? extends GameEntity> entities) {
|
||||
public void onCastHit(GameAvatar caster, List<? extends GameEntity> entities) {
|
||||
for (GameEntity entity : entities) {
|
||||
if (entity instanceof EntityMonster monster) {
|
||||
// Add buff to monster
|
||||
|
@ -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<? extends GameEntity> entities) {
|
||||
public void onCastHit(GameAvatar caster, List<? extends GameEntity> entities) {
|
||||
for (GameEntity entity : entities) {
|
||||
if (entity instanceof EntityProp prop) {
|
||||
caster.getScene().destroyProp(prop);
|
||||
|
@ -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<? extends GameEntity> entities) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<? extends GameEntity> entities) {
|
||||
public void onCastHit(GameAvatar caster, List<? extends GameEntity> entities) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -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<? extends GameEntity> entities) {
|
||||
// Skip
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -32,6 +32,8 @@ public class EntityMonster implements GameEntity, Tickable {
|
||||
private final Position rot;
|
||||
|
||||
private Int2ObjectMap<SceneBuff> 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
|
||||
|
@ -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<Integer> 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()));
|
||||
|
Loading…
Reference in New Issue
Block a user