Initial commit

This commit is contained in:
Melledy
2022-04-17 05:43:07 -07:00
commit 7925d1cda3
354 changed files with 20869 additions and 0 deletions

View File

@@ -0,0 +1,239 @@
package emu.grasscutter.game.entity;
import emu.grasscutter.GenshinConstants;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.data.def.AvatarSkillDepotData;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.World;
import emu.grasscutter.game.avatar.GenshinAvatar;
import emu.grasscutter.game.inventory.EquipType;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.net.proto.AbilityControlBlockOuterClass.AbilityControlBlock;
import emu.grasscutter.net.proto.AbilityEmbryoOuterClass.AbilityEmbryo;
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.FightPropPairOuterClass.FightPropPair;
import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType;
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
import emu.grasscutter.net.proto.SceneAvatarInfoOuterClass.SceneAvatarInfo;
import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo;
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper;
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;
private PlayerDieType killedType;
private int killedBy;
public EntityAvatar(World world, GenshinAvatar avatar) {
super(world);
this.avatar = avatar;
this.id = world.getNextEntityId(EntityIdType.AVATAR);
GenshinItem weapon = this.getAvatar().getWeapon();
if (weapon != null) {
weapon.setWeaponEntityId(world.getNextEntityId(EntityIdType.WEAPON));
}
}
public EntityAvatar(GenshinAvatar avatar) {
super(null);
this.avatar = avatar;
}
public GenshinPlayer getPlayer() {
return avatar.getPlayer();
}
@Override
public Position getPosition() {
return getPlayer().getPos();
}
@Override
public Position getRotation() {
return getPlayer().getRotation();
}
public GenshinAvatar getAvatar() {
return avatar;
}
public int getKilledBy() {
return killedBy;
}
public PlayerDieType getKilledType() {
return killedType;
}
@Override
public boolean isAlive() {
return this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0f;
}
@Override
public Int2FloatOpenHashMap getFightProperties() {
return getAvatar().getFightProperties();
}
public int getWeaponEntityId() {
if (getAvatar().getWeapon() != null) {
return getAvatar().getWeapon().getWeaponEntityId();
}
return 0;
}
@Override
public void onDeath(int killerId) {
this.killedType = PlayerDieType.PlayerDieKillByMonster;
this.killedBy = killerId;
}
public SceneAvatarInfo getSceneAvatarInfo() {
SceneAvatarInfo.Builder avatarInfo = SceneAvatarInfo.newBuilder()
.setPlayerId(this.getPlayer().getId())
.setAvatarId(this.getAvatar().getAvatarId())
.setGuid(this.getAvatar().getGuid())
.setPeerId(this.getPlayer().getPeerId())
.addAllTalentIdList(this.getAvatar().getTalentIdList())
.setCoreProudSkillLevel(this.getAvatar().getCoreProudSkillLevel())
.putAllSkillLevelMap(this.getAvatar().getSkillLevelMap())
.setSkillDepotId(this.getAvatar().getSkillDepotId())
.addAllInherentProudSkillList(this.getAvatar().getProudSkillList())
.putAllProudSkillExtraLevelMap(this.getAvatar().getProudSkillBonusMap())
.addAllTeamResonanceList(this.getAvatar().getPlayer().getTeamManager().getTeamResonances())
.setWearingFlycloakId(this.getAvatar().getFlyCloak())
.setCostumeId(this.getAvatar().getCostume())
.setBornTime(this.getAvatar().getBornTime());
for (GenshinItem item : avatar.getEquips().values()) {
if (item.getItemData().getEquipType() == EquipType.EQUIP_WEAPON) {
avatarInfo.setWeapon(item.createSceneWeaponInfo());
} else {
avatarInfo.addReliquaryList(item.createSceneReliquaryInfo());
}
avatarInfo.addEquipIdList(item.getItemId());
}
return avatarInfo.build();
}
@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.ProtEntityAvatar)
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder())
.setEntityAuthorityInfo(authority)
.setLastMoveSceneTimeMs(this.getLastMoveSceneTimeMs())
.setLastMoveReliableSeq(this.getLastMoveReliableSeq())
.setLifeState(this.getLifeState().getValue());
if (this.getWorld() != null) {
entityInfo.setMotionInfo(this.getMotionInfo());
}
for (Int2FloatMap.Entry entry : getFightProperties().int2FloatEntrySet()) {
if (entry.getIntKey() == 0) {
continue;
}
FightPropPair fightProp = FightPropPair.newBuilder().setType(entry.getIntKey()).setPropValue(entry.getFloatValue()).build();
entityInfo.addFightPropList(fightProp);
}
PropPair pair = PropPair.newBuilder()
.setType(PlayerProperty.PROP_LEVEL.getId())
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, getAvatar().getLevel()))
.build();
entityInfo.addPropList(pair);
entityInfo.setAvatar(this.getSceneAvatarInfo());
return entityInfo.build();
}
public AbilityControlBlock getAbilityControlBlock() {
AvatarData data = this.getAvatar().getAvatarData();
AbilityControlBlock.Builder abilityControlBlock = AbilityControlBlock.newBuilder();
int embryoId = 0;
// Add avatar abilities
if (data.getAbilities() != null) {
for (int id : data.getAbilities()) {
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId)
.setAbilityNameHash(id)
.setAbilityOverrideNameHash(GenshinConstants.DEFAULT_ABILITY_NAME)
.build();
abilityControlBlock.addAbilityEmbryoList(emb);
}
}
// Add default abilities
for (int id : GenshinConstants.DEFAULT_ABILITY_HASHES) {
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId)
.setAbilityNameHash(id)
.setAbilityOverrideNameHash(GenshinConstants.DEFAULT_ABILITY_NAME)
.build();
abilityControlBlock.addAbilityEmbryoList(emb);
}
// Add team resonances
for (int id : this.getPlayer().getTeamManager().getTeamResonancesConfig()) {
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId)
.setAbilityNameHash(id)
.setAbilityOverrideNameHash(GenshinConstants.DEFAULT_ABILITY_NAME)
.build();
abilityControlBlock.addAbilityEmbryoList(emb);
}
// Add skill depot abilities
AvatarSkillDepotData skillDepot = GenshinData.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)
.build();
abilityControlBlock.addAbilityEmbryoList(emb);
}
}
// Add equip abilities
if (this.getAvatar().getBonusAbilityList().size() > 0) {
for (String skill : this.getAvatar().getBonusAbilityList()) {
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId)
.setAbilityNameHash(Utils.abilityHash(skill))
.setAbilityOverrideNameHash(GenshinConstants.DEFAULT_ABILITY_NAME)
.build();
abilityControlBlock.addAbilityEmbryoList(emb);
}
}
//
return abilityControlBlock.build();
}
}

