When a ScriptClassDesc_t for is initialized (SCRIPTDESC), it recursively
invokes its parents initializers in order to obtain their pHelper
member.
Initialization is only done once, so repeated initialization is skipped.
Initialization includes assignment of a vector of ScriptHook_t's
(DEFINE_SCRIPTFUNC/BEGIN_SCRIPTHOOK), which must be initialized
beforehand.
Both of these use (static) globals; Within a translation unit,
initialization order is defined to be the same as the order of
declaration. So within a translation unit we must define all
ScriptHook_t's before the ScriptClassDesc_t using them.
A problem occurs with the parent initialization though, since there is
no defined order between translation units, meaning initialization of a
ScriptClassDesc_t can happen before its ScriptHook_t's, despite being
the correct order within its translation unit.
On MSVC it seems this issue is benign. On GCC/Linux however the
initialization of a ScriptHook_t essentially cleared whatever happened
during the initialization of the ScriptClassDesc_t, meaning many hooks
simply didn't work.
This situation is remedied by delaying the initialization of the
ScriptClassDesc_t's ScriptHook_t vector to only when the constructor of
it is invoked from its translation unit. This is accomplished simply by
adding a boolean parameter to the function (GetScriptDesc()) that is
true in the global constructor invocation, and false by default
(including when doing parent ScriptClassDesc_t initialization).
When false, a valid ScriptClassDesc_t pointer is still returned, which
is all that is needed for the initialization of the child
ScriptClassDesc_t. The value of the returned pointer is a fixed memory
location, and does not change due to the delayed initialization.
The script-helper must be initialized eagerly though, for the search of
a base-class helper. This also changes the SCRIPTDESC slightly to
accommodate the eager initialization of helper instance pointer.
Fixes#244.
This function is used to color impact particles.
On Linux I've noticed that this function sometimes is not successful on
retrieving the surface color, leaving an odd color to render the
particles with. The engine function TraceLineMaterialAndLighting() even
has a boolean return value indicating success.
GetModelMaterialColorAndLighting() does not though, but I still observe
failures (the color parameter is not modified). The color is initialized
with an invalid value. If it detects that retrieving the color failed
(engine function said so or the invalid value was left in place), this
now hamfistedly assumes a lightish grey color, but at least still
correctly (presumably) incorporates lighting information.
When this situation is detected, a warning is also printed to the
console. Because why not.