Implement summon related techniques

Make sure to redownload config files are as new summon unit configs are required
This commit is contained in:
Melledy
2023-12-13 19:10:51 -08:00
parent 6c9f6743cc
commit 09337fd9ec
33 changed files with 4843 additions and 410 deletions

View File

@@ -24,6 +24,7 @@ public class GameData {
@Getter private static Int2ObjectMap<RelicExcel> relicExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<PropExcel> propExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<NpcExcel> npcExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<SummonUnitExcel> summonUnitExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<MonsterExcel> monsterExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<NpcMonsterExcel> npcMonsterExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<StageExcel> stageExcelMap = new Int2ObjectOpenHashMap<>();

View File

@@ -21,6 +21,7 @@ import emu.lunarcore.data.config.FloorInfo;
import emu.lunarcore.data.config.FloorInfo.FloorGroupSimpleInfo;
import emu.lunarcore.data.config.GroupInfo;
import emu.lunarcore.data.config.SkillAbilityInfo;
import emu.lunarcore.data.config.SummonUnitInfo;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
public class ResourceLoader {
@@ -227,8 +228,40 @@ public class ResourceLoader {
// Might be better to cache
private static void loadMazeAbilities() {
// Loaded configs count
int count = 0;
// Load summon unit configs
for (var summonUnitExcel : GameData.getSummonUnitExcelMap().values()) {
if (summonUnitExcel.isIsClient()) {
count++;
continue;
}
// Get file
File file = new File(LunarCore.getConfig().getResourceDir() + "/" + summonUnitExcel.getJsonPath());
if (!file.exists()) continue;
try (FileReader reader = new FileReader(file)) {
SummonUnitInfo info = gson.fromJson(reader, SummonUnitInfo.class);
info.buildMazeSkillActions();
summonUnitExcel.setInfo(info);
count++;
} catch (Exception e) {
e.printStackTrace();
}
}
// Notify the server owner if we are missing any files
if (count < GameData.getSummonUnitExcelMap().size()) {
LunarCore.getLogger().warn("Summon unit configs are missing, please check your resources folder: {resources}/Config/ConfigSummonUnit. Character summon techniques may not work!");
}
// Reset loaded count
count = 0;
// Load maze abilities
for (var avatarExcel : GameData.getAvatarExcelMap().values()) {
// Get file
File file = new File(LunarCore.getConfig().getResourceDir() + "/Config/ConfigAdventureAbility/LocalPlayer/LocalPlayer_" + avatarExcel.getNameKey() + "_Ability.json");

View File

@@ -2,6 +2,7 @@ package emu.lunarcore.data.config;
import java.util.List;
import emu.lunarcore.data.GameData;
import emu.lunarcore.data.excel.AvatarExcel;
import emu.lunarcore.game.battle.skills.*;
import lombok.Getter;
@@ -27,6 +28,13 @@ public class SkillAbilityInfo {
avatarExcel.setMazeSkill(skill);
actionList = skill.getCastActions();
// Hacky way to check if an avatar can summon with their skill
var summonUnitExcel = GameData.getSummonUnitExcelMap().get((skill.getId() * 10) + 1);
if (summonUnitExcel != null && !summonUnitExcel.isIsClient()) {
// TODO duration is hardcoded
skill.getCastActions().add(new MazeSkillSummonUnit(summonUnitExcel, 20));
}
} else if (ability.getName().contains("NormalAtk")) {
skill = new MazeSkill(avatarExcel, 0);
avatarExcel.setMazeAttack(skill);
@@ -46,6 +54,7 @@ public class SkillAbilityInfo {
}
// "Simple" way to parse maze attacks/skills
// TODO parse tasks better
private void parseTask(MazeSkill skill, List<MazeSkillAction> actionList, TaskInfo task) {
if (task.getType().contains("AddMazeBuff")) {
// TODO get duration from params if buff duration is dynamic
@@ -59,7 +68,7 @@ public class SkillAbilityInfo {
// TODO get sp increase value from params, also handle target alias
actionList.add(new MazeSkillModifySP(50));
} else if (task.getType().contains("CreateSummonUnit")) {
// Ignored
} else if (task.getSuccessTaskList() != null) {
for (TaskInfo t : task.getSuccessTaskList()) {
parseTask(skill, actionList, t);

View File

@@ -0,0 +1,75 @@
package emu.lunarcore.data.config;
import java.util.ArrayList;
import java.util.List;
import emu.lunarcore.game.battle.skills.MazeSkillAction;
import emu.lunarcore.game.battle.skills.MazeSkillAddBuff;
import lombok.Getter;
/**
* Original name: SummonUnitConfig
*/
@Getter
public class SummonUnitInfo {
private String AttachPoint;
private SummonUnitTriggers TriggerConfig;
public List<SummonUnitCustomTrigger> getCustomTriggers() {
return TriggerConfig.getCustomTriggers();
}
public SummonUnitCustomTrigger getTriggerByName(String name) {
return getCustomTriggers().stream()
.filter(c -> c.getTriggerName().equals(name))
.findFirst()
.orElse(null);
}
public void buildMazeSkillActions() {
for (var customTrigger : getCustomTriggers()) {
customTrigger.buildMazeSkillActions();
}
}
/**
* Original name: SummonUnitTriggerConfig
*/
@Getter
public static class SummonUnitTriggers {
private List<SummonUnitCustomTrigger> CustomTriggers;
}
/**
* Original name: UnitCustomTriggerConfig
*/
@Getter
public static class SummonUnitCustomTrigger {
private String TriggerName;
private List<TaskInfo> OnTriggerEnter;
private transient List<MazeSkillAction> actions;
public void buildMazeSkillActions() {
// Create actions list
this.actions = new ArrayList<>();
// Sanity check
if (this.OnTriggerEnter == null) return;
// Build maze actions
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);
actionAddBuff.setSendBuffPacket(true);
actions.add(actionAddBuff);
} else if (task.getType().contains("TriggerHitProp")) {
// actions.add(new MazeSkillAddBuff(task.getID(), 20));
}
}
}
}
}

View File

@@ -0,0 +1,28 @@
package emu.lunarcore.data.excel;
import emu.lunarcore.data.GameResource;
import emu.lunarcore.data.ResourceType;
import emu.lunarcore.data.config.SummonUnitInfo;
import lombok.Getter;
@Getter
@ResourceType(name = {"SummonUnitData.json"})
public class SummonUnitExcel extends GameResource {
private int ID;
private String JsonPath;
private boolean IsClient;
private transient SummonUnitInfo info;
@Override
public int getId() {
return ID;
}
public void setInfo(SummonUnitInfo info) {
if (this.info == null && !this.IsClient) {
this.info = info;
}
}
}

View File

@@ -80,9 +80,9 @@ public class BattleService extends BaseGameService {
if (entity instanceof EntityMonster monster) {
monsters.add(monster);
} else if (entity instanceof EntityProp) {
} else if (entity instanceof EntityProp prop) {
it.remove();
player.getScene().removeEntity(entity);
player.getScene().destroyProp(prop);
}
}

View File

@@ -6,7 +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.game.scene.entity.GameEntity;
import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
import lombok.Getter;
import lombok.Setter;
@@ -47,11 +47,11 @@ public class MazeSkill {
}
// Triggered when player attacks an enemy
public void onAttack(GameAvatar caster, List<EntityMonster> monsters) {
public void onAttack(GameAvatar caster, List<? extends GameEntity> entities) {
if (this.getAttackActions().size() == 0) return;
for (var action : this.getAttackActions()) {
action.onAttack(caster, monsters);
action.onAttack(caster, entities);
}
}
}

View File

@@ -4,7 +4,7 @@ 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.game.scene.entity.GameEntity;
import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
public abstract class MazeSkillAction {
@@ -13,6 +13,6 @@ public abstract class MazeSkillAction {
public abstract void onAttack(GameAvatar caster, Battle battle);
public abstract void onAttack(GameAvatar caster, List<EntityMonster> monsters);
public abstract void onAttack(GameAvatar caster, List<? extends GameEntity> entities);
}

View File

@@ -5,14 +5,20 @@ 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.game.scene.entity.GameEntity;
import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
import emu.lunarcore.server.packet.send.PacketSyncEntityBuffChangeListScNotify;
import lombok.Getter;
import lombok.Setter;
@Getter
public class MazeSkillAddBuff extends MazeSkillAction {
private int buffId;
private int duration;
@Setter
private boolean sendBuffPacket;
public MazeSkillAddBuff(int buffId, int duration) {
this.buffId = buffId;
this.duration = duration;
@@ -34,9 +40,17 @@ public class MazeSkillAddBuff extends MazeSkillAction {
}
@Override
public void onAttack(GameAvatar caster, List<EntityMonster> monsters) {
for (EntityMonster monster : monsters) {
monster.addBuff(caster.getAvatarId(), buffId, duration);
public void onAttack(GameAvatar caster, List<? extends GameEntity> entities) {
for (GameEntity entity : entities) {
if (entity instanceof EntityMonster monster) {
// Add buff to monster
var buff = monster.addBuff(caster.getAvatarId(), buffId, duration);
// Send packet
if (buff != null && this.sendBuffPacket) {
caster.getOwner().sendPacket(new PacketSyncEntityBuffChangeListScNotify(entity.getEntityId(), buff));
}
}
}
}

View File

@@ -0,0 +1,34 @@
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) {
for (GameEntity entity : entities) {
if (entity instanceof EntityProp prop) {
caster.getScene().destroyProp(prop);
}
}
}
}

View File

@@ -4,7 +4,7 @@ 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.game.scene.entity.GameEntity;
import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
public class MazeSkillModifyHP extends MazeSkillAction {
@@ -25,7 +25,7 @@ public class MazeSkillModifyHP extends MazeSkillAction {
}
@Override
public void onAttack(GameAvatar caster, List<EntityMonster> monsters) {
public void onAttack(GameAvatar caster, List<? extends GameEntity> entities) {
}

View File

@@ -4,7 +4,7 @@ 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.game.scene.entity.GameEntity;
import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
public class MazeSkillModifySP extends MazeSkillAction {
@@ -28,7 +28,7 @@ public class MazeSkillModifySP extends MazeSkillAction {
}
@Override
public void onAttack(GameAvatar caster, List<EntityMonster> monsters) {
public void onAttack(GameAvatar caster, List<? extends GameEntity> entities) {
}

View File

@@ -2,26 +2,37 @@ 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.EntityMonster;
import emu.lunarcore.game.scene.entity.GameEntity;
import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
import emu.lunarcore.util.Position;
import lombok.Getter;
@Getter
public class MazeSkillSummonUnit extends MazeSkillAction {
private SummonUnitExcel excel;
private int duration;
public MazeSkillSummonUnit(SummonUnitExcel excel, int duration) {
this.excel = excel;
this.duration = duration;
}
@Override
public void onCast(GameAvatar caster, MotionInfo castPosition) {
// TODO Auto-generated method stub
caster.getScene().summonUnit(caster, excel, new Position(castPosition.getPos()), new Position(castPosition.getRot()), duration);
}
@Override
public void onAttack(GameAvatar caster, Battle battle) {
// TODO Auto-generated method stub
// Skip
}
@Override
public void onAttack(GameAvatar caster, List<EntityMonster> monsters) {
// TODO Auto-generated method stub
public void onAttack(GameAvatar caster, List<? extends GameEntity> entities) {
// Skip
}
}

View File

@@ -274,9 +274,16 @@ public class Player {
}
public void setWorldLevel(int level) {
if (this.worldLevel == level) {
return;
}
this.worldLevel = level;
this.save();
this.sendPacket(new PacketPlayerSyncScNotify(this));
if (this.isOnline()) {
this.save();
this.getSession().send(new PacketPlayerSyncScNotify(this));
}
}
public int getWorldLevel() {
@@ -470,7 +477,12 @@ public class Player {
}
public void setBattle(Battle battle) {
// Set battle first
this.battle = battle;
// Scene handler
if (this.getScene() != null) {
this.getScene().onBattleStart(battle);
}
}
public void forceQuitBattle() {
@@ -572,7 +584,7 @@ public class Player {
// Finish puzzle
prop.setState(PropState.Locked);
// Trigger event
this.getScene().invokeTrigger(PropTriggerType.PUZZLE_FINISH, prop.getGroupId(), prop.getInstId());
this.getScene().invokePropTrigger(PropTriggerType.PUZZLE_FINISH, prop.getGroupId(), prop.getInstId());
//
return prop;
}
@@ -711,7 +723,12 @@ public class Player {
}
public void onTick() {
// Update stamina
this.updateStamina();
// Scene update
if (this.getScene() != null) {
this.getScene().onTick();
}
}
@SuppressWarnings("deprecation")

View File

@@ -6,22 +6,27 @@ import java.util.List;
import emu.lunarcore.data.GameData;
import emu.lunarcore.data.config.*;
import emu.lunarcore.data.excel.MazePlaneExcel;
import emu.lunarcore.data.excel.SummonUnitExcel;
import emu.lunarcore.game.avatar.GameAvatar;
import emu.lunarcore.game.battle.Battle;
import emu.lunarcore.game.enums.PlaneType;
import emu.lunarcore.game.scene.entity.*;
import emu.lunarcore.game.scene.triggers.PropTrigger;
import emu.lunarcore.game.scene.triggers.PropTriggerType;
import emu.lunarcore.game.player.Player;
import emu.lunarcore.game.player.lineup.PlayerLineup;
import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
import emu.lunarcore.proto.SceneEntityGroupInfoOuterClass.SceneEntityGroupInfo;
import emu.lunarcore.proto.SceneGroupStateOuterClass.SceneGroupState;
import emu.lunarcore.proto.SceneInfoOuterClass.SceneInfo;
import emu.lunarcore.server.packet.send.PacketActivateFarmElementScRsp;
import emu.lunarcore.server.packet.send.PacketRefreshTriggerByClientScNotify;
import emu.lunarcore.server.packet.send.PacketSceneGroupRefreshScNotify;
import emu.lunarcore.util.Position;
import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import lombok.Getter;
import us.hebi.quickbuf.RepeatedInt;
@Getter
public class Scene {
@@ -39,6 +44,7 @@ public class Scene {
// Avatar entites
private final IntSet avatarEntityIds;
private final Int2ObjectMap<GameAvatar> avatars;
private EntitySummonUnit playerSummon;
// Other entities
private final Int2ObjectMap<GameEntity> entities;
@@ -208,6 +214,64 @@ public class Scene {
return true;
}
// Summons
public synchronized void summonUnit(GameAvatar caster, SummonUnitExcel excel, Position pos, Position rot, int duration) {
// Remove previous summon
this.removeSummonUnit();
// Add a new summoned unit to scene
var summon = new EntitySummonUnit(this, caster, excel, pos, rot);
summon.setDuration(duration);
this.addEntity(summon, true);
}
public synchronized void removeSummonUnit() {
if (this.getPlayerSummon() != null) {
this.removeEntity(this.getPlayerSummon());
}
}
public void handleSummonUnitTriggers(int entityId, String name, MotionInfo motion, RepeatedInt targetIds) {
// Get summon unit
EntitySummonUnit summonUnit = null;
var entity = this.getEntityById(entityId);
if (entity instanceof EntitySummonUnit) {
summonUnit = (EntitySummonUnit) entity;
} else {
return;
}
// Get trigger
var trigger = summonUnit.getExcel().getInfo().getTriggerByName(name);
if (trigger == null) return;
// Get targets
var targets = new ArrayList<GameEntity>();
for (int targetId : targetIds) {
var target = this.getEntityById(targetId);
if (target != null) {
targets.add(target);
}
}
// Handle task actions
for (var action : trigger.getActions()) {
action.onAttack(summonUnit.getCaster(), targets);
}
// Send packet
this.getPlayer().sendPacket(new PacketRefreshTriggerByClientScNotify(entityId, name, targetIds));
}
public void destroyProp(EntityProp prop) {
// TODO sanity check prop to make sure it can be destroyed
this.removeEntity(prop);
}
/**
* Returns the nearest spring (Space Anchor) to the player in the scene
* @return
@@ -238,7 +302,7 @@ public class Scene {
return spring;
}
public void invokeTrigger(PropTriggerType type, int param1, int param2) {
public void invokePropTrigger(PropTriggerType type, int param1, int param2) {
for (PropTrigger trigger : this.getTriggers()) {
if (trigger.shouldRun(param1, param2)) {
trigger.run(this);
@@ -286,6 +350,26 @@ public class Scene {
}
}
// Player events
public void onTick() {
// Remove summoned unit if it expired
if (this.getPlayerSummon() != null) {
if (this.getPlayerSummon().isExpired()) {
this.removeSummonUnit();
}
}
}
public void onBattleStart(Battle battle) {
// Remove summoned unit
if (this.getPlayerSummon() != null) {
this.removeSummonUnit();
}
}
// Proto serialization
public synchronized SceneInfo toProto() {
// Set loaded flag
this.loaded = true;

View File

@@ -0,0 +1,37 @@
package emu.lunarcore.game.scene;
import emu.lunarcore.proto.BuffInfoOuterClass.BuffInfo;
import lombok.Getter;
@Getter
public class SceneBuff {
private int casterAvatarId; // Owner avatar id
private int buffId;
private int buffLevel;
private int duration;
private long createTime;
private long expiry;
public SceneBuff(int casterAvatarId, int buffId, int seconds) {
this.casterAvatarId = casterAvatarId;
this.buffId = buffId;
this.buffLevel = 1;
this.createTime = System.currentTimeMillis();
this.duration = seconds * 1000;
this.expiry = this.createTime + duration;
}
// Serialization
public BuffInfo toProto() {
var proto = BuffInfo.newInstance()
.setBuffId(this.getBuffId())
.setLevel(this.getBuffLevel())
.setBaseAvatarId(this.getCasterAvatarId())
.setAddTimeMs(this.getCreateTime())
.setLifeTime(this.getDuration() / 10)
.setCount(1);
return proto;
}
}

View File

@@ -1,16 +0,0 @@
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);
}
}

View File

@@ -5,7 +5,7 @@ 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.SceneBuff;
import emu.lunarcore.game.scene.triggers.PropTriggerType;
import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
import emu.lunarcore.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
@@ -29,7 +29,7 @@ public class EntityMonster implements GameEntity {
private final Position pos;
private final Position rot;
private Int2ObjectMap<SceneEntityBuff> buffs;
private Int2ObjectMap<SceneBuff> buffs;
private int farmElementId;
@Setter private int overrideStageId;
@Setter private int overrideLevel;
@@ -56,12 +56,17 @@ public class EntityMonster implements GameEntity {
}
}
public void addBuff(int caster, int buffId, int duration) {
public SceneBuff addBuff(int caster, int buffId, int duration) {
if (this.buffs == null) {
this.buffs = new Int2ObjectOpenHashMap<>();
}
this.buffs.put(buffId, new SceneEntityBuff(caster, buffId, duration));
// Create buff
var buff = new SceneBuff(caster, buffId, duration);
// Add to buff map
this.buffs.put(buffId, buff);
return buff;
}
public void applyBuffs(Battle battle) {
@@ -79,7 +84,7 @@ public class EntityMonster implements GameEntity {
}
// Get owner index
int ownerIndex = battle.getLineup().indexOf(entry.getValue().getOwner());
int ownerIndex = battle.getLineup().indexOf(entry.getValue().getCasterAvatarId());
// Add buff to battle if owner exists
if (ownerIndex != -1) {
@@ -92,7 +97,7 @@ public class EntityMonster implements GameEntity {
@Override
public void onRemove() {
// Try to fire any triggers
getScene().invokeTrigger(PropTriggerType.MONSTER_DIE, this.getGroupId(), this.getInstId());
getScene().invokePropTrigger(PropTriggerType.MONSTER_DIE, this.getGroupId(), this.getInstId());
}
@Override

View File

@@ -0,0 +1,72 @@
package emu.lunarcore.game.scene.entity;
import emu.lunarcore.data.excel.SummonUnitExcel;
import emu.lunarcore.game.avatar.GameAvatar;
import emu.lunarcore.game.scene.Scene;
import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
import emu.lunarcore.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.lunarcore.proto.SceneSummonUnitInfoOuterClass.SceneSummonUnitInfo;
import emu.lunarcore.util.Position;
import lombok.Getter;
import lombok.Setter;
@Getter
public class EntitySummonUnit implements GameEntity {
@Setter private int entityId;
private final GameAvatar caster;
private final SummonUnitExcel excel;
private final Scene scene;
private final Position pos;
private final Position rot;
private final long createTime;
private int attachedEntityId;
private int duration;
private long expiry;
public EntitySummonUnit(Scene scene, GameAvatar caster, SummonUnitExcel excel, Position pos, Position rot) {
this.scene = scene;
this.caster = caster;
this.excel = excel;
this.pos = pos;
this.rot = rot;
this.createTime = System.currentTimeMillis();
// Attach summon unit to an entity
String attachPoint = excel.getInfo().getAttachPoint();
if (attachPoint != null && attachPoint.equals("Origin")) {
this.attachedEntityId = caster.getEntityId();
}
}
public void setDuration(int seconds) {
this.duration = seconds * 1000;
this.expiry = this.createTime + duration;
}
public boolean isExpired() {
return System.currentTimeMillis() > this.expiry;
}
@Override
public SceneEntityInfo toSceneEntityProto() {
var summon = SceneSummonUnitInfo.newInstance()
.setLifeTimeMs(this.getDuration())
.setCreateTimeMs(this.getCreateTime())
.setCasterEntityId(this.getCaster().getEntityId())
.setAttachEntityId(this.getAttachedEntityId())
.setSummonUnitId(this.getExcel().getId());
for (var trigger : this.getExcel().getInfo().getCustomTriggers()) {
summon.addCustomTriggers(trigger.getTriggerName());
}
var proto = SceneEntityInfo.newInstance()
.setEntityId(this.getEntityId())
.setMotion(MotionInfo.newInstance().setPos(getPos().toProto()).setRot(getRot().toProto()))
.setSummonUnit(summon);
return proto;
}
}

View File

@@ -0,0 +1,29 @@
package emu.lunarcore.server.packet.recv;
import emu.lunarcore.proto.RefreshTriggerByClientCsReqOuterClass.RefreshTriggerByClientCsReq;
import emu.lunarcore.server.game.GameSession;
import emu.lunarcore.server.packet.CmdId;
import emu.lunarcore.server.packet.Opcodes;
import emu.lunarcore.server.packet.PacketHandler;
import emu.lunarcore.server.packet.send.PacketRefreshTriggerByClientScRsp;
@Opcodes(CmdId.RefreshTriggerByClientCsReq)
public class HandlerRefreshTriggerByClientCsReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] data) throws Exception {
var req = RefreshTriggerByClientCsReq.parseFrom(data);
if (session.getPlayer().getScene() != null) {
session.getPlayer().getScene().handleSummonUnitTriggers(
req.getTriggerEntityId(),
req.getTriggerName(),
req.getTriggerMotion(),
req.getTriggerTargetIdList()
);
}
session.send(new PacketRefreshTriggerByClientScRsp(req));
}
}

View File

@@ -0,0 +1,23 @@
package emu.lunarcore.server.packet.send;
import emu.lunarcore.proto.RefreshTriggerByClientScNotifyOuterClass.RefreshTriggerByClientScNotify;
import emu.lunarcore.server.packet.BasePacket;
import emu.lunarcore.server.packet.CmdId;
import us.hebi.quickbuf.RepeatedInt;
public class PacketRefreshTriggerByClientScNotify extends BasePacket {
public PacketRefreshTriggerByClientScNotify(int triggerEntityId, String name, RepeatedInt targetIds) {
super(CmdId.RefreshTriggerByClientScNotify);
var data = RefreshTriggerByClientScNotify.newInstance()
.setTriggerName(name)
.setTriggerEntityId(triggerEntityId);
for (int id : targetIds) {
data.addTriggerTargetIdList(id);
}
this.setData(data);
}
}

View File

@@ -0,0 +1,20 @@
package emu.lunarcore.server.packet.send;
import emu.lunarcore.proto.RefreshTriggerByClientCsReqOuterClass.RefreshTriggerByClientCsReq;
import emu.lunarcore.proto.RefreshTriggerByClientScRspOuterClass.RefreshTriggerByClientScRsp;
import emu.lunarcore.server.packet.BasePacket;
import emu.lunarcore.server.packet.CmdId;
public class PacketRefreshTriggerByClientScRsp extends BasePacket {
public PacketRefreshTriggerByClientScRsp(RefreshTriggerByClientCsReq req) {
super(CmdId.RefreshTriggerByClientScRsp);
var data = RefreshTriggerByClientScRsp.newInstance()
.setTriggerEntityId(req.getTriggerEntityId())
.setTriggerName(req.getTriggerName())
.setRefreshTrigger(true);
this.setData(data);
}
}

View File

@@ -0,0 +1,23 @@
package emu.lunarcore.server.packet.send;
import emu.lunarcore.game.scene.SceneBuff;
import emu.lunarcore.proto.EntityBuffChangeInfoOuterClass.EntityBuffChangeInfo;
import emu.lunarcore.proto.SyncEntityBuffChangeListScNotifyOuterClass.SyncEntityBuffChangeListScNotify;
import emu.lunarcore.server.packet.BasePacket;
import emu.lunarcore.server.packet.CmdId;
public class PacketSyncEntityBuffChangeListScNotify extends BasePacket {
public PacketSyncEntityBuffChangeListScNotify(int entityId, SceneBuff buff) {
super(CmdId.SyncEntityBuffChangeListScNotify);
var buffChange = EntityBuffChangeInfo.newInstance().setEntityId(entityId)
.setBuffChangeInfo(buff.toProto())
.setEntityId(entityId);
var data = SyncEntityBuffChangeListScNotify.newInstance()
.addEntityBuffInfoList(buffChange);
this.setData(data);
}
}

View File

@@ -24,6 +24,12 @@ public class Position {
this.y = position.getY();
this.z = position.getZ();
}
public Position(Vector vector) {
this.x = vector.getX();
this.y = vector.getY();
this.z = vector.getZ();
}
public int getX() {
return x;