Commit ef6e16aa authored by Melledy's avatar Melledy
Browse files

Refactor WeaponType and MonsterType into enums

parent b9ca4a5d
...@@ -9,6 +9,7 @@ import emu.grasscutter.data.ResourceType.LoadPriority; ...@@ -9,6 +9,7 @@ import emu.grasscutter.data.ResourceType.LoadPriority;
import emu.grasscutter.data.binout.AbilityEmbryoEntry; import emu.grasscutter.data.binout.AbilityEmbryoEntry;
import emu.grasscutter.data.common.PropGrowCurve; import emu.grasscutter.data.common.PropGrowCurve;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.WeaponType;
import emu.grasscutter.utils.Utils; import emu.grasscutter.utils.Utils;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntArrayList;
...@@ -22,7 +23,7 @@ public class AvatarData extends GameResource { ...@@ -22,7 +23,7 @@ public class AvatarData extends GameResource {
private String qualityType; private String qualityType;
private int chargeEfficiency; private int chargeEfficiency;
private int initialWeapon; private int initialWeapon;
private String weaponType; private WeaponType weaponType;
private String imageName; private String imageName;
private int avatarPromoteId; private int avatarPromoteId;
private String cutsceneShow; private String cutsceneShow;
...@@ -83,7 +84,7 @@ public class AvatarData extends GameResource { ...@@ -83,7 +84,7 @@ public class AvatarData extends GameResource {
return this.initialWeapon; return this.initialWeapon;
} }
public String getWeaponType(){ public WeaponType getWeaponType(){
return this.weaponType; return this.weaponType;
} }
......
...@@ -7,13 +7,14 @@ import emu.grasscutter.data.GameResource; ...@@ -7,13 +7,14 @@ import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.ResourceType; import emu.grasscutter.data.ResourceType;
import emu.grasscutter.data.ResourceType.LoadPriority; import emu.grasscutter.data.ResourceType.LoadPriority;
import emu.grasscutter.data.common.PropGrowCurve; import emu.grasscutter.data.common.PropGrowCurve;
import emu.grasscutter.game.props.MonsterType;
@ResourceType(name = "MonsterExcelConfigData.json", loadPriority = LoadPriority.LOW) @ResourceType(name = "MonsterExcelConfigData.json", loadPriority = LoadPriority.LOW)
public class MonsterData extends GameResource { public class MonsterData extends GameResource {
private int id; private int id;
private String monsterName; private String monsterName;
private String type; private MonsterType type;
private String serverScript; private String serverScript;
private List<Integer> affix; private List<Integer> affix;
private String ai; private String ai;
...@@ -55,7 +56,7 @@ public class MonsterData extends GameResource { ...@@ -55,7 +56,7 @@ public class MonsterData extends GameResource {
return monsterName; return monsterName;
} }
public String getType() { public MonsterType getType() {
return type; return type;
} }
......
...@@ -16,6 +16,8 @@ import emu.grasscutter.game.inventory.GameItem; ...@@ -16,6 +16,8 @@ import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ElementType; import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.MonsterType;
import emu.grasscutter.game.props.WeaponType;
import emu.grasscutter.net.proto.AbilityActionGenerateElemBallOuterClass.AbilityActionGenerateElemBall; import emu.grasscutter.net.proto.AbilityActionGenerateElemBallOuterClass.AbilityActionGenerateElemBall;
import emu.grasscutter.net.proto.AbilityIdentifierOuterClass.AbilityIdentifier; import emu.grasscutter.net.proto.AbilityIdentifierOuterClass.AbilityIdentifier;
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
...@@ -244,21 +246,6 @@ public class EnergyManager { ...@@ -244,21 +246,6 @@ public class EnergyManager {
/********** /**********
Energy generation for NAs/CAs. Energy generation for NAs/CAs.
**********/ **********/
private final static Map<String, Integer> initialNormalProbability = Map.ofEntries(
entry("WEAPON_SWORD_ONE_HAND", 10),
entry("WEAPON_BOW", 0),
entry("WEAPON_CLAYMORE", 0),
entry("WEAPON_POLE", 0),
entry("WEAPON_CATALYST", 0)
);
private final static Map<String, Integer> increaseNormalProbability = Map.ofEntries(
entry("WEAPON_SWORD_ONE_HAND", 5),
entry("WEAPON_BOW", 5),
entry("WEAPON_CLAYMORE", 10),
entry("WEAPON_POLE", 4),
entry("WEAPON_CATALYST", 10)
);
private void generateEnergyForNormalAndCharged(EntityAvatar avatar) { private void generateEnergyForNormalAndCharged(EntityAvatar avatar) {
// This logic is based on the descriptions given in // This logic is based on the descriptions given in
// https://genshin-impact.fandom.com/wiki/Energy#Energy_Generated_by_Normal_Attacks // https://genshin-impact.fandom.com/wiki/Energy#Energy_Generated_by_Normal_Attacks
...@@ -270,14 +257,11 @@ public class EnergyManager { ...@@ -270,14 +257,11 @@ public class EnergyManager {
// - Does this really count every individual hit separately? // - Does this really count every individual hit separately?
// Make sure the avatar's weapon type makes sense. // Make sure the avatar's weapon type makes sense.
String weaponType = avatar.getAvatar().getAvatarData().getWeaponType(); WeaponType weaponType = avatar.getAvatar().getAvatarData().getWeaponType();
if (!initialNormalProbability.containsKey(weaponType)) {
return;
}
// Check if we already have probability data for this avatar. If not, insert it. // Check if we already have probability data for this avatar. If not, insert it.
if (!this.avatarNormalProbabilities.containsKey(avatar)) { if (!this.avatarNormalProbabilities.containsKey(avatar)) {
this.avatarNormalProbabilities.put(avatar, initialNormalProbability.get(weaponType)); this.avatarNormalProbabilities.put(avatar, weaponType.getEnergyGainInitialProbability());
} }
// Roll for energy. // Roll for energy.
...@@ -287,11 +271,11 @@ public class EnergyManager { ...@@ -287,11 +271,11 @@ public class EnergyManager {
// If the player wins the roll, we increase the avatar's energy and reset the probability. // If the player wins the roll, we increase the avatar's energy and reset the probability.
if (roll < currentProbability) { if (roll < currentProbability) {
avatar.addEnergy(1.0f, PropChangeReason.PROP_CHANGE_REASON_ABILITY, true); avatar.addEnergy(1.0f, PropChangeReason.PROP_CHANGE_REASON_ABILITY, true);
this.avatarNormalProbabilities.put(avatar, initialNormalProbability.get(weaponType)); this.avatarNormalProbabilities.put(avatar, weaponType.getEnergyGainInitialProbability());
} }
// Otherwise, we increase the probability for the next hit. // Otherwise, we increase the probability for the next hit.
else { else {
this.avatarNormalProbabilities.put(avatar, currentProbability + increaseNormalProbability.get(weaponType)); this.avatarNormalProbabilities.put(avatar, currentProbability + weaponType.getEnergyGainIncreaseProbability());
} }
} }
...@@ -312,8 +296,8 @@ public class EnergyManager { ...@@ -312,8 +296,8 @@ public class EnergyManager {
} }
EntityMonster targetMonster = (EntityMonster)targetEntity; EntityMonster targetMonster = (EntityMonster)targetEntity;
String targetType = targetMonster.getMonsterData().getType(); MonsterType targetType = targetMonster.getMonsterData().getType();
if (!targetType.equals("MONSTER_ORDINARY") && !targetType.equals("MONSTER_BOSS")) { if (targetType != MonsterType.MONSTER_ORDINARY && targetType != MonsterType.MONSTER_BOSS) {
return; return;
} }
...@@ -385,8 +369,8 @@ public class EnergyManager { ...@@ -385,8 +369,8 @@ public class EnergyManager {
public void handleMonsterEnergyDrop(EntityMonster monster, float hpBeforeDamage, float hpAfterDamage) { public void handleMonsterEnergyDrop(EntityMonster monster, float hpBeforeDamage, float hpAfterDamage) {
// Make sure this is actually a monster. // Make sure this is actually a monster.
// Note that some wildlife also has that type, like boars or birds. // Note that some wildlife also has that type, like boars or birds.
String type = monster.getMonsterData().getType(); MonsterType type = monster.getMonsterData().getType();
if (!type.equals("MONSTER_ORDINARY") && !type.equals("MONSTER_BOSS")) { if (type != MonsterType.MONSTER_ORDINARY && type != MonsterType.MONSTER_BOSS) {
return; return;
} }
......
...@@ -4,12 +4,14 @@ import ch.qos.logback.classic.Logger; ...@@ -4,12 +4,14 @@ import ch.qos.logback.classic.Logger;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.command.commands.NoStaminaCommand; import emu.grasscutter.command.commands.NoStaminaCommand;
import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameData;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.entity.EntityAvatar; import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.entity.GameEntity; import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
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.props.PlayerProperty; import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.props.WeaponType;
import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo; import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo;
import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
...@@ -158,23 +160,7 @@ public class StaminaManager { ...@@ -158,23 +160,7 @@ public class StaminaManager {
put(542301, 0.8f); put(542301, 0.8f);
}}; }};
public static final HashSet<Integer> BowAvatars = new HashSet<>();
public static final HashSet<Integer> CatalystAvatars = new HashSet<>();
public static final HashSet<Integer> ClaymoreAvatars = new HashSet<>();
public static final HashSet<Integer> PolearmAvatars = new HashSet<>();
public static final HashSet<Integer> SwordAvatars = new HashSet<>();
public static void initialize() { public static void initialize() {
// Initialize skill categories
GameData.getAvatarDataMap().forEach((avatarId, avatarData) -> {
switch (avatarData.getWeaponType()) {
case "WEAPON_BOW" -> BowAvatars.add(avatarId);
case "WEAPON_CLAYMORE" -> ClaymoreAvatars.add(avatarId);
case "WEAPON_CATALYST" -> CatalystAvatars.add(avatarId);
case "WEAPON_POLE" -> PolearmAvatars.add(avatarId);
case "WEAPON_SWORD_ONE_HAND" -> SwordAvatars.add(avatarId);
}
});
// TODO: Initialize foods etc. // TODO: Initialize foods etc.
} }
...@@ -358,13 +344,14 @@ public class StaminaManager { ...@@ -358,13 +344,14 @@ public class StaminaManager {
} }
setSkillCast(skillId, casterId); setSkillCast(skillId, casterId);
// Handle immediate stamina cost // Handle immediate stamina cost
int currentAvatarId = player.getTeamManager().getCurrentAvatarEntity().getAvatar().getAvatarId(); Avatar currentAvatar = player.getTeamManager().getCurrentAvatarEntity().getAvatar();
if (ClaymoreAvatars.contains(currentAvatarId)) { if (currentAvatar.getAvatarData().getWeaponType() == WeaponType.WEAPON_CLAYMORE) {
// Exclude claymore as their stamina cost starts when MixinStaminaCost gets in // Exclude claymore as their stamina cost starts when MixinStaminaCost gets in
return; return;
} }
// TODO: Differentiate normal attacks from charged attacks and exclude // TODO: Differentiate normal attacks from charged attacks and exclude
// TODO: Temporary: Exclude non-claymore attacks for now // TODO: Temporary: Exclude non-claymore attacks for now
/*
if (BowAvatars.contains(currentAvatarId) if (BowAvatars.contains(currentAvatarId)
|| SwordAvatars.contains(currentAvatarId) || SwordAvatars.contains(currentAvatarId)
|| PolearmAvatars.contains(currentAvatarId) || PolearmAvatars.contains(currentAvatarId)
...@@ -372,7 +359,8 @@ public class StaminaManager { ...@@ -372,7 +359,8 @@ public class StaminaManager {
) { ) {
return; return;
} }
handleImmediateStamina(session, skillId); */
//handleImmediateStamina(session, skillId);
} }
public void handleMixinCostStamina(boolean isSwim) { public void handleMixinCostStamina(boolean isSwim) {
...@@ -543,26 +531,21 @@ public class StaminaManager { ...@@ -543,26 +531,21 @@ public class StaminaManager {
return getTalentMovingSustainedCost(skillCasting); return getTalentMovingSustainedCost(skillCasting);
} }
// Bow avatar charged attack // Bow avatar charged attack
int currentAvatarId = player.getTeamManager().getCurrentAvatarEntity().getAvatar().getAvatarId(); Avatar currentAvatar = player.getTeamManager().getCurrentAvatarEntity().getAvatar();
if (BowAvatars.contains(currentAvatarId)) {
switch (currentAvatar.getAvatarData().getWeaponType()) {
case WEAPON_BOW:
return getBowSustainedCost(skillCasting); return getBowSustainedCost(skillCasting);
} case WEAPON_CLAYMORE:
// Claymore avatar charged attack
if (ClaymoreAvatars.contains(currentAvatarId)) {
return getClaymoreSustainedCost(skillCasting); return getClaymoreSustainedCost(skillCasting);
} case WEAPON_CATALYST:
// Catalyst avatar charged attack
if (CatalystAvatars.contains(currentAvatarId)) {
return getCatalystCost(skillCasting); return getCatalystCost(skillCasting);
} case WEAPON_POLE:
// Polearm avatar charged attack
if (PolearmAvatars.contains(currentAvatarId)) {
return getPolearmCost(skillCasting); return getPolearmCost(skillCasting);
} case WEAPON_SWORD_ONE_HAND:
// Sword avatar charged attack
if (SwordAvatars.contains(skillCasting)) {
return getSwordCost(skillCasting); return getSwordCost(skillCasting);
} }
return new Consumption(); return new Consumption();
} }
......
package emu.grasscutter.game.props;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public enum MonsterType {
MONSTER_NONE (0),
MONSTER_ORDINARY (1),
MONSTER_BOSS (2),
MONSTER_ENV_ANIMAL (3),
MONSTER_LITTLE_MONSTER (4),
MONSTER_FISH (5);
private final int value;
private static final Int2ObjectMap<MonsterType> map = new Int2ObjectOpenHashMap<>();
private static final Map<String, MonsterType> stringMap = new HashMap<>();
static {
Stream.of(values()).forEach(e -> {
map.put(e.getValue(), e);
stringMap.put(e.name(), e);
});
}
private MonsterType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static MonsterType getTypeByValue(int value) {
return map.getOrDefault(value, MONSTER_NONE);
}
public static MonsterType getTypeByName(String name) {
return stringMap.getOrDefault(name, MONSTER_NONE);
}
}
package emu.grasscutter.game.props;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public enum WeaponType {
WEAPON_NONE (0),
WEAPON_SWORD_ONE_HAND (1),
WEAPON_CROSSBOW (2),
WEAPON_STAFF (3),
WEAPON_DOUBLE_DAGGER (4),
WEAPON_KATANA (5),
WEAPON_SHURIKEN (6),
WEAPON_STICK (7),
WEAPON_SPEAR (8),
WEAPON_SHIELD_SMALL (9),
WEAPON_CATALYST (10),
WEAPON_CLAYMORE (11),
WEAPON_BOW (12),
WEAPON_POLE (13);
private final int value;
private int energyGainInitialProbability;
private int energyGainIncreaseProbability;
private static final Int2ObjectMap<WeaponType> map = new Int2ObjectOpenHashMap<>();
private static final Map<String, WeaponType> stringMap = new HashMap<>();
static {
Stream.of(values()).forEach(e -> {
map.put(e.getValue(), e);
stringMap.put(e.name(), e);
});
}
private WeaponType(int value) {
this.value = value;
}
private WeaponType(int value, int energyGainInitialProbability, int energyGainIncreaseProbability) {
this.value = value;
this.energyGainInitialProbability = energyGainInitialProbability;
this.energyGainIncreaseProbability = energyGainIncreaseProbability;
}
public int getValue() {
return value;
}
public int getEnergyGainInitialProbability() {
return energyGainInitialProbability;
}
public int getEnergyGainIncreaseProbability() {
return energyGainIncreaseProbability;
}
public static WeaponType getTypeByValue(int value) {
return map.getOrDefault(value, WEAPON_NONE);
}
public static WeaponType getTypeByName(String name) {
return stringMap.getOrDefault(name, WEAPON_NONE);
}
}
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