EntityAvatar.java 12.4 KB
Newer Older
Melledy's avatar
Melledy committed
1
2
package emu.grasscutter.game.entity;

3
4
import emu.grasscutter.GameConstants;
import emu.grasscutter.data.GameData;
Melledy's avatar
Melledy committed
5
6
import emu.grasscutter.data.excels.AvatarData;
import emu.grasscutter.data.excels.AvatarSkillDepotData;
7
import emu.grasscutter.game.avatar.Avatar;
Melledy's avatar
Melledy committed
8
import emu.grasscutter.game.inventory.EquipType;
9
import emu.grasscutter.game.inventory.GameItem;
Melledy's avatar
Melledy committed
10
import emu.grasscutter.game.player.Player;
Melledy's avatar
Melledy committed
11
12
13
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty;
Melledy's avatar
Melledy committed
14
import emu.grasscutter.game.world.Scene;
Melledy's avatar
Melledy committed
15
16
17
18
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;
19
import emu.grasscutter.net.proto.ChangeEnergyReasonOuterClass.ChangeEnergyReason;
Melledy's avatar
Melledy committed
20
import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason;
Melledy's avatar
Melledy committed
21
22
23
24
25
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;
Melledy's avatar
Melledy committed
26
import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason;
Melledy's avatar
Melledy committed
27
28
29
30
31
32
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;
33
import emu.grasscutter.server.event.player.PlayerMoveEvent;
Melledy's avatar
Melledy committed
34
import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
Melledy's avatar
Melledy committed
35
import emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify;
36
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
Melledy's avatar
Melledy committed
37
38
39
40
41
42
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;

43
44
public class EntityAvatar extends GameEntity {
	private final Avatar avatar;
KingRainbow44's avatar
KingRainbow44 committed
45

Melledy's avatar
Melledy committed
46
47
	private PlayerDieType killedType;
	private int killedBy;
KingRainbow44's avatar
KingRainbow44 committed
48

49
	public EntityAvatar(Scene scene, Avatar avatar) {
50
		super(scene);
Melledy's avatar
Melledy committed
51
		this.avatar = avatar;
logictc's avatar
logictc committed
52
		this.avatar.setCurrentEnergy();
53
		this.id = getScene().getWorld().getNextEntityId(EntityIdType.AVATAR);
KingRainbow44's avatar
KingRainbow44 committed
54

55
		GameItem weapon = this.getAvatar().getWeapon();
Melledy's avatar
Melledy committed
56
		if (weapon != null) {
57
			weapon.setWeaponEntityId(getScene().getWorld().getNextEntityId(EntityIdType.WEAPON));
Melledy's avatar
Melledy committed
58
59
		}
	}
KingRainbow44's avatar
KingRainbow44 committed
60

61
	public EntityAvatar(Avatar avatar) {
Melledy's avatar
Melledy committed
62
63
		super(null);
		this.avatar = avatar;
logictc's avatar
logictc committed
64
		this.avatar.setCurrentEnergy();
Melledy's avatar
Melledy committed
65
66
	}

github-actions's avatar
github-actions committed
67
68
69
    public Player getPlayer() {
        return avatar.getPlayer();
    }
Melledy's avatar
Melledy committed
70

github-actions's avatar
github-actions committed
71
72
73
    @Override
    public Position getPosition() {
        return getPlayer().getPosition();
Melledy's avatar
Melledy committed
74
	}
KingRainbow44's avatar
KingRainbow44 committed
75

Melledy's avatar
Melledy committed
76
77
78
79
80
	@Override
	public Position getRotation() {
		return getPlayer().getRotation();
	}

81
	public Avatar getAvatar() {
Melledy's avatar
Melledy committed
82
83
		return avatar;
	}
KingRainbow44's avatar
KingRainbow44 committed
84

Melledy's avatar
Melledy committed
85
86
87
	public int getKilledBy() {
		return killedBy;
	}
KingRainbow44's avatar
KingRainbow44 committed
88

Melledy's avatar
Melledy committed
89
90
91
92
93
94
95
96
	public PlayerDieType getKilledType() {
		return killedType;
	}

