mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Added a new mode to NPC combat control mod (WIP)
This commit is contained in:
@@ -35,6 +35,7 @@ MotionScanner=0
|
|||||||
;Set to 0 to disable
|
;Set to 0 to disable
|
||||||
;Set to 1 to control all critters in combat
|
;Set to 1 to control all critters in combat
|
||||||
;Set to 2 to control all party members
|
;Set to 2 to control all party members
|
||||||
|
;Set to 3 to order party members to attack a specified target instead of controlling them by yourself
|
||||||
Mode=0
|
Mode=0
|
||||||
;If you want to control only specific critters, uncomment the PIDList line and set a comma delimited list of PIDs
|
;If you want to control only specific critters, uncomment the PIDList line and set a comma delimited list of PIDs
|
||||||
;PIDList=62,89,97,107,160,161
|
;PIDList=62,89,97,107,160,161
|
||||||
|
|||||||
Binary file not shown.
@@ -12,12 +12,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "..\headers\define.h"
|
#include "..\headers\define.h"
|
||||||
#include "..\headers\command.h"
|
//#include "..\headers\command.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
#define OBJ_DATA_LIGHT_DISTANCE (0x6C)
|
#define OBJ_DATA_LIGHT_DISTANCE (0x6C)
|
||||||
#define OBJ_DATA_LIGHT_INTENSITY (0x70)
|
#define OBJ_DATA_LIGHT_INTENSITY (0x70)
|
||||||
|
|
||||||
|
procedure start;
|
||||||
|
procedure AllowControl(variable pid);
|
||||||
|
procedure CombatTurn_Handler;
|
||||||
|
procedure GameModeChange_Handler;
|
||||||
|
procedure InventoryMove_Handler;
|
||||||
|
procedure InvenWield_Handler;
|
||||||
|
|
||||||
variable
|
variable
|
||||||
controlMode,
|
controlMode,
|
||||||
noCheckArray,
|
noCheckArray,
|
||||||
@@ -32,7 +39,7 @@ procedure AllowControl(variable pid) begin
|
|||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
|
|
||||||
procedure combatturn_handler begin
|
procedure CombatTurn_Handler begin
|
||||||
variable
|
variable
|
||||||
status := get_sfall_arg,
|
status := get_sfall_arg,
|
||||||
critter := get_sfall_arg,
|
critter := get_sfall_arg,
|
||||||
@@ -98,7 +105,7 @@ procedure combatturn_handler begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
procedure gamemodechange_handler begin
|
procedure GameModeChange_Handler begin
|
||||||
if (inControl and not(get_game_mode BWAND COMBAT)) then begin
|
if (inControl and not(get_game_mode BWAND COMBAT)) then begin
|
||||||
inControl := false;
|
inControl := false;
|
||||||
npcControl := 0;
|
npcControl := 0;
|
||||||
@@ -106,7 +113,7 @@ procedure gamemodechange_handler begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
procedure inventorymove_handler begin
|
procedure InventoryMove_Handler begin
|
||||||
if (npcControl and get_sfall_arg == 3) then begin // armor slot
|
if (npcControl 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
|
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));
|
display_msg(message_str_game(GAME_MSG_PROTO, 675));
|
||||||
@@ -115,8 +122,9 @@ procedure inventorymove_handler begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
procedure invenwield_handler begin
|
procedure InvenWield_Handler begin
|
||||||
variable critter := get_sfall_arg,
|
variable
|
||||||
|
critter := get_sfall_arg,
|
||||||
item := get_sfall_arg,
|
item := get_sfall_arg,
|
||||||
slot := get_sfall_arg,
|
slot := get_sfall_arg,
|
||||||
event := get_sfall_arg;
|
event := get_sfall_arg;
|
||||||
@@ -135,7 +143,10 @@ procedure start begin
|
|||||||
set_perk_level(PERK_gecko_skinning_perk, 999); // prevent it from appearing in the perk selection window
|
set_perk_level(PERK_gecko_skinning_perk, 999); // prevent it from appearing in the perk selection window
|
||||||
|
|
||||||
controlMode := GetConfig("CombatControl", "Mode", 0);
|
controlMode := GetConfig("CombatControl", "Mode", 0);
|
||||||
if (controlMode > 2) then controlMode := 0;
|
if (controlMode >= 3) then begin
|
||||||
|
if (controlMode == 3) then metarule3(999, 0, 0, 0); // enable feature: order party members to attack a specified target
|
||||||
|
controlMode := 0;
|
||||||
|
end
|
||||||
if (controlMode > 0) then begin
|
if (controlMode > 0) then begin
|
||||||
displayName := GetConfig("CombatControl", "DisplayName", 0);
|
displayName := GetConfig("CombatControl", "DisplayName", 0);
|
||||||
|
|
||||||
@@ -160,10 +171,10 @@ procedure start begin
|
|||||||
perksList := GetConfigListInt("CombatControl", "PerksList");
|
perksList := GetConfigListInt("CombatControl", "PerksList");
|
||||||
fix_array(perksList);
|
fix_array(perksList);
|
||||||
|
|
||||||
register_hook_proc(HOOK_COMBATTURN, combatturn_handler);
|
register_hook_proc(HOOK_COMBATTURN, CombatTurn_Handler);
|
||||||
register_hook_proc(HOOK_GAMEMODECHANGE, gamemodechange_handler);
|
register_hook_proc(HOOK_GAMEMODECHANGE, GameModeChange_Handler);
|
||||||
register_hook_proc(HOOK_INVENTORYMOVE, inventorymove_handler);
|
register_hook_proc(HOOK_INVENTORYMOVE, InventoryMove_Handler);
|
||||||
register_hook_proc(HOOK_INVENWIELD, invenwield_handler);
|
register_hook_proc(HOOK_INVENWIELD, InvenWield_Handler);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Binary file not shown.
@@ -86,6 +86,7 @@ static std::vector<HackPair> hackAddr = {
|
|||||||
// module: PartyControl
|
// module: PartyControl
|
||||||
{0x422BDE, 1}, {0x4229EC, 1},
|
{0x422BDE, 1}, {0x4229EC, 1},
|
||||||
{0x49EB09, 1}, {0x49EB0A, 4}, {0x458242, 1}, {0x458243, 4}, {0x458326, 1}, {0x458327, 4}, {0x42E25B, 1}, {0x42E25C, 4}, // hookcalls
|
{0x49EB09, 1}, {0x49EB0A, 4}, {0x458242, 1}, {0x458243, 4}, {0x458326, 1}, {0x458327, 4}, {0x42E25B, 1}, {0x42E25C, 4}, // hookcalls
|
||||||
|
{0x44C4A7, 1}, {0x44C4A8, 4}, {0x44C75F, 1}, {0x44C760, 4}, {0x44C69A, 1}, {0x44C69B, 4}, {0x44B830, 1}, {0x44B831, 4}, // hookcalls for party order attack
|
||||||
// module: Perks
|
// module: Perks
|
||||||
{0x43C77C, 1}, {0x43C77D, 4}, // hookcall
|
{0x43C77C, 1}, {0x43C77D, 4}, // hookcall
|
||||||
{0x478AC4, 1}, {0x478AC5, 4}, {0x496823, 5},
|
{0x478AC4, 1}, {0x478AC5, 4}, {0x496823, 5},
|
||||||
|
|||||||
@@ -186,10 +186,10 @@ void ToggleNpcFlag(fo::GameObject* npc, long flag, bool set) {
|
|||||||
|
|
||||||
// Returns the position of party member in the existing table (begins from 1)
|
// Returns the position of party member in the existing table (begins from 1)
|
||||||
long IsPartyMemberByPid(long pid) {
|
long IsPartyMemberByPid(long pid) {
|
||||||
size_t patryCount = fo::var::partyMemberMaxCount;
|
size_t partyCount = fo::var::partyMemberMaxCount;
|
||||||
if (patryCount) {
|
if (partyCount) {
|
||||||
DWORD* memberPids = fo::var::partyMemberPidList; // pids from party.txt
|
DWORD* memberPids = fo::var::partyMemberPidList; // pids from party.txt
|
||||||
for (size_t i = 0; i < patryCount; i++) {
|
for (size_t i = 0; i < partyCount; i++) {
|
||||||
if (memberPids[i] == pid) return i + 1;
|
if (memberPids[i] == pid) return i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -802,6 +802,79 @@ namespace WinFlags {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace AIpref {
|
||||||
|
enum distance : long
|
||||||
|
{
|
||||||
|
stay_close = 0,
|
||||||
|
charge = 1,
|
||||||
|
snipe = 2,
|
||||||
|
on_your_own = 3,
|
||||||
|
stay = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
enum disposition : long
|
||||||
|
{
|
||||||
|
none = -1,
|
||||||
|
custom = 0,
|
||||||
|
coward = 1,
|
||||||
|
defensive = 2,
|
||||||
|
aggressive = 3,
|
||||||
|
berserk = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class attack_who : long
|
||||||
|
{
|
||||||
|
whomever_attacking_me = 0,
|
||||||
|
strongest = 1,
|
||||||
|
weakest = 2,
|
||||||
|
whomever = 3,
|
||||||
|
closest = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class run_away_mode : long
|
||||||
|
{
|
||||||
|
none = -1, // get the value from the cap.min_hp (in cai_get_min_hp_)
|
||||||
|
coward = 0, // 0%
|
||||||
|
finger_hurts = 1, // 25% of the lost amount of health
|
||||||
|
bleeding = 2, // 40% of the lost amount of health
|
||||||
|
not_feeling_good = 3, // 60% of the lost amount of health
|
||||||
|
tourniquet = 4, // 75% of the lost amount of health
|
||||||
|
never = 5 // 100%
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class weapon_pref : long
|
||||||
|
{
|
||||||
|
no_pref = 0,
|
||||||
|
melee = 1,
|
||||||
|
melee_over_ranged = 2,
|
||||||
|
ranged_over_melee = 3,
|
||||||
|
ranged = 4,
|
||||||
|
unarmed = 5,
|
||||||
|
unarmed_over_thrown = 6, // not available in party member control panel
|
||||||
|
random = 7 // not available in party member control panel
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class area_attack_mode : long
|
||||||
|
{
|
||||||
|
no_pref = -1, // special logic for NPC (not available in party member control panel)
|
||||||
|
always = 0,
|
||||||
|
sometimes = 1, // use random value from cap.secondary_freq
|
||||||
|
be_sure = 2, // 85% hit chance
|
||||||
|
be_careful = 3, // 50% hit chance
|
||||||
|
be_absolutely_sure = 4, // 95% hit chance
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class chem_use_mode : long
|
||||||
|
{
|
||||||
|
clean = 0,
|
||||||
|
stims_when_hurt_little = 1,
|
||||||
|
stims_when_hurt_lots = 2,
|
||||||
|
sometimes = 3,
|
||||||
|
anytime = 4,
|
||||||
|
always = 5,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
enum QueueType : long
|
enum QueueType : long
|
||||||
{
|
{
|
||||||
drug_effect_event = 0, // critter use drug
|
drug_effect_event = 0, // critter use drug
|
||||||
|
|||||||
@@ -3598,7 +3598,7 @@ void BugFixes::init()
|
|||||||
// Fix broken Print() script function
|
// Fix broken Print() script function
|
||||||
HookCall(0x461AD4, (void*)fo::funcoffs::windowOutput_);
|
HookCall(0x461AD4, (void*)fo::funcoffs::windowOutput_);
|
||||||
|
|
||||||
// Fix for the flags of non-door objects being set/unset when opening/closing objects (e.g. using obj_close/open functions)
|
// Fix for the flags of non-door objects being set/unset when using obj_close/open functions
|
||||||
MakeCall(0x49CBF7, check_door_state_hack_close, 2);
|
MakeCall(0x49CBF7, check_door_state_hack_close, 2);
|
||||||
MakeCall(0x49CB30, check_door_state_hack_open, 1);
|
MakeCall(0x49CB30, check_door_state_hack_open, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "..\main.h"
|
#include "..\main.h"
|
||||||
#include "..\FalloutEngine\Fallout2.h"
|
#include "..\FalloutEngine\Fallout2.h"
|
||||||
#include "LoadGameHook.h"
|
#include "LoadGameHook.h"
|
||||||
|
#include "PartyControl.h"
|
||||||
|
|
||||||
#include "MetaruleExtender.h"
|
#include "MetaruleExtender.h"
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ static bool HorriganEncounterDisabled = false;
|
|||||||
enum class MetaruleFunction : long {
|
enum class MetaruleFunction : long {
|
||||||
SET_HORRIGAN_ENCOUNTER = 200, // sets the number of days for the Frank Horrigan encounter or disable encounter
|
SET_HORRIGAN_ENCOUNTER = 200, // sets the number of days for the Frank Horrigan encounter or disable encounter
|
||||||
CLEAR_KEYBOARD_BUFFER = 201, // clears the keyboard input buffer, should be used in the HOOK_KEYPRESS hook to clear keyboard events in some cases
|
CLEAR_KEYBOARD_BUFFER = 201, // clears the keyboard input buffer, should be used in the HOOK_KEYPRESS hook to clear keyboard events in some cases
|
||||||
|
EXT_PARTY_ORDER_ATTACK = 999
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -61,6 +63,9 @@ static long __fastcall op_metarule3_ext(long metafunc, long* args) {
|
|||||||
case MetaruleFunction::CLEAR_KEYBOARD_BUFFER:
|
case MetaruleFunction::CLEAR_KEYBOARD_BUFFER:
|
||||||
__asm call fo::funcoffs::kb_clear_;
|
__asm call fo::funcoffs::kb_clear_;
|
||||||
break;
|
break;
|
||||||
|
case MetaruleFunction::EXT_PARTY_ORDER_ATTACK:
|
||||||
|
PartyControl::MemberOrderAttackPatch();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fo::func::debug_printf("\nOPCODE ERROR: metarule3(%d, ...) - metarule function number does not exist.\n > Script: %s, procedure %s.",
|
fo::func::debug_printf("\nOPCODE ERROR: metarule3(%d, ...) - metarule function number does not exist.\n > Script: %s, procedure %s.",
|
||||||
metafunc, fo::var::currentProgram->fileName, fo::func::findCurrentProc(fo::var::currentProgram));
|
metafunc, fo::var::currentProgram->fileName, fo::func::findCurrentProc(fo::var::currentProgram));
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "HookScripts.h"
|
#include "HookScripts.h"
|
||||||
#include "LoadGameHook.h"
|
#include "LoadGameHook.h"
|
||||||
#include "ScriptExtender.h"
|
#include "ScriptExtender.h"
|
||||||
|
//#include "Objects.h"
|
||||||
|
|
||||||
#include "PartyControl.h"
|
#include "PartyControl.h"
|
||||||
|
|
||||||
@@ -271,6 +272,9 @@ static void SetCurrentDude(fo::GameObject* npc) {
|
|||||||
}
|
}
|
||||||
if (!exist) __asm call fo::funcoffs::critter_sneak_check_;
|
if (!exist) __asm call fo::funcoffs::critter_sneak_check_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if (!isPartyMember) Objects::SetObjectUniqueID(npc);
|
||||||
|
|
||||||
fo::func::intface_redraw();
|
fo::func::intface_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,6 +626,126 @@ static void __declspec(naked) gdControlUpdateInfo_hook() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool partyOrderPickTargetLoop;
|
||||||
|
static char partyOrderAttackMsg[33];
|
||||||
|
|
||||||
|
// disables the display of the hit chance value when picking a target
|
||||||
|
static void __declspec(naked) gmouse_bk_process_hack() {
|
||||||
|
__asm {
|
||||||
|
mov edx, -1; // mode
|
||||||
|
mov eax, ds:[FO_VAR_gmouse_3d_current_mode];
|
||||||
|
test partyOrderPickTargetLoop, 0xFF;
|
||||||
|
cmovnz eax, edx;
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __fastcall action_attack_to(long unused, fo::GameObject* partyMember) {
|
||||||
|
fo::func::gmouse_set_cursor(20);
|
||||||
|
fo::func::gmouse_3d_set_mode(2);
|
||||||
|
|
||||||
|
fo::GameObject* targetObject = nullptr;
|
||||||
|
fo::GameObject* validTarget = nullptr;
|
||||||
|
|
||||||
|
long outlineColor; // backup color
|
||||||
|
fo::BoundRect rect;
|
||||||
|
partyOrderPickTargetLoop = true;
|
||||||
|
|
||||||
|
do {
|
||||||
|
fo::GameObject* underObject = fo::func::object_under_mouse(1, 0, fo::var::map_elevation);
|
||||||
|
|
||||||
|
if (targetObject && targetObject != underObject) {
|
||||||
|
targetObject->outline = outlineColor;
|
||||||
|
fo::func::obj_bound(targetObject, &rect);
|
||||||
|
if (!outlineColor) {
|
||||||
|
rect.x--;
|
||||||
|
rect.y--;
|
||||||
|
rect.offx += 2;
|
||||||
|
rect.offy += 2;
|
||||||
|
}
|
||||||
|
fo::func::tile_refresh_rect(&rect, fo::var::map_elevation);
|
||||||
|
targetObject = validTarget = nullptr;
|
||||||
|
}
|
||||||
|
if (underObject && underObject != targetObject && underObject->IsCritter() && underObject->critter.teamNum != partyMember->critter.teamNum) {
|
||||||
|
if (underObject->critter.IsNotDead()) {
|
||||||
|
outlineColor = underObject->outline;
|
||||||
|
|
||||||
|
if (underObject->critter.combatState) {
|
||||||
|
underObject->outline = 254 << 8;
|
||||||
|
validTarget = underObject;
|
||||||
|
} else {
|
||||||
|
underObject->outline = 10 << 8;
|
||||||
|
}
|
||||||
|
fo::func::obj_bound(underObject, &rect);
|
||||||
|
fo::func::tile_refresh_rect(&rect, fo::var::map_elevation);
|
||||||
|
targetObject = underObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (validTarget && *(DWORD*)FO_VAR_mouse_buttons == 1) break; // left mouse button
|
||||||
|
|
||||||
|
} while (*(DWORD*)FO_VAR_mouse_buttons != 2 && fo::func::get_input() != 27); // 27 - escape code
|
||||||
|
|
||||||
|
if (validTarget && *(DWORD*)FO_VAR_mouse_buttons == 1) {
|
||||||
|
partyMember->critter.whoHitMe = validTarget;
|
||||||
|
validTarget->outline = outlineColor;
|
||||||
|
|
||||||
|
fo::AIcap* cap = fo::func::ai_cap(partyMember);
|
||||||
|
if (cap->disposition == fo::AIpref::disposition::custom) {
|
||||||
|
cap->attack_who = (long)fo::AIpref::attack_who::whomever;
|
||||||
|
}
|
||||||
|
std::strcpy((char*)FO_VAR_attack_str, partyOrderAttackMsg);
|
||||||
|
fo::func::ai_print_msg(partyMember, 0); // float message
|
||||||
|
}
|
||||||
|
|
||||||
|
partyOrderPickTargetLoop = false;
|
||||||
|
//*(DWORD*)FO_VAR_mouse_buttons = 0;
|
||||||
|
|
||||||
|
fo::func::gmouse_set_cursor(0);
|
||||||
|
fo::func::gmouse_3d_set_mode(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) gmouse_handle_event_hook() {
|
||||||
|
__asm {
|
||||||
|
test ds:[FO_VAR_combat_state], 1;
|
||||||
|
jnz action_attack_to;
|
||||||
|
jmp fo::funcoffs::action_talk_to_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) gmouse_handle_event_hack() {
|
||||||
|
__asm {
|
||||||
|
test ds:[FO_VAR_combat_state], 1;
|
||||||
|
jnz pick;
|
||||||
|
retn;
|
||||||
|
pick:
|
||||||
|
mov eax, edi; // critter
|
||||||
|
call fo::funcoffs::isPartyMember_;
|
||||||
|
test eax, eax;
|
||||||
|
jz end;
|
||||||
|
mov bl, 1;
|
||||||
|
mov eax, 5;
|
||||||
|
mov [esp + 4], eax; // actionMenuList
|
||||||
|
mov word ptr ds:[FO_VAR_gmouse_3d_action_nums][5*2], 81; // index in INTRFACE.LST (ACTIONI.FRM)
|
||||||
|
end:
|
||||||
|
or eax, 1;
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) gmouse_handle_event_hook_restore() {
|
||||||
|
__asm {
|
||||||
|
mov word ptr ds:[FO_VAR_gmouse_3d_action_nums][5*2], 263; // index in INTRFACE.LST (TALKN.FRM)
|
||||||
|
jmp fo::funcoffs::map_enable_bk_processes_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PartyControl::MemberOrderAttackPatch() {
|
||||||
|
MakeCall(0x44C4A7, gmouse_handle_event_hack, 2);
|
||||||
|
HookCall(0x44C75F, gmouse_handle_event_hook);
|
||||||
|
HookCall(0x44C69A, gmouse_handle_event_hook_restore);
|
||||||
|
MakeCall(0x44B830, gmouse_bk_process_hack);
|
||||||
|
}
|
||||||
|
|
||||||
static void NpcAutoLevelPatch() {
|
static void NpcAutoLevelPatch() {
|
||||||
npcAutoLevelEnabled = GetConfigInt("Misc", "NPCAutoLevel", 0) != 0;
|
npcAutoLevelEnabled = GetConfigInt("Misc", "NPCAutoLevel", 0) != 0;
|
||||||
if (npcAutoLevelEnabled) {
|
if (npcAutoLevelEnabled) {
|
||||||
@@ -663,6 +787,8 @@ void PartyControl::init() {
|
|||||||
Translate("sfall", "PartyAddictMsg", "Addict", addictMsg, 16);
|
Translate("sfall", "PartyAddictMsg", "Addict", addictMsg, 16);
|
||||||
dlogr(" Done", DL_INIT);
|
dlogr(" Done", DL_INIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Translate("sfall", "PartyOrderAttack", "I'll take care of it.", partyOrderAttackMsg, 33);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PartyControl::exit() {
|
void PartyControl::exit() {
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ public:
|
|||||||
|
|
||||||
// Returns pointer to "real" dude, which is different from "dude_obj" when controlling another critter
|
// Returns pointer to "real" dude, which is different from "dude_obj" when controlling another critter
|
||||||
static fo::GameObject* RealDudeObject();
|
static fo::GameObject* RealDudeObject();
|
||||||
|
|
||||||
|
static void MemberOrderAttackPatch();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool npcAutoLevelEnabled;
|
extern bool npcAutoLevelEnabled;
|
||||||
|
|||||||
Reference in New Issue
Block a user