Files
sfall/artifacts/mods/gl_partycontrol.ssl
T
NovaRain 143f6895a4 Fixed a bug in CheckWeaponAmmoCost (from Mr.Stalin)
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.
2019-04-07 10:59:02 +08:00

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