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>
- Untrack build-debug/ and build-asan/ (CMake trees committed by mistake in
c9389431) and ignore them.
- Remove extension/src/net and extension/src/pack (m2dev protocol and XChaCha
pack format, superseded by the ported 40250 code), their 18 unregistered tests
and the net/pack tools, the MT_BUILD_NET_TOOLS probe, and the libsodium and zstd
submodules they alone used.
- The fake login server's classic cipher, sequence table and wire layouts move to
extension/tests/classic/ (still used by port.login_flow, port.packet and the
native client's offline mode).
- Archive Godot/m2dev-era plans under docs/archive/; THIRD-PARTY.md updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- MtFrameRate setting (30 / 60 default / display max) as app.Get/SetFrameRateMode,
with a "画面帧率" row injected into the system option dialog (mt_framerate); saved
in the SDL pref path.
- FrameRatePolicy in the live loop: 30 fps after 15 s without input (not while auto
hunting), display switched to 60 Hz unless the highest mode, ADPF
setPreferPowerEfficiency, vsync pacing when the display already runs at the target.
--fps-mode / --idle-fps / --idle-after; --fps-cap / --refresh-rate still pin a test run.
- Perf log: battery current/voltage/power, plugged, fps_mode, idle columns;
perf_summary groups power by mode.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Auto hunt (client-only): PythonPlayerAutoHunt.cpp + AutoHuntScript.inc as the
embedded mt_autohunt module, AUTO touch button, F9/F8.
- Account registration: tools/40250/register_server.py (rc.d mt_register, :11080)
inserts into account.account; net.RegisterAccount/GetRegisterAccountResult
(PythonAccountRegister.cpp) and the mt_register login-window dialog
(RegisterScript.inc).
- --py-exec also runs in --login-screen mode for scripted login-screen tests.
- Touch controller, window manager and render command updates for the
Android native client.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- FreeType: add the cff/psaux/pshinter modules (from the pinned 2.13.3
tarball, same sha256). Android's only CJK font is the CFF2
NotoSansCJK-Regular.ttc, which the TrueType-only build could not open,
so every Chinese glyph drew as a box.
- Font oversample rounds the UI density up: Android's 1760x800 UI on a
2376x1080 screen is 1.35, which rounded to 1x bilevel glyphs stretched
1.35x. Now 2x anti-aliased glyphs are scaled down. macOS 2.0 unchanged.
- MainActivity: a launcher start (no intent args) opens the login screen
against 192.168.21.203 instead of auto-logging into the in-process fake
server; explicit args still select the fake-server smoke flow.
- build-android-native.sh: ANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON for SDL3
and libmain (LOAD alignment 0x1000 -> 0x4000), with a stamp that
rebuilds a cached pre-flag SDL3. Clears Android's 16 KB compat warning.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
eterpack_pack writes locale packs in the original format (COMPRESS
entries, LZO+TEA index), and build_zh_locale.py packs locale/zh into
locale_zh.eix/.epk registered in pack/Index instead of leaving loose
files.
The reviewed translations for names and keys still in English are
kept apart from the server snapshot in data/zh_40250/*_zh_overlay.txt
(1,607 items, 231 mobs/NPCs, 45 locale_game keys) and override it at
build time. Only YMIR, the coordinate-named warp markers and the empty
TOOLTIP_UNSEAL_LEFT_TIME remain English.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build-android-native.sh downloads SDL 3.4.16 (sha256-checked), builds
libSDL3.so and libmain.so (native_render + port_platform + embedded
Python) at API 24, and wraps them in the SDLActivity shell under
android-native/ (package org.metin2port.client). push-android-client.sh
copies the 40250 Client directory into the app's files/ with run-as
(--locale XX selects locale_XX.cfg). port_logic links with
--no-dependent-libraries on ELF targets so the verbatim
`#pragma comment(lib, ...)` lines do not break lld.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mt_codepage implements code pages 874/932/936/949/950/1250-1258 from
Microsoft's bestfit<cp>.txt sources (script/gen_codepage_tables.py,
SHA-256 pinned). Win32Crt's MultiByteToWideChar/WideCharToMultiByte/
IsDBCSLeadByteEx and net/text_codec use it, so the Android API 24 build
no longer depends on iconv. port.codepage checks every table against
its source file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- CGraphicFontTexture rasterises glyph pages at the swapchain density
(UISetFontOversample, MT_FONT_OVERSAMPLE) with anti-aliased coverage;
metrics, packing and UVs stay the 40250 1x values. Default 1 keeps the
verbatim bilevel path (Godot unchanged).
- native.frag: sharp-bilinear sampling for magnified UI textures.
- Multisampled colour/depth with a resolve into the swapchain (MT_MSAA,
default 4); stats line reports msaa=N.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 40250 wire structs hold Win32 long (4 bytes) sockets; on LP64 `long`
is 8, so each TShopItemData was too wide and SHOP_SUBHEADER_GC_START/_EX
misread every item after the first. Pin the wire size with a static_assert.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DXT DDS textures upload the file's own mip levels like 40250
CGraphicImageTexture::CreateDDSTexture (max(1, dwMipMapCount), level i read
at sum(dwLinearSize>>2k), Copy of dwLinearSize>>2i bytes) instead of a
regenerated chain. Non-DDS images keep the D3DX_DEFAULT full chain and mem:
textures get one level. The invented is_ui_tex no-mip rule (icon/, ui/,
locale/, <=128px) is deleted. dxt_decode_test is registered in ctest with
mip-level cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Process now runs 40250's render-time / face-count block and sets view
distance set 0 each frame (25600 under 5000 faces, else scaled by render
time, or the forced range). SetForceSightRange and SkipRenderBuffering are
ported from stubs; the invented SetCursorPosition in UpdateGame is removed.
Port-map boilerplate notes replaced; Destroy recorded as DIVERGENT.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SetGamma, RenderCoolTimeBox, RenderUp/DownButton and GetAvailableMemory are
transliterated from 40250 in place of stubs. The cooldown fan is emitted as
untextured polygon UI commands (native_render + python_ui_surface.gd draw
Bar+quad as a polygon); D3D8 shim gains SetGammaRamp/D3DGAMMARAMP.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 0.1 s wall-clock waits could fit a single frame under ctest -j3, so the
shopkeeper pick missed about one run in four.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MapOutdoorRenderHTP.cpp is the full 40250 source behind the native-terrain
gate: no invented texture-0 fallback, first-splat stage-1 ALPHAOP DISABLE,
GetNumTextures() bound, 40250 shadow-pass states (FOGCOLOR white, CLAMP,
TEXTURE1 m_matDynamicShadow). Fixes the white far-terrain band.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the platform_stub skeleton (every member unimplemented) with the 40250 source, so
guild marks in text tails and mark boxes load and draw.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Delete the platform proxy tree renderer and copy SpeedTreeWrapper, SpeedTreeForest,
SpeedTreeForestDirectX8, SpeedTreeConfig.h and VertexShaders.h from 40250. The SDK
SpeedTreeRT.h public API becomes the shim; the closed CSpeedTreeRT is reimplemented in
platform/SpeedTreeLib/SpeedTreeRT.cpp (procedural geometry, static lighting, single LOD,
DIVERGENT). Shims gain the D3D8 vertex shader declaration tokens, D3D_OK,
CreateVertexShader/DeleteVertexShader, ID3DXBuffer/D3DXAssembleShader, MessageBox and
__min/__max.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>