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>
This commit is contained in:
Thoronium 2023-09-16 15:31:59 -06:00 committed by GitHub
parent 5bd8f532c1
commit 0e44d18ae9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 221 additions and 61 deletions

View File

@ -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 = {
"<add|remove|unlockall> <sceneTagId>" }, permission = "player.setscenetag", permissionTargeted = "player.setscenetag.others")
public final class SetSceneTagCommand implements CommandHandler {
private final Int2ObjectMap<SceneTagData> sceneTagData = GameData.getSceneTagDataMap();
@Override
public void execute(Player sender, Player targetPlayer, List<String> 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));
}
}

View File

@ -116,6 +116,7 @@ public class Player implements PlayerHook, FieldFetch {
@Getter private Map<Integer, ActiveCookCompoundData> activeCookCompounds; @Getter private Map<Integer, ActiveCookCompoundData> activeCookCompounds;
@Getter private Map<Integer, Integer> questGlobalVariables; @Getter private Map<Integer, Integer> questGlobalVariables;
@Getter private Map<Integer, Integer> openStates; @Getter private Map<Integer, Integer> openStates;
@Getter private Map<Integer, Set<Integer>> sceneTags;
@Getter @Setter private Map<Integer, Set<Integer>> unlockedSceneAreas; @Getter @Setter private Map<Integer, Set<Integer>> unlockedSceneAreas;
@Getter @Setter private Map<Integer, Set<Integer>> unlockedScenePoints; @Getter @Setter private Map<Integer, Set<Integer>> unlockedScenePoints;
@Getter @Setter private List<Integer> chatEmojiIdList; @Getter @Setter private List<Integer> chatEmojiIdList;
@ -244,6 +245,7 @@ public class Player implements PlayerHook, FieldFetch {
this.unlockedRecipies = new HashMap<>(); this.unlockedRecipies = new HashMap<>();
this.questGlobalVariables = new HashMap<>(); this.questGlobalVariables = new HashMap<>();
this.openStates = new HashMap<>(); this.openStates = new HashMap<>();
this.sceneTags = new HashMap<>();
this.unlockedSceneAreas = new HashMap<>(); this.unlockedSceneAreas = new HashMap<>();
this.unlockedScenePoints = new HashMap<>(); this.unlockedScenePoints = new HashMap<>();
this.chatEmojiIdList = new ArrayList<>(); this.chatEmojiIdList = new ArrayList<>();
@ -295,6 +297,7 @@ public class Player implements PlayerHook, FieldFetch {
this.codex = new PlayerCodex(this); this.codex = new PlayerCodex(this);
this.applyProperties(); this.applyProperties();
this.applyStartingSceneTags();
this.getFlyCloakList().add(140001); this.getFlyCloakList().add(140001);
this.getNameCardList().add(210001); this.getNameCardList().add(210001);
@ -587,6 +590,20 @@ public class Player implements PlayerHook, FieldFetch {
this.getProperty(PlayerProperty.PROP_DIVE_MAX_STAMINA)); 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. * 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())) { 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. this.setSceneId(this.prevScene <= 0 ? 3 : this.prevScene); // if the player in home, make the player go back.

View File

@ -12,6 +12,8 @@ import emu.grasscutter.game.quest.enums.*;
import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
import emu.grasscutter.scripts.data.ScriptArgs; import emu.grasscutter.scripts.data.ScriptArgs;
import emu.grasscutter.server.packet.send.*; import emu.grasscutter.server.packet.send.*;
import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -313,4 +315,28 @@ public final class PlayerProgressManager extends BasePlayerDataManager {
player.save(); player.save();
player.getQuestManager().queueEvent(QuestCond.QUEST_COND_HISTORY_GOT_ANY_ITEM, id, newCount); 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);
}
} }

View File

