Commit 19d81463 authored by KingRainbow44's avatar KingRainbow44
Browse files

Merge remote-tracking branch 'origin/development' into development

parents 71b118dd e3e917ef
package emu.grasscutter.command.commands;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.player.Player;
import java.util.List;
import static emu.grasscutter.utils.Language.translate;
@Command(label = "setworldlevel", usage = "setworldlevel <level>",
aliases = {"setworldlvl"}, permission = "player.setworldlevel", permissionTargeted = "player.setworldlevel.others", description = "commands.setWorldLevel.description")
public final class SetWorldLevelCommand implements CommandHandler {
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.size() < 1) {
CommandHandler.sendMessage(sender, translate(sender, "commands.setWorldLevel.usage"));
return;
}
try {
int level = Integer.parseInt(args.get(0));
if (level > 8 || level < 0) {
CommandHandler.sendMessage(sender, translate(sender, "commands.setWorldLevel.value_error"));
return;
}
// Set in both world and player props
targetPlayer.getWorld().setWorldLevel(level);
targetPlayer.setWorldLevel(level);
CommandHandler.sendMessage(sender, translate(sender, "commands.setWorldLevel.success", Integer.toString(level)));
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(null, translate(sender, "commands.setWorldLevel.invalid_world_level"));
}
}
}
......@@ -23,7 +23,7 @@ import java.util.Random;
import static emu.grasscutter.Configuration.*;
import static emu.grasscutter.utils.Language.translate;
@Command(label = "spawn", usage = "spawn <entityId> [amount] [level(monster only)] [<x> <y> <z>(monster only, optional)]", permission = "server.spawn", permissionTargeted = "server.spawn.others", description = "commands.spawn.description")
@Command(label = "spawn", usage = "spawn <entityId> [amount] [level(monster only)] [<x> <y> <z>(monster only, optional)]", aliases = {"drop"}, permission = "server.spawn", permissionTargeted = "server.spawn.others", description = "commands.spawn.description")
public final class SpawnCommand implements CommandHandler {
@Override
......
......@@ -56,7 +56,7 @@ public final class TeleportCommand implements CommandHandler {
Position target_pos = new Position(x, y, z);
boolean result = targetPlayer.getWorld().transferPlayerToScene(targetPlayer, sceneId, target_pos);
if (!result) {
CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.invalid_position"));
CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.exists_error"));
} else {
CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.success",
targetPlayer.getNickname(), Float.toString(x), Float.toString(y),
......
......@@ -2,37 +2,25 @@ package emu.grasscutter.command.commands;
import java.util.List;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.Account;
import emu.grasscutter.game.player.Player;
import static emu.grasscutter.utils.Language.translate;
@Command(
label = "unban",
usage = "unban <player>",
usage = "unban <@player>",
description = "commands.unban.description",
targetRequirement = Command.TargetRequirement.NONE
permission = "server.ban",
targetRequirement = Command.TargetRequirement.PLAYER
)
public final class UnBanCommand implements CommandHandler {
private boolean unBanAccount(int uid) {
Player player = Grasscutter.getGameServer().getPlayerByUid(uid, true);
if (player == null) {
return false;
}
Account account = player.getAccount();
private boolean unBanAccount(Player targetPlayer) {
Account account = targetPlayer.getAccount();
if (account == null) {
account = DatabaseHelper.getAccountByPlayerId(uid);
if (account == null) {
return false;
}
return false;
}
account.setBanReason(null);
......@@ -46,24 +34,10 @@ public final class UnBanCommand implements CommandHandler {
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.size() < 1) {
CommandHandler.sendMessage(sender, translate(sender, "commands.unban.command_usage"));
return;
}
int uid = 0;
try {
uid = Integer.parseInt(args.get(0));
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, translate(sender, "commands.unban.invalid_player_id"));
return;
}
if (unBanAccount(uid)) {
CommandHandler.sendMessage(sender, translate(sender, "commands.unban.success"));
if (unBanAccount(targetPlayer)) {
CommandHandler.sendTranslatedMessage(sender, "commands.unban.success");
} else {
CommandHandler.sendMessage(sender, translate(sender, "commands.unban.failure"));
CommandHandler.sendTranslatedMessage(sender, "commands.unban.failure");
}
}
}
\ No newline at end of file
package emu.grasscutter.command.commands;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.managers.energy.EnergyManager;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.player.TeamManager;
import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.net.proto.PropChangeReasonOuterClass;
import emu.grasscutter.utils.Position;
import java.util.List;
import static emu.grasscutter.Configuration.GAME_OPTIONS;
import static emu.grasscutter.utils.Language.translate;
@Command(label = "unlimitenergy", usage = "unlimitenergy [on|off|toggle]", aliases = {"ule"}, permission = "player.unlimitenergy", permissionTargeted = "player.unlimitenergy.others", description = "commands.unlimitenergy.description")
public final class UnlimitEnergyCommand implements CommandHandler {
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if(!GAME_OPTIONS.energyUsage){
CommandHandler.sendMessage(sender, translate(sender, "commands.unlimitenergy.config_error"));
return;
}
Boolean status = targetPlayer.getEnergyManager().getEnergyUsage();
if (args.size() == 1) {
switch (args.get(0).toLowerCase()) {
case "on":
status = true;
break;
case "off":
status = false;
break;
default:
status = !status;
break;
}
}
EnergyManager energyManager=targetPlayer.getEnergyManager();
energyManager.setEnergyUsage(!status);
// if unlimitEnergy is enable , make currentActiveTeam's Avatar full-energy
if (status) {
for (EntityAvatar entityAvatar : targetPlayer.getTeamManager().getActiveTeam()) {
entityAvatar.addEnergy(1000,
PropChangeReasonOuterClass.PropChangeReason.PROP_CHANGE_REASON_GM,true);
}
}
CommandHandler.sendMessage(sender, translate(sender, "commands.unlimitenergy.success", (status ? translate(sender, "commands.status.enabled") : translate(sender, "commands.status.disabled")), targetPlayer.getNickname()));
}
}
package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.tower.TowerLevelRecord;
import java.util.List;
import static emu.grasscutter.utils.Language.translate;
@Command(label = "unlocktower", usage = "unlocktower", aliases = {"ut"}, permission = "player.unlocktower", permissionTargeted = "player.unlocktower.others",
description = "commands.unlocktower.description")
public class UnlockTowerCommand implements CommandHandler {
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
unlockFloor(targetPlayer, targetPlayer.getServer().getTowerScheduleManager()
.getCurrentTowerScheduleData().getEntranceFloorId());
unlockFloor(targetPlayer, targetPlayer.getServer().getTowerScheduleManager()
.getScheduleFloors());
CommandHandler.sendMessage(sender, translate(sender, "commands.unlocktower.success"));
}
public void unlockFloor(Player player, List<Integer> floors){
floors.stream()
.filter(id -> !player.getTowerManager().getRecordMap().containsKey(id))
.forEach(id -> player.getTowerManager().getRecordMap().put(id, new TowerLevelRecord(id)));
}
}
......@@ -95,8 +95,8 @@ public class GameData {
private static final Int2ObjectMap<InvestigationMonsterData> investigationMonsterDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<CityData> cityDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<WeatherData> weatherDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<BattlePassMissionExcelConfigData> battlePassMissionExcelConfigDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<BattlePassRewardExcelConfigData> battlePassRewardExcelConfigDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<BattlePassMissionData> battlePassMissionDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<BattlePassRewardData> battlePassRewardDataMap = new Int2ObjectOpenHashMap<>();
// Cache
private static Map<Integer, List<Integer>> fetters = new HashMap<>();
......@@ -424,11 +424,11 @@ public class GameData {
return weatherDataMap;
}
public static Int2ObjectMap<BattlePassMissionExcelConfigData> getBattlePassMissionExcelConfigDataMap() {
return battlePassMissionExcelConfigDataMap;
public static Int2ObjectMap<BattlePassMissionData> getBattlePassMissionDataMap() {
return battlePassMissionDataMap;
}
public static Int2ObjectMap<BattlePassRewardExcelConfigData> getBattlePassRewardExcelConfigDataMap() {
return battlePassRewardExcelConfigDataMap;
public static Int2ObjectMap<BattlePassRewardData> getBattlePassRewardDataMap() {
return battlePassRewardDataMap;
}
}
......@@ -20,8 +20,9 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class GameDepot {
private static Int2ObjectMap<WeightedList<ReliquaryMainPropData>> relicMainPropDepot = new Int2ObjectOpenHashMap<>();
private static Int2ObjectMap<List<ReliquaryAffixData>> relicAffixDepot = new Int2ObjectOpenHashMap<>();
private static Int2ObjectMap<WeightedList<ReliquaryMainPropData>> relicRandomMainPropDepot = new Int2ObjectOpenHashMap<>();
private static Int2ObjectMap<List<ReliquaryMainPropData>> relicMainPropDepot = new Int2ObjectOpenHashMap<>();
private static Int2ObjectMap<List<ReliquaryAffixData>> relicAffixDepot = new Int2ObjectOpenHashMap<>();
private static Map<String, AvatarConfig> playerAbilities = new HashMap<>();
private static Int2ObjectMap<SpatialIndex<SpawnGroupEntry>> spawnLists = new Int2ObjectOpenHashMap<>();
......@@ -31,8 +32,10 @@ public class GameDepot {
if (data.getWeight() <= 0 || data.getPropDepotId() <= 0) {
continue;
}
WeightedList<ReliquaryMainPropData> list = relicMainPropDepot.computeIfAbsent(data.getPropDepotId(), k -> new WeightedList<>());
list.add(data.getWeight(), data);
List<ReliquaryMainPropData> list = relicMainPropDepot.computeIfAbsent(data.getPropDepotId(), k -> new ArrayList<>());
list.add(data);
WeightedList<ReliquaryMainPropData> weightedList = relicRandomMainPropDepot.computeIfAbsent(data.getPropDepotId(), k -> new WeightedList<>());
weightedList.add(data.getWeight(), data);
}
for (ReliquaryAffixData data : GameData.getReliquaryAffixDataMap().values()) {
if (data.getWeight() <= 0 || data.getDepotId() <= 0) {
......@@ -48,14 +51,18 @@ public class GameDepot {
}
public static ReliquaryMainPropData getRandomRelicMainProp(int depot) {
WeightedList<ReliquaryMainPropData> depotList = relicMainPropDepot.get(depot);
WeightedList<ReliquaryMainPropData> depotList = relicRandomMainPropDepot.get(depot);
if (depotList == null) {
return null;
}
return depotList.next();
}
public static List<ReliquaryAffixData> getRandomRelicAffixList(int depot) {
public static List<ReliquaryMainPropData> getRelicMainPropList(int depot) {
return relicMainPropDepot.get(depot);
}
public static List<ReliquaryAffixData> getRelicAffixList(int depot) {
return relicAffixDepot.get(depot);
}
......
package emu.grasscutter.data.excels;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.ResourceType;
import emu.grasscutter.game.props.BattlePassMissionRefreshType;
import emu.grasscutter.game.props.WatcherTriggerType;
import emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission.MissionStatus;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.FieldDefaults;
@ResourceType(name = {"BattlePassMissionExcelConfigData.json"})
@Getter
public class BattlePassMissionData extends GameResource {
private int addPoint;
private int id;
private int scheduleId;
private int progress;
private TriggerConfig triggerConfig;
private BattlePassMissionRefreshType refreshType;
private transient Set<Integer> mainParams;
@Override
public int getId() {
return this.id;
}
public WatcherTriggerType getTriggerType() {
return this.getTriggerConfig().getTriggerType();
}
public boolean isCycleRefresh() {
return getRefreshType() == null || getRefreshType() == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE;
}
public boolean isValidRefreshType() {
return getRefreshType() == null ||
getRefreshType() == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE ||
getScheduleId() == 2701;
}
@Override
public void onLoad() {
if (this.getTriggerConfig() != null && getTriggerConfig().getParamList()[0].length() > 0) {
this.mainParams = Arrays.stream(getTriggerConfig().getParamList()[0].split("[:;,]")).map(Integer::parseInt).collect(Collectors.toSet());
}
}
@Getter
public static class TriggerConfig {
private WatcherTriggerType triggerType;
private String[] paramList;
}
public emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission toProto() {
var protoBuilder = emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission.newBuilder();
protoBuilder
.setMissionId(getId())
.setTotalProgress(this.getProgress())
.setRewardBattlePassPoint(this.getAddPoint())
.setMissionStatus(MissionStatus.MISSION_STATUS_UNFINISHED)
.setMissionType(this.getRefreshType() == null ? 0 : this.getRefreshType().getValue());
return protoBuilder.build();
}
}
package emu.grasscutter.data.excels;
import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.ResourceType;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.FieldDefaults;
@ResourceType(name = {"BattlePassMissionExcelConfigData.json"})
@FieldDefaults(level = AccessLevel.PRIVATE)
@Getter
@Setter
public class BattlePassMissionExcelConfigData extends GameResource {
private int addPoint;
private int id;
private int progress;
private String refreshType;
@Override
public void onLoad() {
}
@Override
public int getId() {
return this.id;
}
}
......@@ -9,8 +9,7 @@ import java.util.List;
@ResourceType(name = "BattlePassRewardExcelConfigData.json")
@Getter
@Setter
public class BattlePassRewardExcelConfigData extends GameResource {
public class BattlePassRewardData extends GameResource {
private int indexId;
private int level;
private List<Integer> freeRewardIdList;
......@@ -23,5 +22,6 @@ public class BattlePassRewardExcelConfigData extends GameResource {
@Override
public void onLoad() {
}
}
......@@ -6,7 +6,6 @@ import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.ResourceType;
import emu.grasscutter.data.ResourceType.LoadPriority;
import emu.grasscutter.data.common.ItemParamData;
import emu.grasscutter.data.common.OpenCondData;
@ResourceType(name = {"ForgeExcelConfigData.json"}, loadPriority = LoadPriority.HIGHEST)
public class ForgeData extends GameResource {
......@@ -19,6 +18,7 @@ public class ForgeData extends GameResource {
private int queueNum;
private int scoinCost;
private int priority;
private int forgePoint;
private List<ItemParamData> materialItems;
@Override
......@@ -58,6 +58,10 @@ public class ForgeData extends GameResource {
return priority;
}
public int getForgePoint() {
return forgePoint;
}
public List<ItemParamData> getMaterialItems() {
return materialItems;
}
......
......@@ -10,6 +10,7 @@ import emu.grasscutter.game.inventory.*;
import emu.grasscutter.game.props.FightProperty;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import lombok.Getter;
@ResourceType(name = {"MaterialExcelConfigData.json",
"WeaponExcelConfigData.json",
......@@ -19,23 +20,23 @@ import it.unimi.dsi.fastutil.ints.IntSet;
public class ItemData extends GameResource {
private int id;
private int stackLimit = 1;
private int maxUseCount;
private int rankLevel;
private String effectName;
private int[] satiationParams;
private int rank;
private int weight;
private int gadgetId;
@Getter private int stackLimit = 1;
@Getter private int maxUseCount;
@Getter private int rankLevel;
@Getter private String effectName;
@Getter private int[] satiationParams;
@Getter private int rank;
@Getter private int weight;
@Getter private int gadgetId;
private int[] destroyReturnMaterial;
private int[] destroyReturnMaterialCount;
@Getter private int[] destroyReturnMaterial;
@Getter private int[] destroyReturnMaterialCount;
private List<ItemUseData> itemUse;
@Getter private List<ItemUseData> itemUse;
// Food
private String foodQuality;
private String useTarget;
@Getter private String foodQuality;
@Getter private String useTarget;
private String[] iseParam;
// String enums
......@@ -45,42 +46,42 @@ public class ItemData extends GameResource {
private String effectType;
private String destroyRule;
// Post load enum forms of above
private transient MaterialType materialEnumType;
private transient ItemType itemEnumType;
private transient EquipType equipEnumType;
// Relic
private int mainPropDepotId;
private int appendPropDepotId;
private int appendPropNum;
private int setId;
@Getter private int mainPropDepotId;
@Getter private int appendPropDepotId;
@Getter private int appendPropNum;
@Getter private int setId;
private int[] addPropLevels;
private int baseConvExp;
private int maxLevel;
@Getter private int baseConvExp;
@Getter private int maxLevel;
// Weapon
private int weaponPromoteId;
private int weaponBaseExp;
private int storyId;
private int avatarPromoteId;
private int awakenMaterial;
private int[] awakenCosts;
private int[] skillAffix;
@Getter private int weaponPromoteId;
@Getter private int weaponBaseExp;
@Getter private int storyId;
@Getter private int avatarPromoteId;
@Getter private int awakenMaterial;
@Getter private int[] awakenCosts;
@Getter private int[] skillAffix;
private WeaponProperty[] weaponProp;
// Hash
private String icon;
private long nameTextMapHash;
// Post load
private transient MaterialType materialEnumType;
private transient ItemType itemEnumType;
private transient EquipType equipEnumType;
@Getter private String icon;
@Getter private long nameTextMapHash;
private IntSet addPropLevelSet;
@Getter private IntSet addPropLevelSet;
// Furniture
private int comfort;
private List<Integer> furnType;
private List<Integer> furnitureGadgetID;
@Getter private int comfort;
@Getter private List<Integer> furnType;
@Getter private List<Integer> furnitureGadgetID;
@SerializedName("JFDLJGDFIGL")
private int roomSceneId;
@Getter private int roomSceneId;
@Override
public int getId(){
......@@ -91,137 +92,17 @@ public class ItemData extends GameResource {
return this.materialType;
}
public int getStackLimit(){
return this.stackLimit;
}
public int getMaxUseCount(){
return this.maxUseCount;
}
public String getUseTarget(){
return this.useTarget;
}
public String[] getUseParam(){
return this.iseParam;
}
public int getRankLevel(){
return this.rankLevel;
}
public String getFoodQuality(){
return this.foodQuality;
}
public String getEffectName(){
return this.effectName;
}
public int[] getSatiationParams(){
return this.satiationParams;
}
public int[] getDestroyReturnMaterial(){
return this.destroyReturnMaterial;
}
public int[] getDestroyReturnMaterialCount(){
return this.destroyReturnMaterialCount;
}
public List<ItemUseData> getItemUse() {
return itemUse;
}
public long getNameTextMapHash(){
return this.nameTextMapHash;
}
public String getIcon(){
return this.icon;
}
public String getItemTypeString(){
return this.itemType;
}
public int getRank(){
return this.rank;
}
public int getGadgetId() {
return gadgetId;
}
public int getBaseConvExp() {
return baseConvExp;
}
public int getMainPropDepotId() {
return mainPropDepotId;
}
public int getAppendPropDepotId() {
return appendPropDepotId;
}
public int getAppendPropNum() {
return appendPropNum;
}
public int getSetId() {
return setId;
}
public int getWeaponPromoteId() {
return weaponPromoteId;
}
public int getWeaponBaseExp() {
return weaponBaseExp;
}
public int getAwakenMaterial() {
return awakenMaterial;
}
public int[] getAwakenCosts() {
return awakenCosts;
}
public IntSet getAddPropLevelSet() {
return addPropLevelSet;
}
public int[] getSkillAffix() {
return skillAffix;
}
public WeaponProperty[] getWeaponProperties() {
return weaponProp;
}
public int getMaxLevel() {
return maxLevel;
}
public int getComfort() {
return comfort;
}
public List<Integer> getFurnType() {
return furnType;
}
public List<Integer> getFurnitureGadgetID() {
return furnitureGadgetID;
}
public int getRoomSceneId() {
return roomSceneId;
}
public ItemType getItemType() {
return this.itemEnumType;
......@@ -274,26 +155,10 @@ public class ItemData extends GameResource {
}
public static class WeaponProperty {
private FightProperty fightProp;
private String propType;
private float initValue;
private String type;
public String getPropType(){
return this.propType;
}
public float getInitValue(){
return this.initValue;
}
public String getType(){
return this.type;
}
public FightProperty getFightProp() {
return fightProp;
}
@Getter private FightProperty fightProp;
@Getter private String propType;
@Getter private float initValue;
@Getter private String type;
public void onLoad() {
this.fightProp = FightProperty.getPropByName(propType);
......
......@@ -131,6 +131,7 @@ public final class DatabaseHelper {
DatabaseManager.getGameDatabase().getCollection("gachas").deleteMany(eq("ownerId", player.getUid()));
DatabaseManager.getGameDatabase().getCollection("items").deleteMany(eq("ownerId", player.getUid()));
DatabaseManager.getGameDatabase().getCollection("quests").deleteMany(eq("ownerUid", player.getUid()));
DatabaseManager.getGameDatabase().getCollection("battlepass").deleteMany(eq("ownerUid", player.getUid()));
// Delete friendships.
// Here, we need to make sure to not only delete the deleted account's friendships,
......
......@@ -92,15 +92,16 @@ public class HealAbilityManager {
public HealAbilityManager (Player player) {
this.player = player;
healDataAvatarList = new ArrayList();
healDataAvatarList.add(new HealDataAvatar(10000054, "Kokomi", 0).addHealData("E", "ElementalArt_Heal_MaxHP_Base_Percentage", "ElementalArt_Heal_Base_Amount", false));
healDataAvatarList.add(new HealDataAvatar(10000054, "Kokomi", 0).addHealData("E", "ElementalArt_Heal_MaxHP_Base_Percentage", "ElementalArt_Heal_Base_Amount", false).addHealData("Q", "Avatar_Kokomi_ElementalBurst_Heal", 0.0172f, 212f, false));
healDataAvatarList.add(new HealDataAvatar(10000003, "Qin", 1).addHealData("Q", "Heal", "BurstHealConst", true));
healDataAvatarList.add(new HealDataAvatar(10000034, "Noel", 2).addHealData("E", "OnAttack_HealthRate", 0.452f, 282f, true));
healDataAvatarList.add(new HealDataAvatar(10000032, "Bennett", 0).addHealData("Q", "HealMaxHpRatio", "HealConst", false));
healDataAvatarList.add(new HealDataAvatar(10000039, "Diona", 0).addHealData("Q", "HealHPRatio", "HealHP_Const", false));
healDataAvatarList.add(new HealDataAvatar(10000053, "Sayu", 1).addHealData("Q", "Constellation_6_Damage", "Heal_BaseAmount", true).addHealData("Q", "Heal_AttackRatio", "Constellation_6_Heal", true));
healDataAvatarList.add(new HealDataAvatar(10000014, "Barbara", 0).addHealData("E", "HealHPOnAdded", "HealHPOnAdded_Const", true).addHealData("E", "HealHP_OnHittingOthers", "HealHP_Const_OnHittingOthers", true));
healDataAvatarList.add(new HealDataAvatar(10000014, "Barbara", 0).addHealData("E", "HealHPOnAdded", "HealHPOnAdded_Const", true).addHealData("E", "HealHP_OnHittingOthers", "HealHP_Const_OnHittingOthers", true).addHealData("Q", "Avatar_Barbara_IdolHeal", 0.374f, 4660f, true));
healDataAvatarList.add(new HealDataAvatar(10000065, "Shinobu", 0).addHealData("E", "ElementalArt_Heal_MaxHP_Percentage", 0.064f, 795f, false));
healDataAvatarList.add(new HealDataAvatar(10000035, "Qiqi", 1).addHealData("E", "HealHP_OnHittingOthers", "HealHP_Const_OnHittingOthers", true).addHealData("E", "ElementalArt_HealHp_Ratio", "ElementalArt_HealHp_Const", true));
healDataAvatarList.add(new HealDataAvatar(10000035, "Qiqi", 1).addHealData("E", "HealHP_OnHittingOthers", "HealHP_Const_OnHittingOthers", true).addHealData("E", "ElementalArt_HealHp_Ratio", "ElementalArt_HealHp_Const", true).addHealData("Q", "Avatar_Qiqi_ElementalBurst_ApplyModifier", 0.0191f, 1588f, false));
healDataAvatarList.add(new HealDataAvatar(10000046, "Hutao", 0).addHealData("Q", "Avatar_Hutao_VermilionBite_BakeMesh", 0.1166f, 0f, false));
}
public Player getPlayer() {
......@@ -128,7 +129,7 @@ public class HealAbilityManager {
int fightPropertyType = 0;
float healAmount = 0;
float ratio = 0, base = 0;
float maxHP, curAttack, curDefense;
float maxHP, curHP, curAttack, curDefense;
Map<String, Float> map = sourceEntity.getMetaOverrideMap();
for(int i = 0 ; i < healDataAvatarList.size() ; i ++) {
......@@ -139,7 +140,7 @@ public class HealAbilityManager {
for(int j = 0 ; j < healDataList.size(); j++) {
HealData healData = healDataList.get(j);
if(map.containsKey(healData.sRatio)) {
if(map.containsKey(healData.sRatio) || modifierString.equals(healData.sRatio)) {
if(healData.isString) {
ratio = map.get(healData.sRatio);
base = map.get(healData.sBase);
......@@ -173,8 +174,15 @@ public class HealAbilityManager {
if(healActionAvatar != null) {
maxHP = healActionAvatar.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
curHP = healActionAvatar.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP);
curAttack = healActionAvatar.getFightProperty(FightProperty.FIGHT_PROP_CUR_ATTACK);
curDefense = healActionAvatar.getFightProperty(FightProperty.FIGHT_PROP_CUR_DEFENSE);
//Special case for Hu Tao:
if(healDataAvatar.avatarName.equals("Hutao") && curHP <= maxHP * 0.5 && ratio != 0) {
ratio = 0.1555f;
}
switch(fightPropertyType) {
case 0:
healAmount = ratio * maxHP + base;
......
......@@ -242,6 +242,23 @@ public class Avatar {
this.promoteLevel = promoteLevel;
}
static public int getMinPromoteLevel(int level) {
if (level > 80) {
return 6;
} else if (level > 70) {
return 5;
} else if (level > 60) {
return 4;
} else if (level > 50) {
return 3;
} else if (level > 40) {
return 2;
} else if (level > 20) {
return 1;
}
return 0;
}
public Int2ObjectMap<GameItem> getEquips() {
return equips;
}
......
package emu.grasscutter.game.battlepass;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bson.types.ObjectId;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import dev.morphia.annotations.Indexed;
import dev.morphia.annotations.Transient;
import emu.grasscutter.GameConstants;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.common.ItemParamData;
import emu.grasscutter.data.excels.BattlePassRewardData;
import emu.grasscutter.data.excels.RewardData;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.props.BattlePassMissionRefreshType;
import emu.grasscutter.game.props.BattlePassMissionStatus;
import emu.grasscutter.game.props.WatcherTriggerType;
import emu.grasscutter.net.proto.BattlePassCycleOuterClass.BattlePassCycle;
import emu.grasscutter.net.proto.BattlePassProductOuterClass.BattlePassProduct;
import emu.grasscutter.net.proto.BattlePassRewardTagOuterClass.BattlePassRewardTag;
import emu.grasscutter.net.proto.BattlePassUnlockStatusOuterClass.BattlePassUnlockStatus;
import emu.grasscutter.net.proto.BattlePassRewardTakeOptionOuterClass.BattlePassRewardTakeOption;
import emu.grasscutter.net.proto.BattlePassScheduleOuterClass.BattlePassSchedule;
import emu.grasscutter.server.packet.send.PacketBattlePassCurScheduleUpdateNotify;
import emu.grasscutter.server.packet.send.PacketBattlePassMissionUpdateNotify;
import emu.grasscutter.server.packet.send.PacketTakeBattlePassRewardRsp;
import lombok.Getter;
@Entity(value = "battlepass", useDiscriminator = false)
public class BattlePassManager {
@Id private ObjectId id;
@Transient private Player player;
@Id @Getter private ObjectId id;
@Transient @Getter private Player player;
@Indexed private int ownerUid;
private int point;
private int awardTakenLevel;
@Getter private int point;
@Getter private int cyclePoints; // Weekly maximum cap
@Getter private int level;
@Getter private boolean viewed;
@Getter private boolean paid;
private Map<Integer, BattlePassMission> missions;
private Map<Integer, BattlePassReward> takenRewards;
@Deprecated // Morphia only
public BattlePassManager() {}
......@@ -26,39 +56,226 @@ public class BattlePassManager {
this.setPlayer(player);
}
public ObjectId getId() {
return id;
}
public Player getPlayer() {
return this.player;
}
public void setPlayer(Player player) {
this.player = player;
this.ownerUid = player.getUid();
}
public int getPoint() {
return point;
public void updateViewed() {
this.viewed = true;
}
public int getAwardTakenLevel() {
return awardTakenLevel;
}
public boolean setLevel(int level) {
if (level >= 0 && level <= GameConstants.BATTLE_PASS_MAX_LEVEL) {
this.level = level;
this.point = 0;
this.player.sendPacket(new PacketBattlePassCurScheduleUpdateNotify(this.player));
return true;
}
return false;
}
public void addPoint(int point){
this.point += point;
player.getSession().send(new PacketBattlePassCurScheduleUpdateNotify(player.getSession().getPlayer()));
public void addPoints(int points){
this.addPointsDirectly(points, false);
this.player.sendPacket(new PacketBattlePassCurScheduleUpdateNotify(player));
this.save();
}
public void updateAwardTakenLevel(int level){
this.awardTakenLevel = level;
player.getSession().send(new PacketBattlePassCurScheduleUpdateNotify(player.getSession().getPlayer()));
this.save();
public void addPointsDirectly(int points, boolean isWeekly) {
int amount = points;
if (isWeekly) {
amount = Math.min(amount, GameConstants.BATTLE_PASS_POINT_PER_WEEK - this.cyclePoints);
}
if (amount <= 0) {
return;
}
this.point += amount;
this.cyclePoints += amount;
if (this.point >= GameConstants.BATTLE_PASS_POINT_PER_LEVEL && this.getLevel() < GameConstants.BATTLE_PASS_MAX_LEVEL) {
int levelups = Math.floorDiv(this.point, GameConstants.BATTLE_PASS_POINT_PER_LEVEL);
// Make sure player cant go above max BP level
levelups = Math.min(levelups, GameConstants.BATTLE_PASS_MAX_LEVEL - levelups);
// Set new points after level up
this.point = this.point - (levelups * GameConstants.BATTLE_PASS_POINT_PER_LEVEL);
this.level += levelups;
}
}
public Map<Integer, BattlePassMission> getMissions() {
if (this.missions == null) this.missions = new HashMap<>();
return this.missions;
}
// Will return a new empty mission if the mission id is not found
public BattlePassMission loadMissionById(int id) {
return getMissions().computeIfAbsent(id, i -> new BattlePassMission(i));
}
public boolean hasMission(int id) {
return getMissions().containsKey(id);
}
public Map<Integer, BattlePassReward> getTakenRewards() {
if (this.takenRewards == null) this.takenRewards = new HashMap<>();
return this.takenRewards;
}
// Mission triggers
public void triggerMission(WatcherTriggerType triggerType) {
getPlayer().getServer().getBattlePassMissionManager().triggerMission(getPlayer(), triggerType);
}
public void triggerMission(WatcherTriggerType triggerType, int param, int progress) {
getPlayer().getServer().getBattlePassMissionManager().triggerMission(getPlayer(), triggerType, param, progress);
}
// Handlers
public void takeMissionPoint(List<Integer> missionIdList) {
// Obvious exploit check
if (missionIdList.size() > GameData.getBattlePassMissionDataMap().size()) {
return;
}
List<BattlePassMission> updatedMissions = new ArrayList<>(missionIdList.size());
for (int id : missionIdList) {
// Skip if we dont have this mission
if (!this.hasMission(id)) {
continue;
}
BattlePassMission mission = this.loadMissionById(id);
if (mission.getData() == null) {
this.getMissions().remove(mission.getId());
continue;
}
// Take reward
if (mission.getStatus() == BattlePassMissionStatus.MISSION_STATUS_FINISHED) {
this.addPointsDirectly(mission.getData().getAddPoint(), mission.getData().isCycleRefresh());
mission.setStatus(BattlePassMissionStatus.MISSION_STATUS_POINT_TAKEN);
updatedMissions.add(mission);
}
}
if (updatedMissions.size() > 0) {
// Save to db
this.save();
// Packet
getPlayer().sendPacket(new PacketBattlePassMissionUpdateNotify(updatedMissions));
getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(getPlayer()));
}
}
public void takeReward(List<BattlePassRewardTakeOption> takeOptionList) {
List<BattlePassRewardTag> rewardList = new ArrayList<>();
for (BattlePassRewardTakeOption option : takeOptionList) {
// Duplicate check
if (option.getTag().getRewardId() == 0 || getTakenRewards().containsKey(option.getTag().getRewardId())) {
continue;
}
// Level check
if (option.getTag().getLevel() > this.getLevel()) {
continue;
}
BattlePassRewardData rewardData = GameData.getBattlePassRewardDataMap().get(option.getTag().getLevel());
// Sanity check with excel data
if (rewardData.getFreeRewardIdList().contains(option.getTag().getRewardId())) {
rewardList.add(option.getTag());
} else if (this.isPaid() && rewardData.getPaidRewardIdList().contains(option.getTag().getRewardId())) {
rewardList.add(option.getTag());
}
}
// Get rewards
List<ItemParamData> rewardItems = null;
if (rewardList.size() > 0) {
rewardItems = new ArrayList<>();
for (BattlePassRewardTag tag : rewardList) {
RewardData reward = GameData.getRewardDataMap().get(tag.getRewardId());
if (reward == null) continue;
BattlePassReward bpReward = new BattlePassReward(tag.getLevel(), tag.getRewardId(), tag.getUnlockStatus() == BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_PAID);
this.getTakenRewards().put(bpReward.getRewardId(), bpReward);
rewardItems.addAll(reward.getRewardItemList());
}
// Save to db
this.save();
// Add items and send battle pass schedule packet
getPlayer().getInventory().addItemParamDatas(rewardItems);
getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(getPlayer()));
}
getPlayer().sendPacket(new PacketTakeBattlePassRewardRsp(takeOptionList, rewardItems));
}
public int buyLevels(int buyLevel) {
int boughtLevels = Math.min(buyLevel, GameConstants.BATTLE_PASS_MAX_LEVEL - buyLevel);
if (boughtLevels > 0) {
int price = GameConstants.BATTLE_PASS_LEVEL_PRICE * boughtLevels;
if (getPlayer().getPrimogems() < price) {
return 0;
}
this.level += boughtLevels;
this.save();
getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(getPlayer()));
}
return boughtLevels;
}
public void resetDailyMissions() {
// TODO
}
public void resetWeeklyMissions() {
// TODO
}
//
public BattlePassSchedule getScheduleProto() {
BattlePassSchedule.Builder schedule = BattlePassSchedule.newBuilder()
.setScheduleId(2700)
.setLevel(this.getLevel())
.setPoint(this.getPoint())
.setBeginTime(0)
.setEndTime(2059483200)
.setIsViewed(this.isViewed())
.setUnlockStatus(this.isPaid() ? BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_PAID : BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_FREE)
.setCurCyclePoints(this.getCyclePoints())
.setCurCycle(BattlePassCycle.newBuilder().setBeginTime(0).setEndTime(2059483200).setCycleIdx(3));
for (BattlePassReward reward : getTakenRewards().values()) {
schedule.addRewardTakenList(reward.toProto());
}
return schedule.build();
}
public void save() {
DatabaseHelper.saveBattlePass(this);
}
......
package emu.grasscutter.game.battlepass;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Transient;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.BattlePassMissionData;
import emu.grasscutter.game.props.BattlePassMissionStatus;
@Entity
public class BattlePassMission {
private int id;
private int progress;
private BattlePassMissionStatus status;
@Transient
private BattlePassMissionData data;
@Deprecated // Morphia only
public BattlePassMission() {}
public BattlePassMission(int id) {
this.id = id;
}
public int getId() {
return id;
}
public BattlePassMissionData getData() {
if (this.data == null) {
this.data = GameData.getBattlePassMissionDataMap().get(getId());
}
return this.data;
}
public int getProgress() {
return progress;
}
public void addProgress(int addProgress, int maxProgress) {
this.progress = Math.min(addProgress + this.progress, maxProgress);
}
public BattlePassMissionStatus getStatus() {
if (status == null) status = BattlePassMissionStatus.MISSION_STATUS_UNFINISHED;
return status;
}
public void setStatus(BattlePassMissionStatus status) {
this.status = status;
}
public boolean isFinshed() {
return getStatus().getValue() >= 2;
}
public emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission toProto() {
var protoBuilder = emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission.newBuilder();
protoBuilder
.setMissionId(getId())
.setCurProgress(getProgress())
.setTotalProgress(getData().getProgress())
.setRewardBattlePassPoint(getData().getAddPoint())
.setMissionStatus(getStatus().getMissionStatus())
.setMissionType(getData().getRefreshType() == null ? 0 : getData().getRefreshType().getValue());
return protoBuilder.build();
}
}
package emu.grasscutter.game.battlepass;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.BattlePassMissionData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.BattlePassMissionRefreshType;
import emu.grasscutter.game.props.BattlePassMissionStatus;
import emu.grasscutter.game.props.WatcherTriggerType;
import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.packet.send.PacketBattlePassMissionUpdateNotify;
public class BattlePassMissionManager {
private final GameServer server;
private final Map<WatcherTriggerType, List<BattlePassMissionData>> cachedTriggers;
// BP Mission manager for the server, contains cached triggers so we dont have to load it for each player
public BattlePassMissionManager(GameServer server) {
this.server = server;
this.cachedTriggers = new HashMap<>();
for (BattlePassMissionData missionData : GameData.getBattlePassMissionDataMap().values()) {
if (missionData.isValidRefreshType()) {
List<BattlePassMissionData> triggerList = getTriggers().computeIfAbsent(missionData.getTriggerType(), e -> new ArrayList<>());
triggerList.add(missionData);
}
}
}
public GameServer getServer() {
return server;
}
private Map<WatcherTriggerType, List<BattlePassMissionData>> getTriggers() {
return cachedTriggers;
}
public void triggerMission(Player player, WatcherTriggerType triggerType) {
triggerMission(player, triggerType, 0, 1);
}
public void triggerMission(Player player, WatcherTriggerType triggerType, int param, int progress) {
List<BattlePassMissionData> triggerList = getTriggers().get(triggerType);
if (triggerList == null || triggerList.isEmpty()) return;
for (BattlePassMissionData data : triggerList) {
// Skip params check if param == 0
if (param != 0) {
if (!data.getMainParams().contains(param)) {
continue;
}
}
// Get mission from player, if it doesnt exist, then we make one
BattlePassMission mission = player.getBattlePassManager().loadMissionById(data.getId());
if (mission.isFinshed()) continue;
// Add progress
mission.addProgress(progress, data.getProgress());
if (mission.getProgress() >= data.getProgress()) {
mission.setStatus(BattlePassMissionStatus.MISSION_STATUS_FINISHED);
}
// Save to db
player.getBattlePassManager().save();
// Packet
player.sendPacket(new PacketBattlePassMissionUpdateNotify(mission));
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment