Under gcc-9 (e.g. used by Ubuntu 20.04), compilation fails with:
```
/usr/include/c++/9/variant: In instantiation of ‘constexpr const size_t std::variant_size_v<user_var>’:
/usr/include/c++/9/variant:1023:10: required from ‘struct std::__detail::__variant::__gen_vtable<true, void, user_var::operator++(int)::<lambda(auto:22&&)>&&, user_var&>’
/usr/include/c++/9/variant:1656:23: required from ‘constexpr decltype(auto) std::__do_visit(_Visitor&&, _Variants&& ...) [with bool __use_index = false; bool __same_return_types = true; _Visitor = user_var::operator++(int)::<lambda(auto:22&&)>; _Variants = {user_var&}]’
/usr/include/c++/9/variant:1672:29: required from ‘constexpr std::__detail::__variant::__visit_result_t<_Visitor, _Variants ...> std::visit(_Visitor&&, _Variants&& ...) [with _Visitor = user_var::operator++(int)::<lambda(auto:22&&)>; _Variants = {user_var&}; std::__detail::__variant::__visit_result_t<_Visitor, _Variants ...> = void]’
scripts/DallasFuncs.h:21:75: required from here
/usr/include/c++/9/variant:94:29: error: incomplete type ‘std::variant_size<user_var>’ used in nested name specifier
94 | inline constexpr size_t variant_size_v = variant_size<_Variant>::value;
```
Judging from the date of P2162, calling std::visit with std::variant
derivatives is only specified for C++20 and onwards. But Descent3
only asks for C++17.
Since ``class user_var`` does not have any members that need would
need to be accessed via std::visit, we can "add a hint" and
explicitly specify the base type.
$GIT/scripts/LEVEL15.cpp: In function ‘void aMatCenPuzzleInit()’:
$GIT/scripts/LEVEL15.cpp:833:38: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
833 | #define MagicMatCenSwitchSequence (*((int *)(&User_vars[17])))
$GIT/scripts/LEVEL15.cpp:834:25: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
834 | #define MatCenStateA (*((int *)(&User_vars[0])))
...
$GIT/scripts/Level6.cpp: In function ‘void aPriestKeyEnter(int)’:
$GIT/scripts/Level6.cpp:910:47: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
910 | #define Var_ThereIsPlayerInPriestKeyPuzzle (*((int *)(&User_vars[7])))
Turn ``User_var`` into an array of std::variant, the latter of which can hold
either float or int. Savegames do not carry the necessary type information
which variant (float/int) is in use; instead, this is statically decided by
the level DLL logic on a per-index basis. This approach is retained for now.
A lot of ``Var_something = 0`` is used despite Var_something being
logically used as float, so we need to override op= to keep the
variant type as-is.
Due to ``#include "DallasFuncs.cpp"``, DF is recompiled 52 times.
Rework it to build just once. The compile time goes down for me
from 1m45.3s to 1m38.8s on my 1135G7 CPU running make -j8.
The switcheroo involving OSIRISEXTERN is unnecessary; if it is empty,
it is "extern" anyway.
One function, ``osicommon_Initialize``, is present twice and can lead
to duplicate definitions in the linker stage, which is probably what
the DallasFuncs.cpp comment alluded to. It is moved away into its own
.cpp file.
Both e.g. AIGame3.cpp and DallasFuncs.cpp include
``osiris_vector.h``. Right now, this is not a problem because
DallasFuncs.cpp is not compiled itself, but included from
AIGame3.cpp, in other words, it is all just one translation unit.
I have a plan to do away with ``#include "DallasFuncs.cpp"``, which
means the linker invocation for AIGame3.so will have at least two
translation units, and thus two definitions of the osiris vector
functions, which is not allowed.
This also has the side-effect to reduce compile-time a little,
from 1m57.5s to 1m48.7s on my 1135G7 CPU using `make -j8`.
I want to namespace the stuff in DallasFuncs.cpp, and when I do that,
there comes about an ambiguity between ``NewNamespace::aUserFlagSet``
and the ``::aUserFlagSet`` declared by LEVEL15 (also ``qUserFlag``).
Due to ``#include "DallasFuncs.cpp"``, LEVEL15.cpp already has a
declaration (and definition) for ``aUserFlagSet``, and so we can jsut
remove the two lines.
gcc warns about strict aliasing violations in fix.cpp:
fix/fix.cpp: In function "int FloatRound(float)":
fix/fix.cpp:157:14: warning: dereferencing type-punned pointer will
break strict-aliasing rules [-Wstrict-aliasing]
157 | return ((*((int *)&nf)) & 0x7FFFFF) - 2048;
But these functions and then some are unused, so delete them altogether.
It is possible to cause the death of the CollectorNomad2 object (rush
to it before it possibly leaves again into the sidepackets the ship
won't fit through). The transition happens here:
```
f0 KillObject (objp=0x3d4d3e0 <Objects+384000>, killer=0x3cef7e0 <Objects>, damage=3) at /home/jengelh/D3/Descent3/damage.cpp:1036
f1 ApplyDamageToGeneric (hit_obj=0x3d4d3e0 <Objects+384000>, killer=0x3cef7e0 <Objects>, damage_type=6, damage=3, server_says=0, weapon_id=255) at /home/jengelh/D3/Descent3/damage.cpp:1401
f2 collide_generic_and_player (robotobj=0x3d4d3e0 <Objects+384000>, playerobj=0x3cef7e0 <Objects>, collision_point=0x7f877f40a830, collision_normal=0x7f877f40a858, f_reverse_normal=true, hit_info=0x7f877f40a810) at /home/jengelh/D3/physics/collide.cpp:2127
f3 collide_two_objects (A=0x3cef7e0 <Objects>, B=0x3d4d3e0 <Objects+384000>, collision_point=0x7f877f40a830, collision_normal=0x7f877f40a858, hit_info=0x7f877f40a810) at /home/jengelh/D3/physics/collide.cpp:2505
f4 do_physics_sim (obj=0x3cef7e0 <Objects>) at /home/jengelh/D3/physics/physics.cpp:1515
f5 ObjDoFrame (obj=0x3cef7e0 <Objects>) at /home/jengelh/D3/Descent3/object.cpp:2824
f6 ObjDoFrameAll () at /home/jengelh/D3/Descent3/object.cpp:2988
f7 GameFrame () at /home/jengelh/D3/Descent3/GameLoop.cpp:2980
f8 GameSequencer () at /home/jengelh/D3/Descent3/gamesequence.cpp:1221
f9 PlayGame () at /home/jengelh/D3/Descent3/game.cpp:834
f10 MainLoop () at /home/jengelh/D3/Descent3/descent.cpp:550
f11 Descent3 () at /home/jengelh/D3/Descent3/descent.cpp:508
f12 oeD3LnxApp::run (this=0x7f877f00db50) at /home/jengelh/D3/Descent3/sdlmain.cpp:151
<frame 2> (gdb) p robotobj
$1 = {
type = 2 '\002' (OBJ_ROBOT), dummy_type = 255 '\377', id = 276,
flags = 2135072, name = 0x5020000aff30 "CollectorNomad2",
handle = 2432, next = 178, prev = -1,
control_type = 1 '\001' (CT_AI), movement_type = 2 '\002' (MC_ROLLING),
render_type = 1 '\001' (LRT_GOURAUD), lighting_render_type = 1 '\001', roomnum = 58,
pos = {x = 2350.21484, y = -263.523956, z = 1868.59888},
orient = {
rvec = {x = 0.882905424, y = 1.63964216e-14, z = -0.469550878},
uvec = {x = -1.25793295e-14, y = 1, z = 1.12662192e-14},
fvec = {x = 0.469550878, y = -4.04037088e-15, z = 0.882905424}
},...}
```
Thus, KillObject sets obj->control_type=CT_DYING. In the same game
tick, Level6.cpp then calls aAIGoalFollowPathSimple which triggers
the assertion.
```
Int3 in $GIT/Descent3/osiris_predefs.cpp at line 571.(Descent 3 Debug Break)
f0 osipf_AIGoalFollowPathSimple (objhandle=2432, path_id=21, guid=7, flags=1052928, slot=3) at $GIT/Descent3/osiris_predefs.cpp:571
f1 AI_GoalFollowPathSimple (objhandle=2432, path_id=21, guid=7, flags=1052928, slot=3) at $GIT/scripts/osiris_import.h:170
f2 aAIGoalFollowPathSimple (objhandle=2432, pathid=21, flags=1052928, goalid=7, priority=3) at $GIT/scripts/DallasFuncs.cpp:3649
f3 LevelScript_0000::CallEvent (this=0x5020000ba430, event=256, data=0x7f963e71d930) at $GIT/scripts/Level6.cpp:2465
f4 CallInstanceEvent (id=0, ptr=0x5020000ba430, event=256, data=0x7f963e71d930) at $GIT/scripts/Level6.cpp:2209
f5 Osiris_CallLevelEvent (event=256, data=0x7f963e71d930) at $GIT/Descent3/OsirisLoadandBind.cpp:2000
f6 GameFrame () at $GIT/Descent3/GameLoop.cpp:3020
f7 GameSequencer () at $GIT/Descent3/gamesequence.cpp:1221
f8 PlayGame () at $GIT/Descent3/game.cpp:834
f9 MainLoop () at $GIT/Descent3/descent.cpp:550
f10 Descent3 () at $GIT/Descent3/descent.cpp:508
f11 oeD3LnxApp::run (this=0x7f963e80db50) at $GIT/Descent3/sdlmain.cpp:151
```
For lightning effect we using ps_rand() function which expects number in range [0, 0x7fff], but RAND_MAX is 0x7fffffff (INT_MAX, for 64-bit systems). In result lightnings strikes on every allowed frame and leads to epilepsy.