Both units are the 40250 bodies; only the PDT-stream draw becomes
UIRenderAddImage (with the rendering mode). SCREEN/COLOR_DODGE were packed as
0x28 (INVDESTALPHA+ONE); 40250 uses INVDESTCOLOR+ONE (0x2A). OnIsType calls the
base OnIsType instead of 40250's recursing IsType. port.grp_resource covers the
quads, UVs, colour and blend mode.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CPythonNetworkStream::GamePhase throttles RefreshInventory/RefreshSafebox to
one call per 300 ms, so the bag slot could still be empty in the UI when the
test clicked it right after player state changed (~1 in 3 runs failed).
Also drops a leftover debug printf from CWindowManager::RunMouseMove.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-fno-strict-aliasing on the port targets: 40250 relies on MSVC's lack of
type-based alias analysis (DXTCImage reads Color8888 through DWORD*).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Host-side window records + message queue; WM_SIZE/WM_MOVE/WM_DESTROY sent
synchronously as Win32 does; PostQuitMessage also queues WM_QUIT. 64-bit
pointer casts ADAPTED. port.ms_window.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TextBar and DibBar verbatim over the FreeType GDI shim (+GetTextExtentPoint32A);
BlockTexture verbatim except Render, which records the clipped quad as a UI
image of the device CPU texture (UIRenderAddImageNamed). Notices now render;
port.text_bar covers block split, pixels, colour, ClearBar and TipBoard clip.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>