Skip to content
Snippets Groups Projects
Commit 897f082b authored by Melledy's avatar Melledy
Browse files

Implement AbilityManager

parent 176f3e91
Branches
Tags
No related merge requests found
Showing
with 438 additions and 34 deletions
...@@ -9,6 +9,8 @@ import java.util.Map; ...@@ -9,6 +9,8 @@ import java.util.Map;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.utils.Utils; import emu.grasscutter.utils.Utils;
import emu.grasscutter.data.custom.AbilityEmbryoEntry; import emu.grasscutter.data.custom.AbilityEmbryoEntry;
import emu.grasscutter.data.custom.AbilityModifier;
import emu.grasscutter.data.custom.AbilityModifierEntry;
import emu.grasscutter.data.custom.OpenConfigEntry; import emu.grasscutter.data.custom.OpenConfigEntry;
import emu.grasscutter.data.custom.ScenePointEntry; import emu.grasscutter.data.custom.ScenePointEntry;
import emu.grasscutter.data.def.*; import emu.grasscutter.data.def.*;
...@@ -22,6 +24,7 @@ public class GameData { ...@@ -22,6 +24,7 @@ public class GameData {
// BinOutputs // BinOutputs
private static final Int2ObjectMap<String> abilityHashes = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap<String> abilityHashes = new Int2ObjectOpenHashMap<>();
private static final Map<String, AbilityEmbryoEntry> abilityEmbryos = new HashMap<>(); private static final Map<String, AbilityEmbryoEntry> abilityEmbryos = new HashMap<>();
private static final Map<String, AbilityModifierEntry> abilityModifiers = new HashMap<>();
private static final Map<String, OpenConfigEntry> openConfigEntries = new HashMap<>(); private static final Map<String, OpenConfigEntry> openConfigEntries = new HashMap<>();
private static final Map<String, ScenePointEntry> scenePointEntries = new HashMap<>(); private static final Map<String, ScenePointEntry> scenePointEntries = new HashMap<>();
...@@ -101,6 +104,10 @@ public class GameData { ...@@ -101,6 +104,10 @@ public class GameData {
return abilityEmbryos; return abilityEmbryos;
} }
public static Map<String, AbilityModifierEntry> getAbilityModifiers() {
return abilityModifiers;
}
public static Map<String, OpenConfigEntry> getOpenConfigEntries() { public static Map<String, OpenConfigEntry> getOpenConfigEntries() {
return openConfigEntries; return openConfigEntries;
} }
......
...@@ -18,6 +18,11 @@ import emu.grasscutter.Grasscutter; ...@@ -18,6 +18,11 @@ import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.common.PointData; import emu.grasscutter.data.common.PointData;
import emu.grasscutter.data.common.ScenePointConfig; import emu.grasscutter.data.common.ScenePointConfig;
import emu.grasscutter.data.custom.AbilityEmbryoEntry; import emu.grasscutter.data.custom.AbilityEmbryoEntry;
import emu.grasscutter.data.custom.AbilityModifier;
import emu.grasscutter.data.custom.AbilityModifier.AbilityConfigData;
import emu.grasscutter.data.custom.AbilityModifier.AbilityModifierAction;
import emu.grasscutter.data.custom.AbilityModifier.AbilityModifierActionType;
import emu.grasscutter.data.custom.AbilityModifierEntry;
import emu.grasscutter.data.custom.OpenConfigEntry; import emu.grasscutter.data.custom.OpenConfigEntry;
import emu.grasscutter.data.custom.ScenePointEntry; import emu.grasscutter.data.custom.ScenePointEntry;
import emu.grasscutter.game.world.SpawnDataEntry; import emu.grasscutter.game.world.SpawnDataEntry;
...@@ -47,6 +52,7 @@ public class ResourceLoader { ...@@ -47,6 +52,7 @@ public class ResourceLoader {
// Load ability lists // Load ability lists
loadAbilityEmbryos(); loadAbilityEmbryos();
loadOpenConfig(); loadOpenConfig();
loadAbilityModifiers();
// Load resources // Load resources
loadResources(); loadResources();
// Process into depots // Process into depots
...@@ -244,6 +250,69 @@ public class ResourceLoader { ...@@ -244,6 +250,69 @@ public class ResourceLoader {
} }
} }
private static void loadAbilityModifiers() {
// Load from BinOutput
File folder = new File(Utils.toFilePath(Grasscutter.getConfig().RESOURCE_FOLDER + "BinOutput/Ability/Temp/AvatarAbilities/"));
File[] files = folder.listFiles();
if (files == null) {
Grasscutter.getLogger().error("Error loading ability modifiers: no files found in " + folder.getAbsolutePath());
return;
}
for (File file : files) {
List<AbilityConfigData> abilityConfigList = null;
try (FileReader fileReader = new FileReader(file)) {
abilityConfigList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, AbilityConfigData.class).getType());
} catch (Exception e) {
e.printStackTrace();
continue;
}
for (AbilityConfigData data : abilityConfigList) {
if (data.Default.modifiers == null || data.Default.modifiers.size() == 0) {
continue;
}
AbilityModifierEntry modifierEntry = new AbilityModifierEntry(data.Default.abilityName);
for (Entry<String, AbilityModifier> entry : data.Default.modifiers.entrySet()) {
AbilityModifier modifier = entry.getValue();
// Stare.
if (modifier.onAdded != null) {
for (AbilityModifierAction action : modifier.onAdded) {
if (action.$type.contains("HealHP")) {
action.type = AbilityModifierActionType.HealHP;
modifierEntry.getOnAdded().add(action);
}
}
}
if (modifier.onThinkInterval != null) {
for (AbilityModifierAction action : modifier.onThinkInterval) {
if (action.$type.contains("HealHP")) {
action.type = AbilityModifierActionType.HealHP;
modifierEntry.getOnThinkInterval().add(action);
}
}
}
if (modifier.onRemoved != null) {
for (AbilityModifierAction action : modifier.onRemoved) {
if (action.$type.contains("HealHP")) {
action.type = AbilityModifierActionType.HealHP;
modifierEntry.getOnRemoved().add(action);
}
}
}
}
GameData.getAbilityModifiers().put(modifierEntry.getName(), modifierEntry);
}
}
}
private static void loadSpawnData() { private static void loadSpawnData() {
// Read from cached file if exists // Read from cached file if exists
File spawnDataEntries = new File(Grasscutter.getConfig().DATA_FOLDER + "Spawns.json"); File spawnDataEntries = new File(Grasscutter.getConfig().DATA_FOLDER + "Spawns.json");
......
package emu.grasscutter.data.custom;
import java.util.Map;
public class AbilityModifier {
public AbilityModifierAction[] onAdded;
public AbilityModifierAction[] onThinkInterval;
public AbilityModifierAction[] onRemoved;
public static class AbilityConfigData {
public AbilityData Default;
}
public static class AbilityData {
public String abilityName;
public Map<String, AbilityModifier> modifiers;
}
public static class AbilityModifierAction {
public String $type;
public AbilityModifierActionType type;
public String target;
public AbilityModifierValue amount;
public AbilityModifierValue amountByTargetCurrentHPRatio;
}
public static class AbilityModifierValue {
public boolean isFormula;
public boolean isDynamic;
public String dynamicKey;
}
public enum AbilityModifierActionType {
HealHP, ApplyModifier, LoseHP;
}
}
package emu.grasscutter.data.custom;
import java.util.ArrayList;
import java.util.List;
import emu.grasscutter.data.custom.AbilityModifier.AbilityModifierAction;
public class AbilityModifierEntry {
private String name; // Custom value
public List<AbilityModifierAction> onModifierAdded;
public List<AbilityModifierAction> onThinkInterval;
public List<AbilityModifierAction> onRemoved;
public AbilityModifierEntry(String name) {
this.name = name;
this.onModifierAdded = new ArrayList<>();
this.onThinkInterval = new ArrayList<>();
this.onRemoved = new ArrayList<>();
}
public String getName() {
return name;
}
public List<AbilityModifierAction> getOnAdded() {
return onModifierAdded;
}
public List<AbilityModifierAction> getOnThinkInterval() {
return onThinkInterval;
}
public List<AbilityModifierAction> getOnRemoved() {
return onRemoved;
}
}
package emu.grasscutter.game.ability;
import com.google.protobuf.InvalidProtocolBufferException;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.custom.AbilityModifier;
import emu.grasscutter.data.custom.AbilityModifier.AbilityModifierAction;
import emu.grasscutter.data.custom.AbilityModifier.AbilityModifierActionType;
import emu.grasscutter.data.custom.AbilityModifierEntry;
import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.net.proto.AbilityInvokeArgumentOuterClass.AbilityInvokeArgument;
import emu.grasscutter.net.proto.AbilityInvokeEntryHeadOuterClass.AbilityInvokeEntryHead;
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
import emu.grasscutter.net.proto.AbilityMetaModifierChangeOuterClass.AbilityMetaModifierChange;
import emu.grasscutter.net.proto.AbilityMetaReInitOverrideMapOuterClass.AbilityMetaReInitOverrideMap;
import emu.grasscutter.net.proto.AbilityScalarTypeOuterClass.AbilityScalarType;
import emu.grasscutter.net.proto.AbilityScalarValueEntryOuterClass.AbilityScalarValueEntry;
import emu.grasscutter.net.proto.ModifierActionOuterClass.ModifierAction;
import emu.grasscutter.utils.Utils;
public class AbilityManager {
private Player player;
public AbilityManager(Player player) {
this.player = player;
}
public Player getPlayer() {
return this.player;
}
public void onAbilityInvoke(AbilityInvokeEntry invoke) throws Exception {
//System.out.println(invoke.getArgumentType() + " (" + invoke.getArgumentTypeValue() + "): " + Utils.bytesToHex(invoke.toByteArray()));
switch (invoke.getArgumentType()) {
case ABILITY_META_OVERRIDE_PARAM:
handleOverrideParam(invoke);
break;
case ABILITY_META_REINIT_OVERRIDEMAP:
handleReinitOverrideMap(invoke);
break;
case ABILITY_META_MODIFIER_CHANGE:
handleModifierChange(invoke);
break;
case ABILITY_MIXIN_COST_STAMINA:
handleMixinCostStamina(invoke);
break;
case ABILITY_ACTION_GENERATE_ELEM_BALL:
handleGenerateElemBall(invoke);
break;
default:
break;
}
}
private void handleOverrideParam(AbilityInvokeEntry invoke) throws Exception {
GameEntity entity = player.getScene().getEntityById(invoke.getEntityId());
if (entity == null) {
return;
}
AbilityScalarValueEntry entry = AbilityScalarValueEntry.parseFrom(invoke.getAbilityData());
entity.getMetaOverrideMap().put(entry.getKey().getStr(), entry.getFloatValue());
}
private void handleReinitOverrideMap(AbilityInvokeEntry invoke) throws Exception {
GameEntity entity = player.getScene().getEntityById(invoke.getEntityId());
if (entity == null) {
return;
}
AbilityMetaReInitOverrideMap map = AbilityMetaReInitOverrideMap.parseFrom(invoke.getAbilityData());
for (AbilityScalarValueEntry entry : map.getOverrideMapList()) {
entity.getMetaOverrideMap().put(entry.getKey().getStr(), entry.getFloatValue());
}
}
private void handleModifierChange(AbilityInvokeEntry invoke) throws Exception {
GameEntity target = player.getScene().getEntityById(invoke.getEntityId());
if (target == null) {
return;
}
AbilityInvokeEntryHead head = invoke.getHead();
if (head == null) {
return;
}
AbilityMetaModifierChange data = AbilityMetaModifierChange.parseFrom(invoke.getAbilityData());
if (data == null) {
return;
}
GameEntity sourceEntity = player.getScene().getEntityById(data.getApplyEntityId());
if (sourceEntity == null) {
return;
}
// This is not how it works but we will keep it for now since healing abilities dont work properly anyways
if (data.getAction() == ModifierAction.ADDED && data.getParentAbilityName() != null) {
// Handle add modifier here
String modifierString = data.getParentAbilityName().getStr();
AbilityModifierEntry modifier = GameData.getAbilityModifiers().get(modifierString);
if (modifier != null && modifier.getOnAdded().size() > 0) {
for (AbilityModifierAction action : modifier.getOnAdded()) {
invokeAction(action, target, sourceEntity);
}
}
// Add to meta modifier list
target.getMetaModifiers().put(head.getInstancedModifierId(), modifierString);
} else if (data.getAction() == ModifierAction.REMOVED) {
String modifierString = target.getMetaModifiers().get(head.getInstancedModifierId());
if (modifierString != null) {
// Get modifier and call on remove event
AbilityModifierEntry modifier = GameData.getAbilityModifiers().get(modifierString);
if (modifier != null && modifier.getOnRemoved().size() > 0) {
for (AbilityModifierAction action : modifier.getOnRemoved()) {
invokeAction(action, target, sourceEntity);
}
}
// Remove from meta modifiers
target.getMetaModifiers().remove(head.getInstancedModifierId());
}
}
}
private void handleMixinCostStamina(AbilityInvokeEntry invoke) {
// Not the right way of doing this
if (Grasscutter.getConfig().OpenStamina) {
// getPlayer().getStaminaManager().updateStamina(getPlayer().getSession(), -450);
// TODO
// set flag in stamina/movement manager that specifies the player is currently using an alternate sprint
}
}
private void handleGenerateElemBall(AbilityInvokeEntry invoke) {
// TODO create elemental energy orbs
}
private void invokeAction(AbilityModifierAction action, GameEntity target, GameEntity sourceEntity) {
switch (action.type) {
case HealHP -> {
if (action.amount == null) {
return;
}
float healAmount = 0;
if (action.amount.isDynamic && action.amount.dynamicKey != null) {
healAmount = sourceEntity.getMetaOverrideMap().getOrDefault(action.amount.dynamicKey, 0f);
}
if (healAmount > 0) {
target.heal(healAmount);
}
}
case LoseHP -> {
if (action.amountByTargetCurrentHPRatio == null) {
return;
}
float damageAmount = 0;
if (action.amount.isDynamic && action.amount.dynamicKey != null) {
damageAmount = sourceEntity.getMetaOverrideMap().getOrDefault(action.amount.dynamicKey, 0f);
}
if (damageAmount > 0) {
target.damage(damageAmount);
}
}
}
}
}
...@@ -17,17 +17,21 @@ import emu.grasscutter.net.proto.AbilityControlBlockOuterClass.AbilityControlBlo ...@@ -17,17 +17,21 @@ import emu.grasscutter.net.proto.AbilityControlBlockOuterClass.AbilityControlBlo
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;
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason;
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;
import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair; import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair;
import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType;
import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason;
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
import emu.grasscutter.net.proto.SceneAvatarInfoOuterClass.SceneAvatarInfo; import emu.grasscutter.net.proto.SceneAvatarInfoOuterClass.SceneAvatarInfo;
import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; 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.VectorOuterClass.Vector; import emu.grasscutter.net.proto.VectorOuterClass.Vector;
import emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper; import emu.grasscutter.utils.ProtoHelper;
import emu.grasscutter.utils.Utils; import emu.grasscutter.utils.Utils;
...@@ -110,6 +114,19 @@ public class EntityAvatar extends GameEntity { ...@@ -110,6 +114,19 @@ public class EntityAvatar extends GameEntity {
this.killedBy = killerId; this.killedBy = killerId;
} }
@Override
public float heal(float amount) {
float healed = super.heal(amount);
if (healed > 0f) {
getScene().broadcastPacket(
new PacketEntityFightPropChangeReasonNotify(this, FightProperty.FIGHT_PROP_CUR_HP, healed, PropChangeReason.PROP_CHANGE_ABILITY, ChangeHpReason.ChangeHpAddAbility)
);
}
return healed;
}
public SceneAvatarInfo getSceneAvatarInfo() { public SceneAvatarInfo getSceneAvatarInfo() {
SceneAvatarInfo.Builder avatarInfo = SceneAvatarInfo.newBuilder() SceneAvatarInfo.Builder avatarInfo = SceneAvatarInfo.newBuilder()
.setUid(this.getPlayer().getUid()) .setUid(this.getPlayer().getUid())
......
package emu.grasscutter.game.entity; package emu.grasscutter.game.entity;
import java.util.HashMap;
import java.util.Map;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.LifeState; import emu.grasscutter.game.props.LifeState;
import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.Scene;
...@@ -9,8 +12,11 @@ import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; ...@@ -9,8 +12,11 @@ import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.grasscutter.net.proto.VectorOuterClass.Vector; import emu.grasscutter.net.proto.VectorOuterClass.Vector;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public abstract class GameEntity { public abstract class GameEntity {
protected int id; protected int id;
...@@ -25,6 +31,10 @@ public abstract class GameEntity { ...@@ -25,6 +31,10 @@ public abstract class GameEntity {
private int lastMoveSceneTimeMs; private int lastMoveSceneTimeMs;
private int lastMoveReliableSeq; private int lastMoveReliableSeq;
// Abilities
private Map<String, Float> metaOverrideMap;
private Int2ObjectMap<String> metaModifiers;
public GameEntity(Scene scene) { public GameEntity(Scene scene) {
this.scene = scene; this.scene = scene;
this.moveState = MotionState.MOTION_NONE; this.moveState = MotionState.MOTION_NONE;
...@@ -54,6 +64,20 @@ public abstract class GameEntity { ...@@ -54,6 +64,20 @@ public abstract class GameEntity {
return isAlive() ? LifeState.LIFE_ALIVE : LifeState.LIFE_DEAD; return isAlive() ? LifeState.LIFE_ALIVE : LifeState.LIFE_DEAD;
} }
public Map<String, Float> getMetaOverrideMap() {
if (this.metaOverrideMap == null) {
this.metaOverrideMap = new HashMap<>();
}
return this.metaOverrideMap;
}
public Int2ObjectMap<String> getMetaModifiers() {
if (this.metaModifiers == null) {
this.metaModifiers = new Int2ObjectOpenHashMap<>();
}
return this.metaModifiers;
}
public abstract Int2FloatOpenHashMap getFightProperties(); public abstract Int2FloatOpenHashMap getFightProperties();
public abstract Position getPosition(); public abstract Position getPosition();
...@@ -146,4 +170,53 @@ public abstract class GameEntity { ...@@ -146,4 +170,53 @@ public abstract class GameEntity {
public void setSpawnEntry(SpawnDataEntry spawnEntry) { public void setSpawnEntry(SpawnDataEntry spawnEntry) {
this.spawnEntry = spawnEntry; this.spawnEntry = spawnEntry;
} }
public float heal(float amount) {
if (this.getFightProperties() == null) {
return 0f;
}
float curHp = getFightProperty(FightProperty.FIGHT_PROP_CUR_HP);
float maxHp = getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
if (curHp >= maxHp) {
return 0f;
}
float healed = Math.min(maxHp - curHp, amount);
this.addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, healed);
getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, FightProperty.FIGHT_PROP_CUR_HP));
return healed;
}
public void damage(float amount) {
damage(amount, 0);
}
public void damage(float amount, int killerId) {
// Sanity check
if (getFightProperties() == null) {
return;
}
// Lose hp
addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, -amount);
// Check if dead
boolean isDead = false;
if (getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) <= 0f) {
setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0f);
isDead = true;
}
// Packets
this.getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, FightProperty.FIGHT_PROP_CUR_HP));
// Check if dead
if (isDead) {
getScene().killEntity(this, 0);
}
}
} }
...@@ -8,6 +8,7 @@ import emu.grasscutter.data.def.PlayerLevelData; ...@@ -8,6 +8,7 @@ import emu.grasscutter.data.def.PlayerLevelData;
import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.Account; import emu.grasscutter.game.Account;
import emu.grasscutter.game.CoopRequest; import emu.grasscutter.game.CoopRequest;
import emu.grasscutter.game.ability.AbilityManager;
import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.avatar.AvatarProfileData; import emu.grasscutter.game.avatar.AvatarProfileData;
import emu.grasscutter.game.avatar.AvatarStorage; import emu.grasscutter.game.avatar.AvatarStorage;
...@@ -89,7 +90,8 @@ public class Player { ...@@ -89,7 +90,8 @@ public class Player {
@Transient private FriendsList friendsList; @Transient private FriendsList friendsList;
@Transient private MailHandler mailHandler; @Transient private MailHandler mailHandler;
@Transient private MessageHandler messageHandler; @Transient private MessageHandler messageHandler;
@Transient private AbilityManager abilityManager;
@Transient private SotSManager sotsManager; @Transient private SotSManager sotsManager;
private TeamManager teamManager; private TeamManager teamManager;
...@@ -142,6 +144,7 @@ public class Player { ...@@ -142,6 +144,7 @@ public class Player {
this.friendsList = new FriendsList(this); this.friendsList = new FriendsList(this);
this.mailHandler = new MailHandler(this); this.mailHandler = new MailHandler(this);
this.towerManager = new TowerManager(this); this.towerManager = new TowerManager(this);
this.abilityManager = new AbilityManager(this);
this.pos = new Position(); this.pos = new Position();
this.rotation = new Position(); this.rotation = new Position();
this.properties = new HashMap<>(); this.properties = new HashMap<>();
...@@ -1025,6 +1028,10 @@ public class Player { ...@@ -1025,6 +1028,10 @@ public class Player {
public SotSManager getSotSManager() { return sotsManager; } public SotSManager getSotSManager() { return sotsManager; }
public AbilityManager getAbilityManager() {
return abilityManager;
}
public synchronized void onTick() { public synchronized void onTick() {
// Check ping // Check ping
if (this.getLastPingTime() > System.currentTimeMillis() + 60000) { if (this.getLastPingTime() > System.currentTimeMillis() + 60000) {
......
...@@ -385,27 +385,7 @@ public class Scene { ...@@ -385,27 +385,7 @@ public class Scene {
} }
// Sanity check // Sanity check
if (target.getFightProperties() == null) { target.damage(result.getDamage(), result.getAttackerId());
return;
}
// Lose hp
target.addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, -result.getDamage());
// Check if dead
boolean isDead = false;
if (target.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) <= 0f) {
target.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0f);
isDead = true;
}
// Packets
this.broadcastPacket(new PacketEntityFightPropUpdateNotify(target, FightProperty.FIGHT_PROP_CUR_HP));
// Check if dead
if (isDead) {
this.killEntity(target, result.getAttackerId());
}
} }
public void killEntity(GameEntity target, int attackerId) { public void killEntity(GameEntity target, int attackerId) {
......
...@@ -6,6 +6,7 @@ import emu.grasscutter.net.proto.AbilityInvocationsNotifyOuterClass.AbilityInvoc ...@@ -6,6 +6,7 @@ import emu.grasscutter.net.proto.AbilityInvocationsNotifyOuterClass.AbilityInvoc
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.utils.Utils;
@Opcodes(PacketOpcodes.AbilityInvocationsNotify) @Opcodes(PacketOpcodes.AbilityInvocationsNotify)
public class HandlerAbilityInvocationsNotify extends PacketHandler { public class HandlerAbilityInvocationsNotify extends PacketHandler {
...@@ -15,7 +16,7 @@ public class HandlerAbilityInvocationsNotify extends PacketHandler { ...@@ -15,7 +16,7 @@ public class HandlerAbilityInvocationsNotify extends PacketHandler {
AbilityInvocationsNotify notif = AbilityInvocationsNotify.parseFrom(payload); AbilityInvocationsNotify notif = AbilityInvocationsNotify.parseFrom(payload);
for (AbilityInvokeEntry entry : notif.getInvokesList()) { for (AbilityInvokeEntry entry : notif.getInvokesList()) {
//System.out.println(entry.getArgumentType() + ": " + Utils.bytesToHex(entry.getAbilityData().toByteArray())); session.getPlayer().getAbilityManager().onAbilityInvoke(entry);
session.getPlayer().getAbilityInvokeHandler().addEntry(entry.getForwardType(), entry); session.getPlayer().getAbilityInvokeHandler().addEntry(entry.getForwardType(), entry);
} }
......
...@@ -6,6 +6,7 @@ import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry ...@@ -6,6 +6,7 @@ import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry
import emu.grasscutter.net.proto.ClientAbilityInitFinishNotifyOuterClass.ClientAbilityInitFinishNotify; import emu.grasscutter.net.proto.ClientAbilityInitFinishNotifyOuterClass.ClientAbilityInitFinishNotify;
import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.utils.Utils;
@Opcodes(PacketOpcodes.ClientAbilityInitFinishNotify) @Opcodes(PacketOpcodes.ClientAbilityInitFinishNotify)
public class HandlerClientAbilityInitFinishNotify extends PacketHandler { public class HandlerClientAbilityInitFinishNotify extends PacketHandler {
...@@ -15,6 +16,7 @@ public class HandlerClientAbilityInitFinishNotify extends PacketHandler { ...@@ -15,6 +16,7 @@ public class HandlerClientAbilityInitFinishNotify extends PacketHandler {
ClientAbilityInitFinishNotify notif = ClientAbilityInitFinishNotify.parseFrom(payload); ClientAbilityInitFinishNotify notif = ClientAbilityInitFinishNotify.parseFrom(payload);
for (AbilityInvokeEntry entry : notif.getInvokesList()) { for (AbilityInvokeEntry entry : notif.getInvokesList()) {
session.getPlayer().getAbilityManager().onAbilityInvoke(entry);
session.getPlayer().getClientAbilityInitFinishHandler().addEntry(entry.getForwardType(), entry); session.getPlayer().getClientAbilityInitFinishHandler().addEntry(entry.getForwardType(), entry);
} }
......
...@@ -14,11 +14,6 @@ public class HandlerEvtCreateGadgetNotify extends PacketHandler { ...@@ -14,11 +14,6 @@ public class HandlerEvtCreateGadgetNotify extends PacketHandler {
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
EvtCreateGadgetNotify notify = EvtCreateGadgetNotify.parseFrom(payload); EvtCreateGadgetNotify notify = EvtCreateGadgetNotify.parseFrom(payload);
// Dont handle in singleplayer
if (!session.getPlayer().getWorld().isMultiplayer()) {
return;
}
// Sanity check - dont add duplicate entities // Sanity check - dont add duplicate entities
if (session.getPlayer().getScene().getEntityById(notify.getEntityId()) != null) { if (session.getPlayer().getScene().getEntityById(notify.getEntityId()) != null) {
return; return;
......
...@@ -12,11 +12,6 @@ public class HandlerEvtDestroyGadgetNotify extends PacketHandler { ...@@ -12,11 +12,6 @@ public class HandlerEvtDestroyGadgetNotify extends PacketHandler {
@Override @Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
EvtDestroyGadgetNotify notify = EvtDestroyGadgetNotify.parseFrom(payload); EvtDestroyGadgetNotify notify = EvtDestroyGadgetNotify.parseFrom(payload);
// Dont handle in singleplayer
if (!session.getPlayer().getWorld().isMultiplayer()) {
return;
}
session.getPlayer().getScene().onPlayerDestroyGadget(notify.getEntityId()); session.getPlayer().getScene().onPlayerDestroyGadget(notify.getEntityId());
} }
......
...@@ -23,7 +23,7 @@ public class HandlerSetEntityClientDataNotify extends PacketHandler { ...@@ -23,7 +23,7 @@ public class HandlerSetEntityClientDataNotify extends PacketHandler {
BasePacket packet = new BasePacket(PacketOpcodes.SetEntityClientDataNotify, true); BasePacket packet = new BasePacket(PacketOpcodes.SetEntityClientDataNotify, true);
packet.setData(notif); packet.setData(notif);
session.getPlayer().getScene().broadcastPacketToOthers(session.getPlayer(), packet); session.getPlayer().getScene().broadcastPacket(packet);
} }
} }
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