Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions Maple2.Database/Model/CharacterConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ internal class CharacterConfig {
public IList<int>? FavoriteStickers { get; set; }
public IList<long>? FavoriteDesigners { get; set; }
public IDictionary<LapenshardSlot, int>? Lapenshards { get; set; }
public List<SkillCooldown>? SkillCooldowns { get; set; }
public long DeathTick { get; set; }
public int DeathCount { get; set; }
public IDictionary<int, int>? GatheringCounts { get; set; }
Expand Down Expand Up @@ -56,7 +55,6 @@ public static void Configure(EntityTypeBuilder<CharacterConfig> builder) {
builder.Property(config => config.FavoriteStickers).HasJsonConversion();
builder.Property(config => config.FavoriteDesigners).HasJsonConversion();
builder.Property(config => config.Lapenshards).HasJsonConversion();
builder.Property(config => config.SkillCooldowns).HasJsonConversion();
builder.Property(config => config.GatheringCounts).HasJsonConversion();
builder.Property(config => config.GuideRecords).HasJsonConversion();

Expand Down Expand Up @@ -86,29 +84,6 @@ public static implicit operator Maple2.Model.Game.SkillMacro(SkillMacro? other)
}
}

internal class SkillCooldown {
public int SkillId { get; set; }
public int OriginSkillId { get; set; }
public long EndTick { get; set; }

[return: NotNullIfNotNull(nameof(other))]
public static implicit operator SkillCooldown?(Maple2.Model.Game.SkillCooldown? other) {
return other == null ? null : new SkillCooldown {
SkillId = other.SkillId,
OriginSkillId = other.OriginSkillId,
EndTick = other.EndTick,
};
}

[return: NotNullIfNotNull(nameof(other))]
public static implicit operator Maple2.Model.Game.SkillCooldown?(SkillCooldown? other) {
return other == null ? null : new Maple2.Model.Game.SkillCooldown(other.SkillId) {
OriginSkillId = other.OriginSkillId,
EndTick = other.EndTick,
};
}
}

