mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
It caused NPCs to not switch to other weapons when there is not enough ammo to shoot. Moved CheckWeaponAmmoCost code from Inventory.cpp to Combat.cpp. Now the debug editor starts at the center of the screen. Updated the previous fix in NPC combat control mod.
154 lines
5.4 KiB
Plaintext
154 lines
5.4 KiB
Plaintext
/*
|
|
|
|
NPC Combat Control
|
|
|
|
Allows to take control of your party member or other NPCs during combat
|
|
|
|
NOTE: this script requires compiler from sfall modderspack with -s option
|
|
(short circuit evaluation)
|
|
|
|
version 1.1
|
|
|
|
*/
|
|
|
|
#include "..\headers\define.h"
|
|
#include "..\headers\command.h"
|
|
#include "main.h"
|
|
|
|
#define OBJ_DATA_LIGHT_DISTANCE (0x6C)
|
|
#define OBJ_DATA_LIGHT_INTENSITY (0x70)
|
|
|
|
variable
|
|
controlMode,
|
|
noCheckArray,
|
|
pidList,
|
|
lightInt, lightDist, npcControl,
|
|
displayName, displayNameColor,
|
|
inControl := false,
|
|
hasGeckoSkinning := false;
|
|
|
|
|
|
procedure AllowControl(variable pid) begin
|
|
if (noCheckArray or scan_array(pidList, pid bwand 0xFFFFFF) != -1) and (party_member_obj(pid)) then return true;
|
|
return false;
|
|
end
|
|
|
|
procedure combatturn_handler begin
|
|
variable
|
|
status := get_sfall_arg,
|
|
critter := get_sfall_arg,
|
|
//arg3 := get_sfall_arg,
|
|
pid;
|
|
|
|
//display_msg("Combat Turn: " + status + ", by " + obj_name(critter) + ", arg3: " + arg3);
|
|
if npcControl then begin
|
|
if lightInt then lightInt := round((lightInt / 65536.0) * 100); // calc percent of intensity
|
|
obj_set_light_level(npcControl, lightInt, lightDist); // restore/off light for NPC
|
|
end
|
|
|
|
pid := obj_pid(critter);
|
|
if (status == 1 and (AllowControl(pid) or controlMode == 1)) then begin
|
|
set_dude_obj(critter);
|
|
if (critter != real_dude_obj) then begin
|
|
if not(npcControl) then obj_set_light_level(real_dude_obj, 0, 0); // dude off light
|
|
npcControl := critter;
|
|
lightDist := get_object_data(critter, OBJ_DATA_LIGHT_DISTANCE);
|
|
lightInt := get_object_data(critter, OBJ_DATA_LIGHT_INTENSITY);
|
|
obj_set_light_level(critter, 100, 4);
|
|
|
|
if hasGeckoSkinning then critter_add_trait(critter, TRAIT_PERK, PERK_gecko_skinning_perk, 1);
|
|
inControl := true;
|
|
end else if npcControl then begin
|
|
obj_set_light_level(dude_obj, 100, 4); // set default light
|
|
npcControl := 0;
|
|
end
|
|
if inControl then begin
|
|
// center the screen on the controlled critter and remove roof tiles
|
|
move_to(dude_obj, dude_tile, dude_elevation);
|
|
if (displayName and critter != real_dude_obj) then begin
|
|
set_iface_tag_text(displayName, obj_name(critter), displayNameColor);
|
|
show_iface_tag(displayName);
|
|
end
|
|
end
|
|
end else if inControl then begin
|
|
if displayName then hide_iface_tag(displayName);
|
|
if (status == -1 or AllowControl(pid) == false) then begin
|
|
set_dude_obj(real_dude_obj);
|
|
obj_set_light_level(dude_obj, 100, 4);
|
|
npcControl := 0;
|
|
end
|
|
end
|
|
end
|
|
|
|
procedure gamemodechange_handler begin
|
|
if not(hasGeckoSkinning) then hasGeckoSkinning := has_trait(TRAIT_PERK, real_dude_obj, PERK_gecko_skinning_perk);
|
|
if (inControl and not(get_game_mode BWAND COMBAT)) then begin
|
|
inControl := false;
|
|
if (dude_obj != real_dude_obj) then begin
|
|
set_dude_obj(real_dude_obj);
|
|
obj_set_light_level(dude_obj, 100, 4);
|
|
npcControl := 0;
|
|
end
|
|
move_to(dude_obj, dude_tile, dude_elevation);
|
|
end
|
|
end
|
|
|
|
procedure inventorymove_handler begin
|
|
if (inControl and get_sfall_arg == 3) then begin // armor slot
|
|
if (obj_pid(dude_obj) == PID_MARCUS or proto_data(obj_pid(dude_obj), cr_body_type) != CR_BODY_BIPED) then begin
|
|
display_msg(message_str_game(GAME_MSG_PROTO, 675));
|
|
set_sfall_return(true);
|
|
end
|
|
end
|
|
end
|
|
|
|
procedure invenwield_handler begin
|
|
variable critter := get_sfall_arg,
|
|
item := get_sfall_arg,
|
|
slot := get_sfall_arg,
|
|
event := get_sfall_arg;
|
|
|
|
// Fix weapon duplication when equipping in combat
|
|
if (event and slot == INVEN_TYPE_RIGHT_HAND and AllowControl(obj_pid(critter))) then begin
|
|
set_flags(item, get_flags(item) bwand bwnot(FLAG_LEFT_HAND));
|
|
end
|
|
end
|
|
|
|
procedure start begin
|
|
if (game_loaded and sfall_ver_major >= 4) then begin
|
|
variable configSection := "CombatControl";
|
|
|
|
set_perk_ranks(PERK_gecko_skinning_perk, 1);
|
|
set_perk_level(PERK_gecko_skinning_perk, 999); // prevent it from appearing in the perk selection window
|
|
|
|
controlMode := GetConfig("CombatControl", "Mode", 0);
|
|
if (controlMode > 2) then controlMode := 0;
|
|
if (controlMode > 0) then begin
|
|
displayName := GetConfig("CombatControl", "DisplayName", 0);
|
|
|
|
if displayName then begin
|
|
variable nameTag := add_iface_tag;
|
|
debug_msg("NPC control - added new box: " + nameTag);
|
|
if (nameTag <= 0) then begin // box added?
|
|
variable maxBoxCount := get_ini_setting("ddraw.ini|Misc|BoxBarCount");
|
|
if (maxBoxCount < 0) then maxBoxCount := 9;
|
|
else maxBoxCount += 4;
|
|
if (displayName < 5 or displayName > maxBoxCount) then displayName := 0;
|
|
end else begin
|
|
displayName := nameTag;
|
|
end
|
|
displayNameColor := GetConfig("CombatControl", "DisplayNameColor", 0);
|
|
end
|
|
|
|
pidList := GetConfigListInt("CombatControl", "PIDList");
|
|
fix_array(pidList);
|
|
noCheckArray := (len_array(pidList) == 0);
|
|
|
|
register_hook_proc(HOOK_COMBATTURN, combatturn_handler);
|
|
register_hook_proc(HOOK_GAMEMODECHANGE, gamemodechange_handler);
|
|
register_hook_proc(HOOK_INVENTORYMOVE, inventorymove_handler);
|
|
register_hook_proc(HOOK_INVENWIELD, invenwield_handler);
|
|
end
|
|
end
|
|
end
|