mirror of
https://github.com/fallout2-ce/fallout2-ce.git
synced 2026-07-27 16:47:11 -07:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9936e10ff | ||
|
|
6bd1daae0b | ||
|
|
d8336761cc | ||
|
|
5055e2b0d4 | ||
|
|
a0954c8df7 | ||
|
|
7abab85e0a |
@@ -38,7 +38,7 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
|
||||
| Hooks / Hook functions | init_hook<br>get_sfall_arg<br>get_sfall_args<br>get_sfall_arg_at<br>set_sfall_return<br>set_sfall_arg<br>register_hook<br>register_hook_proc<br>register_hook_proc_spec | âś… except init_hook | See below for implemented hooks. `init_hook` is deprecated and will not be implemented. register_hook_proc and register_hook_proc_spec both add hooks to the *end* of the hook list, instead of beginning and end, respectively. |
|
||||
| Arrays / Array functions | create_array<br>temp_array<br>fix_array<br>get/set_array<br>resize_array<br>free_array<br>scan_array<br>len_array<br>save/load_array<br>array_key<br>arrayexpr | âś… except save_array, load_array | - |
|
||||
| Perks and traits / NPC perks | set_fake_perk_npc<br>set_fake_trait_npc<br>set_selectable_perk_npc<br>has_fake_perk_npc<br>has_fake_trait_npc | not implemented | - |
|
||||
| Global scripts / Global script functions | set_global_script_repeat<br>set_global_script_type<br>available_global_script_types | implemented: all except available_global_script_types | - |
|
||||
| Global scripts / Global script functions | set_global_script_repeat<br>set_global_script_type<br>available_global_script_types | implemented: all except available_global_script_types | `GlobalScriptPaths` masks now match archive-backed scripts regardless of `/` vs `\` separators, matching Windows-style `.dat` contents on non-Windows hosts. |
|
||||
| Combat | attack_is_aimed<br>block_combat<br>force_aimed_shots<br>disable_aimed_shots<br>get_attack_type<br>get/set_bodypart_hit_modifier<br>combat_data<br>get/set/reset_critical_table<br>get_last_target<br>get_last_attacker<br>set_critter_burst_disable<br>get/set_critter_current_ap<br>set_spray_settings<br>get/set_combat_free_move | implemented: only get_attack_type, get_bodypart_hit_modifier, combat_data, set_bodypart_hit_modifier | - |
|
||||
| Car | set_car_current_town<br>car_gas_amount<br>set_car_intface_art | implemented: all except set_car_intface_art | - |
|
||||
| Interface / Windows and images | art_frame_data<br>interface_art_draw<br>interface_print<br>draw_image<br>draw_image_scaled<br>get_window_under_mouse<br>create_win<br>get_window_attribute<br>message_box<br>set_window_flag<br>win_fill_color<br>interface_overlay<br>dialog_message<br>get_text_width<br>hide_window<br>show_window | implemented: only message_box, get_text_width, show_window | - |
|
||||
|
||||
@@ -641,7 +641,7 @@ int fileNameListInit(const char* pattern, char*** fileNameListPtr)
|
||||
char dir[COMPAT_MAX_DIR];
|
||||
char fileName[COMPAT_MAX_FNAME];
|
||||
char extension[COMPAT_MAX_EXT];
|
||||
compat_windows_path_to_native(name);
|
||||
compat_path_to_native(name);
|
||||
compat_splitpath(name, nullptr, dir, fileName, extension);
|
||||
|
||||
if (!isWildcard || *dir == '\0' || (strchr(dir, '\\') == nullptr && strchr(dir, '/') == nullptr)) {
|
||||
|
||||
+26
-4
@@ -42,6 +42,7 @@ static DFile* dfileOpenInternal(DBase* dbase, const char* filename, const char*
|
||||
static int dfileReadCharInternal(DFile* stream);
|
||||
static bool dfileReadCompressed(DFile* stream, void* ptr, size_t size);
|
||||
static void dfileUngetCompressed(DFile* stream, int ch);
|
||||
static bool dfilePathMatchesPattern(const char* pattern, const char* path);
|
||||
|
||||
// Reads .DAT file contents.
|
||||
//
|
||||
@@ -201,11 +202,15 @@ bool dbaseClose(DBase* dbase)
|
||||
// 0x4E5308
|
||||
bool dbaseFindFirstEntry(DBase* dbase, DFileFindData* findFileData, const char* pattern)
|
||||
{
|
||||
// fpattern-matching requires native-separators
|
||||
assert(pattern != nullptr);
|
||||
compat_strlcpy(findFileData->pattern, pattern, sizeof(findFileData->pattern));
|
||||
compat_path_to_native(findFileData->pattern);
|
||||
|
||||
for (int index = 0; index < dbase->entriesLength; index++) {
|
||||
DBaseEntry* entry = &(dbase->entries[index]);
|
||||
if (fpattern_match(pattern, entry->path)) {
|
||||
if (dfilePathMatchesPattern(findFileData->pattern, entry->path)) {
|
||||
strcpy(findFileData->fileName, entry->path);
|
||||
strcpy(findFileData->pattern, pattern);
|
||||
findFileData->index = index;
|
||||
return true;
|
||||
}
|
||||
@@ -219,7 +224,7 @@ bool dbaseFindNextEntry(DBase* dbase, DFileFindData* findFileData)
|
||||
{
|
||||
for (int index = findFileData->index + 1; index < dbase->entriesLength; index++) {
|
||||
DBaseEntry* entry = &(dbase->entries[index]);
|
||||
if (fpattern_match(findFileData->pattern, entry->path)) {
|
||||
if (dfilePathMatchesPattern(findFileData->pattern, entry->path)) {
|
||||
strcpy(findFileData->fileName, entry->path);
|
||||
findFileData->index = index;
|
||||
return true;
|
||||
@@ -638,7 +643,15 @@ static int dbaseFindEntryByFilePath(const void* file, const void* entryName)
|
||||
// 0x4E5D9C
|
||||
static DFile* dfileOpenInternal(DBase* dbase, const char* filePath, const char* mode, DFile* dfile)
|
||||
{
|
||||
DBaseEntry* entry = (DBaseEntry*)bsearch(filePath, dbase->entries, dbase->entriesLength, sizeof(*dbase->entries), dbaseFindEntryByFilePath);
|
||||
assert(filePath != nullptr);
|
||||
|
||||
// .dat files contain windows path separators
|
||||
char normalizedFilePath[COMPAT_MAX_PATH];
|
||||
compat_strlcpy(normalizedFilePath, filePath, sizeof(normalizedFilePath));
|
||||
compat_path_to_windows(normalizedFilePath);
|
||||
|
||||
DBaseEntry* entry;
|
||||
entry = (DBaseEntry*)bsearch(normalizedFilePath, dbase->entries, dbase->entriesLength, sizeof(*dbase->entries), dbaseFindEntryByFilePath);
|
||||
if (entry == nullptr) {
|
||||
goto err;
|
||||
}
|
||||
@@ -860,4 +873,13 @@ static void dfileUngetCompressed(DFile* stream, int ch)
|
||||
stream->position--;
|
||||
}
|
||||
|
||||
// pattern must be normalized to native paths, since that's what fpattern requires
|
||||
static bool dfilePathMatchesPattern(const char* pattern, const char* path)
|
||||
{
|
||||
char normalizedPath[COMPAT_MAX_PATH];
|
||||
compat_strlcpy(normalizedPath, path, sizeof(normalizedPath));
|
||||
compat_path_to_native(normalizedPath);
|
||||
return fpattern_match(pattern, normalizedPath);
|
||||
}
|
||||
|
||||
} // namespace fallout
|
||||
|
||||
+2
-2
@@ -132,7 +132,7 @@ bool gameConfigInit(bool isMapper, int argc, char** argv)
|
||||
// CE: Detect alternative default music directory.
|
||||
char alternativeMusicPath[COMPAT_MAX_PATH];
|
||||
strcpy(alternativeMusicPath, "data\\sound\\music\\*.acm");
|
||||
compat_windows_path_to_native(alternativeMusicPath);
|
||||
compat_path_to_native(alternativeMusicPath);
|
||||
compat_resolve_path(alternativeMusicPath);
|
||||
|
||||
char** acms;
|
||||
@@ -260,7 +260,7 @@ static void gameConfigResolvePath(const char* section, const char* key)
|
||||
{
|
||||
char* path;
|
||||
configGetString(&gGameConfig, section, key, &path);
|
||||
compat_windows_path_to_native(path);
|
||||
compat_path_to_native(path);
|
||||
compat_resolve_path(path);
|
||||
}
|
||||
|
||||
|
||||
+48
-11
@@ -1,5 +1,6 @@
|
||||
#include "platform_compat.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -38,6 +39,23 @@ int compat_strnicmp(const char* string1, const char* string2, size_t size)
|
||||
return SDL_strncasecmp(string1, string2, size);
|
||||
}
|
||||
|
||||
size_t compat_strlcpy(char* dest, const char* src, size_t size)
|
||||
{
|
||||
size_t srcLength = strlen(src);
|
||||
|
||||
if (size != 0) {
|
||||
size_t copyLength = srcLength;
|
||||
if (copyLength >= size) {
|
||||
copyLength = size - 1;
|
||||
}
|
||||
|
||||
memcpy(dest, src, copyLength);
|
||||
dest[copyLength] = '\0';
|
||||
}
|
||||
|
||||
return srcLength;
|
||||
}
|
||||
|
||||
char* compat_strupr(char* string)
|
||||
{
|
||||
return SDL_strupr(string);
|
||||
@@ -205,7 +223,7 @@ int compat_mkdir(const char* path)
|
||||
{
|
||||
char nativePath[COMPAT_MAX_PATH];
|
||||
strcpy(nativePath, path);
|
||||
compat_windows_path_to_native(nativePath);
|
||||
compat_path_to_native(nativePath);
|
||||
compat_resolve_path(nativePath);
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -230,7 +248,7 @@ FILE* compat_fopen(const char* path, const char* mode)
|
||||
{
|
||||
char nativePath[COMPAT_MAX_PATH];
|
||||
strcpy(nativePath, path);
|
||||
compat_windows_path_to_native(nativePath);
|
||||
compat_path_to_native(nativePath);
|
||||
compat_resolve_path(nativePath);
|
||||
return fopen(nativePath, mode);
|
||||
}
|
||||
@@ -239,7 +257,7 @@ gzFile compat_gzopen(const char* path, const char* mode)
|
||||
{
|
||||
char nativePath[COMPAT_MAX_PATH];
|
||||
strcpy(nativePath, path);
|
||||
compat_windows_path_to_native(nativePath);
|
||||
compat_path_to_native(nativePath);
|
||||
compat_resolve_path(nativePath);
|
||||
return gzopen(nativePath, mode);
|
||||
}
|
||||
@@ -278,7 +296,7 @@ int compat_remove(const char* path)
|
||||
{
|
||||
char nativePath[COMPAT_MAX_PATH];
|
||||
strcpy(nativePath, path);
|
||||
compat_windows_path_to_native(nativePath);
|
||||
compat_path_to_native(nativePath);
|
||||
compat_resolve_path(nativePath);
|
||||
return remove(nativePath);
|
||||
}
|
||||
@@ -287,28 +305,47 @@ int compat_rename(const char* oldFileName, const char* newFileName)
|
||||
{
|
||||
char nativeOldFileName[COMPAT_MAX_PATH];
|
||||
strcpy(nativeOldFileName, oldFileName);
|
||||
compat_windows_path_to_native(nativeOldFileName);
|
||||
compat_path_to_native(nativeOldFileName);
|
||||
compat_resolve_path(nativeOldFileName);
|
||||
|
||||
char nativeNewFileName[COMPAT_MAX_PATH];
|
||||
strcpy(nativeNewFileName, newFileName);
|
||||
compat_windows_path_to_native(nativeNewFileName);
|
||||
compat_path_to_native(nativeNewFileName);
|
||||
compat_resolve_path(nativeNewFileName);
|
||||
|
||||
return rename(nativeOldFileName, nativeNewFileName);
|
||||
}
|
||||
|
||||
void compat_windows_path_to_native(char* path)
|
||||
void compat_path_to_native(char* path)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
char* pch = path;
|
||||
while (*pch != '\0') {
|
||||
if (*pch == '\\') {
|
||||
if (
|
||||
#ifdef _WIN32
|
||||
*pch == '/'
|
||||
#else
|
||||
*pch == '\\'
|
||||
#endif
|
||||
) {
|
||||
#ifdef _WIN32
|
||||
*pch = '\\';
|
||||
#else
|
||||
*pch = '/';
|
||||
#endif
|
||||
}
|
||||
pch++;
|
||||
}
|
||||
}
|
||||
|
||||
void compat_path_to_windows(char* path)
|
||||
{
|
||||
char* pch = path;
|
||||
while (*pch != '\0') {
|
||||
if (*pch == '/') {
|
||||
*pch = '\\';
|
||||
}
|
||||
pch++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void compat_resolve_path(char* path)
|
||||
@@ -369,7 +406,7 @@ int compat_access(const char* path, int mode)
|
||||
{
|
||||
char nativePath[COMPAT_MAX_PATH];
|
||||
strcpy(nativePath, path);
|
||||
compat_windows_path_to_native(nativePath);
|
||||
compat_path_to_native(nativePath);
|
||||
compat_resolve_path(nativePath);
|
||||
return access(nativePath, mode);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace fallout {
|
||||
|
||||
int compat_stricmp(const char* string1, const char* string2);
|
||||
int compat_strnicmp(const char* string1, const char* string2, size_t size);
|
||||
size_t compat_strlcpy(char* dest, const char* src, size_t size);
|
||||
char* compat_strupr(char* string);
|
||||
char* compat_strlwr(char* string);
|
||||
char* compat_itoa(int value, char* buffer, int radix);
|
||||
@@ -39,7 +40,8 @@ char* compat_fgets(char* buffer, int maxCount, FILE* stream);
|
||||
char* compat_gzgets(gzFile stream, char* buffer, int maxCount);
|
||||
int compat_remove(const char* path);
|
||||
int compat_rename(const char* oldFileName, const char* newFileName);
|
||||
void compat_windows_path_to_native(char* path);
|
||||
void compat_path_to_native(char* path);
|
||||
void compat_path_to_windows(char* path);
|
||||
void compat_resolve_path(char* path);
|
||||
int compat_access(const char* path, int mode);
|
||||
char* compat_strdup(const char* string);
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ bool sfallConfigInit(int argc, char** argv)
|
||||
configSetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_CITIES_LIMIT_FIX, true);
|
||||
|
||||
configSetString(&gSfallConfig, SFALL_CONFIG_SCRIPTS_KEY, SFALL_CONFIG_INI_CONFIG_FOLDER, "");
|
||||
configSetString(&gSfallConfig, SFALL_CONFIG_SCRIPTS_KEY, SFALL_CONFIG_GLOBAL_SCRIPT_PATHS, "");
|
||||
configSetString(&gSfallConfig, SFALL_CONFIG_SCRIPTS_KEY, SFALL_CONFIG_GLOBAL_SCRIPT_PATHS, "scripts\\gl_*.int"); // TODO: remove
|
||||
|
||||
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_PIPBOY_AVAILABLE_AT_GAMESTART, 0);
|
||||
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_USE_WALK_DISTANCE, 5);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "sfall_global_scripts.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
@@ -7,6 +9,7 @@
|
||||
|
||||
#include "animation.h"
|
||||
#include "db.h"
|
||||
#include "debug.h"
|
||||
#include "input.h"
|
||||
#include "platform_compat.h"
|
||||
#include "scripts.h"
|
||||
@@ -47,23 +50,27 @@ bool sfall_gl_scr_init()
|
||||
*end = '\0';
|
||||
}
|
||||
|
||||
char normalizedPattern[COMPAT_MAX_PATH];
|
||||
compat_strlcpy(normalizedPattern, curr, sizeof(normalizedPattern));
|
||||
compat_path_to_native(normalizedPattern);
|
||||
|
||||
char drive[COMPAT_MAX_DRIVE];
|
||||
char dir[COMPAT_MAX_DIR];
|
||||
compat_splitpath(curr, drive, dir, nullptr, nullptr);
|
||||
compat_splitpath(normalizedPattern, drive, dir, nullptr, nullptr);
|
||||
|
||||
char** files;
|
||||
int filesLength = fileNameListInit(curr, &files);
|
||||
char** files = nullptr;
|
||||
int filesLength = fileNameListInit(normalizedPattern, &files);
|
||||
debugPrint("GlobalScriptPaths mask %s matched %d script(s)\n", curr, filesLength);
|
||||
if (filesLength != 0) {
|
||||
for (int index = 0; index < filesLength; index++) {
|
||||
char path[COMPAT_MAX_PATH];
|
||||
compat_makepath(path, drive, dir, files[index], nullptr);
|
||||
|
||||
state->paths.push_back(std::string { path });
|
||||
state->paths.emplace_back(path);
|
||||
}
|
||||
|
||||
fileNameListFree(&files, 0);
|
||||
}
|
||||
|
||||
fileNameListFree(&files, 0);
|
||||
|
||||
if (end != nullptr) {
|
||||
*end = ',';
|
||||
curr = end + 1;
|
||||
@@ -73,6 +80,7 @@ bool sfall_gl_scr_init()
|
||||
}
|
||||
|
||||
std::sort(state->paths.begin(), state->paths.end());
|
||||
debugPrint("GlobalScriptPaths resolved %d script path(s)\n", static_cast<int>(state->paths.size()));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -96,6 +104,8 @@ void sfall_gl_scr_exit()
|
||||
|
||||
void sfall_gl_scr_exec_start_proc()
|
||||
{
|
||||
int loadedScripts = 0;
|
||||
|
||||
for (auto& path : state->paths) {
|
||||
Program* program = programCreateByPath(path.c_str());
|
||||
if (program != nullptr) {
|
||||
@@ -107,11 +117,14 @@ void sfall_gl_scr_exec_start_proc()
|
||||
}
|
||||
|
||||
state->globalScripts.push_back(std::move(scr));
|
||||
loadedScripts++;
|
||||
|
||||
programInterpret(program, -1);
|
||||
}
|
||||
}
|
||||
|
||||
debugPrint("Loaded %d global script(s)\n", loadedScripts);
|
||||
|
||||
tickersAdd(sfall_gl_scr_process_input);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -563,7 +563,7 @@ static bool xlistEnumerate(const char* pattern, XListEnumerationHandler* handler
|
||||
|
||||
char nativePattern[COMPAT_MAX_PATH];
|
||||
strcpy(nativePattern, pattern);
|
||||
compat_windows_path_to_native(nativePattern);
|
||||
compat_path_to_native(nativePattern);
|
||||
|
||||
char drive[COMPAT_MAX_DRIVE];
|
||||
char dir[COMPAT_MAX_DIR];
|
||||
@@ -615,7 +615,7 @@ static bool xlistEnumerate(const char* pattern, XListEnumerationHandler* handler
|
||||
} else {
|
||||
char path[COMPAT_MAX_PATH];
|
||||
snprintf(path, sizeof(path), "%s\\%s", xbase->path, pattern);
|
||||
compat_windows_path_to_native(path);
|
||||
compat_path_to_native(path);
|
||||
|
||||
if (fileFindFirst(path, &directoryFileFindData)) {
|
||||
do {
|
||||
|
||||
Reference in New Issue
Block a user