mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-01-25 13:13:06 +08:00
Fix default Traveler
This commit is contained in:
parent
af01282594
commit
6c1cff38b4
@ -44,6 +44,8 @@ import it.unimi.dsi.fastutil.ints.*;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@ -59,7 +61,7 @@ public class Avatar {
|
||||
@Indexed @Getter private int ownerId; // Id of player that this avatar belongs to
|
||||
@Transient private Player owner;
|
||||
@Transient @Getter private AvatarData avatarData;
|
||||
@Transient @Getter private AvatarSkillDepotData skillDepot;
|
||||
@Nullable @Transient @Getter private AvatarSkillDepotData skillDepot;
|
||||
@Transient @Getter private long guid; // Player unique id
|
||||
@Getter private int avatarId; // Id of avatar
|
||||
@Getter @Setter private int level = 1;
|
||||
@ -123,6 +125,7 @@ public class Avatar {
|
||||
|
||||
public Avatar(AvatarData data) {
|
||||
this();
|
||||
|
||||
this.avatarId = data.getId();
|
||||
this.nameCardRewardId = data.getNameCardRewardId();
|
||||
this.nameCardId = data.getNameCardId();
|
||||
@ -135,19 +138,17 @@ public class Avatar {
|
||||
|
||||
// Combat properties
|
||||
Stream.of(FightProperty.values())
|
||||
.map(FightProperty::getId)
|
||||
.filter(id -> (id > 0) && (id < 3000))
|
||||
.forEach(id -> this.setFightProperty(id, 0f));
|
||||
.map(FightProperty::getId)
|
||||
.filter(id -> (id > 0) && (id < 3000))
|
||||
.forEach(id -> this.setFightProperty(id, 0f));
|
||||
|
||||
// Skill depot
|
||||
this.setSkillDepotData(
|
||||
switch (this.avatarId) {
|
||||
case GameConstants.MAIN_CHARACTER_MALE -> GameData.getAvatarSkillDepotDataMap()
|
||||
.get(504); // Hack to start with anemo skills
|
||||
case GameConstants.MAIN_CHARACTER_FEMALE -> GameData.getAvatarSkillDepotDataMap()
|
||||
.get(704);
|
||||
default -> data.getSkillDepot();
|
||||
});
|
||||
this.setSkillDepotData(switch (this.getAvatarId()) {
|
||||
case GameConstants.MAIN_CHARACTER_MALE ->
|
||||
GameData.getAvatarSkillDepotDataMap().get(501);
|
||||
case GameConstants.MAIN_CHARACTER_FEMALE ->
|
||||
GameData.getAvatarSkillDepotDataMap().get(701);
|
||||
default -> data.getSkillDepot();
|
||||
});
|
||||
|
||||
// Set stats
|
||||
this.recalcStats();
|
||||
@ -175,6 +176,16 @@ public class Avatar {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if the avatar is a main character.
|
||||
*/
|
||||
public boolean isMainCharacter() {
|
||||
return List.of(
|
||||
GameConstants.MAIN_CHARACTER_MALE,
|
||||
GameConstants.MAIN_CHARACTER_FEMALE
|
||||
).contains(this.getAvatarId());
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return this.owner;
|
||||
}
|
||||
@ -192,6 +203,11 @@ public class Avatar {
|
||||
this.owner = player;
|
||||
this.ownerId = player.getUid();
|
||||
this.guid = player.getNextGameGuid();
|
||||
|
||||
if (this.isMainCharacter()) {
|
||||
// Apply skill depot based on player resonance.
|
||||
this.changeElement(player.getMainCharacterElement(), false);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addSatiation(int value) {
|
||||
@ -273,14 +289,28 @@ public class Avatar {
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the avatar's element to the target element, if the character has values for it set in
|
||||
* the candSkillDepot
|
||||
* Changes the avatar's element to the target element.
|
||||
* Only applies if the avatar has the element in its 'candSkillDepot's.
|
||||
*
|
||||
* @param elementTypeToChange element to change to
|
||||
* @return false if failed or already using that element, true if it actually changed
|
||||
* @param newElement The new element to change to.
|
||||
* @return True if the element was changed, false otherwise.
|
||||
*/
|
||||
public boolean changeElement(@Nonnull ElementType elementTypeToChange) {
|
||||
var candSkillDepotIdsList = this.avatarData.getCandSkillDepotIds();
|
||||
public boolean changeElement(@Nonnull ElementType newElement) {
|
||||
return this.changeElement(newElement, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the avatar's element to the target element.
|
||||
* Only applies if the avatar has the element in its 'candSkillDepot's.
|
||||
*
|
||||
* @param elementTypeToChange The new element to change to.
|
||||
* @param notify Whether to notify the player of the change.
|
||||
* @return True if the element was changed, false otherwise.
|
||||
*/
|
||||
public boolean changeElement(@Nonnull ElementType elementTypeToChange, boolean notify) {
|
||||
if (elementTypeToChange == ElementType.None) return true;
|
||||
|
||||
var candSkillDepotIdsList = this.getAvatarData().getCandSkillDepotIds();
|
||||
var candSkillDepotIndex = elementTypeToChange.getDepotIndex();
|
||||
|
||||
// if no candidate skill to change or index out of bound
|
||||
@ -297,7 +327,9 @@ public class Avatar {
|
||||
}
|
||||
|
||||
// Set skill depot
|
||||
setSkillDepotData(skillDepot, true);
|
||||
this.setSkillDepotData(skillDepot, notify);
|
||||
// Set element.
|
||||
this.getPlayer().setMainCharacterElement(elementTypeToChange);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -383,17 +415,21 @@ public class Avatar {
|
||||
}
|
||||
|
||||
public IntSet getTalentIdList() { // Returns a copy of the unlocked constellations for the current
|
||||
// skillDepot.
|
||||
var talents = new IntOpenHashSet(this.getSkillDepot().getTalents());
|
||||
talents.removeIf(id -> !this.talentIdList.contains(id));
|
||||
return talents;
|
||||
if (this.getSkillDepot() != null) {
|
||||
// skillDepot.
|
||||
var talents = new IntOpenHashSet(this.getSkillDepot().getTalents());
|
||||
talents.removeIf(id -> !this.talentIdList.contains(id));
|
||||
return talents;
|
||||
} else return new IntOpenHashSet();
|
||||
}
|
||||
|
||||
public int getCoreProudSkillLevel() {
|
||||
var lockedTalents = new IntOpenHashSet(this.getSkillDepot().getTalents());
|
||||
lockedTalents.removeAll(this.getTalentIdList());
|
||||
// One below the lowest locked talent, or 6 if there are no locked talents.
|
||||
return lockedTalents.intStream().map(i -> i % 10).min().orElse(7) - 1;
|
||||
if (this.getSkillDepot() != null) {
|
||||
var lockedTalents = new IntOpenHashSet(this.getSkillDepot().getTalents());
|
||||
lockedTalents.removeAll(this.getTalentIdList());
|
||||
// One below the lowest locked talent, or 6 if there are no locked talents.
|
||||
return lockedTalents.intStream().map(i -> i % 10).min().orElse(7) - 1;
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
public boolean equipItem(GameItem item, boolean shouldRecalc) {
|
||||
@ -624,14 +660,16 @@ public class Avatar {
|
||||
AvatarSkillDepotData skillDepot =
|
||||
GameData.getAvatarSkillDepotDataMap().get(this.getSkillDepotId());
|
||||
this.getProudSkillList().clear();
|
||||
for (InherentProudSkillOpens openData : skillDepot.getInherentProudSkillOpens()) {
|
||||
if (openData.getProudSkillGroupId() == 0) {
|
||||
continue;
|
||||
}
|
||||
if (openData.getNeedAvatarPromoteLevel() <= this.getPromoteLevel()) {
|
||||
int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1;
|
||||
if (GameData.getProudSkillDataMap().containsKey(proudSkillId)) {
|
||||
this.getProudSkillList().add(proudSkillId);
|
||||
if (skillDepot != null) {
|
||||
for (InherentProudSkillOpens openData : skillDepot.getInherentProudSkillOpens()) {
|
||||
if (openData.getProudSkillGroupId() == 0) {
|
||||
continue;
|
||||
}
|
||||
if (openData.getNeedAvatarPromoteLevel() <= this.getPromoteLevel()) {
|
||||
int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1;
|
||||
if (GameData.getProudSkillDataMap().containsKey(proudSkillId)) {
|
||||
this.getProudSkillList().add(proudSkillId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,10 +40,7 @@ import emu.grasscutter.game.managers.forging.ForgingManager;
|
||||
import emu.grasscutter.game.managers.mapmark.MapMark;
|
||||
import emu.grasscutter.game.managers.mapmark.MapMarksManager;
|
||||
import emu.grasscutter.game.managers.stamina.StaminaManager;
|
||||
import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.game.props.ClimateType;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.props.WatcherTriggerType;
|
||||
import emu.grasscutter.game.props.*;
|
||||
import emu.grasscutter.game.quest.QuestManager;
|
||||
import emu.grasscutter.game.quest.enums.QuestCond;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
@ -64,7 +61,6 @@ import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo
|
||||
import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture;
|
||||
import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason;
|
||||
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
|
||||
import emu.grasscutter.net.proto.TrialAvatarGrantRecordOuterClass.TrialAvatarGrantRecord.GrantReason;
|
||||
import emu.grasscutter.scripts.data.SceneRegion;
|
||||
import emu.grasscutter.server.event.player.PlayerJoinEvent;
|
||||
import emu.grasscutter.server.event.player.PlayerQuitEvent;
|
||||
@ -88,7 +84,6 @@ import java.time.ZoneId;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
||||
|
||||
@ -213,6 +208,8 @@ public class Player {
|
||||
@Getter private PlayerProgress playerProgress;
|
||||
@Getter private Set<Integer> activeQuestTimers;
|
||||
|
||||
@Getter @Setter private ElementType mainCharacterElement = ElementType.None;
|
||||
|
||||
@Deprecated
|
||||
@SuppressWarnings({"rawtypes", "unchecked"}) // Morphia only!
|
||||
public Player() {
|
||||
@ -291,6 +288,7 @@ public class Player {
|
||||
// On player creation
|
||||
public Player(GameSession session) {
|
||||
this();
|
||||
|
||||
this.account = session.getAccount();
|
||||
this.accountId = this.getAccount().getId();
|
||||
this.session = session;
|
||||
@ -300,6 +298,10 @@ public class Player {
|
||||
this.birthday = new PlayerBirthday();
|
||||
this.codex = new PlayerCodex(this);
|
||||
|
||||
this.applyProperties();
|
||||
this.getFlyCloakList().add(140001);
|
||||
this.getNameCardList().add(210001);
|
||||
|
||||
this.messageHandler = null;
|
||||
this.mapMarksManager = new MapMarksManager(this);
|
||||
this.staminaManager = new StaminaManager(this);
|
||||
@ -313,10 +315,6 @@ public class Player {
|
||||
this.cookingManager = new CookingManager(this);
|
||||
this.cookingCompoundManager = new CookingCompoundManager(this);
|
||||
this.satiationManager = new SatiationManager(this);
|
||||
|
||||
this.applyProperties();
|
||||
this.getFlyCloakList().add(140001);
|
||||
this.getNameCardList().add(210001);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -537,10 +535,9 @@ public class Player {
|
||||
* @param defaultValue The value to apply if the property doesn't exist.
|
||||
*/
|
||||
private void setOrFetch(PlayerProperty property, int defaultValue) {
|
||||
if (!this.properties.containsKey(property.getId())) {
|
||||
this.setProperty(property, defaultValue, false);
|
||||
this.save();
|
||||
}
|
||||
this.setProperty(property,
|
||||
this.properties.containsKey(property.getId()) ?
|
||||
this.getProperty(property) : defaultValue, false);
|
||||
}
|
||||
|
||||
public int getPrimogems() {
|
||||
@ -864,80 +861,6 @@ public class Player {
|
||||
addAvatar(new Avatar(avatarId), true);
|
||||
}
|
||||
|
||||
public List<Integer> getTrialAvatarParam (int trialAvatarId) {
|
||||
if (GameData.getTrialAvatarCustomData().isEmpty()) { // use default data if custom data not available
|
||||
if (GameData.getTrialAvatarDataMap().get(trialAvatarId) == null) return List.of();
|
||||
|
||||
return GameData.getTrialAvatarDataMap().get(trialAvatarId)
|
||||
.getTrialAvatarParamList();
|
||||
}
|
||||
// use custom data
|
||||
if (GameData.getTrialAvatarCustomData().get(trialAvatarId) == null) return List.of();
|
||||
|
||||
var trialCustomParams = GameData.getTrialAvatarCustomData().get(trialAvatarId).getTrialAvatarParamList();
|
||||
return trialCustomParams.isEmpty() ? List.of() : Stream.of(trialCustomParams.get(0).split(";")).map(Integer::parseInt).toList();
|
||||
}
|
||||
|
||||
public boolean addTrialAvatar(int trialAvatarId, GrantReason reason, int questMainId){
|
||||
List<Integer> trialAvatarBasicParam = getTrialAvatarParam(trialAvatarId);
|
||||
if (trialAvatarBasicParam.isEmpty()) return false;
|
||||
|
||||
Avatar avatar = new Avatar(trialAvatarBasicParam.get(0));
|
||||
if (avatar.getAvatarData() == null || !hasSentLoginPackets()) return false;
|
||||
|
||||
avatar.setOwner(this);
|
||||
// Add trial weapons and relics
|
||||
avatar.setTrialAvatarInfo(trialAvatarBasicParam.get(1), trialAvatarId, reason, questMainId);
|
||||
avatar.equipTrialItems();
|
||||
// Recalc stats
|
||||
avatar.recalcStats();
|
||||
|
||||
// Packet, mimic official server behaviour, add to player's bag but not saving to db
|
||||
sendPacket(new PacketAvatarAddNotify(avatar, false));
|
||||
// add to avatar to temporary trial team
|
||||
getTeamManager().addAvatarToTrialTeam(avatar);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean addTrialAvatarForQuest(int trialAvatarId, int questMainId) {
|
||||
// TODO: Find method for 'setupTrialAvatarTeamForQuest'.
|
||||
getTeamManager().setupTrialAvatars(true);
|
||||
if (!addTrialAvatar(
|
||||
trialAvatarId,
|
||||
GrantReason.GRANT_REASON_BY_QUEST,
|
||||
questMainId)) return false;
|
||||
getTeamManager().trialAvatarTeamPostUpdate();
|
||||
// Packet, mimic official server behaviour, neccessary to stop player from modifying team
|
||||
sendPacket(new PacketAvatarTeamUpdateNotify(this));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addTrialAvatarsForActivity(List<Integer> trialAvatarIds) {
|
||||
getTeamManager().setupTrialAvatars(false);
|
||||
trialAvatarIds.forEach(trialAvatarId -> addTrialAvatar(
|
||||
trialAvatarId,
|
||||
GrantReason.GRANT_REASON_BY_TRIAL_AVATAR_ACTIVITY,
|
||||
0));
|
||||
getTeamManager().trialAvatarTeamPostUpdate(0);
|
||||
}
|
||||
|
||||
public boolean removeTrialAvatarForQuest(int trialAvatarId) {
|
||||
if (!getTeamManager().isUsingTrialTeam()) return false;
|
||||
|
||||
sendPacket(new PacketAvatarDelNotify(List.of(getTeamManager().getTrialAvatarGuid(trialAvatarId))));
|
||||
getTeamManager().removeTrialAvatarTeam(trialAvatarId);
|
||||
sendPacket(new PacketAvatarTeamUpdateNotify());
|
||||
return true;
|
||||
}
|
||||
|
||||
public void removeTrialAvatarForActivity() {
|
||||
if (!getTeamManager().isUsingTrialTeam()) return;
|
||||
|
||||
sendPacket(new PacketAvatarDelNotify(getTeamManager().getActiveTeam().stream()
|
||||
.map(x -> x.getAvatar().getGuid()).toList()));
|
||||
getTeamManager().removeTrialAvatarTeam();
|
||||
}
|
||||
|
||||
public void addFlycloak(int flycloakId) {
|
||||
this.getFlyCloakList().add(flycloakId);
|
||||
this.sendPacket(new PacketAvatarGainFlycloakNotify(flycloakId));
|
||||
|
Loading…
Reference in New Issue
Block a user