	@Override
	public boolean isAlive() {
		return this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0f;
	}
KingRainbow44's avatar
KingRainbow44 committed
97

Melledy's avatar
Melledy committed
98
99
100
101
	@Override
	public Int2FloatOpenHashMap getFightProperties() {
		return getAvatar().getFightProperties();
	}
KingRainbow44's avatar
KingRainbow44 committed
102

Melledy's avatar
Melledy committed
103
104
105
106
107
108
109
	public int getWeaponEntityId() {
		if (getAvatar().getWeapon() != null) {
			return getAvatar().getWeapon().getWeaponEntityId();
		}
		return 0;
	}

github-actions's avatar
github-actions committed
110
111
    @Override
    public void onDeath(int killerId) {
112
113
        super.onDeath(killerId); // Invoke super class's onDeath() method.

github-actions's avatar
github-actions committed
114
115
116
117
        this.killedType = PlayerDieType.PLAYER_DIE_TYPE_KILL_BY_MONSTER;
        this.killedBy = killerId;
        clearEnergy(ChangeEnergyReason.CHANGE_ENERGY_REASON_NONE);
    }
118
119

	public void onDeath(PlayerDieType dieType, int killerId) {
120
121
        super.onDeath(killerId); // Invoke super class's onDeath() method.

122
123
		this.killedType = dieType;
		this.killedBy = killerId;
124
		clearEnergy(ChangeEnergyReason.CHANGE_ENERGY_REASON_NONE);
125
	}
KingRainbow44's avatar
KingRainbow44 committed
126

Melledy's avatar
Melledy committed
127
128
129
	@Override
	public float heal(float amount) {
		float healed = super.heal(amount);
KingRainbow44's avatar
KingRainbow44 committed
130

Melledy's avatar
Melledy committed
131
132
		if (healed > 0f) {
			getScene().broadcastPacket(
github-actions's avatar
github-actions committed
133
                new PacketEntityFightPropChangeReasonNotify(this, FightProperty.FIGHT_PROP_CUR_HP, healed, PropChangeReason.PROP_CHANGE_REASON_ABILITY, ChangeHpReason.CHANGE_HP_REASON_ADD_ABILITY)
Melledy's avatar
Melledy committed
134
135
			);
		}
KingRainbow44's avatar
KingRainbow44 committed
136

Melledy's avatar
Melledy committed
137
138
		return healed;
	}
KingRainbow44's avatar
KingRainbow44 committed
139

140
141
	public void clearEnergy(ChangeEnergyReason reason) {
		// Fight props.
142
		FightProperty curEnergyProp = this.getAvatar().getSkillDepot().getElementType().getCurEnergyProp();
143
144
		FightProperty maxEnergyProp = this.getAvatar().getSkillDepot().getElementType().getMaxEnergyProp();

github-actions's avatar
github-actions committed
145
146
        // Get max energy.
        float maxEnergy = this.avatar.getFightProperty(maxEnergyProp);
147

github-actions's avatar
github-actions committed
148
149
        // Set energy to zero.
        this.avatar.setCurrentEnergy(curEnergyProp, 0);
150

github-actions's avatar
github-actions committed
151
152
        // Send packets.
        this.getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, curEnergyProp));
153

154
		if (reason == ChangeEnergyReason.CHANGE_ENERGY_REASON_SKILL_START) {
155
156
157
			this.getScene().broadcastPacket(new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, -maxEnergy, reason));
		}
	}
KingRainbow44's avatar
KingRainbow44 committed
158

159
160
	public void addEnergy(float amount, PropChangeReason reason) {
		this.addEnergy(amount, reason, false);
161
	}
162
	public void addEnergy(float amount, PropChangeReason reason, boolean isFlat) {
163
		// Get current and maximum energy for this avatar.
164
165
166
167
168
		FightProperty curEnergyProp = this.getAvatar().getSkillDepot().getElementType().getCurEnergyProp();
		FightProperty maxEnergyProp = this.getAvatar().getSkillDepot().getElementType().getMaxEnergyProp();

		float curEnergy = this.getFightProperty(curEnergyProp);
		float maxEnergy = this.getFightProperty(maxEnergyProp);
KingRainbow44's avatar
KingRainbow44 committed
169

170
171
172
		// Get energy recharge.
		float energyRecharge = this.getFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY);

