Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
5f192eb
Send experience_update to client on XP gain and level-up
barrelin-oss Aug 30, 2026
15b132e
Bot autonomy stack: party JSON protocol, perf fixes, city habitabilit…
barrelin-oss Aug 30, 2026
7618059
Restore 12 spells blocked by unmapped legacy magic types
barrelin-oss Aug 30, 2026
181078a
Fix loot table and shop item references (audit vs items.yaml)
barrelin-oss Aug 30, 2026
0e064f9
Fix ECS entity id vs player_id confusion across magic, combat, effects
barrelin-oss Aug 30, 2026
735df87
Mage bots: fix entity-id player lookups in magic_system, grant starti…
barrelin-oss Aug 30, 2026
967c46f
Expose player regen pacing in server.yaml (regen section)
barrelin-oss Aug 30, 2026
b8a5cce
Add dynamic ground-field subsystem (Spike-Field, Ice-Storm, Cloud-Kill)
barrelin-oss Aug 30, 2026
ea49d5d
Add final 7 legacy magic types - all spells now load
barrelin-oss Aug 30, 2026
709100b
Fix crafting/fishing potion references - boot is now warning-free
barrelin-oss Aug 30, 2026
536af07
Merge master (709100b) into entity-id audit branch
barrelin-oss Aug 30, 2026
ea594cb
Fix hunger int8 overflow and stock food in general shops
barrelin-oss Aug 31, 2026
b1ad5ac
Bots: eat, sync MP, and stop deadlocking on regen
barrelin-oss Aug 31, 2026
ea92e88
Set owner on shop-bought items, and log equip failures
barrelin-oss Sep 1, 2026
9796eb0
Fix shop buy_categories to match the real item numbering
barrelin-oss Sep 1, 2026
0bbe376
Bots: sell loot, normalize item payloads, equip what they buy
barrelin-oss Sep 1, 2026
29c30e7
Expose item requirements in shop catalog, log silent refusals
barrelin-oss Sep 1, 2026
2132a7b
Bots: respect item requirements and equip before resting
barrelin-oss Sep 1, 2026
cf91879
Bots: cap fleeAndRecover so a stalled regen cannot freeze them
barrelin-oss Sep 2, 2026
3631175
Add stat_point_request so awarded points can be spent
barrelin-oss Sep 2, 2026
b61b835
Bots: spend stat points on a per-role policy
barrelin-oss Sep 2, 2026
262a5a0
Add a spell learning flow so raising INT can unlock spells
barrelin-oss Sep 2, 2026
e2dfed1
Bots: learn spells once their INT reaches the requirement
barrelin-oss Sep 2, 2026
98b12bc
Persist the item name so the items table is readable
barrelin-oss Sep 2, 2026
cdaf68b
Wire NPC dodge_rate so attacks stop always landing at 99%
barrelin-oss Sep 2, 2026
2ccfcfa
Distinguish a resolved miss from a rejected attack
barrelin-oss Sep 2, 2026
dbb8dda
Bots: log misses and report a hit rate
barrelin-oss Sep 2, 2026
f036f42
Spawn points: respawn_time_ms from mapdata, one due time per death
barrelin-oss Sep 5, 2026
0ef3e4d
Bots: one potion per cooldown, only after HP/MP moved since the last one
barrelin-oss Sep 5, 2026
9fc0603
Attack pace per weapon speed and STR, reported as attack_interval_ms
barrelin-oss Sep 5, 2026
acd7f7e
Fix party kills paying zero XP to everyone
barrelin-oss Sep 5, 2026
5340298
Tests: npc registry maps defense_ratio to dodge_rate
barrelin-oss Sep 5, 2026
609bd35
City hall quests end to end: loader, quest_* protocol, rewards, bots
barrelin-oss Sep 5, 2026
d4eed80
GM commands /reloadconfig and /shutdown
barrelin-oss Sep 5, 2026
4a49ce3
Docs: PROGRESS entries for the 2026-09-04 work, drop doors/chests
barrelin-oss Sep 5, 2026
bf74271
Bots: stop looping on loot they cannot carry
barrelin-oss Sep 5, 2026
fb62939
Bots: gm-smoke.mjs, live check of /reloadconfig and /shutdown
barrelin-oss Sep 5, 2026
e60489a
Bots: read hunger only from hunger_update
barrelin-oss Sep 5, 2026
3369e22
Bots: report the current action, detour around blocked tiles, skip un…
barrelin-oss Sep 5, 2026
56c078f
Pass max_connections to ixwebsocket; bots reconnect on socket close
barrelin-oss Sep 5, 2026
812062e
Spawn inside the generator rect; NPC home is the spawn tile
barrelin-oss Sep 5, 2026
d7105d8
Bots: retreat from swarms instead of tanking on potions
barrelin-oss Sep 5, 2026
ccd6623
NPCs no longer wander out of their generator rect
barrelin-oss Sep 5, 2026
c5d3a09
Bots: reset per-session state on reconnect; lighter test arenas
barrelin-oss Sep 5, 2026
9c728d8
Legacy MapData for all maps, npc_name in spawners, periodic random mo…
barrelin-oss Sep 5, 2026
a8cc772
Bots: map-peek clears the view after a GM teleport
barrelin-oss Sep 5, 2026
c5c29d1
NPC registry: passive creatures (Rabbit, Cat, Unicorn) are huntable m…
barrelin-oss Sep 5, 2026
2e1cacf
GM teleports sync the client
barrelin-oss Sep 5, 2026
5def3f2
Bots: log the raw response when a move is refused without an error code
barrelin-oss Sep 5, 2026
bc6fd4c
The 8 NPC templates the converted MapData needed
barrelin-oss Sep 5, 2026
e8e48f4
Legacy MapData read with the original Korean numbering for NPC types 70+
barrelin-oss Sep 5, 2026
daee2aa
The fence: a PreToolUse hook that refuses what a session must not dec…
barrelin-oss Sep 5, 2026
05d7b5c
Legacy items and NPCs merged, spot type 28, bots that enter dead
barrelin-oss Sep 5, 2026
d319b76
Dialog option actions are names on the wire
barrelin-oss Sep 5, 2026
bacd816
The bank is reachable; /setgold tells the client; quest-smoke cleans …
barrelin-oss Sep 5, 2026
1c9130e
Character list carries the equipment visuals; Olympia NPC templates
barrelin-oss Sep 5, 2026
9f993fa
Olympia quest line, item descriptions and a reference of Olympia's me…
barrelin-oss Sep 7, 2026
95017e9
Olympia mechanics: specialties, elites, daily quests, treasure chests…
barrelin-oss Sep 7, 2026
e769fd4
Items carry their description on the wire
barrelin-oss Sep 7, 2026
3bb7602
Potions get their descriptions
barrelin-oss Sep 7, 2026
4c0685c
New bag items land on a random spot, not the corner
barrelin-oss Sep 7, 2026
602f76d
Super attacks over JSON, weapon class on items, stationary dummies
barrelin-oss Sep 7, 2026
c2ff3c4
Enforce gender_limit on equip
barrelin-oss Sep 7, 2026
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
24 changes: 24 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ project(hgserver
LANGUAGES CXX
)

