Server batch: experience_update, bot autonomy stack, legacy magic types, loot/shop audit - #1
Open
barrelin-oss wants to merge 11 commits into
Open
Server batch: experience_update, bot autonomy stack, legacy magic types, loot/shop audit#1barrelin-oss wants to merge 11 commits into
barrelin-oss wants to merge 11 commits into
Conversation
Adds a dedicated experience_update server->client message sent whenever a player gains XP (solo/party NPC kill XP, crusade rewards, login reward delivery). Carries experience_gained, new total experience and level; on level-up also levels_gained, new max_hp/max_mp/max_sp and unspent stat_points. Implemented as an experience_gain callback on player_system (fired from add_experience only when XP actually changes; silent at max level), wired in game_handlers so every add_experience call site is covered. Also fixes pre-existing MSVC build breaks: missing NOMINMAX include order in three bridge translation units and unguarded POSIX time functions (timegm/gmtime_r/localtime_r) in auth_system and a crusade test. Documented in docs/protocol/player.md, docs/JSON_PROTOCOL.md and docs/protocol/items.md; PROGRESS.md updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…y, headless bot client - JSON party messages (invite/accept/leave/update) + handlers and docs - Fix loot gold credited to ECS entity id instead of player_id - npc_registry YAML: parse gold_min/gold_max; npcs.yaml exp/gold keys fixed - Perf: O(1) player lookup in find_aggro_target; sees_all counter gates the far-admin scan in get_players_who_can_see - Case-insensitive .amd loading (ARESDEN/ELVINE were silently skipped), lowercase map names; characters start in their nation town - Registration rate limit configurable (auth.max_registration_attempts) - mapdata configs for default/aresden/elvine (spawners, merchants, initial points validated by tools/bot/scan-map.mjs) - tools/bot: headless bot client (hunt/loot/shop/party), gen-bots, scanner - posix_time_compat shim (pre-existing local build fix, included as-is) WIP checkpoint requested by worktree session relaxed-bell-f49dbe for merge. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The modernized magic_type enum was missing six values used by the HBX Magic.cfg data (14, 19, 21, 25, 26, 27), so 15 spells were skipped at load as invalid magic_type - including all high-circle attack magic (Blizzard, Meteor-Strike, Lightning-Strike, Bloody-Shock-Wave). - Add create_dynamic(14), damage_linear(19), damage_area_no_center(21), damage_area_sp_down(25), armor_break(26), ice_linear(27) to the enum - Implement line targeting (find_line_targets): Bresenham trace from caster toward target up to 12 tiles, faction and safe-zone filtered - damage_area_sp_down drains SP from player targets (effect2 dice, parsed into new sp_drain field) - armor_break deals pure damage (ignores_defense now honored via deal_pure_damage) - Cancellation becomes an offensive dispel (debuff category, removes the target effects) instead of hitting the utility stub - Fix 4 placeholder rows in magic.yaml copied from Lightning-Strike in the original cfg: Cancellation type 28, Resurrection 32, Illusion-Movement and Mass-Illusion-Movement 16 - create_dynamic spells (Spike-Field, Ice-Storm, Cloud-Kill) stay skipped with an info log until the dynamic ground-object subsystem exists (tracked in PROGRESS.md) - New registry test covering the legacy types; 2522 tests pass Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
loot_tables.yaml and shops.yaml were authored against a different item numbering than items.yaml - 22 referenced IDs did not exist (375+ validation warnings per boot) and several existing IDs pointed at the wrong item entirely (bosses dropping Tomato/Hoe/Garlic/Carrot as placeholders for Ice/Merien gear; potion shops selling a MagicNecklace; blacksmiths selling Dagger variants labeled ShortSword/MainGauche). Audited every reference against items.yaml using the intent recorded in the line comments: - Remapped 16 references whose intended item exists under another ID (BlackShadowSword 926, The_Devastator 923, BarbarianHammer 928, KlonessAxe 929, StormBringer 924, GiantSword 46, Flameberge+1 55, MagicWand(MS20) 256, KnecklaceOfStoneGolem 647, SapphireRing 336 ...) - Removed 32 pool entries whose intended item does not exist in this item set (AncientTablets, CritCandy, SSS/E.S.W/I.M.C manuals, XelimaCap/Hat/Helm, NecklaceOfXelima, DragonWand MS40, HolyBlade, GiantBattleHammer) plus the vegetable placeholders - Rewrote ~50 stale comments to the real item names (no behavior change) - shops.yaml: ShopKeeper-E/W sell RedPotion/BluePotion/GreenPotion (91/93/95); Gandlf/William sell Dagger/ShortSword/MainGauche (1/8/12) All references now resolve; no in-pool duplicates; 2522 tests pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Entity ids from the shared entity_manager are not player ids; casting one
to the other made get_player() return nullptr (or the wrong player) and
silently skipped guarded blocks. Standard fix: get_player_by_entity().
- magic_system: 21 lookup sites (mana/HP/SP costs, silenced/level/stat
checks, range and safe-zone checks, damage/heal scaling, SP drain,
resurrection, debuff resist); AOE/line target finders now push the real
p.ecs_entity instead of fabricating entity{player_id.value, 0}
- application: periodic heal/mana_drain/mana_restore effect ticks never
applied to players
- game_handlers_combat: spell-cast broadcast target resolution; respawn
invulnerability was keyed on a fabricated entity and never matched
- player_system::remove_player: effect cleanup used entity{id.value},
leaking active effects on logout
- wave4 legacy handlers: attack/cast fabricated caster entities from
player_id, so spell knowledge/cooldowns could never match the JSON path
- tests: fixtures now resolve the real ecs_entity (old fabricated form
only passed because fixtures spawn no NPCs, keeping counters aligned)
Legitimate uses kept: admin API player_id from the wire, inventory/trade
entity_id{pid.value} keying (consistent), spatial entity_id{index}.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ng spells
- magic_system.cpp: 20x get_player(player_id{entity.id}) -> get_player_by_entity;
mana cost, range checks, INT scaling and player-target effects were silently
skipped (ECS entity ids are not player ids)
- auth_handlers: grant qualifying spells on first login (magic_data '[]')
- tools/bot: mage role (Magic-Missile at range, self-Heal, mana potions),
combat-aware potion use, resting state that waits for natural regen
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tick_ms + hp/mp/sp_interval_ms wired through server_config into player_system_config (set_config was never called before — defaults only). Amounts keep the legacy formulas; intervals control how fast a full roll lands. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New world::dynamic_object_system managing temporary tile objects,
modernized from the legacy CDynamicObject system. The three create_
dynamic (type 14) spells now load and cast:
- Spike-Field: 25 spike traps in a 5x5 area; 2d4 physical damage when
an entity steps on a trap tile (movement-triggered, owner-immune)
- Ice-Storm: single field ticking 3d3+5 ice damage in 5x5 every ~1s,
applies freeze (20s) to players
- Cloud-Kill: single cloud ticking 1d8 poison damage in 3x3 (power 40
from cfg), applies poison DoT to players
Field data is parsed from magic.yaml effect3 {object type, rx, ry}
(legacy Magic.cfg effect10/11/12 columns). Spawn validation: walkable
tile, not a safe zone, one object per tile; area ticks skip players in
safe zones. Damage is attributed to the caster so kill credit flows
through the normal combat/death pipeline.
Protocol: new dynamic_object_spawn / dynamic_object_removed broadcasts
to visible players, plus re-send of visible fields on enter_game and
teleport. Documented in docs/protocol/combat.md and JSON_PROTOCOL.md.
Not ported (documented in PROGRESS.md): weather shortening fire
duration, fire-ice mutual duration reduction, coal fire spreading,
NPC-move spike triggers.
8 new tests; registry test updated for type-14 loading; 2530 tests pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Closes the magic type cycle: sp_down_area(5), sp_up_area(7), create(10), possession(15) and tremor(22) join the enum, removing the last invalid magic_type skips at boot (66/66 spells loadable). - Staminar-Drain: direct area SP drain (effect1 average); the sp_down_spot single-target variant now drains SP too instead of applying an empty effect. Celebrating-Light (zero dice) is a harmless visual cast. - Staminar-Recovery / Great-Staminar-Recov.: area ally SP restore; healing path branches on sp_up_spot/sp_up_area to restore SP instead of HP (sp_up_spot previously healed HP by mistake) - Create-Food: drops a random basic food (Baguette/Meat/Fish) at the caster via item_ops::drop_loot + ground item broadcast - Tremor: area earthquake damage 3d4+3 (legacy knockback not ported, documented) - Possession: accepted as no-op (legacy ground-item ownership does not exist in the modern server) - Fixed two more entity-id-as-player-id lookups found while wiring: on_spell_cast caster resolution (game_handlers_combat.cpp) and the healing apply_heal pid (magic_system.cpp) New registry test covering the five types; 2531 tests pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
recipes.yaml and fishing.yaml referenced potions from a different item set (same class as the loot/shop audit). Remapped by function, results are name-referenced: HealthPotion -> RedPotion, ManaPotion -> BluePotion, RevitalizingPotion -> GreenPotion (and Big variants); fishing rare catch SuperPowerGreenPotion -> SuperGreenPotion (391). Eliminates the last 7 registry warnings at startup. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Overlap with helbreathx-52 (20 magic_system lookup sites, on_spell_cast caster, healing apply_heal pid) resolved in favor of master. Remaining delta: AOE/line target fabrication, damage/heal scaling lookups, SP drain, debuff resists, application.cpp effect ticks, respawn invulnerability, logout effect cleanup, wave4 legacy handlers, test fixtures. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a dedicated
experience_updateserver->client message sent whenever a player gains XP (solo/party NPC kill XP, crusade rewards, login reward delivery). Carriesexperience_gained, new totalexperienceandlevel; on level-up alsolevels_gained, newmax_hp/max_mp/max_spand unspentstat_points.Implemented via an experience-gain callback on
player_system(fired fromadd_experienceonly when XP actually changes), wired ingame_handlersso every call site is covered. Includes protocol docs (docs/protocol/player.md,docs/JSON_PROTOCOL.md,docs/protocol/items.md), PROGRESS.md entry, and a new unit test. Also fixes pre-existing MSVC build breaks (NOMINMAX include order, unguarded POSIX time functions).Full test suite passes: 2521 tests OK.
🤖 Generated with Claude Code