Killing monsters should now unlock the proper chests

This commit is contained in:
Melledy
2023-10-07 05:35:11 -07:00
parent 7e33c18063
commit c73279191b
11 changed files with 163 additions and 31 deletions

View File

@@ -6,6 +6,7 @@ import java.util.List;
import com.google.gson.annotations.SerializedName;
import emu.lunarcore.game.enums.PropState;
import emu.lunarcore.game.scene.triggers.TriggerOpenTreasureWhenMonsterDie;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@@ -61,6 +62,15 @@ public class FloorInfo {
// Force prop to be in the unlocked state
prop.setState(PropState.CheckPointEnable);
} else if (prop.getInitLevelGraph() != null) {
String json = prop.getInitLevelGraph();
// Hacky way to setup prop triggers
if (json.contains("Maze_GroupProp_OpenTreasure_WhenMonsterDie")) {
prop.setTrigger(new TriggerOpenTreasureWhenMonsterDie(group.getId()));
}
prop.setInitLevelGraph(null);
}
}
}

View File

@@ -1,6 +1,7 @@
package emu.lunarcore.data.config;
import emu.lunarcore.game.enums.PropState;
import emu.lunarcore.game.scene.triggers.PropTrigger;
import lombok.Getter;
import lombok.Setter;
@@ -15,7 +16,10 @@ public class PropInfo extends ObjectInfo {
private int EventID;
private int CocoonID;
private int FarmElementID;
private int ChestID;
@Setter
private PropState State = PropState.Closed;
@Setter private String InitLevelGraph;
@Setter private PropState State = PropState.Closed;
@Setter private transient PropTrigger trigger;
}

View File

