From 0d69782d3c930f08dbdfc6f4796abbcf24490d9c Mon Sep 17 00:00:00 2001 From: Zin <62830952+Zintixx@users.noreply.github.com> Date: Thu, 6 Mar 2025 09:21:01 -0800 Subject: [PATCH] Conditions --- Maple2.Model/Game/User/IPlayerInfo.cs | 3 +++ Maple2.Model/Game/User/PlayerInfo.cs | 19 +++++++++----- .../Sync/PlayerInfoUpdateEvent.cs | 4 +++ .../Sync/PlayerInfoUpdateExtensions.cs | 4 +++ Maple2.Server.Core/proto/sync.proto | 26 +++++++++++-------- Maple2.Server.Game/Manager/PartyManager.cs | 4 +++ Maple2.Server.Game/Manager/QuestManager.cs | 5 ++-- Maple2.Server.Game/Manager/StatsManager.cs | 1 + .../PacketHandlers/InstrumentHandler.cs | 8 ++++++ Maple2.Server.Game/Session/GameSession.cs | 12 ++++++--- Maple2.Server.Game/Util/ConditionUtil.cs | 25 ++++++++++++++++++ 11 files changed, 89 insertions(+), 22 deletions(-) diff --git a/Maple2.Model/Game/User/IPlayerInfo.cs b/Maple2.Model/Game/User/IPlayerInfo.cs index 953c5b13c..687dea35d 100644 --- a/Maple2.Model/Game/User/IPlayerInfo.cs +++ b/Maple2.Model/Game/User/IPlayerInfo.cs @@ -33,6 +33,9 @@ public interface IPlayerInfo { public AchievementInfo AchievementInfo { get; set; } // Dungeon public Dictionary DungeonEnterLimits { get; set; } + // Guild + public long GuildId { get; set; } + public string GuildName { get; set; } // Timestamp public long UpdateTime { get; set; } diff --git a/Maple2.Model/Game/User/PlayerInfo.cs b/Maple2.Model/Game/User/PlayerInfo.cs index 0c2a0f3f5..56ee035c8 100644 --- a/Maple2.Model/Game/User/PlayerInfo.cs +++ b/Maple2.Model/Game/User/PlayerInfo.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Numerics; +using System.Numerics; using Maple2.Model.Common; using Maple2.Model.Enum; using Maple2.PacketLib.Tools; @@ -34,6 +31,8 @@ public static implicit operator PlayerInfo(Player player) { PremiumTime = player.Character.PremiumTime, LastOnlineTime = player.Character.LastOnlineTime, DungeonEnterLimits = [], + GuildId = player.Character.GuildId, + GuildName = player.Character.GuildName, }; } @@ -75,8 +74,8 @@ public void WriteTo(IByteWriter writer) { writer.Write(default); writer.WriteLong(); writer.Write(default); - writer.WriteLong(); // Guild Id - writer.WriteUnicodeString(); // Guild Name + writer.WriteLong(GuildId); + writer.WriteUnicodeString(GuildName); writer.WriteUnicodeString(Motto); writer.WriteUnicodeString(Picture); writer.WriteByte((byte) ClubIds.Count); @@ -129,6 +128,10 @@ public class CharacterInfo { public short Channel { get; set; } public long LastOnlineTime { get; set; } + // Guild + public long GuildId { get; set; } + public string GuildName { get; set; } + public long UpdateTime { get; set; } public bool Online => Channel != 0; @@ -155,6 +158,8 @@ public CharacterInfo(CharacterInfo other) { MapId = other.MapId; Channel = other.Channel; LastOnlineTime = other.LastOnlineTime; + GuildId = other.GuildId; + GuildName = other.GuildName; } public static implicit operator CharacterInfo(Player player) { @@ -169,6 +174,8 @@ public static implicit operator CharacterInfo(Player player) { level: player.Character.Level) { MapId = player.Character.MapId, Channel = player.Character.Channel, + GuildId = player.Character.GuildId, + GuildName = player.Character.GuildName, }; } } diff --git a/Maple2.Server.Core/Sync/PlayerInfoUpdateEvent.cs b/Maple2.Server.Core/Sync/PlayerInfoUpdateEvent.cs index 5af4c440f..cfeb6f814 100644 --- a/Maple2.Server.Core/Sync/PlayerInfoUpdateEvent.cs +++ b/Maple2.Server.Core/Sync/PlayerInfoUpdateEvent.cs @@ -49,6 +49,10 @@ public PlayerInfoUpdateEvent(IPlayerInfo player, PlayerUpdateRequest request) { Type |= UpdateField.Profile; } else if (request.HasGender && player.Gender != (Gender) request.Gender) { Type |= UpdateField.Profile; + } else if (request.HasGuildId && player.GuildId != request.GuildId) { + Type |= UpdateField.Profile; + } else if (request.HasGuildName && player.GuildName != request.GuildName) { + Type |= UpdateField.Profile; } if (request.HasJob && player.Job != (Job) request.Job) { Type |= UpdateField.Job; diff --git a/Maple2.Server.Core/Sync/PlayerInfoUpdateExtensions.cs b/Maple2.Server.Core/Sync/PlayerInfoUpdateExtensions.cs index 22f826cf0..f0700f56b 100644 --- a/Maple2.Server.Core/Sync/PlayerInfoUpdateExtensions.cs +++ b/Maple2.Server.Core/Sync/PlayerInfoUpdateExtensions.cs @@ -73,6 +73,8 @@ public static void Update(this IPlayerInfo self, UpdateField type, IPlayerInfo o self.Name = other.Name; self.Motto = other.Motto; self.Picture = other.Picture; + self.GuildId = other.GuildId; + self.GuildName = other.GuildName; } if (type.HasFlag(UpdateField.Job)) { self.Job = other.Job; @@ -124,6 +126,8 @@ public static void SetFields(this PlayerUpdateRequest request, UpdateField type, request.Motto = info.Motto; request.Picture = info.Picture; request.LastOnlineTime = info.LastOnlineTime; + request.GuildId = info.GuildId; + request.GuildName = info.GuildName; } if (type.HasFlag(UpdateField.Job)) { request.Job = (int) info.Job; diff --git a/Maple2.Server.Core/proto/sync.proto b/Maple2.Server.Core/proto/sync.proto index cf979a2a9..a581d2caf 100644 --- a/Maple2.Server.Core/proto/sync.proto +++ b/Maple2.Server.Core/proto/sync.proto @@ -58,14 +58,16 @@ message PlayerUpdateRequest { optional int32 channel = 12; optional int64 premium_time = 13; optional int64 last_online_time = 14; - optional HealthUpdate health = 15; - optional HomeUpdate home = 16; - optional TrophyUpdate trophy = 17; - repeated ClubUpdate clubs = 18; - repeated DungeonEnterLimitUpdate dungeon_enter_limits = 19; + optional int64 guild_id = 15; + optional string guild_name = 16; + optional HealthUpdate health = 17; + optional HomeUpdate home = 18; + optional TrophyUpdate trophy = 19; + repeated ClubUpdate clubs = 20; + repeated DungeonEnterLimitUpdate dungeon_enter_limits = 21; // Batch updates in a queue rather than immediately forwarding. - bool async = 20; + bool async = 22; } message PlayerUpdateResponse { @@ -91,9 +93,11 @@ message PlayerInfoResponse { int64 last_online_time = 12; int32 map_id = 13; int32 channel = 14; - HealthUpdate health = 15; - HomeUpdate home = 16; - TrophyUpdate trophy = 17; - repeated ClubUpdate clubs = 18; - repeated DungeonEnterLimitUpdate dungeon_enter_limits = 19; + int64 guild_id = 15; + string guild_name = 16; + HealthUpdate health = 17; + HomeUpdate home = 18; + TrophyUpdate trophy = 19; + repeated ClubUpdate clubs = 20; + repeated DungeonEnterLimitUpdate dungeon_enter_limits = 21; } diff --git a/Maple2.Server.Game/Manager/PartyManager.cs b/Maple2.Server.Game/Manager/PartyManager.cs index 755437c3e..a5d0f6546 100644 --- a/Maple2.Server.Game/Manager/PartyManager.cs +++ b/Maple2.Server.Game/Manager/PartyManager.cs @@ -306,6 +306,10 @@ public void SetDungeon(int dungeonId, int dungeonRoomId, bool set) { session.Send(PartyPacket.DungeonReset(set, dungeonId)); } + public int GuildMemberCount() { + return Party?.Members.Values.Count(member => member.Info.GuildId == session.Player.Value.Character.GuildId) ?? 0; + } + public void SetPartySearch(PartySearch? partySearch) { if (Party == null) { return; diff --git a/Maple2.Server.Game/Manager/QuestManager.cs b/Maple2.Server.Game/Manager/QuestManager.cs index a85fed59a..01d9e2948 100644 --- a/Maple2.Server.Game/Manager/QuestManager.cs +++ b/Maple2.Server.Game/Manager/QuestManager.cs @@ -183,9 +183,10 @@ public void Update(ConditionType type, long counter = 1, string targetString = " .Concat(accountValues.Values.Where(quest => quest.State != QuestState.Completed)); foreach (Quest quest in quests) { // TODO: Not sure if ProgressMap really means that only progress counts in this map. It doesn't make sense for some quests. - /*if (quest.Metadata.Basic.ProgressMaps != null && !quest.Metadata.Basic.ProgressMaps.Contains(session.Player.Value.Character.MapId)) { + // Testing only on FieldMission for now. + if (quest.Metadata.Basic.Type == QuestType.FieldMission && quest.Metadata.Basic.ProgressMaps != null && !quest.Metadata.Basic.ProgressMaps.Contains(session.Player.Value.Character.MapId)) { continue; - }*/ + } foreach (Quest.Condition condition in quest.Conditions.Values.Where(condition => condition.Metadata.Type == type)) { // Already meets the requirement and does not need to be updated diff --git a/Maple2.Server.Game/Manager/StatsManager.cs b/Maple2.Server.Game/Manager/StatsManager.cs index 94157e6b8..194359926 100644 --- a/Maple2.Server.Game/Manager/StatsManager.cs +++ b/Maple2.Server.Game/Manager/StatsManager.cs @@ -137,6 +137,7 @@ private void AddEquips(FieldPlayer player) { Log.Logger.Debug("Calculating Gearscore. Item ID: {id} - Gearscore: {gearscore} - Rarity: {rarity}, Enchant Level: {enchantLevel}, Limit Break Level: {limitBreakLevel}", item.Metadata.Id, item.Metadata.Property.GearScore, item.Rarity, item.Enchant?.Enchants ?? 0, item.LimitBreak?.Level ?? 0); Values.GearScore += player.Field.Lua.CalcItemLevel(item.Metadata.Property.GearScore, item.Rarity, item.Type.Type, item.Enchant?.Enchants ?? 0, item.LimitBreak?.Level ?? 0).Item1; player.Session.Dungeon.UpdateDungeonEnterLimit(); + player.Session.ConditionUpdate(ConditionType.item_gear_score, counter: Values.GearScore); if (item.Socket != null) { for (int index = 0; index < item.Socket.UnlockSlots; index++) { diff --git a/Maple2.Server.Game/PacketHandlers/InstrumentHandler.cs b/Maple2.Server.Game/PacketHandlers/InstrumentHandler.cs index 5e730baed..de74d45c9 100644 --- a/Maple2.Server.Game/PacketHandlers/InstrumentHandler.cs +++ b/Maple2.Server.Game/PacketHandlers/InstrumentHandler.cs @@ -141,6 +141,8 @@ private void HandleStartScore(GameSession session, IByteReader packet) { } session.Instrument.Score = score; + session.ConditionUpdate(ConditionType.music_play_score, codeLong: score.Id, targetLong: session.Field.MapId); + score.RemainUses--; session.Field.Broadcast(InstrumentPacket.StartScore(session.Instrument, score)); session.Send(InstrumentPacket.RemainUses(score.Uid, score.RemainUses)); @@ -170,6 +172,11 @@ private void HandleStopScore(GameSession session) { // Modifier is the number of 500ms ticks that have passed. session.Exp.AddExp(expType, (totalTickTime - 500) / 500); + session.ConditionUpdate(ConditionType.music_play_instrument_time, counter: totalTickTime / 1000, targetLong: session.Field.MapId, codeLong: session.Instrument.Value.Id); + if (session.Instrument.Ensemble) { + session.ConditionUpdate(ConditionType.play_ensenble_time, counter: totalTickTime / 1000, targetLong: session.Field.MapId); + } + session.Field.RemoveInstrument(session.Instrument.ObjectId); session.Instrument = null; } @@ -214,6 +221,7 @@ private void HandleJoinEnsemble(GameSession session, IByteReader packet) { memberSession.Field.Broadcast(InstrumentPacket.StartScore(memberSession.Instrument, memberSession.StagedScoreItem)); memberSession.Send(InstrumentPacket.RemainUses(memberSession.StagedScoreItem.Uid, memberSession.StagedScoreItem.RemainUses)); memberSession.ConditionUpdate(ConditionType.music_play_ensemble); + memberSession.ConditionUpdate(ConditionType.music_play_ensemble_in, codeLong: memberSession.Field.MapId, targetLong: memberSession.Field.MapId); } } diff --git a/Maple2.Server.Game/Session/GameSession.cs b/Maple2.Server.Game/Session/GameSession.cs index bd176f9c8..4155cafdf 100644 --- a/Maple2.Server.Game/Session/GameSession.cs +++ b/Maple2.Server.Game/Session/GameSession.cs @@ -372,9 +372,15 @@ public bool EnterField() { return false; } - if (!Player.Value.Unlock.Maps.Contains(Player.Value.Character.MapId) && Field.Metadata.Property.ExploreType > 0) { - ExpType expType = Field.Metadata.Property.ExploreType == 1 ? ExpType.mapCommon : ExpType.mapHidden; - Exp.AddExp(expType); + if (!Player.Value.Unlock.Maps.Contains(Player.Value.Character.MapId)) { + if (Field.Metadata.Property.ExploreType > 0) { + ExpType expType = Field.Metadata.Property.ExploreType == 1 ? ExpType.mapCommon : ExpType.mapHidden; + Exp.AddExp(expType); + } + + ConditionUpdate(ConditionType.explore_continent, codeLong: (int) Field.Metadata.Property.Continent); + ConditionUpdate(ConditionType.continent, codeLong: (int) Field.Metadata.Property.Continent); + ConditionUpdate(ConditionType.explore, codeLong: Field.MapId); } Player.Value.Unlock.Maps.Add(Player.Value.Character.MapId); diff --git a/Maple2.Server.Game/Util/ConditionUtil.cs b/Maple2.Server.Game/Util/ConditionUtil.cs index e1f03f1bf..25e5226d2 100644 --- a/Maple2.Server.Game/Util/ConditionUtil.cs +++ b/Maple2.Server.Game/Util/ConditionUtil.cs @@ -6,6 +6,17 @@ namespace Maple2.Server.Game.Util; public static class ConditionUtil { public static bool Check(this ConditionMetadata condition, GameSession session, string targetString = "", long targetLong = 0, string codeString = "", long codeLong = 0) { + if (condition.PartyCount > 0) { + if (session.Party.Party == null || session.Party.Party.Members.Count < condition.PartyCount) { + return false; + } + } + + if (condition.GuildPartyCount > 0) { + if (session.Party.Party == null || session.Party.GuildMemberCount() < condition.GuildPartyCount) { + return false; + } + } bool code = condition.Codes == null || condition.Codes.CheckCode(session, condition.Type, codeString, codeLong); bool target = condition.Target == null || condition.Target.CheckTarget(session, condition.Type, targetString, targetLong); return target && code; @@ -97,6 +108,12 @@ private static bool CheckCode(this ConditionMetadata.Parameters code, GameSessio case ConditionType.holdtime: case ConditionType.riding: case ConditionType.fish_big: + case ConditionType.music_play_instrument_time: + case ConditionType.music_play_ensemble_in: + case ConditionType.music_play_score: + case ConditionType.explore_continent: + case ConditionType.continent: + case ConditionType.explore: if (code.Range != null && InRange((ConditionMetadata.Range) code.Range, (int) longValue)) { return true; } @@ -141,6 +158,7 @@ private static bool CheckCode(this ConditionMetadata.Parameters code, GameSessio case ConditionType.wedding_propose_decline: case ConditionType.wedding_propose_declined: case ConditionType.wedding_hall_cancel: + case ConditionType.item_gear_score: return true; } return false; @@ -196,6 +214,9 @@ private static bool CheckTarget(this ConditionMetadata.Parameters target, GameSe case ConditionType.holdtime: case ConditionType.riding: case ConditionType.skill: + case ConditionType.music_play_instrument_time: + case ConditionType.music_play_score: + case ConditionType.music_play_ensemble_in: if (target.Range != null && target.Range.Value.Min >= longValue && target.Range.Value.Max <= longValue) { return true; @@ -263,6 +284,10 @@ private static bool CheckTarget(this ConditionMetadata.Parameters target, GameSe case ConditionType.wedding_propose_decline: case ConditionType.wedding_propose_declined: case ConditionType.wedding_hall_cancel: + case ConditionType.explore_continent: + case ConditionType.continent: + case ConditionType.explore: + case ConditionType.item_gear_score: return true; } return false;