diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index 9b4e2234..92b13b71 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -284,6 +284,8 @@ #define get_current_inven_size(obj) sfall_func1("get_current_inven_size", obj) #define get_cursor_mode sfall_func0("get_cursor_mode") #define get_flags(obj) sfall_func1("get_flags", obj) +#define get_ini_section(file, sect) sfall_func2("get_ini_section", file, sect) +#define get_ini_sections(file) sfall_func1("get_ini_sections", file) #define get_interface_x(winType) sfall_func2("get_window_attribute", winType, 1) #define get_interface_y(winType) sfall_func2("get_window_attribute", winType, 2) #define get_inven_ap_cost sfall_func0("get_inven_ap_cost") diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index 263b9797..6cea5252 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -456,6 +456,13 @@ Some utility/math functions are available: > void sfall_func0("real_dude_obj") - returns the initial dude_obj after taking control of other critters in combat +> array sfall_func1("get_ini_sections", string fileName) +- returns an array of names of all sections in a given INI file + +> array sfall_func2("get_ini_section", string fileName, string section) +- returns an associative array of keys and values for a given INI file and section +- NOTE: all keys and their values will be of String type + > int sfall_func0("car_gas_amount") - returns the current amount of fuel in player's car (between 0 and 80000) - to change fuel amount, use vanilla function: metarule(METARULE_GIVE_CAR_GAS, amount) - amount can be positive or negative diff --git a/sfall/Graphics.cpp b/sfall/Graphics.cpp index 2e3e5fad..2558573d 100644 --- a/sfall/Graphics.cpp +++ b/sfall/Graphics.cpp @@ -37,8 +37,8 @@ static DWORD ResHeight; DWORD GPUBlt; DWORD GraphicsMode; -bool PlayAviMovie = false; -bool AviMovieWidthFit = false; +bool Gfx_PlayAviMovie = false; +bool Gfx_AviMovieWidthFit = false; static DWORD yoffset; //static DWORD xoffset; @@ -590,7 +590,7 @@ static void Refresh() { } void Gfx_RefreshGraphics() { - if (!PlayAviMovie) Refresh(); + if (!Gfx_PlayAviMovie) Refresh(); } HRESULT Gfx_CreateMovieTexture(D3DSURFACE_DESC &desc) { @@ -606,9 +606,9 @@ void Gfx_ReleaseMovieTexture() { void Gfx_SetMovieTexture(bool state) { dlog("\nSet movie texture.", DL_INIT); if (!state) { - PlayAviMovie = false; + Gfx_PlayAviMovie = false; return; - } else if (PlayAviMovie) return; + } else if (Gfx_PlayAviMovie) return; if (!movieTex) Gfx_CreateMovieTexture(movieDesc); D3DSURFACE_DESC &desc = movieDesc; @@ -645,7 +645,7 @@ void Gfx_SetMovieTexture(bool state) { subtitleShow = false; } else if (aviAspect < winAspect) { - if (AviMovieWidthFit || (hrpIsEnabled && *(DWORD*)HRPAddress(0x1006EC10) == 2)) { + if (Gfx_AviMovieWidthFit || (hrpIsEnabled && *(DWORD*)HRPAddress(0x1006EC10) == 2)) { //desc.Width = gWidth; // scales the movie surface to screen width } else { // scales width proportionally and places the movie surface at the center of the window along the X-axis @@ -671,7 +671,7 @@ void Gfx_SetMovieTexture(bool state) { CopyMemory(vertexPointer, shaderVertices, sizeof(shaderVertices)); movieBuffer->Unlock(); - PlayAviMovie = true; + Gfx_PlayAviMovie = true; } void Gfx_ShowMovieFrame(IDirect3DTexture9* tex) { @@ -812,7 +812,7 @@ public: } mainTex->UnlockRect(0); //mainTexLock = false; - //if (PlayAviMovie) return DD_OK; // Blt method is not executed during avi playback because the sfShowFrame_ function is blocked + //if (Gfx_PlayAviMovie) return DD_OK; // Blt method is not executed during avi playback because the sfShowFrame_ function is blocked if (!DeviceLost) { d3d9Device->SetTexture(0, mainTex); @@ -994,7 +994,7 @@ public: if (mainTexLock) mainTex->UnlockRect(0); mainTexLock = false; - if (!IsPlayMovie && !PlayAviMovie) { + if (!IsPlayMovie && !Gfx_PlayAviMovie) { //dlog("\nUnlock -> RefreshGraphics", DL_INIT); Refresh(); } @@ -1061,7 +1061,7 @@ public: primaryDDSurface->SetPalette(0); // update if (FakeDirectDrawSurface::IsPlayMovie) return DD_OK; // prevents flickering at the beginning of playback (w/o HRP & GPUBlt=2) } - if (!PlayAviMovie) { + if (!Gfx_PlayAviMovie) { //dlog("\nSetEntries -> RefreshGraphics", DL_INIT); Refresh(); } diff --git a/sfall/Graphics.h b/sfall/Graphics.h index 0815440a..2b170399 100644 --- a/sfall/Graphics.h +++ b/sfall/Graphics.h @@ -25,12 +25,12 @@ extern DWORD GraphicsMode; extern DWORD GPUBlt; -extern bool PlayAviMovie; -extern bool AviMovieWidthFit; - extern IDirect3D9* d3d9; extern IDirect3DDevice9* d3d9Device; +extern bool Gfx_PlayAviMovie; +extern bool Gfx_AviMovieWidthFit; + void Graphics_Init(); void Graphics_Exit(); void Graphics_OnGameLoad(); diff --git a/sfall/Movies.cpp b/sfall/Movies.cpp index 3122ddea..231b8244 100644 --- a/sfall/Movies.cpp +++ b/sfall/Movies.cpp @@ -595,7 +595,7 @@ void Movies_Init() { if (GraphicsMode != 0) { int allowDShowMovies = GetConfigInt("Graphics", "AllowDShowMovies", 0); if (allowDShowMovies > 0) { - AviMovieWidthFit = (allowDShowMovies >= 2); + Gfx_AviMovieWidthFit = (allowDShowMovies >= 2); MakeJump(0x44E690, gmovie_play_hack); HookCall(0x44E993, gmovie_play_hook_stop); /* NOTE: At this address 0x487781, HRP changes the callback procedure to display mve frames. */ diff --git a/sfall/ScriptExtender.cpp b/sfall/ScriptExtender.cpp index d8a9eb82..da31ffd7 100644 --- a/sfall/ScriptExtender.cpp +++ b/sfall/ScriptExtender.cpp @@ -857,6 +857,8 @@ static const SfallOpcodeMetadata opcodeMetaArray[] = { {mf_create_win, "create_win", {DATATYPE_MASK_STR, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {mf_draw_image, "draw_image", {DATATYPE_MASK_INT | DATATYPE_MASK_STR, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {mf_draw_image_scaled, "draw_image_scaled", {DATATYPE_MASK_INT | DATATYPE_MASK_STR, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, + {mf_get_ini_section, "get_ini_section", {DATATYPE_MASK_STR, DATATYPE_MASK_STR}}, + {mf_get_ini_sections, "get_ini_sections", {DATATYPE_MASK_STR}}, {mf_get_window_attribute, "get_window_attribute", {DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {mf_hide_window, "hide_window", {DATATYPE_MASK_STR}}, {mf_interface_art_draw, "interface_art_draw", {DATATYPE_MASK_INT, DATATYPE_MASK_INT | DATATYPE_MASK_STR, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, diff --git a/sfall/ScriptExtender.h b/sfall/ScriptExtender.h index 51d4281b..4ef5b4c0 100644 --- a/sfall/ScriptExtender.h +++ b/sfall/ScriptExtender.h @@ -22,11 +22,11 @@ #include "FalloutStructs.h" // TODO: replace with enum class -enum SfallDataType { - DATATYPE_NONE = 0, - DATATYPE_INT, - DATATYPE_FLOAT, - DATATYPE_STR +enum SfallDataType : unsigned long { + DATATYPE_NONE = 0, + DATATYPE_INT = 1, + DATATYPE_FLOAT = 2, + DATATYPE_STR = 3, }; typedef struct { diff --git a/sfall/ScriptOps/MetaruleOps.hpp b/sfall/ScriptOps/MetaruleOps.hpp index f76614b2..bd93b95c 100644 --- a/sfall/ScriptOps/MetaruleOps.hpp +++ b/sfall/ScriptOps/MetaruleOps.hpp @@ -134,6 +134,8 @@ static const SfallMetarule metaruleArray[] = { {"get_current_inven_size", mf_get_current_inven_size, 1, 1}, {"get_cursor_mode", mf_get_cursor_mode, 0, 0}, {"get_flags", mf_get_flags, 1, 1}, + {"get_ini_section", mf_get_ini_section, 2, 2}, + {"get_ini_sections", mf_get_ini_sections, 1, 1}, {"get_inven_ap_cost", mf_get_inven_ap_cost, 0, 0}, {"get_map_enter_position", mf_get_map_enter_position, 0, 0}, {"get_metarule_table", mf_get_metarule_table, 0, 0}, diff --git a/sfall/ScriptOps/MiscOps.hpp b/sfall/ScriptOps/MiscOps.hpp index 805681d4..94ec0101 100644 --- a/sfall/ScriptOps/MiscOps.hpp +++ b/sfall/ScriptOps/MiscOps.hpp @@ -18,6 +18,8 @@ #pragma once +#include + #include "main.h" #include "AI.h" @@ -1152,6 +1154,55 @@ static void mf_set_ini_setting() { opHandler.setReturn(-1); } +static void mf_get_ini_sections() { + std::string fileName = std::string(".\\") + opHandler.arg(0).strValue(); + if (!GetPrivateProfileSectionNamesA(gTextBuffer, GlblTextBufferSize(), fileName.c_str())) { + opHandler.setReturn(CreateTempArray(0, 0)); + return; + } + std::vector sections; + char* section = gTextBuffer; + while (*section != 0) { + sections.push_back(section); // position + section += std::strlen(section) + 1; + } + size_t sz = sections.size(); + int arrayId = CreateTempArray(sz, 0); + sArrayVar &arr = arrays[arrayId]; + + for (size_t i = 0; i < sz; ++i) { + size_t j = i + 1; + int len = (j < sz) ? sections[j] - sections[i] - 1 : -1; + arr.val[i].set(sections[i], len); // copy string from buffer + } + opHandler.setReturn(arrayId); +} + +static void mf_get_ini_section() { + std::string fileName = std::string(".\\") + opHandler.arg(0).strValue(); + const char* section = opHandler.arg(1).strValue(); + int arrayId = CreateTempArray(-1, 0); // associative + + if (GetPrivateProfileSectionA(section, gTextBuffer, GlblTextBufferSize(), fileName.c_str())) { + sArrayVar &arr = arrays[arrayId]; + char *key = gTextBuffer, *val = nullptr; + while (*key != 0) { + char* val = std::strpbrk(key, "="); + if (val != nullptr) { + *val = '\0'; + val += 1; + + setArray(arrayId, ScriptValue(key).rawValue(), VAR_TYPE_STR, ScriptValue(val).rawValue(), VAR_TYPE_STR, 0); + + key = val + std::strlen(val) + 1; + } else { + key += std::strlen(key) + 1; + } + } + } + opHandler.setReturn(arrayId); +} + static void mf_npc_engine_level_up() { if (opHandler.arg(0).asBool()) { if (!npcEngineLevelUp) SafeWrite16(0x4AFC1C, 0x840F); // enable diff --git a/sfall/ScriptOps/WorldmapOps.hpp b/sfall/ScriptOps/WorldmapOps.hpp index a7bb69d2..03b7674b 100644 --- a/sfall/ScriptOps/WorldmapOps.hpp +++ b/sfall/ScriptOps/WorldmapOps.hpp @@ -19,7 +19,6 @@ #pragma once #include "main.h" -#include "Arrays.h" #include "ScriptExtender.h" #include "Worldmap.h"