View File

@@ -0,0 +1,147 @@
package emu.grasscutter.game.entity;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.World;
import emu.grasscutter.game.props.PlayerProperty;
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.EvtCreateGadgetNotifyOuterClass.EvtCreateGadgetNotify;
import emu.grasscutter.net.proto.GadgetClientParamOuterClass.GadgetClientParam;
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.utils.Position;
import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public class EntityClientGadget extends EntityGadget {
private final GenshinPlayer owner;
private final Position pos;
private final Position rot;
private int configId;
private int campId;
private int campType;
private int ownerEntityId;
private int targetEntityId;
private boolean asyncLoad;
public EntityClientGadget(World world, GenshinPlayer player, EvtCreateGadgetNotify notify) {
super(world);
this.owner = player;
this.id = notify.getEntityId();
this.pos = new Position(notify.getInitPos());
this.rot = new Position(notify.getInitEulerAngles());
this.configId = notify.getConfigId();
this.campId = notify.getCampId();
this.campType = notify.getCampType();
this.ownerEntityId = notify.getPropOwnerEntityId();
this.targetEntityId = notify.getTargetEntityId();
this.asyncLoad = notify.getIsAsyncLoad();
}
@Override
public int getGadgetId() {
return configId;
}
public GenshinPlayer getOwner() {
return owner;
}
public int getCampId() {
return campId;
}
public int getCampType() {
return campType;
}
public int getOwnerEntityId() {
return ownerEntityId;
}
public int getTargetEntityId() {
return targetEntityId;
}
public boolean isAsyncLoad() {
return this.asyncLoad;
}
@Override
public void onDeath(int killerId) {
}
@Override
public Int2FloatOpenHashMap getFightProperties() {
// TODO Auto-generated method stub
return null;
}
@Override
public Position getPosition() {
// TODO Auto-generated method stub
return this.pos;
}
@Override
public Position getRotation() {
// TODO Auto-generated method stub
return this.rot;
}
@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.ProtEntityGadget)
.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);
GadgetClientParam clientGadget = GadgetClientParam.newBuilder()
.setCampId(this.getCampId())
.setCampType(this.getCampType())
.setOwnerEntityId(this.getOwnerEntityId())
.setTargetEntityId(this.getTargetEntityId())
.setAsyncLoad(this.isAsyncLoad())
.build();
SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder()
.setGadgetId(this.getGadgetId())
.setOwnerEntityId(this.getOwnerEntityId())
.setIsEnableInteract(true)
.setClientGadget(clientGadget)
.setPropOwnerEntityId(this.getOwnerEntityId())
.setAuthorityPeerId(this.getOwner().getPeerId());
entityInfo.setGadget(gadgetInfo);
return entityInfo.build();
}
}