internal class Wardrobe {
public int Type { get; set; }
public int KeyId { get; set; }
Expand Down
8 changes: 2 additions & 6 deletions Maple2.Database/Storage/Game/GameStorage.User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,11 +310,11 @@ public bool SaveCharacter(Character character) {
}

public (IList<KeyBind>? KeyBinds, IList<QuickSlot[]>? HotBars, List<SkillMacro>?, List<Wardrobe>?, List<int>? FavoriteStickers, List<long>? FavoriteDesigners,
IDictionary<LapenshardSlot, int>? Lapenshards, IList<SkillCooldown>? SkillCooldowns, long DeathTick, int DeathCount, int ExplorationProgress, IDictionary<AttributePointSource, int>?,
IDictionary<LapenshardSlot, int>? Lapenshards, long DeathTick, int DeathCount, int ExplorationProgress, IDictionary<AttributePointSource, int>?,
IDictionary<BasicAttribute, int>?, SkillPoint? SkillPoint, IDictionary<int, int>? GatheringCounts, IDictionary<int, int>? GuideRecords, SkillBook?) LoadCharacterConfig(long characterId) {
CharacterConfig? config = Context.CharacterConfig.Find(characterId);
if (config == null) {
return (null, null, null, null, null, null, null, null, 0, 0, 0, null, null, null, null, null, null);
return (null, null, null, null, null, null, null, 0, 0, 0, null, null, null, null, null, null);
}

SkillBook? skillBook = config.SkillBook == null ? null : new SkillBook {
Expand Down Expand Up @@ -344,7 +344,6 @@ public bool SaveCharacter(Character character) {
config.FavoriteStickers?.Select(stickers => stickers).ToList(),
config.FavoriteDesigners?.Select(designer => designer).ToList(),
config.Lapenshards,
config.SkillCooldowns?.Select<Model.SkillCooldown, SkillCooldown>(cooldown => cooldown).ToList(),
config.DeathTick,
config.DeathCount,
config.ExplorationProgress,
Expand Down Expand Up @@ -390,9 +389,6 @@ public bool SaveCharacterConfig(
config.FavoriteStickers = favoriteStickers;
config.FavoriteDesigners = favoriteDesigners;
config.Lapenshards = lapenshards;
config.SkillCooldowns = skillCooldowns.Where(cooldown => cooldown.EndTick > Environment.TickCount64)
.Select<SkillCooldown, Model.SkillCooldown>(cooldown => cooldown)
.ToList();
config.DeathTick = deathTick;
config.DeathCount = deathCount;
config.ExplorationProgress = explorationProgress;
Expand Down
1 change: 1 addition & 0 deletions Maple2.File.Ingest/Mapper/AdditionalEffectMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ protected override IEnumerable<AdditionalEffectMetadata> Map() {
IntervalTick: data.BasicProperty.intervalTick,
DelayTick: data.BasicProperty.delayTick,
MaxCount: data.BasicProperty.maxBuffCount,
UseInGameTime: data.BasicProperty.useInGameTime,
KeepOnDeath: data.BasicProperty.deadKeepEffect,
RemoveOnLogout: data.BasicProperty.logoutClearEffect,
RemoveOnLeaveField: data.BasicProperty.leaveFieldClearEffect,
Expand Down
6 changes: 5 additions & 1 deletion Maple2.File.Ingest/Mapper/SkillMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@ protected override IEnumerable<StoredSkillMetadata> Map() {
MaxLevel: levels.Keys.Max()),
State: new SkillMetadataState(
InBattle: data.basic.stateAttr.battle == 1,
SuperArmor: data.basic.stateAttr.superArmor),
SuperArmor: data.basic.stateAttr.superArmor,
UseInGameTime: data.basic.stateAttr.useInGameTime == 1,
IgnoreReduceCooldown: data.basic.stateAttr.ignoreReduceCooldown == 1,
CooldownGroupId: data.basic.stateAttr.cooldownGroupID,
RechargeMaxCount: data.basic.stateAttr.rechargeMaxCount),
Levels: levels
);
}
Expand Down
1 change: 1 addition & 0 deletions Maple2.Model/Enum/PlayerObjectFlag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ public enum PlayerObjectFlag : byte {
Motto = 16,
GearScore = 32,
State = 64,
All = Dead | Position | Level | Job | Motto | GearScore | State,
}
13 changes: 9 additions & 4 deletions Maple2.Model/Game/User/SkillCooldown.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,22 @@ namespace Maple2.Model.Game;

public class SkillCooldown : IByteSerializable {
public readonly int SkillId;
public int OriginSkillId { get; init; }
public readonly short Level;
public int GroupId { get; init; }
public long EndTick;
public int Charges;

public SkillCooldown(int skillId) {
public SkillCooldown(int skillId, short level) {
SkillId = skillId;
Level = level;
GroupId = 0;
Charges = 0;
}

public void WriteTo(IByteWriter writer) {
writer.WriteInt(SkillId);
writer.WriteInt(OriginSkillId);
writer.WriteInt(GroupId);
writer.WriteInt((int) EndTick);
writer.WriteInt(); // Unknown Tick. Origin Skill tick maybe?
writer.WriteInt(Charges);
}
}
1 change: 1 addition & 0 deletions Maple2.Model/Metadata/AdditionalEffectMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public record AdditionalEffectMetadataProperty(
int IntervalTick,
int DelayTick,
int MaxCount,
bool UseInGameTime,
bool KeepOnDeath,
bool RemoveOnLogout,
bool RemoveOnLeaveField,
Expand Down
6 changes: 5 additions & 1 deletion Maple2.Model/Metadata/SkillMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ public record SkillMetadataProperty(

public record SkillMetadataState(
bool InBattle,
int SuperArmor); // 0, 1, 3
int SuperArmor, // 0, 1, 3
bool UseInGameTime,
int CooldownGroupId,
bool IgnoreReduceCooldown,
int RechargeMaxCount);

public record SkillMetadataLevel(
BeginCondition Condition,
Expand Down
40 changes: 40 additions & 0 deletions Maple2.Server.Core/proto/world/world.proto
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ service World {
rpc PlayerWarp(maple2.PlayerWarpRequest) returns (maple2.PlayerWarpResponse);
// Admin
rpc Admin(maple2.AdminRequest) returns (maple2.AdminResponse);
// Buff
rpc PlayerConfig(PlayerConfigRequest) returns (PlayerConfigResponse);
}

enum Server {
Expand Down Expand Up @@ -521,3 +523,41 @@ message AddChannelResponse {
int32 grpc_port = 2;
int32 game_channel = 3;
}

message PlayerConfigRequest {
message Save {
repeated BuffInfo buffs = 1;
repeated SkillCooldownInfo skill_cooldowns = 2;
}

message Get { }

int64 requester_id = 1;
oneof buff {
Save save = 2;
Get get = 3;
}
}

message PlayerConfigResponse {
repeated BuffInfo buffs = 1;
repeated SkillCooldownInfo skill_cooldowns = 2;
}

message BuffInfo {
int32 id = 1;
int32 level = 2;
int32 ms_remaining = 3;
int64 stop_time = 4;
bool enabled = 5;
int32 stacks = 6;
}

message SkillCooldownInfo {
int32 skill_id = 1;
int32 skill_level = 2;
int32 group_id = 3;
int32 ms_remaining = 4;
int64 stop_time = 5;
int32 charges = 6;
}
15 changes: 8 additions & 7 deletions Maple2.Server.Game/Commands/BuffCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,18 @@ private void Handle(InvocationContext ctx, int buffId, int level, int stack, int
}

if (duration > 0) {
duration *= 1000; // convert to milliseconds
duration = (int) TimeSpan.FromSeconds(1).TotalMilliseconds * duration;
}

long startTick = session.Field.FieldTick;
if (all) {
foreach (FieldPlayer player in session.Field.Players.Values) {
if (remove) {
player.Buffs.Remove(buffId);
} else {
player.Buffs.AddBuff(session.Player, player, buffId, (short) level, duration);
player.Buffs.AddBuff(session.Player, player, buffId, (short) level, startTick, duration);
if (stack > 1) {
player.Buffs.Buffs[buffId].Stack(stack);
player.Buffs.Buffs[buffId].Stack(player.Field.FieldTick, stack);
session.Field?.Broadcast(BuffPacket.Update(player.Buffs.Buffs[buffId]));
}
}
Expand All @@ -74,19 +75,19 @@ private void Handle(InvocationContext ctx, int buffId, int level, int stack, int
player.Buffs.Remove(buffId);
return;
}
player.Buffs.AddBuff(session.Player, player, buffId, (short) level, duration);
player.Buffs.AddBuff(session.Player, player, buffId, (short) level, startTick, duration);
if (stack > 1) {
player.Buffs.Buffs[buffId].Stack(stack);
player.Buffs.Buffs[buffId].Stack(player.Field.FieldTick, stack);
session.Field.Broadcast(BuffPacket.Update(player.Buffs.Buffs[buffId]));
}
} else {
if (remove) {
session.Player.Buffs.Remove(buffId);
return;
}
session.Player.Buffs.AddBuff(session.Player, session.Player, buffId, (short) level, duration);
session.Player.Buffs.AddBuff(session.Player, session.Player, buffId, (short) level, startTick, duration);
if (stack > 1) {
session.Player.Buffs.Buffs[buffId].Stack(stack);
session.Player.Buffs.Buffs[buffId].Stack(session.Field.FieldTick, stack);
session.Field?.Broadcast(BuffPacket.Update(session.Player.Buffs.Buffs[buffId]));
}
}
Expand Down
46 changes: 35 additions & 11 deletions Maple2.Server.Game/Manager/Config/BuffManager.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using System.Collections.Concurrent;
using Maple2.Database.Extensions;
using Maple2.Model.Enum;
using Maple2.Model.Game;
using Maple2.Model.Metadata;
using Maple2.Server.Game.Model;
using Maple2.Server.Game.Model.Skill;
using Maple2.Server.Game.Packets;
using Maple2.Server.Game.Session;
using Maple2.Server.Game.Util;
using Maple2.Server.World.Service;
using Maple2.Tools.Extensions;
using Serilog;

Expand Down Expand Up @@ -58,14 +61,14 @@ public void LoadFieldBuffs() {
}
}

public void AddBuff(IActor caster, IActor owner, int id, short level, int durationSec = -1, bool notifyField = true) {
public void AddBuff(IActor caster, IActor owner, int id, short level, long startTick, int durationMs = -1, bool notifyField = true) {
if (!owner.Field.SkillMetadata.TryGetEffect(id, level, out AdditionalEffectMetadata? additionalEffect)) {
logger.Error("Invalid buff: {SkillId},{Level}", id, level);
return;
}

if (durationSec < 0) {
durationSec = additionalEffect.Property.DurationTick;
if (durationMs < 0) {
durationMs = additionalEffect.Property.DurationTick;
}

// Check if immune to any present buffs
Expand All @@ -79,7 +82,7 @@ public void AddBuff(IActor caster, IActor owner, int id, short level, int durati
if (level > existing.Level) {

}
if (!existing.Stack()) {
if (!existing.Stack(startTick)) {
return;
}
if (notifyField) {
Expand All @@ -97,9 +100,9 @@ public void AddBuff(IActor caster, IActor owner, int id, short level, int durati
}
}

var buff = new Buff(owner.Field, additionalEffect, NextLocalId(), caster, owner, durationSec);
var buff = new Buff(additionalEffect, NextLocalId(), caster, owner, startTick, durationMs);
if (!Buffs.TryAdd(id, buff)) {
Buffs[id].Stack();
Buffs[id].Stack(startTick);
owner.Field.Broadcast(BuffPacket.Update(buff));
return;
}
Expand Down Expand Up @@ -309,7 +312,7 @@ public void LeaveField() {

private void AddMapBuffs() {
foreach (MapEntranceBuff buff in Actor.Field.Metadata.EntranceBuffs) {
AddBuff(Actor, Actor, buff.Id, buff.Level);
AddBuff(Actor, Actor, buff.Id, buff.Level, Actor.Field.FieldTick);
}

if (Actor.Field.Metadata.Property.Type == MapType.Pvp) {
Expand All @@ -325,21 +328,21 @@ private void AddMapBuffs() {
}

if (Actor.Field.Metadata.Property.Region == MapRegion.ShadowWorld) {
AddBuff(Actor, Actor, Constant.shadowWorldBuffHpUp, 1);
AddBuff(Actor, Actor, Constant.shadowWorldBuffMoveProtect, 1);
AddBuff(Actor, Actor, Constant.shadowWorldBuffHpUp, 1, Actor.Field.FieldTick);
AddBuff(Actor, Actor, Constant.shadowWorldBuffMoveProtect, 1, Actor.Field.FieldTick);
}
}

public void AddItemBuffs(Item item) {
foreach (ItemMetadataAdditionalEffect buff in item.Metadata.AdditionalEffects) {
AddBuff(Actor, Actor, buff.Id, buff.Level);
AddBuff(Actor, Actor, buff.Id, buff.Level, Actor.Field.FieldTick);
}

if (item.Socket != null) {
foreach (ItemGemstone? gem in item.Socket.Sockets) {
if (gem != null && Actor.Field.ItemMetadata.TryGet(gem.ItemId, out ItemMetadata? metadata)) {
foreach (ItemMetadataAdditionalEffect buff in metadata.AdditionalEffects) {
AddBuff(Actor, Actor, buff.Id, buff.Level);
AddBuff(Actor, Actor, buff.Id, buff.Level, Actor.Field.FieldTick);
}
}
}
Expand All @@ -362,6 +365,23 @@ public void RemoveItemBuffs(Item item) {
}
}

public void SetCacheBuffs(IList<BuffInfo> buffs, long currentTick) {
if (Actor is not FieldPlayer player) {
return;
}

foreach (BuffInfo info in buffs) {
if (!player.Field.SkillMetadata.TryGetEffect(info.Id, (short) info.Level, out AdditionalEffectMetadata? additionalEffect)) {
logger.Error("Invalid buff: {SkillId},{Level}", info.Id, info.Level);
continue;
}

if (additionalEffect.Property.UseInGameTime || info.MsRemaining > 0) {
AddBuff(Actor, Actor, info.Id, (short) info.Level, currentTick, info.MsRemaining);
}
}
}

public bool Remove(int id) {
//TODO: Check if buff is removable/should be removed
if (!Buffs.Remove(id, out Buff? buff)) {
Expand Down Expand Up @@ -406,4 +426,8 @@ private bool CheckImmunity(int newBuffId, BuffCategory category) {

return true;
}

public List<Buff> GetSaveCacheBuffs() {
return Buffs.Values.Where(buff => !buff.Metadata.Property.RemoveOnLogout).ToList();
}
}
Loading