Change to 180 TPS - #1237
Change to 180 TPS#1237Kurtsley wants to merge 3 commits into
Conversation
|
Looking good and thanks for working on this complex task Regarding smoke and explosions - they should leave behind residual smoke as this is present in the OG However, the smoke dissipates faster than that of a smoke grenade - which is likely affected by the tick counter and the value for dissipation Regarding explosion speed, can you confirm the effects of the More-Options toggle for "Explosions damage instantly" still work correctly. When off, it should follow the OG behaviour with damage being applied after the explosion has reached maximal radius. When on, it should apply damage to a unit as soon as the expanding radius hits it - this was an optional fix to avoid a situation with the OG where a unit could run out of an explosion unscathed. By applying damage as soon as the expanding explosion hits the unit, they take damage under the normal rules for armour/pen immediately and cannot avoid being harmed. |
|
I reduced the length that the smoke from explosions sticks around. I'm starting to think, as has been stated before, that most of the issues are related to values being set according to a 144hz monitor. The original developer set the tick rate to his monitor refresh rate of 144. This PR is attempting to set the tick rate to three times the game fraterate instead of the original 1:1 ratio that was used when writing this originally. It comes down to going through every single instance where the tick rate is being used in logic and deciding if it an animation or time issue. With the battle AI, most decisions are based on ticks per second. For example, the think interval is ticks per turn / 4. I would assume that the game wants the AI to make decisions every quarter second, so this value should not be touched. Grenade priming also works like this, it is based on time. I think any value that works with the animation of sprites and is based on ticks may need to be looked into. So far, I haven't touched much beyond changing the tick multiplier and messing with the explosions. From what I can see, the explosion radius isn't a tick issue, dividing by 1.5 instead of 2 seems to fix it. I will need to look at damage next. The HE cannon does seem pretty weak, but the power is correct. The rate of fire is still correct, it just had to be divided by 5 instead of 4 to match the 36fps assumption. TLDR: There will be no magic solution, basically everything needs to be tweaked to work with the new tick rate. |
|
Many thanks for your continued work on this; agreed, navigating the mess of calcs linked to both TPS and FPS and correcting them (or separating them) has always been the scary side of this issue Are we definitely sure on the Original Game being 18fps and 36tps or is that reversed at times (for example, in slow speed simulation)? @JonnyH @Skin36 if you are able to advise on the exact values the original game assumes for each when your time allows, it would be really appreciated 🍻 Do we know who did the original work linking calcs to an assumed 144FPS? I can't seem to find on the tracker (so may be pre-github) |
|
Git blame suggests the original 60->144 "change" was 76dda03 Before that the numbers I had there were 100% made up - it was still when stuff was being reverse engineered so I tweaked some things to "look about right" for the vehicle movement. Anything that might have been correct at that time is likely due to luck rather than intent :) |
|
Once we have a consistent time base, we might "finally" decouple the frame rate and tick rate. But that's a separate change :) I think the best way is to rework the main {(tick gamestate) (handle input and UI events) ( render)} loop with something more similar to timers - we have 2 events, the update tick, triggered every 1/180 seconds, and the imput/ui/render, which should probably be aligned to display refresh. The simplest way of doing this would be to have both on a thread, so they block and just queue up if the tick would have happened while the thread it busy. The render would then know it can access the current state without worrying about asynchronous access. The input and UI updates would be coupled with the render, as interacting at a subframe latency probably doesn't actually make sense. While this might cause jitter of +- 1 frame's worth of ticks, apoc not being a super accuracy-based competitive twitch-reflex game likely means it doesn't really matter either. Though we might need to think of what happens if the system cannot keep up - I don't want (for example) the render events to completely starve the queue, but an ordered event "queue" of those should correctly interleave so everything just goes slower when the system isn't able to keep up, which is probably fine for a single player game. Though might need to ensure the queue size is bounded. |
|
@FilmBoy84 asked upthread whether we're definitely sure about 36 TPS. I have something concrete on that. Provenance first, so you can weigh it: this comes from a fork where I've been running Ghidra against the retail 36 TPS holds upThe negative result first: there is no printable "36 ticks" string in either binary. So 36 was never directly bound, and community observation is all it ever rested on. But the fire-overlay scheduler corroborates it structurally. So: 36 is right, and this PR is right to keep The multiplier is the free parameter — the hazard is un-derived constants
That's the real risk here, and this PR already demonstrates it: Might be worth making those derive instead: static const int FUEL_TICKS_PER_SECOND = TICKS_PER_SECOND;and grepping for other bare A way to validate whichever multiplier you pickThe three scheduler cadences above are measurable against the original. If a chosen multiplier is right, fire spread rate and the turn-based wrap should line up when mapped through it. That's a falsifiable check rather than eyeballing walk speed. Happy to write up the fire-scheduler findings in more detail (binary, generation and file offset for each) if that'd be useful to anyone auditing #997. |
Regenerate the comparison report after the timing header moved and bring the previously stale parity status table in sync with its in-repo sources. Related to OpenApoc#1237
Carry the upstream horizontal-scrollbar behavior through the develop reconciliation so wide research-lab rows remain navigable. Related to OpenApoc#1237
Apply the repository clang-format 18 target across the reconciled source set and make the style file language-neutral so Objective-C++ sources are checked by the same target. Related to OpenApoc#1237
Sort equal-count report rows deterministically, lock the ordering with a pure Python test, and refresh the generated report from the reconciled sources. Related to OpenApoc#1237
Document the binary-proven 36 TPS base, add named vanilla-unit conversions, and scale the calibrated fuel threshold with the engine multiplier while retaining the 4/144 configuration canaries. Related to OpenApoc#1237
Regenerate the comparison report after the named vanilla constants moved the timing definitions to new source lines. Related to OpenApoc#1237
Remove redundant constructor-definition semicolons and disambiguate one multiplication expression so clang-format 18.1.3 and 18.1.8 produce the same tree. This keeps the reconciled base lint-clean on both CI and the local toolchain. Related to OpenApoc#1237
Use the MainMenu Skirmish route directly, accept both sides of the current nested StageCmd loss, and preserve the complete battle as a known-red acceptance for the live-FIFO scheduler change. Related to OpenApoc#1237
Document the binary-proven 36 TPS base, add named vanilla-unit conversions, and scale the calibrated fuel threshold with the engine multiplier while retaining the 4/144 configuration canaries. Related to OpenApoc#1237
Regenerate the comparison report after the named vanilla constants moved the timing definitions to new source lines. Related to OpenApoc#1237
The recovered invasion coefficients corroborate the community-observed 36 TPS interpretation without independently proving its absolute cadence. Add named vanilla-unit conversions and scale the calibrated fuel threshold while retaining explicit 4/144 configuration canaries. Related to OpenApoc#1237
Record the invasion coefficient ratios across the durable timing evidence and state their mathematical limit so future work does not mistake corroboration for an independently recovered absolute clock. Related to OpenApoc#1237
Centralize tactical result decisions, require exact arena workloads, and preserve engine exit truth in validation receipts so incomplete automation cannot pass as gameplay success. Related to OpenApoc#1237
Reconcile durable reports, findings, runtime comments, and lock-test descriptions with the evidence boundary already stated in gametime.h. The repository selects 36 TPS as its observational compatibility canon; recovered coefficients corroborate only the unit-free 1:60:86400 ratio, while recovered shield logic binds a 36-tick interval rather than an absolute second. Verification: 37/37 CTest, focused timing/shield locks, compare-report regeneration and test, ignored-binary check, diff check, and complete clang-format 18.1.3/18.1.8 dry runs. Related to OpenApoc#1237
Prevent partial generations, invalid force specifications, and unclean engine shutdowns from producing scoreable robot evidence. Socket-free contracts cover every arena lifecycle. Related to OpenApoc#1237
Replace the last two overstatements in timing comments with compatibility-base and observed-catalog language. Cite the canonical ISO non-4 UFO2P FUN_0006d384 evidence with its exact VA and file offset in the durable solution note. Verification: focused 2/2 and full 37/37 CTest, report regeneration check/test, ignored-binary and diff checks, and complete clang-format 18.1.3/18.1.8 dry runs. Related to OpenApoc#1237
Make finite Skirmish shutdown truth unconditional and treat adversarial ledgers as commit points so scores cannot outlive missing evidence. Roll back uncommitted generation scoring on persistence failure. Related to OpenApoc#1237
Addresses #997, #1216 so far.
The following is a list of what appears to have been fixed, many are very lightly tested and the changes could very easily have affected things in other parts of the game that I don't yet know about. This is just a running list to help me keep track of what has been done.
Battlescape
Cityscape
NA
Both
Problems