port.grp_math pins the 40250 conventions: D3DXVec3Rotation applies the
inverse rotation, GetRotationFromMatrix returns negated Z*X*Y angles, and
CGraphicColor defaults to opaque white.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds CreateSemaphore/ReleaseSemaphore/WaitForSingleObject/CloseHandle/
SetThreadPriority/_beginthreadex to Win32Crt; port.file_loader_thread covers
the shims, CThread and both the un-Created (40250 live) and Created loader.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CPythonGraphic::SaveScreenShot queues a readback of the next presented
frame (ScreenShotHost -> VulkanWindow::request_frame); WriteScreenShot runs
the rest of 40250's function verbatim (X8R8G8B8 rows, SaveJPEG, EXIF tag).
jpeg_save is encoded with stb_image_write. SHGetSpecialFolderPath returns
$HOME/Documents (else cwd); CreateDirectory/_access/jpeg_save accept '\\'.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The CSpeedTreeRT stand-in now returns the collision objects stored in
the .spt (12000 section: spheres and cylinders) instead of one fixed trunk
cylinder, and takes leaf texture rects from the 10000 section instead of
hand-picked atlas rects (trees without leaf maps use the frond rect).
SpeedGrass/BoundaryShapeManager are N_A (no 40250 caller).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copy SoundBase/SoundData/SoundInstance*/SoundManager*/Type from 40250 and
implement the AIL_* calls they make in MilesAil.cpp (2D pan, 3D distance and
listener pan, threaded stream decode, loop counts). The SDL host drains the
mixer. CSoundManager is created/updated/destroyed where 40250 does it and the
old AudioCommands bridge is removed. Port-map MilesLib 142/142 PORTED.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Curve::eval scanned every knot to find the first one past t; long animation
tracks made that the top of CPythonCharacterManager::Deform. Knots are checked
for ascending order at load and unsorted curves keep the linear scan, so the
chosen knot is unchanged. Desktop live game: Deform samples 93 -> 58.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A geometry-cache hit moved every vertex vector out of the cache into the draw
(deep copy of positions/normals/uv/diffuse/indices/bones each frame). The cache
now lends its vectors to the frame's first draw of that geometry and takes them
back in Render3DBeginFrame; later draws of the same key+revision in the frame
(terrain splat layers, shadow-map pass) are marked shared_geometry and carry no
vectors -- the native host looks the GPU geometry up by key+revision, and draw
captures expand them (Render3DExpandSharedGeometry). Index reads reuse a scratch
buffer. Desktop live game: RenderGame rnd 1.7 -> 1.2 ms, no visual change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Draws recorded inside CPythonApplication::RenderGame are marked Render3DDraw::scene and
drawn by a scene pass compatible with pass_ into a reduced-resolution image, composited
where RenderGame drew; the UI stays full resolution. --render-scale / MT_RENDER_SCALE,
desktop default 1.0 (unchanged path).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
itemdesc_translate_zh.tsv maps the English description/summary text to Chinese (1,788 entries,
every itemdesc row covered). build_zh_locale.py replaces the cells and wraps Chinese into
26-byte lines joined by ' |', which 40250's Western SplitDescription turns into forced line
breaks; the 50307 overlay row is wrapped the same way.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CShopEx::Buy rejected price 0 as a hack; allow it like CShop::Buy already does.
Rebuilt and deployed game on 203; buying the box for 0 verified.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Server (tools/server/hunt-set, deployed on 203): game patch adds quest function
item.set_attribute (CItem::SetForceAttribute); quest hunt_set turns the unused
ITEM_QUEST 50307 into a per-class box of eight +9 pieces with five max-value
attributes each. Item mall sells it for 2,000,000.
Client locale: name overlay plus whole-row overlays for item_list.txt (gift-box
icon) and itemdesc.txt (build_zh_locale.py ROW_FILES).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The server checks a move only for its distance and speed, so the local
character skips the background-object and map-attribute collision.
Other characters and doors still block it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
skilldesc.txt takes Longju's name, description and condition columns
and its affect texts where their format arguments match 40250's; a
reviewed overlay fills the gaps and renames the empire languages.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
support_skills_max.quest sets 121/122/124/126-129/131 to their skill_proto
max, the horse to level 30 (skill 130) and the horse skills 137-139 (140 for
assassins), once per character. install.sh adds it to locale_list and
pc.set_skill_level to quest_functions (qc rejects it otherwise), then make.py.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ring-warp/: ring_warp.quest without use count or cooldown (the ring is never
used up) + install.sh (GBK, make.py, item name 移动戒指).
npc-shops: [page] lines in items.tsv make an extended shop written to
shop_table_ex.txt; item-mall is now 增益 (29) + 道具 (12, incl. 70058 at 1 gold).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
128 literals written directly in the quest sources, outside gameforge.*;
build_zh_quest_inline.py patches them in GBK before make.py (qc) on the server.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
40250 quests say gameforge.<quest>.<key>, loaded by game from
share/locale/<locale>/translate.lua at start. build_zh_translate_lua.py
lays the reviewed data/zh_40250/quest_translate_zh.tsv over the English
file line by line (nested tables kept), re-wraps at the quest window
width, and writes GBK with 0x5C trail bytes doubled. Deployed on 203;
blacksmith dialog shows Chinese.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The character window's tabs and stat labels (VIT/INT/Character Status,
Status/Abilities/...) are baked into locale/<xx>/ui/windows/windows.dds;
the zh build only overlaid text keys, so they stayed English. The folder
is now replaced as a whole (its .sub files index its own atlas).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tools/server/item-mall-shop becomes tools/server/npc-shops with one
directory per shop (shop.conf + items.tsv) and install.sh <shop dir>.
New mount shop: 35 ride tickets on NPC 20368 (renamed 坐骑商人 via
NPC_NAME -> mob_names.txt) beside the stable boy in a1/b1/c1. Verified
on 203: 35 slots at the drafted prices, bought + used 71114 -> mounted.
zh overlay: 71118 虎坐骑券(黄), 20368 坐骑商人.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the macOS-only AudioToolbox decoder with mt_host::decode_audio: a
RIFF/WAVE PCM parser plus vendored dr_mp3, resampled/remixed to 44.1 kHz
stereo float with SDL_ConvertAudioSamples. macOS and Android now share one
path; the AudioToolbox link is gone.
BGM is no longer cached in clips_ (a 5-minute track is ~100 MB of float):
only the playing track is kept, and a new one decodes on a worker thread
(the pack read stays on the main thread) so map changes do not stall.
host.audio_decode test: synthetic wav layouts + all 1578 pack .wav, 9 pack
.mp3 and 25 Client/BGM .mp3 decode (7060 s of audio in ~3.6 s on M2).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- test/: bgfx/Godot render goldens and compare shots nothing reads any more;
the Granny oracle result m2-numeric.json moves to oracle/
- formats/: only the .spt sniffer was still linked; it moves into
platform/SpeedTreeLib, the rest and tools/map_probe go
- bgm/ duplicated Client/BGM byte for byte; tools/root archived root scripts
that root.epk already holds; extension/src/proto had no build reference
- GEMINI.md duplicated AGENTS.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Godot-era batch records move verbatim to docs/archive/PORT-HISTORY.md.
README and THIRD-PARTY no longer mention submodules.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>