Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ Version 1.3.0 (Bakeapple): Not yet released
- Default gore level to 1
- Default `gibbing` to disabled for dedicated servers

[@nickalreadyinuse](https://github.com/nickalreadyinuse)
- Sync animation state for crouched players in first person spectate view
- Sync rail scanner in first person spectate
- Implement damage screen flash in first person spectate mode
- Add `cl_damageflash_spectator` console command to toggle damage screen flash in first person spectate

[@natarii](https://github.com/natarii)
- Implement FFLink client functionality in launcher

Expand All @@ -50,8 +56,6 @@ Version 1.3.0 (Bakeapple): Not yet released

[@nickalreadyinuse](https://github.com/nickalreadyinuse)
- Optimize network performance for `af_obj_update` packets and bot decommission logic
- Sync animation state for crouched players in first person spectate view
- Sync rail scanner in first person spectate
- Fix Alt+Enter crash in Direct3D 11 renderer

Version 1.2.2 (Willow): Released Jan-04-2026
Expand Down
5 changes: 5 additions & 0 deletions game_patch/misc/alpine_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@ bool alpine_player_settings_load(rf::Player* player)
g_alpine_game_config.damage_screen_flash = std::stoi(settings["DamageScreenFlash"]);
processed_keys.insert("DamageScreenFlash");
}
if (settings.count("SpectateDamageScreenFlash")) {
g_alpine_game_config.spectate_damage_screen_flash = std::stoi(settings["SpectateDamageScreenFlash"]);
processed_keys.insert("SpectateDamageScreenFlash");
}
if (settings.count("ExplosionFlashLightsWeapons")) {
g_alpine_game_config.explosion_weapon_flash_lights = std::stoi(settings["ExplosionFlashLightsWeapons"]);
processed_keys.insert("ExplosionFlashLightsWeapons");
Expand Down Expand Up @@ -1115,6 +1119,7 @@ void alpine_player_settings_save(rf::Player* player)
file << "NeverAutoswitchExplosives=" << player->settings.dont_autoswitch_to_explosives << "\n";
file << "ToggleCrouch=" << player->settings.toggle_crouch << "\n";
file << "DamageScreenFlash=" << g_alpine_game_config.damage_screen_flash << "\n";
file << "SpectateDamageScreenFlash=" << g_alpine_game_config.spectate_damage_screen_flash << "\n";
file << "ExplosionFlashLightsWeapons=" << g_alpine_game_config.explosion_weapon_flash_lights << "\n";
file << "ExplosionFlashLightsEnv=" << g_alpine_game_config.explosion_env_flash_lights << "\n";
file << "BurningEntityLights=" << g_alpine_game_config.burning_entity_lights << "\n";
Expand Down
1 change: 1 addition & 0 deletions game_patch/misc/alpine_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ struct AlpineGameSettings
bool show_run_timer = true;
bool multi_ricochet = false;
bool damage_screen_flash = true;
bool spectate_damage_screen_flash = true;
bool explosion_weapon_flash_lights = true;
bool explosion_env_flash_lights = true;
bool burning_entity_lights = true;
Expand Down
13 changes: 12 additions & 1 deletion game_patch/misc/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,8 @@ FunHook<void()> players_do_frame_hook{
[]() {
players_do_frame_hook.call_target();
if (multi_spectate_is_spectating()) {
rf::hud_do_frame(multi_spectate_get_target_player());
rf::Player* target = multi_spectate_get_target_player();
rf::hud_do_frame(target);
}
else {
local_delayed_spawn_do_frame(); // try to spawn if a delayed spawn is queued
Expand All @@ -513,6 +514,15 @@ ConsoleCommand2 damage_screen_flash_cmd{
"Toggle damage screen flash effect",
};

ConsoleCommand2 spectate_damage_screen_flash_cmd{
"cl_damageflash_spectator",
[]() {
g_alpine_game_config.spectate_damage_screen_flash = !g_alpine_game_config.spectate_damage_screen_flash;
rf::console::print("Spectator damage screen flash effect is {}", g_alpine_game_config.spectate_damage_screen_flash ? "enabled" : "disabled");
},
"Toggle damage screen flash effect while spectating",
};

ConsoleCommand2 weapon_explosion_flash_lights_cmd{
"cl_explosionflashweapons",
[]() {
Expand Down Expand Up @@ -926,6 +936,7 @@ void player_do_patch()

// Commands
damage_screen_flash_cmd.register_cmd();
spectate_damage_screen_flash_cmd.register_cmd();
weapon_explosion_flash_lights_cmd.register_cmd();
env_explosion_flash_lights_cmd.register_cmd();
burning_entity_lights_cmd.register_cmd();
Expand Down
24 changes: 24 additions & 0 deletions game_patch/multi/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "server_internal.h"
#include "../main/main.h"
#include "../hud/hud.h"
#include "../hud/multi_spectate.h"
#include "../rf/multi.h"
#include "../rf/misc.h"
#include "../rf/player/player.h"
Expand Down Expand Up @@ -903,6 +904,26 @@ CodeInjection process_obj_update_check_flags_injection{
},
};

// Trigger spectator damage screen flash when the spectated player's health or armor decreases.
// Injected at the point in process_obj_update_packet where a health/armor decrease has been
// confirmed (OUF_HEALTH_ARMOR set, new value < entity value) but before the local-player check.
// edi = entity pointer at this address.
CodeInjection process_obj_update_health_armor_spectate_injection{
0x0047E4DA,
[](auto& regs) {
if (!g_alpine_game_config.spectate_damage_screen_flash || rf::is_server)
return;
rf::Entity* entity = regs.edi;
if (!entity)
return;
rf::Player* spectated = multi_spectate_get_target_player();
if (!spectated || spectated == rf::local_player || multi_spectate_is_freelook())
return;
if (entity == rf::entity_from_handle(spectated->entity_handle))
rf::local_screen_flash(rf::local_player, 255, 0, 0, 128);
},
};

CodeInjection process_obj_update_weapon_fire_injection{
0x0047E2FF,
[](auto& regs) {
Expand Down Expand Up @@ -2378,6 +2399,9 @@ void network_init()
// Fix obj_update packet handling
process_obj_update_check_flags_injection.install();

// Spectator damage screen flash via obj_update health/armor
process_obj_update_health_armor_spectate_injection.install();

// Verify on/off weapons handling
process_obj_update_weapon_fire_injection.install();

Expand Down
Loading