mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-22 06:31:26 +00:00
Merge remote-tracking branch 'origin/development' into development
This commit is contained in:
commit
cfccb2d991
@ -404,6 +404,10 @@ public final class GameData {
|
||||
private static final Int2ObjectMap<WeaponPromoteData> weaponPromoteDataMap =
|
||||
new Int2ObjectOpenHashMap<>();
|
||||
|
||||
@Getter
|
||||
private static final Int2ObjectMap<StatuePromoteData> statuePromoteDataMap =
|
||||
new Int2ObjectOpenHashMap<>();
|
||||
|
||||
@Getter
|
||||
private static final Int2ObjectMap<WeatherData> weatherDataMap = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
@ -567,6 +571,10 @@ public final class GameData {
|
||||
return weaponPromoteDataMap.get((promoteId << 8) + promoteLevel);
|
||||
}
|
||||
|
||||
public static StatuePromoteData getStatuePromoteData(int cityId, int promoteLevel) {
|
||||
return statuePromoteDataMap.get((cityId << 8) + promoteLevel);
|
||||
}
|
||||
|
||||
public static ReliquaryLevelData getRelicLevelData(int rankLevel, int level) {
|
||||
return reliquaryLevelDataMap.get((rankLevel << 8) + level);
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
package emu.grasscutter.data.excels;
|
||||
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
import emu.grasscutter.data.common.ItemParamData;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@ResourceType(name = "StatuePromoteExcelConfigData.json")
|
||||
public class StatuePromoteData extends GameResource {
|
||||
@Getter @Setter private int level;
|
||||
@Getter @Setter private int cityId;
|
||||
@Getter @Setter private ItemParamData[] costItems;
|
||||
@Getter @Setter private int[] rewardIdList;
|
||||
@Getter @Setter private int stamina;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return (cityId << 8) + level;
|
||||
}
|
||||
}
|
28
src/main/java/emu/grasscutter/game/city/CityInfoData.java
Normal file
28
src/main/java/emu/grasscutter/game/city/CityInfoData.java
Normal file
@ -0,0 +1,28 @@
|
||||
package emu.grasscutter.game.city;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import emu.grasscutter.net.proto.CityInfoOuterClass.CityInfo;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
public class CityInfoData {
|
||||
@Getter @Setter private int cityId;
|
||||
|
||||
@Getter @Setter
|
||||
private int level = 1; // level of the city (include level SotS, level Frostbearing Trees, etc.)
|
||||
|
||||
@Getter @Setter private int numCrystal = 0; // number of crystals in the city
|
||||
|
||||
public CityInfoData(int cityId) {
|
||||
this.cityId = cityId;
|
||||
}
|
||||
|
||||
public CityInfo toProto() {
|
||||
return CityInfo.newBuilder()
|
||||
.setCityId(cityId)
|
||||
.setLevel(level)
|
||||
.setCrystalNum(numCrystal)
|
||||
.build();
|
||||
}
|
||||
}
|
@ -81,7 +81,7 @@ public final class DungeonManager {
|
||||
}
|
||||
|
||||
public boolean isFinishedSuccessfully() {
|
||||
if (passConfigData.getLogicType() == null) return false;
|
||||
if (passConfigData.getConds() == null) return false;
|
||||
return LogicType.calculate(passConfigData.getLogicType(), finishedConditions);
|
||||
}
|
||||
|
||||
@ -286,14 +286,18 @@ public final class DungeonManager {
|
||||
}
|
||||
|
||||
public void finishDungeon() {
|
||||
// Mark the dungeon has completed for the players.
|
||||
var dungeonId = this.getDungeonData().getId();
|
||||
this.getScene()
|
||||
.getPlayers()
|
||||
.forEach(player -> player.getPlayerProgress().markDungeonAsComplete(dungeonId));
|
||||
this.notifyEndDungeon(true);
|
||||
this.endDungeon(BaseDungeonResult.DungeonEndReason.COMPLETED);
|
||||
}
|
||||
|
||||
notifyEndDungeon(true);
|
||||
endDungeon(BaseDungeonResult.DungeonEndReason.COMPLETED);
|
||||
public void quitDungeon() {
|
||||
this.notifyEndDungeon(false);
|
||||
this.endDungeon(BaseDungeonResult.DungeonEndReason.QUIT);
|
||||
}
|
||||
|
||||
public void failDungeon() {
|
||||
this.notifyEndDungeon(false);
|
||||
this.endDungeon(BaseDungeonResult.DungeonEndReason.FAILED);
|
||||
}
|
||||
|
||||
public void notifyEndDungeon(boolean successfully) {
|
||||
@ -301,8 +305,11 @@ public final class DungeonManager {
|
||||
.getPlayers()
|
||||
.forEach(
|
||||
p -> {
|
||||
// Trigger the fail event if needed.
|
||||
if (!successfully) {
|
||||
// Trigger the fail and success event.
|
||||
if (successfully) {
|
||||
var dungeonId = this.getDungeonData().getId();
|
||||
p.getPlayerProgress().markDungeonAsComplete(dungeonId);
|
||||
} else {
|
||||
p.getQuestManager()
|
||||
.queueEvent(QuestContent.QUEST_CONTENT_FAIL_DUNGEON, dungeonData.getId());
|
||||
}
|
||||
@ -317,16 +324,6 @@ public final class DungeonManager {
|
||||
.callEvent(new ScriptArgs(0, EventType.EVENT_DUNGEON_SETTLE, successfully ? 1 : 0));
|
||||
}
|
||||
|
||||
public void quitDungeon() {
|
||||
notifyEndDungeon(false);
|
||||
endDungeon(BaseDungeonResult.DungeonEndReason.QUIT);
|
||||
}
|
||||
|
||||
public void failDungeon() {
|
||||
notifyEndDungeon(false);
|
||||
endDungeon(BaseDungeonResult.DungeonEndReason.FAILED);
|
||||
}
|
||||
|
||||
public void endDungeon(BaseDungeonResult.DungeonEndReason endReason) {
|
||||
if (scene.getDungeonSettleListeners() != null) {
|
||||
scene.getDungeonSettleListeners().forEach(o -> o.onDungeonSettle(this, endReason));
|
||||
|
@ -150,6 +150,7 @@ public class EntityGadget extends EntityBaseGadget {
|
||||
public void updateState(int state) {
|
||||
if (state == this.getState()) return; // Don't triggers events
|
||||
|
||||
var oldState = this.getState();
|
||||
this.setState(state);
|
||||
ticksSinceChange = getScene().getSceneTimeSeconds();
|
||||
this.getScene().broadcastPacket(new PacketGadgetStateNotify(this, state));
|
||||
@ -157,7 +158,11 @@ public class EntityGadget extends EntityBaseGadget {
|
||||
.getScriptManager()
|
||||
.callEvent(
|
||||
new ScriptArgs(
|
||||
this.getGroupId(), EventType.EVENT_GADGET_STATE_CHANGE, state, this.getConfigId()));
|
||||
this.getGroupId(),
|
||||
EventType.EVENT_GADGET_STATE_CHANGE,
|
||||
state,
|
||||
this.getConfigId())
|
||||
.setParam3(oldState));
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true) // Dont use!
|
||||
|
@ -36,4 +36,9 @@ public class EquipInventoryTab implements InventoryTab {
|
||||
public int getMaxCapacity() {
|
||||
return this.maxCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCountById(int itemId) {
|
||||
return (int) items.stream().filter(item -> item.getItemId() == itemId).count();
|
||||
}
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ public class GameItem {
|
||||
|
||||
public void checkIsNew(Inventory inventory) {
|
||||
// display notification when player obtain new item
|
||||
if (inventory.getItemByGuid(this.itemId) == null) {
|
||||
if (inventory.getItemById(this.itemId) == null) {
|
||||
this.newItem = true;
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ import emu.grasscutter.utils.Utils;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import it.unimi.dsi.fastutil.longs.*;
|
||||
import java.util.*;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.val;
|
||||
|
||||
public class Inventory extends BasePlayerManager implements Iterable<GameItem> {
|
||||
private final Long2ObjectMap<GameItem> store;
|
||||
@ -62,6 +64,24 @@ public class Inventory extends BasePlayerManager implements Iterable<GameItem> {
|
||||
return this.getItems().get(id);
|
||||
}
|
||||
|
||||
@Nullable public InventoryTab getInventoryTabByItemId(int itemId) {
|
||||
val itemData = GameData.getItemDataMap().get(itemId);
|
||||
if (itemData == null || itemData.getItemType() == null) {
|
||||
return null;
|
||||
}
|
||||
return getInventoryTab(itemData.getItemType());
|
||||
}
|
||||
|
||||
@Nullable public GameItem getItemById(int itemId) {
|
||||
val inventoryTab = this.getInventoryTabByItemId(itemId);
|
||||
return inventoryTab != null ? inventoryTab.getItemById(itemId) : null;
|
||||
}
|
||||
|
||||
public int getItemCountById(int itemId) {
|
||||
val inventoryTab = this.getInventoryTabByItemId(itemId);
|
||||
return inventoryTab != null ? inventoryTab.getItemCountById(itemId) : 0;
|
||||
}
|
||||
|
||||
public boolean addItem(int itemId) {
|
||||
return addItem(itemId, 1);
|
||||
}
|
||||
@ -562,7 +582,7 @@ public class Inventory extends BasePlayerManager implements Iterable<GameItem> {
|
||||
tab = getInventoryTab(item.getItemData().getItemType());
|
||||
}
|
||||
|
||||
putItem(item, tab);
|
||||
this.putItem(item, tab);
|
||||
|
||||
// Equip to a character if possible
|
||||
if (item.isEquipped()) {
|
||||
|
@ -10,4 +10,6 @@ public interface InventoryTab {
|
||||
int getSize();
|
||||
|
||||
int getMaxCapacity();
|
||||
|
||||
int getItemCountById(int itemId);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package emu.grasscutter.game.inventory;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.val;
|
||||
|
||||
public class MaterialInventoryTab implements InventoryTab {
|
||||
private final Int2ObjectMap<GameItem> items;
|
||||
@ -36,4 +37,10 @@ public class MaterialInventoryTab implements InventoryTab {
|
||||
public int getMaxCapacity() {
|
||||
return this.maxCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCountById(int itemId) {
|
||||
val item = getItemById(itemId);
|
||||
return item != null ? item.getCount() : 0;
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,24 @@ package emu.grasscutter.game.managers;
|
||||
|
||||
import ch.qos.logback.classic.Logger;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.CityData;
|
||||
import emu.grasscutter.data.excels.RewardData;
|
||||
import emu.grasscutter.game.city.CityInfoData;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.player.BasePlayerManager;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason;
|
||||
import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason;
|
||||
import emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketLevelupCityRsp;
|
||||
import emu.grasscutter.server.packet.send.PacketSceneForceUnlockNotify;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
@ -208,4 +217,91 @@ public class SotSManager extends BasePlayerManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CityData getCityByAreaId(int areaId) {
|
||||
return GameData.getCityDataMap().values().stream()
|
||||
.filter(city -> city.getAreaIdVec().contains(areaId))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public CityInfoData getCityInfo(int cityId) {
|
||||
if (player.getCityInfoData() == null) player.setCityInfoData(new HashMap<>());
|
||||
var cityInfo = player.getCityInfoData().get(cityId);
|
||||
if (cityInfo == null) {
|
||||
cityInfo = new CityInfoData(cityId);
|
||||
player.getCityInfoData().put(cityId, cityInfo);
|
||||
}
|
||||
return cityInfo;
|
||||
}
|
||||
|
||||
public void addCityInfo(CityInfoData cityInfoData) {
|
||||
if (player.getCityInfoData() == null) player.setCityInfoData(new HashMap<>());
|
||||
|
||||
player.getCityInfoData().put(cityInfoData.getCityId(), cityInfoData);
|
||||
}
|
||||
|
||||
public void levelUpSotS(int areaId, int sceneId, int itemNum) {
|
||||
if (itemNum <= 0) return;
|
||||
|
||||
// search city by areaId
|
||||
var city = this.getCityByAreaId(areaId);
|
||||
if (city == null) return;
|
||||
var cityId = city.getCityId();
|
||||
|
||||
// check data level up
|
||||
var cityInfo = this.getCityInfo(cityId);
|
||||
var nextStatuePromoteData = GameData.getStatuePromoteData(cityId, cityInfo.getLevel() + 1);
|
||||
if (nextStatuePromoteData == null) return;
|
||||
var nextLevelCrystal = nextStatuePromoteData.getCostItems()[0].getCount();
|
||||
|
||||
// delete item from inventory
|
||||
var itemNumrequired = Math.min(itemNum, nextLevelCrystal - cityInfo.getNumCrystal());
|
||||
player
|
||||
.getInventory()
|
||||
.removeItemById(nextStatuePromoteData.getCostItems()[0].getId(), itemNumrequired);
|
||||
|
||||
// update number oculi
|
||||
cityInfo.setNumCrystal(cityInfo.getNumCrystal() + itemNumrequired);
|
||||
|
||||
// hanble quest
|
||||
if (itemNumrequired >= 1)
|
||||
player.getQuestManager().queueEvent(QuestContent.QUEST_CONTENT_CITY_LEVEL_UP, cityId, areaId);
|
||||
|
||||
// handle oculi overflow
|
||||
if (cityInfo.getNumCrystal() >= nextLevelCrystal) {
|
||||
cityInfo.setNumCrystal(cityInfo.getNumCrystal() - nextLevelCrystal);
|
||||
cityInfo.setLevel(cityInfo.getLevel() + 1);
|
||||
|
||||
// update max stamina and notify client
|
||||
player.setProperty(
|
||||
PlayerProperty.PROP_MAX_STAMINA,
|
||||
player.getProperty(PlayerProperty.PROP_MAX_STAMINA)
|
||||
+ nextStatuePromoteData.getStamina() * 100,
|
||||
true);
|
||||
|
||||
// Add items to inventory
|
||||
if (nextStatuePromoteData.getRewardIdList() != null) {
|
||||
for (var rewardId : nextStatuePromoteData.getRewardIdList()) {
|
||||
RewardData rewardData = GameData.getRewardDataMap().get(rewardId);
|
||||
if (rewardData == null) continue;
|
||||
|
||||
player
|
||||
.getInventory()
|
||||
.addItemParamDatas(rewardData.getRewardItemList(), ActionReason.CityLevelupReward);
|
||||
}
|
||||
}
|
||||
|
||||
// unlock forcescene
|
||||
player.sendPacket(new PacketSceneForceUnlockNotify(1, true));
|
||||
}
|
||||
|
||||
// update data
|
||||
this.addCityInfo(cityInfo);
|
||||
|
||||
// Packets
|
||||
player.sendPacket(
|
||||
new PacketLevelupCityRsp(
|
||||
sceneId, cityInfo.getLevel(), cityId, cityInfo.getNumCrystal(), areaId, 0));
|
||||
}
|
||||
}
|
||||
|
@ -389,6 +389,9 @@ public class StaminaManager extends BasePlayerManager {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update previous motion state
|
||||
this.previousState = currentState;
|
||||
|
||||
// Update the current state.
|
||||
this.currentState = motionState;
|
||||
// logger.trace(currentState + "\t" + (notifyEntityId == currentAvatarEntityId ? "character" : "vehicle"));
|
||||
@ -417,6 +420,11 @@ public class StaminaManager extends BasePlayerManager {
|
||||
// Internal handler
|
||||
|
||||
private void handleImmediateStamina(GameSession session, @NotNull MotionState motionState) {
|
||||
// Don't double dip on sustained stamina start costs
|
||||
if (previousState == currentState) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (motionState) {
|
||||
case MOTION_STATE_CLIMB ->
|
||||
updateStaminaRelative(session, new Consumption(ConsumptionType.CLIMB_START), true);
|
||||
|
@ -15,6 +15,7 @@ import emu.grasscutter.game.activity.ActivityManager;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.avatar.AvatarStorage;
|
||||
import emu.grasscutter.game.battlepass.BattlePassManager;
|
||||
import emu.grasscutter.game.city.CityInfoData;
|
||||
import emu.grasscutter.game.entity.GameEntity;
|
||||
import emu.grasscutter.game.expedition.ExpeditionInfo;
|
||||
import emu.grasscutter.game.friends.FriendsList;
|
||||
@ -28,7 +29,6 @@ import emu.grasscutter.game.mail.MailHandler;
|
||||
import emu.grasscutter.game.managers.FurnitureManager;
|
||||
import emu.grasscutter.game.managers.ResinManager;
|
||||
import emu.grasscutter.game.managers.SatiationManager;
|
||||
import emu.grasscutter.game.managers.SotSManager;
|
||||
import emu.grasscutter.game.managers.cooking.ActiveCookCompoundData;
|
||||
import emu.grasscutter.game.managers.cooking.CookingCompoundManager;
|
||||
import emu.grasscutter.game.managers.cooking.CookingManager;
|
||||
@ -38,6 +38,7 @@ import emu.grasscutter.game.managers.forging.ActiveForgeData;
|
||||
import emu.grasscutter.game.managers.forging.ForgingManager;
|
||||
import emu.grasscutter.game.managers.mapmark.MapMark;
|
||||
import emu.grasscutter.game.managers.mapmark.MapMarksManager;
|
||||
import emu.grasscutter.game.managers.SotSManager;
|
||||
import emu.grasscutter.game.managers.stamina.StaminaManager;
|
||||
import emu.grasscutter.game.props.*;
|
||||
import emu.grasscutter.game.quest.QuestManager;
|
||||
@ -221,6 +222,8 @@ public class Player implements PlayerHook, FieldFetch {
|
||||
|
||||
@Getter @Setter private ElementType mainCharacterElement = ElementType.None;
|
||||
|
||||
@Getter @Setter private Map<Integer, CityInfoData> cityInfoData; // cityId -> CityData
|
||||
|
||||
@Deprecated
|
||||
@SuppressWarnings({"rawtypes", "unchecked"}) // Morphia only!
|
||||
public Player() {
|
||||
@ -267,6 +270,7 @@ public class Player implements PlayerHook, FieldFetch {
|
||||
this.chatEmojiIdList = new ArrayList<>();
|
||||
this.playerProgress = new PlayerProgress();
|
||||
this.activeQuestTimers = new HashSet<>();
|
||||
this.cityInfoData = new HashMap<>();
|
||||
|
||||
this.attackResults = new LinkedBlockingQueue<>();
|
||||
this.coopRequests = new Int2ObjectOpenHashMap<>();
|
||||
@ -1520,6 +1524,8 @@ public class Player implements PlayerHook, FieldFetch {
|
||||
PropChangeReason.PROP_CHANGE_REASON_PLAYER_ADD_EXP));
|
||||
case PROP_PLAYER_LEVEL -> this.sendPacket(new PacketPlayerPropChangeReasonNotify(this, prop, currentValue, value,
|
||||
PropChangeReason.PROP_CHANGE_REASON_LEVELUP));
|
||||
case PROP_MAX_STAMINA -> this.sendPacket(new PacketPlayerPropChangeReasonNotify(this, prop, currentValue, value,
|
||||
PropChangeReason.PROP_CHANGE_REASON_CITY_LEVELUP));
|
||||
|
||||
// TODO: Handle world level changing.
|
||||
// case PROP_PLAYER_WORLD_LEVEL -> this.sendPacket(new PacketPlayerPropChangeReasonNotify(this, prop, currentValue, value,
|
||||
|
@ -16,6 +16,7 @@ import emu.grasscutter.net.proto.ChildQuestOuterClass.ChildQuest;
|
||||
import emu.grasscutter.net.proto.ParentQuestOuterClass.ParentQuest;
|
||||
import emu.grasscutter.server.packet.send.*;
|
||||
import emu.grasscutter.utils.ConversionUtils;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.*;
|
||||
@ -120,6 +121,15 @@ public class GameMainQuest {
|
||||
this.triggerQuestVarAction(i, this.questVars[i]);
|
||||
}
|
||||
|
||||
public void randomQuestVar(int i, int low, int high) {
|
||||
int previousValue = this.questVars[i];
|
||||
this.questVars[i] = Utils.random.nextInt(low, high);
|
||||
Grasscutter.getLogger()
|
||||
.debug("questVar {} value randomized from {} to {}", i, previousValue, this.questVars[i]);
|
||||
|
||||
this.triggerQuestVarAction(i, this.questVars[i]);
|
||||
}
|
||||
|
||||
public void triggerQuestVarAction(int index, int value) {
|
||||
var questManager = this.getQuestManager();
|
||||
questManager.queueEvent(QuestCond.QUEST_COND_QUEST_VAR_EQUAL, index, value);
|
||||
|
@ -172,6 +172,8 @@ public class GameQuest {
|
||||
this.failProgressList = new int[questData.getFailCond().size()];
|
||||
}
|
||||
|
||||
this.getMainQuest().getTalks().values().removeIf(talk -> talk.getId() == this.getSubQuestId());
|
||||
|
||||
this.getOwner().getPlayerProgress().resetCurrentProgress(String.valueOf(this.subQuestId));
|
||||
|
||||
setState(QuestState.QUEST_STATE_UNSTARTED);
|
||||
|
@ -282,7 +282,7 @@ public class QuestManager extends BasePlayerManager {
|
||||
}
|
||||
|
||||
public GameMainQuest getMainQuestByTalkId(int talkId) {
|
||||
int mainQuestId = GameData.getQuestTalkMap().getOrDefault(talkId, talkId / 100);
|
||||
var mainQuestId = GameData.getQuestTalkMap().getOrDefault(talkId, 0);
|
||||
return getMainQuestById(mainQuestId);
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,6 @@ package emu.grasscutter.game.quest.conditions;
|
||||
|
||||
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_COMPLETE_TALK;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.quest.QuestData;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.quest.QuestValueCond;
|
||||
@ -20,16 +18,12 @@ public class ConditionCompleteTalk extends BaseCondition {
|
||||
String paramStr,
|
||||
int... params) {
|
||||
val talkId = condition.getParam()[0];
|
||||
val unknownParam = condition.getParam()[1]; // e.g. 3 for 7081601
|
||||
val checkMainQuest = owner.getQuestManager().getMainQuestByTalkId(talkId);
|
||||
if (checkMainQuest == null
|
||||
|| GameData.getMainQuestDataMap().get(checkMainQuest.getParentQuestId()).getTalks()
|
||||
== null) {
|
||||
Grasscutter.getLogger()
|
||||
.debug("Warning: mainQuest {} hasn't been started yet, or has no talks", talkId / 100);
|
||||
return false;
|
||||
if (checkMainQuest == null) {
|
||||
return talkId == params[0];
|
||||
}
|
||||
|
||||
val talkData = checkMainQuest.getTalks().get(talkId);
|
||||
return talkData != null || checkMainQuest.getChildQuestById(talkId) != null;
|
||||
return talkData != null;
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ public class ConditionItemNumLessThan extends BaseCondition {
|
||||
String paramStr,
|
||||
int... params) {
|
||||
val itemId = condition.getParam()[0];
|
||||
val amount = condition.getParam()[1];
|
||||
val checkItem = owner.getInventory().getItemByGuid(itemId);
|
||||
return checkItem == null || checkItem.getCount() < amount;
|
||||
val targetAmount = condition.getParam()[1];
|
||||
val amount = owner.getInventory().getItemCountById(itemId);
|
||||
return amount < targetAmount;
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,11 @@ public class ConditionPackHaveItem extends BaseCondition {
|
||||
String paramStr,
|
||||
int... params) {
|
||||
val itemId = condition.getParam()[0];
|
||||
val targetAmount = condition.getParam()[1];
|
||||
val checkItem = owner.getInventory().getItemByGuid(itemId);
|
||||
return checkItem != null && checkItem.getCount() >= targetAmount;
|
||||
var targetAmount = condition.getParam()[1];
|
||||
if (targetAmount == 0) {
|
||||
targetAmount = 1;
|
||||
}
|
||||
val amount = owner.getInventory().getItemCountById(itemId);
|
||||
return amount >= targetAmount;
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,12 @@ public class ContentAddQuestProgress extends BaseContent {
|
||||
val currentCount =
|
||||
quest.getOwner().getPlayerProgress().getCurrentProgress(String.valueOf(progressId));
|
||||
|
||||
var targetAmount = condition.getCount();
|
||||
if (targetAmount == 0) {
|
||||
targetAmount = 1;
|
||||
}
|
||||
// if the condition count is 0 I think it is safe to assume that the
|
||||
// condition count from EXEC only needs to be 1
|
||||
return currentCount >= condition.getCount();
|
||||
return currentCount >= targetAmount;
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,10 @@ package emu.grasscutter.game.quest.content;
|
||||
|
||||
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_COMPLETE_ANY_TALK;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.quest.QuestData;
|
||||
import emu.grasscutter.game.quest.GameQuest;
|
||||
import emu.grasscutter.game.quest.QuestValueContent;
|
||||
import java.util.stream.Stream;
|
||||
import emu.grasscutter.game.quest.*;
|
||||
import java.util.Arrays;
|
||||
import lombok.val;
|
||||
|
||||
@QuestValueContent(QUEST_CONTENT_COMPLETE_ANY_TALK)
|
||||
public class ContentCompleteAnyTalk extends BaseContent {
|
||||
@ -14,10 +13,21 @@ public class ContentCompleteAnyTalk extends BaseContent {
|
||||
@Override
|
||||
public boolean execute(
|
||||
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
|
||||
return Stream.of(condition.getParamStr().split(","))
|
||||
.mapToInt(Integer::parseInt)
|
||||
.anyMatch(
|
||||
talkId ->
|
||||
GameData.getTalkConfigDataMap().get(params[0]) != null && talkId == params[0]);
|
||||
var conditionTalk =
|
||||
Arrays.stream(condition.getParamStr().split(",")).mapToInt(Integer::parseInt).toArray();
|
||||
|
||||
for (var talkId : conditionTalk) {
|
||||
val checkMainQuest = quest.getOwner().getQuestManager().getMainQuestByTalkId(talkId);
|
||||
if (checkMainQuest == null) {
|
||||
if (talkId == params[0]) return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
val talkData = checkMainQuest.getTalks().get(talkId);
|
||||
if (talkData != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -12,10 +12,9 @@ public class ContentCompleteTalk extends BaseContent {
|
||||
public boolean execute(
|
||||
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
|
||||
val talkId = condition.getParam()[0];
|
||||
if (talkId != params[0]) return false;
|
||||
val checkMainQuest = quest.getOwner().getQuestManager().getMainQuestByTalkId(talkId);
|
||||
if (checkMainQuest == null) {
|
||||
return false;
|
||||
return talkId == params[0];
|
||||
}
|
||||
|
||||
val talkData = checkMainQuest.getTalks().get(talkId);
|
||||
|
@ -5,12 +5,16 @@ import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_ITEM_L
|
||||
import emu.grasscutter.data.excels.quest.QuestData;
|
||||
import emu.grasscutter.game.quest.GameQuest;
|
||||
import emu.grasscutter.game.quest.QuestValueContent;
|
||||
import lombok.val;
|
||||
|
||||
@QuestValueContent(QUEST_CONTENT_ITEM_LESS_THAN)
|
||||
public class ContentItemLessThan extends BaseContent {
|
||||
@Override
|
||||
public boolean execute(
|
||||
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
|
||||
return condition.getParam()[0] == params[0] && condition.getCount() > params[1];
|
||||
val itemId = condition.getParam()[0];
|
||||
val targetAmount = condition.getParam()[1];
|
||||
val amount = quest.getOwner().getInventory().getItemCountById(itemId);
|
||||
return amount < targetAmount;
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,11 @@ public class ContentLuaNotify extends BaseContent {
|
||||
@Override
|
||||
public boolean execute(
|
||||
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
|
||||
return condition.getParamStr().equals(paramStr)
|
||||
&& condition.getCount()
|
||||
<= quest.getOwner().getPlayerProgress().getCurrentProgress(paramStr);
|
||||
var targetAmount = condition.getCount();
|
||||
if (targetAmount == 0) {
|
||||
targetAmount = 1;
|
||||
}
|
||||
return targetAmount
|
||||
<= quest.getOwner().getPlayerProgress().getCurrentProgress(condition.getParamStr());
|
||||
}
|
||||
}
|
||||
|
@ -5,16 +5,19 @@ import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_OBTAIN
|
||||
import emu.grasscutter.data.excels.quest.QuestData;
|
||||
import emu.grasscutter.game.quest.GameQuest;
|
||||
import emu.grasscutter.game.quest.QuestValueContent;
|
||||
import lombok.val;
|
||||
|
||||
@QuestValueContent(QUEST_CONTENT_OBTAIN_ITEM)
|
||||
public class ContentObtainItem extends BaseContent {
|
||||
@Override
|
||||
public boolean execute(
|
||||
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
|
||||
var targetCount = condition.getCount();
|
||||
if (targetCount == 0) {
|
||||
targetCount = 1;
|
||||
val itemId = condition.getParam()[0];
|
||||
var targetAmount = condition.getCount();
|
||||
if (targetAmount == 0) {
|
||||
targetAmount = 1;
|
||||
}
|
||||
return condition.getParam()[0] == params[0] && targetCount <= params[1];
|
||||
val amount = quest.getOwner().getInventory().getItemCountById(itemId);
|
||||
return amount >= targetAmount;
|
||||
}
|
||||
}
|
||||
|
@ -2,23 +2,18 @@ package emu.grasscutter.game.quest.content;
|
||||
|
||||
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_TRIGGER_FIRE;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.excels.quest.QuestData;
|
||||
import emu.grasscutter.game.quest.GameQuest;
|
||||
import emu.grasscutter.game.quest.QuestValueContent;
|
||||
import lombok.val;
|
||||
|
||||
@QuestValueContent(QUEST_CONTENT_TRIGGER_FIRE)
|
||||
public class ContentTriggerFire extends BaseContent {
|
||||
@Override
|
||||
public boolean execute(
|
||||
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
|
||||
if (quest.getTriggers().containsKey(quest.getTriggerNameById(params[0]))) {
|
||||
// We don't want to put a new key here
|
||||
return quest.getTriggers().get(quest.getTriggerNameById(params[0]));
|
||||
} else {
|
||||
Grasscutter.getLogger()
|
||||
.debug("Quest {} doesn't have trigger {} registered.", quest.getSubQuestId(), params[0]);
|
||||
return false;
|
||||
}
|
||||
val triggerId = condition.getParam()[0];
|
||||
val triggerName = quest.getTriggerNameById(triggerId);
|
||||
return quest.getTriggers().getOrDefault(triggerName, false);
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ public enum QuestExec implements QuestTrigger {
|
||||
QUEST_EXEC_SET_QUEST_VAR(48),
|
||||
QUEST_EXEC_INC_QUEST_VAR(49),
|
||||
QUEST_EXEC_DEC_QUEST_VAR(50),
|
||||
QUEST_EXEC_RANDOM_QUEST_VAR(51), // missing
|
||||
QUEST_EXEC_RANDOM_QUEST_VAR(51),
|
||||
QUEST_EXEC_ACTIVATE_SCANNING_PIC(52), // missing, currently unused
|
||||
QUEST_EXEC_RELOAD_SCENE_TAG(53), // missing
|
||||
QUEST_EXEC_REGISTER_DYNAMIC_GROUP_ONLY(54), // missing
|
||||
|
@ -0,0 +1,21 @@
|
||||
package emu.grasscutter.game.quest.exec;
|
||||
|
||||
import emu.grasscutter.data.excels.quest.QuestData;
|
||||
import emu.grasscutter.game.quest.GameQuest;
|
||||
import emu.grasscutter.game.quest.QuestValueExec;
|
||||
import emu.grasscutter.game.quest.enums.QuestExec;
|
||||
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
|
||||
|
||||
@QuestValueExec(QuestExec.QUEST_EXEC_RANDOM_QUEST_VAR)
|
||||
public class ExecRandomQuestVar extends QuestExecHandler {
|
||||
@Override
|
||||
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
|
||||
quest
|
||||
.getMainQuest()
|
||||
.randomQuestVar(
|
||||
Integer.parseInt(paramStr[0]),
|
||||
Integer.parseInt(paramStr[1]),
|
||||
Integer.parseInt(paramStr[2]));
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package emu.grasscutter.server.packet.recv;
|
||||
|
||||
import emu.grasscutter.net.packet.Opcodes;
|
||||
import emu.grasscutter.net.packet.PacketHandler;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.LevelupCityReqOuterClass.LevelupCityReq;
|
||||
import emu.grasscutter.server.game.GameSession;
|
||||
|
||||
@Opcodes(PacketOpcodes.LevelupCityReq)
|
||||
public class HandlerLevelupCityReq extends PacketHandler {
|
||||
|
||||
@Override
|
||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||
LevelupCityReq req = LevelupCityReq.parseFrom(payload);
|
||||
|
||||
// Level up city
|
||||
session
|
||||
.getPlayer()
|
||||
.getSotsManager()
|
||||
.levelUpSotS(req.getAreaId(), req.getSceneId(), req.getItemNum());
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ package emu.grasscutter.server.packet.send;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.net.packet.BasePacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.CityInfoOuterClass.CityInfo;
|
||||
import emu.grasscutter.net.proto.GetSceneAreaRspOuterClass.GetSceneAreaRsp;
|
||||
|
||||
public class PacketGetSceneAreaRsp extends BasePacket {
|
||||
@ -17,9 +16,9 @@ public class PacketGetSceneAreaRsp extends BasePacket {
|
||||
GetSceneAreaRsp.newBuilder()
|
||||
.setSceneId(sceneId)
|
||||
.addAllAreaIdList(player.getUnlockedSceneAreas(sceneId))
|
||||
.addCityInfoList(CityInfo.newBuilder().setCityId(1).setLevel(1).build())
|
||||
.addCityInfoList(CityInfo.newBuilder().setCityId(2).setLevel(1).build())
|
||||
.addCityInfoList(CityInfo.newBuilder().setCityId(3).setLevel(1).build())
|
||||
.addCityInfoList(player.getSotsManager().getCityInfo(1).toProto())
|
||||
.addCityInfoList(player.getSotsManager().getCityInfo(2).toProto())
|
||||
.addCityInfoList(player.getSotsManager().getCityInfo(3).toProto())
|
||||
.build();
|
||||
|
||||
this.setData(p);
|
||||
|
@ -0,0 +1,29 @@
|
||||
package emu.grasscutter.server.packet.send;
|
||||
|
||||
import emu.grasscutter.net.packet.BasePacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.CityInfoOuterClass.CityInfo;
|
||||
import emu.grasscutter.net.proto.LevelupCityRspOuterClass.LevelupCityRsp;
|
||||
|
||||
public class PacketLevelupCityRsp extends BasePacket {
|
||||
|
||||
public PacketLevelupCityRsp(
|
||||
int sceneId, int level, int cityId, int crystalNum, int areaId, int retcode) {
|
||||
super(PacketOpcodes.LevelupCityRsp);
|
||||
|
||||
LevelupCityRsp proto =
|
||||
LevelupCityRsp.newBuilder()
|
||||
.setSceneId(sceneId)
|
||||
.setCityInfo(
|
||||
CityInfo.newBuilder()
|
||||
.setCityId(cityId)
|
||||
.setLevel(level)
|
||||
.setCrystalNum(crystalNum)
|
||||
.build())
|
||||
.setAreaId(areaId)
|
||||
.setRetcode(retcode)
|
||||
.build();
|
||||
|
||||
this.setData(proto);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user