mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Added patch for healing time on worldmap and set_world_map_heal_time
* the time interval check is tied to real time clock, instead of game time.
This commit is contained in:
@@ -392,6 +392,7 @@
|
||||
#define set_unique_id(obj) sfall_func1("set_unique_id", obj)
|
||||
#define set_unjam_locks_time(time) sfall_func1("set_unjam_locks_time", time)
|
||||
#define set_window_flag(winID, flag, value) sfall_func3("set_window_flag", winID, flag, value)
|
||||
#define set_worldmap_heal_time(time) sfall_func1("set_worldmap_heal_time", time)
|
||||
#define show_win sfall_func0("show_window")
|
||||
#define show_window(winName) sfall_func1("show_window", winName)
|
||||
#define signal_close_game sfall_func0("signal_close_game")
|
||||
|
||||
@@ -606,7 +606,7 @@ int ret0 - pass 1 at the start of turn to skip the turn, pass -1 at the end
|
||||
|
||||
#### `HOOK_CARTRAVEL (hs_cartravel.int)`
|
||||
|
||||
Runs continuously during worldmap travel on car.
|
||||
Runs continuously during world map travel by car.
|
||||
|
||||
```
|
||||
int arg0 - vanilla car speed (between 3 and 8 "steps")
|
||||
|
||||
@@ -1132,6 +1132,14 @@ sfall_funcX metarule functions
|
||||
- `frame`: frame number, the first frame starts from zero
|
||||
- `rotation`: rotation to get the frame for, useful when reading FRM files by path
|
||||
|
||||
----
|
||||
#### set_worldmap_heal_time
|
||||
`void sfall_func1("set_worldmap_heal_time", int minutes)`
|
||||
- Sets the time interval in minutes for healing during world map travel
|
||||
- Passing 0 will revert to 1 second in real time (vanilla engine behavior)
|
||||
- Passing -1 will disable healing during travel
|
||||
- The time interval will be reset each time the player reloads the game
|
||||
|
||||
|
||||
****
|
||||
_See other documentation files (arrays.md, hookscripts.md) for related functions reference._
|
||||
|
||||
@@ -225,6 +225,7 @@ FUNC(dude_stand_, 0x418378)
|
||||
FUNC(dude_standup_, 0x418574)
|
||||
FUNC(editor_design_, 0x431DF8)
|
||||
FUNC(elapsed_time_, 0x4C93E0)
|
||||
FUNC(elapsed_tocks_, 0x4C9400)
|
||||
FUNC(elevator_end_, 0x43F6D0)
|
||||
FUNC(elevator_start_, 0x43F324)
|
||||
FUNC(endgame_slideshow_, 0x43F788)
|
||||
|
||||
@@ -123,6 +123,7 @@ void ClearLoopFlag(LoopFlag flag) {
|
||||
}
|
||||
|
||||
static void __stdcall GameModeChange(DWORD state) { // OnGameModeChange
|
||||
Worldmap::OnGameModeChange();
|
||||
HookCommon::GameModeChangeHook(state);
|
||||
}
|
||||
|
||||
|
||||
@@ -146,6 +146,7 @@ static const SfallMetarule metarules[] = {
|
||||
{"set_outline", mf_set_outline, 2, 2, -1, {ARG_OBJECT, ARG_INT}},
|
||||
{"set_quest_failure_value", mf_set_quest_failure_value, 2, 2, -1, {ARG_INT, ARG_INT}},
|
||||
{"set_rest_heal_time", mf_set_rest_heal_time, 1, 1, -1, {ARG_INT}},
|
||||
{"set_worldmap_heal_time", mf_set_worldmap_heal_time, 1, 1, -1, {ARG_INT}},
|
||||
{"set_rest_mode", mf_set_rest_mode, 1, 1, -1, {ARG_INT}},
|
||||
{"set_scr_name", mf_set_scr_name, 0, 1, -1, {ARG_STRING}},
|
||||
{"set_terrain_name", mf_set_terrain_name, 3, 3, -1, {ARG_INT, ARG_INT, ARG_STRING}},
|
||||
|
||||
@@ -202,6 +202,10 @@ void mf_set_rest_heal_time(OpcodeContext& ctx) {
|
||||
Worldmap::SetRestHealTime(ctx.arg(0).rawValue());
|
||||
}
|
||||
|
||||
void mf_set_worldmap_heal_time(OpcodeContext& ctx) {
|
||||
Worldmap::SetWorldMapHealTime(ctx.arg(0).rawValue());
|
||||
}
|
||||
|
||||
void mf_set_rest_mode(OpcodeContext& ctx) {
|
||||
Worldmap::SetRestMode(ctx.arg(0).rawValue());
|
||||
}
|
||||
|
||||
@@ -50,6 +50,8 @@ void mf_get_map_enter_position(OpcodeContext&);
|
||||
|
||||
void mf_set_rest_heal_time(OpcodeContext&);
|
||||
|
||||
void mf_set_worldmap_heal_time(OpcodeContext&);
|
||||
|
||||
void mf_set_rest_mode(OpcodeContext&);
|
||||
|
||||
void mf_set_rest_on_map(OpcodeContext&);
|
||||
|
||||
@@ -57,6 +57,11 @@ static DWORD worldMapTicks;
|
||||
|
||||
static DWORD WorldMapEncounterRate;
|
||||
|
||||
static const long WorldMapHealingDefaultInterval = 0;
|
||||
// Healing interval in game time
|
||||
static long worldMapHealingInterval = WorldMapHealingDefaultInterval;
|
||||
static DWORD worldMapLastHealTime;
|
||||
|
||||
static double tickFract = 0.0;
|
||||
static double mapMultiMod = 1.0;
|
||||
static float scriptMapMulti = 1.0f;
|
||||
@@ -448,6 +453,34 @@ static void WorldmapFpsPatch() {
|
||||
}
|
||||
}
|
||||
|
||||
// Original function checks how many system Ticks (not game ticks) passed since last WM loop iteration and if more than 1000 ms,
|
||||
// applies one healing to the whole party according to their healing rate.
|
||||
// So we hijack it and return number bigger than 1000 to force the event, or 0 to skip it.
|
||||
static DWORD __fastcall wmWorldMap_HealingTimeElapsed(DWORD elapsedTocks) {
|
||||
if (worldMapHealingInterval == 0) return elapsedTocks;
|
||||
if (worldMapHealingInterval > 0 && (*fo::ptr::fallout_game_time - worldMapLastHealTime > (DWORD)worldMapHealingInterval)) {
|
||||
worldMapLastHealTime = *fo::ptr::fallout_game_time;
|
||||
return 10000; // force healing
|
||||
}
|
||||
return 0; // skip healing
|
||||
}
|
||||
|
||||
static void __declspec(naked) wmWorldMap_elapsed_tocks_hook() {
|
||||
__asm {
|
||||
push ecx;
|
||||
call fo::funcoffs::elapsed_tocks_;
|
||||
mov ecx, eax;
|
||||
call wmWorldMap_HealingTimeElapsed;
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void WorldmapHealingRatePatch() {
|
||||
dlogr("Applying world map healing rate patch.", DL_INIT);
|
||||
HookCall(0x4C0085, wmWorldMap_elapsed_tocks_hook);
|
||||
}
|
||||
|
||||
static void PathfinderFixInit() {
|
||||
//if (IniReader::GetConfigInt("Misc", "PathfinderFix", 0)) {
|
||||
dlogr("Applying Pathfinder patch.", DL_INIT);
|
||||
@@ -572,13 +605,20 @@ void Worldmap::SetCarInterfaceArt(DWORD artIndex) {
|
||||
SafeWrite32(0x4C2D9B, artIndex);
|
||||
}
|
||||
|
||||
void Worldmap::SetRestHealTime(DWORD minutes) {
|
||||
void Worldmap::SetRestHealTime(long minutes) {
|
||||
if (minutes > 0) {
|
||||
SafeWrite32(0x499FDE, minutes);
|
||||
restTime = (minutes != 180);
|
||||
}
|
||||
}
|
||||
|
||||
void Worldmap::SetWorldMapHealTime(long minutes) {
|
||||
worldMapHealingInterval = (minutes >= 0)
|
||||
? minutes * 60 * 10
|
||||
: -1;
|
||||
worldMapLastHealTime = *fo::ptr::fallout_game_time;
|
||||
}
|
||||
|
||||
void Worldmap::SetRestMode(DWORD mode) {
|
||||
RestRestore(); // restore default
|
||||
|
||||
@@ -595,8 +635,8 @@ void Worldmap::SetRestMode(DWORD mode) {
|
||||
SafeWrite32(0x42E588, 0x94); // jmp 0x42E620
|
||||
}
|
||||
if (mode & 4) { // bit3 - disable healing during resting
|
||||
SafeWrite16(0x499FD4, 0x9090);
|
||||
SafeWrite16(0x499E93, 0x8FEB); // jmp 0x499E24
|
||||
SafeWrite16(0x499FD4, 0x9090); // Check4Health_
|
||||
SafeWrite16(0x499E93, 0x8FEB); // TimedRest_: jmp 0x499E24
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,6 +718,10 @@ const char* Worldmap::GetCustomAreaTitle(long areaID) {
|
||||
return (it != wmAreaHotSpotTitle.cend()) ? it->second.c_str() : nullptr;
|
||||
}
|
||||
|
||||
void Worldmap::OnGameModeChange() {
|
||||
if (InWorldMap()) worldMapLastHealTime = *fo::ptr::fallout_game_time;
|
||||
}
|
||||
|
||||
void Worldmap::OnGameReset() {
|
||||
SetCarInterfaceArt(433); // set index
|
||||
if (restTime) SetRestHealTime(180);
|
||||
@@ -685,6 +729,7 @@ void Worldmap::OnGameReset() {
|
||||
mapRestInfo.clear();
|
||||
wmTerrainTypeNames.clear();
|
||||
wmAreaHotSpotTitle.clear();
|
||||
worldMapHealingInterval = WorldMapHealingDefaultInterval;
|
||||
}
|
||||
|
||||
void Worldmap::init() {
|
||||
@@ -694,6 +739,7 @@ void Worldmap::init() {
|
||||
MapLimitsPatches();
|
||||
WorldmapFpsPatch();
|
||||
PipBoyAutomapsPatch();
|
||||
WorldmapHealingRatePatch();
|
||||
|
||||
// Add a flashing icon to the Horrigan encounter
|
||||
HookCall(0x4C071C, wmRndEncounterOccurred_hook);
|
||||
|
||||
@@ -29,12 +29,14 @@ public:
|
||||
void init();
|
||||
|
||||
static void OnGameReset();
|
||||
static void OnGameModeChange();
|
||||
|
||||
static void SaveData(HANDLE);
|
||||
static bool LoadData(HANDLE);
|
||||
|
||||
static void SetCarInterfaceArt(DWORD artIndex);
|
||||
static void SetRestHealTime(DWORD minutes);
|
||||
static void SetRestHealTime(long minutes);
|
||||
static void SetWorldMapHealTime(long minutes);
|
||||
static void SetRestMode(DWORD mode);
|
||||
static void SetRestMapLevel(int mapId, long elev, bool canRest);
|
||||
static long __fastcall GetRestMapLevel(long elev, int mapId);
|
||||
|
||||
Reference in New Issue
Block a user