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; package emu.grasscutter.game;
import emu.grasscutter.game.player.Player;
public class CoopRequest { public class CoopRequest {
private final GenshinPlayer requester; private final Player requester;
private final long requestTime; private final long requestTime;
private final long expireTime; private final long expireTime;
public CoopRequest(GenshinPlayer requester) { public CoopRequest(Player requester) {
this.requester = requester; this.requester = requester;
this.requestTime = System.currentTimeMillis(); this.requestTime = System.currentTimeMillis();
this.expireTime = this.requestTime + 10000; this.expireTime = this.requestTime + 10000;
} }
public GenshinPlayer getRequester() { public Player getRequester() {
return requester; return requester;
} }
......
...@@ -5,6 +5,7 @@ import java.util.HashMap; ...@@ -5,6 +5,7 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
...@@ -15,10 +16,10 @@ import dev.morphia.annotations.Indexed; ...@@ -15,10 +16,10 @@ import dev.morphia.annotations.Indexed;
import dev.morphia.annotations.PostLoad; import dev.morphia.annotations.PostLoad;
import dev.morphia.annotations.PrePersist; import dev.morphia.annotations.PrePersist;
import dev.morphia.annotations.Transient; import dev.morphia.annotations.Transient;
import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.common.FightPropData; import emu.grasscutter.data.common.FightPropData;
import emu.grasscutter.data.custom.OpenConfigEntry; import emu.grasscutter.data.custom.OpenConfigEntry;
import emu.grasscutter.data.custom.OpenConfigEntry.SkillPointModifier;
import emu.grasscutter.data.def.AvatarData; import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.data.def.AvatarPromoteData; import emu.grasscutter.data.def.AvatarPromoteData;
import emu.grasscutter.data.def.AvatarSkillData; import emu.grasscutter.data.def.AvatarSkillData;
...@@ -26,27 +27,32 @@ import emu.grasscutter.data.def.AvatarSkillDepotData; ...@@ -26,27 +27,32 @@ import emu.grasscutter.data.def.AvatarSkillDepotData;
import emu.grasscutter.data.def.AvatarSkillDepotData.InherentProudSkillOpens; import emu.grasscutter.data.def.AvatarSkillDepotData.InherentProudSkillOpens;
import emu.grasscutter.data.def.AvatarTalentData; import emu.grasscutter.data.def.AvatarTalentData;
import emu.grasscutter.data.def.EquipAffixData; 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.ReliquaryAffixData;
import emu.grasscutter.data.def.ReliquaryLevelData; import emu.grasscutter.data.def.ReliquaryLevelData;
import emu.grasscutter.data.def.ReliquaryMainPropData; import emu.grasscutter.data.def.ReliquaryMainPropData;
import emu.grasscutter.data.def.ReliquarySetData; import emu.grasscutter.data.def.ReliquarySetData;
import emu.grasscutter.data.def.WeaponCurveData; import emu.grasscutter.data.def.WeaponCurveData;
import emu.grasscutter.data.def.WeaponPromoteData; 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.database.DatabaseHelper;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.entity.EntityAvatar; import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.inventory.EquipType; 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.ElementType;
import emu.grasscutter.game.props.EntityIdType; import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.FetterState; import emu.grasscutter.game.props.FetterState;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo; 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.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.PacketAbilityChangeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarEquipChangeNotify; import emu.grasscutter.server.packet.send.PacketAvatarEquipChangeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarFightPropNotify; import emu.grasscutter.server.packet.send.PacketAvatarFightPropNotify;
...@@ -56,12 +62,12 @@ import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; ...@@ -56,12 +62,12 @@ import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@Entity(value = "avatars", noClassnameStored = true) @Entity(value = "avatars", useDiscriminator = false)
public class GenshinAvatar { public class Avatar {
@Id private ObjectId id; @Id private ObjectId id;
@Indexed private int ownerId; // Id of player that this avatar belongs to @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 AvatarData data;
@Transient private long guid; // Player unique id @Transient private long guid; // Player unique id
private int avatarId; // Id of avatar private int avatarId; // Id of avatar
...@@ -73,13 +79,14 @@ public class GenshinAvatar { ...@@ -73,13 +79,14 @@ public class GenshinAvatar {
private int satiationPenalty; // ? private int satiationPenalty; // ?
private float currentHp; private float currentHp;
@Transient private final Int2ObjectMap<GenshinItem> equips; @Transient private final Int2ObjectMap<GameItem> equips;
@Transient private final Int2FloatOpenHashMap fightProp; @Transient private final Int2FloatOpenHashMap fightProp;
@Transient private Set<String> extraAbilityEmbryos; @Transient private Set<String> extraAbilityEmbryos;
private List<Integer> fetters; private List<Integer> fetters;
private Map<Integer, Integer> skillLevelMap; // Talent levels private Map<Integer, Integer> skillLevelMap; // Talent levels
private Map<Integer, Integer> skillExtraChargeMap; // Charges
private Map<Integer, Integer> proudSkillBonusMap; // Talent bonus levels (from const) private Map<Integer, Integer> proudSkillBonusMap; // Talent bonus levels (from const)
private int skillDepotId; private int skillDepotId;
private int coreProudSkillLevel; // Constellation level private int coreProudSkillLevel; // Constellation level
...@@ -89,29 +96,38 @@ public class GenshinAvatar { ...@@ -89,29 +96,38 @@ public class GenshinAvatar {
private int flyCloak; private int flyCloak;
private int costume; private int costume;
private int bornTime; private int bornTime;
private int fetterLevel = 1;
private int fetterExp;
private int nameCardRewardId;
private int nameCardId;
public GenshinAvatar() { public Avatar() {
// Morhpia only! // Morhpia only!
this.equips = new Int2ObjectOpenHashMap<>(); this.equips = new Int2ObjectOpenHashMap<>();
this.fightProp = new Int2FloatOpenHashMap(); this.fightProp = new Int2FloatOpenHashMap();
this.extraAbilityEmbryos = new HashSet<>(); this.extraAbilityEmbryos = new HashSet<>();
this.proudSkillBonusMap = new HashMap<>(); this.proudSkillBonusMap = new HashMap<>();
this.fetters = new ArrayList<>(); // TODO Move to genshin avatar this.fetters = new ArrayList<>(); // TODO Move to avatar
} }
// On creation // On creation
public GenshinAvatar(int avatarId) { public Avatar(int avatarId) {
this(GenshinData.getAvatarDataMap().get(avatarId)); this(GameData.getAvatarDataMap().get(avatarId));
} }
public GenshinAvatar(AvatarData data) { public Avatar(AvatarData data) {
this(); this();
this.avatarId = data.getId(); this.avatarId = data.getId();
this.nameCardRewardId = data.getNameCardRewardId();
this.nameCardId = data.getNameCardId();
this.data = data; this.data = data;
this.bornTime = (int) (System.currentTimeMillis() / 1000); this.bornTime = (int) (System.currentTimeMillis() / 1000);
this.flyCloak = 140001; this.flyCloak = 140001;
this.skillLevelMap = new HashMap<>(); this.skillLevelMap = new HashMap<>();
this.skillExtraChargeMap = new HashMap<>();
this.talentIdList = new HashSet<>(); this.talentIdList = new HashSet<>();
this.proudSkillList = new HashSet<>(); this.proudSkillList = new HashSet<>();
...@@ -135,7 +151,7 @@ public class GenshinAvatar { ...@@ -135,7 +151,7 @@ public class GenshinAvatar {
this.onLoad(); this.onLoad();
} }
public GenshinPlayer getPlayer() { public Player getPlayer() {
return this.owner; return this.owner;
} }
...@@ -155,10 +171,10 @@ public class GenshinAvatar { ...@@ -155,10 +171,10 @@ public class GenshinAvatar {
return ownerId; return ownerId;
} }
public void setOwner(GenshinPlayer player) { public void setOwner(Player player) {
this.owner = player; this.owner = player;
this.ownerId = player.getUid(); this.ownerId = player.getUid();
this.guid = player.getNextGenshinGuid(); this.guid = player.getNextGameGuid();
} }
public int getSatiation() { public int getSatiation() {
...@@ -169,6 +185,14 @@ public class GenshinAvatar { ...@@ -169,6 +185,14 @@ public class GenshinAvatar {
this.satiation = satiation; this.satiation = satiation;
} }
public int getNameCardRewardId() {
return nameCardRewardId;
}
public void setNameCardRewardId(int nameCardRewardId) {
this.nameCardRewardId = nameCardRewardId;
}
public int getSatiationPenalty() { public int getSatiationPenalty() {
return satiationPenalty; return satiationPenalty;
} }
...@@ -213,19 +237,19 @@ public class GenshinAvatar { ...@@ -213,19 +237,19 @@ public class GenshinAvatar {
this.promoteLevel = promoteLevel; this.promoteLevel = promoteLevel;
} }
public Int2ObjectMap<GenshinItem> getEquips() { public Int2ObjectMap<GameItem> getEquips() {
return equips; return equips;
} }
public GenshinItem getEquipBySlot(EquipType slot) { public GameItem getEquipBySlot(EquipType slot) {
return this.getEquips().get(slot.getValue()); return this.getEquips().get(slot.getValue());
} }
private GenshinItem getEquipBySlot(int slotId) { private GameItem getEquipBySlot(int slotId) {
return this.getEquips().get(slotId); return this.getEquips().get(slotId);
} }
public GenshinItem getWeapon() { public GameItem getWeapon() {
return this.getEquipBySlot(EquipType.EQUIP_WEAPON); return this.getEquipBySlot(EquipType.EQUIP_WEAPON);
} }
...@@ -254,7 +278,7 @@ public class GenshinAvatar { ...@@ -254,7 +278,7 @@ public class GenshinAvatar {
} }
if (openData.getNeedAvatarPromoteLevel() <= this.getPromoteLevel()) { if (openData.getNeedAvatarPromoteLevel() <= this.getPromoteLevel()) {
int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1; int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1;
if (GenshinData.getProudSkillDataMap().containsKey(proudSkillId)) { if (GameData.getProudSkillDataMap().containsKey(proudSkillId)) {
this.getProudSkillList().add(proudSkillId); this.getProudSkillList().add(proudSkillId);
} }
} }
...@@ -264,6 +288,13 @@ public class GenshinAvatar { ...@@ -264,6 +288,13 @@ public class GenshinAvatar {
public Map<Integer, Integer> getSkillLevelMap() { public Map<Integer, Integer> getSkillLevelMap() {
return skillLevelMap; return skillLevelMap;
} }
public Map<Integer, Integer> getSkillExtraChargeMap() {
if (skillExtraChargeMap == null) {
skillExtraChargeMap = new HashMap<>();
}
return skillExtraChargeMap;
}
public Map<Integer, Integer> getProudSkillBonusMap() { public Map<Integer, Integer> getProudSkillBonusMap() {
return proudSkillBonusMap; return proudSkillBonusMap;
...@@ -281,6 +312,30 @@ public class GenshinAvatar { ...@@ -281,6 +312,30 @@ public class GenshinAvatar {
return fetters; 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() { public float getCurrentHp() {
return currentHp; return currentHp;
} }
...@@ -345,16 +400,33 @@ public class GenshinAvatar { ...@@ -345,16 +400,33 @@ public class GenshinAvatar {
return bornTime; 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(); EquipType itemEquipType = item.getItemData().getEquipType();
if (itemEquipType == EquipType.EQUIP_NONE) { if (itemEquipType == EquipType.EQUIP_NONE) {
return false; return false;
} }
if (getEquips().containsKey(itemEquipType.getValue())) { // 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); unequipItem(itemEquipType);
} }
// Set equip
getEquips().put(itemEquipType.getValue(), item); getEquips().put(itemEquipType.getValue(), item);
if (itemEquipType == EquipType.EQUIP_WEAPON && getPlayer().getWorld() != null) { if (itemEquipType == EquipType.EQUIP_WEAPON && getPlayer().getWorld() != null) {
...@@ -376,7 +448,7 @@ public class GenshinAvatar { ...@@ -376,7 +448,7 @@ public class GenshinAvatar {
} }
public boolean unequipItem(EquipType slot) { public boolean unequipItem(EquipType slot) {
GenshinItem item = getEquips().remove(slot.getValue()); GameItem item = getEquips().remove(slot.getValue());
if (item != null) { if (item != null) {
item.setEquipCharacter(0); item.setEquipCharacter(0);
...@@ -394,7 +466,7 @@ public class GenshinAvatar { ...@@ -394,7 +466,7 @@ public class GenshinAvatar {
public void recalcStats(boolean forceSendAbilityChange) { public void recalcStats(boolean forceSendAbilityChange) {
// Setup // Setup
AvatarData data = this.getAvatarData(); AvatarData data = this.getAvatarData();
AvatarPromoteData promoteData = GenshinData.getAvatarPromoteData(data.getAvatarPromoteId(), this.getPromoteLevel()); AvatarPromoteData promoteData = GameData.getAvatarPromoteData(data.getAvatarPromoteId(), this.getPromoteLevel());
Int2IntOpenHashMap setMap = new Int2IntOpenHashMap(); Int2IntOpenHashMap setMap = new Int2IntOpenHashMap();
// Extra ability embryos // Extra ability embryos
...@@ -403,6 +475,8 @@ public class GenshinAvatar { ...@@ -403,6 +475,8 @@ public class GenshinAvatar {
// Fetters // Fetters
this.setFetterList(data.getFetters()); this.setFetterList(data.getFetters());
this.setNameCardRewardId(data.getNameCardRewardId());
this.setNameCardId(data.getNameCardId());
// Get hp percent, set to 100% if none // 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); 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 { ...@@ -434,21 +508,21 @@ public class GenshinAvatar {
// Artifacts // Artifacts
for (int slotId = 1; slotId <= 5; slotId++) { for (int slotId = 1; slotId <= 5; slotId++) {
// Get artifact // Get artifact
GenshinItem equip = this.getEquipBySlot(slotId); GameItem equip = this.getEquipBySlot(slotId);
if (equip == null) { if (equip == null) {
continue; continue;
} }
// Artifact main stat // Artifact main stat
ReliquaryMainPropData mainPropData = GenshinData.getReliquaryMainPropDataMap().get(equip.getMainPropId()); ReliquaryMainPropData mainPropData = GameData.getReliquaryMainPropDataMap().get(equip.getMainPropId());
if (mainPropData != null) { if (mainPropData != null) {
ReliquaryLevelData levelData = GenshinData.getRelicLevelData(equip.getItemData().getRankLevel(), equip.getLevel()); ReliquaryLevelData levelData = GameData.getRelicLevelData(equip.getItemData().getRankLevel(), equip.getLevel());
if (levelData != null) { if (levelData != null) {
this.addFightProperty(mainPropData.getFightProp(), levelData.getPropValue(mainPropData.getFightProp())); this.addFightProperty(mainPropData.getFightProp(), levelData.getPropValue(mainPropData.getFightProp()));
} }
} }
// Artifact sub stats // Artifact sub stats
for (int appendPropId : equip.getAppendPropIdList()) { for (int appendPropId : equip.getAppendPropIdList()) {
ReliquaryAffixData affixData = GenshinData.getReliquaryAffixDataMap().get(appendPropId); ReliquaryAffixData affixData = GameData.getReliquaryAffixDataMap().get(appendPropId);
if (affixData != null) { if (affixData != null) {
this.addFightProperty(affixData.getFightProp(), affixData.getPropValue()); this.addFightProperty(affixData.getFightProp(), affixData.getPropValue());
} }
...@@ -461,7 +535,7 @@ public class GenshinAvatar { ...@@ -461,7 +535,7 @@ public class GenshinAvatar {
// Set stuff // Set stuff
for (Int2IntOpenHashMap.Entry e : setMap.int2IntEntrySet()) { for (Int2IntOpenHashMap.Entry e : setMap.int2IntEntrySet()) {
ReliquarySetData setData = GenshinData.getReliquarySetDataMap().get(e.getIntKey()); ReliquarySetData setData = GameData.getReliquarySetDataMap().get(e.getIntKey());
if (setData == null) { if (setData == null) {
continue; continue;
} }
...@@ -474,7 +548,7 @@ public class GenshinAvatar { ...@@ -474,7 +548,7 @@ public class GenshinAvatar {
if (amount >= setData.getSetNeedNum()[setIndex]) { if (amount >= setData.getSetNeedNum()[setIndex]) {
int affixId = (setData.getEquipAffixId() * 10) + setIndex; int affixId = (setData.getEquipAffixId() * 10) + setIndex;
EquipAffixData affix = GenshinData.getEquipAffixDataMap().get(affixId); EquipAffixData affix = GameData.getEquipAffixDataMap().get(affixId);
if (affix == null) { if (affix == null) {
continue; continue;
} }
...@@ -493,17 +567,17 @@ public class GenshinAvatar { ...@@ -493,17 +567,17 @@ public class GenshinAvatar {
} }
// Weapon // Weapon
GenshinItem weapon = this.getWeapon(); GameItem weapon = this.getWeapon();
if (weapon != null) { if (weapon != null) {
// Add stats // Add stats
WeaponCurveData curveData = GenshinData.getWeaponCurveDataMap().get(weapon.getLevel()); WeaponCurveData curveData = GameData.getWeaponCurveDataMap().get(weapon.getLevel());
if (curveData != null) { if (curveData != null) {
for (WeaponProperty weaponProperty : weapon.getItemData().getWeaponProperties()) { for (WeaponProperty weaponProperty : weapon.getItemData().getWeaponProperties()) {
this.addFightProperty(weaponProperty.getFightProp(), weaponProperty.getInitValue() * curveData.getMultByProp(weaponProperty.getType())); this.addFightProperty(weaponProperty.getFightProp(), weaponProperty.getInitValue() * curveData.getMultByProp(weaponProperty.getType()));
} }
} }
// Weapon promotion stats // Weapon promotion stats
WeaponPromoteData wepPromoteData = GenshinData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel()); WeaponPromoteData wepPromoteData = GameData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel());
if (wepPromoteData != null) { if (wepPromoteData != null) {
for (FightPropData prop : wepPromoteData.getAddProps()) { for (FightPropData prop : wepPromoteData.getAddProps()) {
if (prop.getValue() == 0f || prop.getProp() == null) { if (prop.getValue() == 0f || prop.getProp() == null) {
...@@ -521,7 +595,7 @@ public class GenshinAvatar { ...@@ -521,7 +595,7 @@ public class GenshinAvatar {
} }
// Calculate affix id // Calculate affix id
int affixId = (af * 10) + weapon.getRefinement(); int affixId = (af * 10) + weapon.getRefinement();
EquipAffixData affix = GenshinData.getEquipAffixDataMap().get(affixId); EquipAffixData affix = GameData.getEquipAffixDataMap().get(affixId);
if (affix == null) { if (affix == null) {
continue; continue;
} }
...@@ -538,7 +612,7 @@ public class GenshinAvatar { ...@@ -538,7 +612,7 @@ public class GenshinAvatar {
} }
// Add proud skills and unlock them if needed // 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(); this.getProudSkillList().clear();
for (InherentProudSkillOpens openData : skillDepot.getInherentProudSkillOpens()) { for (InherentProudSkillOpens openData : skillDepot.getInherentProudSkillOpens()) {
if (openData.getProudSkillGroupId() == 0) { if (openData.getProudSkillGroupId() == 0) {
...@@ -546,7 +620,7 @@ public class GenshinAvatar { ...@@ -546,7 +620,7 @@ public class GenshinAvatar {
} }
if (openData.getNeedAvatarPromoteLevel() <= this.getPromoteLevel()) { if (openData.getNeedAvatarPromoteLevel() <= this.getPromoteLevel()) {
int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1; int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1;
if (GenshinData.getProudSkillDataMap().containsKey(proudSkillId)) { if (GameData.getProudSkillDataMap().containsKey(proudSkillId)) {
this.getProudSkillList().add(proudSkillId); this.getProudSkillList().add(proudSkillId);
} }
} }
...@@ -554,7 +628,7 @@ public class GenshinAvatar { ...@@ -554,7 +628,7 @@ public class GenshinAvatar {
// Proud skills // Proud skills
for (int proudSkillId : this.getProudSkillList()) { for (int proudSkillId : this.getProudSkillList()) {
ProudSkillData proudSkillData = GenshinData.getProudSkillDataMap().get(proudSkillId); ProudSkillData proudSkillData = GameData.getProudSkillDataMap().get(proudSkillId);
if (proudSkillData == null) { if (proudSkillData == null) {
continue; continue;
} }
...@@ -571,7 +645,7 @@ public class GenshinAvatar { ...@@ -571,7 +645,7 @@ public class GenshinAvatar {
// Constellations // Constellations
if (this.getTalentIdList().size() > 0) { if (this.getTalentIdList().size() > 0) {
for (int talentId : this.getTalentIdList()) { for (int talentId : this.getTalentIdList()) {
AvatarTalentData avatarTalentData = GenshinData.getAvatarTalentDataMap().get(talentId); AvatarTalentData avatarTalentData = GameData.getAvatarTalentDataMap().get(talentId);
if (avatarTalentData == null) { if (avatarTalentData == null) {
return; return;
} }
...@@ -615,7 +689,7 @@ public class GenshinAvatar { ...@@ -615,7 +689,7 @@ public class GenshinAvatar {
return; return;
} }
OpenConfigEntry entry = GenshinData.getOpenConfigEntries().get(openConfig); OpenConfigEntry entry = GameData.getOpenConfigEntries().get(openConfig);
if (entry == null) { if (entry == null) {
if (forceAdd) { if (forceAdd) {
// Add config string to ability skill list anyways // Add config string to ability skill list anyways
...@@ -631,9 +705,10 @@ public class GenshinAvatar { ...@@ -631,9 +705,10 @@ public class GenshinAvatar {
} }
} }
public void recalcProudSkillBonusMap() { public void recalcConstellations() {
// Clear first // Clear first
this.getProudSkillBonusMap().clear(); this.getProudSkillBonusMap().clear();
this.getSkillExtraChargeMap().clear();
// Sanity checks // Sanity checks
if (getData() == null || getData().getSkillDepot() == null) { if (getData() == null || getData().getSkillDepot() == null) {
...@@ -642,18 +717,33 @@ public class GenshinAvatar { ...@@ -642,18 +717,33 @@ public class GenshinAvatar {
if (this.getTalentIdList().size() > 0) { if (this.getTalentIdList().size() > 0) {
for (int talentId : this.getTalentIdList()) { 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) { if (avatarTalentData == null || avatarTalentData.getOpenConfig() == null || avatarTalentData.getOpenConfig().length() == 0) {
continue; continue;
} }
// Get open config to find which skill should be boosted // 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) { if (entry == null) {
continue; 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; int skillId = 0;
if (entry.getExtraTalentIndex() == 2 && this.getData().getSkillDepot().getSkills().size() >= 2) { if (entry.getExtraTalentIndex() == 2 && this.getData().getSkillDepot().getSkills().size() >= 2) {
...@@ -670,7 +760,7 @@ public class GenshinAvatar { ...@@ -670,7 +760,7 @@ public class GenshinAvatar {
} }
// Get proud skill group id // Get proud skill group id
AvatarSkillData skillData = GenshinData.getAvatarSkillDataMap().get(skillId); AvatarSkillData skillData = GameData.getAvatarSkillDataMap().get(skillId);
if (skillData == null) { if (skillData == null) {
continue; continue;
...@@ -701,9 +791,14 @@ public class GenshinAvatar { ...@@ -701,9 +791,14 @@ public class GenshinAvatar {
} }
public AvatarInfo toProto() { public AvatarInfo toProto() {
int fetterLevel = this.getFetterLevel();
AvatarFetterInfo.Builder avatarFetter = AvatarFetterInfo.newBuilder() AvatarFetterInfo.Builder avatarFetter = AvatarFetterInfo.newBuilder()
.setExpLevel(10) .setExpLevel(fetterLevel);
.setExpNumber(6325); // Highest Level
if (fetterLevel != 10) {
avatarFetter.setExpNumber(this.getFetterExp());
}
if (this.getFetterList() != null) { if (this.getFetterList() != null) {
for (int i = 0; i < this.getFetterList().size(); i++) { for (int i = 0; i < this.getFetterList().size(); i++) {
...@@ -715,6 +810,12 @@ public class GenshinAvatar { ...@@ -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() AvatarInfo.Builder avatarInfo = AvatarInfo.newBuilder()
.setAvatarId(this.getAvatarId()) .setAvatarId(this.getAvatarId())
.setGuid(this.getGuid()) .setGuid(this.getGuid())
...@@ -725,14 +826,18 @@ public class GenshinAvatar { ...@@ -725,14 +826,18 @@ public class GenshinAvatar {
.setCoreProudSkillLevel(this.getCoreProudSkillLevel()) .setCoreProudSkillLevel(this.getCoreProudSkillLevel())
.putAllSkillLevelMap(this.getSkillLevelMap()) .putAllSkillLevelMap(this.getSkillLevelMap())
.addAllInherentProudSkillList(this.getProudSkillList()) .addAllInherentProudSkillList(this.getProudSkillList())
.putAllProudSkillExtraLevel(getProudSkillBonusMap()) .putAllProudSkillExtraLevelMap(getProudSkillBonusMap())
.setAvatarType(1) .setAvatarType(1)
.setBornTime(this.getBornTime()) .setBornTime(this.getBornTime())
.setFetterInfo(avatarFetter) .setFetterInfo(avatarFetter)
.setWearingFlycloakId(this.getFlyCloak()) .setWearingFlycloakId(this.getFlyCloak())
.setCostumeId(this.getCostume()); .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()); avatarInfo.addEquipGuidList(item.getGuid());
} }
...@@ -744,6 +849,46 @@ public class GenshinAvatar { ...@@ -744,6 +849,46 @@ public class GenshinAvatar {
return avatarInfo.build(); 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 @PostLoad
private void onLoad() { private void onLoad() {
......
package emu.grasscutter.game.avatar; package emu.grasscutter.game.avatar;
import dev.morphia.annotations.Entity;
@Entity
public class AvatarProfileData { public class AvatarProfileData {
private int avatarId; private int avatarId;
private int level; private int level;
public AvatarProfileData(GenshinAvatar avatar) { public AvatarProfileData(Avatar avatar) {
this.update(avatar); this.update(avatar);
} }
...@@ -16,7 +19,7 @@ public class AvatarProfileData { ...@@ -16,7 +19,7 @@ public class AvatarProfileData {
return level; return level;
} }
public void update(GenshinAvatar avatar) { public void update(Avatar avatar) {
this.avatarId = avatar.getAvatarId(); this.avatarId = avatar.getAvatarId();
this.level = avatar.getLevel(); this.level = avatar.getLevel();
} }
......
...@@ -3,12 +3,12 @@ package emu.grasscutter.game.avatar; ...@@ -3,12 +3,12 @@ package emu.grasscutter.game.avatar;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import emu.grasscutter.data.GenshinData; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.AvatarData; import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.entity.EntityAvatar; 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.PacketAvatarChangeCostumeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarFlycloakChangeNotify; import emu.grasscutter.server.packet.send.PacketAvatarFlycloakChangeNotify;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
...@@ -16,22 +16,22 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; ...@@ -16,22 +16,22 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
public class AvatarStorage implements Iterable<GenshinAvatar> { public class AvatarStorage implements Iterable<Avatar> {
private final GenshinPlayer player; private final Player player;
private final Int2ObjectMap<GenshinAvatar> avatars; private final Int2ObjectMap<Avatar> avatars;
private final Long2ObjectMap<GenshinAvatar> avatarsGuid; private final Long2ObjectMap<Avatar> avatarsGuid;
public AvatarStorage(GenshinPlayer player) { public AvatarStorage(Player player) {
this.player = player; this.player = player;
this.avatars = new Int2ObjectOpenHashMap<>(); this.avatars = new Int2ObjectOpenHashMap<>();
this.avatarsGuid = new Long2ObjectOpenHashMap<>(); this.avatarsGuid = new Long2ObjectOpenHashMap<>();
} }
public GenshinPlayer getPlayer() { public Player getPlayer() {
return player; return player;
} }
public Int2ObjectMap<GenshinAvatar> getAvatars() { public Int2ObjectMap<Avatar> getAvatars() {
return avatars; return avatars;
} }
...@@ -39,11 +39,11 @@ public class AvatarStorage implements Iterable<GenshinAvatar> { ...@@ -39,11 +39,11 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
return this.avatars.size(); return this.avatars.size();
} }
public GenshinAvatar getAvatarById(int id) { public Avatar getAvatarById(int id) {
return getAvatars().get(id); return getAvatars().get(id);
} }
public GenshinAvatar getAvatarByGuid(long id) { public Avatar getAvatarByGuid(long id) {
return avatarsGuid.get(id); return avatarsGuid.get(id);
} }
...@@ -51,7 +51,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> { ...@@ -51,7 +51,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
return getAvatars().containsKey(id); return getAvatars().containsKey(id);
} }
public boolean addAvatar(GenshinAvatar avatar) { public boolean addAvatar(Avatar avatar) {
if (avatar.getAvatarData() == null || this.hasAvatar(avatar.getAvatarId())) { if (avatar.getAvatarData() == null || this.hasAvatar(avatar.getAvatarId())) {
return false; return false;
} }
...@@ -68,14 +68,14 @@ public class AvatarStorage implements Iterable<GenshinAvatar> { ...@@ -68,14 +68,14 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
return true; return true;
} }
public void addStartingWeapon(GenshinAvatar avatar) { public void addStartingWeapon(Avatar avatar) {
// Make sure avatar owner is this player // Make sure avatar owner is this player
if (avatar.getPlayer() != this.getPlayer()) { if (avatar.getPlayer() != this.getPlayer()) {
return; return;
} }
// Create weapon // Create weapon
GenshinItem weapon = new GenshinItem(avatar.getAvatarData().getInitialWeapon()); GameItem weapon = new GameItem(avatar.getAvatarData().getInitialWeapon());
if (weapon.getItemData() != null) { if (weapon.getItemData() != null) {
this.getPlayer().getInventory().addItem(weapon); this.getPlayer().getInventory().addItem(weapon);
...@@ -85,7 +85,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> { ...@@ -85,7 +85,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
} }
public boolean wearFlycloak(long avatarGuid, int flycloakId) { public boolean wearFlycloak(long avatarGuid, int flycloakId) {
GenshinAvatar avatar = this.getAvatarByGuid(avatarGuid); Avatar avatar = this.getAvatarByGuid(avatarGuid);
if (avatar == null || !getPlayer().getFlyCloakList().contains(flycloakId)) { if (avatar == null || !getPlayer().getFlyCloakList().contains(flycloakId)) {
return false; return false;
...@@ -101,7 +101,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> { ...@@ -101,7 +101,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
} }
public boolean changeCostume(long avatarGuid, int costumeId) { public boolean changeCostume(long avatarGuid, int costumeId) {
GenshinAvatar avatar = this.getAvatarByGuid(avatarGuid); Avatar avatar = this.getAvatarByGuid(avatarGuid);
if (avatar == null) { if (avatar == null) {
return false; return false;
...@@ -130,15 +130,15 @@ public class AvatarStorage implements Iterable<GenshinAvatar> { ...@@ -130,15 +130,15 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
} }
public void loadFromDatabase() { 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 // Should never happen
if (avatar.getObjectId() == null) { if (avatar.getObjectId() == null) {
continue; continue;
} }
AvatarData avatarData = GenshinData.getAvatarDataMap().get(avatar.getAvatarId()); AvatarData avatarData = GameData.getAvatarDataMap().get(avatar.getAvatarId());
if (avatarData == null) { if (avatarData == null) {
continue; continue;
} }
...@@ -148,7 +148,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> { ...@@ -148,7 +148,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
avatar.setOwner(getPlayer()); avatar.setOwner(getPlayer());
// Force recalc of const boosted skills // Force recalc of const boosted skills
avatar.recalcProudSkillBonusMap(); avatar.recalcConstellations();
// Add to avatar storage // Add to avatar storage
this.avatars.put(avatar.getAvatarId(), avatar); this.avatars.put(avatar.getAvatarId(), avatar);
...@@ -157,7 +157,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> { ...@@ -157,7 +157,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
} }
public void postLoad() { public void postLoad() {
for (GenshinAvatar avatar : this) { for (Avatar avatar : this) {
// Weapon check // Weapon check
if (avatar.getWeapon() == null) { if (avatar.getWeapon() == null) {
this.addStartingWeapon(avatar); this.addStartingWeapon(avatar);
...@@ -168,7 +168,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> { ...@@ -168,7 +168,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
} }
@Override @Override
public Iterator<GenshinAvatar> iterator() { public Iterator<Avatar> iterator() {
return getAvatars().values().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; 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.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 { public class DungeonManager {
private final GameServer server; private final GameServer server;
private static final BasicDungeonSettleListener basicDungeonSettleObserver = new BasicDungeonSettleListener();
public DungeonManager(GameServer server) { public DungeonManager(GameServer server) {
this.server = server; this.server = server;
} }
...@@ -12,4 +26,88 @@ public class DungeonManager { ...@@ -12,4 +26,88 @@ public class DungeonManager {
public GameServer getServer() { public GameServer getServer() {
return server; 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; package emu.grasscutter.game.entity;
import emu.grasscutter.GenshinConstants; import emu.grasscutter.GameConstants;
import emu.grasscutter.data.GenshinData; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.AvatarData; import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.data.def.AvatarSkillDepotData; import emu.grasscutter.data.def.AvatarSkillDepotData;
import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.GenshinScene;
import emu.grasscutter.game.World;
import emu.grasscutter.game.avatar.GenshinAvatar;
import emu.grasscutter.game.inventory.EquipType; 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.EntityIdType;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty; 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.AbilityControlBlockOuterClass.AbilityControlBlock;
import emu.grasscutter.net.proto.AbilityEmbryoOuterClass.AbilityEmbryo; import emu.grasscutter.net.proto.AbilityEmbryoOuterClass.AbilityEmbryo;
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
...@@ -34,29 +34,29 @@ import emu.grasscutter.utils.Utils; ...@@ -34,29 +34,29 @@ import emu.grasscutter.utils.Utils;
import it.unimi.dsi.fastutil.ints.Int2FloatMap; import it.unimi.dsi.fastutil.ints.Int2FloatMap;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public class EntityAvatar extends GenshinEntity { public class EntityAvatar extends GameEntity {
private final GenshinAvatar avatar; private final Avatar avatar;
private PlayerDieType killedType; private PlayerDieType killedType;
private int killedBy; private int killedBy;
public EntityAvatar(GenshinScene scene, GenshinAvatar avatar) { public EntityAvatar(Scene scene, Avatar avatar) {
super(scene); super(scene);
this.avatar = avatar; this.avatar = avatar;
this.id = getScene().getWorld().getNextEntityId(EntityIdType.AVATAR); this.id = getScene().getWorld().getNextEntityId(EntityIdType.AVATAR);
GenshinItem weapon = this.getAvatar().getWeapon(); GameItem weapon = this.getAvatar().getWeapon();
if (weapon != null) { if (weapon != null) {
weapon.setWeaponEntityId(getScene().getWorld().getNextEntityId(EntityIdType.WEAPON)); weapon.setWeaponEntityId(getScene().getWorld().getNextEntityId(EntityIdType.WEAPON));
} }
} }
public EntityAvatar(GenshinAvatar avatar) { public EntityAvatar(Avatar avatar) {
super(null); super(null);
this.avatar = avatar; this.avatar = avatar;
} }
public GenshinPlayer getPlayer() { public Player getPlayer() {
return avatar.getPlayer(); return avatar.getPlayer();
} }
...@@ -70,7 +70,7 @@ public class EntityAvatar extends GenshinEntity { ...@@ -70,7 +70,7 @@ public class EntityAvatar extends GenshinEntity {
return getPlayer().getRotation(); return getPlayer().getRotation();
} }
public GenshinAvatar getAvatar() { public Avatar getAvatar() {
return avatar; return avatar;
} }
...@@ -101,13 +101,18 @@ public class EntityAvatar extends GenshinEntity { ...@@ -101,13 +101,18 @@ public class EntityAvatar extends GenshinEntity {
@Override @Override
public void onDeath(int killerId) { 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; this.killedBy = killerId;
} }
public SceneAvatarInfo getSceneAvatarInfo() { public SceneAvatarInfo getSceneAvatarInfo() {
SceneAvatarInfo.Builder avatarInfo = SceneAvatarInfo.newBuilder() SceneAvatarInfo.Builder avatarInfo = SceneAvatarInfo.newBuilder()
.setPlayerId(this.getPlayer().getUid()) .setUid(this.getPlayer().getUid())
.setAvatarId(this.getAvatar().getAvatarId()) .setAvatarId(this.getAvatar().getAvatarId())
.setGuid(this.getAvatar().getGuid()) .setGuid(this.getAvatar().getGuid())
.setPeerId(this.getPlayer().getPeerId()) .setPeerId(this.getPlayer().getPeerId())
...@@ -122,7 +127,7 @@ public class EntityAvatar extends GenshinEntity { ...@@ -122,7 +127,7 @@ public class EntityAvatar extends GenshinEntity {
.setCostumeId(this.getAvatar().getCostume()) .setCostumeId(this.getAvatar().getCostume())
.setBornTime(this.getAvatar().getBornTime()); .setBornTime(this.getAvatar().getBornTime());
for (GenshinItem item : avatar.getEquips().values()) { for (GameItem item : avatar.getEquips().values()) {
if (item.getItemData().getEquipType() == EquipType.EQUIP_WEAPON) { if (item.getItemData().getEquipType() == EquipType.EQUIP_WEAPON) {
avatarInfo.setWeapon(item.createSceneWeaponInfo()); avatarInfo.setWeapon(item.createSceneWeaponInfo());
} else { } else {
...@@ -145,7 +150,7 @@ public class EntityAvatar extends GenshinEntity { ...@@ -145,7 +150,7 @@ public class EntityAvatar extends GenshinEntity {
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId()) .setEntityId(getId())
.setEntityType(ProtEntityType.ProtEntityAvatar) .setEntityType(ProtEntityType.PROT_ENTITY_AVATAR)
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder()) .setEntityClientData(EntityClientData.newBuilder())
.setEntityAuthorityInfo(authority) .setEntityAuthorityInfo(authority)
...@@ -161,7 +166,7 @@ public class EntityAvatar extends GenshinEntity { ...@@ -161,7 +166,7 @@ public class EntityAvatar extends GenshinEntity {
if (entry.getIntKey() == 0) { if (entry.getIntKey() == 0) {
continue; 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); entityInfo.addFightPropList(fightProp);
} }
...@@ -187,17 +192,17 @@ public class EntityAvatar extends GenshinEntity { ...@@ -187,17 +192,17 @@ public class EntityAvatar extends GenshinEntity {
AbilityEmbryo emb = AbilityEmbryo.newBuilder() AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId) .setAbilityId(++embryoId)
.setAbilityNameHash(id) .setAbilityNameHash(id)
.setAbilityOverrideNameHash(GenshinConstants.DEFAULT_ABILITY_NAME) .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
.build(); .build();
abilityControlBlock.addAbilityEmbryoList(emb); abilityControlBlock.addAbilityEmbryoList(emb);
} }
} }
// Add default abilities // Add default abilities
for (int id : GenshinConstants.DEFAULT_ABILITY_HASHES) { for (int id : GameConstants.DEFAULT_ABILITY_HASHES) {
AbilityEmbryo emb = AbilityEmbryo.newBuilder() AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId) .setAbilityId(++embryoId)
.setAbilityNameHash(id) .setAbilityNameHash(id)
.setAbilityOverrideNameHash(GenshinConstants.DEFAULT_ABILITY_NAME) .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
.build(); .build();
abilityControlBlock.addAbilityEmbryoList(emb); abilityControlBlock.addAbilityEmbryoList(emb);
} }
...@@ -206,18 +211,18 @@ public class EntityAvatar extends GenshinEntity { ...@@ -206,18 +211,18 @@ public class EntityAvatar extends GenshinEntity {
AbilityEmbryo emb = AbilityEmbryo.newBuilder() AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId) .setAbilityId(++embryoId)
.setAbilityNameHash(id) .setAbilityNameHash(id)
.setAbilityOverrideNameHash(GenshinConstants.DEFAULT_ABILITY_NAME) .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
.build(); .build();
abilityControlBlock.addAbilityEmbryoList(emb); abilityControlBlock.addAbilityEmbryoList(emb);
} }
// Add skill depot abilities // 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) { if (skillDepot != null && skillDepot.getAbilities() != null) {
for (int id : skillDepot.getAbilities()) { for (int id : skillDepot.getAbilities()) {
AbilityEmbryo emb = AbilityEmbryo.newBuilder() AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId) .setAbilityId(++embryoId)
.setAbilityNameHash(id) .setAbilityNameHash(id)
.setAbilityOverrideNameHash(GenshinConstants.DEFAULT_ABILITY_NAME) .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
.build(); .build();
abilityControlBlock.addAbilityEmbryoList(emb); abilityControlBlock.addAbilityEmbryoList(emb);
} }
...@@ -228,7 +233,7 @@ public class EntityAvatar extends GenshinEntity { ...@@ -228,7 +233,7 @@ public class EntityAvatar extends GenshinEntity {
AbilityEmbryo emb = AbilityEmbryo.newBuilder() AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId) .setAbilityId(++embryoId)
.setAbilityNameHash(Utils.abilityHash(skill)) .setAbilityNameHash(Utils.abilityHash(skill))
.setAbilityOverrideNameHash(GenshinConstants.DEFAULT_ABILITY_NAME) .setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
.build(); .build();
abilityControlBlock.addAbilityEmbryoList(emb); 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; package emu.grasscutter.game.entity;
import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.GenshinScene;
import emu.grasscutter.game.World;
import emu.grasscutter.game.props.PlayerProperty; 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.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; 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.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData; import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
...@@ -22,8 +23,8 @@ import emu.grasscutter.utils.Position; ...@@ -22,8 +23,8 @@ import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper; import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public class EntityClientGadget extends EntityGadget { public class EntityClientGadget extends EntityBaseGadget {
private final GenshinPlayer owner; private final Player owner;
private final Position pos; private final Position pos;
private final Position rot; private final Position rot;
...@@ -35,7 +36,7 @@ public class EntityClientGadget extends EntityGadget { ...@@ -35,7 +36,7 @@ public class EntityClientGadget extends EntityGadget {
private int targetEntityId; private int targetEntityId;
private boolean asyncLoad; private boolean asyncLoad;
public EntityClientGadget(GenshinScene scene, GenshinPlayer player, EvtCreateGadgetNotify notify) { public EntityClientGadget(Scene scene, Player player, EvtCreateGadgetNotify notify) {
super(scene); super(scene);
this.owner = player; this.owner = player;
this.id = notify.getEntityId(); this.id = notify.getEntityId();
...@@ -54,7 +55,7 @@ public class EntityClientGadget extends EntityGadget { ...@@ -54,7 +55,7 @@ public class EntityClientGadget extends EntityGadget {
return configId; return configId;
} }
public GenshinPlayer getOwner() { public Player getOwner() {
return owner; return owner;
} }
...@@ -112,7 +113,7 @@ public class EntityClientGadget extends EntityGadget { ...@@ -112,7 +113,7 @@ public class EntityClientGadget extends EntityGadget {
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId()) .setEntityId(getId())
.setEntityType(ProtEntityType.ProtEntityGadget) .setEntityType(ProtEntityType.PROT_ENTITY_GADGET)
.setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder())) .setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder()))
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder()) .setEntityClientData(EntityClientData.newBuilder())
...@@ -125,7 +126,7 @@ public class EntityClientGadget extends EntityGadget { ...@@ -125,7 +126,7 @@ public class EntityClientGadget extends EntityGadget {
.build(); .build();
entityInfo.addPropList(pair); entityInfo.addPropList(pair);
GadgetClientParam clientGadget = GadgetClientParam.newBuilder() ClientGadgetInfoOuterClass.ClientGadgetInfo clientGadget = ClientGadgetInfoOuterClass.ClientGadgetInfo.newBuilder()
.setCampId(this.getCampId()) .setCampId(this.getCampId())
.setCampType(this.getCampType()) .setCampType(this.getCampType())
.setOwnerEntityId(this.getOwnerEntityId()) .setOwnerEntityId(this.getOwnerEntityId())
......
package emu.grasscutter.game.entity; package emu.grasscutter.game.entity;
import emu.grasscutter.game.GenshinScene; import java.util.Arrays;
import emu.grasscutter.game.World; 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); 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 abstract int getGadgetId(); 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);
}
@Override
public Int2FloatOpenHashMap getFightProperties() {
// TODO Auto-generated method stub
return null;
}
@Override @Override
public void onDeath(int killerId) { 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; package emu.grasscutter.game.entity;
import emu.grasscutter.data.def.ItemData; import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.GenshinScene; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.World;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.props.EntityIdType; import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
...@@ -24,20 +23,36 @@ import emu.grasscutter.utils.Position; ...@@ -24,20 +23,36 @@ import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper; import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public class EntityItem extends EntityGadget { public class EntityItem extends EntityBaseGadget {
private final Position pos; private final Position pos;
private final Position rot; private final Position rot;
private final GenshinItem item; private final GameItem item;
private final long guid; 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); super(scene);
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET); this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
this.pos = new Position(pos); this.pos = new Position(pos);
this.rot = new Position(); this.rot = new Position();
this.guid = player.getNextGenshinGuid(); this.guid = player == null ? scene.getWorld().getHost().getNextGameGuid() : player.getNextGameGuid();
this.item = new GenshinItem(itemData, count); 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 @Override
...@@ -45,7 +60,7 @@ public class EntityItem extends EntityGadget { ...@@ -45,7 +60,7 @@ public class EntityItem extends EntityGadget {
return this.id; return this.id;
} }
private GenshinItem getItem() { private GameItem getItem() {
return this.item; return this.item;
} }
...@@ -81,6 +96,10 @@ public class EntityItem extends EntityGadget { ...@@ -81,6 +96,10 @@ public class EntityItem extends EntityGadget {
return null; return null;
} }
public boolean isShare() {
return share;
}
@Override @Override
public SceneEntityInfo toProto() { public SceneEntityInfo toProto() {
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder() EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder()
...@@ -92,7 +111,7 @@ public class EntityItem extends EntityGadget { ...@@ -92,7 +111,7 @@ public class EntityItem extends EntityGadget {
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId()) .setEntityId(getId())
.setEntityType(ProtEntityType.ProtEntityGadget) .setEntityType(ProtEntityType.PROT_ENTITY_GADGET)
.setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder())) .setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder()))
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder()) .setEntityClientData(EntityClientData.newBuilder())
...@@ -108,7 +127,7 @@ public class EntityItem extends EntityGadget { ...@@ -108,7 +127,7 @@ public class EntityItem extends EntityGadget {
SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder() SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder()
.setGadgetId(this.getItemData().getGadgetId()) .setGadgetId(this.getItemData().getGadgetId())
.setTrifleItem(this.getItem().toProto()) .setTrifleItem(this.getItem().toProto())
.setBornType(GadgetBornType.GadgetBornInAir) .setBornType(GadgetBornType.GADGET_BORN_IN_AIR)
.setAuthorityPeerId(this.getWorld().getHostPeerId()) .setAuthorityPeerId(this.getWorld().getHostPeerId())
.setIsEnableInteract(true); .setIsEnableInteract(true);
......
package emu.grasscutter.game.entity; 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.common.PropGrowCurve;
import emu.grasscutter.data.def.MonsterCurveData; import emu.grasscutter.data.def.MonsterCurveData;
import emu.grasscutter.data.def.MonsterData; import emu.grasscutter.data.def.MonsterData;
import emu.grasscutter.game.GenshinScene; import emu.grasscutter.game.dungeons.DungeonChallenge;
import emu.grasscutter.game.World;
import emu.grasscutter.game.props.EntityIdType; import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty; 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.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
...@@ -22,12 +23,13 @@ import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; ...@@ -22,12 +23,13 @@ import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo;
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.grasscutter.net.proto.SceneMonsterInfoOuterClass.SceneMonsterInfo; import emu.grasscutter.net.proto.SceneMonsterInfoOuterClass.SceneMonsterInfo;
import emu.grasscutter.net.proto.SceneWeaponInfoOuterClass.SceneWeaponInfo; import emu.grasscutter.net.proto.SceneWeaponInfoOuterClass.SceneWeaponInfo;
import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper; import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatMap; import it.unimi.dsi.fastutil.ints.Int2FloatMap;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public class EntityMonster extends GenshinEntity { public class EntityMonster extends GameEntity {
private final MonsterData monsterData; private final MonsterData monsterData;
private final Int2FloatOpenHashMap fightProp; private final Int2FloatOpenHashMap fightProp;
...@@ -36,8 +38,9 @@ public class EntityMonster extends GenshinEntity { ...@@ -36,8 +38,9 @@ public class EntityMonster extends GenshinEntity {
private final Position bornPos; private final Position bornPos;
private final int level; private final int level;
private int weaponEntityId; 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); super(scene);
this.id = getWorld().getNextEntityId(EntityIdType.MONSTER); this.id = getWorld().getNextEntityId(EntityIdType.MONSTER);
this.monsterData = monsterData; this.monsterData = monsterData;
...@@ -99,10 +102,26 @@ public class EntityMonster extends GenshinEntity { ...@@ -99,10 +102,26 @@ public class EntityMonster extends GenshinEntity {
public boolean isAlive() { public boolean isAlive() {
return this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0f; return this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0f;
} }
public int getPoseId() {
return poseId;
}
public void setPoseId(int poseId) {
this.poseId = poseId;
}
@Override @Override
public void onDeath(int killerId) { 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() { public void recalcStats() {
...@@ -130,7 +149,7 @@ public class EntityMonster extends GenshinEntity { ...@@ -130,7 +149,7 @@ public class EntityMonster extends GenshinEntity {
this.setFightProperty(FightProperty.FIGHT_PROP_ICE_SUB_HURT, data.getIceSubHurt()); this.setFightProperty(FightProperty.FIGHT_PROP_ICE_SUB_HURT, data.getIceSubHurt());
// Level curve // Level curve
MonsterCurveData curve = GenshinData.getMonsterCurveDataMap().get(this.getLevel()); MonsterCurveData curve = GameData.getMonsterCurveDataMap().get(this.getLevel());
if (curve != null) { if (curve != null) {
for (PropGrowCurve growCurve : data.getPropGrowCurves()) { for (PropGrowCurve growCurve : data.getPropGrowCurves()) {
FightProperty prop = FightProperty.getPropByName(growCurve.getType()); FightProperty prop = FightProperty.getPropByName(growCurve.getType());
...@@ -167,7 +186,7 @@ public class EntityMonster extends GenshinEntity { ...@@ -167,7 +186,7 @@ public class EntityMonster extends GenshinEntity {
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId()) .setEntityId(getId())
.setEntityType(ProtEntityType.ProtEntityMonster) .setEntityType(ProtEntityType.PROT_ENTITY_MONSTER)
.setMotionInfo(this.getMotionInfo()) .setMotionInfo(this.getMotionInfo())
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder()) .setEntityClientData(EntityClientData.newBuilder())
...@@ -178,7 +197,7 @@ public class EntityMonster extends GenshinEntity { ...@@ -178,7 +197,7 @@ public class EntityMonster extends GenshinEntity {
if (entry.getIntKey() == 0) { if (entry.getIntKey() == 0) {
continue; 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); entityInfo.addFightPropList(fightProp);
} }
...@@ -190,13 +209,13 @@ public class EntityMonster extends GenshinEntity { ...@@ -190,13 +209,13 @@ public class EntityMonster extends GenshinEntity {
SceneMonsterInfo.Builder monsterInfo = SceneMonsterInfo.newBuilder() SceneMonsterInfo.Builder monsterInfo = SceneMonsterInfo.newBuilder()
.setMonsterId(getMonsterId()) .setMonsterId(getMonsterId())
.setGroupId(133003095) .setGroupId(this.getGroupId())
.setConfigId(95001) .setConfigId(this.getConfigId())
.addAllAffixList(getMonsterData().getAffix()) .addAllAffixList(getMonsterData().getAffix())
.setAuthorityPeerId(getWorld().getHostPeerId()) .setAuthorityPeerId(getWorld().getHostPeerId())
.setPoseId(0) .setPoseId(this.getPoseId())
.setBlockId(3001) .setBlockId(3001)
.setBornType(MonsterBornType.MonsterBornDefault) .setBornType(MonsterBornType.MONSTER_BORN_DEFAULT)
.setSpecialNameId(40); .setSpecialNameId(40);
if (getMonsterData().getDescribeData() != null) { if (getMonsterData().getDescribeData() != null) {
...@@ -210,7 +229,7 @@ public class EntityMonster extends GenshinEntity { ...@@ -210,7 +229,7 @@ public class EntityMonster extends GenshinEntity {
.setAbilityInfo(AbilitySyncStateInfo.newBuilder()) .setAbilityInfo(AbilitySyncStateInfo.newBuilder())
.build(); .build();
monsterInfo.setWeaponList(weaponInfo); monsterInfo.addWeaponList(weaponInfo);
} }
entityInfo.setMonster(monsterInfo); 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