From 0e44d18ae94380a7dd6f1e034a25d02bd208ef5b Mon Sep 17 00:00:00 2001 From: Thoronium <107363768+NotThorny@users.noreply.github.com> Date: Sat, 16 Sep 2023 15:31:59 -0600 Subject: [PATCH] Better SceneTags (#2361) * Add scene tag handling * Move warns to debug * Move to PlayerProgressManager * Add success message * Inline check * Improve per-scene handling * Update src/main/java/emu/grasscutter/command/commands/SetSceneTagCommand.java Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com> * Update src/main/java/emu/grasscutter/command/commands/SetSceneTagCommand.java Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com> * Fix types * Small fix * Update ScriptLib.java --------- Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com> --- .../command/commands/SetSceneTagCommand.java | 98 +++++++++++++++++++ .../emu/grasscutter/game/player/Player.java | 21 ++++ .../game/player/PlayerProgressManager.java | 26 +++++ .../emu/grasscutter/scripts/ScriptLib.java | 14 +-- .../recv/HandlerSceneInitFinishReq.java | 2 +- .../PacketPlayerWorldSceneInfoListNotify.java | 88 +++++++---------- src/main/resources/languages/en-US.json | 3 + src/main/resources/languages/es-ES.json | 3 + src/main/resources/languages/fr-FR.json | 3 + src/main/resources/languages/it-IT.json | 3 + src/main/resources/languages/ja-JP.json | 3 + src/main/resources/languages/ko-KR.json | 3 + src/main/resources/languages/pl-PL.json | 3 + src/main/resources/languages/ro-RO.json | 3 + src/main/resources/languages/ru-RU.json | 3 + src/main/resources/languages/zh-CN.json | 3 + src/main/resources/languages/zh-TW.json | 3 + 17 files changed, 221 insertions(+), 61 deletions(-) create mode 100644 src/main/java/emu/grasscutter/command/commands/SetSceneTagCommand.java diff --git a/src/main/java/emu/grasscutter/command/commands/SetSceneTagCommand.java b/src/main/java/emu/grasscutter/command/commands/SetSceneTagCommand.java new file mode 100644 index 000000000..fcef0d165 --- /dev/null +++ b/src/main/java/emu/grasscutter/command/commands/SetSceneTagCommand.java @@ -0,0 +1,98 @@ +package emu.grasscutter.command.commands; + +import emu.grasscutter.command.*; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.scene.SceneTagData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.packet.send.*; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import lombok.val; + +import java.util.*; + +@Command(label = "setSceneTag", aliases = { "tag" }, usage = { + " " }, permission = "player.setscenetag", permissionTargeted = "player.setscenetag.others") +public final class SetSceneTagCommand implements CommandHandler { + private final Int2ObjectMap sceneTagData = GameData.getSceneTagDataMap(); + + @Override + public void execute(Player sender, Player targetPlayer, List args) { + if (args.size() == 0) { + sendUsageMessage(sender); + return; + } + + val actionStr = args.get(0).toLowerCase(); + var value = -1; + + if (args.size() > 1) { + try { + value = Integer.parseInt(args.get(1)); + } catch (NumberFormatException ignored) { + CommandHandler.sendTranslatedMessage(sender, "commands.execution.argument_error"); + return; + } + } else { + if (actionStr.equals("unlockall")) { + unlockAllSceneTags(targetPlayer); + return; + } else { + CommandHandler.sendTranslatedMessage(sender, "commands.execution.argument_error"); + return; + } + } + + val userVal = value; + + var sceneData = sceneTagData.values().stream().filter(sceneTag -> sceneTag.getId() == userVal).findFirst(); + if (sceneData == null) { + CommandHandler.sendTranslatedMessage(sender, "commands.generic.invalid.id"); + return; + } + int scene = sceneData.get().getSceneId(); + + switch (actionStr) { + case "add", "set" -> addSceneTag(targetPlayer, scene, value); + case "remove", "del" -> removeSceneTag(targetPlayer, scene, value); + default -> CommandHandler.sendTranslatedMessage(sender, "commands.execution.argument_error"); + } + + CommandHandler.sendTranslatedMessage(sender, "commands.generic.set_to", value, actionStr); + + } + + private void addSceneTag(Player targetPlayer, int scene, int value) { + targetPlayer.getProgressManager().addSceneTag(scene, value); + } + + private void removeSceneTag(Player targetPlayer, int scene, int value) { + targetPlayer.getProgressManager().delSceneTag(scene, value); + } + + private void unlockAllSceneTags(Player targetPlayer) { + var allData = sceneTagData.values(); + + // Add all SceneTags + allData.stream().toList().forEach(sceneTag -> { + if (targetPlayer.getSceneTags().get(sceneTag.getSceneId()) == null) { + targetPlayer.getSceneTags().put(sceneTag.getSceneId(), new HashSet<>()); + } + targetPlayer.getSceneTags().get(sceneTag.getSceneId()).add(sceneTag.getId()); + }); + + // Remove default SceneTags, as most are "before" or "locked" states + allData.stream().filter(sceneTag -> sceneTag.isDefaultValid()) + // Only remove for big world as some other scenes only have defaults + .filter(sceneTag -> sceneTag.getSceneId() == 3) + .forEach(sceneTag -> { + targetPlayer.getSceneTags().get(sceneTag.getSceneId()).remove(sceneTag.getId()); + }); + + this.setSceneTags(targetPlayer); + } + + private void setSceneTags(Player targetPlayer) { + targetPlayer.sendPacket(new PacketPlayerWorldSceneInfoListNotify(targetPlayer)); + } + +} diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index 5adc13b80..25b1f66f0 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -116,6 +116,7 @@ public class Player implements PlayerHook, FieldFetch { @Getter private Map activeCookCompounds; @Getter private Map questGlobalVariables; @Getter private Map openStates; + @Getter private Map> sceneTags; @Getter @Setter private Map> unlockedSceneAreas; @Getter @Setter private Map> unlockedScenePoints; @Getter @Setter private List chatEmojiIdList; @@ -244,6 +245,7 @@ public class Player implements PlayerHook, FieldFetch { this.unlockedRecipies = new HashMap<>(); this.questGlobalVariables = new HashMap<>(); this.openStates = new HashMap<>(); + this.sceneTags = new HashMap<>(); this.unlockedSceneAreas = new HashMap<>(); this.unlockedScenePoints = new HashMap<>(); this.chatEmojiIdList = new ArrayList<>(); @@ -295,6 +297,7 @@ public class Player implements PlayerHook, FieldFetch { this.codex = new PlayerCodex(this); this.applyProperties(); + this.applyStartingSceneTags(); this.getFlyCloakList().add(140001); this.getNameCardList().add(210001); @@ -587,6 +590,20 @@ public class Player implements PlayerHook, FieldFetch { this.getProperty(PlayerProperty.PROP_DIVE_MAX_STAMINA)); } + /** + * Applies all default scenetags to the player. + */ + private void applyStartingSceneTags() { + GameData.getSceneTagDataMap().values().stream() + .filter(sceneTag -> sceneTag.isDefaultValid()) + .forEach(sceneTag -> { + if (this.getSceneTags().get(sceneTag.getSceneId()) == null) { + this.getSceneTags().put(sceneTag.getSceneId(), new HashSet<>()); + } + this.getSceneTags().get(sceneTag.getSceneId()).add(sceneTag.getId()); + }); + } + /** * Applies a property to the player if it doesn't exist in the database. * @@ -1384,6 +1401,10 @@ public class Player implements PlayerHook, FieldFetch { } */ + // Ensure the player has valid scenetags, allows old accounts to work + if (this.getSceneTags().isEmpty() || this.getSceneTags() == null) { + this.applyStartingSceneTags(); + } if (GameHome.HOME_SCENE_IDS.contains(this.getSceneId())) { this.setSceneId(this.prevScene <= 0 ? 3 : this.prevScene); // if the player in home, make the player go back. diff --git a/src/main/java/emu/grasscutter/game/player/PlayerProgressManager.java b/src/main/java/emu/grasscutter/game/player/PlayerProgressManager.java index 788928066..c284ad76b 100644 --- a/src/main/java/emu/grasscutter/game/player/PlayerProgressManager.java +++ b/src/main/java/emu/grasscutter/game/player/PlayerProgressManager.java @@ -12,6 +12,8 @@ import emu.grasscutter.game.quest.enums.*; import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; import emu.grasscutter.scripts.data.ScriptArgs; import emu.grasscutter.server.packet.send.*; + +import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; @@ -313,4 +315,28 @@ public final class PlayerProgressManager extends BasePlayerDataManager { player.save(); player.getQuestManager().queueEvent(QuestCond.QUEST_COND_HISTORY_GOT_ANY_ITEM, id, newCount); } + + /****************************************************************************************************************** + ****************************************************************************************************************** + * SCENETAGS + ****************************************************************************************************************** + *****************************************************************************************************************/ + public void addSceneTag(int sceneId, int sceneTagId) { + player.getSceneTags().computeIfAbsent(sceneId, k -> new HashSet<>()).add(sceneTagId); + player.sendPacket(new PacketPlayerWorldSceneInfoListNotify(player)); + } + + public void delSceneTag(int sceneId, int sceneTagId) { + // Sanity check + if (player.getSceneTags().get(sceneId) == null) { + // Can't delete something that doesn't exist + return; + } + player.getSceneTags().get(sceneId).remove(sceneTagId); + player.sendPacket(new PacketPlayerWorldSceneInfoListNotify(player)); + } + + public boolean checkSceneTag(int sceneId, int sceneTagId) { + return player.getSceneTags().get(sceneId).contains(sceneTagId); + } } diff --git a/src/main/java/emu/grasscutter/scripts/ScriptLib.java b/src/main/java/emu/grasscutter/scripts/ScriptLib.java index 4830a4a0d..48313204b 100644 --- a/src/main/java/emu/grasscutter/scripts/ScriptLib.java +++ b/src/main/java/emu/grasscutter/scripts/ScriptLib.java @@ -1013,22 +1013,22 @@ public class ScriptLib { } public int AddSceneTag(int sceneId, int sceneTagId){ - logger.warn("[LUA] Call unimplemented AddSceneTag with {}, {}", sceneId, sceneTagId); - //TODO implement + logger.debug("[LUA] Call AddSceneTag with {}, {}", sceneId, sceneTagId); + getSceneScriptManager().getScene().getHost().getProgressManager().addSceneTag(sceneId, sceneTagId); return 0; } public int DelSceneTag(int sceneId, int sceneTagId){ - logger.warn("[LUA] Call unimplemented DelSceneTag with {}, {}", sceneId, sceneTagId); - //TODO implement + logger.debug("[LUA] Call DelSceneTag with {}, {}", sceneId, sceneTagId); + getSceneScriptManager().getScene().getHost().getProgressManager().delSceneTag(sceneId, sceneTagId); return 0; } public boolean CheckSceneTag(int sceneId, int sceneTagId){ - logger.warn("[LUA] Call unimplemented CheckSceneTag with {}, {}", sceneId, sceneTagId); - //TODO implement - return false; + logger.debug("[LUA] Call CheckSceneTag with {}, {}", sceneId, sceneTagId); + return getSceneScriptManager().getScene().getHost().getProgressManager().checkSceneTag(sceneId, sceneTagId); } + public int StartHomeGallery(int galleryId, int uid){ logger.warn("[LUA] Call unimplemented StartHomeGallery with {} {}", galleryId, uid); //TODO implement diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java index 83484a512..99fc9e146 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java @@ -17,7 +17,7 @@ public class HandlerSceneInitFinishReq extends PacketHandler { session.send(new PacketServerTimeNotify()); session.send(new PacketWorldPlayerInfoNotify(world)); session.send(new PacketWorldDataNotify(world)); - session.send(new PacketPlayerWorldSceneInfoListNotify()); + session.send(new PacketPlayerWorldSceneInfoListNotify(player)); session.send(new BasePacket(PacketOpcodes.SceneForceUnlockNotify)); session.send(new PacketHostPlayerNotify(world)); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerWorldSceneInfoListNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerWorldSceneInfoListNotify.java index e81ddb617..dcf5ca43d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerWorldSceneInfoListNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerWorldSceneInfoListNotify.java @@ -1,46 +1,48 @@ package emu.grasscutter.server.packet.send; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.excels.scene.SceneTagData; +import emu.grasscutter.game.player.Player; import emu.grasscutter.net.packet.*; import emu.grasscutter.net.proto.MapLayerInfoOuterClass; import emu.grasscutter.net.proto.PlayerWorldSceneInfoListNotifyOuterClass.PlayerWorldSceneInfoListNotify; import emu.grasscutter.net.proto.PlayerWorldSceneInfoOuterClass.PlayerWorldSceneInfo; -import java.util.stream.IntStream; + +import java.util.Map; public class PacketPlayerWorldSceneInfoListNotify extends BasePacket { - public PacketPlayerWorldSceneInfoListNotify() { + public PacketPlayerWorldSceneInfoListNotify(Player player) { super(PacketOpcodes.PlayerWorldSceneInfoListNotify); // Rename opcode later + var sceneTags = player.getSceneTags(); + PlayerWorldSceneInfoListNotify.Builder proto = PlayerWorldSceneInfoListNotify.newBuilder() - .addInfoList(PlayerWorldSceneInfo.newBuilder().setSceneId(1).setIsLocked(false).build()) - .addInfoList( - PlayerWorldSceneInfo.newBuilder() - .setSceneId(3) - .setIsLocked(false) + .addInfoList(PlayerWorldSceneInfo.newBuilder().setSceneId(1).setIsLocked(false).build()); + + // Iterate over all scenes + for (int scene : GameData.getSceneDataMap().keySet()) { + var worldInfoBuilder = PlayerWorldSceneInfo.newBuilder() + .setSceneId(scene) + .setIsLocked(false); + + /** Add scene-specific data */ + + // Scenetags + if (sceneTags.keySet().contains(scene)) { + worldInfoBuilder .addAllSceneTagIdList( - GameData.getSceneTagDataMap().values().stream() - .filter(sceneTag -> sceneTag.getSceneId() == 3) - .filter( - sceneTag -> - sceneTag.isDefaultValid() - || sceneTag.getCond().get(0).getCondType() != null) - .map(SceneTagData::getId) - .toList()) - // .addSceneTagIdList(102) // Jade chamber (alr added) - // .addSceneTagIdList(113) - // .addSceneTagIdList(117) - // .addSceneTagIdList(1093) // 3.0 Vana_real - .addSceneTagIdList(1094) // 3.0 Vana_dream - // .addSceneTagIdList(1095) // 3.0 Vana_first - // .addSceneTagIdList(1096) // 3.0 Vana_festival - .addSceneTagIdList(152) // 3.1 event - .addSceneTagIdList(153) // 3.1 event - .addSceneTagIdList(1164) // Desert Arena (XMSM_CWLTop) - .addSceneTagIdList(1166) // Desert Pyramid (CWL_Trans_02) - .setMapLayerInfo( + sceneTags.entrySet().stream() + .filter(e -> e.getKey().equals(scene)) + .map(Map.Entry::getValue) + .toList() + .get(0) + ); + } + + // Map layer information (Big world) + if (scene == 3) { + worldInfoBuilder.setMapLayerInfo( MapLayerInfoOuterClass.MapLayerInfo.newBuilder() .addAllUnlockedMapLayerIdList( GameData.getMapLayerDataMap().keySet()) // MapLayer Ids @@ -49,31 +51,11 @@ public class PacketPlayerWorldSceneInfoListNotify extends BasePacket { .addAllUnlockedMapLayerGroupIdList( GameData.getMapLayerGroupDataMap() .keySet()) // will show MapLayer options when hovered over - .build()) // map layer test - .build()) - .addInfoList( - PlayerWorldSceneInfo.newBuilder() - .setSceneId(4) - .setIsLocked(false) - .addSceneTagIdList(106) - .addSceneTagIdList(109) - .addSceneTagIdList(117) - .build()) - .addInfoList(PlayerWorldSceneInfo.newBuilder().setSceneId(5).setIsLocked(false).build()) - .addInfoList(PlayerWorldSceneInfo.newBuilder().setSceneId(6).setIsLocked(false).build()) - .addInfoList(PlayerWorldSceneInfo.newBuilder().setSceneId(7).setIsLocked(false).build()) - .addInfoList( - PlayerWorldSceneInfo.newBuilder() - .setSceneId(9) - .setIsLocked(false) - .addAllSceneTagIdList(IntStream.range(0, 3000).boxed().toList()) - .build()) - .addInfoList( - PlayerWorldSceneInfo.newBuilder() - .setSceneId(10) - .setIsLocked(false) - .addAllSceneTagIdList(IntStream.range(0, 3000).boxed().toList()) - .build()); // 3.8 + .build()); // map layer test + } + + proto.addInfoList(worldInfoBuilder.build()); + } this.setData(proto); } diff --git a/src/main/resources/languages/en-US.json b/src/main/resources/languages/en-US.json index 24efee19a..22535e21b 100644 --- a/src/main/resources/languages/en-US.json +++ b/src/main/resources/languages/en-US.json @@ -324,6 +324,9 @@ "setProp": { "description": "Sets accountwide properties. Things like godmode can be enabled this way, as well as changing things like unlocked abyss floor and battle pass progress.\n\tValues for (case-insensitive): GodMode | UnlimitedStamina | UnlimitedEnergy | TowerLevel | WorldLevel | BPLevel | SetOpenState | UnsetOpenState | UnlockMap\n\t(cont.) see PlayerProperty enum for other possible values, of the form PROP_MAX_SPRING_VOLUME -> max_spring_volume" }, + "setSceneTag":{ + "description": "Sets account-specific scene tags. This controls things like rocks blocking doors, buildings being visible, and other (usually quest-related) things that affect what is visible in your world." + }, "setStats": { "description": "Sets fight property for your current active character\n\tValues for : hp | maxhp | def | atk | em | er | crate | cdmg | cdr | heal | heali | shield | defi\n\t(cont.) Elemental DMG Bonus: epyro | ecryo | ehydro | egeo | edendro | eelectro | ephys\n\t(cont.) Elemental RES: respyro | rescryo | reshydro | resgeo | resdendro | reselectro | resphys", "locked_to": "%s locked to %s.", diff --git a/src/main/resources/languages/es-ES.json b/src/main/resources/languages/es-ES.json index 4fe9759a3..dd0583e66 100644 --- a/src/main/resources/languages/es-ES.json +++ b/src/main/resources/languages/es-ES.json @@ -324,6 +324,9 @@ "setProp": { "description": "Establece propiedades de la cuenta. Cosas como el modo Dios pueden ser establecidos con este comando, además de cambiar cosas como desbloquear pisos del abismo o progreso del pase de batalla.\n\tValores para : godmode | nostamina | unlimitedenergy | abyss | worldlevel | bplevel\n\t(cont.) Observa PlayerProperty enum para ver otros posibles valores, de la forma PROP_MAX_SPRING_VOLUME -> max_spring_volume" }, + "setSceneTag":{ + "description": "Establece etiquetas de escena específicas de la cuenta. Esto controla cosas como rocas bloqueando puertas, edificios visibles y otras cosas (normalmente relacionadas con misiones) que afectan a lo que es visible en tu mundo." + }, "setStats": { "description": "Establece propiedades de combate para tu personaje actual\n\tValores para : hp | maxhp | def | atk | em | er | crate | cdmg | cdr | heal | heali | shield | defi\n\t(cont.) Bonus de daño elemental: epyro | ecryo | ehydro | egeo | edendro | eelectro | ephys\n\t(cont.) Resistencia elemental: respyro | rescryo | reshydro | resgeo | resdendro | reselectro | resphys", "locked_to": "%s fijado a %s.", diff --git a/src/main/resources/languages/fr-FR.json b/src/main/resources/languages/fr-FR.json index d4ff5bdec..e4dd36dd6 100644 --- a/src/main/resources/languages/fr-FR.json +++ b/src/main/resources/languages/fr-FR.json @@ -324,6 +324,9 @@ "setProp": { "description": "Définit des propriétes pour votre compte. Des choses comme le godemode peuvent être activés avec cette commande, et le déblocage de l'abysse ainsi que l'avancement du PB.\n\tValues for : godmode | nostamina | unlimitedenergy | abyss | worldlevel | bplevel\n\t(cont.) see PlayerProperty enum for other possible values, of form PROP_MAX_SPRING_VOLUME -> max_spring_volume" }, + "setSceneTag":{ + "description": "Définit les balises de scène spécifiques au compte. Cela permet de contrôler des choses comme les rochers qui bloquent les portes, les bâtiments qui sont visibles, et d'autres choses (généralement liées aux quêtes) qui affectent ce qui est visible dans votre monde." + }, "setStats": { "description": "Définit les propriétés de combat de votre personnage actif\n\tValeurs pour : hp | maxhp | def | atk | em | er | crate | cdmg | cdr | heal | heali | shield | defi\n\t(cont.) Bonus de dégât élémentaire: epyro | ecryo | ehydro | egeo | edendro | eelectro | ephys\n\t(cont.) Résistance élémentaire: respyro | rescryo | reshydro | resgeo | resdendro | reselectro | resphys", "locked_to": "%s verrouillé à %s.", diff --git a/src/main/resources/languages/it-IT.json b/src/main/resources/languages/it-IT.json index 9da88682d..d61dffcce 100644 --- a/src/main/resources/languages/it-IT.json +++ b/src/main/resources/languages/it-IT.json @@ -324,6 +324,9 @@ "setProp": { "description": "Imposta le proprietà dell'intero account. Cose come godmode possono essere abilitate in questo modo, oltre a cambiare cose come il pavimento dell'abisso sbloccato e il progresso del pass battaglia.\n\tValori per (senza distinzione tra maiuscole e minuscole): GodMode | UnlimitedStamina | UnlimitedEnergy | TowerLevel | WorldLevel | BPLevel | SetOpenState | UnsetOpenState | UnlockMap\n\t(cont.) vedi PlayerProperty enum per altri possibili valori, nella forma PROP_MAX_SPRING_VOLUME -> max_spring_volume" }, + "setSceneTag":{ + "description": "Imposta i tag di scena specifici dell'account. Questo controlla cose come le rocce che bloccano le porte, gli edifici visibili e altre cose (di solito legate alle missioni) che influenzano ciò che è visibile nel mondo." + }, "setStats": { "description": "Imposta la proprietà di combattimento per il tuo personaggio attivo corrente\n\tValori per : hp | maxhp | def | atk | em | er | crate | cdmg | cdr | heal | heali | shield | defi\n\t(cont.) Elemental DMG Bonus: epyro | ecryo | ehydro | egeo | edendro | eelectro | ephys\n\t(cont.) Elemental RES: respyro | rescryo | reshydro | resgeo | resdendro | reselectro | resphys", "locked_to": "%s bloccato a %s.", diff --git a/src/main/resources/languages/ja-JP.json b/src/main/resources/languages/ja-JP.json index 3072828b5..28a65ab08 100644 --- a/src/main/resources/languages/ja-JP.json +++ b/src/main/resources/languages/ja-JP.json @@ -324,6 +324,9 @@ "setProp": { "description": "アカウント全体のプロパティを設定します。 godmodeのようなものはこの方法で有効にすることができ、アンロックされた深淵の床やバトル パスの進行状況などを変更することもできます。\n\t の値: godmode | nostamina | unlimitedenergy | abyss | worldlevel | bplevel\n\tmax_spring_volume の形式の他の設定可能な値についてはPlayerPropertyを参照してください。" }, + "setSceneTag":{ + "description": "アカウント固有のシーンタグを設定します。これは岩がドアを塞いだり、建物が見えたり、その他(大抵はクエストに関連した)あなたのワールドで見えるものに影響を与えるものをコントロールします。" + }, "setStats": { "description": "現在アクティブ状態のステータスを設定します。\n\t の値: hp | maxhp | def | atk | em | er | crate | cdmg | cdr | heal | heali | shield | defi\n\t(cont.) Elemental DMG Bonus: epyro | ecryo | ehydro | egeo | edendro | eelectro | ephys\n\t(cont.) Elemental RES: respyro | rescryo | reshydro | resgeo | resdendro | reselectro | resphys", "locked_to": "%s は %s にロックされています。", diff --git a/src/main/resources/languages/ko-KR.json b/src/main/resources/languages/ko-KR.json index 6748b1799..d546a69dd 100644 --- a/src/main/resources/languages/ko-KR.json +++ b/src/main/resources/languages/ko-KR.json @@ -324,6 +324,9 @@ "setProp": { "description": "계정의 속성을 변경합니다. godmode등이 이를 통해 활성화 될 수 있으며, 나선비경을 잠금해제하거나, 기행의 레벨을 조정하는 등의 명령또한 이를 통해 가능합니다." }, + "setSceneTag":{ + "description": "계정별 장면 태그를 설정합니다. 이는 바위가 문을 막거나 건물이 보이거나, 월드에 표시되는 것에 영향을 주는 기타(주로 퀘스트 관련) 것들을 제어합니다." + }, "setStats": { "description": "당신의 현재 캐릭터의 스텟들을 조절합니다.", "locked_to": "%s가 %s로 잠겨있습니다.", diff --git a/src/main/resources/languages/pl-PL.json b/src/main/resources/languages/pl-PL.json index 440e5b455..ce32f6408 100644 --- a/src/main/resources/languages/pl-PL.json +++ b/src/main/resources/languages/pl-PL.json @@ -324,6 +324,9 @@ "setProp": { "description": "Ustaw pewne własności konta, takie jak tryb nieśmiertelności (godmode) czy też zmiana postępu Battle Pass.\n\tMożliwe nazwy własności: godmode | nostamina | unlimitedenergy | abyss | worldlevel | bplevel | ...\n\tTa komenda ma więcej nazw własności, które może otrzymać. Możesz je wszystkie zobaczyć w pliku \"game/props/PlayerProperty.java\".\n\tW tym pliku, przyjmują one formę \"PROP_XXX_YYY_ZZZ\", ale powinieneś je zapisywać jako \"xxx_yyy_zzz\" jeśli chcesz je użyć w tej komendzie." }, + "setSceneTag":{ + "description": "Ustawia znaczniki sceny specyficzne dla konta. Kontroluje to takie rzeczy jak skały blokujące drzwi, widoczne budynki i inne (zwykle związane z zadaniami) rzeczy, które wpływają na to, co jest widoczne w twoim świecie." + }, "setStats": { "description": "Ustaw statystykę walki dla obecnie wybranej postaci wybranego gracza.\n\tMożliwe nazwy statystyki: hp | maxhp | def | atk | em | er | crate | cdmg | cdr | heal | heali | shield | defi\n\tDodatkowe obrażenia od żywiołu: epyro | ecryo | ehydro | egeo | edendro | eelectro | ephys\n\tOdporność na żywioł: respyro | rescryo | reshydro | resgeo | resdendro | reselectro | resphys", "locked_to": "%s zablokowano dla %s.", diff --git a/src/main/resources/languages/ro-RO.json b/src/main/resources/languages/ro-RO.json index fcfd43c63..44e040396 100644 --- a/src/main/resources/languages/ro-RO.json +++ b/src/main/resources/languages/ro-RO.json @@ -324,6 +324,9 @@ "setProp": { "description": "Stabilește proprietățile la nivel de cont. Lucruri precum godmode pot fi activate în acest fel, precum și schimbarea unor lucuri precum etajul abisului deblocat și progresul battle pass.\n\tValori pentru : godmode | nostamina | unlimitedenergy | abyss | worldlevel | bplevel\n\t(cont.) see PlayerProperty enum for other possible values, of form PROP_MAX_SPRING_VOLUME -> max_spring_volume" }, + "setSceneTag":{ + "description": "Stabilește etichetele de scenă specifice contului. Aceasta controlează lucruri precum rocile care blochează ușile, clădirile care sunt vizibile și alte lucruri (de obicei legate de misiuni) care afectează ceea ce este vizibil în lumea ta." + }, "setStats": { "description": "Stabilește proprietatea de luptă pentru caracterul activ curent.\n\tValori pentru : hp | maxhp | def | atk | em | er | crate | cdmg | cdr | heal | heali | shield | defi\n\t(cont.) Elemental DMG Bonus: epyro | ecryo | ehydro | egeo | edendro | eelectro | ephys\n\t(cont.) Elemental RES: respyro | rescryo | reshydro | resgeo | resdendro | reselectro | resphys", "locked_to": "🇺🇸%s locked to %s.", diff --git a/src/main/resources/languages/ru-RU.json b/src/main/resources/languages/ru-RU.json index 74f0c6417..b4034c2c7 100644 --- a/src/main/resources/languages/ru-RU.json +++ b/src/main/resources/languages/ru-RU.json @@ -324,6 +324,9 @@ "setProp": { "description": "Задаёт свойства аккаунта. С помощью данной команды может быть включен godmode, а также разблокированы этажи Коридора Бездны и изменён прогресс боевого пропуска.\n\tВозможные значения <св-во>: godmode | nostamina | unlimitedenergy | abyss | worldlevel | bplevel\n\t(прод.) см. перечисление (enum) PlayerProperty для остальных возможных значений, of form PROP_MAX_SPRING_VOLUME -> max_spring_volume" }, + "setSceneTag":{ + "description": "Устанавливает специфические для учетной записи теги сцены. Это позволяет управлять такими вещами, как камни, блокирующие двери, видимость зданий и другими (обычно связанными с квестами) вещами, которые влияют на видимость в вашем мире." + }, "setStats": { "description": "Задаёт боевые характеристики для активного персонажа\n\tВозможные значения <хар-ка>: hp | maxhp | def | atk | em | er | crate | cdmg | cdr | heal | heali | shield | defi\n\t(прод.) Бонус элементального урона: epyro | ecryo | ehydro | egeo | edendro | eelectro | ephys\n\t(прод.) Элементальное сопротивление: respyro | rescryo | reshydro | resgeo | resdendro | reselectro | resphys", "locked_to": "%s зафиксировано на значении %s.", diff --git a/src/main/resources/languages/zh-CN.json b/src/main/resources/languages/zh-CN.json index 7236783f9..a1b659242 100644 --- a/src/main/resources/languages/zh-CN.json +++ b/src/main/resources/languages/zh-CN.json @@ -324,6 +324,9 @@ "setProp": { "description": "设置账号的状态。比如可以通过此命令启用 GodMode,也可以解锁深渊或更改纪行等级\n\t可更改的状态列表(不区分大小写):GodMode(上帝模式)|UnlimitedStamina(无限体力)|UnlimitedEnergy(无限能量)|TowerLevel(深渊)|WorldLevel(世界等级)|BPLevel(纪行等级)|SetOpenState(设置开放状态)|UnsetOpenState(取消开放状态)|UnlockMap(解锁地图)\n\t查看 PlayerProperty enum 以获得其他数值,格式为 PROP_MAX_SPRING_VOLUME -> max_spring_volume" }, + "setSceneTag":{ + "description": "设置特定于账户的场景标签。这可以控制诸如石头挡住门、建筑物可见以及其他(通常与任务相关)影响世界可见度的事物。" + }, "setStats": { "description": "设置当前角色的属性\n\t可更改的属性列表:hp(生命值)|maxhp(最大生命值)|def(防御力)|atk(攻击力)|em(元素精通)|er(元素充能效率)|crate(暴击率)|cdmg(暴击伤害)|cdr(冷却缩减)|heal(治疗加成)|heali(受治疗加成)|shield(护盾强效)|defi(无视防御)\n\t元素增伤:epyro(火)|ecryo(冰)|ehydro(水)|egeo(岩)|edendro(草)|eelectro(雷)|ephys(物理)\n\t元素抗性:respyro(火)|rescryo(冰)|reshydro(水)|resgeo(岩)|resdendro(草)|reselectro(雷)|resphys(物理)", "locked_to": "%s 已锁定为 %s。", diff --git a/src/main/resources/languages/zh-TW.json b/src/main/resources/languages/zh-TW.json index 3fd663950..f208b12b4 100644 --- a/src/main/resources/languages/zh-TW.json +++ b/src/main/resources/languages/zh-TW.json @@ -324,6 +324,9 @@ "setProp": { "description": "設定帳號屬性。比如可以通過此命令啟用無敵,也可以解鎖深淵或更改紀行等級。\n\t可更改的屬性列表: godmode(無敵)|nostamina(無限體力)|unlimitedenergy(無限元素能量)|abyss(深淵螺旋)|worldlevel(世界等級)|bplevel(紀行等級)\n\t(cont.) `有關其他可能的數值,請參閱 PlayerProperty 列舉。 (範例 PROP_MAX_SPRING_VOLUME -> max_spring_volume)`" }, + "setSceneTag":{ + "description": "設置帳戶特定的場景標籤。 這可以控制諸如擋住門的岩石、可見的建築物以及影響世界中可見內容的其他(通常與任務相關)的事物。" + }, "setStats": { "description": "設定目前角色的數據類型。\n\t可使用的數據類型:hp (生命值)| maxhp (最大生命值) | def(防禦力) | atk (攻擊力)| em (元素精通) | er (元素充能效率) | crate(暴擊率) | cdmg (暴擊傷害)| cdr (冷卻縮減) | heal(治療加成)| heali (受治療加成)| shield (護盾強效)| defi (無視防禦)\n\t(cont.) 元素增傷類:epyro (火傷) | ecryo (冰傷) | ehydro (水傷) | egeo (岩傷) | edendro (草傷) | eelectro (雷傷) | ephys (物傷)(cont.) 元素減傷類:respyro (火抗) | rescryo (冰抗) | reshydro (水抗) | resgeo (岩抗) | resdendro (草抗) | reselectro (雷抗) | resphys (物抗)", "locked_to": "%s 已鎖定為 %s.",