3 Commits

Author SHA1 Message Date
Acentech Dev
2927be1ba9 chore(docs): regenerate QuestProgressExtended packet doc as C2
Some checks failed
.NET Core / build (push) Has been cancelled
The packet definition declares C2HeaderWithSubCode, but the committed
doc was generated from an older C1 header and never refreshed. This is
the doc generator's output for the current XML, so the tree stays clean
after a build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 22:04:13 +03:00
Acentech Dev
16752f3649 chore(deploy): default RESOLVE_IP to the emulator host alias
Without RESOLVE_IP the ConnectServer advertises the public IP, which the
emulator cannot reach, so server select hangs. Default to 10.0.2.2 and
allow an override for real devices on the LAN.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 22:04:13 +03:00
Acentech Dev
ef3bffe39c feat(items): add Imperial Sword (0/50) and Imperial Staff (5/50)
Two new weapons placed at free item slots so they never collide with
standard Season 6 items. The client name DB (Item_eng.bmd) is the source
of tooltip name/stats, so only free slots are usable for custom items.

Both seed paths are covered:
- Fresh DB: Weapons.Initialize() calls the new CreateImperialWeapons050().
- Existing DB: AddImperialWeapons050UpdateSeason6 (UpdateVersion 95),
  applied from the AdminPanel Updates page, with an idempotency guard.

Imperial Sword is a Magic Gladiator weapon (copy of 0/28), Imperial Staff
is a Wizard weapon (copy of 5/31).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 22:03:52 +03:00
6 changed files with 93 additions and 6 deletions

View File

@@ -17,6 +17,10 @@ services:
environment:
DB_HOST: database
ASPNETCORE_URLS: http://+:8080
# ConnectServer'in GameServer'i client'a hangi IP ile bildirecegi.
# Default: emulator host alias 10.0.2.2 (normal ConnectServer 44405 akisi calissin).
# Gercek cihaz icin: RESOLVE_IP=<PC LAN IP> ile override et (orn. 192.168.0.4).
RESOLVE_IP: ${RESOLVE_IP:-10.0.2.2}
working_dir: /app/
depends_on:
- database

View File

@@ -1,4 +1,4 @@
# C1 F6 0C - QuestProgressExtended (by server)
# C2 F6 0C - QuestProgressExtended (by server)
## Is sent when
@@ -12,10 +12,10 @@ The client shows the quest progress accordingly.
| Index | Length | Data Type | Value | Description |
|-------|--------|-----------|-------|-------------|
| 0 | 1 | Byte | 0xC1 | [Packet type](PacketTypes.md) |
| 1 | 1 | Byte | 272 | Packet header - length of the packet |
| 2 | 1 | Byte | 0xF6 | Packet header - packet type identifier |
| 3 | 1 | Byte | 0x0C | Packet header - sub packet type identifier |
| 0 | 1 | Byte | 0xC2 | [Packet type](PacketTypes.md) |
| 1 | 2 | Short | 272 | Packet header - length of the packet |
| 3 | 1 | Byte | 0xF6 | Packet header - packet type identifier |
| 4 | 1 | Byte | 0x0C | Packet header - sub packet type identifier |
| 5 | 1 | Byte | | ConditionCount |
| 6 | 1 | Byte | | RewardCount |
| 7 | 1 | Byte | | RandomRewardCount |

View File

@@ -234,7 +234,7 @@
* [C1 F6 0A - AvailableQuests (by server)](C1-F6-0A-AvailableQuests_by-server.md)
* [C1 F6 0B - QuestStepInfo (by server)](C1-F6-0B-QuestStepInfo_by-server.md)
* [C1 F6 0C - QuestProgress (by server)](C1-F6-0C-QuestProgress_by-server.md)
* [C1 F6 0C - QuestProgressExtended (by server)](C1-F6-0C-QuestProgressExtended_by-server.md)
* [C2 F6 0C - QuestProgressExtended (by server)](C2-F6-0C-QuestProgressExtended_by-server.md)
* [C1 F6 0D - QuestCompletionResponse (by server)](C1-F6-0D-QuestCompletionResponse_by-server.md)
* [C1 F6 0F - QuestCancelled (by server)](C1-F6-0F-QuestCancelled_by-server.md)
* [C1 F6 1A - QuestStateList (by server)](C1-F6-1A-QuestStateList_by-server.md)

View File

