Previous version skipped collision the frame immediately after a call to SetPos. It worked for one-off calls (teleports for instance) and continuous call along a pre-defined path (scenic travel). However, in the case of mod which uses SetPos to simulate a player-controlled movement, it is equivalent to using tcl.
Solution:
1/ skip update of mPosition and mPreviousPosition to avoid janky interpolation
2/ use back plain moveObject() instead of moveObjectBy() since we don't want physics simulation
3/ rework a little bit waterwalking influence on coordinate because of 1/
Currently, we use a peculiar mapping of ESM classes by their std::type_info::name. This mapping is an undefined behaviour because std::type_info::name is strictly implementation defined. It could return a non-unique value on some platforms. With this PR we use the unsigned int sRecordId of the ESM class as a more efficient lookup type that does not build on undefined behaviour. We can expect marginally faster save-game loading with these changes as well.
Instead of registering the desired change of position and rely on
physics simulation to apply it to the world, immediately change the
position in the world without reset the simulation.
When a script calls SetPos for x,y,z in sequence on an actor, we need to make sure
that the actor will not spawn under ground at x,y coordinates.
Now that change of coordinates are cumulated and applied all at once, we
need to account for the whole offset.
To this end move the terrain height check inside of Actor class.
its current position.
Use it in relevant MWScripts opcode (move and moveworld).
Remove the fragile detection of scripted translation from PhysicsTaskScheduler.
No user visible change, just a more robust mechanism.
Before this change, if an actor position was changed while the physics
simulation was running, the simulation result would be discarded. It is
fine in case of one off event such as teleport, but in the case of
scripts making use of this functionality to make lifts or conveyor (such
as Sotha Sil Expanded mod) it broke actor movement.
To alleviate this issue, at the end of the simulation, the position of the Actor
in the world is compared to the position it had at the beginning of the
simulation. A difference indicate a force move occured. In this case,
the Actor mPosition and mPreviousPosition are translated by the difference of position.
Since the Actor position will be really set while the next simulation runs, we
save it in the mNextPosition field.
setPosition(getPosition() + diff) to move actor in scripts.
With background physics, this is very slightly off with the collision
object position.
When the script run long enough (a few dozen frames for instance),
the accumulated error becomes too big. It make actors fall through lifts floors.