View File

@@ -0,0 +1,17 @@
package emu.grasscutter.game.entity;
import emu.grasscutter.game.World;
public abstract class EntityGadget extends GenshinEntity {
public EntityGadget(World world) {
super(world);
}
public abstract int getGadgetId();
@Override
public void onDeath(int killerId) {
}
}

View File

@@ -0,0 +1,118 @@
package emu.grasscutter.game.entity;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.World;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.PlayerProperty;
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.GadgetBornTypeOuterClass.GadgetBornType;
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.utils.Position;
import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public class EntityItem extends EntityGadget {
private final Position pos;
private final Position rot;
private final GenshinItem item;
private final long guid;
public EntityItem(World world, GenshinPlayer player, ItemData itemData, Position pos, int count) {
super(world);
this.id = world.getNextEntityId(EntityIdType.GADGET);
this.pos = new Position(pos);
this.rot = new Position();
this.guid = player.getNextGuid();
this.item = new GenshinItem(itemData, count);
}
@Override
public int getId() {
return this.id;
}
private GenshinItem getItem() {
return this.item;
}
public ItemData getItemData() {
return this.getItem().getItemData();
}
public long getGuid() {
return guid;
}
public int getCount() {
return this.getItem().getCount();
}
@Override
public int getGadgetId() {
return this.getItemData().getGadgetId();
}
@Override
public Position getPosition() {
return this.pos;
}
@Override
public Position getRotation() {
return this.rot;
}
@Override
public Int2FloatOpenHashMap getFightProperties() {
return null;
}
@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.ProtEntityGadget)
.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.getItemData().getGadgetId())
.setTrifleItem(this.getItem().toProto())
.setBornType(GadgetBornType.GadgetBornInAir)
.setAuthorityPeerId(this.getWorld().getHostPeerId())
.setIsEnableInteract(true);
entityInfo.setGadget(gadgetInfo);
return entityInfo.build();
}
}

View File

