Applied only where no unqualified name in the block could be captured by
the introduced enumerators.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only local variables and definition parameters are renamed; shadowing
struct fields and enumerators in headers are left for a separate change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
make_event() lowercased the event name twice: cParser::getToken() already
folds ASCII via toLowerChar() (which intentionally leaves bytes >= 0x80
alone), then ToLower() ran std::tolower() over every byte on top of that.
With a non-"C" global locale, that second pass remaps cp1250 uppercase
accented letters (e.g. 0xAF -> 0xBF). Every lookup path - TTrack::AssignEvents(),
child-event resolution in multi_event, event-launcher name resolution -
normalizes only through the parser, so a registered name containing such a
letter can no longer be found: the track logs "can't find assigned event"
and the binding is silently dropped.
Removing the extra ToLower() makes the registration key match every lookup
site (ASCII-only folding, non-ASCII bytes compared verbatim), and matches
the direction toLowerChar()'s own comment already points at for UTF-8.
A whois with no triggering vehicle previously just wrote nothing to
the target cell with no trace in the log, which is a real pain to
diagnose from the scenery side (this is exactly the kind of thing that
cost real debugging time on a station script recently).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
whois_event::run_() dereferenced m_activator unconditionally in every
branch (this predates this PR). getvalues_event::run_() and
putvalues_event::run_() already guard the same way elsewhere in this
file; whois_event was missing it. Single early return covers every
branch, old and new.
The +8/+16/+24/+32/+40 (and the new +48) modes all pick the reporting
vehicle the same way: the activator's own Mechanik if it's the primary
driver, otherwise the consist's controlling vehicle (ctOwner) - so the
event still resolves correctly if a wagon happens to trigger it ahead
of its locomotive.
+0 (train name / stations left / stop flag) predates that pattern and
never got it: it required m_activator->Mechanik directly and silently
wrote nothing otherwise. A whois hook placed where the loco doesn't
necessarily lead (e.g. a train that reverses direction, or one being
propelled) can have a wagon trigger the event first and the memcell
stays empty, with no error - hard to diagnose from scenery side.
Same owner-selection, same guard semantics (still nothing written if
neither the activator nor its consist has a controller), only the
source of the vehicle it reads from is widened.
In TSegment there were two different formulas for a derivative. Most places called GetFirstDerivative() that used the direct formula from the curve points. However RaPositionGet() had its own calculation based on pre-computed cubic polynomial coefficients. This latter method is faster and simpler, so change GetFirstDerivative() to use it and change RaPositionGet() to just call GetFirstDerivative().
TSegment::GetTFromS() is a significant hotspot in the non-rendering part of the state_manager update (about 13%). This change introduces a FastGetTFromS() version that interpolates from precomputed values instead of doing the whole calculation on every call. Computing position from track distance is now done in constant time. This reduces the contribution to about 0.3%.
- Lua bindings are no longer using FFI in favor of the "classic" Lua C API.
- This makes it work properly on native Linux builds.
- Changed the Lua API slightly:
- Removed the `api.event_preparefunc()` function because it is no longer necessary. Instead, you can pass any function you want without preparing it first.
- Added an `api.event_exists()` function. Takes a single `name` argument.
- Any `api.find_*()` functions return `nil` instead of an userdata representing a null pointer when the requested object is not found.