This avoids a crash that stops the maps from being updated
when the base mod ruleset is not valid (e.g. a trait is missing a
FieldLoader.Required property). This also significantly improves the
upgrade performance.
- Rename Bits<T> to BitSet<T>.
- Implement set based helpers for BitSet<T>.
- When representing TargetTypes of ITargetable in various traits, use a BitSet<TargetableType> instead of HashSet<string> for better performance & reduced memory usage.
- Fix FieldLoader to trim input values when generating a BitSet<T>.
- Require T in BitSet<T> and BitSetAllocator<T> to be a class since it's just a marker value. This allows the JIT to instantiate generic code for these classes once, as they don't benefit from specialized code for T. (Typically JITs will generate shared code for all reference types, and unique code for every value type encountered).
- Cache active target query.
- Prefer .Count == 0 over Any when working with Lists.
- Use helper for GetEnabledTargetTypes.
- Don't declare target variable until actually needed.
Actors involved in the trigger are determined as actors move around near the trigger - and can be expensive in some maps. This allows us to avoid allocating new sets and the CPU hit required to set it up each time.
This provides a more efficient way of determining the bounds by avoiding LINQ. A helper that works directly on arrays prevents allocation of an enumerator when the collection is know to be an array.
Shroud footprints are recalculated as actors move around the map, and thus this gets called quite often. This allows us to avoid allocating a new set and the CPU hit required to set it up each time.
The old sequence was not recovering when this trait lost its required
condition while the aim anim was running.
Now it doesn't unconditionally return, but instead checks what the
current sequence is and resets to base turret sequence if AimAnim is
disabled.
While C&C-specific sound defaults might be acceptable for C&C-specific traits like MadTank and Chronoshiftable, for common, generic traits like Building they no longer are.
WithReloadingSpriteTurret was bound to run into conflicts with any WithTurret*Animation traits due to overriding the turret sequence constantly via ITick.
Using (stacked) conditions instead avoids that.
Re-evaluate before every spawn attempt instead.
Also accounts for ActorSpawner being conditional now.
While a bit more costly in terms of performance, this allows to create spawns mid-game.
penev discovered that the RulesetLoaded functions of projectiles were
never being called, meaning that their blocking calculations were not
properly accounting for actors with large hitboxes.
The best fix for this is to change FindActorsOnLine to always account
for the largest actor's hit radius, rather than forcing callers to pass
the largest radius. Per the comment in Util.cs, as a result, move this
computation to ActorMap. I decided to simplify by not making a separate
calculation for actors that block projectiles only; this may cause a
small performance degradation as the search space is a bit larger.
Similarly to this, I've removed the ability to specify a search radius
manually. Because this is only a search radius, setting a value smaller
than the largest eligible actor makes no sense; that would lead to
completely inconsistent blocking. Setting a larger value, on the other
hand, would make no difference.
CreateEffectWarhead was the only place in core code any of these search
radii were set, and that's because 0 was a mysterious magic value that
made the warhead incapable of hitting actors. I replaced it with a
boolean flag that more clearly indicates the actual behaviour.
Fixes#14151.