@@ -0,0 +1,219 @@
package emu.grasscutter.game.entity;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.common.PropGrowCurve;
import emu.grasscutter.data.def.MonsterCurveData;
import emu.grasscutter.data.def.MonsterData;
import emu.grasscutter.game.World;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty;
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.FightPropPairOuterClass.FightPropPair;
import emu.grasscutter.net.proto.MonsterBornTypeOuterClass.MonsterBornType;
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.SceneMonsterInfoOuterClass.SceneMonsterInfo;
import emu.grasscutter.net.proto.SceneWeaponInfoOuterClass.SceneWeaponInfo;
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 {
private final MonsterData monsterData;
private final Int2FloatOpenHashMap fightProp;
private final Position pos;
private final Position rot;
private final Position bornPos;
private final int level;
private int weaponEntityId;
public EntityMonster(World world, MonsterData monsterData, Position pos, int level) {
super(world);
this.id = world.getNextEntityId(EntityIdType.MONSTER);
this.monsterData = monsterData;
this.fightProp = new Int2FloatOpenHashMap();
this.pos = new Position(pos);
this.rot = new Position();
this.bornPos = getPosition().clone();
this.level = level;
// Monster weapon
if (getMonsterWeaponId() > 0) {
this.weaponEntityId = world.getNextEntityId(EntityIdType.WEAPON);
}
this.recalcStats();
}
@Override
public int getId() {
return this.id;
}
public MonsterData getMonsterData() {
return monsterData;
}
public int getMonsterWeaponId() {
return getMonsterData().getWeaponId();
}
private int getMonsterId() {
return this.getMonsterData().getId();
}
public int getLevel() {
return level;
}
@Override
public Position getPosition() {
return this.pos;
}
@Override
public Position getRotation() {
return this.rot;
}
public Position getBornPos() {
return bornPos;
}
@Override
public Int2FloatOpenHashMap getFightProperties() {
return fightProp;
}
@Override
public boolean isAlive() {
return this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0f;
}
@Override
public void onDeath(int killerId) {
}
public void recalcStats() {
// Monster data
MonsterData data = this.getMonsterData();
// 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);
// Clear properties
this.getFightProperties().clear();
// Base stats
this.setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, data.getBaseHp());
this.setFightProperty(FightProperty.FIGHT_PROP_BASE_ATTACK, data.getBaseAttack());
this.setFightProperty(FightProperty.FIGHT_PROP_BASE_DEFENSE, data.getBaseDefense());
this.setFightProperty(FightProperty.FIGHT_PROP_PHYSICAL_SUB_HURT, data.getPhysicalSubHurt());
this.setFightProperty(FightProperty.FIGHT_PROP_FIRE_SUB_HURT, .1f);
this.setFightProperty(FightProperty.FIGHT_PROP_ELEC_SUB_HURT, data.getElecSubHurt());
this.setFightProperty(FightProperty.FIGHT_PROP_WATER_SUB_HURT, data.getWaterSubHurt());
this.setFightProperty(FightProperty.FIGHT_PROP_GRASS_SUB_HURT, data.getGrassSubHurt());
this.setFightProperty(FightProperty.FIGHT_PROP_WIND_SUB_HURT, data.getWindSubHurt());
this.setFightProperty(FightProperty.FIGHT_PROP_ROCK_SUB_HURT, .1f);
this.setFightProperty(FightProperty.FIGHT_PROP_ICE_SUB_HURT, data.getIceSubHurt());
// Level curve
MonsterCurveData curve = GenshinData.getMonsterCurveDataMap().get(this.getLevel());
if (curve != null) {
for (PropGrowCurve growCurve : data.getPropGrowCurves()) {
FightProperty prop = FightProperty.getPropByName(growCurve.getType());
this.setFightProperty(prop, this.getFightProperty(prop) * curve.getMultByProp(growCurve.getGrowCurve()));
}
}
// Set % stats
this.setFightProperty(
FightProperty.FIGHT_PROP_MAX_HP,
(getFightProperty(FightProperty.FIGHT_PROP_BASE_HP) * (1f + getFightProperty(FightProperty.FIGHT_PROP_HP_PERCENT))) + getFightProperty(FightProperty.FIGHT_PROP_HP)
);
this.setFightProperty(
FightProperty.FIGHT_PROP_CUR_ATTACK,
(getFightProperty(FightProperty.FIGHT_PROP_BASE_ATTACK) * (1f + getFightProperty(FightProperty.FIGHT_PROP_ATTACK_PERCENT))) + getFightProperty(FightProperty.FIGHT_PROP_ATTACK)
);
this.setFightProperty(
FightProperty.FIGHT_PROP_CUR_DEFENSE,
(getFightProperty(FightProperty.FIGHT_PROP_BASE_DEFENSE) * (1f + getFightProperty(FightProperty.FIGHT_PROP_DEFENSE_PERCENT))) + getFightProperty(FightProperty.FIGHT_PROP_DEFENSE)
);
// Set current hp
this.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * hpPercent);
}
@Override
public SceneEntityInfo toProto() {
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder()
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
.setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(this.getBornPos().toProto()))
.setBornPos(this.getBornPos().toProto())
.build();
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId())
.setEntityType(ProtEntityType.ProtEntityMonster)
.setMotionInfo(this.getMotionInfo())
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder())
.setEntityAuthorityInfo(authority)
.setLifeState(this.getLifeState().getValue());
for (Int2FloatMap.Entry entry : getFightProperties().int2FloatEntrySet()) {
if (entry.getIntKey() == 0) {
continue;
}
FightPropPair fightProp = FightPropPair.newBuilder().setType(entry.getIntKey()).setPropValue(entry.getFloatValue()).build();
entityInfo.addFightPropList(fightProp);
}
PropPair pair = PropPair.newBuilder()
.setType(PlayerProperty.PROP_LEVEL.getId())
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, getLevel()))
.build();
entityInfo.addPropList(pair);
SceneMonsterInfo.Builder monsterInfo = SceneMonsterInfo.newBuilder()
.setMonsterId(getMonsterId())
.setGroupId(133003095)
.setConfigId(95001)
.addAllAffixList(getMonsterData().getAffix())
.setAuthorityPeerId(getWorld().getHostPeerId())
.setPoseId(0)
.setBlockId(3001)
.setBornType(MonsterBornType.MonsterBornDefault)
.setSpecialNameId(40);
if (getMonsterData().getDescribeData() != null) {
monsterInfo.setTitleId(getMonsterData().getDescribeData().getTitleID());
}
if (this.getMonsterWeaponId() > 0) {
SceneWeaponInfo weaponInfo = SceneWeaponInfo.newBuilder()
.setEntityId(this.weaponEntityId)
.setGadgetId(this.getMonsterWeaponId())
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
.build();
monsterInfo.setWeaponList(weaponInfo);
}
entityInfo.setMonster(monsterInfo);
return entityInfo.build();
}
}

