Battles with monsters in mazes now drop items

This commit is contained in:
Melledy
2023-10-04 23:58:34 -07:00
parent 08a62e3f6e
commit 8bb7672a6b
6 changed files with 115 additions and 7 deletions

View File

@@ -36,6 +36,7 @@ public class GameData {
private static Int2ObjectMap<EquipmentPromotionExcel> equipmentPromotionExcelMap = new Int2ObjectOpenHashMap<>(); private static Int2ObjectMap<EquipmentPromotionExcel> equipmentPromotionExcelMap = new Int2ObjectOpenHashMap<>();
private static Int2ObjectMap<MazeBuffExcel> mazeBuffExcelMap = new Int2ObjectOpenHashMap<>(); private static Int2ObjectMap<MazeBuffExcel> mazeBuffExcelMap = new Int2ObjectOpenHashMap<>();
private static Int2ObjectMap<CocoonExcel> cocoonExcelMap = new Int2ObjectOpenHashMap<>(); private static Int2ObjectMap<CocoonExcel> cocoonExcelMap = new Int2ObjectOpenHashMap<>();
private static Int2ObjectMap<MonsterDropExcel> monsterDropExcelMap = new Int2ObjectOpenHashMap<>();
private static Int2ObjectMap<PlayerLevelExcel> playerLevelExcelMap = new Int2ObjectOpenHashMap<>(); private static Int2ObjectMap<PlayerLevelExcel> playerLevelExcelMap = new Int2ObjectOpenHashMap<>();
private static Int2ObjectMap<ExpTypeExcel> expTypeExcelMap = new Int2ObjectOpenHashMap<>(); private static Int2ObjectMap<ExpTypeExcel> expTypeExcelMap = new Int2ObjectOpenHashMap<>();
@@ -117,4 +118,8 @@ public class GameData {
public static CocoonExcel getCocoonExcel(int cocoonId, int worldLevel) { public static CocoonExcel getCocoonExcel(int cocoonId, int worldLevel) {
return cocoonExcelMap.get((cocoonId << 8) + worldLevel); return cocoonExcelMap.get((cocoonId << 8) + worldLevel);
} }
public static MonsterDropExcel getMonsterDropExcel(int monsterNpcId, int worldLevel) {
return monsterDropExcelMap.get((monsterNpcId << 4) + worldLevel);
}
} }

View File

@@ -0,0 +1,24 @@
package emu.lunarcore.data.excel;
import java.util.List;
import emu.lunarcore.data.GameResource;
import emu.lunarcore.data.ResourceType;
import emu.lunarcore.data.common.ItemParam;
import lombok.Getter;
@Getter
@ResourceType(name = {"MonsterDrop.json"})
public class MonsterDropExcel extends GameResource {
private int MonsterTemplateID;
private int WorldLevel;
private int AvatarExpReward;
private List<ItemParam> DisplayItemList;
@Override
public int getId() {
return (MonsterTemplateID << 4) + WorldLevel;
}
}

View File

