Commit 01b190bc authored by Magix's avatar Magix Committed by GitHub
Browse files

UPGRADE TO 1.1.0 POG

Merge `development` into `stable`
parents 6b81b888 1beddf16
package emu.grasscutter.game;
import emu.grasscutter.game.player.Player;
public class CoopRequest {
private final GenshinPlayer requester;
private final Player requester;
private final long requestTime;
private final long expireTime;
public CoopRequest(GenshinPlayer requester) {
public CoopRequest(Player requester) {
this.requester = requester;
this.requestTime = System.currentTimeMillis();
this.expireTime = this.requestTime + 10000;
}
public GenshinPlayer getRequester() {
public Player getRequester() {
return requester;
}
......
......@@ -5,6 +5,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.bson.types.ObjectId;
......@@ -15,10 +16,10 @@ import dev.morphia.annotations.Indexed;
import dev.morphia.annotations.PostLoad;
import dev.morphia.annotations.PrePersist;
import dev.morphia.annotations.Transient;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.common.FightPropData;
import emu.grasscutter.data.custom.OpenConfigEntry;
import emu.grasscutter.data.custom.OpenConfigEntry.SkillPointModifier;
import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.data.def.AvatarPromoteData;
import emu.grasscutter.data.def.AvatarSkillData;
......@@ -26,27 +27,32 @@ import emu.grasscutter.data.def.AvatarSkillDepotData;
import emu.grasscutter.data.def.AvatarSkillDepotData.InherentProudSkillOpens;
import emu.grasscutter.data.def.AvatarTalentData;
import emu.grasscutter.data.def.EquipAffixData;
import emu.grasscutter.data.def.ItemData.WeaponProperty;
import emu.grasscutter.data.def.ProudSkillData;
import emu.grasscutter.data.def.ReliquaryAffixData;
import emu.grasscutter.data.def.ReliquaryLevelData;
import emu.grasscutter.data.def.ReliquaryMainPropData;
import emu.grasscutter.data.def.ReliquarySetData;
import emu.grasscutter.data.def.WeaponCurveData;
import emu.grasscutter.data.def.WeaponPromoteData;
import emu.grasscutter.data.def.ItemData.WeaponProperty;
import emu.grasscutter.data.def.ProudSkillData;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.inventory.EquipType;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.FetterState;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo;
import emu.grasscutter.net.proto.FetterDataOuterClass.FetterData;
import emu.grasscutter.net.proto.AvatarInfoOuterClass.AvatarInfo;
import emu.grasscutter.net.proto.AvatarSkillInfoOuterClass.AvatarSkillInfo;
import emu.grasscutter.net.proto.FetterDataOuterClass.FetterData;
import emu.grasscutter.net.proto.ShowAvatarInfoOuterClass;
import emu.grasscutter.net.proto.ShowAvatarInfoOuterClass.ShowAvatarInfo;
import emu.grasscutter.net.proto.ShowEquipOuterClass.ShowEquip;
import emu.grasscutter.server.packet.send.PacketAbilityChangeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarEquipChangeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarFightPropNotify;
......@@ -56,12 +62,12 @@ import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@Entity(value = "avatars", noClassnameStored = true)
public class GenshinAvatar {
@Entity(value = "avatars", useDiscriminator = false)
public class Avatar {
@Id private ObjectId id;
@Indexed private int ownerId; // Id of player that this avatar belongs to
@Transient private GenshinPlayer owner;
@Transient private Player owner;
@Transient private AvatarData data;
@Transient private long guid; // Player unique id
private int avatarId; // Id of avatar
......@@ -73,13 +79,14 @@ public class GenshinAvatar {
private int satiationPenalty; // ?
private float currentHp;
@Transient private final Int2ObjectMap<GenshinItem> equips;
@Transient private final Int2ObjectMap<GameItem> equips;
@Transient private final Int2FloatOpenHashMap fightProp;
@Transient private Set<String> extraAbilityEmbryos;
private List<Integer> fetters;
private Map<Integer, Integer> skillLevelMap; // Talent levels
private Map<Integer, Integer> skillExtraChargeMap; // Charges
private Map<Integer, Integer> proudSkillBonusMap; // Talent bonus levels (from const)
private int skillDepotId;
private int coreProudSkillLevel; // Constellation level
......@@ -90,28 +97,37 @@ public class GenshinAvatar {
private int costume;
private int bornTime;
public GenshinAvatar() {
private int fetterLevel = 1;
private int fetterExp;
private int nameCardRewardId;
private int nameCardId;
public Avatar() {
// Morhpia only!
this.equips = new Int2ObjectOpenHashMap<>();
this.fightProp = new Int2FloatOpenHashMap();
this.extraAbilityEmbryos = new HashSet<>();
this.proudSkillBonusMap = new HashMap<>();
this.fetters = new ArrayList<>(); // TODO Move to genshin avatar
this.fetters = new ArrayList<>(); // TODO Move to avatar
}
// On creation
public GenshinAvatar(int avatarId) {
this(GenshinData.getAvatarDataMap().get(avatarId));
public Avatar(int avatarId) {
this(GameData.getAvatarDataMap().get(avatarId));
}
public GenshinAvatar(AvatarData data) {
public Avatar(AvatarData data) {
this();
this.avatarId = data.getId();
this.nameCardRewardId = data.getNameCardRewardId();
this.nameCardId = data.getNameCardId();
this.data = data;
this.bornTime = (int) (System.currentTimeMillis() / 1000);
this.flyCloak = 140001;
this.skillLevelMap = new HashMap<>();
this.skillExtraChargeMap = new HashMap<>();
this.talentIdList = new HashSet<>();
this.proudSkillList = new HashSet<>();
......@@ -135,7 +151,7 @@ public class GenshinAvatar {
this.onLoad();
}
public GenshinPlayer getPlayer() {
public Player getPlayer() {
return this.owner;
}
......@@ -155,10 +171,10 @@ public class GenshinAvatar {
return ownerId;
}
public void setOwner(GenshinPlayer player) {
public void setOwner(Player player) {
this.owner = player;
this.ownerId = player.getUid();
this.guid = player.getNextGenshinGuid();
this.guid = player.getNextGameGuid();
}
public int getSatiation() {
......@@ -169,6 +185,14 @@ public class GenshinAvatar {
this.satiation = satiation;
}
public int getNameCardRewardId() {
return nameCardRewardId;
}
public void setNameCardRewardId(int nameCardRewardId) {
this.nameCardRewardId = nameCardRewardId;
}
public int getSatiationPenalty() {
return satiationPenalty;
}
......@@ -213,19 +237,19 @@ public class GenshinAvatar {
this.promoteLevel = promoteLevel;
}
public Int2ObjectMap<GenshinItem> getEquips() {
public Int2ObjectMap<GameItem> getEquips() {
return equips;
}
public GenshinItem getEquipBySlot(EquipType slot) {
public GameItem getEquipBySlot(EquipType slot) {
return this.getEquips().get(slot.getValue());
}
private GenshinItem getEquipBySlot(int slotId) {
private GameItem getEquipBySlot(int slotId) {
return this.getEquips().get(slotId);
}
public GenshinItem getWeapon() {
public GameItem getWeapon() {
return this.getEquipBySlot(EquipType.EQUIP_WEAPON);
}
......@@ -254,7 +278,7 @@ public class GenshinAvatar {
}
if (openData.getNeedAvatarPromoteLevel() <= this.getPromoteLevel()) {
int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1;
if (GenshinData.getProudSkillDataMap().containsKey(proudSkillId)) {
if (GameData.getProudSkillDataMap().containsKey(proudSkillId)) {
this.getProudSkillList().add(proudSkillId);
}
}
......@@ -265,6 +289,13 @@ public class GenshinAvatar {
return skillLevelMap;
}
public Map<Integer, Integer> getSkillExtraChargeMap() {
if (skillExtraChargeMap == null) {
skillExtraChargeMap = new HashMap<>();
}
return skillExtraChargeMap;
}
public Map<Integer, Integer> getProudSkillBonusMap() {
return proudSkillBonusMap;
}
......@@ -281,6 +312,30 @@ public class GenshinAvatar {
return fetters;
}
public int getFetterLevel() {
return fetterLevel;
}
public void setFetterLevel(int fetterLevel) {
this.fetterLevel = fetterLevel;
}
public int getFetterExp() {
return fetterExp;
}
public void setFetterExp(int fetterExp) {
this.fetterExp = fetterExp;
}
public int getNameCardId() {
return nameCardId;
}
public void setNameCardId(int nameCardId) {
this.nameCardId = nameCardId;
}
public float getCurrentHp() {
return currentHp;
}
......@@ -345,16 +400,33 @@ public class GenshinAvatar {
return bornTime;
}
public boolean equipItem(GenshinItem item, boolean shouldRecalc) {
public boolean equipItem(GameItem item, boolean shouldRecalc) {
// Sanity check equip type
EquipType itemEquipType = item.getItemData().getEquipType();
if (itemEquipType == EquipType.EQUIP_NONE) {
return false;
}
// Check if other avatars have this item equipped
Avatar otherAvatar = getPlayer().getAvatars().getAvatarById(item.getEquipCharacter());
if (otherAvatar != null) {
// Unequip other avatar's item
if (otherAvatar.unequipItem(item.getItemData().getEquipType())) {
getPlayer().sendPacket(new PacketAvatarEquipChangeNotify(otherAvatar, item.getItemData().getEquipType()));
}
// Swap with other avatar
if (getEquips().containsKey(itemEquipType.getValue())) {
GameItem toSwap = this.getEquipBySlot(itemEquipType);
otherAvatar.equipItem(toSwap, false);
}
// Recalc
otherAvatar.recalcStats();
} else if (getEquips().containsKey(itemEquipType.getValue())) {
// Unequip item in current slot if it exists
unequipItem(itemEquipType);
}
// Set equip
getEquips().put(itemEquipType.getValue(), item);
if (itemEquipType == EquipType.EQUIP_WEAPON && getPlayer().getWorld() != null) {
......@@ -376,7 +448,7 @@ public class GenshinAvatar {
}
public boolean unequipItem(EquipType slot) {
GenshinItem item = getEquips().remove(slot.getValue());
GameItem item = getEquips().remove(slot.getValue());
if (item != null) {
item.setEquipCharacter(0);
......@@ -394,7 +466,7 @@ public class GenshinAvatar {
public void recalcStats(boolean forceSendAbilityChange) {
// Setup
AvatarData data = this.getAvatarData();
AvatarPromoteData promoteData = GenshinData.getAvatarPromoteData(data.getAvatarPromoteId(), this.getPromoteLevel());
AvatarPromoteData promoteData = GameData.getAvatarPromoteData(data.getAvatarPromoteId(), this.getPromoteLevel());
Int2IntOpenHashMap setMap = new Int2IntOpenHashMap();
// Extra ability embryos
......@@ -403,6 +475,8 @@ public class GenshinAvatar {
// Fetters
this.setFetterList(data.getFetters());
this.setNameCardRewardId(data.getNameCardRewardId());
this.setNameCardId(data.getNameCardId());
// Get hp percent, set to 100% if none
float hpPercent = this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) <= 0 ? 1f : this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) / this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
......@@ -434,21 +508,21 @@ public class GenshinAvatar {
// Artifacts
for (int slotId = 1; slotId <= 5; slotId++) {
// Get artifact
GenshinItem equip = this.getEquipBySlot(slotId);
GameItem equip = this.getEquipBySlot(slotId);
if (equip == null) {
continue;
}
// Artifact main stat
ReliquaryMainPropData mainPropData = GenshinData.getReliquaryMainPropDataMap().get(equip.getMainPropId());
ReliquaryMainPropData mainPropData = GameData.getReliquaryMainPropDataMap().get(equip.getMainPropId());
if (mainPropData != null) {
ReliquaryLevelData levelData = GenshinData.getRelicLevelData(equip.getItemData().getRankLevel(), equip.getLevel());
ReliquaryLevelData levelData = GameData.getRelicLevelData(equip.getItemData().getRankLevel(), equip.getLevel());
if (levelData != null) {
this.addFightProperty(mainPropData.getFightProp(), levelData.getPropValue(mainPropData.getFightProp()));
}
}
// Artifact sub stats
for (int appendPropId : equip.getAppendPropIdList()) {
ReliquaryAffixData affixData = GenshinData.getReliquaryAffixDataMap().get(appendPropId);
ReliquaryAffixData affixData = GameData.getReliquaryAffixDataMap().get(appendPropId);
if (affixData != null) {
this.addFightProperty(affixData.getFightProp(), affixData.getPropValue());
}
......@@ -461,7 +535,7 @@ public class GenshinAvatar {
// Set stuff
for (Int2IntOpenHashMap.Entry e : setMap.int2IntEntrySet()) {
ReliquarySetData setData = GenshinData.getReliquarySetDataMap().get(e.getIntKey());
ReliquarySetData setData = GameData.getReliquarySetDataMap().get(e.getIntKey());
if (setData == null) {
continue;
}
......@@ -474,7 +548,7 @@ public class GenshinAvatar {
if (amount >= setData.getSetNeedNum()[setIndex]) {
int affixId = (setData.getEquipAffixId() * 10) + setIndex;
EquipAffixData affix = GenshinData.getEquipAffixDataMap().get(affixId);
EquipAffixData affix = GameData.getEquipAffixDataMap().get(affixId);
if (affix == null) {
continue;
}
......@@ -493,17 +567,17 @@ public class GenshinAvatar {
}
// Weapon
GenshinItem weapon = this.getWeapon();
GameItem weapon = this.getWeapon();
if (weapon != null) {
// Add stats
WeaponCurveData curveData = GenshinData.getWeaponCurveDataMap().get(weapon.getLevel());
WeaponCurveData curveData = GameData.getWeaponCurveDataMap().get(weapon.getLevel());
if (curveData != null) {
for (WeaponProperty weaponProperty : weapon.getItemData().getWeaponProperties()) {
this.addFightProperty(weaponProperty.getFightProp(), weaponProperty.getInitValue() * curveData.getMultByProp(weaponProperty.getType()));
}
}
// Weapon promotion stats
WeaponPromoteData wepPromoteData = GenshinData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel());
WeaponPromoteData wepPromoteData = GameData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel());
if (wepPromoteData != null) {
for (FightPropData prop : wepPromoteData.getAddProps()) {
if (prop.getValue() == 0f || prop.getProp() == null) {
......@@ -521,7 +595,7 @@ public class GenshinAvatar {
}
// Calculate affix id
int affixId = (af * 10) + weapon.getRefinement();
EquipAffixData affix = GenshinData.getEquipAffixDataMap().get(affixId);
EquipAffixData affix = GameData.getEquipAffixDataMap().get(affixId);
if (affix == null) {
continue;
}
......@@ -538,7 +612,7 @@ public class GenshinAvatar {
}
// Add proud skills and unlock them if needed
AvatarSkillDepotData skillDepot = GenshinData.getAvatarSkillDepotDataMap().get(this.getSkillDepotId());
AvatarSkillDepotData skillDepot = GameData.getAvatarSkillDepotDataMap().get(this.getSkillDepotId());
this.getProudSkillList().clear();
for (InherentProudSkillOpens openData : skillDepot.getInherentProudSkillOpens()) {
if (openData.getProudSkillGroupId() == 0) {
......@@ -546,7 +620,7 @@ public class GenshinAvatar {
}
if (openData.getNeedAvatarPromoteLevel() <= this.getPromoteLevel()) {
int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1;
if (GenshinData.getProudSkillDataMap().containsKey(proudSkillId)) {
if (GameData.getProudSkillDataMap().containsKey(proudSkillId)) {
this.getProudSkillList().add(proudSkillId);
}
}
......@@ -554,7 +628,7 @@ public class GenshinAvatar {
// Proud skills
for (int proudSkillId : this.getProudSkillList()) {
ProudSkillData proudSkillData = GenshinData.getProudSkillDataMap().get(proudSkillId);
ProudSkillData proudSkillData = GameData.getProudSkillDataMap().get(proudSkillId);
if (proudSkillData == null) {
continue;
}
......@@ -571,7 +645,7 @@ public class GenshinAvatar {
// Constellations
if (this.getTalentIdList().size() > 0) {
for (int talentId : this.getTalentIdList()) {
AvatarTalentData avatarTalentData = GenshinData.getAvatarTalentDataMap().get(talentId);
AvatarTalentData avatarTalentData = GameData.getAvatarTalentDataMap().get(talentId);
if (avatarTalentData == null) {
return;
}
......@@ -615,7 +689,7 @@ public class GenshinAvatar {
return;
}
OpenConfigEntry entry = GenshinData.getOpenConfigEntries().get(openConfig);
OpenConfigEntry entry = GameData.getOpenConfigEntries().get(openConfig);
if (entry == null) {
if (forceAdd) {
// Add config string to ability skill list anyways
......@@ -631,9 +705,10 @@ public class GenshinAvatar {
}
}
public void recalcProudSkillBonusMap() {
public void recalcConstellations() {
// Clear first
this.getProudSkillBonusMap().clear();
this.getSkillExtraChargeMap().clear();
// Sanity checks
if (getData() == null || getData().getSkillDepot() == null) {
......@@ -642,18 +717,33 @@ public class GenshinAvatar {
if (this.getTalentIdList().size() > 0) {
for (int talentId : this.getTalentIdList()) {
AvatarTalentData avatarTalentData = GenshinData.getAvatarTalentDataMap().get(talentId);
AvatarTalentData avatarTalentData = GameData.getAvatarTalentDataMap().get(talentId);
if (avatarTalentData == null || avatarTalentData.getOpenConfig() == null || avatarTalentData.getOpenConfig().length() == 0) {
continue;
}
// Get open config to find which skill should be boosted
OpenConfigEntry entry = GenshinData.getOpenConfigEntries().get(avatarTalentData.getOpenConfig());
OpenConfigEntry entry = GameData.getOpenConfigEntries().get(avatarTalentData.getOpenConfig());
if (entry == null) {
continue;
}
// Check if we can add charges to a skill
if (entry.getSkillPointModifiers() != null) {
for (SkillPointModifier mod : entry.getSkillPointModifiers()) {
AvatarSkillData skillData = GameData.getAvatarSkillDataMap().get(mod.getSkillId());
if (skillData == null) continue;
int charges = skillData.getMaxChargeNum() + mod.getDelta();
this.getSkillExtraChargeMap().put(mod.getSkillId(), charges);
}
continue;
}
// Check if a skill can be boosted by +3 levels
int skillId = 0;
if (entry.getExtraTalentIndex() == 2 && this.getData().getSkillDepot().getSkills().size() >= 2) {
......@@ -670,7 +760,7 @@ public class GenshinAvatar {
}
// Get proud skill group id
AvatarSkillData skillData = GenshinData.getAvatarSkillDataMap().get(skillId);
AvatarSkillData skillData = GameData.getAvatarSkillDataMap().get(skillId);
if (skillData == null) {
continue;
......@@ -701,9 +791,14 @@ public class GenshinAvatar {
}
public AvatarInfo toProto() {
int fetterLevel = this.getFetterLevel();
AvatarFetterInfo.Builder avatarFetter = AvatarFetterInfo.newBuilder()
.setExpLevel(10)
.setExpNumber(6325); // Highest Level
.setExpLevel(fetterLevel);
if (fetterLevel != 10) {
avatarFetter.setExpNumber(this.getFetterExp());
}
if (this.getFetterList() != null) {
for (int i = 0; i < this.getFetterList().size(); i++) {
......@@ -715,6 +810,12 @@ public class GenshinAvatar {
}
}
int cardId = this.getNameCardId();
if (this.getPlayer().getNameCardList().contains(cardId)) {
avatarFetter.addRewardedFetterLevelList(10);
}
AvatarInfo.Builder avatarInfo = AvatarInfo.newBuilder()
.setAvatarId(this.getAvatarId())
.setGuid(this.getGuid())
......@@ -725,14 +826,18 @@ public class GenshinAvatar {
.setCoreProudSkillLevel(this.getCoreProudSkillLevel())
.putAllSkillLevelMap(this.getSkillLevelMap())
.addAllInherentProudSkillList(this.getProudSkillList())
.putAllProudSkillExtraLevel(getProudSkillBonusMap())
.putAllProudSkillExtraLevelMap(getProudSkillBonusMap())
.setAvatarType(1)
.setBornTime(this.getBornTime())
.setFetterInfo(avatarFetter)
.setWearingFlycloakId(this.getFlyCloak())
.setCostumeId(this.getCostume());
for (GenshinItem item : this.getEquips().values()) {
for (Entry<Integer, Integer> entry : this.getSkillExtraChargeMap().entrySet()) {
avatarInfo.putSkillMap(entry.getKey(), AvatarSkillInfo.newBuilder().setMaxChargeCount(entry.getValue()).build());
}
for (GameItem item : this.getEquips().values()) {
avatarInfo.addEquipGuidList(item.getGuid());
}
......@@ -745,6 +850,46 @@ public class GenshinAvatar {
return avatarInfo.build();
}
// used only in character showcase
public ShowAvatarInfo toShowAvatarInfoProto() {
AvatarFetterInfo.Builder avatarFetter = AvatarFetterInfo.newBuilder()
.setExpLevel(this.getFetterLevel());
ShowAvatarInfo.Builder showAvatarInfo = ShowAvatarInfoOuterClass.ShowAvatarInfo.newBuilder()
.setAvatarId(avatarId)
.addAllTalentIdList(this.getTalentIdList())
.putAllFightPropMap(this.getFightProperties())
.setSkillDepotId(this.getSkillDepotId())
.setCoreProudSkillLevel(this.getCoreProudSkillLevel())
.addAllInherentProudSkillList(this.getProudSkillList())
.putAllSkillLevelMap(this.getSkillLevelMap())
.putAllProudSkillExtraLevelMap(this.getProudSkillBonusMap())
.setFetterInfo(avatarFetter)
.setCostumeId(this.getCostume());
showAvatarInfo.putPropMap(PlayerProperty.PROP_LEVEL.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, this.getLevel()));
showAvatarInfo.putPropMap(PlayerProperty.PROP_EXP.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_EXP, this.getExp()));
showAvatarInfo.putPropMap(PlayerProperty.PROP_BREAK_LEVEL.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_BREAK_LEVEL, this.getPromoteLevel()));
showAvatarInfo.putPropMap(PlayerProperty.PROP_SATIATION_VAL.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_SATIATION_VAL, this.getSatiation()));
showAvatarInfo.putPropMap(PlayerProperty.PROP_SATIATION_PENALTY_TIME.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_SATIATION_VAL, this.getSatiationPenalty()));
int maxStamina = this.getPlayer().getProperty(PlayerProperty.PROP_MAX_STAMINA);
showAvatarInfo.putPropMap(PlayerProperty.PROP_MAX_STAMINA.getId(), ProtoHelper.newPropValue(PlayerProperty.PROP_MAX_STAMINA, maxStamina));
for (GameItem item : this.getEquips().values()) {
if (item.getItemType() == ItemType.ITEM_RELIQUARY) {
showAvatarInfo.addEquipList(ShowEquip.newBuilder()
.setItemId(item.getItemId())
.setReliquary(item.toReliquaryProto()));
} else if (item.getItemType() == ItemType.ITEM_WEAPON) {
showAvatarInfo.addEquipList(ShowEquip.newBuilder()
.setItemId(item.getItemId())
.setWeapon(item.toWeaponProto()));
}
}
return showAvatarInfo.build();
}
@PostLoad
private void onLoad() {
......
package emu.grasscutter.game.avatar;
import dev.morphia.annotations.Entity;
@Entity
public class AvatarProfileData {
private int avatarId;
private int level;
public AvatarProfileData(GenshinAvatar avatar) {
public AvatarProfileData(Avatar avatar) {
this.update(avatar);
}
......@@ -16,7 +19,7 @@ public class AvatarProfileData {
return level;
}
public void update(GenshinAvatar avatar) {
public void update(Avatar avatar) {
this.avatarId = avatar.getAvatarId();
this.level = avatar.getLevel();
}
......
......@@ -3,12 +3,12 @@ package emu.grasscutter.game.avatar;
import java.util.Iterator;
import java.util.List;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.server.packet.send.PacketAvatarChangeCostumeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarFlycloakChangeNotify;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
......@@ -16,22 +16,22 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
public class AvatarStorage implements Iterable<GenshinAvatar> {
private final GenshinPlayer player;
private final Int2ObjectMap<GenshinAvatar> avatars;
private final Long2ObjectMap<GenshinAvatar> avatarsGuid;
public class AvatarStorage implements Iterable<Avatar> {
private final Player player;
private final Int2ObjectMap<Avatar> avatars;
private final Long2ObjectMap<Avatar> avatarsGuid;
public AvatarStorage(GenshinPlayer player) {
public AvatarStorage(Player player) {
this.player = player;
this.avatars = new Int2ObjectOpenHashMap<>();
this.avatarsGuid = new Long2ObjectOpenHashMap<>();
}
public GenshinPlayer getPlayer() {
public Player getPlayer() {
return player;
}
public Int2ObjectMap<GenshinAvatar> getAvatars() {
public Int2ObjectMap<Avatar> getAvatars() {
return avatars;
}
......@@ -39,11 +39,11 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
return this.avatars.size();
}
public GenshinAvatar getAvatarById(int id) {
public Avatar getAvatarById(int id) {
return getAvatars().get(id);
}
public GenshinAvatar getAvatarByGuid(long id) {
public Avatar getAvatarByGuid(long id) {
return avatarsGuid.get(id);
}
......@@ -51,7 +51,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
return getAvatars().containsKey(id);
}
public boolean addAvatar(GenshinAvatar avatar) {
public boolean addAvatar(Avatar avatar) {
if (avatar.getAvatarData() == null || this.hasAvatar(avatar.getAvatarId())) {
return false;
}
......@@ -68,14 +68,14 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
return true;
}
public void addStartingWeapon(GenshinAvatar avatar) {
public void addStartingWeapon(Avatar avatar) {
// Make sure avatar owner is this player
if (avatar.getPlayer() != this.getPlayer()) {
return;
}
// Create weapon
GenshinItem weapon = new GenshinItem(avatar.getAvatarData().getInitialWeapon());
GameItem weapon = new GameItem(avatar.getAvatarData().getInitialWeapon());
if (weapon.getItemData() != null) {
this.getPlayer().getInventory().addItem(weapon);
......@@ -85,7 +85,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
}
public boolean wearFlycloak(long avatarGuid, int flycloakId) {
GenshinAvatar avatar = this.getAvatarByGuid(avatarGuid);
Avatar avatar = this.getAvatarByGuid(avatarGuid);
if (avatar == null || !getPlayer().getFlyCloakList().contains(flycloakId)) {
return false;
......@@ -101,7 +101,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
}
public boolean changeCostume(long avatarGuid, int costumeId) {
GenshinAvatar avatar = this.getAvatarByGuid(avatarGuid);
Avatar avatar = this.getAvatarByGuid(avatarGuid);
if (avatar == null) {
return false;
......@@ -130,15 +130,15 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
}
public void loadFromDatabase() {
List<GenshinAvatar> avatars = DatabaseHelper.getAvatars(getPlayer());
List<Avatar> avatars = DatabaseHelper.getAvatars(getPlayer());
for (GenshinAvatar avatar : avatars) {
for (Avatar avatar : avatars) {
// Should never happen
if (avatar.getObjectId() == null) {
continue;
}
AvatarData avatarData = GenshinData.getAvatarDataMap().get(avatar.getAvatarId());
AvatarData avatarData = GameData.getAvatarDataMap().get(avatar.getAvatarId());
if (avatarData == null) {
continue;
}
......@@ -148,7 +148,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
avatar.setOwner(getPlayer());
// Force recalc of const boosted skills
avatar.recalcProudSkillBonusMap();
avatar.recalcConstellations();
// Add to avatar storage
this.avatars.put(avatar.getAvatarId(), avatar);
......@@ -157,7 +157,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
}
public void postLoad() {
for (GenshinAvatar avatar : this) {
for (Avatar avatar : this) {
// Weapon check
if (avatar.getWeapon() == null) {
this.addStartingWeapon(avatar);
......@@ -168,7 +168,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
}
@Override
public Iterator<GenshinAvatar> iterator() {
public Iterator<Avatar> iterator() {
return getAvatars().values().iterator();
}
}
package emu.grasscutter.game.combine;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.CombineData;
import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.net.proto.RetcodeOuterClass;
import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.packet.send.PacketCombineRsp;
import it.unimi.dsi.fastutil.Pair;
import java.util.List;
public class CombineManger {
private final GameServer gameServer;
public GameServer getGameServer() {
return gameServer;
}
public CombineManger(GameServer gameServer) {
this.gameServer = gameServer;
}
public CombineResult combineItem(Player player, int cid, int count){
// check config exist
if(!GameData.getCombineDataMap().containsKey(cid)){
player.getWorld().getHost().sendPacket(new PacketCombineRsp());
return null;
}
CombineData combineData = GameData.getCombineDataMap().get(cid);
if(combineData.getPlayerLevel() > player.getLevel()){
return null;
}
// check enough
var enough = combineData.getMaterialItems().stream()
.filter(item -> player.getInventory()
.getInventoryTab(ItemType.ITEM_MATERIAL)
.getItemById(item.getId())
.getCount() < item.getCount() * count
)
.findAny()
.isEmpty();
// if not enough
if(!enough){
player.getWorld().getHost().sendPacket(
new PacketCombineRsp(RetcodeOuterClass.Retcode.RET_ITEM_COMBINE_COUNT_NOT_ENOUGH_VALUE)
);
return null;
}
if (player.getMora() >= combineData.getScoinCost()) {
player.setMora(player.getMora() - combineData.getScoinCost() * count);
} else {
return null;
}
// try to remove materials
combineData.getMaterialItems().stream()
.map(item -> Pair.of(player.getInventory()
.getInventoryTab(ItemType.ITEM_MATERIAL)
.getItemById(item.getId())
,item.getCount() * count)
)
.forEach(item -> player.getInventory().removeItem(item.first(), item.second()));
// make the result
player.getInventory().addItem(combineData.getResultItemId(),
combineData.getResultItemCount() * count);
CombineResult result = new CombineResult();
result.setMaterial(List.of());
result.setResult(List.of(new CombineData.CombineItemPair(combineData.getResultItemId(),
combineData.getResultItemCount() * count)));
// TODO lucky characters
result.setExtra(List.of());
result.setBack(List.of());
return result;
}
}
package emu.grasscutter.game.combine;
import emu.grasscutter.data.def.CombineData;
import java.util.List;
public class CombineResult {
private List<CombineData.CombineItemPair> material;
private List<CombineData.CombineItemPair> result;
private List<CombineData.CombineItemPair> extra;
private List<CombineData.CombineItemPair> back;
public List<CombineData.CombineItemPair> getMaterial() {
return material;
}
public void setMaterial(List<CombineData.CombineItemPair> material) {
this.material = material;
}
public List<CombineData.CombineItemPair> getResult() {
return result;
}
public void setResult(List<CombineData.CombineItemPair> result) {
this.result = result;
}
public List<CombineData.CombineItemPair> getExtra() {
return extra;
}
public void setExtra(List<CombineData.CombineItemPair> extra) {
this.extra = extra;
}
public List<CombineData.CombineItemPair> getBack() {
return back;
}
public void setBack(List<CombineData.CombineItemPair> back) {
this.back = back;
}
}
package emu.grasscutter.game.drop;
public class DropData {
private int minWeight;
private int maxWeight;
private int itemId;
private int minCount;
private int maxCount;
private boolean share = false;
private boolean give = false;
public boolean isGive() {
return give;
}
public void setGive(boolean give) {
this.give = give;
}
public int getItemId() {
return itemId;
}
public void setItemId(int itemId) {
this.itemId = itemId;
}
public int getMinCount() {
return minCount;
}
public int getMaxCount() {
return maxCount;
}
public int getMinWeight() {
return minWeight;
}
public int getMaxWeight() {
return maxWeight;
}
public boolean isShare() {
return share;
}
public void setIsShare(boolean share) {
this.share = share;
}
}
package emu.grasscutter.game.drop;
import java.util.List;
public class DropInfo {
public int getMonsterId() {
return monsterId;
}
public List<DropData> getDropDataList() {
return dropDataList;
}
private int monsterId;
private List<DropData> dropDataList;
}
package emu.grasscutter.game.drop;
import com.google.gson.reflect.TypeToken;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.game.entity.EntityItem;
import emu.grasscutter.game.entity.EntityMonster;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.Utils;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.io.FileReader;
import java.util.Collection;
import java.util.List;
public class DropManager {
public GameServer getGameServer() {
return gameServer;
}
private final GameServer gameServer;
public Int2ObjectMap<List<DropData>> getDropData() {
return dropData;
}
private final Int2ObjectMap<List<DropData>> dropData;
public DropManager(GameServer gameServer) {
this.gameServer = gameServer;
this.dropData = new Int2ObjectOpenHashMap<>();
this.load();
}
public synchronized void load() {
try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "Drop.json")) {
getDropData().clear();
List<DropInfo> banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, DropInfo.class).getType());
if(banners.size() > 0) {
for (DropInfo di : banners) {
getDropData().put(di.getMonsterId(), di.getDropDataList());
}
Grasscutter.getLogger().info("Drop data successfully loaded.");
} else {
Grasscutter.getLogger().error("Unable to load drop data. Drop data size is 0.");
}
} catch (Exception e) {
Grasscutter.getLogger().error("Unable to load drop data.", e);
}
}
private void addDropEntity(DropData dd, Scene dropScene, ItemData itemData, Position pos, int num, Player target) {
if (!dd.isGive() && (itemData.getItemType() != ItemType.ITEM_VIRTUAL || itemData.getGadgetId() != 0)) {
EntityItem entity = new EntityItem(dropScene, target, itemData, pos, num, dd.isShare());
if (!dd.isShare())
dropScene.addEntityToSingleClient(target, entity);
else
dropScene.addEntity(entity);
} else {
if (target != null) {
target.getInventory().addItem(new GameItem(itemData, num), ActionReason.SubfieldDrop, true);
} else {
// target is null if items will be added are shared. no one could pick it up because of the combination(give + shared)
// so it will be sent to all players' inventories directly.
dropScene.getPlayers().forEach(x -> {
x.getInventory().addItem(new GameItem(itemData, num), ActionReason.SubfieldDrop, true);
});
}
}
}
private void processDrop(DropData dd, EntityMonster em, Player gp) {
int target = Utils.randomRange(1, 10000);
if (target >= dd.getMinWeight() && target < dd.getMaxWeight()) {
ItemData itemData = GameData.getItemDataMap().get(dd.getItemId());
int num = Utils.randomRange(dd.getMinCount(), dd.getMaxCount());
if (itemData == null) {
return;
}
if (itemData.isEquip()) {
for (int i = 0; i < num; i++) {
float range = (5f + (.1f * num));
Position pos = em.getPosition().clone().addX((float) (Math.random() * range) - (range / 2)).addY(3f).addZ((float) (Math.random() * range) - (range / 2));
addDropEntity(dd, em.getScene(), itemData, pos, num, gp);
}
} else {
Position pos = em.getPosition().clone().addY(3f);
addDropEntity(dd, em.getScene(), itemData, pos, num, gp);
}
}
}
public void callDrop(EntityMonster em) {
int id = em.getMonsterData().getId();
if (getDropData().containsKey(id)) {
for (DropData dd : getDropData().get(id)) {
if (dd.isShare())
processDrop(dd, em, null);
else {
for (Player gp : em.getScene().getPlayers()) {
processDrop(dd, em, gp);
}
}
}
}
}
}
package emu.grasscutter.game.dungeons;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.server.packet.send.PacketDungeonSettleNotify;
import emu.grasscutter.utils.Utils;
public class BasicDungeonSettleListener implements DungeonSettleListener {
@Override
public void onDungeonSettle(Scene scene) {
scene.setAutoCloseTime(Utils.getCurrentSeconds() + 1000);
scene.broadcastPacket(new PacketDungeonSettleNotify(scene.getChallenge()));
}
}
package emu.grasscutter.game.dungeons;
import emu.grasscutter.data.common.ItemParamData;
import emu.grasscutter.data.def.DungeonData;
import emu.grasscutter.game.entity.EntityMonster;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.scripts.data.ScriptArgs;
import emu.grasscutter.server.packet.send.PacketChallengeDataNotify;
import emu.grasscutter.server.packet.send.PacketDungeonChallengeBeginNotify;
import emu.grasscutter.server.packet.send.PacketDungeonChallengeFinishNotify;
import emu.grasscutter.server.packet.send.PacketGadgetAutoPickDropInfoNotify;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.ArrayList;
import java.util.List;
public class DungeonChallenge {
private final Scene scene;
private final SceneGroup group;
private int challengeIndex;
private int challengeId;
private boolean success;
private boolean progress;
private int score;
private int objective = 0;
private IntSet rewardedPlayers;
public DungeonChallenge(Scene scene, SceneGroup group) {
this.scene = scene;
this.group = group;
this.setRewardedPlayers(new IntOpenHashSet());
}
public Scene getScene() {
return scene;
}
public SceneGroup getGroup() {
return group;
}
public int getChallengeIndex() {
return challengeIndex;
}
public void setChallengeIndex(int challengeIndex) {
this.challengeIndex = challengeIndex;
}
public int getChallengeId() {
return challengeId;
}
public void setChallengeId(int challengeId) {
this.challengeId = challengeId;
}
public int getObjective() {
return objective;
}
public void setObjective(int objective) {
this.objective = objective;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean isSuccess) {
this.success = isSuccess;
}
public boolean inProgress() {
return progress;
}
public int getScore() {
return score;
}
public int getTimeLimit() {
return 600;
}
public IntSet getRewardedPlayers() {
return rewardedPlayers;
}
public void setRewardedPlayers(IntSet rewardedPlayers) {
this.rewardedPlayers = rewardedPlayers;
}
public void start() {
this.progress = true;
getScene().broadcastPacket(new PacketDungeonChallengeBeginNotify(this));
}
public void finish() {
this.progress = false;
getScene().broadcastPacket(new PacketDungeonChallengeFinishNotify(this));
if (this.isSuccess()) {
// Call success script event
this.getScene().getScriptManager().callEvent(EventType.EVENT_CHALLENGE_SUCCESS, null);
// Settle
settle();
} else {
this.getScene().getScriptManager().callEvent(EventType.EVENT_CHALLENGE_FAIL, null);
}
}
private void settle() {
getScene().getDungeonSettleObservers().forEach(o -> o.onDungeonSettle(getScene()));
getScene().getScriptManager().callEvent(EventType.EVENT_DUNGEON_SETTLE, new ScriptArgs(this.isSuccess() ? 1 : 0));
}
public void onMonsterDie(EntityMonster entity) {
score = getScore() + 1;
getScene().broadcastPacket(new PacketChallengeDataNotify(this, 1, getScore()));
if (getScore() >= getObjective() && this.progress) {
this.setSuccess(true);
finish();
}
}
public void getStatueDrops(Player player) {
DungeonData dungeonData = getScene().getDungeonData();
if (!isSuccess() || dungeonData == null || dungeonData.getRewardPreview() == null || dungeonData.getRewardPreview().getPreviewItems().length == 0) {
return;
}
// Already rewarded
if (getRewardedPlayers().contains(player.getUid())) {
return;
}
List<GameItem> rewards = new ArrayList<>();
for (ItemParamData param : getScene().getDungeonData().getRewardPreview().getPreviewItems()) {
rewards.add(new GameItem(param.getId(), Math.max(param.getCount(), 1)));
}
player.getInventory().addItems(rewards, ActionReason.DungeonStatueDrop);
player.sendPacket(new PacketGadgetAutoPickDropInfoNotify(rewards));
getRewardedPlayers().add(player.getUid());
}
}
package emu.grasscutter.game.dungeons;
import emu.grasscutter.GameConstants;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.custom.ScenePointEntry;
import emu.grasscutter.data.def.DungeonData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.SceneType;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.packet.send.PacketDungeonEntryInfoRsp;
import emu.grasscutter.server.packet.send.PacketPlayerEnterDungeonRsp;
import emu.grasscutter.utils.Position;
import java.util.List;
public class DungeonManager {
private final GameServer server;
private static final BasicDungeonSettleListener basicDungeonSettleObserver = new BasicDungeonSettleListener();
public DungeonManager(GameServer server) {
this.server = server;
}
......@@ -12,4 +26,88 @@ public class DungeonManager {
public GameServer getServer() {
return server;
}
public void getEntryInfo(Player player, int pointId) {
ScenePointEntry entry = GameData.getScenePointEntryById(player.getScene().getId(), pointId);
if (entry == null) {
// Error
player.sendPacket(new PacketDungeonEntryInfoRsp());
return;
}
player.sendPacket(new PacketDungeonEntryInfoRsp(player, entry.getPointData()));
}
public boolean enterDungeon(Player player, int pointId, int dungeonId) {
DungeonData data = GameData.getDungeonDataMap().get(dungeonId);
if (data == null) {
return false;
}
Grasscutter.getLogger().info(player.getNickname() + " is trying to enter dungeon " + dungeonId);
int sceneId = data.getSceneId();
player.getScene().setPrevScene(sceneId);
if(player.getWorld().transferPlayerToScene(player, sceneId, data)){
player.getScene().addDungeonSettleObserver(basicDungeonSettleObserver);
}
player.getScene().setPrevScenePoint(pointId);
player.sendPacket(new PacketPlayerEnterDungeonRsp(pointId, dungeonId));
return true;
}
/**
* used in tower dungeons handoff
*/
public boolean handoffDungeon(Player player, int dungeonId, List<DungeonSettleListener> dungeonSettleListeners) {
DungeonData data = GameData.getDungeonDataMap().get(dungeonId);
if (data == null) {
return false;
}
Grasscutter.getLogger().info(player.getNickname() + " is trying to enter tower dungeon " + dungeonId);
if(player.getWorld().transferPlayerToScene(player, data.getSceneId(), data)){
dungeonSettleListeners.forEach(player.getScene()::addDungeonSettleObserver);
}
return true;
}
public void exitDungeon(Player player) {
if (player.getScene().getSceneType() != SceneType.SCENE_DUNGEON) {
return;
}
// Get previous scene
int prevScene = player.getScene().getPrevScene() > 0 ? player.getScene().getPrevScene() : 3;
// Get previous position
DungeonData dungeonData = player.getScene().getDungeonData();
Position prevPos = new Position(GameConstants.START_POSITION);
if (dungeonData != null) {
ScenePointEntry entry = GameData.getScenePointEntryById(prevScene, player.getScene().getPrevScenePoint());
if (entry != null) {
prevPos.set(entry.getPointData().getTranPos());
}
}
// clean temp team if it has
player.getTeamManager().cleanTemporaryTeam();
player.getTowerManager().clearEntry();
// Transfer player back to world
player.getWorld().transferPlayerToScene(player, prevScene, prevPos);
player.sendPacket(new BasePacket(PacketOpcodes.PlayerQuitDungeonRsp));
}
public void updateDailyDungeons() {
for (ScenePointEntry entry : GameData.getScenePointEntries().values()) {
entry.getPointData().updateDailyDungeon();
}
}
}
package emu.grasscutter.game.dungeons;
import emu.grasscutter.game.world.Scene;
public interface DungeonSettleListener {
void onDungeonSettle(Scene scene);
}
package emu.grasscutter.game.dungeons;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.server.packet.send.PacketDungeonSettleNotify;
import emu.grasscutter.server.packet.send.PacketTowerFloorRecordChangeNotify;
import emu.grasscutter.utils.Utils;
public class TowerDungeonSettleListener implements DungeonSettleListener {
@Override
public void onDungeonSettle(Scene scene) {
scene.setAutoCloseTime(Utils.getCurrentSeconds() + 1000);
var towerManager = scene.getPlayers().get(0).getTowerManager();
towerManager.notifyCurLevelRecordChangeWhenDone();
scene.broadcastPacket(new PacketTowerFloorRecordChangeNotify(towerManager.getCurrentFloorId()));
scene.broadcastPacket(new PacketDungeonSettleNotify(scene.getChallenge(),
true,
towerManager.hasNextLevel(),
towerManager.getNextFloorId()
));
}
}
package emu.grasscutter.game.entity;
import emu.grasscutter.GenshinConstants;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.GameConstants;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.data.def.AvatarSkillDepotData;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.GenshinScene;
import emu.grasscutter.game.World;
import emu.grasscutter.game.avatar.GenshinAvatar;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.inventory.EquipType;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.game.world.World;
import emu.grasscutter.net.proto.AbilityControlBlockOuterClass.AbilityControlBlock;
import emu.grasscutter.net.proto.AbilityEmbryoOuterClass.AbilityEmbryo;
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
......@@ -34,29 +34,29 @@ import emu.grasscutter.utils.Utils;
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public class EntityAvatar extends GenshinEntity {
private final GenshinAvatar avatar;
public class EntityAvatar extends GameEntity {
private final Avatar avatar;
private PlayerDieType killedType;
private int killedBy;
public EntityAvatar(GenshinScene scene, GenshinAvatar avatar) {
public EntityAvatar(Scene scene, Avatar avatar) {
super(scene);
this.avatar = avatar;
this.id = getScene().getWorld().getNextEntityId(EntityIdType.AVATAR);
GenshinItem weapon = this.getAvatar().getWeapon();
GameItem weapon = this.getAvatar().getWeapon();
if (weapon != null) {
weapon.setWeaponEntityId(getScene().getWorld().getNextEntityId(EntityIdType.WEAPON));
}
}
public EntityAvatar(GenshinAvatar avatar) {
public EntityAvatar(Avatar avatar) {
super(null);
this.avatar = avatar;
}
public GenshinPlayer getPlayer() {
public Player getPlayer() {
return avatar.getPlayer();
}
......@@ -70,7 +70,7 @@ public class EntityAvatar extends GenshinEntity {
return getPlayer().getRotation();
}
public GenshinAvatar getAvatar() {
public Avatar getAvatar() {
return avatar;
}
......@@ -101,13 +101,18 @@ public class EntityAvatar extends GenshinEntity {
@Override
public void onDeath(int killerId) {
this.killedType = PlayerDieType.PlayerDieKillByMonster;
this.killedType = PlayerDieType.PLAYER_DIE_KILL_BY_MONSTER;
this.killedBy = killerId;
}
public void onDeath(PlayerDieType dieType, int killerId) {
this.killedType = dieType;
this.killedBy = killerId;
}
public SceneAvatarInfo getSceneAvatarInfo() {
SceneAvatarInfo.Builder avatarInfo = SceneAvatarInfo.newBuilder()
.setPlayerId(this.getPlayer().getUid())
.setUid(this.getPlayer().getUid())
.setAvatarId(this.getAvatar().getAvatarId())
.setGuid(this.getAvatar().getGuid())
.setPeerId(this.getPlayer().getPeerId())
......@@ -122,7 +127,7 @@ public class EntityAvatar extends GenshinEntity {
.setCostumeId(this.getAvatar().getCostume())
.setBornTime(this.getAvatar().getBornTime());
for (GenshinItem item : avatar.getEquips().values()) {
for (GameItem item : avatar.getEquips().values()) {
if (item.getItemData().getEquipType() == EquipType.EQUIP_WEAPON) {
avatarInfo.setWeapon(item.createSceneWeaponInfo());
} else {
......@@ -145,7 +150,7 @@ public class EntityAvatar extends GenshinEntity {
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId())
.setEntityType(ProtEntityType.ProtEntityAvatar)
.setEntityType(ProtEntityType.PROT_ENTITY_AVATAR)
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder())
.setEntityAuthorityInfo(authority)
......@@ -161,7 +166,7 @@ public class EntityAvatar extends GenshinEntity {
if (entry.getIntKey() == 0) {
continue;
}
FightPropPair fightProp = FightPropPair.newBuilder().setType(entry.getIntKey()).setPropValue(entry.getFloatValue()).build();
FightPropPair fightProp = FightPropPair.newBuilder().setPropType(entry.getIntKey()).setPropValue(entry.getFloatValue()).build();
entityInfo.addFightPropList(fightProp);
}
......@@ -187,17 +192,17 @@ public class EntityAvatar extends GenshinEntity {
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId)
.setAbilityNameHash(id)
.setAbilityOverrideNameHash(GenshinConstants.DEFAULT_ABILITY_NAME)
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
.build();
abilityControlBlock.addAbilityEmbryoList(emb);
}
}
// Add default abilities
for (int id : GenshinConstants.DEFAULT_ABILITY_HASHES) {
for (int id : GameConstants.DEFAULT_ABILITY_HASHES) {
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId)
.setAbilityNameHash(id)
.setAbilityOverrideNameHash(GenshinConstants.DEFAULT_ABILITY_NAME)
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
.build();
abilityControlBlock.addAbilityEmbryoList(emb);
}
......@@ -206,18 +211,18 @@ public class EntityAvatar extends GenshinEntity {
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId)
.setAbilityNameHash(id)
.setAbilityOverrideNameHash(GenshinConstants.DEFAULT_ABILITY_NAME)
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
.build();
abilityControlBlock.addAbilityEmbryoList(emb);
}
// Add skill depot abilities
AvatarSkillDepotData skillDepot = GenshinData.getAvatarSkillDepotDataMap().get(this.getAvatar().getSkillDepotId());
AvatarSkillDepotData skillDepot = GameData.getAvatarSkillDepotDataMap().get(this.getAvatar().getSkillDepotId());
if (skillDepot != null && skillDepot.getAbilities() != null) {
for (int id : skillDepot.getAbilities()) {
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId)
.setAbilityNameHash(id)
.setAbilityOverrideNameHash(GenshinConstants.DEFAULT_ABILITY_NAME)
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
.build();
abilityControlBlock.addAbilityEmbryoList(emb);
}
......@@ -228,7 +233,7 @@ public class EntityAvatar extends GenshinEntity {
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId)
.setAbilityNameHash(Utils.abilityHash(skill))
.setAbilityOverrideNameHash(GenshinConstants.DEFAULT_ABILITY_NAME)
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
.build();
abilityControlBlock.addAbilityEmbryoList(emb);
}
......
package emu.grasscutter.game.entity;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.game.world.World;
public abstract class EntityBaseGadget extends GameEntity {
public EntityBaseGadget(Scene scene) {
super(scene);
}
public abstract int getGadgetId();
@Override
public void onDeath(int killerId) {
}
}
package emu.grasscutter.game.entity;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.GenshinScene;
import emu.grasscutter.game.World;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.game.world.World;
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
import emu.grasscutter.net.proto.ClientGadgetInfoOuterClass;
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
......@@ -22,8 +23,8 @@ import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public class EntityClientGadget extends EntityGadget {
private final GenshinPlayer owner;
public class EntityClientGadget extends EntityBaseGadget {
private final Player owner;
private final Position pos;
private final Position rot;
......@@ -35,7 +36,7 @@ public class EntityClientGadget extends EntityGadget {
private int targetEntityId;
private boolean asyncLoad;
public EntityClientGadget(GenshinScene scene, GenshinPlayer player, EvtCreateGadgetNotify notify) {
public EntityClientGadget(Scene scene, Player player, EvtCreateGadgetNotify notify) {
super(scene);
this.owner = player;
this.id = notify.getEntityId();
......@@ -54,7 +55,7 @@ public class EntityClientGadget extends EntityGadget {
return configId;
}
public GenshinPlayer getOwner() {
public Player getOwner() {
return owner;
}
......@@ -112,7 +113,7 @@ public class EntityClientGadget extends EntityGadget {
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId())
.setEntityType(ProtEntityType.ProtEntityGadget)
.setEntityType(ProtEntityType.PROT_ENTITY_GADGET)
.setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder()))
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder())
......@@ -125,7 +126,7 @@ public class EntityClientGadget extends EntityGadget {
.build();
entityInfo.addPropList(pair);
GadgetClientParam clientGadget = GadgetClientParam.newBuilder()
ClientGadgetInfoOuterClass.ClientGadgetInfo clientGadget = ClientGadgetInfoOuterClass.ClientGadgetInfo.newBuilder()
.setCampId(this.getCampId())
.setCampType(this.getCampType())
.setOwnerEntityId(this.getOwnerEntityId())
......
package emu.grasscutter.game.entity;
import emu.grasscutter.game.GenshinScene;
import emu.grasscutter.game.World;
import java.util.Arrays;
import java.util.List;
public abstract class EntityGadget extends GenshinEntity {
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.GadgetData;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.EntityType;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.game.world.World;
import emu.grasscutter.net.proto.ClientGadgetInfoOuterClass;
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo;
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
import emu.grasscutter.net.proto.WorktopInfoOuterClass.WorktopInfo;
import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
public EntityGadget(GenshinScene scene) {
public class EntityGadget extends EntityBaseGadget {
private final GadgetData data;
private final Position pos;
private final Position rot;
private int gadgetId;
private int state;
private IntSet worktopOptions;
public EntityGadget(Scene scene, int gadgetId, Position pos) {
super(scene);
this.data = GameData.getGadgetDataMap().get(gadgetId);
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
this.gadgetId = gadgetId;
this.pos = pos.clone();
this.rot = new Position();
}
public GadgetData getGadgetData() {
return data;
}
@Override
public Position getPosition() {
// TODO Auto-generated method stub
return this.pos;
}
@Override
public Position getRotation() {
// TODO Auto-generated method stub
return this.rot;
}
public int getGadgetId() {
return gadgetId;
}
public void setGadgetId(int gadgetId) {
this.gadgetId = gadgetId;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public IntSet getWorktopOptions() {
return worktopOptions;
}
public void addWorktopOptions(int[] options) {
if (this.worktopOptions == null) {
this.worktopOptions = new IntOpenHashSet();
}
Arrays.stream(options).forEach(this.worktopOptions::add);
}
public void removeWorktopOption(int option) {
if (this.worktopOptions == null) {
return;
}
this.worktopOptions.remove(option);
}
public abstract int getGadgetId();
@Override
public Int2FloatOpenHashMap getFightProperties() {
// TODO Auto-generated method stub
return null;
}
@Override
public void onDeath(int killerId) {
}
@Override
public SceneEntityInfo toProto() {
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder()
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
.setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder()))
.setBornPos(Vector.newBuilder())
.build();
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId())
.setEntityType(ProtEntityType.PROT_ENTITY_GADGET)
.setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder()))
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder())
.setEntityAuthorityInfo(authority)
.setLifeState(1);
PropPair pair = PropPair.newBuilder()
.setType(PlayerProperty.PROP_LEVEL.getId())
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1))
.build();
entityInfo.addPropList(pair);
SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder()
.setGadgetId(this.getGadgetId())
.setGroupId(this.getGroupId())
.setConfigId(this.getConfigId())
.setGadgetState(this.getState())
.setIsEnableInteract(true)
.setAuthorityPeerId(this.getScene().getWorld().getHostPeerId());
if (this.getGadgetData().getType() == EntityType.Worktop && this.getWorktopOptions() != null) {
WorktopInfo worktop = WorktopInfo.newBuilder()
.addAllOptionList(this.getWorktopOptions())
.build();
gadgetInfo.setWorktop(worktop);
}
entityInfo.setGadget(gadgetInfo);
return entityInfo.build();
}
}
package emu.grasscutter.game.entity;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.GenshinScene;
import emu.grasscutter.game.World;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
......@@ -24,20 +23,36 @@ import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public class EntityItem extends EntityGadget {
public class EntityItem extends EntityBaseGadget {
private final Position pos;
private final Position rot;
private final GenshinItem item;
private final GameItem item;
private final long guid;
public EntityItem(GenshinScene scene, GenshinPlayer player, ItemData itemData, Position pos, int count) {
private final boolean share;
public EntityItem(Scene scene, Player player, ItemData itemData, Position pos, int count) {
super(scene);
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
this.pos = new Position(pos);
this.rot = new Position();
this.guid = player.getNextGenshinGuid();
this.item = new GenshinItem(itemData, count);
this.guid = player == null ? scene.getWorld().getHost().getNextGameGuid() : player.getNextGameGuid();
this.item = new GameItem(itemData, count);
this.share = true;
}
// In official game, some drop items are shared to all players, and some other items are independent to all players
// For example, if you killed a monster in MP mode, all players could get drops but rarity and number of them are different
// but if you broke regional mine, when someone picked up the drop then it disappeared
public EntityItem(Scene scene, Player player, ItemData itemData, Position pos, int count, boolean share) {
super(scene);
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
this.pos = new Position(pos);
this.rot = new Position();
this.guid = player == null ? scene.getWorld().getHost().getNextGameGuid() : player.getNextGameGuid();
this.item = new GameItem(itemData, count);
this.share = share;
}
@Override
......@@ -45,7 +60,7 @@ public class EntityItem extends EntityGadget {
return this.id;
}
private GenshinItem getItem() {
private GameItem getItem() {
return this.item;
}
......@@ -81,6 +96,10 @@ public class EntityItem extends EntityGadget {
return null;
}
public boolean isShare() {
return share;
}
@Override
public SceneEntityInfo toProto() {
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder()
......@@ -92,7 +111,7 @@ public class EntityItem extends EntityGadget {
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId())
.setEntityType(ProtEntityType.ProtEntityGadget)
.setEntityType(ProtEntityType.PROT_ENTITY_GADGET)
.setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder()))
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder())
......@@ -108,7 +127,7 @@ public class EntityItem extends EntityGadget {
SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder()
.setGadgetId(this.getItemData().getGadgetId())
.setTrifleItem(this.getItem().toProto())
.setBornType(GadgetBornType.GadgetBornInAir)
.setBornType(GadgetBornType.GADGET_BORN_IN_AIR)
.setAuthorityPeerId(this.getWorld().getHostPeerId())
.setIsEnableInteract(true);
......
package emu.grasscutter.game.entity;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.common.PropGrowCurve;
import emu.grasscutter.data.def.MonsterCurveData;
import emu.grasscutter.data.def.MonsterData;
import emu.grasscutter.game.GenshinScene;
import emu.grasscutter.game.World;
import emu.grasscutter.game.dungeons.DungeonChallenge;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.game.world.World;
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
......@@ -22,12 +23,13 @@ import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo;
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.grasscutter.net.proto.SceneMonsterInfoOuterClass.SceneMonsterInfo;
import emu.grasscutter.net.proto.SceneWeaponInfoOuterClass.SceneWeaponInfo;
import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public class EntityMonster extends GenshinEntity {
public class EntityMonster extends GameEntity {
private final MonsterData monsterData;
private final Int2FloatOpenHashMap fightProp;
......@@ -36,8 +38,9 @@ public class EntityMonster extends GenshinEntity {
private final Position bornPos;
private final int level;
private int weaponEntityId;
private int poseId;
public EntityMonster(GenshinScene scene, MonsterData monsterData, Position pos, int level) {
public EntityMonster(Scene scene, MonsterData monsterData, Position pos, int level) {
super(scene);
this.id = getWorld().getNextEntityId(EntityIdType.MONSTER);
this.monsterData = monsterData;
......@@ -100,9 +103,25 @@ public class EntityMonster extends GenshinEntity {
return this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0f;
}
public int getPoseId() {
return poseId;
}
public void setPoseId(int poseId) {
this.poseId = poseId;
}
@Override
public void onDeath(int killerId) {
if (this.getSpawnEntry() != null) {
this.getScene().getDeadSpawnedEntities().add(getSpawnEntry());
}
if (getScene().getScriptManager().isInit() && this.getGroupId() > 0) {
getScene().getScriptManager().callEvent(EventType.EVENT_ANY_MONSTER_DIE, null);
}
if (getScene().getChallenge() != null && getScene().getChallenge().getGroup().id == this.getGroupId()) {
getScene().getChallenge().onMonsterDie(this);
}
}
public void recalcStats() {
......@@ -130,7 +149,7 @@ public class EntityMonster extends GenshinEntity {
this.setFightProperty(FightProperty.FIGHT_PROP_ICE_SUB_HURT, data.getIceSubHurt());
// Level curve
MonsterCurveData curve = GenshinData.getMonsterCurveDataMap().get(this.getLevel());
MonsterCurveData curve = GameData.getMonsterCurveDataMap().get(this.getLevel());
if (curve != null) {
for (PropGrowCurve growCurve : data.getPropGrowCurves()) {
FightProperty prop = FightProperty.getPropByName(growCurve.getType());
......@@ -167,7 +186,7 @@ public class EntityMonster extends GenshinEntity {
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId())
.setEntityType(ProtEntityType.ProtEntityMonster)
.setEntityType(ProtEntityType.PROT_ENTITY_MONSTER)
.setMotionInfo(this.getMotionInfo())
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder())
......@@ -178,7 +197,7 @@ public class EntityMonster extends GenshinEntity {
if (entry.getIntKey() == 0) {
continue;
}
FightPropPair fightProp = FightPropPair.newBuilder().setType(entry.getIntKey()).setPropValue(entry.getFloatValue()).build();
FightPropPair fightProp = FightPropPair.newBuilder().setPropType(entry.getIntKey()).setPropValue(entry.getFloatValue()).build();
entityInfo.addFightPropList(fightProp);
}
......@@ -190,13 +209,13 @@ public class EntityMonster extends GenshinEntity {
SceneMonsterInfo.Builder monsterInfo = SceneMonsterInfo.newBuilder()
.setMonsterId(getMonsterId())
.setGroupId(133003095)
.setConfigId(95001)
.setGroupId(this.getGroupId())
.setConfigId(this.getConfigId())
.addAllAffixList(getMonsterData().getAffix())
.setAuthorityPeerId(getWorld().getHostPeerId())
.setPoseId(0)
.setPoseId(this.getPoseId())
.setBlockId(3001)
.setBornType(MonsterBornType.MonsterBornDefault)
.setBornType(MonsterBornType.MONSTER_BORN_DEFAULT)
.setSpecialNameId(40);
if (getMonsterData().getDescribeData() != null) {
......@@ -210,7 +229,7 @@ public class EntityMonster extends GenshinEntity {
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
.build();
monsterInfo.setWeaponList(weaponInfo);
monsterInfo.addWeaponList(weaponInfo);
}
entityInfo.setMonster(monsterInfo);
......
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