github-actions's avatar
github-actions committed
173
174
175
176
        // Scale amount by energy recharge, if the amount is not flat.
        if (!isFlat) {
            amount *= energyRecharge;
        }
177
178

		// Determine the new energy value.
Melledy's avatar
Melledy committed
179
		float newEnergy = Math.min(curEnergy + amount, maxEnergy);
KingRainbow44's avatar
KingRainbow44 committed
180

181
		// Set energy and notify.
Melledy's avatar
Melledy committed
182
		if (newEnergy != curEnergy) {
logictc's avatar
logictc committed
183
			this.avatar.setCurrentEnergy(curEnergyProp, newEnergy);
KingRainbow44's avatar
KingRainbow44 committed
184

185
186
			this.getScene().broadcastPacket(new PacketAvatarFightPropUpdateNotify(this.getAvatar(), curEnergyProp));
			this.getScene().broadcastPacket(new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, newEnergy, reason));
Melledy's avatar
Melledy committed
187
		}
KingRainbow44's avatar
KingRainbow44 committed
188
189
	}

Melledy's avatar
Melledy committed
190
191
	public SceneAvatarInfo getSceneAvatarInfo() {
		SceneAvatarInfo.Builder avatarInfo = SceneAvatarInfo.newBuilder()
192
				.setUid(this.getPlayer().getUid())
Melledy's avatar
Melledy committed
193
194
195
196
197
198
199
200
201
202
203
204
205
				.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());
KingRainbow44's avatar
KingRainbow44 committed
206

207
		for (GameItem item : avatar.getEquips().values()) {
Melledy's avatar
Melledy committed
208
209
210
211
212
213
214
			if (item.getItemData().getEquipType() == EquipType.EQUIP_WEAPON) {
				avatarInfo.setWeapon(item.createSceneWeaponInfo());
			} else {
				avatarInfo.addReliquaryList(item.createSceneReliquaryInfo());
			}
			avatarInfo.addEquipIdList(item.getItemId());
		}
KingRainbow44's avatar
KingRainbow44 committed
215

Melledy's avatar
Melledy committed
216
217
218
219
220
221
222
223
224
225
226
		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();
KingRainbow44's avatar
KingRainbow44 committed
227

Melledy's avatar
Melledy committed
228
229
		SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
				.setEntityId(getId())
230
				.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_AVATAR)
Melledy's avatar
Melledy committed
231
232
233
234
235
236
				.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
				.setEntityClientData(EntityClientData.newBuilder())
				.setEntityAuthorityInfo(authority)
				.setLastMoveSceneTimeMs(this.getLastMoveSceneTimeMs())
				.setLastMoveReliableSeq(this.getLastMoveReliableSeq())
				.setLifeState(this.getLifeState().getValue());
KingRainbow44's avatar
KingRainbow44 committed
237

238
		if (this.getScene() != null) {
Melledy's avatar
Melledy committed
239
240
			entityInfo.setMotionInfo(this.getMotionInfo());
		}
KingRainbow44's avatar
KingRainbow44 committed
241

Melledy's avatar
Melledy committed
242
243
244
245
		for (Int2FloatMap.Entry entry : getFightProperties().int2FloatEntrySet()) {
			if (entry.getIntKey() == 0) {
				continue;
			}
246
			FightPropPair fightProp = FightPropPair.newBuilder().setPropType(entry.getIntKey()).setPropValue(entry.getFloatValue()).build();
Melledy's avatar
Melledy committed
247
248
			entityInfo.addFightPropList(fightProp);
		}
KingRainbow44's avatar
KingRainbow44 committed
249

Melledy's avatar
Melledy committed
250
251
252
253
254
		PropPair pair = PropPair.newBuilder()
				.setType(PlayerProperty.PROP_LEVEL.getId())
				.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, getAvatar().getLevel()))
				.build();
		entityInfo.addPropList(pair);
KingRainbow44's avatar
KingRainbow44 committed
255

Melledy's avatar
Melledy committed
256
		entityInfo.setAvatar(this.getSceneAvatarInfo());
KingRainbow44's avatar
KingRainbow44 committed
257

Melledy's avatar
Melledy committed
258
259
		return entityInfo.build();
	}
