mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-22 12:05:39 +00:00
Implement diving
This commit is contained in:
parent
f656143038
commit
cc91a2dcfc
@ -35,7 +35,6 @@ public final class GameConstants {
|
||||
"Avatar_FallAnthem_Achievement_Listener",
|
||||
"GrapplingHookSkill_Ability",
|
||||
"Avatar_PlayerBoy_DiveStamina_Reduction",
|
||||
"Ability_Avatar_Dive_Team",
|
||||
"Ability_Avatar_Dive_SealEcho",
|
||||
"Absorb_SealEcho_Bullet_01",
|
||||
"Absorb_SealEcho_Bullet_02",
|
||||
@ -43,6 +42,9 @@ public final class GameConstants {
|
||||
"ActivityAbility_Absorb_Shoot",
|
||||
"SceneAbility_DiveVolume"
|
||||
};
|
||||
public static final String[] DEFAULT_TEAM_ABILITY_STRINGS = {
|
||||
"Ability_Avatar_Dive_Team"
|
||||
};
|
||||
public static final SparseSet ILLEGAL_WEAPONS = new SparseSet("""
|
||||
10000-10008, 11411, 11506-11508, 12505, 12506, 12508, 12509,
|
||||
13503, 13506, 14411, 14503, 14505, 14508, 15504-15506
|
||||
|
@ -86,6 +86,12 @@ public final class SetPropCommand implements CommandHandler {
|
||||
this.props.put("fly", flyable);
|
||||
this.props.put("glider", flyable);
|
||||
this.props.put("canglide", flyable);
|
||||
|
||||
Prop dive = new Prop("CanDive", PlayerProperty.PROP_PLAYER_CAN_DIVE, PseudoProp.CAN_DIVE);
|
||||
this.props.put("dive", dive);
|
||||
this.props.put("swim", dive);
|
||||
this.props.put("water", dive);
|
||||
this.props.put("candive", dive);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -129,6 +135,7 @@ public final class SetPropCommand implements CommandHandler {
|
||||
case SET_OPENSTATE -> this.setOpenState(targetPlayer, value, 1);
|
||||
case UNSET_OPENSTATE -> this.setOpenState(targetPlayer, value, 0);
|
||||
case UNLOCK_MAP -> unlockMap(targetPlayer, value);
|
||||
case CAN_DIVE -> canDive(targetPlayer, value);
|
||||
default -> targetPlayer.setProperty(prop.prop, value);
|
||||
};
|
||||
|
||||
@ -219,6 +226,20 @@ public final class SetPropCommand implements CommandHandler {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean canDive(Player targetPlayer, int value) {
|
||||
// allow diving and set max stamina OR not
|
||||
if (value == 0) {
|
||||
targetPlayer.setProperty(PlayerProperty.PROP_PLAYER_CAN_DIVE, 0);
|
||||
targetPlayer.setProperty(PlayerProperty.PROP_DIVE_MAX_STAMINA, 0);
|
||||
targetPlayer.setProperty(PlayerProperty.PROP_DIVE_CUR_STAMINA, 0);
|
||||
} else {
|
||||
targetPlayer.setProperty(PlayerProperty.PROP_PLAYER_CAN_DIVE, 1);
|
||||
targetPlayer.setProperty(PlayerProperty.PROP_DIVE_MAX_STAMINA, 10000);
|
||||
targetPlayer.setProperty(PlayerProperty.PROP_DIVE_CUR_STAMINA, 10000);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean unlockMap(Player targetPlayer, int value) {
|
||||
// Unlock.
|
||||
GameData.getScenePointsPerScene()
|
||||
@ -270,7 +291,8 @@ public final class SetPropCommand implements CommandHandler {
|
||||
SET_OPENSTATE,
|
||||
UNSET_OPENSTATE,
|
||||
UNLOCK_MAP,
|
||||
IS_FLYABLE
|
||||
IS_FLYABLE,
|
||||
CAN_DIVE
|
||||
}
|
||||
|
||||
static class Prop {
|
||||
|
@ -579,14 +579,20 @@ public class Player implements PlayerHook, FieldFetch {
|
||||
this.setOrFetch(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT, 50);
|
||||
this.setOrFetch(PlayerProperty.PROP_IS_FLYABLE,
|
||||
withQuesting ? 0 : 1);
|
||||
this.setOrFetch(PlayerProperty.PROP_PLAYER_CAN_DIVE,
|
||||
withQuesting ? 0 : 1);
|
||||
this.setOrFetch(PlayerProperty.PROP_IS_TRANSFERABLE, 1);
|
||||
this.setOrFetch(PlayerProperty.PROP_MAX_STAMINA,
|
||||
withQuesting ? 10000 : 24000);
|
||||
this.setOrFetch(PlayerProperty.PROP_DIVE_MAX_STAMINA,
|
||||
withQuesting ? 10000 : 0);
|
||||
this.setOrFetch(PlayerProperty.PROP_PLAYER_RESIN, 160);
|
||||
|
||||
// The player's current stamina is always their max stamina.
|
||||
this.setProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA,
|
||||
this.getProperty(PlayerProperty.PROP_MAX_STAMINA));
|
||||
this.setProperty(PlayerProperty.PROP_DIVE_CUR_STAMINA,
|
||||
this.getProperty(PlayerProperty.PROP_DIVE_MAX_STAMINA));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1515,7 +1521,7 @@ public class Player implements PlayerHook, FieldFetch {
|
||||
int min = this.getPropertyMin(prop);
|
||||
int max = this.getPropertyMax(prop);
|
||||
if (min <= value && value <= max) {
|
||||
int currentValue = this.properties.get(prop.getId());
|
||||
int currentValue = this.properties.getOrDefault(prop.getId(), 0);
|
||||
this.properties.put(prop.getId(), value);
|
||||
if (sendPacket) {
|
||||
// Send property change reasons if needed.
|
||||
|
@ -1,53 +1,48 @@
|
||||
package emu.grasscutter.game.player;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import dev.morphia.annotations.Transient;
|
||||
import emu.grasscutter.GameConstants;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import dev.morphia.annotations.*;
|
||||
import emu.grasscutter.*;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.avatar.AvatarSkillDepotData;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.entity.EntityBaseGadget;
|
||||
import emu.grasscutter.game.entity.EntityTeam;
|
||||
import emu.grasscutter.game.props.ElementType;
|
||||
import emu.grasscutter.game.props.EnterReason;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.game.world.World;
|
||||
import emu.grasscutter.net.packet.BasePacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.game.entity.*;
|
||||
import emu.grasscutter.game.props.*;
|
||||
import emu.grasscutter.game.world.*;
|
||||
import emu.grasscutter.net.packet.*;
|
||||
import emu.grasscutter.net.proto.*;
|
||||
import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType;
|
||||
import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
|
||||
import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType;
|
||||
import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
|
||||
import emu.grasscutter.net.proto.TrialAvatarGrantRecordOuterClass.TrialAvatarGrantRecord.GrantReason;
|
||||
import emu.grasscutter.net.proto.VisionTypeOuterClass;
|
||||
import emu.grasscutter.server.event.entity.EntityCreationEvent;
|
||||
import emu.grasscutter.server.event.player.PlayerTeamDeathEvent;
|
||||
import emu.grasscutter.server.packet.send.*;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.val;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
||||
|
||||
@Entity
|
||||
public final class TeamManager extends BasePlayerDataManager {
|
||||
@Transient private final List<EntityAvatar> avatars;
|
||||
@Transient @Getter private final Set<EntityBaseGadget> gadgets;
|
||||
@Transient @Getter private final IntSet teamResonances;
|
||||
@Transient @Getter private final IntSet teamResonancesConfig;
|
||||
@Transient
|
||||
@Getter
|
||||
private final IntSet teamResonancesConfig;
|
||||
@Transient
|
||||
@Getter
|
||||
@Setter
|
||||
private Set<String> teamAbilityEmbryos;
|
||||
// This needs to be a LinkedHashMap to guarantee insertion order.
|
||||
@Getter private LinkedHashMap<Integer, TeamInfo> teams;
|
||||
@Getter
|
||||
private LinkedHashMap<Integer, TeamInfo> teams;
|
||||
private int currentTeamIndex;
|
||||
@Getter @Setter private int currentCharacterIndex;
|
||||
@Transient @Getter @Setter private TeamInfo mpTeam;
|
||||
@ -69,6 +64,7 @@ public final class TeamManager extends BasePlayerDataManager {
|
||||
this.gadgets = new HashSet<>();
|
||||
this.teamResonances = new IntOpenHashSet();
|
||||
this.teamResonancesConfig = new IntOpenHashSet();
|
||||
this.teamAbilityEmbryos = new HashSet<>();
|
||||
this.trialAvatars = new HashMap<>();
|
||||
this.trialAvatarTeam = new TeamInfo();
|
||||
}
|
||||
@ -84,6 +80,42 @@ public final class TeamManager extends BasePlayerDataManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Add team ability embryos, NOT to be confused with avatarAbilties.
|
||||
// These should include the ones in LevelEntity (according to levelEntityConfig field in sceneId)
|
||||
// rn only apply to big world defaults, but will fix scaramouch domain circles (BinOutput/LevelEntity/Level_Monster_Nada_setting)
|
||||
public AbilityControlBlockOuterClass.AbilityControlBlock getAbilityControlBlock() {
|
||||
AbilityControlBlockOuterClass.AbilityControlBlock.Builder abilityControlBlock = AbilityControlBlockOuterClass.AbilityControlBlock.newBuilder();
|
||||
int embryoId = 0;
|
||||
|
||||
// add from default
|
||||
if (Arrays.stream(GameConstants.DEFAULT_TEAM_ABILITY_STRINGS).count() > 0) {
|
||||
List<String> teamAbilties = Arrays.stream(GameConstants.DEFAULT_TEAM_ABILITY_STRINGS).toList();
|
||||
for (String skill : teamAbilties) {
|
||||
AbilityEmbryoOuterClass.AbilityEmbryo emb = AbilityEmbryoOuterClass.AbilityEmbryo.newBuilder()
|
||||
.setAbilityId(++embryoId)
|
||||
.setAbilityNameHash(Utils.abilityHash(skill))
|
||||
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
|
||||
.build();
|
||||
abilityControlBlock.addAbilityEmbryoList(emb);
|
||||
}
|
||||
}
|
||||
|
||||
// same as avatar ability hash (add frm levelEntityConfig data)
|
||||
if (this.getTeamAbilityEmbryos().size() > 0) {
|
||||
for (String skill : this.getTeamAbilityEmbryos()) {
|
||||
AbilityEmbryoOuterClass.AbilityEmbryo emb = AbilityEmbryoOuterClass.AbilityEmbryo.newBuilder()
|
||||
.setAbilityId(++embryoId)
|
||||
.setAbilityNameHash(Utils.abilityHash(skill))
|
||||
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
|
||||
.build();
|
||||
abilityControlBlock.addAbilityEmbryoList(emb);
|
||||
}
|
||||
}
|
||||
|
||||
// return block to add
|
||||
return abilityControlBlock.build();
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return this.getPlayer().getWorld();
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
package emu.grasscutter.game.props;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import java.util.stream.Stream;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public enum PlayerProperty {
|
||||
PROP_NONE(0),
|
||||
PROP_EXP(1001, 0),
|
||||
@ -60,7 +60,10 @@ public enum PlayerProperty {
|
||||
PROP_IS_AUTO_UNLOCK_SPECIFIC_EQUIP(10044), // New; unknown/un-used.
|
||||
PROP_PLAYER_GCG_COIN(10045), // New; unknown/un-used.
|
||||
PROP_PLAYER_WAIT_SUB_GCG_COIN(10046), // New; unknown/un-used.
|
||||
PROP_PLAYER_ONLINE_TIME(10047); // New; unknown/un-used.
|
||||
PROP_PLAYER_ONLINE_TIME(10047), // New; unknown/un-used.
|
||||
PROP_PLAYER_CAN_DIVE(10048, 0, 1), // Can the player dive? [0, 1]
|
||||
PROP_DIVE_MAX_STAMINA(10049, 0, 10000), // The maximum stamina of the player when diving. [0, 10000]
|
||||
PROP_DIVE_CUR_STAMINA(10050, 0, 10000); // The current stamina of the player when diving. [0, 10000]
|
||||
|
||||
private static final int inf = Integer.MAX_VALUE; // Maybe this should be something else?
|
||||
private static final Int2ObjectMap<PlayerProperty> map = new Int2ObjectOpenHashMap<>();
|
||||
|
@ -3,9 +3,7 @@ package emu.grasscutter.server.packet.send;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.inventory.GameItem;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.net.packet.BasePacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.AbilityControlBlockOuterClass;
|
||||
import emu.grasscutter.net.packet.*;
|
||||
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
|
||||
import emu.grasscutter.net.proto.AvatarEnterSceneInfoOuterClass.AvatarEnterSceneInfo;
|
||||
import emu.grasscutter.net.proto.MPLevelEntityInfoOuterClass.MPLevelEntityInfo;
|
||||
@ -28,8 +26,7 @@ public class PacketPlayerEnterSceneInfoNotify extends BasePacket {
|
||||
TeamEnterSceneInfo.newBuilder()
|
||||
.setTeamEntityId(player.getTeamManager().getEntity().getId()) // 150995833
|
||||
.setTeamAbilityInfo(empty)
|
||||
.setAbilityControlBlock(
|
||||
AbilityControlBlockOuterClass.AbilityControlBlock.newBuilder().build()));
|
||||
.setAbilityControlBlock(player.getTeamManager().getAbilityControlBlock()));
|
||||
proto.setMpLevelEntityInfo(
|
||||
MPLevelEntityInfo.newBuilder()
|
||||
.setEntityId(player.getWorld().getLevelEntityId()) // 184550274
|
||||
|
Loading…
Reference in New Issue
Block a user