@ -1013,22 +1013,22 @@ public class ScriptLib {
} }
public int AddSceneTag(int sceneId, int sceneTagId){ public int AddSceneTag(int sceneId, int sceneTagId){
logger.warn("[LUA] Call unimplemented AddSceneTag with {}, {}", sceneId, sceneTagId); logger.debug("[LUA] Call AddSceneTag with {}, {}", sceneId, sceneTagId);
//TODO implement getSceneScriptManager().getScene().getHost().getProgressManager().addSceneTag(sceneId, sceneTagId);
return 0; return 0;
} }
public int DelSceneTag(int sceneId, int sceneTagId){ public int DelSceneTag(int sceneId, int sceneTagId){
logger.warn("[LUA] Call unimplemented DelSceneTag with {}, {}", sceneId, sceneTagId); logger.debug("[LUA] Call DelSceneTag with {}, {}", sceneId, sceneTagId);
//TODO implement getSceneScriptManager().getScene().getHost().getProgressManager().delSceneTag(sceneId, sceneTagId);
return 0; return 0;
} }
public boolean CheckSceneTag(int sceneId, int sceneTagId){ public boolean CheckSceneTag(int sceneId, int sceneTagId){
logger.warn("[LUA] Call unimplemented CheckSceneTag with {}, {}", sceneId, sceneTagId); logger.debug("[LUA] Call CheckSceneTag with {}, {}", sceneId, sceneTagId);
//TODO implement return getSceneScriptManager().getScene().getHost().getProgressManager().checkSceneTag(sceneId, sceneTagId);
return false;
} }
public int StartHomeGallery(int galleryId, int uid){ public int StartHomeGallery(int galleryId, int uid){
logger.warn("[LUA] Call unimplemented StartHomeGallery with {} {}", galleryId, uid); logger.warn("[LUA] Call unimplemented StartHomeGallery with {} {}", galleryId, uid);
//TODO implement //TODO implement

View File

@ -17,7 +17,7 @@ public class HandlerSceneInitFinishReq extends PacketHandler {
session.send(new PacketServerTimeNotify()); session.send(new PacketServerTimeNotify());
session.send(new PacketWorldPlayerInfoNotify(world)); session.send(new PacketWorldPlayerInfoNotify(world));
session.send(new PacketWorldDataNotify(world)); session.send(new PacketWorldDataNotify(world));
session.send(new PacketPlayerWorldSceneInfoListNotify()); session.send(new PacketPlayerWorldSceneInfoListNotify(player));
session.send(new BasePacket(PacketOpcodes.SceneForceUnlockNotify)); session.send(new BasePacket(PacketOpcodes.SceneForceUnlockNotify));
session.send(new PacketHostPlayerNotify(world)); session.send(new PacketHostPlayerNotify(world));

View File

@ -1,46 +1,48 @@
package emu.grasscutter.server.packet.send; package emu.grasscutter.server.packet.send;
import emu.grasscutter.data.GameData; 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.packet.*;
import emu.grasscutter.net.proto.MapLayerInfoOuterClass; import emu.grasscutter.net.proto.MapLayerInfoOuterClass;
import emu.grasscutter.net.proto.PlayerWorldSceneInfoListNotifyOuterClass.PlayerWorldSceneInfoListNotify; import emu.grasscutter.net.proto.PlayerWorldSceneInfoListNotifyOuterClass.PlayerWorldSceneInfoListNotify;
import emu.grasscutter.net.proto.PlayerWorldSceneInfoOuterClass.PlayerWorldSceneInfo; import emu.grasscutter.net.proto.PlayerWorldSceneInfoOuterClass.PlayerWorldSceneInfo;
import java.util.stream.IntStream;
import java.util.Map;
public class PacketPlayerWorldSceneInfoListNotify extends BasePacket { public class PacketPlayerWorldSceneInfoListNotify extends BasePacket {
public PacketPlayerWorldSceneInfoListNotify() { public PacketPlayerWorldSceneInfoListNotify(Player player) {
super(PacketOpcodes.PlayerWorldSceneInfoListNotify); // Rename opcode later super(PacketOpcodes.PlayerWorldSceneInfoListNotify); // Rename opcode later
var sceneTags = player.getSceneTags();
PlayerWorldSceneInfoListNotify.Builder proto = PlayerWorldSceneInfoListNotify.Builder proto =
PlayerWorldSceneInfoListNotify.newBuilder() PlayerWorldSceneInfoListNotify.newBuilder()
.addInfoList(PlayerWorldSceneInfo.newBuilder().setSceneId(1).setIsLocked(false).build()) .addInfoList(PlayerWorldSceneInfo.newBuilder().setSceneId(1).setIsLocked(false).build());
.addInfoList(
PlayerWorldSceneInfo.newBuilder() // Iterate over all scenes
.setSceneId(3) for (int scene : GameData.getSceneDataMap().keySet()) {
.setIsLocked(false) var worldInfoBuilder = PlayerWorldSceneInfo.newBuilder()
.setSceneId(scene)
.setIsLocked(false);
/** Add scene-specific data */
// Scenetags
if (sceneTags.keySet().contains(scene)) {
worldInfoBuilder
.addAllSceneTagIdList( .addAllSceneTagIdList(
GameData.getSceneTagDataMap().values().stream() sceneTags.entrySet().stream()
.filter(sceneTag -> sceneTag.getSceneId() == 3) .filter(e -> e.getKey().equals(scene))
.filter( .map(Map.Entry::getValue)
sceneTag -> .toList()
sceneTag.isDefaultValid() .get(0)
|| sceneTag.getCond().get(0).getCondType() != null) );
.map(SceneTagData::getId) }
.toList())
// .addSceneTagIdList(102) // Jade chamber (alr added) // Map layer information (Big world)
// .addSceneTagIdList(113) if (scene == 3) {
// .addSceneTagIdList(117) worldInfoBuilder.setMapLayerInfo(
// .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(
MapLayerInfoOuterClass.MapLayerInfo.newBuilder() MapLayerInfoOuterClass.MapLayerInfo.newBuilder()
.addAllUnlockedMapLayerIdList( .addAllUnlockedMapLayerIdList(
GameData.getMapLayerDataMap().keySet()) // MapLayer Ids GameData.getMapLayerDataMap().keySet()) // MapLayer Ids
@ -49,31 +51,11 @@ public class PacketPlayerWorldSceneInfoListNotify extends BasePacket {
.addAllUnlockedMapLayerGroupIdList( .addAllUnlockedMapLayerGroupIdList(
GameData.getMapLayerGroupDataMap() GameData.getMapLayerGroupDataMap()
.keySet()) // will show MapLayer options when hovered over .keySet()) // will show MapLayer options when hovered over
.build()) // map layer test .build()); // map layer test
.build()) }
.addInfoList(
PlayerWorldSceneInfo.newBuilder() proto.addInfoList(worldInfoBuilder.build());
.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
this.setData(proto); this.setData(proto);
} }

View File

@ -324,6 +324,9 @@
"setProp": { "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 <prop> (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" "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 <prop> (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": { "setStats": {
"description": "Sets fight property for your current active character\n\tValues for <stat>: 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", "description": "Sets fight property for your current active character\n\tValues for <stat>: 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.", "locked_to": "%s locked to %s.",

View File

@ -324,6 +324,9 @@
"setProp": { "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 <prop>: 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" "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 <prop>: 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": { "setStats": {
"description": "Establece propiedades de combate para tu personaje actual\n\tValores para <estado>: 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", "description": "Establece propiedades de combate para tu personaje actual\n\tValores para <estado>: 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.", "locked_to": "%s fijado a %s.",

View File

@ -324,6 +324,9 @@
"setProp": { "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 <prop>: 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" "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 <prop>: 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": { "setStats": {
"description": "Définit les propriétés de combat de votre personnage actif\n\tValeurs pour <stat>: 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", "description": "Définit les propriétés de combat de votre personnage actif\n\tValeurs pour <stat>: 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.", "locked_to": "%s verrouillé à %s.",

View File

@ -324,6 +324,9 @@
"setProp": { "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 <prop> (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" "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 <prop> (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": { "setStats": {
"description": "Imposta la proprietà di combattimento per il tuo personaggio attivo corrente\n\tValori per <stat>: 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", "description": "Imposta la proprietà di combattimento per il tuo personaggio attivo corrente\n\tValori per <stat>: 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.", "locked_to": "%s bloccato a %s.",

View File

@ -324,6 +324,9 @@
"setProp": { "setProp": {
"description": "アカウント全体のプロパティを設定します。 godmodeのようなものはこの方法で有効にすることができ、アンロックされた深淵の床やバトル パスの進行状況などを変更することもできます。\n\t<prop> の値: godmode | nostamina | unlimitedenergy | abyss | worldlevel | bplevel\n\tmax_spring_volume の形式の他の設定可能な値についてはPlayerPropertyを参照してください。" "description": "アカウント全体のプロパティを設定します。 godmodeのようなものはこの方法で有効にすることができ、アンロックされた深淵の床やバトル パスの進行状況などを変更することもできます。\n\t<prop> の値: godmode | nostamina | unlimitedenergy | abyss | worldlevel | bplevel\n\tmax_spring_volume の形式の他の設定可能な値についてはPlayerPropertyを参照してください。"
}, },
"setSceneTag":{
"description": "アカウント固有のシーンタグを設定します。これは岩がドアを塞いだり、建物が見えたり、その他(大抵はクエストに関連した)あなたのワールドで見えるものに影響を与えるものをコントロールします。"
},
"setStats": { "setStats": {
"description": "現在アクティブ状態のステータスを設定します。\n\t <stat>の値: 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", "description": "現在アクティブ状態のステータスを設定します。\n\t <stat>の値: 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 にロックされています。", "locked_to": "%s は %s にロックされています。",

View File

@ -324,6 +324,9 @@
"setProp": { "setProp": {
"description": "계정의 속성을 변경합니다. godmode등이 이를 통해 활성화 될 수 있으며, 나선비경을 잠금해제하거나, 기행의 레벨을 조정하는 등의 명령또한 이를 통해 가능합니다." "description": "계정의 속성을 변경합니다. godmode등이 이를 통해 활성화 될 수 있으며, 나선비경을 잠금해제하거나, 기행의 레벨을 조정하는 등의 명령또한 이를 통해 가능합니다."
}, },
"setSceneTag":{
"description": "계정별 장면 태그를 설정합니다. 이는 바위가 문을 막거나 건물이 보이거나, 월드에 표시되는 것에 영향을 주는 기타(주로 퀘스트 관련) 것들을 제어합니다."
},
"setStats": { "setStats": {
"description": "당신의 현재 캐릭터의 스텟들을 조절합니다.", "description": "당신의 현재 캐릭터의 스텟들을 조절합니다.",
"locked_to": "%s가 %s로 잠겨있습니다.", "locked_to": "%s가 %s로 잠겨있습니다.",

View File

@ -324,6 +324,9 @@
"setProp": { "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." "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": { "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", "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.", "locked_to": "%s zablokowano dla %s.",

View File

@ -324,6 +324,9 @@
"setProp": { "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 <prop>: 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" "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 <prop>: 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": { "setStats": {
"description": "Stabilește proprietatea de luptă pentru caracterul activ curent.\n\tValori pentru <stat>: 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", "description": "Stabilește proprietatea de luptă pentru caracterul activ curent.\n\tValori pentru <stat>: 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.", "locked_to": "🇺🇸%s locked to %s.",

View File

@ -324,6 +324,9 @@
"setProp": { "setProp": {
"description": "Задаёт свойства аккаунта. С помощью данной команды может быть включен godmode, а также разблокированы этажи Коридора Бездны и изменён прогресс боевого пропуска.\n\tВозможные значения <св-во>: godmode | nostamina | unlimitedenergy | abyss | worldlevel | bplevel\n\t(прод.) см. перечисление (enum) PlayerProperty для остальных возможных значений, of form PROP_MAX_SPRING_VOLUME -> max_spring_volume" "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": { "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", "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.", "locked_to": "%s зафиксировано на значении %s.",

View File

@ -324,6 +324,9 @@
"setProp": { "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" "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": { "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(物理)", "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。", "locked_to": "%s 已锁定为 %s。",

View File

@ -324,6 +324,9 @@
"setProp": { "setProp": {
"description": "設定帳號屬性。比如可以通過此命令啟用無敵,也可以解鎖深淵或更改紀行等級。\n\t可更改的屬性列表 godmode(無敵)|nostamina(無限體力)|unlimitedenergy(無限元素能量)|abyss(深淵螺旋)|worldlevel(世界等級)|bplevel(紀行等級)\n\t(cont.) `有關其他可能的數值,請參閱 PlayerProperty 列舉。 (範例 PROP_MAX_SPRING_VOLUME -> max_spring_volume)`" "description": "設定帳號屬性。比如可以通過此命令啟用無敵,也可以解鎖深淵或更改紀行等級。\n\t可更改的屬性列表 godmode(無敵)|nostamina(無限體力)|unlimitedenergy(無限元素能量)|abyss(深淵螺旋)|worldlevel(世界等級)|bplevel(紀行等級)\n\t(cont.) `有關其他可能的數值,請參閱 PlayerProperty 列舉。 (範例 PROP_MAX_SPRING_VOLUME -> max_spring_volume)`"
}, },
"setSceneTag":{
"description": "設置帳戶特定的場景標籤。 這可以控制諸如擋住門的岩石、可見的建築物以及影響世界中可見內容的其他(通常與任務相關)的事物。"
},
"setStats": { "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 (物抗)", "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.", "locked_to": "%s 已鎖定為 %s.",