It has always been here, but appears to serve no purpose.
`multi_explode_robot_sub` clears `Stolen_items`, so at first look, this
swap seems to be preserving the prior values. However,
`multi_send_robot_explode` does not use `Stolen_items`, and after
`multi_send_robot_explode` completes, `Stolen_items` is explicitly wiped
again. Thus, removing the whole block will let the wipe performed by
`multi_explode_robot_sub` stand, producing the same result with less
code.
Commit 829e95b6 meant to remove the restriction that the game not be
hoard mode, but incorrectly also removed the restriction that the game
be multiplayer. Restore the multiplayer restriction.
Reported-by: zicodxx <https://github.com/dxx-rebirth/dxx-rebirth/issues/433>
Fixes: 829e95b6f8 ("Separate hoard/proximity tracking")
This removes the need to walk all objects when creating a new one, since
each object can have a private generation counter, unaware of other
objects. For compatibility with demos, mix in the object's index when
writing the signature value.
This was requested by a user in early 2018. However, the proposed
prototype was susceptible to various forms of desynchronization, and was
unsuitable for merging. No further revisions were proposed, and the
feature languished. This commit enables the guidebot in cooperative
games and addresses the known synchronization problems, as well as some
other bugs that were uncovered during light testing. This is classified
as an experimental feature because it has not been heavily tested in
complicated games.
Requested-by: cfeuersaenger <https://github.com/dxx-rebirth/dxx-rebirth/issues/364>
`blast_nearby_glass` calls `check_effect_blowup`, but ignores the result.
If `check_effect_blowup` executes a blow-up effect, and the blown object
is a switch, the return value will instruct the caller to execute the
associated trigger. Since `blast_nearby_glass` ignores the return
value, it never executes a trigger. This was originally masked by a bug
that passed undefined data from `blast_nearby_glass` to
`check_effect_blowup`, which usually confused `check_effect_blowup` into
treating the explosion as not originating from the player. This
confusion then forced an early return when a switch was hit, effectively
accidentally making switches invulnerable to `blast_nearby_glass`.
Commit f6352e7 fixed the data confusion, allowing `check_effect_blowup`
to recognize that the explosion came from a player's weapon. However,
it did not add handling for the trigger, so now `blast_nearby_glass` can
destroy the switch without activating the trigger. This is at the least
annoying, and in some levels may make progress impossible. There are
two ways to resolve this:
- Fix the logic to always execute the switch when the switch is
destroyed, whether by direct hit or by `blast_nearby_glass`.
- Restore the quirk that switches are invulnerable to
`blast_nearby_glass`.
Conveniently, the `force_blowup_flag` is set by `blast_nearby_glass` and
clear for all other callers, so it can be used to recognize that the
caller will not handle the switch. Use this to implement choice 2.
Even with this change, a direct hit by a missile can still destroy a
switch and activate its trigger, since that is handled through
`collide_weapon_and_wall`. Thus, players can still use the technique of
using a guided missile to activate an otherwise impossible switch.
Fixes: f6352e7957 ("Pass correct object to check_effect_blowup")
Reported-by: wm4 <https://github.com/dxx-rebirth/dxx-rebirth/issues/419>
Fix original bug that buddy was limited to 5 hints per program run, not
5 per boss as it probably should have been.
Due to savegame format limitations, this still is not right. Reloading
the game should restore Buddy_gave_hint_count to its value at save time,
but will not.
digi_play_sample_once is supposed to cancel prior instances of the
sound, but that functionality was lost in
21082c6db2. As a result, the sound can be
stacked up to the limit of the engine. Even when the functionality
existed, its implementation was wrong.
- Change these sounds to be attached to the player generating them.
- Pass the cancellation flag to other players when sending a sound.
- Send the full value of `volume`, rather than truncating it.
- Implement cancellation by killing and restarting the earlier version of a cancelled sound.
- Delete an ugly hack that prevented the patched logic from ever running.
- Fix an ancient quirk in digi_mixer that caused it to report all sounds as not playing, which then caused digi_sync_sounds to instantly cancel the new sound.
Reported-by: Mako88 <https://github.com/dxx-rebirth/dxx-rebirth/issues/88>
Reported-by: ryusei117 <https://github.com/dxx-rebirth/dxx-rebirth/issues/88#issuecomment-269597361>
Fixes: 21082c6db2 ("Added own channel management to SDL_mixer sound interface since the builtin channel management of this lib cannot handle our needs; Little code cleanup")
Various files included compiler-static_assert.h to use the compatibility
macros for compilers that lacked a working C++11 static_assert.
However, some source files used static_assert without this inclusion,
and no one ever reported problems. From this, assume that no one uses a
compiler which lacks C++11 static_assert. Remove the inclusions that
were only for the compatibility macro. Keep the inclusions that use the
assert_equal helper.
Materialization centers ("Matcens") have a governor to prevent
overrunning the level in robots. However, due to a logic ordering
error, multiplayer games failed to record how many robots had been
destroyed, so for the purpose of detecting whether there were currently
"too many" robots in play, the game pretended that no robots had ever
been destroyed. Therefore, once enough robots had been created to reach
the "too many" threshold, matcens stopped generating robots, regardless
of how efficiently the player(s) had been destroying robots.
Reported-by: Mako88 <https://github.com/dxx-rebirth/dxx-rebirth/issues/132>
Reported-by: Sirius-TR <https://github.com/dxx-rebirth/dxx-rebirth/issues/386>
When `apply_force_damage` was called to damage a robot, it tested if the
`ctype.laser_info.parent_signature` of the other object matched
`ConsoleObject->signature` and, if so, awarded points to the console
player. This allowed the player to sometimes get points for ramming a
robot to death, but was buggy. When the player rams a robot, the player
is the other object, so accessing `ctype.laser_info` is wrong.
Historically, the player's signature was zero and player
`ctype.laser_info.parent_signature` (an inactive and therefore incorrect
branch of the union) happened to be zero, so the test succeeded. Commit
44753209d6 changed the layout of
`struct player_info` such that
`ConsoleObject->ctype.laser_info.parent_signature` was not zero, causing
the player not to be his own parent. Prior to this commit, the player
could still wrongly fail the test if the `player_info` member that
aliased `laser_info.parent_signature` was nonzero. In the commit
preceding the obvious break, `player_info.player_flags` aliased
`laser_info.parent_signature`, so a player with certain flags (such as
invulnerability) would wrongly fail the test. The exact manifestation
has changed over time as `struct player_info` gained members.
Restructure the test so that a ramming kill always awards points,
without checking ancestry.
Reported-by: Descender1032 <https://forum.dxx-rebirth.com/showthread.php?tid=1006> (no commit identifiers given)
Fixes: 44753209d6 ("Move homing_object_dist to object.ctype.player_info")
Like many things in the main game loop, lavafall handling was
historically done on a per-frame basis, then its effects were scaled to
FrameTime to normalize the results. Ignoring rounding errors, this
produced roughly equivalent damage for high framerate users (who
experienced many but small damage hits) and low framerate users (who
experienced few but large damage hits). However, the randomized
movement was not scaled to FrameTime, which caused differing results for
high framerate users versus low framerate users. Commit b36c6f20c7
tried to fix this by forcing scrape_player_on_wall to run at a capped
maximum effective frame rate, then scaling the damage in
check_volatile_wall accordingly, so that high framerate users would
experience fewer damage hits, but the ones they received were larger,
thus maintaining approximately the same damage as before.
Prior to b36c6f20c7, damage was always scaled to FrameTime. In
b36c6f20c7 and later, damage scaled to max(FrameTime,
DESIGNATED_GAME_FRAMETIME), causing users with a high frame rate (and
thus low FrameTime) to take more damage on each pass. This damage
increase was balanced by an added hack in scrape_player_on_wall to limit
the frequency of the scrape so that high framerate users would skip some
scrapes, giving them a virtual frame rate appropriate to
DESIGNATED_GAME_FRAMETIME. However, the damage is only balanced if the
new governor is used consistently. It is not used consistently, so it
caused a regression for passable lava surfaces. Scraping on a solid
lava surface goes through scrape_player_on_wall and respects the
governor. Touching a passable lava surface (only available in Descent
2) bypasses scrape_player_on_wall and jumps directly to
check_volatile_wall, thereby bypassing the governor. This allows high
framerate users touching a passable lava surface to take many hits (as
they always did), but not receive the full benefit of downward scaling
the damage (as they once did) due to the new max() expression. Thus,
they are damaged frequently, but still take damage consistent with being
damaged infrequently.
Fix this by moving the hack from scrape_player_on_wall to
check_volatile_wall, so that both solid lava surfaces and passable lava
surfaces respect the governor. The governor is still an ugly hack that
should not be global, but this is a spot fix for the immediate problem.
Fixes: b36c6f20c7 ("Made scrape_player_on_wall() based on a timer. Due to the player being pushed away from the lava/water surface in every frame in a random vector (wrong, too), player movement per frame was not enough to counter this on FPS rates > ~120 which made damage scaling per frame nonsensical in these situations. Instead, execute scrape results in intevals based on DESIGNATED_GAME_FRAMETIME (or per frame if FrameTime>DESIGNATED_GAME_FRAMETIME) which fixes the issues and generally works much better for the purpose of this function.")
Commit f4b21088a0 ("Track vulcan ammo explicitly") fixed an original
retail bug that prevented the thief from stealing energy weapons,
because the thief could only steal weapons for which the player had ammo
and energy weapons never have ammo. This went unremarked for several
years, until a recent report of the new semantics as a game-breaking
regression because the thief is now "ridiculously potent".
Address this report, as well as an intermittently raised issue from
various users over time, by adding two new knobs to both the single
player "Gameplay" menu and the multiplayer setup screen: "Remove Thief
at level start" and "Prevent Thief Stealing Energy Weapons".
"Remove Thief" deletes the thief object during level load. It has no
impact on save games, and changing it after entering a level has no
effect on any thief already in the level.
"Prevent Thief Stealing" is checked at the moment of theft and, when
enabled, prevents stealing primary weapons other than Vulcan/Gauss.
This can be changed at will in single player and is immediately
effective. In multiplayer, this option can only be changed by the game
host in the pre-game setup.
For both knobs, there is one pair of checkboxes to control this as a
player preference, which applies in single player games. There is a
second pair of checkboxes in the multiplayer setup, which applies only
to multiplayer games. Therefore, in multiplayer, the host chooses thief
settings and all clients use the host's choice. The host may configure
the thief differently in multiplayer from how the host plays in single
player.
For users who wanted to remove the thief, no specific tally has been
kept for who requested it or when. Now that the code is being updated,
this is thrown in as an easy addition.
Reported-by: MegaDescent <http://forum.dxx-rebirth.com/showthread.php?tid=980> (for the thief stealing energy weapons as a game-breaking regression)