Golden Archer#843
Conversation
…it from being overwritten on DB load
sven-n
left a comment
There was a problem hiding this comment.
Please refactor to a feature plugin, so we don't need all this database changes and be more flexible. The plugin could even be named differently (more generically) when it's configurable which NPC can handle such collect & reward requests.
| POSTGRES_USER: postgres | ||
| ports: | ||
| - "5432" | ||
| - "5432:5432" |
There was a problem hiding this comment.
Revert this change, please. We don't want to expose the database on a real deployment.
| POSTGRES_USER: postgres | ||
| ports: | ||
| - "5432" | ||
| - "5432:5432" |
There was a problem hiding this comment.
Revert this change, please. We don't want to expose the database on a real deployment.
| var connection = this._player.Connection; | ||
| if (connection != null) | ||
| { | ||
| // Calculate the number of renas in the inventory | ||
| int invRenas = this._player.Inventory?.Items.Count(i => | ||
| i.Definition?.Group == 14 && (i.Definition?.Number == 21 || i.Definition?.Number == 30 || i.Definition?.Number == 31)) ?? 0; | ||
|
|
||
| int registered = this._player.SelectedCharacter?.RegisteredRenas ?? 0; | ||
|
|
||
| int WritePacket() | ||
| { | ||
| var span = connection.Output.GetSpan(10)[..10]; | ||
| span[0] = 0xC1; // Packet type (C1) | ||
| span[1] = 0x0A; // Length (10 bytes) | ||
| span[2] = 0x94; // Packet code for Event Chip/Rena Result | ||
| span[3] = 0x00; // Result (0 = Success) | ||
|
|
||
| // Registered Count (int / 32-bit) at offset 4 | ||
| span[4] = (byte)(registered & 0xFF); | ||
| span[5] = (byte)((registered >> 8) & 0xFF); | ||
| span[6] = (byte)((registered >> 16) & 0xFF); | ||
| span[7] = (byte)((registered >> 24) & 0xFF); | ||
|
|
||
| // Remaining Inventory Count (short / 16-bit) at offset 8 | ||
| span[8] = (byte)(invRenas & 0xFF); | ||
| span[9] = (byte)((invRenas >> 8) & 0xFF); | ||
|
|
||
| return 10; | ||
| } | ||
|
|
||
| await connection.SendAsync(WritePacket).ConfigureAwait(false); |
There was a problem hiding this comment.
Sorry, but this is not the way how we define and send packets.
AI falls into this trap all the time, btw ;-)
- Extend
src\Network\Packets\ServerToClient\ServerToClientPackets.xml - Rebuild the packets project
- Now there should be a Send... extension method for the connection, which takes the required values as parameters.
There was a problem hiding this comment.
Did you consider adding a (feature) plugin for this whole feature? Then you could put this configuration into the plugin configuration. I don't want to add too many specialized configurations to the GameConfiguration.
There was a problem hiding this comment.
Can this be more configurable to be more generic and not limited to one NPC type?
Like adding these options:
- Accept item
- Npc (MonsterDefinition)
A plugin could contain a list of this configurations.
| player.OpenedNpc = null; | ||
| await player.PlayerState.TryAdvanceToAsync(PlayerState.EnteredWorld).ConfigureAwait(false); |
There was a problem hiding this comment.
You may want to use the CloseNpcDialogAction instead:
- packet handlers should not have game logic directly
- The close action implements additional logging and checks
| (i.Definition?.Group == 14 && i.Definition?.Number == 21) || // Rena | ||
| (i.Definition?.Group == 14 && i.Definition?.Number == 30) || // Event Chip | ||
| (i.Definition?.Group == 14 && i.Definition?.Number == 31) // Stone | ||
| ); |
There was a problem hiding this comment.
This looks a bit strange to me. Isn't golden archer just about Rena? Why are other items accepted?
Could they be configured, instead?
| /// <summary> | ||
| /// Gets or sets the number of registered renas for the Golden Archer (progress towards next reward). | ||
| /// </summary> | ||
| public int RegisteredRenas { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the total number of registered renas for the Golden Archer (all-time counter for rankings). | ||
| /// </summary> | ||
| public int TotalRegisteredRenas { get; set; } | ||
|
|
There was a problem hiding this comment.
Just an idea... instead of adding such 'attributes' here, what about adding two attribute definitions in Stats and adding them as Character.Attributes?
This way they could also be used somehow in custom formulas ;-)
| /// <summary> | ||
| /// Gets or sets the zen reward from the Golden Archer. | ||
| /// </summary> | ||
| public int RewardZen { get; set; } = 5000000; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the chance of dropping an item from the <see cref="RewardItems"/> list. A value between 0.0 and 100.0 (e.g. 50 for 50%). | ||
| /// </summary> | ||
| [System.ComponentModel.DataAnnotations.Display(Name = "Item Drop Chance (%)")] | ||
| public double ItemDropChance { get; set; } = 100.0; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the possible items that can drop. If an item drops, one is picked randomly from this list. | ||
| /// </summary> | ||
| public virtual ICollection<ItemDefinition> RewardItems { get; protected set; } = new List<ItemDefinition>(); |
There was a problem hiding this comment.
Can this be replaced by reference to DropItemGroup?
| <ItemGroup> | ||
| <PackageVersion Include="BCrypt.Net-Next" Version="4.0.3" /> | ||
| <PackageVersion Include="BenchmarkDotNet" Version="0.15.8" /> | ||
| <PackageVersion Include="BlazingModal" Version="1.0.8" /> |
| <PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.10"> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| </PackageVersion> |
There was a problem hiding this comment.
Why? It's already added transitive by Microsoft.EntityFrameworkCore.Tools in the right version.
Description
This PR introduces the Golden Archer feature, including full database configuration persistence, Web AdminPanel support, database seeding, and unit test coverage.
Features & Logic Overview
14, 21), Event Chip (14, 30), or Stone (14, 31) at NPC No. 236 (Golden Archer).RegisteredRenas) and lifetime statistics (TotalRegisteredRenas).RewardItemslist according to the specified drop probability.Web AdminPanel & Persistence Fixes
GoldenArcherConfigurationmodel exposed as a distinct fieldset in AdminPanel.RequiredRenas(Default: 1)RewardZen(Default: 5,000,000)ItemDropChance (%)(0.0% to 100.0%)RewardItemslistAddGoldenArcherConfigurationPlugInupdate plugin and added default seeding inGameConfigurationInitializerto ensure settings persist across server restarts and new database setups.Unit Tests
Added unit test suite in
tests/MUnique.OpenMU.Tests/GoldenArcherTest.cs(4/4 Passed - 100%):RegisterAsync_NoNpcOpened_DoesNothingAsyncRegisterAsync_NoRenasInInventory_ShowsMessageAsyncRegisterAsync_WithRena_IncreasesRegisteredRenasAsyncRegisterAsync_ReachesThreshold_ResetsCounterAndRewardsZenAsyncSmall fix in docker-compose.yaml
How to Test
Video:
https://github.com/user-attachments/assets/8937b26a-f705-407b-8898-d542931b6246