# Windows: stop windows.h from defining min/max macros (they clobber std::min/std::max)
if(WIN32)
add_compile_definitions(NOMINMAX WIN32_LEAN_AND_MEAN)
endif()

# Output directories - all binaries go to bin/
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_SOURCE_DIR}/bin)
Expand Down Expand Up @@ -103,6 +108,7 @@ set(PROTOCOL_SOURCES
set(WORLD_SOURCES
src/world/map.cpp
src/world/world_subsystem.cpp
src/world/dynamic_object_system.cpp
)

set(ENTITY_SOURCES
Expand Down Expand Up @@ -162,6 +168,15 @@ set(SKILL_SOURCES

set(QUEST_SOURCES
src/quest/quest_system.cpp
src/quest/quest_loader.cpp
)

set(SPECIALTY_SOURCES
src/specialty/specialty_system.cpp
)

set(ACHIEVEMENT_SOURCES
src/achievement/achievement_system.cpp
)

set(SOCIAL_SOURCES
Expand Down Expand Up @@ -227,7 +242,9 @@ set(BRIDGE_SOURCES
src/bridge/handlers/game_handlers.cpp
src/bridge/handlers/game_handlers_movement.cpp
src/bridge/handlers/game_handlers_combat.cpp
src/bridge/handlers/game_handlers_quest.cpp
src/bridge/handlers/game_handlers_npc.cpp
src/bridge/handlers/game_handlers_treasure.cpp
src/bridge/handlers/game_handlers_shop.cpp
src/bridge/handlers/game_handlers_chat.cpp
src/bridge/handlers/game_handlers_social.cpp
Expand Down Expand Up @@ -265,6 +282,8 @@ add_library(hgserver_core STATIC
${INVENTORY_SOURCES}
${SKILL_SOURCES}
${QUEST_SOURCES}
${SPECIALTY_SOURCES}
${ACHIEVEMENT_SOURCES}
${SOCIAL_SOURCES}
${WAR_SOURCES}
${PERSISTENCE_SOURCES}
Expand Down Expand Up @@ -352,7 +371,12 @@ add_executable(hgserver_tests
tests/test_npc.cpp
tests/test_item.cpp
tests/test_combat.cpp
tests/test_attack_timing.cpp
tests/test_quest_loader.cpp
tests/test_specialty.cpp
tests/test_achievement.cpp
tests/test_magic.cpp
tests/test_dynamic_objects.cpp
tests/test_inventory.cpp
tests/test_bank_storage.cpp
tests/test_skill.cpp
Expand Down
37 changes: 37 additions & 0 deletions bin/game_configs/achievements.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# achievements.yaml - achievements (after the Helbreath Olympia client: General / PvM / PvP / Challenges).
# kind: kills_total | kills_type (param = npc sprite type) | elites_killed | quests_completed | gold_looted |
# chests_opened | level | specialties_leveled. target = value that unlocks it. title = optional title.
achievements:
# --- General ---
- {id: 1, category: general, kind: level, target: 20, points: 5, name: "Apprentice", description: "Reach level 20"}
- {id: 2, category: general, kind: level, target: 50, points: 10, name: "Veteran", description: "Reach level 50", title: "Veteran"}
- {id: 3, category: general, kind: level, target: 100, points: 20, name: "Champion", description: "Reach level 100", title: "Champion"}
- {id: 4, category: general, kind: level, target: 140, points: 30, name: "Hero of the Land", description: "Reach level 140", title: "Hero"}
- {id: 5, category: general, kind: level, target: 180, points: 50, name: "Max Level", description: "Reach level 180", title: "Legend"}
- {id: 10, category: general, kind: quests_completed, target: 1, points: 5, name: "Errand", description: "Complete a quest"}
- {id: 11, category: general, kind: quests_completed, target: 10, points: 10, name: "Diplomacy I", description: "Complete 10 quests"}
- {id: 12, category: general, kind: quests_completed, target: 50, points: 20, name: "Diplomacy II", description: "Complete 50 quests", title: "Diplomat"}
- {id: 13, category: general, kind: quests_completed, target: 200, points: 40, name: "Diplomacy III", description: "Complete 200 quests", title: "Envoy"}
- {id: 20, category: general, kind: gold_looted, target: 10000, points: 5, name: "Gold Loot I", description: "Loot 10,000 gold from monsters and chests"}
- {id: 21, category: general, kind: gold_looted, target: 100000, points: 10, name: "Gold Loot II", description: "Loot 100,000 gold"}
- {id: 22, category: general, kind: gold_looted, target: 1000000, points: 25, name: "Gold Loot III", description: "Loot 1,000,000 gold", title: "Wealthy"}
- {id: 30, category: general, kind: chests_opened, target: 1, points: 5, name: "Finders Keepers", description: "Open a treasure chest"}
- {id: 31, category: general, kind: chests_opened, target: 25, points: 15, name: "Treasure Hunter", description: "Open 25 treasure chests", title: "Treasure Hunter"}
- {id: 32, category: general, kind: chests_opened, target: 100, points: 30, name: "Chest Whisperer", description: "Open 100 treasure chests"}
# --- PvM ---
- {id: 100, category: pvm, kind: kills_total, target: 1, points: 5, name: "First Blood", description: "Kill your first monster"}
- {id: 101, category: pvm, kind: kills_total, target: 1000, points: 10, name: "Hunter", description: "Kill 1,000 monsters"}
- {id: 102, category: pvm, kind: kills_total, target: 10000, points: 20, name: "Slayer", description: "Kill 10,000 monsters", title: "Slayer"}
- {id: 103, category: pvm, kind: kills_total, target: 100000, points: 40, name: "Exterminator", description: "Kill 100,000 monsters", title: "Exterminator"}
- {id: 110, category: pvm, kind: elites_killed, target: 1, points: 10, name: "Elite Hunter", description: "Kill an elite monster"}
- {id: 111, category: pvm, kind: elites_killed, target: 50, points: 25, name: "Elite Bane", description: "Kill 50 elite monsters", title: "Elite Bane"}
- {id: 120, category: pvm, kind: specialties_leveled, target: 1, points: 5, name: "Specialist", description: "Gain a specialty level"}
- {id: 121, category: pvm, kind: specialties_leveled, target: 25, points: 25, name: "Master of Beasts", description: "Gain 25 specialty levels", title: "Beastmaster"}
- {id: 130, category: pvm, kind: kills_type, param: 10, target: 5000, points: 15, name: "Slime Slayer", description: "Kill 5,000 Slimes", title: "Slime Slayer"}
- {id: 131, category: pvm, kind: kills_type, param: 14, target: 5000, points: 15, name: "Orc Slayer", description: "Kill 5,000 Orcs", title: "Orc Slayer"}
- {id: 132, category: pvm, kind: kills_type, param: 28, target: 3000, points: 20, name: "Troll Slayer", description: "Kill 3,000 Trolls", title: "Troll Slayer"}
- {id: 133, category: pvm, kind: kills_type, param: 13, target: 3000, points: 20, name: "Cyclops Slayer", description: "Kill 3,000 Cyclops", title: "Cyclops Slayer"}
- {id: 134, category: pvm, kind: kills_type, param: 57, target: 5000, points: 20, name: "Frog Catcher", description: "Kill 5,000 Giant Frogs"}
- {id: 135, category: pvm, kind: kills_type, param: 31, target: 2000, points: 25, name: "Demon Slayer", description: "Kill 2,000 Demons", title: "Demon Slayer"}
- {id: 136, category: pvm, kind: kills_type, param: 52, target: 1000, points: 25, name: "Gargoyle Breaker", description: "Kill 1,000 Gargoyles"}
- {id: 137, category: pvm, kind: kills_type, param: 65, target: 2000, points: 25, name: "Ice Breaker", description: "Kill 2,000 Ice Golems"}
139 changes: 137 additions & 2 deletions bin/game_configs/dialogs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
# close - end dialog
# open_shop - open the NPC's shop interface
# open_bank - open bank deposit/withdraw interface
# open_quests - open quest interface (stub)
# open_quests - list the quests this officer offers (quest_list_response push)
# offer_citizenship - faction enrollment (stub)
# select_crusade_job - crusade role selection (stub)
# claim_rewards - claim quest/kill rewards (stub)
# claim_rewards - turn in every finished quest from this officer
#
# Options with 'next' navigate to another node (goto_node action).
# Options with 'action' trigger the specified action.
Expand All @@ -21,6 +21,7 @@ dialogs:
start:
text: "I am the city hall officer. How may I help you?"
options:
- { label: "What tasks does the city have?", action: open_quests }
- { label: "I want to become a citizen", action: offer_citizenship }
- { label: "Crusade duties", next: crusade }
- { label: "I have completed a quest", action: claim_rewards }
Expand All @@ -39,6 +40,7 @@ dialogs:
start:
text: "I am the city hall officer of Elvine. What do you need?"
options:
- { label: "What tasks does the city have?", action: open_quests }
- { label: "I want to become a citizen", action: offer_citizenship }
- { label: "Crusade duties", next: crusade }
- { label: "I have completed a quest", action: claim_rewards }
Expand Down Expand Up @@ -93,3 +95,136 @@ dialogs:
options:
- { label: "Show me your wares", action: open_shop }
- { label: "Goodbye", action: close }

# Quest NPCs (legacy action_limit 6) - added 2026-09-05 with the converted MapData
McGaffin:
greeting: "Greetings. Aresden needs capable hands."
nodes:
start:
text: "I keep the task board for Aresden. Anything you finish, report back to me."
options:
- { label: "What tasks are there?", action: open_quests }
- { label: "I have completed a task", action: claim_rewards }
- { label: "Goodbye", action: close }

Perry:
greeting: "Ah, a volunteer."
nodes:
start:
text: "There is always work for those willing to leave the city walls."
options:
- { label: "What tasks are there?", action: open_quests }
- { label: "I have completed a task", action: claim_rewards }
- { label: "Goodbye", action: close }

Devlin:
greeting: "Speak quickly, I have little time."
nodes:
start:
text: "Elvine rewards those who serve it. Do you have something to report?"
options:
- { label: "What tasks are there?", action: open_quests }
- { label: "I have completed a task", action: claim_rewards }
- { label: "Goodbye", action: close }

# Command hall officer (cmdhall_1 / cmdhall_2)
Gail:
greeting: "Welcome to the command hall."
nodes:
start:
text: "The crusade is organised from here. What is your business?"
options:
- { label: "Select my crusade job", action: select_crusade_job }
- { label: "Goodbye", action: close }

# ---- Olympia persons: named quest givers (contents/persons.json + quests.json) ----
Enzu:
greeting: "Greetings, traveller."
nodes:
start:
text: "New around here? The lands south of the farms are a good place to learn to survive."
options:
- { label: "What tasks are there?", action: open_quests }
- { label: "I have completed a quest", action: claim_rewards }
- { label: "Goodbye", action: close }
Daara:
greeting: "Keep your voice down, the Orcs hear everything."
nodes:
start:
text: "This cave is crawling with Orcs. I could use a blade or two."
options:
- { label: "What tasks are there?", action: open_quests }
- { label: "I have completed a quest", action: claim_rewards }
- { label: "Goodbye", action: close }
Oxyia:
greeting: "Another one who wandered in."
nodes:
start:
text: "I keep watch here. The elite Orcs are not ready for hunting yet; come back later."
options:
- { label: "What tasks are there?", action: open_quests }
- { label: "I have completed a quest", action: claim_rewards }
- { label: "Goodbye", action: close }
Lagus:
greeting: "Hungry?"
nodes:
start:
text: "Scorpion is not bad once you get the skin off. Help me stock the pot."
options:
- { label: "What tasks are there?", action: open_quests }
- { label: "I have completed a quest", action: claim_rewards }
- { label: "Goodbye", action: close }
Lysio:
greeting: "The garden was beautiful once."
nodes:
start:
text: "Trolls and Unicorns have taken the garden. Aresden pays well for clearing it."
options:
- { label: "What tasks are there?", action: open_quests }
- { label: "I have completed a quest", action: claim_rewards }
- { label: "Goodbye", action: close }
Lisyo:
greeting: "The garden was beautiful once."
nodes:
start:
text: "Trolls and Unicorns have taken the garden. Elvine pays well for clearing it."
options:
- { label: "What tasks are there?", action: open_quests }
- { label: "I have completed a quest", action: claim_rewards }
- { label: "Goodbye", action: close }
Irenicus:
greeting: "Middleland answers to nobody. Good."
nodes:
start:
text: "Trolls, Cyclops, Ogres, Werewolves. Pick your enemy, I pay for all of them."
options:
- { label: "What tasks are there?", action: open_quests }
- { label: "I have completed a quest", action: claim_rewards }
- { label: "Goodbye", action: close }
Litzy:
greeting: "Hsss."
nodes:
start:
text: "The lizard eyes you, then the Cyclops behind you. It seems to want them gone."
options:
- { label: "What tasks are there?", action: open_quests }
- { label: "I have completed a quest", action: claim_rewards }
- { label: "Goodbye", action: close }
Fooldya:
greeting: "Cold enough for you?"
nodes:
start:
text: "Golems, Beholders and Frosts. Icebound has them all, and I want fewer of each."
options:
- { label: "What tasks are there?", action: open_quests }
- { label: "I have completed a quest", action: claim_rewards }
- { label: "Goodbye", action: close }
Moeru:
greeting: "You climbed this far. Impressive."
nodes:
start:
text: "The third floor is mine. Demons, Gargoyles and Dark Elves disagree; convince them."
options:
- { label: "What tasks are there?", action: open_quests }
- { label: "I have completed a quest", action: claim_rewards }
- { label: "Goodbye", action: close }
2 changes: 1 addition & 1 deletion bin/game_configs/fishing.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ fish_types:

# Rare items (non-fish)
- { type_id: 10, name: "Power Green Potion", item: PowerGreenPotion, difficulty: 40, lifespan_min: 25, visual_type: 3, weight: 3 }
- { type_id: 11, name: "Super Power Green Potion", item: SuperPowerGreenPotion, difficulty: 60, lifespan_min: 25, visual_type: 3, weight: 2 }
- { type_id: 11, name: "Super Green Potion", item: SuperGreenPotion, difficulty: 60, lifespan_min: 25, visual_type: 3, weight: 2 }
- { type_id: 90, name: "Ruby", item: Ruby, difficulty: 50, lifespan_min: 25, visual_type: 3, weight: 1 }
- { type_id: 95, name: "Diamond", item: Diamond, difficulty: 50, lifespan_min: 25, visual_type: 3, weight: 1 }
Loading