KingRainbow44's avatar
KingRainbow44 committed
260

Melledy's avatar
Melledy committed
261
262
263
264
	public AbilityControlBlock getAbilityControlBlock() {
		AvatarData data = this.getAvatar().getAvatarData();
		AbilityControlBlock.Builder abilityControlBlock = AbilityControlBlock.newBuilder();
		int embryoId = 0;
KingRainbow44's avatar
KingRainbow44 committed
265

Melledy's avatar
Melledy committed
266
267
268
269
270
271
		// Add avatar abilities
		if (data.getAbilities() != null) {
			for (int id : data.getAbilities()) {
				AbilityEmbryo emb = AbilityEmbryo.newBuilder()
						.setAbilityId(++embryoId)
						.setAbilityNameHash(id)
272
						.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
Melledy's avatar
Melledy committed
273
274
275
276
						.build();
				abilityControlBlock.addAbilityEmbryoList(emb);
			}
		}
KingRainbow44's avatar
KingRainbow44 committed
277
		// Add default abilities
278
		for (int id : GameConstants.DEFAULT_ABILITY_HASHES) {
Melledy's avatar
Melledy committed
279
280
281
			AbilityEmbryo emb = AbilityEmbryo.newBuilder()
					.setAbilityId(++embryoId)
					.setAbilityNameHash(id)
282
					.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
Melledy's avatar
Melledy committed
283
284
285
					.build();
			abilityControlBlock.addAbilityEmbryoList(emb);
		}
KingRainbow44's avatar
KingRainbow44 committed
286
		// Add team resonances
Melledy's avatar
Melledy committed
287
288
289
290
		for (int id : this.getPlayer().getTeamManager().getTeamResonancesConfig()) {
			AbilityEmbryo emb = AbilityEmbryo.newBuilder()
					.setAbilityId(++embryoId)
					.setAbilityNameHash(id)
291
					.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
Melledy's avatar
Melledy committed
292
293
294
295
					.build();
			abilityControlBlock.addAbilityEmbryoList(emb);
		}
		// Add skill depot abilities
296
		AvatarSkillDepotData skillDepot = GameData.getAvatarSkillDepotDataMap().get(this.getAvatar().getSkillDepotId());
Melledy's avatar
Melledy committed
297
298
299
300
301
		if (skillDepot != null && skillDepot.getAbilities() != null) {
			for (int id : skillDepot.getAbilities()) {
				AbilityEmbryo emb = AbilityEmbryo.newBuilder()
						.setAbilityId(++embryoId)
						.setAbilityNameHash(id)
302
						.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
Melledy's avatar
Melledy committed
303
304
305
306
307
						.build();
				abilityControlBlock.addAbilityEmbryoList(emb);
			}
		}
		// Add equip abilities
308
309
		if (this.getAvatar().getExtraAbilityEmbryos().size() > 0) {
			for (String skill : this.getAvatar().getExtraAbilityEmbryos()) {
Melledy's avatar
Melledy committed
310
311
312
				AbilityEmbryo emb = AbilityEmbryo.newBuilder()
						.setAbilityId(++embryoId)
						.setAbilityNameHash(Utils.abilityHash(skill))
313
						.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
Melledy's avatar
Melledy committed
314
315
316
317
						.build();
				abilityControlBlock.addAbilityEmbryoList(emb);
			}
		}
KingRainbow44's avatar
KingRainbow44 committed
318

Melledy's avatar
Melledy committed
319
320
		//
		return abilityControlBlock.build();
Melledy's avatar
Melledy committed
321
	}
KingRainbow44's avatar
KingRainbow44 committed
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338

    /**
     * Move this entity to a new position.
     * Additionally invoke player move event.
     * @param newPosition The new position.
     * @param rotation The new rotation.
     */
    @Override public void move(Position newPosition, Position rotation) {
        // Invoke player move event.
        PlayerMoveEvent event = new PlayerMoveEvent(
            this.getPlayer(), PlayerMoveEvent.MoveType.PLAYER,
            this.getPosition(), newPosition
        ); event.call();

        // Set position and rotation.
        super.move(event.getDestination(), rotation);
    }
Melledy's avatar
Melledy committed
339
}