Implement challenge rewards

This commit is contained in:
Melledy
2023-11-05 14:17:38 -08:00
parent 285d067fd6
commit 4a11e06169
17 changed files with 1620 additions and 9 deletions

View File

@@ -15,6 +15,7 @@ public class GameConstants {
public static final String DEFAULT_NAME = "Trailblazer";
public static final int TRAILBLAZER_AVATAR_ID = 8001;
public static final int MAX_TRAILBLAZER_LEVEL = 70;
public static final int MATERIAL_HCOIN_ID = 1; // Material id for jades. DO NOT CHANGE
public static final int MATERIAL_COIN_ID = 2; // Material id for credits. DO NOT CHANGE
public static final int MAX_STAMINA = 240;
public static final int MAX_AVATARS_IN_TEAM = 4;

View File

@@ -28,10 +28,13 @@ public class GameData {
@Getter private static Int2ObjectMap<MapEntranceExcel> mapEntranceExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<HeroExcel> heroExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<ShopExcel> shopExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<RewardExcel> rewardExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<ItemComposeExcel> itemComposeExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<ChallengeGroupExcel> challengeGroupExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<ChallengeExcel> challengeExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<ChallengeTargetExcel> challengeTargetExcelMap = new Int2ObjectOpenHashMap<>();
private static Int2ObjectMap<ChallengeRewardExcel> challengeRewardExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<RogueManagerExcel> rogueManagerExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<RogueTalentExcel> rogueTalentExcelMap = new Int2ObjectOpenHashMap<>();
@@ -135,4 +138,8 @@ public class GameData {
public static MonsterDropExcel getMonsterDropExcel(int monsterNpcId, int worldLevel) {
return monsterDropExcelMap.get((monsterNpcId << 4) + worldLevel);
}
public static ChallengeRewardExcel getChallengeRewardExcel(int groupId, int starCount) {
return challengeRewardExcelMap.get((groupId << 16) + starCount);
}
}

View File

@@ -10,6 +10,7 @@ import lombok.Getter;
@ResourceType(name = {"ChallengeMazeConfig.json"})
public class ChallengeExcel extends GameResource {
private int ID;
private int GroupID;
private int MapEntranceID;
private int StageNum;
private int ChallengeCountDown;

View File

@@ -0,0 +1,17 @@
package emu.lunarcore.data.excel;
import emu.lunarcore.data.GameResource;
import emu.lunarcore.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = {"ChallengeGroupConfig.json"})
public class ChallengeGroupExcel extends GameResource {
private int GroupID;
private int RewardLineGroupID;
@Override
public int getId() {
return GroupID;
}
}

View File

@@ -0,0 +1,18 @@
package emu.lunarcore.data.excel;
import emu.lunarcore.data.GameResource;
import emu.lunarcore.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = {"ChallengeMazeRewardLine.json"})
public class ChallengeRewardExcel extends GameResource {
private int GroupID;
private int StarCount;
private int RewardID;
@Override
public int getId() {
return (GroupID << 16) + StarCount;
}
}

View File

@@ -0,0 +1,57 @@
package emu.lunarcore.data.excel;
import java.util.ArrayList;
import java.util.List;
import emu.lunarcore.GameConstants;
import emu.lunarcore.data.GameResource;
import emu.lunarcore.data.ResourceType;
import emu.lunarcore.data.common.ItemParam;
import lombok.Getter;
@Getter
@ResourceType(name = {"RewardData.json"})
public class RewardExcel extends GameResource {
private int RewardID;
private int Hcoin;
private int ItemID_1;
private int Count_1;
private int ItemID_2;
private int Count_2;
private int ItemID_3;
private int Count_3;
private int ItemID_4;
private int Count_4;
private int ItemID_5;
private int Count_5;
private transient List<ItemParam> rewards;
@Override
public int getId() {
return RewardID;
}
@Override
public void onLoad() {
this.rewards = new ArrayList<>();
if (Hcoin > 0) {
this.rewards.add(new ItemParam(GameConstants.MATERIAL_HCOIN_ID, Hcoin));
}
if (ItemID_1 > 0) {
this.rewards.add(new ItemParam(ItemID_1, Count_1));
} if (ItemID_2 > 0) {
this.rewards.add(new ItemParam(ItemID_2, Count_2));
} if (ItemID_3 > 0) {
this.rewards.add(new ItemParam(ItemID_3, Count_3));
} if (ItemID_4 > 0) {
this.rewards.add(new ItemParam(ItemID_4, Count_4));
} if (ItemID_5 > 0) {
this.rewards.add(new ItemParam(ItemID_5, Count_5));
}
}
}

View File

@@ -0,0 +1,57 @@
package emu.lunarcore.game.challenge;
import org.bson.types.ObjectId;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import dev.morphia.annotations.Indexed;
import emu.lunarcore.LunarCore;
import emu.lunarcore.game.player.Player;
import emu.lunarcore.proto.ChallengeRewardOuterClass.ChallengeReward;
import lombok.Getter;
@Getter
@Entity(value = "challengeReward", useDiscriminator = false)
public class ChallengeGroupReward {
@Id
private ObjectId id;
@Indexed
private int ownerUid;
private int groupId;
private long takenStars;
@Deprecated // Morphia
public ChallengeGroupReward() {}
public ChallengeGroupReward(Player player, int groupId) {
this.ownerUid = player.getUid();
this.groupId = groupId;
}
public boolean hasTakenReward(int starCount) {
return (takenStars & (1L << starCount)) != 0;
}
public void setTakenReward(int starCount) {
this.takenStars |= 1L << starCount;
this.save();
}
public ChallengeReward toProto() {
var proto = ChallengeReward.newInstance()
.setGroupId(this.getGroupId())
.setTakenChallengeReward(this.getTakenStars());
return proto;
}
public void delete() {
LunarCore.getGameDatabase().delete(this);
}
public void save() {
LunarCore.getGameDatabase().save(this);
}
}

View File

@@ -21,6 +21,7 @@ public class ChallengeHistory {
private int ownerUid;
private int challengeId;
private int groupId;
private int takenReward;
private int stars;
@@ -36,6 +37,14 @@ public class ChallengeHistory {
this.stars = Math.max(this.stars, stars);
}
public int getTotalStars() {
int total = 0;
for (int i = 0; i < 3; i++) {
total += (this.stars & (1 << i)) != 0 ? 1 : 0;
}
return total;
}
public Challenge toProto() {
var proto = Challenge.newInstance()
.setChallengeId(this.getChallengeId())

View File

@@ -1,10 +1,12 @@
package emu.lunarcore.game.challenge;
import java.util.List;
import java.util.stream.Stream;
import emu.lunarcore.LunarCore;
import emu.lunarcore.data.GameData;
import emu.lunarcore.data.excel.ChallengeExcel;
import emu.lunarcore.game.inventory.GameItem;
import emu.lunarcore.game.player.BasePlayerManager;
import emu.lunarcore.game.player.Player;
import emu.lunarcore.game.player.lineup.PlayerLineup;
@@ -17,10 +19,12 @@ import lombok.Getter;
@Getter
public class ChallengeManager extends BasePlayerManager {
private Int2ObjectMap<ChallengeHistory> history;
private Int2ObjectMap<ChallengeGroupReward> takenRewards;
public ChallengeManager(Player player) {
super(player);
this.history = new Int2ObjectOpenHashMap<>();
this.takenRewards = new Int2ObjectOpenHashMap<>();
}
public void startChallenge(int challengeId) {
@@ -84,7 +88,7 @@ public class ChallengeManager extends BasePlayerManager {
getPlayer().sendPacket(new PacketStartChallengeScRsp(getPlayer(), challengeId));
}
public void addHistory(int challengeId, int stars) {
public synchronized void addHistory(int challengeId, int stars) {
// Dont write challenge history if the player didnt get any stars
if (stars <= 0) return;
@@ -96,11 +100,66 @@ public class ChallengeManager extends BasePlayerManager {
info.save();
}
public synchronized List<GameItem> takeRewards(int groupId, int starCount) {
// Get excels
var challengeGroup = GameData.getChallengeGroupExcelMap().get(groupId);
if (challengeGroup == null) return null;
var challengeReward = GameData.getChallengeRewardExcel(challengeGroup.getRewardLineGroupID(), starCount);
if (challengeReward == null) return null;
var rewardExcel = GameData.getRewardExcelMap().get(challengeReward.getRewardID());
if (rewardExcel == null) return null;
// Validate
int totalStars = 0;
for (ChallengeHistory ch : this.getHistory().values()) {
// Legacy compatibility
if (ch.getGroupId() == 0) {
var challengeExcel = GameData.getChallengeExcelMap().get(ch.getChallengeId());
if (challengeExcel == null) continue;
ch.setGroupId(challengeExcel.getGroupID());
ch.save();
}
// Add total stars
if (ch.getGroupId() == groupId) {
totalStars += ch.getTotalStars();
}
}
// Check if the player has enough stars
if (totalStars < starCount) {
return null;
}
// Get reward info
var reward = this.getTakenRewards().computeIfAbsent(groupId, id -> new ChallengeGroupReward(getPlayer(), groupId));
if (reward.hasTakenReward(starCount)) {
return null;
}
reward.setTakenReward(starCount);
// Add items to inventory
return getPlayer().getInventory().addItemParams(rewardExcel.getRewards());
}
public void loadFromDatabase() {
Stream<ChallengeHistory> stream = LunarCore.getGameDatabase().getObjects(ChallengeHistory.class, "ownerUid", this.getPlayer().getUid());
// Load challenge history
Stream<ChallengeHistory> stream = LunarCore.getGameDatabase().getObjects(ChallengeHistory.class, "ownerUid", getPlayer().getUid());
stream.forEach(info -> {
this.getHistory().put(info.getChallengeId(), info);
});
// Load challenge rewards
Stream<ChallengeGroupReward> stream2 = LunarCore.getGameDatabase().getObjects(ChallengeGroupReward.class, "ownerUid", getPlayer().getUid());
stream2.forEach(info -> {
this.getTakenRewards().put(info.getGroupId(), info);
});
}
}

View File

@@ -142,6 +142,12 @@ public class Inventory extends BasePlayerManager {
return results;
}
public List<GameItem> addItemParams(Collection<ItemParam> params) {
// TODO handle params if they are equipment or relics
List<GameItem> items = params.stream().map(param -> new GameItem(param.getId(), param.getCount())).toList();
return addItems(items, false);
}
private synchronized GameItem putItem(GameItem item) {
// Dont add items that dont have a valid item definition.

View File

@@ -0,0 +1,24 @@
package emu.lunarcore.server.packet.recv;
import java.util.List;
import emu.lunarcore.game.inventory.GameItem;
import emu.lunarcore.proto.TakeChallengeRewardCsReqOuterClass.TakeChallengeRewardCsReq;
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.PacketTakeChallengeRewardScRsp;
@Opcodes(CmdId.TakeChallengeRewardCsReq)
public class HandlerTakeChallengeRewardCsReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] data) throws Exception {
var req = TakeChallengeRewardCsReq.parseFrom(data);
List<GameItem> rewards = session.getPlayer().getChallengeManager().takeRewards(req.getGroupId(), req.getStarCount());
session.send(new PacketTakeChallengeRewardScRsp(req.getGroupId(), req.getStarCount(), rewards));
}
}

View File

@@ -16,6 +16,10 @@ public class PacketGetChallengeScRsp extends BasePacket {
data.addChallengeList(history.toProto());
}
for (var reward : player.getChallengeManager().getTakenRewards().values()) {
data.addChallengeRewardList(reward.toProto());
}
this.setData(data);
}
}

View File

@@ -0,0 +1,30 @@
package emu.lunarcore.server.packet.send;
import java.util.Collection;
import emu.lunarcore.game.inventory.GameItem;
import emu.lunarcore.proto.TakeChallengeRewardScRspOuterClass.TakeChallengeRewardScRsp;
import emu.lunarcore.server.packet.BasePacket;
import emu.lunarcore.server.packet.CmdId;
public class PacketTakeChallengeRewardScRsp extends BasePacket {
public PacketTakeChallengeRewardScRsp(int groupId, int starCount, Collection<GameItem> rewards) {
super(CmdId.TakeChallengeRewardScRsp);
var data = TakeChallengeRewardScRsp.newInstance();
if (rewards != null) {
data.setGroupId(groupId)
.setStarCount(starCount);
for (GameItem item : rewards) {
data.getMutableReward().addItemList(item.toProto());
}
} else {
data.setRetcode(1);
}
this.setData(data);
}
}