@@ -0,0 +1,56 @@
// <copyright file="AddImperialWeapons050UpdateSeason6.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.Updates;
using System.Runtime.InteropServices;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.Persistence.Initialization.VersionSeasonSix.Items;
using MUnique.OpenMU.PlugIns;
/// <summary>
/// Adds two new weapons at item number 50: Imperial Sword (group 0, Magic Gladiator) and
/// Imperial Staff (group 5, Wizard), as full working weapons (damage, attack speed, requirements,
/// options, equip flags). Placed at free slots so they never collide with standard items.
/// </summary>
[PlugIn]
[Display(Name = PlugInName, Description = PlugInDescription)]
[Guid("BE9DD7D1-F352-4C56-A646-D78C36978982")]
public class AddImperialWeapons050UpdateSeason6 : UpdatePlugInBase
{
internal const string PlugInName = "Add Imperial Weapons (0/50, 5/50)";
internal const string PlugInDescription = "Adds Imperial Sword (0/50) and Imperial Staff (5/50) as fully working weapons.";
/// <inheritdoc />
public override UpdateVersion Version => UpdateVersion.AddImperialWeapons050Season6;
/// <inheritdoc />
public override string DataInitializationKey => VersionSeasonSix.DataInitialization.Id;
/// <inheritdoc />
public override string Name => PlugInName;
/// <inheritdoc />
public override string Description => PlugInDescription;
/// <inheritdoc />
public override bool IsMandatory => true;
/// <inheritdoc />
public override DateTime CreatedAt => new(2026, 07, 16, 12, 0, 0, DateTimeKind.Utc);
/// <inheritdoc />
#pragma warning disable CS1998
protected override async ValueTask ApplyAsync(IContext context, GameConfiguration gameConfiguration)
#pragma warning restore CS1998
{
// Idempotency guard: skip if the Imperial Sword 0/50 already exists.
if (gameConfiguration.Items.Any(i => i.Group == 0 && i.Number == 50))
{
return;
}
new Weapons(context, gameConfiguration).CreateImperialWeapons050();
}
}

View File

@@ -479,4 +479,9 @@ public enum UpdateVersion
/// The version of the <see cref="AddIsQuestItemFlagPlugIn"/>.
/// </summary>
AddIsQuestItemFlag = 94,
/// <summary>
/// The version of the <see cref="AddImperialWeapons050UpdateSeason6"/>.
/// </summary>
AddImperialWeapons050Season6 = 95,
}

View File

@@ -269,6 +269,9 @@ internal class Weapons : InitializerBase
this.CreateWeapon(5, 34, 0, 0, 1, 4, false, "Raven Stick", 147, 70, 78, 30, 98, 130, 0, 50, 14, 0, 0, 0, 0, 0, 0, 0, 2, 0);
this.CreateWeapon(5, 36, 0, 0, 1, 4, false, "Divine Stick of Archangel", 104, 153, 165, 30, 182, 146, 0, 55, 13, 0, 0, 0, 0, 0, 0, 0, 1, 0);
// ADAMU-CUSTOM: new Imperial weapons at free slots (fresh-DB seed path; existing DBs get them via AddImperialWeapons050UpdateSeason6).
this.CreateImperialWeapons050();
this.AddGuardianOptions();
}
@@ -522,6 +525,25 @@ internal class Weapons : InitializerBase
}
}
/// <summary>
/// Creates only the two new "Imperial" weapons at item number 50 (Imperial Sword 0/50 and
/// Imperial Staff 5/50), reusing <see cref="CreateWeapon"/> and the already-persisted
/// item level bonus tables (looked up by name). Intended for a configuration update
/// plug-in running against an existing database, so it does NOT recreate the tables.
/// </summary>
public void CreateImperialWeapons050()
{
this._weaponDamageIncreaseTable = this.GameConfiguration.ItemLevelBonusTables.First(t => t.Name == "Damage Increase (Weapons)");
this._staffRiseTableEven = this.GameConfiguration.ItemLevelBonusTables.First(t => t.Name == "Staff Rise (even)");
this._staffRiseTableOdd = this.GameConfiguration.ItemLevelBonusTables.First(t => t.Name == "Staff Rise (odd)");
// Imperial Sword (copy of 0/28, Magic Gladiator) at number 50.
this.CreateWeapon(0, 50, 0, 56, 1, 4, true, "Imperial Sword", 139, 98, 122, 45, 90, 109, 380, 91, 73, 17, 0, 0, 0, 0, 1, 0, 0, 0);
// Imperial Staff (copy of 5/31, Wizard) at number 50.
this.CreateWeapon(5, 50, 0, 0, 1, 4, true, "Imperial Staff", 137, 57, 61, 30, 182, 124, 380, 48, 14, 0, 0, 2, 0, 0, 0, 0, 0, 0);
}
private void AddGuardianOptions()
{
var weaponOption = this.GameConfiguration.ItemOptions.First(io => io.PossibleOptions.Any(po => po.OptionType == ItemOptionTypes.GuardianOption && po.Number == (int)ItemGroups.Weapon));