SOFLAM Integration Core
The visible beam Changed
Everybody who can see infrared should see the beam. That needed one switch to be turned on and one origin to be decided.
GTG_SOFLAM_BeamComponent to a device that carries a designator and set m_sBeamLightPrefab to GTG_SOFLAM_IRLaserLight.et. The component finds the designator on its own entity and draws between the device and the point in the registry.Components tick only where the entity is owned
By default a component's frame event runs only on the machine that owns the entity. Without asking for more, the beam would be invisible to everybody except the operator – although the target point was replicated correctly. The fix is one override, plus a frame mask that is set permanently rather than tied to the optic: someone who is not aiming has no optic open.
class GTG_SOFLAM_BeamComponent : ScriptGameComponent
{
override event bool OnTicksOnRemoteProxy()
{
return true; // also tick on machines that do not own the entity
}
override void OnPostInit(IEntity owner)
{
super.OnPostInit(owner);
m_Owner = owner;
m_Designator = GTG_SOFLAM_LaserDesignatorComponent.FindOn(owner);
SetEventMask(owner, EntityEvent.FRAME); // permanent: not coupled to who is aiming
}
}
EOnFrame and works for the owner, but on every other client simply never runs. In Workbench the host is the owner, so nothing shows. The same applies to a vehicle component on a client that does not own the aircraft: its frame events never run there.The beam knows why it is not drawn
A beam that does not come looks the same at five exit points. The component prints the reason, once per reason, when the same reason has stood for a full second (a short window is normal at start-up, because the entry is created without a position and the first position follows with the next report):
[GTG_SOFLAM] Kein Strahl seit einer Sekunde: kein Designator an dieser Entitaet
[GTG_SOFLAM] Kein Strahl seit einer Sekunde: Ersteller-Id ungueltig -- Traegerentitaet ohne RplComponent
[GTG_SOFLAM] Kein Strahl seit einer Sekunde: Zielablage nicht gefunden
[GTG_SOFLAM] Kein Strahl seit einer Sekunde: kein Ziel unter dieser Ersteller-Id eingetragen
[GTG_SOFLAM] Kein Strahl seit einer Sekunde: Ziel eingetragen, aber ohne Position
In order: no designator on this entity; creator id invalid (carrier without a replication component); registry not found; no target under this creator id; target present but without a position. Only printed while the designator's laser is on.
One origin for everyone
For a while the operator saw the beam from a camera-fixed origin and everybody else from the measured exit of the
lens. The camera-fixed one was deliberate – looking along your own beam you would otherwise see just a dot. The
price was that the beam came out of the wrong corner: the server log showed offsets of exactly the old constants (-0.10 / 0.10 / 0.05), so the code had done what it was told.
The decision was that the beam comes out of the source, for everybody. The special case went away, and there is now one
measured aperture – the one that provably leaves from the lowest lens in the outside view. Its offsets are attributes (m_fEmitterForward -0.0736, m_fEmitterDown 0.0253, m_fEmitterRight -0.0371, in metres, device coordinates),
the start is smoothed with a time constant of m_fEmitterSmoothTime = 0.08 s (display only; the reported point stays exact), and for the operator the end of the beam is the freshly computed point (GetLiveTargetPosition()) because the crosshair is real time and the reported point is up to one report old.
The cone is trimmed to the target
The light is a spot (Type Spot, radius 500 in the prefab). Left alone it ran up to 450 m behind a target at 50 - 250 m and, because the origin sits beside the line of sight, showed up left or right of the target in the depth – it looked like “the laser goes past the target”, while the direction was right all the time (0.04 degrees off, measured).
So the radius is clamped to the distance (between 50 and 500 m) every frame, and the near plane scales with it at 1 : 10000.
Local, not replicated
The light entity is created locally on each machine (SpawnEntityPrefabLocal), not on a dedicated server. It follows the replicated target point and needs no
replication of its own. It is only switched on for those who can see infrared (the previous page).