@@ -5,10 +5,12 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import emu.lunarcore.data.GameData; import emu.lunarcore.data.GameData;
import emu.lunarcore.data.common.ItemParam;
import emu.lunarcore.data.excel.MazeBuffExcel; import emu.lunarcore.data.excel.MazeBuffExcel;
import emu.lunarcore.data.excel.StageExcel; import emu.lunarcore.data.excel.StageExcel;
import emu.lunarcore.game.avatar.GameAvatar; import emu.lunarcore.game.avatar.GameAvatar;
import emu.lunarcore.game.enums.StageType; import emu.lunarcore.game.enums.StageType;
import emu.lunarcore.game.inventory.GameItem;
import emu.lunarcore.game.player.Player; import emu.lunarcore.game.player.Player;
import emu.lunarcore.game.player.PlayerLineup; import emu.lunarcore.game.player.PlayerLineup;
import emu.lunarcore.game.scene.entity.EntityMonster; import emu.lunarcore.game.scene.entity.EntityMonster;
@@ -17,6 +19,7 @@ import emu.lunarcore.proto.SceneMonsterOuterClass.SceneMonster;
import emu.lunarcore.proto.SceneMonsterWaveOuterClass.SceneMonsterWave; import emu.lunarcore.proto.SceneMonsterWaveOuterClass.SceneMonsterWave;
import emu.lunarcore.util.Utils; import emu.lunarcore.util.Utils;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.ints.IntList;
import lombok.Getter; import lombok.Getter;
@@ -28,6 +31,7 @@ public class Battle {
private final List<EntityMonster> npcMonsters; private final List<EntityMonster> npcMonsters;
private final List<MazeBuff> buffs; private final List<MazeBuff> buffs;
private final List<StageExcel> stages; private final List<StageExcel> stages;
private final List<GameItem> drops;
private final long timestamp; private final long timestamp;
private Battle(Player player, PlayerLineup lineup) { private Battle(Player player, PlayerLineup lineup) {
@@ -37,6 +41,7 @@ public class Battle {
this.npcMonsters = new ArrayList<>(); this.npcMonsters = new ArrayList<>();
this.buffs = new ArrayList<>(); this.buffs = new ArrayList<>();
this.stages = new ArrayList<>(); this.stages = new ArrayList<>();
this.drops = new ArrayList<>();
this.timestamp = System.currentTimeMillis(); this.timestamp = System.currentTimeMillis();
} }
@@ -84,6 +89,8 @@ public class Battle {
return count; return count;
} }
// Battle buffs
public MazeBuff addBuff(int buffId, int ownerIndex) { public MazeBuff addBuff(int buffId, int ownerIndex) {
return addBuff(buffId, ownerIndex, 0xffffffff); return addBuff(buffId, ownerIndex, 0xffffffff);
} }
@@ -102,6 +109,51 @@ public class Battle {
this.buffs.clear(); this.buffs.clear();
} }
// Drops
public void calculateDrops() {
// TODO this isnt the right way drops are calculated on the official server... but its good enough for now
if (this.getNpcMonsters().size() == 0) {
return;
}
var dropMap = new Int2IntOpenHashMap();
// Get drops from monsters
for (EntityMonster monster : this.getNpcMonsters()) {
var dropExcel = GameData.getMonsterDropExcel(monster.getExcel().getId(), monster.getWorldLevel());
if (dropExcel == null || dropExcel.getDisplayItemList() == null) {
continue;
}
for (ItemParam param : dropExcel.getDisplayItemList()) {
int id = param.getId();
int count = Utils.randomRange(0, 3);
if (id == 2) {
count = dropExcel.getAvatarExpReward();
}
dropMap.put(id, count + dropMap.get(id));
}
}
for (var entry : dropMap.int2IntEntrySet()) {
if (entry.getIntValue() <= 0) {
continue;
}
// Create item and add it to player
GameItem item = new GameItem(entry.getIntKey(), entry.getIntValue());
if (getPlayer().getInventory().addItem(item)) {
this.getDrops().add(item);
}
}
}
// Serialization
public SceneBattleInfo toProto() { public SceneBattleInfo toProto() {
// Build battle info // Build battle info
var proto = SceneBattleInfo.newInstance() var proto = SceneBattleInfo.newInstance()

View File

@@ -179,10 +179,10 @@ public class BattleService extends BaseGameService {
player.sendPacket(new PacketStartCocoonStageScRsp(battle, cocoonId, wave)); player.sendPacket(new PacketStartCocoonStageScRsp(battle, cocoonId, wave));
} }
public void finishBattle(Player player, BattleEndStatus result, RepeatedMessage<AvatarBattleInfo> battleAvatars) { public Battle finishBattle(Player player, BattleEndStatus result, RepeatedMessage<AvatarBattleInfo> battleAvatars) {
// Sanity check to make sure player is in a battle // Sanity check to make sure player is in a battle
if (!player.isInBattle()) { if (!player.isInBattle()) {
return; return null;
} }
// Get battle object and setup variables // Get battle object and setup variables
@@ -199,6 +199,8 @@ public class BattleService extends BaseGameService {
for (var monster : battle.getNpcMonsters()) { for (var monster : battle.getNpcMonsters()) {
player.getScene().removeEntity(monster); player.getScene().removeEntity(monster);
} }
// Drops
battle.calculateDrops();
} }
case BATTLE_END_LOSE -> { case BATTLE_END_LOSE -> {
// Set avatar hp to 20% if the player's party is downed // Set avatar hp to 20% if the player's party is downed
@@ -247,6 +249,7 @@ public class BattleService extends BaseGameService {
// Done - Clear battle object from player // Done - Clear battle object from player
player.setBattle(null); player.setBattle(null);
return battle;
} }
public void reEnterBattle(Player player, int stageId) { public void reEnterBattle(Player player, int stageId) {

View File

@@ -1,5 +1,6 @@
package emu.lunarcore.server.packet.recv; package emu.lunarcore.server.packet.recv;
import emu.lunarcore.game.battle.Battle;
import emu.lunarcore.proto.PVEBattleResultCsReqOuterClass.PVEBattleResultCsReq; import emu.lunarcore.proto.PVEBattleResultCsReqOuterClass.PVEBattleResultCsReq;
import emu.lunarcore.server.game.GameSession; import emu.lunarcore.server.game.GameSession;
import emu.lunarcore.server.packet.CmdId; import emu.lunarcore.server.packet.CmdId;
@@ -14,13 +15,17 @@ public class HandlerPVEBattleResultCsReq extends PacketHandler {
public void handle(GameSession session, byte[] header, byte[] data) throws Exception { public void handle(GameSession session, byte[] header, byte[] data) throws Exception {
var req = PVEBattleResultCsReq.parseFrom(data); var req = PVEBattleResultCsReq.parseFrom(data);
session.getServer().getBattleService().finishBattle( Battle battle = session.getServer().getBattleService().finishBattle(
session.getPlayer(), session.getPlayer(),
req.getEndStatus(), req.getEndStatus(),
req.getStt().getBattleAvatarList() req.getStt().getBattleAvatarList()
); );
session.send(new PacketPVEBattleResultScRsp(req)); if (battle != null) {
session.send(new PacketPVEBattleResultScRsp(req, battle));
} else {
session.send(new PacketPVEBattleResultScRsp());
}
} }
} }

View File

@@ -1,5 +1,7 @@
package emu.lunarcore.server.packet.send; package emu.lunarcore.server.packet.send;
import emu.lunarcore.game.battle.Battle;
import emu.lunarcore.game.inventory.GameItem;
import emu.lunarcore.proto.ItemListOuterClass.ItemList; import emu.lunarcore.proto.ItemListOuterClass.ItemList;
import emu.lunarcore.proto.PVEBattleResultCsReqOuterClass.PVEBattleResultCsReq; import emu.lunarcore.proto.PVEBattleResultCsReqOuterClass.PVEBattleResultCsReq;
import emu.lunarcore.proto.PVEBattleResultScRspOuterClass.PVEBattleResultScRsp; import emu.lunarcore.proto.PVEBattleResultScRspOuterClass.PVEBattleResultScRsp;
@@ -7,14 +9,31 @@ import emu.lunarcore.server.packet.BasePacket;
import emu.lunarcore.server.packet.CmdId; import emu.lunarcore.server.packet.CmdId;
public class PacketPVEBattleResultScRsp extends BasePacket { public class PacketPVEBattleResultScRsp extends BasePacket {
public PacketPVEBattleResultScRsp(PVEBattleResultCsReq req) { public PacketPVEBattleResultScRsp() {
super(CmdId.PVEBattleResultScRsp); super(CmdId.PVEBattleResultScRsp);
var data = PVEBattleResultScRsp.newInstance()
.setRetcode(1);
this.setData(data);
}
public PacketPVEBattleResultScRsp(PVEBattleResultCsReq req, Battle battle) {
super(CmdId.PVEBattleResultScRsp);
// Item drop list data
ItemList dropData = ItemList.newInstance();
for (GameItem drop : battle.getDrops()) {
dropData.addItemList(drop.toProto());
}
// Battle result
var data = PVEBattleResultScRsp.newInstance() var data = PVEBattleResultScRsp.newInstance()
.setUnk1(ItemList.newInstance()) .setUnk1(ItemList.newInstance())
.setUnk2(ItemList.newInstance())
.setUnk3(ItemList.newInstance()) .setUnk3(ItemList.newInstance())
.setDropData(dropData)
.setResVersion(Integer.toString(req.getClientResVersion())) .setResVersion(Integer.toString(req.getClientResVersion()))
.setBinVersion("") .setBinVersion("")
.setBattleId(req.getBattleId()) .setBattleId(req.getBattleId())