Files
sfall/artifacts/mods/gl_highlighting.ssl
T
NovaRain ca3df3347d Fixed LOS check in gl_highlighting for some containers on maps
Fixed opcode number for set_perk_int in docs (closes #633)
Updated resource files.
2026-07-02 09:06:07 +08:00

210 lines
7.4 KiB
ObjectPascal

/**
Item Highlighting mod
Previously was part of sfall itself, now a separate mod.
Features:
- highlights items, containers (optional) and lootable corpses (optional) on the ground
- highlights critters using the same rules as combat mode highlighting (optional)
- configurable hotkey is used to trigger highlight
- hotkey can be pressed and held to continuously update highlighted objects based on current position
- only objects in direct line-of-sight of player are highlighted (optional)
- motion scanner is required to enable highlight (optional)
- motion scanner charges are decreased on each use (optional)
NOTE: this script requires compiler from sfall modderspack with -s option
(short circuit evaluation)
version 1.3
**/
#pragma sce
#include "main.h"
//#include "..\..\..\!SRC\headers\define.h"
#define CRITTER_IS_DEAD (1)
#define PID_MOTION_SENSOR (59)
#define REPEAT_FRAMES (10)
#define NO_HIGHLIGHT(obj) (get_flags(obj) bwand FLAG_NOHIGHLIGHT)
#define NO_STEAL(obj) (get_proto_data(obj_pid(obj), PROTO_CR_FLAGS) bwand CFLG_NOSTEAL)
#define IS_EMPTY(obj) (inven_ptr(obj, 0) == 0)
variable begin
configSection := "Highlighting";
highlightKey;
isHighlight;
alsoContainer;
alsoCorpse;
alsoCritter;
checkLOS;
outlineColor;
outlineColorContainers;
outlineColorContainersEmpty;
outlineColorCorpses;
outlineColorCorpsesEmpty;
motionScanner;
highlightFailMsg1;
highlightFailMsg2;
end
procedure DudeCanSee(variable obj) begin
variable block := obj_blocking_line(dude_obj, tile_num(obj), BLOCKING_TYPE_SHOOT);
return not block or block == obj or tile_num(block) == tile_num(obj);
end
procedure DudeCanHear(variable obj) begin
variable hearDist := dude_perception * 5;
if (get_flags(obj) bwand FLAG_TRANSGLASS) then
hearDist /= 2;
return tile_distance_objs(dude_obj, obj) <= hearDist;
end
procedure GetOutlineColor(variable obj, variable isCritter) begin
if isCritter then begin
if get_team(obj) == get_team(dude_obj) then return OUTLINE_GREEN_GLOW;
if not DudeCanSee(obj) then begin
if (DudeCanHear(obj)) then return OUTLINE_DARK_YELLOW;
return 0;
end
return OUTLINE_RED_GLOW;
end
if checkLOS and not DudeCanSee(obj) then
return 0;
if obj_type(obj) == OBJ_TYPE_CRITTER then
return outlineColorCorpsesEmpty if IS_EMPTY(obj) else outlineColorCorpses;
if obj_item_subtype(obj) == item_type_container then
return outlineColorContainersEmpty if IS_EMPTY(obj) else outlineColorContainers;
return outlineColor;
end
procedure ToggleHighlightObject(variable obj, variable enable, variable isCritter) begin
if (not alsoContainer or obj_item_subtype(obj) != item_type_container) and NO_HIGHLIGHT(obj) then return;
set_outline(obj, GetOutlineColor(obj, isCritter) if enable else 0);
end
procedure ToggleHighlight(variable enable) begin
variable obj, isCorpse;
foreach obj in list_as_array(LIST_GROUNDITEMS) begin
if obj and obj != outlined_object then begin
call ToggleHighlightObject(obj, enable, false);
end
end
if (alsoCorpse or alsoCritter) then begin
foreach obj in list_as_array(LIST_CRITTERS) begin
if obj and obj != dude_obj then begin
isCorpse := critter_state(obj) == CRITTER_IS_DEAD;
if (alsoCritter and not isCorpse) or (isCorpse and not NO_STEAL(obj)) then begin
call ToggleHighlightObject(obj, enable, not isCorpse);
end
end
end
end
tile_refresh_display;
if (checkLOS or alsoCritter) and enable != isHighlight then begin
set_global_script_repeat(REPEAT_FRAMES if enable else 0);
end
isHighlight := enable;
end
procedure KeyPressHandler begin
variable pressed := get_sfall_arg,
scanCode := get_sfall_arg,
scanner, charges;
if scanCode == highlightKey and not(get_game_mode bwand bwnot(COMBAT bwor PCOMBAT)) then begin
if pressed then begin
set_global_script_repeat(REPEAT_FRAMES);
if motionScanner then begin
scanner := obj_carrying_pid_obj(dude_obj, PID_MOTION_SENSOR);
if scanner then begin
if motionScanner >= 2 then begin
charges := get_weapon_ammo_count(scanner);
if charges > 0 then begin
set_weapon_ammo_count(scanner, charges - 1);
intface_redraw;
call ToggleHighlight(true);
end else begin
display_msg(highlightFailMsg2);
end
end else begin
call ToggleHighlight(true);
end
end else begin
display_msg(highlightFailMsg1);
end
end else begin
call ToggleHighlight(true);
end
end else begin
call ToggleHighlight(false);
end
end
end
// visual glitch fix, turn off highlight when entering combat
procedure CombatTurnHandler begin
if isHighlight then begin
call ToggleHighlight(false);
end
end
// visual glitch fix, turn off highlight when opening other interfaces
procedure GameModeChangeHandler begin
if isHighlight and (get_game_mode bwand bwnot(COMBAT bwor PCOMBAT)) then begin
call ToggleHighlight(false);
end
end
procedure InventoryMoveHandler begin
// remove item outline when player picks up the item
if (isHighlight and get_sfall_arg == 7) then set_outline(get_sfall_arg, 0);
end
procedure start begin
if game_loaded then begin
if (sfall_ver_major < 4) then return;
call InitConfigs;
highlightKey := GetConfig(configSection, "Key", 0);
alsoContainer := GetConfig(configSection, "Containers", 0);
alsoCorpse := GetConfig(configSection, "Corpses", 0);
alsoCritter := GetConfig(configSection, "Critters", 0);
checkLOS := GetConfig(configSection, "CheckLOS", 0);
outlineColor := GetConfig(configSection, "OutlineColor", 16);
if (outlineColor < 1) then outlineColor := 64;
outlineColorContainers := GetConfig(configSection, "OutlineColorContainers", 32);
if (outlineColorContainers < 1) then outlineColorContainers := 64;
outlineColorContainersEmpty := GetConfig(configSection, "OutlineColorContainersEmpty", 4);
if (outlineColorContainersEmpty < 0) then outlineColorContainersEmpty := 64; // allow 0
outlineColorCorpses := GetConfig(configSection, "OutlineColorCorpses", 32);
if (outlineColorCorpses < 1) then outlineColorCorpses := 64;
outlineColorCorpsesEmpty := GetConfig(configSection, "OutlineColorCorpsesEmpty", 4);
if (outlineColorCorpsesEmpty < 0) then outlineColorCorpsesEmpty := 64; // allow 0
motionScanner := GetConfig(configSection, "MotionScanner", 0);
highlightFailMsg1 := Translate("HighlightFail1", "You aren't carrying a motion sensor.");
highlightFailMsg2 := Translate("HighlightFail2", "Your motion sensor is out of charge.");
register_hook_proc(HOOK_KEYPRESS, KeyPressHandler);
register_hook_proc(HOOK_COMBATTURN, CombatTurnHandler);
register_hook_proc(HOOK_GAMEMODECHANGE, GameModeChangeHandler);
register_hook_proc(HOOK_INVENTORYMOVE, InventoryMoveHandler);
set_global_script_type(1);
end else begin
if isHighlight and not(get_game_mode bwand bwnot(COMBAT bwor PCOMBAT)) then begin
call ToggleHighlight(true);
end
end
end