View File

@@ -0,0 +1,102 @@
package emu.grasscutter.game.entity;
import emu.grasscutter.game.World;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.LifeState;
import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
import emu.grasscutter.utils.Position;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public abstract class GenshinEntity {
protected int id;
private final World world;
private MotionState moveState;
private int lastMoveSceneTimeMs;
private int lastMoveReliableSeq;
public GenshinEntity(World world) {
this.world = world;
this.moveState = MotionState.MotionNone;
}
public int getId() {
return this.id;
}
public World getWorld() {
return world;
}
public boolean isAlive() {
return true;
}
public LifeState getLifeState() {
return isAlive() ? LifeState.LIFE_ALIVE : LifeState.LIFE_DEAD;
}
public abstract Int2FloatOpenHashMap getFightProperties();
public abstract Position getPosition();
public abstract Position getRotation();
public MotionState getMotionState() {
return moveState;
}
public void setMotionState(MotionState moveState) {
this.moveState = moveState;
}
public int getLastMoveSceneTimeMs() {
return lastMoveSceneTimeMs;
}
public void setLastMoveSceneTimeMs(int lastMoveSceneTimeMs) {
this.lastMoveSceneTimeMs = lastMoveSceneTimeMs;
}
public int getLastMoveReliableSeq() {
return lastMoveReliableSeq;
}
public void setLastMoveReliableSeq(int lastMoveReliableSeq) {
this.lastMoveReliableSeq = lastMoveReliableSeq;
}
public abstract SceneEntityInfo toProto();
public abstract void onDeath(int killerId);
public void setFightProperty(FightProperty prop, float value) {
this.getFightProperties().put(prop.getId(), value);
}
private void setFightProperty(int id, float value) {
this.getFightProperties().put(id, value);
}
public void addFightProperty(FightProperty prop, float value) {
this.getFightProperties().put(prop.getId(), getFightProperty(prop) + value);
}
public float getFightProperty(FightProperty prop) {
return getFightProperties().getOrDefault(prop.getId(), 0f);
}
protected MotionInfo getMotionInfo() {
MotionInfo proto = MotionInfo.newBuilder()
.setPos(getPosition().toProto())
.setRot(getRotation().toProto())
.setSpeed(Vector.newBuilder())
.setState(this.getMotionState())
.build();
return proto;
}
}