@@ -16,6 +16,7 @@ import emu.lunarcore.data.excel.AvatarExcel;
import emu.lunarcore.game.inventory.GameItem;
import emu.lunarcore.game.inventory.ItemMainType;
import emu.lunarcore.game.player.Player;
import emu.lunarcore.game.scene.Scene;
import emu.lunarcore.game.scene.entity.GameEntity;
import emu.lunarcore.proto.AvatarOuterClass.Avatar;
import emu.lunarcore.proto.AvatarSkillTreeOuterClass.AvatarSkillTree;
@@ -86,6 +87,11 @@ public class GameAvatar implements GameEntity {
this.setHeroPath(path);
}
@Override
public Scene getScene() {
return this.getOwner().getScene();
}
public void setExcel(AvatarExcel excel) {
if (this.excel == null) {
this.excel = excel;

View File

@@ -14,6 +14,8 @@ import emu.lunarcore.game.enums.PropState;
import emu.lunarcore.game.enums.PropType;
import emu.lunarcore.game.player.PlayerLineup;
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.proto.SceneEntityGroupInfoOuterClass.SceneEntityGroupInfo;
import emu.lunarcore.proto.SceneInfoOuterClass.SceneInfo;
@@ -24,6 +26,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import lombok.Getter;
@Getter
@@ -36,6 +39,7 @@ public class Scene {
private int entryId;
private int lastEntityId = 0;
private boolean loaded = false;
// Avatar entites
private IntSet avatarEntityIds;
@@ -45,6 +49,7 @@ public class Scene {
private Int2ObjectMap<GameEntity> entities;
// Cache
private List<PropTrigger> triggers;
private List<EntityProp> healingSprings;
public Scene(Player player, MazePlaneExcel excel, int floorId) {
@@ -57,7 +62,8 @@ public class Scene {
this.avatarEntityIds = new IntOpenHashSet();
this.avatars = new Int2ObjectOpenHashMap<>();
this.entities = new Int2ObjectOpenHashMap<>();
this.healingSprings = new ArrayList<>();
this.healingSprings = new ObjectArrayList<>();
this.triggers = new ObjectArrayList<>();
PlayerLineup lineup = getPlayer().getCurrentLineup();
@@ -90,7 +96,7 @@ public class Scene {
if (npcMonsterExcel == null) continue;
// Create monster with excels
EntityMonster monster = new EntityMonster(npcMonsterExcel, monsterInfo.clonePos());
EntityMonster monster = new EntityMonster(this, npcMonsterExcel, monsterInfo.clonePos());
monster.getRot().setY((int) (monsterInfo.getRotY() * 1000f));
monster.setInstId(monsterInfo.getID());
monster.setEventId(monsterInfo.getEventID());
@@ -112,7 +118,7 @@ public class Scene {
}
// Create prop from prop info
EntityProp prop = new EntityProp(propExcel, propInfo.clonePos());
EntityProp prop = new EntityProp(this, propExcel, propInfo.clonePos());
prop.setState(propInfo.getState());
prop.getRot().set(
(int) (propInfo.getRotX() * 1000f),
@@ -127,10 +133,15 @@ public class Scene {
// Open simulated universe
prop.setState(PropState.Open);
} else if (prop.getExcel().getPropType() == PropType.PROP_SPRING) {
// Teleport anchors cache
// Cache teleport anchors
this.getHealingSprings().add(prop);
}
// Add trigger
if (propInfo.getTrigger() != null) {
this.getTriggers().add(propInfo.getTrigger());
}
// Add to monsters
this.addEntity(prop);
}
@@ -155,7 +166,7 @@ public class Scene {
if (haseDuplicateNpcId) continue;
// Create npc from npc info
EntityNpc npc = new EntityNpc(npcInfo.getNPCID(), npcInfo.clonePos());
EntityNpc npc = new EntityNpc(this, npcInfo.getNPCID(), npcInfo.clonePos());
npc.getRot().setY((int) (npcInfo.getRotY() * 1000f));
npc.setInstId(npcInfo.getID());
npc.setGroupId(group.getId());
@@ -165,6 +176,9 @@ public class Scene {
}
}
}
// Done
this.loaded = true;
}
public void setEntryId(int entryId) {
@@ -175,8 +189,8 @@ public class Scene {
return ++lastEntityId;
}
public GameEntity getEntityById(int id) {
return this.entities.get(id);
public synchronized GameEntity getEntityById(int id) {
return this.getEntities().get(id);
}
public void syncLineup() {
@@ -237,15 +251,24 @@ public class Scene {
player.sendPacket(new PacketActivateFarmElementScRsp(entityId, worldLevel));
return true;
}
// TODO
public void fireTrigger(PropTriggerType type, int param) {
for (PropTrigger trigger : this.getTriggers()) {
if (trigger.shouldRun(param)) {
trigger.run(this);
}
}
}
public synchronized void addEntity(GameEntity entity) {
// Dont add if monster id already exists
if (entity.getEntityId() != 0) return;
// Set entity id and add monster to entity map
entity.setEntityId(this.getNextEntityId());
this.entities.put(entity.getEntityId(), entity);
this.getEntities().put(entity.getEntityId(), entity);
// Entity add callback
entity.onAdd(this);
entity.onAdd();
}
public synchronized void removeEntity(GameEntity entity) {
@@ -253,17 +276,17 @@ public class Scene {
}
public synchronized void removeEntity(int entityId) {
GameEntity entity = this.entities.remove(entityId);
GameEntity entity = this.getEntities().remove(entityId);
if (entity != null) {
// Entity remove callback
entity.onRemove(this);
entity.onRemove();
// Send packet
player.sendPacket(new PacketSceneGroupRefreshScNotify(null, entity));
}
}
public SceneInfo toProto() {
public synchronized SceneInfo toProto() {
// Proto
var proto = SceneInfo.newInstance()
.setWorldId(this.getExcel().getWorldID())
@@ -293,7 +316,7 @@ public class Scene {
groups.put(0, playerGroup);
// Add rest of the entities to groups
for (var entity : entities.values()) {
for (var entity : getEntities().values()) {
var group = groups.computeIfAbsent(entity.getGroupId(), i -> SceneEntityGroupInfo.newInstance().setGroupId(i));
group.addEntityList(entity.toSceneEntityProto());
}

View File

@@ -2,6 +2,8 @@ package emu.lunarcore.game.scene.entity;
import emu.lunarcore.data.excel.NpcMonsterExcel;
import emu.lunarcore.data.excel.StageExcel;
import emu.lunarcore.game.scene.Scene;
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;
@@ -19,11 +21,13 @@ public class EntityMonster implements GameEntity {
@Setter private int eventId;
@Setter private int overrideStageId;
private NpcMonsterExcel excel;
private Position pos;
private Position rot;
private final Scene scene;
private final NpcMonsterExcel excel;
private final Position pos;
private final Position rot;
public EntityMonster(NpcMonsterExcel excel, Position pos) {
public EntityMonster(Scene scene, NpcMonsterExcel excel, Position pos) {
this.scene = scene;
this.excel = excel;
this.pos = pos;
this.rot = new Position();
@@ -36,6 +40,12 @@ public class EntityMonster implements GameEntity {
return this.overrideStageId;
}
}
@Override
public void onRemove() {
// Try to fire any triggers
getScene().fireTrigger(PropTriggerType.MONSTER_DIE, this.getGroupId());
}
@Override
public SceneEntityInfo toSceneEntityProto() {

View File

@@ -1,5 +1,6 @@
package emu.lunarcore.game.scene.entity;
import emu.lunarcore.game.scene.Scene;
import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
import emu.lunarcore.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.lunarcore.proto.SceneNpcInfoOuterClass.SceneNpcInfo;
@@ -14,10 +15,12 @@ public class EntityNpc implements GameEntity {
@Setter private int instId;
@Setter private int npcId;
private Position pos;
private Position rot;
private final Scene scene;
private final Position pos;
private final Position rot;
public EntityNpc(int npcId, Position pos) {
public EntityNpc(Scene scene, int npcId, Position pos) {
this.scene = scene;
this.npcId = npcId;
this.pos = pos;
this.rot = new Position();

View File

@@ -6,6 +6,7 @@ import emu.lunarcore.game.scene.Scene;
import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
import emu.lunarcore.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.lunarcore.proto.ScenePropInfoOuterClass.ScenePropInfo;
import emu.lunarcore.server.packet.send.PacketSceneGroupRefreshScNotify;
import emu.lunarcore.util.Position;
import lombok.Getter;
import lombok.Setter;
@@ -15,13 +16,15 @@ public class EntityProp implements GameEntity {
@Setter private int entityId;
@Setter private int groupId;
@Setter private int instId;
@Setter private PropState state;
private PropState state;
private PropExcel excel;
private Position pos;
private Position rot;
private final Scene scene;
private final PropExcel excel;
private final Position pos;
private final Position rot;
public EntityProp(PropExcel excel, Position pos) {
public EntityProp(Scene scene, PropExcel excel, Position pos) {
this.scene = scene;
this.excel = excel;
this.pos = pos;
this.rot = new Position();
@@ -32,8 +35,17 @@ public class EntityProp implements GameEntity {
return excel.getId();
}
public void setState(PropState state) {
// Set state
this.state = state;
// Sync state update to client
if (this.getScene().isLoaded()) {
this.getScene().getPlayer().sendPacket(new PacketSceneGroupRefreshScNotify(this, null));
}
}
@Override
public void onRemove(Scene scene) {
public void onRemove() {
if (excel.isRecoverMp()) {
scene.getPlayer().getLineupManager().addMp(2);
} else if (excel.isRecoverHp()) {

View File

@@ -4,10 +4,12 @@ import emu.lunarcore.game.scene.Scene;
import emu.lunarcore.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
public interface GameEntity {
public int getEntityId();
public void setEntityId(int id);
public Scene getScene();
public default int getGroupId() {
return 0;
@@ -17,11 +19,11 @@ public interface GameEntity {
return 0;
}
public default void onAdd(Scene scene) {
public default void onAdd() {
}
public default void onRemove(Scene scene) {
public default void onRemove() {
}

View File

@@ -0,0 +1,13 @@
package emu.lunarcore.game.scene.triggers;
import emu.lunarcore.game.scene.Scene;
public abstract class PropTrigger {
public abstract PropTriggerType getType();
public abstract boolean shouldRun(int param);
public abstract void run(Scene scene);
}

View File

@@ -0,0 +1,5 @@
package emu.lunarcore.game.scene.triggers;
public enum PropTriggerType {
MONSTER_DIE;
}

View File

@@ -0,0 +1,44 @@
package emu.lunarcore.game.scene.triggers;
import emu.lunarcore.game.enums.PropState;
import emu.lunarcore.game.enums.PropType;
import emu.lunarcore.game.scene.Scene;
import emu.lunarcore.game.scene.entity.EntityProp;
import emu.lunarcore.game.scene.entity.GameEntity;
import lombok.Getter;
@Getter
public class TriggerOpenTreasureWhenMonsterDie extends PropTrigger {
private int groupId;
public TriggerOpenTreasureWhenMonsterDie(int groupId) {
this.groupId = groupId;
}
@Override
public PropTriggerType getType() {
return PropTriggerType.MONSTER_DIE;
}
@Override
public boolean shouldRun(int param) {
return this.groupId == param;
}
@Override
public void run(Scene scene) {
synchronized (scene) {
for (GameEntity entity : scene.getEntities().values()) {
if (entity.getGroupId() != this.groupId) {
continue;
}
if (entity instanceof EntityProp prop) {
if (prop.getExcel().getPropType() == PropType.PROP_TREASURE_CHEST) {
prop.setState(PropState.ChestClosed);
}
}
}
}
}
}