mirror of
https://github.com/fallout2-ce/fallout2-ce.git
synced 2026-07-27 16:47:11 -07:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2759d28997 | ||
|
|
cbc40e2df7 | ||
|
|
41c3fa2b8c | ||
|
|
4a6dc44419 | ||
|
|
9a4108f44d | ||
|
|
0ef73e73da | ||
|
|
9e5660d9fe | ||
|
|
620505bec3 |
@@ -1,31 +0,0 @@
|
||||
### Description
|
||||
|
||||
<!--- Clearly describe the changes introduced by this PR. What was fixed, added, or updated? --->
|
||||
|
||||
### Reproduction Steps and Savefile (if available)
|
||||
|
||||
<!--- Provide detailed steps to reproduce the issue. Include a savefile if applicable, preferrably for Sonora --->
|
||||
|
||||
### Screenshots
|
||||
|
||||
<!--- If the PR includes visual changes, add screenshots here. --->
|
||||
|
||||
|
||||
<!---
|
||||
|
||||
**Important Notes**
|
||||
|
||||
- *Preview builds are not available for pull requests from forked repositories.* To enable preview builds, submit the PR from a branch within this repository.
|
||||
|
||||
- *Formatting issues? You have two options:*
|
||||
1. **Fix formatting automatically** using the following Docker command: *(If you're using Windows, remove `--user $(id -u):$(id -g)`)*
|
||||
```bash
|
||||
docker run --rm \
|
||||
-v $(pwd):/app --workdir /app \
|
||||
--user $(id -u):$(id -g) silkeh/clang:18 \
|
||||
bash -c 'find src -type f -name \*.cc -o -name \*.h | xargs clang-format -i'
|
||||
```
|
||||
2. **Skip formatting check** by adding the `skip-formatting` label to this PR.
|
||||
|
||||
--->
|
||||
|
||||
@@ -30,7 +30,13 @@ jobs:
|
||||
git config --global --add safe.directory "*"
|
||||
mkdir -p build
|
||||
cd build
|
||||
emcmake cmake ../ -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain/Emscripten.cmake -DCMAKE_BUILD_TYPE=Release && emmake make VERBOSE=1 -j 4
|
||||
if [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]; then
|
||||
export BUILD_TYPE=Debug
|
||||
else
|
||||
export BUILD_TYPE=Release
|
||||
fi
|
||||
emcmake cmake ../ -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain/Emscripten.cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
||||
emmake make VERBOSE=1 -j 4
|
||||
cd ..
|
||||
|
||||
- name: Add node
|
||||
|
||||
+1
-3
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
|
||||
@@ -305,14 +305,12 @@ if(WIN32)
|
||||
_CRT_NONSTDC_NO_WARNINGS
|
||||
NOMINMAX
|
||||
WIN32_LEAN_AND_MEAN
|
||||
_STATIC_CPPLIB
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(${EXECUTABLE_NAME}
|
||||
winmm
|
||||
libcpmt
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@
|
||||
"cacheVariables": {
|
||||
"CMAKE_GENERATOR_TOOLSET": "v141_xp",
|
||||
"CMAKE_C_FLAGS": "/D_WIN32_WINNT=0x0501",
|
||||
"CMAKE_CXX_FLAGS": "/D_WIN32_WINNT=0x0501 /D_STATIC_CPPLIB",
|
||||
"CMAKE_CXX_FLAGS": "/D_WIN32_WINNT=0x0501",
|
||||
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded$<$<CONFIG:Debug>:Debug>"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# Fallout 2 Community Edition
|
||||
|
||||
Fallout 2 Community Edition is a fully working re-implementation of Fallout 2, with the same original gameplay, engine bugfixes, and some quality of life improvements, that works (mostly) hassle-free on multiple platforms. This is a fork of the original project, which isn't getting regular updates.
|
||||
Fallout 2 Community Edition is a fully working re-implementation of Fallout 2, with the same original gameplay, engine bugfixes, and some quality of life improvements, that works (mostly) hassle-free on multiple platforms.
|
||||
|
||||
Popular Fallout 2 total conversion mods are partially supported. Original versions of Nevada and Sonora (that do not rely on extended features provided by Sfall) work. [Fallout 2 Restoration Project](https://github.com/BGforgeNet/Fallout2_Restoration_Project), [Fallout Et Tu](https://github.com/rotators/Fo1in2) and [Olympus 2207](https://olympus2207.com) are not yet supported. Other mods (particularly Resurrection and Yesterday) are not tested.
|
||||
Popular Fallout 2 total conversion mods are partially supported. Original versions of Nevada and Sonora (that do not rely on extended features provided by Sfall) likely work, although there is no complete walkthrough confirmation yet. [Fallout 2 Restoration Project](https://github.com/BGforgeNet/Fallout2_Restoration_Project), [Fallout Et Tu](https://github.com/rotators/Fo1in2) and [Olympus 2207](https://olympus2207.com) are not yet supported. Other mods (particularly Resurrection and Yesterday) are not tested.
|
||||
|
||||
There is also [Fallout Community Edition](https://github.com/alexbatalov/fallout1-ce) (not affiliated with this fork).
|
||||
There is also [Fallout Community Edition](https://github.com/alexbatalov/fallout1-ce).
|
||||
|
||||
## Installation
|
||||
|
||||
You must own the game to play. Purchase your copy on [GOG](https://www.gog.com/game/fallout_2), [Epic Games](https://store.epicgames.com/p/fallout-2) or [Steam](https://store.steampowered.com/app/38410). Download latest [release](https://github.com/fallout2-ce/fallout2-ce/releases) or build from source.
|
||||
You must own the game to play. Purchase your copy on [GOG](https://www.gog.com/game/fallout_2), [Epic Games](https://store.epicgames.com/p/fallout-2) or [Steam](https://store.steampowered.com/app/38410). Download latest [release](https://github.com/alexbatalov/fallout2-ce/releases) or build from source. You can also check latest [debug](https://github.com/alexbatalov/fallout2-ce/actions) build intended for testers.
|
||||
|
||||
### Windows
|
||||
|
||||
@@ -102,11 +102,7 @@ The second configuration file is `f2_res.ini`. Use it to change game window size
|
||||
[MAIN]
|
||||
SCR_WIDTH=1280
|
||||
SCR_HEIGHT=720
|
||||
WINDOWED=1 ; 0 = fullscreen
|
||||
SCALE_2X=1 ; 0 = original scale, 1 = 2x
|
||||
|
||||
[IFACE]
|
||||
IFACE_BAR_MODE, IFACE_BAR_SIDE_ART, IFACE_BAR_SIDES_ORI, IFACE_BAR_WIDTH supported (require assets in appropriate places)
|
||||
WINDOWED=1
|
||||
```
|
||||
|
||||
Recommendations:
|
||||
@@ -116,10 +112,7 @@ Recommendations:
|
||||
|
||||
In time this stuff will receive in-game interface, right now you have to do it manually.
|
||||
|
||||
The third configuration file is `ddraw.ini` (part of Sfall). There are dozens of options that adjust or override engine behaviour and gameplay mechanics. This file is intended for modders and advanced users. Currently only a small subset of these settings are actually implemented. For high res configs, the following is recommended:
|
||||
```[Main]
|
||||
HiResMode=1
|
||||
```
|
||||
The third configuration file is `ddraw.ini` (part of Sfall). There are dozens of options that adjust or override engine behaviour and gameplay mechanics. This file is intended for modders and advanced users. Currently only a small subset of these settings are actually implemented.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -172,6 +172,9 @@ int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4
|
||||
showSplash();
|
||||
}
|
||||
|
||||
#if (defined(__EMSCRIPTEN__) && !defined(NDEBUG))
|
||||
debugPrint("This is a web build with debug mode so print to the console\n");
|
||||
#else
|
||||
// CE: Handle debug mode (exactly as seen in `mapper2.exe`).
|
||||
const char* debugMode = settings.debug.mode.c_str();
|
||||
if (compat_stricmp(debugMode, "environment") == 0) {
|
||||
@@ -185,6 +188,7 @@ int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4
|
||||
} else if (compat_stricmp(debugMode, "gnw") == 0) {
|
||||
_debug_register_func(_win_debug);
|
||||
}
|
||||
#endif
|
||||
|
||||
interfaceFontsInit();
|
||||
fontManagerAdd(&gModernFontManager);
|
||||
|
||||
+2
-11
@@ -21,7 +21,6 @@
|
||||
#include "queue.h"
|
||||
#include "random.h"
|
||||
#include "settings.h"
|
||||
#include "sfall_config.h"
|
||||
#include "sound_effects_cache.h"
|
||||
#include "stat.h"
|
||||
#include "svga.h"
|
||||
@@ -746,17 +745,9 @@ int backgroundSoundLoad(const char* fileName, int a2, int a3, int a4)
|
||||
}
|
||||
|
||||
// 0x450A08
|
||||
int _gsound_background_play_level_music(const char* fileName, int a2)
|
||||
int _gsound_background_play_level_music(const char* a1, int a2)
|
||||
{
|
||||
int gaplessMusic = 0;
|
||||
configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_GAPLESS_MUSIC, &gaplessMusic);
|
||||
if (gaplessMusic) {
|
||||
if (!strcmp(fileName, gBackgroundSoundFileName)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return backgroundSoundLoad(fileName, a2, 14, 16);
|
||||
return backgroundSoundLoad(a1, a2, 14, 16);
|
||||
}
|
||||
|
||||
// 0x450AB4
|
||||
|
||||
+25
-30
@@ -50,10 +50,10 @@ static int stealthBoyTurnOff(Object* critter, Object* item);
|
||||
static int _insert_drug_effect(Object* critter, Object* item, int duration, int* stats, int* mods);
|
||||
static void _perform_drug_effect(Object* critter, int* stats, int* mods, bool isImmediate);
|
||||
static bool _drug_effect_allowed(Object* critter, int pid);
|
||||
static int _insert_withdrawal(Object* obj, int active, int duration, int perk, int pid);
|
||||
static int _item_wd_clear_all(Object* obj, void* data);
|
||||
static void performWithdrawalStart(Object* obj, int perk, int pid);
|
||||
static void performWithdrawalEnd(Object* obj, int perk);
|
||||
static int _insert_withdrawal(Object* obj, int a2, int a3, int a4, int a5);
|
||||
static int _item_wd_clear_all(Object* a1, void* data);
|
||||
static void performWithdrawalStart(Object* obj, int perk, int a3);
|
||||
static void performWithdrawalEnd(Object* obj, int a2);
|
||||
static int drugGetAddictionGvarByPid(int drugPid);
|
||||
static void dudeSetAddiction(int drugPid);
|
||||
static void dudeClearAddiction(int drugPid);
|
||||
@@ -1550,9 +1550,6 @@ bool weaponCanBeReloadedWith(Object* weapon, Object* ammo)
|
||||
}
|
||||
|
||||
// 0x478918
|
||||
// weaponReload adds ammo to the weapon and removes it from the given ammo stack
|
||||
// return -1 if ammo is incompatible with weapon; otherwise returns the number of
|
||||
// rounds left in the ammo stack
|
||||
int weaponReload(Object* weapon, Object* ammo)
|
||||
{
|
||||
if (!weaponCanBeReloadedWith(weapon, ammo)) {
|
||||
@@ -1571,26 +1568,26 @@ int weaponReload(Object* weapon, Object* ammo)
|
||||
}
|
||||
|
||||
// NOTE: Uninline.
|
||||
int quantity = ammoGetQuantity(ammo);
|
||||
int v10 = ammoGetQuantity(ammo);
|
||||
|
||||
int left = quantity;
|
||||
int v11 = v10;
|
||||
if (ammoQuantity < ammoCapacity) {
|
||||
int newQuantity;
|
||||
if (ammoQuantity + quantity > ammoCapacity) {
|
||||
left = quantity - (ammoCapacity - ammoQuantity);
|
||||
newQuantity = ammoCapacity;
|
||||
int v12;
|
||||
if (ammoQuantity + v10 > ammoCapacity) {
|
||||
v11 = v10 - (ammoCapacity - ammoQuantity);
|
||||
v12 = ammoCapacity;
|
||||
} else {
|
||||
left = 0;
|
||||
newQuantity = ammoQuantity + quantity;
|
||||
v11 = 0;
|
||||
v12 = ammoQuantity + v10;
|
||||
}
|
||||
|
||||
weapon->data.item.weapon.ammoTypePid = ammo->pid;
|
||||
|
||||
ammoSetQuantity(ammo, left);
|
||||
ammoSetQuantity(weapon, newQuantity);
|
||||
ammoSetQuantity(ammo, v11);
|
||||
ammoSetQuantity(weapon, v12);
|
||||
}
|
||||
|
||||
return left;
|
||||
return v11;
|
||||
}
|
||||
|
||||
// 0x478A1C
|
||||
@@ -2917,14 +2914,14 @@ int drugEffectEventWrite(File* stream, void* data)
|
||||
}
|
||||
|
||||
// 0x47A290
|
||||
static int _insert_withdrawal(Object* obj, int active, int duration, int perk, int pid)
|
||||
static int _insert_withdrawal(Object* obj, int a2, int duration, int perk, int pid)
|
||||
{
|
||||
WithdrawalEvent* withdrawalEvent = (WithdrawalEvent*)internal_malloc(sizeof(*withdrawalEvent));
|
||||
if (withdrawalEvent == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
withdrawalEvent->active = active;
|
||||
withdrawalEvent->field_0 = a2;
|
||||
withdrawalEvent->pid = pid;
|
||||
withdrawalEvent->perk = perk;
|
||||
|
||||
@@ -2945,7 +2942,7 @@ int _item_wd_clear(Object* obj, void* data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!withdrawalEvent->active) {
|
||||
if (!withdrawalEvent->field_0) {
|
||||
performWithdrawalEnd(obj, withdrawalEvent->perk);
|
||||
}
|
||||
|
||||
@@ -2953,11 +2950,11 @@ int _item_wd_clear(Object* obj, void* data)
|
||||
}
|
||||
|
||||
// 0x47A324
|
||||
static int _item_wd_clear_all(Object* obj, void* data)
|
||||
static int _item_wd_clear_all(Object* a1, void* data)
|
||||
{
|
||||
WithdrawalEvent* withdrawalEvent = (WithdrawalEvent*)data;
|
||||
|
||||
if (obj != _wd_obj) {
|
||||
if (a1 != _wd_obj) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2965,12 +2962,11 @@ static int _item_wd_clear_all(Object* obj, void* data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!withdrawalEvent->active) {
|
||||
if (!withdrawalEvent->field_0) {
|
||||
performWithdrawalEnd(_wd_obj, withdrawalEvent->perk);
|
||||
}
|
||||
|
||||
// schedule start of withdrawal
|
||||
_insert_withdrawal(obj, 1, _wd_onset, withdrawalEvent->perk, withdrawalEvent->pid);
|
||||
_insert_withdrawal(a1, 1, _wd_onset, withdrawalEvent->perk, withdrawalEvent->pid);
|
||||
|
||||
_wd_obj = nullptr;
|
||||
|
||||
@@ -2982,7 +2978,7 @@ int withdrawalEventProcess(Object* obj, void* data)
|
||||
{
|
||||
WithdrawalEvent* withdrawalEvent = (WithdrawalEvent*)data;
|
||||
|
||||
if (withdrawalEvent->active) {
|
||||
if (withdrawalEvent->field_0) {
|
||||
performWithdrawalStart(obj, withdrawalEvent->perk, withdrawalEvent->pid);
|
||||
} else {
|
||||
if (withdrawalEvent->perk == PERK_JET_ADDICTION) {
|
||||
@@ -3013,7 +3009,7 @@ int withdrawalEventRead(File* stream, void** dataPtr)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fileReadInt32(stream, &(withdrawalEvent->active)) == -1) goto err;
|
||||
if (fileReadInt32(stream, &(withdrawalEvent->field_0)) == -1) goto err;
|
||||
if (fileReadInt32(stream, &(withdrawalEvent->pid)) == -1) goto err;
|
||||
if (fileReadInt32(stream, &(withdrawalEvent->perk)) == -1) goto err;
|
||||
|
||||
@@ -3031,7 +3027,7 @@ int withdrawalEventWrite(File* stream, void* data)
|
||||
{
|
||||
WithdrawalEvent* withdrawalEvent = (WithdrawalEvent*)data;
|
||||
|
||||
if (fileWriteInt32(stream, withdrawalEvent->active) == -1) return -1;
|
||||
if (fileWriteInt32(stream, withdrawalEvent->field_0) == -1) return -1;
|
||||
if (fileWriteInt32(stream, withdrawalEvent->pid) == -1) return -1;
|
||||
if (fileWriteInt32(stream, withdrawalEvent->perk) == -1) return -1;
|
||||
|
||||
@@ -3068,7 +3064,6 @@ static void performWithdrawalStart(Object* obj, int perk, int pid)
|
||||
}
|
||||
}
|
||||
|
||||
// schedule end of withdrawal
|
||||
_insert_withdrawal(obj, 0, duration, perk, pid);
|
||||
}
|
||||
|
||||
|
||||
+7
-7
@@ -49,13 +49,13 @@ bool dudeIsWeaponDisabled(Object* weapon);
|
||||
int itemGetInventoryFid(Object* obj);
|
||||
Object* critterGetWeaponForHitMode(Object* critter, int hitMode);
|
||||
int itemGetActionPointCost(Object* obj, int hitMode, bool aiming);
|
||||
int itemGetQuantity(Object* obj, Object* item);
|
||||
int itemGetQuantity(Object* obj, Object* a2);
|
||||
int itemIsQueued(Object* obj);
|
||||
Object* itemReplace(Object* owner, Object* itemToReplace, int flags);
|
||||
Object* itemReplace(Object* a1, Object* a2, int a3);
|
||||
bool itemIsHidden(Object* obj);
|
||||
int weaponGetAttackTypeForHitMode(Object* weapon, int hitMode);
|
||||
int weaponGetSkillForHitMode(Object* weapon, int hitMode);
|
||||
int weaponGetSkillValue(Object* critter, int hitMode);
|
||||
int weaponGetAttackTypeForHitMode(Object* a1, int a2);
|
||||
int weaponGetSkillForHitMode(Object* a1, int a2);
|
||||
int weaponGetSkillValue(Object* a1, int a2);
|
||||
int weaponGetDamageMinMax(Object* weapon, int* minDamagePtr, int* maxDamagePtr);
|
||||
int weaponGetDamage(Object* critter, int hitMode);
|
||||
int weaponGetDamageType(Object* critter, Object* weapon);
|
||||
@@ -123,14 +123,14 @@ int _item_d_clear(Object* obj, void* data);
|
||||
int drugEffectEventProcess(Object* obj, void* data);
|
||||
int drugEffectEventRead(File* stream, void** dataPtr);
|
||||
int drugEffectEventWrite(File* stream, void* data);
|
||||
int _item_wd_clear(Object* obj, void* data);
|
||||
int _item_wd_clear(Object* obj, void* a2);
|
||||
int withdrawalEventProcess(Object* obj, void* data);
|
||||
int withdrawalEventRead(File* stream, void** dataPtr);
|
||||
int withdrawalEventWrite(File* stream, void* data);
|
||||
int itemGetTotalCaps(Object* obj);
|
||||
int itemCapsAdjust(Object* obj, int amount);
|
||||
int itemGetMoney(Object* obj);
|
||||
int itemSetMoney(Object* obj, int amount);
|
||||
int itemSetMoney(Object* obj, int a2);
|
||||
|
||||
bool booksGetInfo(int bookPid, int* messageIdPtr, int* skillPtr);
|
||||
bool explosionEmitsLight();
|
||||
|
||||
+8
-18
@@ -359,6 +359,8 @@ void _InitLoadSave()
|
||||
if (quickSaveSlots > 0 && quickSaveSlots <= saveLoadTotalSlots) {
|
||||
autoQuickSaveSlots = true;
|
||||
}
|
||||
|
||||
pipboyMessageListInit();
|
||||
}
|
||||
|
||||
// 0x47B85C
|
||||
@@ -459,8 +461,6 @@ int lsgSaveGame(int mode)
|
||||
return -1;
|
||||
}
|
||||
|
||||
pipboyMessageListInit();
|
||||
|
||||
if (_GetSlotList() == -1) {
|
||||
windowRefresh(gLoadSaveWindow);
|
||||
|
||||
@@ -941,8 +941,6 @@ int lsgSaveGame(int mode)
|
||||
|
||||
lsgWindowFree(LOAD_SAVE_WINDOW_TYPE_SAVE_GAME);
|
||||
|
||||
pipboyMessageListFree();
|
||||
|
||||
tileWindowRefresh();
|
||||
|
||||
if (mode == LOAD_SAVE_MODE_QUICK) {
|
||||
@@ -1085,8 +1083,6 @@ int lsgLoadGame(int mode)
|
||||
return -1;
|
||||
}
|
||||
|
||||
pipboyMessageListInit();
|
||||
|
||||
if (_GetSlotList() == -1) {
|
||||
gameMouseSetCursor(MOUSE_CURSOR_ARROW);
|
||||
windowRefresh(gLoadSaveWindow);
|
||||
@@ -1476,8 +1472,6 @@ int lsgLoadGame(int mode)
|
||||
? LOAD_SAVE_WINDOW_TYPE_LOAD_GAME_FROM_MAIN_MENU
|
||||
: LOAD_SAVE_WINDOW_TYPE_LOAD_GAME);
|
||||
|
||||
pipboyMessageListFree();
|
||||
|
||||
if (mode == LOAD_SAVE_MODE_QUICK) {
|
||||
if (rc == 1) {
|
||||
_quick_done = true;
|
||||
@@ -2303,11 +2297,9 @@ static void _ShowSlotList(int windowType)
|
||||
int inactiveColor = _colorTable[8804];
|
||||
|
||||
{
|
||||
MessageListItem messageListItemBack = { 201, 0, nullptr, nullptr };
|
||||
if (!messageListGetItem(&gPipboyMessageList, &messageListItemBack)) {
|
||||
debugPrint("Error: Couldn't find LoadSave Message!");
|
||||
messageListItemBack.text = "BACK";
|
||||
}
|
||||
MessageListItem messageListItemBack;
|
||||
messageListItemBack.num = 201; // Back
|
||||
messageListGetItem(&gPipboyMessageList, &messageListItemBack);
|
||||
fontDrawText(
|
||||
gLoadSaveWindowBuffer + LS_WINDOW_WIDTH * (y + 0) + 95,
|
||||
messageListItemBack.text,
|
||||
@@ -2316,11 +2308,9 @@ static void _ShowSlotList(int windowType)
|
||||
_currentSlotPage > 0 ? activeColor : inactiveColor);
|
||||
}
|
||||
{
|
||||
MessageListItem messageListItemMore = { 200, 0, nullptr, nullptr };
|
||||
if (!messageListGetItem(&gPipboyMessageList, &messageListItemMore)) {
|
||||
debugPrint("Error: Couldn't find LoadSave Message!");
|
||||
messageListItemMore.text = "MORE";
|
||||
}
|
||||
MessageListItem messageListItemMore;
|
||||
messageListItemMore.num = 200; // More
|
||||
messageListGetItem(&gPipboyMessageList, &messageListItemMore);
|
||||
fontDrawText(gLoadSaveWindowBuffer + LS_WINDOW_WIDTH * (y + 0) + 210,
|
||||
messageListItemMore.text,
|
||||
LS_WINDOW_WIDTH,
|
||||
|
||||
+2
-11
@@ -36,7 +36,6 @@
|
||||
#include "random.h"
|
||||
#include "scripts.h"
|
||||
#include "settings.h"
|
||||
#include "sfall_config.h"
|
||||
#include "svga.h"
|
||||
#include "text_object.h"
|
||||
#include "tile.h"
|
||||
@@ -820,11 +819,7 @@ int mapLoadById(int map)
|
||||
static int mapLoad(File* stream)
|
||||
{
|
||||
_map_save_in_game(true);
|
||||
int gaplessMusic = 0;
|
||||
configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_GAPLESS_MUSIC, &gaplessMusic);
|
||||
if (!gaplessMusic) {
|
||||
backgroundSoundLoad("wind2", 12, 13, 16);
|
||||
}
|
||||
backgroundSoundLoad("wind2", 12, 13, 16);
|
||||
isoDisable();
|
||||
_partyMemberPrepLoad();
|
||||
_gmouse_disable_scrolling();
|
||||
@@ -1253,16 +1248,12 @@ int mapHandleTransition()
|
||||
if (gMapTransition.map == -1) {
|
||||
if (!isInCombat()) {
|
||||
animationStop();
|
||||
// SFALL: Remove text floaters when moving to the world map
|
||||
textObjectsReset();
|
||||
wmTownMap(); // nb this is a world map transition
|
||||
wmTownMap();
|
||||
memset(&gMapTransition, 0, sizeof(gMapTransition));
|
||||
}
|
||||
} else if (gMapTransition.map == -2) {
|
||||
if (!isInCombat()) {
|
||||
animationStop();
|
||||
// SFALL: Remove text floaters when moving to the world map
|
||||
textObjectsReset();
|
||||
wmWorldMap();
|
||||
memset(&gMapTransition, 0, sizeof(gMapTransition));
|
||||
}
|
||||
|
||||
+438
-664
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,6 @@ int pipboyLoad(File* stream);
|
||||
|
||||
extern MessageList gPipboyMessageList;
|
||||
int pipboyMessageListInit();
|
||||
void pipboyMessageListFree();
|
||||
|
||||
} // namespace fallout
|
||||
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ typedef struct DrugEffectEvent {
|
||||
} DrugEffectEvent;
|
||||
|
||||
typedef struct WithdrawalEvent {
|
||||
int active; // 0 == end withdrawal, 1 == start withdrawal
|
||||
int field_0;
|
||||
int pid;
|
||||
int perk;
|
||||
} WithdrawalEvent;
|
||||
|
||||
@@ -68,7 +68,6 @@ bool sfallConfigInit(int argc, char** argv)
|
||||
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);
|
||||
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_AUTO_OPEN_DOORS, 0);
|
||||
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_GAPLESS_MUSIC, 0);
|
||||
|
||||
char path[COMPAT_MAX_PATH];
|
||||
char* executable = argv[0];
|
||||
|
||||
@@ -80,7 +80,6 @@ namespace fallout {
|
||||
#define SFALL_CONFIG_PIPBOY_AVAILABLE_AT_GAMESTART "PipBoyAvailableAtGameStart"
|
||||
#define SFALL_CONFIG_USE_WALK_DISTANCE "UseWalkDistance"
|
||||
#define SFALL_CONFIG_AUTO_OPEN_DOORS "AutoOpenDoors"
|
||||
#define SFALL_CONFIG_GAPLESS_MUSIC "GaplessMusic"
|
||||
|
||||
#define SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_MULTIPLIER 1
|
||||
#define SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_DIVISOR 3
|
||||
|
||||
+18
-58
@@ -534,7 +534,7 @@ static int wmTileGrabArt(int tileIdx);
|
||||
static int wmInterfaceRefresh();
|
||||
static void wmInterfaceRefreshDate(bool shouldRefreshWindow);
|
||||
static int wmMatchWorldPosToArea(int x, int y, int* areaIdxPtr);
|
||||
static int wmInterfaceDrawCircleOverlay(CityInfo* cityInfo, CitySizeDescription* citySizeInfo, unsigned char* buffer, int x, int y, int destPitch);
|
||||
static int wmInterfaceDrawCircleOverlay(CityInfo* cityInfo, CitySizeDescription* citySizeInfo, unsigned char* buffer, int x, int y);
|
||||
static void wmInterfaceDrawSubTileRectFogged(unsigned char* dest, int width, int height, int pitch);
|
||||
static int wmInterfaceDrawSubTileList(TileInfo* tileInfo, int column, int row, int x, int y, int a6);
|
||||
static int wmDrawCursorStopped();
|
||||
@@ -5221,50 +5221,17 @@ static int wmInterfaceRefresh()
|
||||
}
|
||||
|
||||
// Render cities.
|
||||
constexpr int PADDING = 100;
|
||||
|
||||
int viewportWidth = 472;
|
||||
int viewportHeight = 465;
|
||||
|
||||
int bufferWidth = viewportWidth + PADDING * 2;
|
||||
int bufferHeight = viewportHeight + PADDING * 2;
|
||||
|
||||
unsigned char* paddedBuf = (unsigned char*)malloc(bufferWidth * bufferHeight);
|
||||
if (paddedBuf != nullptr) {
|
||||
// Copy current wmBkWinBuf into center of paddedBuf
|
||||
memset(paddedBuf, 0, bufferWidth * bufferHeight); // Clear padding
|
||||
|
||||
for (int y = 0; y < viewportHeight; y++) {
|
||||
memcpy(
|
||||
paddedBuf + bufferWidth * (y + PADDING) + PADDING,
|
||||
wmBkWinBuf + y * WM_WINDOW_WIDTH,
|
||||
viewportWidth);
|
||||
}
|
||||
|
||||
// Draw cities onto a padded buffer
|
||||
for (int index = 0; index < wmMaxAreaNum; index++) {
|
||||
CityInfo* cityInfo = &wmAreaInfoList[index];
|
||||
if (cityInfo->state != CITY_STATE_UNKNOWN) {
|
||||
CitySizeDescription* citySizeDescription = &wmSphereData[cityInfo->size];
|
||||
int cityX = cityInfo->x - wmWorldOffsetX + PADDING;
|
||||
int cityY = cityInfo->y - wmWorldOffsetY + PADDING;
|
||||
|
||||
if (cityX >= 0 && cityX <= bufferWidth - citySizeDescription->frmImage.getWidth() &&
|
||||
cityY >= 0 && cityY <= bufferHeight - citySizeDescription->frmImage.getHeight()) {
|
||||
wmInterfaceDrawCircleOverlay(cityInfo, citySizeDescription, paddedBuf, cityX, cityY, bufferWidth);
|
||||
}
|
||||
for (int index = 0; index < wmMaxAreaNum; index++) {
|
||||
CityInfo* cityInfo = &(wmAreaInfoList[index]);
|
||||
if (cityInfo->state != CITY_STATE_UNKNOWN) {
|
||||
CitySizeDescription* citySizeDescription = &(wmSphereData[cityInfo->size]);
|
||||
int cityX = cityInfo->x - wmWorldOffsetX;
|
||||
int cityY = cityInfo->y - wmWorldOffsetY;
|
||||
if (cityX >= 0 && cityX <= 472 - citySizeDescription->frmImage.getWidth()
|
||||
&& cityY >= 0 && cityY <= 465 - citySizeDescription->frmImage.getHeight()) {
|
||||
wmInterfaceDrawCircleOverlay(cityInfo, citySizeDescription, wmBkWinBuf, cityX, cityY);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy center portion back to wmBkWinBuf
|
||||
for (int y = 0; y < viewportHeight; y++) {
|
||||
memcpy(
|
||||
wmBkWinBuf + y * WM_WINDOW_WIDTH,
|
||||
paddedBuf + bufferWidth * (y + PADDING) + PADDING,
|
||||
viewportWidth);
|
||||
}
|
||||
|
||||
free(paddedBuf);
|
||||
}
|
||||
|
||||
// Hide unknown subtiles, dim unvisited.
|
||||
@@ -5417,46 +5384,39 @@ static int wmMatchWorldPosToArea(int x, int y, int* areaIdxPtr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Function augmented to add destPitch to align city icons properly
|
||||
// 0x4C3FA8
|
||||
static int wmInterfaceDrawCircleOverlay(
|
||||
CityInfo* city,
|
||||
CitySizeDescription* citySizeDescription,
|
||||
unsigned char* dest,
|
||||
int x,
|
||||
int y,
|
||||
int destPitch)
|
||||
static int wmInterfaceDrawCircleOverlay(CityInfo* city, CitySizeDescription* citySizeDescription, unsigned char* dest, int x, int y)
|
||||
{
|
||||
_dark_translucent_trans_buf_to_buf(
|
||||
citySizeDescription->frmImage.getData(),
|
||||
_dark_translucent_trans_buf_to_buf(citySizeDescription->frmImage.getData(),
|
||||
citySizeDescription->frmImage.getWidth(),
|
||||
citySizeDescription->frmImage.getHeight(),
|
||||
citySizeDescription->frmImage.getWidth(),
|
||||
dest,
|
||||
x,
|
||||
y,
|
||||
destPitch,
|
||||
WM_WINDOW_WIDTH,
|
||||
0x10000,
|
||||
circleBlendTable,
|
||||
_commonGrayTable);
|
||||
|
||||
// CE: Slightly increase whitespace between cirle and city name.
|
||||
int nameY = y + citySizeDescription->frmImage.getHeight() + 3;
|
||||
int maxY = (464) + 200 - fontGetLineHeight(); // 200 for the PADDING
|
||||
int maxY = 464 - fontGetLineHeight();
|
||||
if (nameY < maxY) {
|
||||
MessageListItem messageListItem;
|
||||
char name[40];
|
||||
if (wmAreaIsKnown(city->areaId)) {
|
||||
// NOTE: Uninline.
|
||||
wmGetAreaName(city, name);
|
||||
} else {
|
||||
strncpy(name, getmsg(&wmMsgFile, &messageListItem, 1004), 40);
|
||||
}
|
||||
|
||||
int width = fontGetStringWidth(name);
|
||||
fontDrawText(
|
||||
dest + destPitch * nameY + x + citySizeDescription->frmImage.getWidth() / 2 - width / 2,
|
||||
fontDrawText(dest + WM_WINDOW_WIDTH * nameY + x + citySizeDescription->frmImage.getWidth() / 2 - width / 2,
|
||||
name,
|
||||
width,
|
||||
destPitch,
|
||||
WM_WINDOW_WIDTH,
|
||||
_colorTable[992] | FONT_SHADOW);
|
||||
}
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -1,8 +1,8 @@
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(fpattern
|
||||
GIT_REPOSITORY "https://github.com/alexbatalov/fpattern"
|
||||
GIT_TAG 8523173ec252c3b796fcdfca0fcc6329642fbbe3 # v1.9
|
||||
GIT_REPOSITORY "https://github.com/fallout2-ce/fpattern"
|
||||
GIT_TAG 35005aec7dd94584a7563fb75bc0597b2259058d # v1.9
|
||||
GIT_SHALLOW TRUE
|
||||
GIT_PROGRESS TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
|
||||
Reference in New Issue
Block a user