mirror of
https://github.com/fallout2-ce/fallout2-ce.git
synced 2026-07-27 16:47:11 -07:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07939225c6 | ||
|
|
b10526330c | ||
|
|
4c1cad7122 | ||
|
|
b76ff8257e | ||
|
|
6edbd70d60 | ||
|
|
15917dccb3 | ||
|
|
33aae49066 | ||
|
|
bfd41bb40c | ||
|
|
0ccaef5ef0 |
@@ -144,13 +144,13 @@ In time this stuff will receive in-game interface, right now you have to do it m
|
||||
* Expanded 4-row barter screen
|
||||
* Expanded AP bar
|
||||
* Party members can loot and barter in place of PC
|
||||
* Increased pathfinding nodes 5x for more accurate pathfinding, and use accurate path length for walk vs run
|
||||
* Increased pathfinding nodes 5x for more accurate pathfinding
|
||||
* Ctrl-click to quickly move items when bartering, looting, or stealing
|
||||
* _a_ to select "all" when selecting item quantity, and for `Take All` when looting
|
||||
* When bartering, caps default to the right amount to balance the trade
|
||||
* _a_ to select "all" when selecting item quantity
|
||||
* _a_ to `Take All` when looting
|
||||
* When bartering, caps default to the right amount to balance the trade (if possible)
|
||||
* Music continues playing between maps
|
||||
* Auto open doors
|
||||
* Integrated "HELP" menu
|
||||
* 44.1 kHz stereo sound/music supported, in .ogg and .wav format as well as legacy .acm
|
||||
* Last used save slot is remembered
|
||||
* Item/Corpse/Container/Critter highlighting (configure using [mods/sfall-mods.ini](https://github.com/sfall-team/sfall/blob/master/artifacts/config_files/sfall-mods.ini))
|
||||
|
||||
@@ -75,7 +75,7 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
|
||||
| Global scripts / Global script functions | set_global_script_repeat<br>set_global_script_type<br>available_global_script_types | âś… except available_global_script_types | - |
|
||||
| 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 | âś… except block_combat, force_aimed_shots, disable_aimed_shots, get_last_target, get_last_attacker, set_spray_settings | - |
|
||||
| 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<br>create_message_window | implemented: get_window_under_mouse, create_win, get_window_attribute, message_box, set_window_flag, dialog_message, get_text_width, hide_window, show_window, create_message_window | - |
|
||||
| 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<br>create_message_window | âś… except interface_print, draw_image, draw_image_scaled, interface_overlay | - |
|
||||
| Interface / Outline | outlined_object<br>get_outline<br>set_outline | âś… | - |
|
||||
| Interface / Main interface | intface_is_hidden<br>intface_redraw<br>intface_hide<br>intface_show<br>set_quest_failure_value | implemented: only intface_redraw | `intface_redraw` only supports the zero-argument form; the optional-argument path is explicitly unimplemented. |
|
||||
| Interface / Inventory | display_stats<br>inventory_redraw<br>critter_inven_obj2<br>get_current_inven_size<br>item_weight | âś… except get_current_inven_size | - |
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB |
@@ -1 +0,0 @@
|
||||
{0}{}{HELP}
|
||||
@@ -1 +0,0 @@
|
||||
{0}{}{AIDE}
|
||||
@@ -1 +0,0 @@
|
||||
{0}{}{HILFE}
|
||||
@@ -1 +0,0 @@
|
||||
{0}{}{AIUTO}
|
||||
@@ -1 +0,0 @@
|
||||
{0}{}{POMOC}
|
||||
@@ -1 +0,0 @@
|
||||
{0}{}{AJUDA}
|
||||
@@ -1 +0,0 @@
|
||||
{0}{}{ПОМОЩЬ}
|
||||
@@ -1 +0,0 @@
|
||||
{0}{}{AYUDA}
|
||||
+1
-10
@@ -39,16 +39,7 @@ IFACE_BAR_SIDES_ORI=0
|
||||
;if IFACE_BAR_WIDTH=800 - Interface bar will use 800pix wide asset from f2_res.dat. Note
|
||||
|
||||
IFACE_BAR_WIDTH=640
|
||||
|
||||
; Controls ammo display in the HP/AC cluster.
|
||||
; 0 = stock 1-pixel ammo bar only.
|
||||
; 1 = numeric current/max ammo counter only.
|
||||
; 2 = HRP 2-pixel ammo bar only.
|
||||
; 3 = hidden, no stock bar and no numeric counter.
|
||||
; 4 = stock 1-pixel ammo bar plus numeric counter.
|
||||
; 5 = HRP 2-pixel ammo bar plus numeric counter.
|
||||
IFACE_AMMO_COUNTER=0
|
||||
|
||||
|
||||
;##################################################################################################################
|
||||
[STATIC_SCREENS]
|
||||
|
||||
|
||||
@@ -130,8 +130,6 @@ inventory_columns=2
|
||||
;Set to 1 to scale only the main menu background image to fit the screen while maintaining aspect ratio.
|
||||
;Set to 2 to also scale the main menu button panel, red buttons, and button labels with the menu art.
|
||||
main_menu_scale_mode=1
|
||||
;Set to 1 to show a Help option in the in-game options menu which opens the F1 help screen.
|
||||
in_game_menu_help=1
|
||||
|
||||
|
||||
[qol]
|
||||
|
||||
+141
-79
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "animation.h"
|
||||
#include "content_config.h"
|
||||
#include "datafile.h"
|
||||
#include "debug.h"
|
||||
#include "draw.h"
|
||||
#include "game.h"
|
||||
@@ -524,34 +525,6 @@ unsigned char* artLockFrameData(int fid, int frame, int direction, CacheEntry**
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 0x4191CC
|
||||
unsigned char* artLockFrameDataReturningSize(int fid, CacheEntry** handlePtr, int* widthPtr, int* heightPtr)
|
||||
{
|
||||
*handlePtr = nullptr;
|
||||
|
||||
Art* art = nullptr;
|
||||
cacheLock(&gArtCache, fid, (void**)&art, handlePtr);
|
||||
|
||||
if (art == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// NOTE: Uninline.
|
||||
*widthPtr = artGetWidth(art, 0, 0);
|
||||
if (*widthPtr == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// NOTE: Uninline.
|
||||
*heightPtr = artGetHeight(art, 0, 0);
|
||||
if (*heightPtr == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// NOTE: Uninline.
|
||||
return artGetFrameData(art, 0, 0);
|
||||
}
|
||||
|
||||
// 0x419260
|
||||
int artUnlock(CacheEntry* handle)
|
||||
{
|
||||
@@ -1221,6 +1194,51 @@ static bool artIndexedPngHasSupportedTransparency(const LodePNGColorMode& color)
|
||||
return true;
|
||||
}
|
||||
|
||||
static Art* artAllocateSingleFrame(int width, int height, unsigned char** frameDataPtr)
|
||||
{
|
||||
if (width <= 0 || height <= 0 || width > SHRT_MAX || height > SHRT_MAX) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t pixelCount = static_cast<size_t>(width) * static_cast<size_t>(height);
|
||||
if (pixelCount > kMaxNamedPngPixels || pixelCount > INT_MAX) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Art header = {};
|
||||
header.version = 4;
|
||||
header.framesPerSecond = 10;
|
||||
header.actionFrame = 0;
|
||||
header.frameCount = 1;
|
||||
header.dataSize = sizeof(ArtFrame) + static_cast<int>(pixelCount);
|
||||
|
||||
int currentPadding = paddingForSize(sizeof(Art));
|
||||
for (int rotation = 0; rotation < ROTATION_COUNT; rotation++) {
|
||||
header.dataOffsets[rotation] = 0;
|
||||
header.padding[rotation] = currentPadding;
|
||||
}
|
||||
|
||||
int dataSize = artGetDataSize(&header);
|
||||
unsigned char* data = reinterpret_cast<unsigned char*>(internal_malloc(dataSize));
|
||||
if (data == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
memset(data, 0, dataSize);
|
||||
Art* art = reinterpret_cast<Art*>(data);
|
||||
*art = header;
|
||||
|
||||
ArtFrame* frame = reinterpret_cast<ArtFrame*>(data + sizeof(Art) + art->padding[0]);
|
||||
frame->width = static_cast<short>(width);
|
||||
frame->height = static_cast<short>(height);
|
||||
frame->size = static_cast<int>(pixelCount);
|
||||
frame->x = 0;
|
||||
frame->y = 0;
|
||||
|
||||
*frameDataPtr = reinterpret_cast<unsigned char*>(frame) + sizeof(ArtFrame);
|
||||
return art;
|
||||
}
|
||||
|
||||
static Art* artLoadIndexedPng(const char* path)
|
||||
{
|
||||
std::vector<unsigned char> encoded;
|
||||
@@ -1255,47 +1273,44 @@ static Art* artLoadIndexedPng(const char* path)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t pixelCount = static_cast<size_t>(width) * static_cast<size_t>(height);
|
||||
|
||||
Art header = {};
|
||||
header.version = 4;
|
||||
header.framesPerSecond = 10;
|
||||
header.actionFrame = 0;
|
||||
header.frameCount = 1;
|
||||
header.dataSize = sizeof(ArtFrame) + static_cast<int>(pixelCount);
|
||||
|
||||
int currentPadding = paddingForSize(sizeof(Art));
|
||||
for (int rotation = 0; rotation < ROTATION_COUNT; rotation++) {
|
||||
header.dataOffsets[rotation] = 0;
|
||||
header.padding[rotation] = currentPadding;
|
||||
}
|
||||
|
||||
int dataSize = artGetDataSize(&header);
|
||||
unsigned char* data = reinterpret_cast<unsigned char*>(internal_malloc(dataSize));
|
||||
if (data == nullptr) {
|
||||
unsigned char* frameData = nullptr;
|
||||
Art* art = artAllocateSingleFrame(static_cast<int>(width), static_cast<int>(height), &frameData);
|
||||
if (art == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
memset(data, 0, dataSize);
|
||||
Art* art = reinterpret_cast<Art*>(data);
|
||||
*art = header;
|
||||
|
||||
ArtFrame* frame = reinterpret_cast<ArtFrame*>(data + sizeof(Art) + art->padding[0]);
|
||||
frame->width = static_cast<short>(width);
|
||||
frame->height = static_cast<short>(height);
|
||||
frame->size = static_cast<int>(pixelCount);
|
||||
frame->x = 0;
|
||||
frame->y = 0;
|
||||
|
||||
if (!artUnpackIndexedPngPixels(indexedData, width, height, state.info_png.color.bitdepth, reinterpret_cast<unsigned char*>(frame) + sizeof(ArtFrame))) {
|
||||
if (!artUnpackIndexedPngPixels(indexedData, width, height, state.info_png.color.bitdepth, frameData)) {
|
||||
debugPrint("ART: failed to read indexed PNG pixels: %s\n", path);
|
||||
internal_free(data);
|
||||
internal_free(art);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return art;
|
||||
}
|
||||
|
||||
static Art* artLoadPcx(const char* path)
|
||||
{
|
||||
char mutablePath[COMPAT_MAX_PATH];
|
||||
strncpy(mutablePath, path, sizeof(mutablePath));
|
||||
mutablePath[sizeof(mutablePath) - 1] = '\0';
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
unsigned char* pcxData = datafileRead(mutablePath, &width, &height);
|
||||
if (pcxData == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned char* frameData = nullptr;
|
||||
Art* art = artAllocateSingleFrame(width, height, &frameData);
|
||||
if (art != nullptr) {
|
||||
memcpy(frameData, pcxData, static_cast<size_t>(width) * static_cast<size_t>(height));
|
||||
}
|
||||
|
||||
internal_free(pcxData);
|
||||
return art;
|
||||
}
|
||||
|
||||
static Art* artLoadFrm(const char* path)
|
||||
{
|
||||
File* stream = fileOpen(path, "rb");
|
||||
@@ -1340,6 +1355,10 @@ Art* artLoad(const char* path)
|
||||
return artLoadIndexedPng(path);
|
||||
}
|
||||
|
||||
if (artPathHasExtension(path, ".pcx")) {
|
||||
return artLoadPcx(path);
|
||||
}
|
||||
|
||||
Art* art = artLoadFrm(path);
|
||||
if (art != nullptr) {
|
||||
return art;
|
||||
@@ -1491,7 +1510,7 @@ public:
|
||||
|
||||
const Art* art() const { return _art.get(); }
|
||||
|
||||
unsigned char* frameData(int frame, int direction, int& outWidth, int& outHeight) const;
|
||||
ArtFrame* frame(int frame, int direction) const;
|
||||
|
||||
unsigned int mru = 0;
|
||||
|
||||
@@ -1504,17 +1523,9 @@ NamedCacheEntry::NamedCacheEntry(ArtPtr&& art)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned char* NamedCacheEntry::frameData(int frame, int direction, int& outWidth, int& outHeight) const
|
||||
ArtFrame* NamedCacheEntry::frame(int frame, int direction) const
|
||||
{
|
||||
unsigned char* data = artGetFrameData(_art.get(), frame, direction);
|
||||
if (!data) {
|
||||
outWidth = 0;
|
||||
outHeight = 0;
|
||||
return nullptr;
|
||||
}
|
||||
outWidth = artGetWidth(_art.get(), frame, direction);
|
||||
outHeight = artGetHeight(_art.get(), frame, direction);
|
||||
return data;
|
||||
return artGetFrame(_art.get(), frame, direction);
|
||||
}
|
||||
|
||||
std::shared_ptr<NamedCacheEntry> artLockNamedFrameData(const char* path)
|
||||
@@ -1597,9 +1608,12 @@ ObjectType FrmId::objectType() const
|
||||
FrmImage::FrmImage()
|
||||
{
|
||||
_key = nullptr;
|
||||
_frame = nullptr;
|
||||
_data = nullptr;
|
||||
_width = 0;
|
||||
_height = 0;
|
||||
_xOffset = 0;
|
||||
_yOffset = 0;
|
||||
}
|
||||
|
||||
FrmImage::~FrmImage()
|
||||
@@ -1610,9 +1624,12 @@ FrmImage::~FrmImage()
|
||||
FrmImage::FrmImage(FrmImage&& other) noexcept
|
||||
: _namedKey(std::move(other._namedKey))
|
||||
, _key(other._key)
|
||||
, _frame(other._frame)
|
||||
, _data(other._data)
|
||||
, _width(other._width)
|
||||
, _height(other._height)
|
||||
, _xOffset(other._xOffset)
|
||||
, _yOffset(other._yOffset)
|
||||
{
|
||||
other.resetInternal();
|
||||
}
|
||||
@@ -1623,9 +1640,12 @@ FrmImage& FrmImage::operator=(FrmImage&& other) noexcept
|
||||
unlock();
|
||||
_namedKey = std::move(other._namedKey);
|
||||
_key = other._key;
|
||||
_frame = other._frame;
|
||||
_data = other._data;
|
||||
_width = other._width;
|
||||
_height = other._height;
|
||||
_xOffset = other._xOffset;
|
||||
_yOffset = other._yOffset;
|
||||
|
||||
other.resetInternal();
|
||||
}
|
||||
@@ -1633,33 +1653,60 @@ FrmImage& FrmImage::operator=(FrmImage&& other) noexcept
|
||||
}
|
||||
|
||||
bool FrmImage::lock(const FrmId& frmId)
|
||||
{
|
||||
return lock(frmId, 0, 0);
|
||||
}
|
||||
|
||||
bool FrmImage::lock(const FrmId& frmId, int frame, int direction)
|
||||
{
|
||||
if (frmId.fid() >= 0) {
|
||||
return lock(frmId.fid());
|
||||
return lock(frmId.fid(), frame, direction);
|
||||
}
|
||||
if (frmId.filePath() != nullptr) {
|
||||
return frmId.hasObjectType()
|
||||
? lock(frmId.objectType(), frmId.filePath())
|
||||
: lock(frmId.filePath());
|
||||
? lock(frmId.objectType(), frmId.filePath(), frame, direction)
|
||||
: lock(frmId.filePath(), frame, direction);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FrmImage::lock(unsigned int fid)
|
||||
{
|
||||
return lock(fid, 0, 0);
|
||||
}
|
||||
|
||||
bool FrmImage::lock(unsigned int fid, int frame, int direction)
|
||||
{
|
||||
if (isLocked()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_data = artLockFrameDataReturningSize(fid, &_key, &_width, &_height);
|
||||
if (!_data) {
|
||||
Art* art = artLock(fid, &_key);
|
||||
if (art == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_frame = artGetFrame(art, frame, direction);
|
||||
if (_frame == nullptr) {
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
_data = reinterpret_cast<unsigned char*>(_frame) + sizeof(ArtFrame);
|
||||
_width = _frame->width;
|
||||
_height = _frame->height;
|
||||
_xOffset = _frame->x;
|
||||
_yOffset = _frame->y;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FrmImage::lock(const char* frmPath)
|
||||
{
|
||||
return lock(frmPath, 0, 0);
|
||||
}
|
||||
|
||||
bool FrmImage::lock(const char* frmPath, int frame, int direction)
|
||||
{
|
||||
if (isLocked()) {
|
||||
return false;
|
||||
@@ -1668,21 +1715,33 @@ bool FrmImage::lock(const char* frmPath)
|
||||
_namedKey = artLockNamedFrameData(frmPath);
|
||||
if (!_namedKey) return false;
|
||||
|
||||
_data = _namedKey->frameData(0, 0, _width, _height);
|
||||
if (_data == nullptr) {
|
||||
_namedKey = nullptr;
|
||||
_frame = _namedKey->frame(frame, direction);
|
||||
if (_frame == nullptr) {
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
_data = reinterpret_cast<unsigned char*>(_frame) + sizeof(ArtFrame);
|
||||
_width = _frame->width;
|
||||
_height = _frame->height;
|
||||
_xOffset = _frame->x;
|
||||
_yOffset = _frame->y;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FrmImage::lock(ObjectType objType, const char* frmRelativePath)
|
||||
{
|
||||
return lock(objType, frmRelativePath, 0, 0);
|
||||
}
|
||||
|
||||
bool FrmImage::lock(ObjectType objType, const char* frmRelativePath, int frame, int direction)
|
||||
{
|
||||
if (objType < OBJ_TYPE_ITEM || objType >= OBJ_TYPE_COUNT) {
|
||||
return false;
|
||||
}
|
||||
snprintf(_art_name, sizeof(_art_name), "%s%s%s\\%s", _cd_path_base, "art\\", gArtListDescriptions[objType].name, frmRelativePath);
|
||||
return lock(_art_name);
|
||||
return lock(_art_name, frame, direction);
|
||||
}
|
||||
|
||||
void FrmImage::unlock()
|
||||
@@ -1697,9 +1756,12 @@ void FrmImage::resetInternal()
|
||||
{
|
||||
_namedKey = nullptr;
|
||||
_key = nullptr;
|
||||
_frame = nullptr;
|
||||
_data = nullptr;
|
||||
_width = 0;
|
||||
_height = 0;
|
||||
_xOffset = 0;
|
||||
_yOffset = 0;
|
||||
}
|
||||
|
||||
} // namespace fallout
|
||||
|
||||
@@ -128,7 +128,6 @@ void artRender(int fid, unsigned char* dest, int width, int height, int pitch);
|
||||
int art_list_str(int fid, char* name);
|
||||
Art* artLock(int fid, CacheEntry** cache_entry);
|
||||
unsigned char* artLockFrameData(int fid, int frame, int direction, CacheEntry** out_cache_entry);
|
||||
unsigned char* artLockFrameDataReturningSize(int fid, CacheEntry** out_cache_entry, int* widthPtr, int* heightPtr);
|
||||
int artUnlock(CacheEntry* cache_entry);
|
||||
int artCacheFlush();
|
||||
int artCopyFileName(int objectType, int id, char* dest);
|
||||
@@ -185,8 +184,8 @@ private:
|
||||
const char* _path = nullptr;
|
||||
};
|
||||
|
||||
// A helper for using RAII to read single-frame FRM's.
|
||||
// lock/unlock use the art-cache instead of just loading/unloading directly.
|
||||
// RAII helper for locking one selected frame from FID-backed or path-backed art.
|
||||
// lock/unlock use caches instead of just loading/unloading directly.
|
||||
class FrmImage {
|
||||
public:
|
||||
FrmImage();
|
||||
@@ -201,13 +200,19 @@ public:
|
||||
|
||||
bool isLocked() const { return _key != nullptr || _namedKey; }
|
||||
bool lock(const FrmId& frmId);
|
||||
bool lock(const FrmId& frmId, int frame, int direction);
|
||||
bool lock(unsigned int fid);
|
||||
bool lock(unsigned int fid, int frame, int direction);
|
||||
bool lock(const char* frmPath);
|
||||
bool lock(const char* frmPath, int frame, int direction);
|
||||
bool lock(ObjectType objType, const char* frmRelativePath);
|
||||
bool lock(ObjectType objType, const char* frmRelativePath, int frame, int direction);
|
||||
void unlock();
|
||||
|
||||
int getWidth() const { return _width; }
|
||||
int getHeight() const { return _height; }
|
||||
int getXOffset() const { return _xOffset; }
|
||||
int getYOffset() const { return _yOffset; }
|
||||
// Returns FRM frame data if locked, nullptr otherwise.
|
||||
unsigned char* getData() const { return _data; }
|
||||
|
||||
@@ -218,9 +223,12 @@ private:
|
||||
|
||||
std::shared_ptr<NamedCacheEntry> _namedKey;
|
||||
CacheEntry* _key = nullptr;
|
||||
ArtFrame* _frame = nullptr;
|
||||
unsigned char* _data = nullptr;
|
||||
int _width = 0;
|
||||
int _height = 0;
|
||||
int _xOffset = 0;
|
||||
int _yOffset = 0;
|
||||
};
|
||||
|
||||
} // namespace fallout
|
||||
|
||||
+10
-13
@@ -663,7 +663,7 @@ static int gCharacterEditorPrimaryStatMinusBtns[7];
|
||||
static unsigned char* gCharacterEditorWindowBuffer;
|
||||
|
||||
// 0x57060C edit_win
|
||||
static int gCharacterEditorWindow = -1;
|
||||
static int gCharacterEditorWindow;
|
||||
|
||||
// + stats buttons
|
||||
//
|
||||
@@ -1436,27 +1436,24 @@ static int characterEditorWindowInit()
|
||||
str = getmsg(&gCharacterEditorMessageList, &gCharacterEditorMessageListItem, 111);
|
||||
strcpy(kills, str);
|
||||
|
||||
int tabLabelY = 5;
|
||||
int inactiveTabLabelY = tabLabelY + 1;
|
||||
|
||||
// perks selected
|
||||
len = fontGetStringWidth(perks);
|
||||
fontDrawText(
|
||||
gCharacterEditorFrmCopy[46] + tabLabelY * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 61 - len / 2,
|
||||
gCharacterEditorFrmCopy[46] + 5 * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 61 - len / 2,
|
||||
perks,
|
||||
_editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth(),
|
||||
_editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth(),
|
||||
_colorTable[18979]);
|
||||
|
||||
len = fontGetStringWidth(karma);
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED] + inactiveTabLabelY * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 159 - len / 2,
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED] + 5 * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 159 - len / 2,
|
||||
karma,
|
||||
_editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth(),
|
||||
_editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth(),
|
||||
_colorTable[14723]);
|
||||
|
||||
len = fontGetStringWidth(kills);
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED] + inactiveTabLabelY * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 257 - len / 2,
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED] + 5 * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 257 - len / 2,
|
||||
kills,
|
||||
_editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth(),
|
||||
_editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth(),
|
||||
@@ -1464,21 +1461,21 @@ static int characterEditorWindowInit()
|
||||
|
||||
// karma selected
|
||||
len = fontGetStringWidth(perks);
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_KARMA_FOLDER_SELECTED] + inactiveTabLabelY * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 61 - len / 2,
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_KARMA_FOLDER_SELECTED] + 5 * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 61 - len / 2,
|
||||
perks,
|
||||
_editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth(),
|
||||
_editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth(),
|
||||
_colorTable[14723]);
|
||||
|
||||
len = fontGetStringWidth(karma);
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_KARMA_FOLDER_SELECTED] + tabLabelY * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 159 - len / 2,
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_KARMA_FOLDER_SELECTED] + 5 * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 159 - len / 2,
|
||||
karma,
|
||||
_editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth(),
|
||||
_editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth(),
|
||||
_colorTable[18979]);
|
||||
|
||||
len = fontGetStringWidth(kills);
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_KARMA_FOLDER_SELECTED] + inactiveTabLabelY * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 257 - len / 2,
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_KARMA_FOLDER_SELECTED] + 5 * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 257 - len / 2,
|
||||
kills,
|
||||
_editorFrmImages[46].getWidth(),
|
||||
_editorFrmImages[46].getWidth(),
|
||||
@@ -1486,21 +1483,21 @@ static int characterEditorWindowInit()
|
||||
|
||||
// kills selected
|
||||
len = fontGetStringWidth(perks);
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_KILLS_FOLDER_SELECTED] + inactiveTabLabelY * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 61 - len / 2,
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_KILLS_FOLDER_SELECTED] + 5 * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 61 - len / 2,
|
||||
perks,
|
||||
_editorFrmImages[46].getWidth(),
|
||||
_editorFrmImages[46].getWidth(),
|
||||
_colorTable[14723]);
|
||||
|
||||
len = fontGetStringWidth(karma);
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_KILLS_FOLDER_SELECTED] + inactiveTabLabelY * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 159 - len / 2,
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_KILLS_FOLDER_SELECTED] + 5 * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 159 - len / 2,
|
||||
karma,
|
||||
_editorFrmImages[46].getWidth(),
|
||||
_editorFrmImages[46].getWidth(),
|
||||
_colorTable[14723]);
|
||||
|
||||
len = fontGetStringWidth(kills);
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_KILLS_FOLDER_SELECTED] + tabLabelY * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 257 - len / 2,
|
||||
fontDrawText(gCharacterEditorFrmCopy[EDITOR_GRAPHIC_KILLS_FOLDER_SELECTED] + 5 * _editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth() + 257 - len / 2,
|
||||
kills,
|
||||
_editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth(),
|
||||
_editorFrmImages[EDITOR_GRAPHIC_PERKS_FOLDER_SELECTED].getWidth(),
|
||||
|
||||
+64
-53
@@ -3537,7 +3537,7 @@ void attackInit(Attack* attack, Object* attacker, Object* defender, int hitMode,
|
||||
attack->defenderFlags = 0;
|
||||
attack->defenderKnockback = 0;
|
||||
attack->extrasLength = 0;
|
||||
attack->intendedTarget = defender;
|
||||
attack->oops = defender;
|
||||
}
|
||||
|
||||
// 0x422F3C
|
||||
@@ -4336,7 +4336,7 @@ static int attackComputeCriticalFailure(Attack* attack)
|
||||
int rounds = attackType == ATTACK_TYPE_RANGED ? attack->ammoQuantity : 1;
|
||||
attackComputeDamage(attack, rounds, 2);
|
||||
} else {
|
||||
attack->defender = attack->intendedTarget;
|
||||
attack->defender = attack->oops;
|
||||
}
|
||||
|
||||
if (attack->defender != nullptr) {
|
||||
@@ -4758,28 +4758,31 @@ void _apply_damage(Attack* attack, bool animated)
|
||||
{
|
||||
Object* attacker = attack->attacker;
|
||||
bool attackerIsCritter = attacker != nullptr && FID_TYPE(attacker->fid) == OBJ_TYPE_CRITTER;
|
||||
bool hitUnintendedTarget = attack->defender != attack->intendedTarget;
|
||||
bool v5 = attack->defender != attack->oops;
|
||||
|
||||
if (attackerIsCritter && (attacker->data.critter.combat.results & DAM_DEAD) == 0) {
|
||||
_set_new_results(attacker, attack->attackerFlags);
|
||||
_damage_object(attacker, attack->attackerDamage, animated, hitUnintendedTarget, attacker);
|
||||
// TODO: Not sure about "attack->defender == attack->oops".
|
||||
_damage_object(attacker, attack->attackerDamage, animated, attack->defender == attack->oops, attacker);
|
||||
}
|
||||
|
||||
// bystanders might flee
|
||||
if (attack->intendedTarget != nullptr && hitUnintendedTarget) {
|
||||
_combatai_notify_onlookers(attack->intendedTarget);
|
||||
Object* v7 = attack->oops;
|
||||
if (v7 != nullptr && v7 != attack->defender) {
|
||||
_combatai_notify_onlookers(v7);
|
||||
}
|
||||
|
||||
Object* defender = attack->defender;
|
||||
bool defenderIsCritter = defender != nullptr && FID_TYPE(defender->fid) == OBJ_TYPE_CRITTER;
|
||||
|
||||
if (!defenderIsCritter && !hitUnintendedTarget) {
|
||||
bool shouldRunDamageProc = !objectIsPartyMember(attack->defender) || !objectIsPartyMember(attack->attacker);
|
||||
if (shouldRunDamageProc) {
|
||||
if (defender != nullptr && defender->sid != -1) {
|
||||
scriptSetFixedParam(defender->sid, attack->attackerDamage);
|
||||
scriptSetObjects(defender->sid, attack->attacker, attack->weapon);
|
||||
scriptExecProc(defender->sid, SCRIPT_PROC_DAMAGE);
|
||||
if (!defenderIsCritter && !v5) {
|
||||
bool v9 = objectIsPartyMember(attack->defender) && objectIsPartyMember(attack->attacker) ? false : true;
|
||||
if (v9) {
|
||||
if (defender != nullptr) {
|
||||
if (defender->sid != -1) {
|
||||
scriptSetFixedParam(defender->sid, attack->attackerDamage);
|
||||
scriptSetObjects(defender->sid, attack->attacker, attack->weapon);
|
||||
scriptExecProc(defender->sid, SCRIPT_PROC_DAMAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4787,17 +4790,24 @@ void _apply_damage(Attack* attack, bool animated)
|
||||
if (defenderIsCritter && (defender->data.critter.combat.results & DAM_DEAD) == 0) {
|
||||
_set_new_results(defender, attack->defenderFlags);
|
||||
|
||||
if ((defender->data.critter.combat.results & (DAM_DEAD | DAM_KNOCKED_OUT)) != 0) {
|
||||
if (!hitUnintendedTarget || defender != gDude) {
|
||||
critterSetWhoHitMe(defender, attack->attacker);
|
||||
if (defenderIsCritter) {
|
||||
if (defenderIsCritter) {
|
||||
if ((defender->data.critter.combat.results & (DAM_DEAD | DAM_KNOCKED_OUT)) != 0) {
|
||||
if (!v5 || defender != gDude) {
|
||||
critterSetWhoHitMe(defender, attack->attacker);
|
||||
}
|
||||
} else if (defender == attack->oops || defender->data.critter.combat.team != attack->attacker->data.critter.combat.team) {
|
||||
_combatai_check_retaliation(defender, attack->attacker);
|
||||
}
|
||||
}
|
||||
} else if (attackerIsCritter && (defender == attack->intendedTarget || defender->data.critter.combat.team != attack->attacker->data.critter.combat.team)) {
|
||||
_combatai_check_retaliation(defender, attack->attacker);
|
||||
}
|
||||
|
||||
scriptSetObjects(defender->sid, attack->attacker, attack->weapon);
|
||||
_damage_object(defender, attack->defenderDamage, animated, hitUnintendedTarget, attacker);
|
||||
_combatai_notify_onlookers(defender);
|
||||
_damage_object(defender, attack->defenderDamage, animated, attack->defender != attack->oops, attacker);
|
||||
|
||||
if (defenderIsCritter) {
|
||||
_combatai_notify_onlookers(defender);
|
||||
}
|
||||
|
||||
if (attack->defenderDamage >= 0 && (attack->attackerFlags & DAM_HIT) != 0) {
|
||||
scriptSetObjects(attack->attacker->sid, nullptr, attack->defender);
|
||||
@@ -4814,13 +4824,14 @@ void _apply_damage(Attack* attack, bool animated)
|
||||
if (defenderIsCritter) {
|
||||
if ((obj->data.critter.combat.results & (DAM_DEAD | DAM_KNOCKED_OUT)) != 0) {
|
||||
critterSetWhoHitMe(obj, attack->attacker);
|
||||
} else if (attackerIsCritter && obj->data.critter.combat.team != attack->attacker->data.critter.combat.team) {
|
||||
} else if (obj->data.critter.combat.team != attack->attacker->data.critter.combat.team) {
|
||||
_combatai_check_retaliation(obj, attack->attacker);
|
||||
}
|
||||
}
|
||||
|
||||
scriptSetObjects(obj->sid, attack->attacker, attack->weapon);
|
||||
_damage_object(obj, attack->extrasDamage[index], animated, hitUnintendedTarget, attack->attacker);
|
||||
// TODO: Not sure about defender == oops.
|
||||
_damage_object(obj, attack->extrasDamage[index], animated, attack->defender == attack->oops, attack->attacker);
|
||||
_combatai_notify_onlookers(obj);
|
||||
|
||||
if (attack->extrasDamage[index] >= 0) {
|
||||
@@ -4889,18 +4900,18 @@ static void _set_new_results(Object* critter, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
// 0x425020 damage_object
|
||||
static void _damage_object(Object* target, int damage, bool animated, int hitUnintendedTarget, Object* damageSource)
|
||||
// 0x425020
|
||||
static void _damage_object(Object* a1, int damage, bool animated, int a4, Object* a5)
|
||||
{
|
||||
if (target == nullptr) {
|
||||
if (a1 == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (FID_TYPE(target->fid) != OBJ_TYPE_CRITTER) {
|
||||
if (FID_TYPE(a1->fid) != OBJ_TYPE_CRITTER) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (critterFlagCheck(target->pid, CRITTER_INVULNERABLE)) {
|
||||
if (critterFlagCheck(a1->pid, CRITTER_INVULNERABLE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4908,50 +4919,50 @@ static void _damage_object(Object* target, int damage, bool animated, int hitUni
|
||||
return;
|
||||
}
|
||||
|
||||
critterAdjustHitPoints(target, -damage);
|
||||
critterAdjustHitPoints(a1, -damage);
|
||||
|
||||
if (target == gDude) {
|
||||
if (a1 == gDude) {
|
||||
interfaceRenderHitPoints(animated);
|
||||
}
|
||||
|
||||
target->data.critter.combat.damageLastTurn += damage;
|
||||
a1->data.critter.combat.damageLastTurn += damage;
|
||||
|
||||
if (!hitUnintendedTarget) {
|
||||
if (!a4) {
|
||||
// TODO: Not sure about this one.
|
||||
if (!objectIsPartyMember(target) || !objectIsPartyMember(damageSource)) {
|
||||
scriptSetFixedParam(target->sid, damage);
|
||||
scriptExecProc(target->sid, SCRIPT_PROC_DAMAGE);
|
||||
if (!objectIsPartyMember(a1) || !objectIsPartyMember(a5)) {
|
||||
scriptSetFixedParam(a1->sid, damage);
|
||||
scriptExecProc(a1->sid, SCRIPT_PROC_DAMAGE);
|
||||
}
|
||||
}
|
||||
|
||||
if ((target->data.critter.combat.results & DAM_DEAD) != 0) {
|
||||
scriptSetObjects(target->sid, target->data.critter.combat.whoHitMe, nullptr);
|
||||
scriptExecProc(target->sid, SCRIPT_PROC_DESTROY);
|
||||
itemDestroyAllHidden(target);
|
||||
if ((a1->data.critter.combat.results & DAM_DEAD) != 0) {
|
||||
scriptSetObjects(a1->sid, a1->data.critter.combat.whoHitMe, nullptr);
|
||||
scriptExecProc(a1->sid, SCRIPT_PROC_DESTROY);
|
||||
itemDestroyAllHidden(a1);
|
||||
|
||||
if (target != gDude) {
|
||||
Object* whoHitMe = target->data.critter.combat.whoHitMe;
|
||||
if (a1 != gDude) {
|
||||
Object* whoHitMe = a1->data.critter.combat.whoHitMe;
|
||||
if (whoHitMe == gDude || (whoHitMe != nullptr && whoHitMe->data.critter.combat.team == gDude->data.critter.combat.team)) {
|
||||
bool scriptOverrides = false;
|
||||
Script* scr;
|
||||
if (scriptGetScript(target->sid, &scr) != -1) {
|
||||
if (scriptGetScript(a1->sid, &scr) != -1) {
|
||||
scriptOverrides = scr->scriptOverrides;
|
||||
}
|
||||
|
||||
if (!scriptOverrides) {
|
||||
_combat_exps += critterGetExp(target);
|
||||
killsIncByType(critterGetKillType(target));
|
||||
_combat_exps += critterGetExp(a1);
|
||||
killsIncByType(critterGetKillType(a1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (target->sid != -1) {
|
||||
scriptRemove(target->sid);
|
||||
target->sid = -1;
|
||||
if (a1->sid != -1) {
|
||||
scriptRemove(a1->sid);
|
||||
a1->sid = -1;
|
||||
}
|
||||
|
||||
partyMemberRemove(target);
|
||||
scriptHooks_OnDeath(target);
|
||||
partyMemberRemove(a1);
|
||||
scriptHooks_OnDeath(a1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5023,11 +5034,11 @@ void _combat_display(Attack* attack)
|
||||
|
||||
char text[280];
|
||||
if (attack->defender != nullptr
|
||||
&& attack->intendedTarget != nullptr
|
||||
&& attack->defender != attack->intendedTarget
|
||||
&& attack->oops != nullptr
|
||||
&& attack->defender != attack->oops
|
||||
&& (attack->attackerFlags & DAM_HIT) != 0) {
|
||||
if (FID_TYPE(attack->defender->fid) == OBJ_TYPE_CRITTER) {
|
||||
if (attack->intendedTarget == gDude) {
|
||||
if (attack->oops == gDude) {
|
||||
// 608 (male) - Oops! %s was hit instead of you!
|
||||
// 708 (female) - Oops! %s was hit instead of you!
|
||||
messageListItem.num = baseMessageId + 8;
|
||||
@@ -5037,7 +5048,7 @@ void _combat_display(Attack* attack)
|
||||
} else {
|
||||
// 509 (male) - Oops! %s were hit instead of %s!
|
||||
// 559 (female) - Oops! %s were hit instead of %s!
|
||||
const char* name = objectGetName(attack->intendedTarget);
|
||||
const char* name = objectGetName(attack->oops);
|
||||
messageListItem.num = baseMessageId + 9;
|
||||
if (messageListGetItem(&gCombatMessageList, &messageListItem)) {
|
||||
snprintf(text, sizeof(text), messageListItem.text, mainCritterName, name);
|
||||
|
||||
+2
-2
@@ -103,7 +103,7 @@ typedef struct Attack {
|
||||
Object* attacker;
|
||||
int hitMode;
|
||||
Object* weapon;
|
||||
int attackHitLocation; // UNUSED?
|
||||
int attackHitLocation;
|
||||
int attackerDamage;
|
||||
int attackerFlags;
|
||||
int ammoQuantity;
|
||||
@@ -114,7 +114,7 @@ typedef struct Attack {
|
||||
int defenderDamage;
|
||||
int defenderFlags;
|
||||
int defenderKnockback;
|
||||
Object* intendedTarget; // mainTarget
|
||||
Object* oops;
|
||||
int extrasLength;
|
||||
Object* extras[EXPLOSION_TARGET_COUNT];
|
||||
int extrasHitLocation[EXPLOSION_TARGET_COUNT];
|
||||
|
||||
+4
-14
@@ -89,6 +89,7 @@ namespace fallout {
|
||||
static int gameTakeScreenshot(int width, int height, unsigned char* buffer, unsigned char* palette);
|
||||
static void gameFreeGlobalVars();
|
||||
static bool tryLoadBaseCEModAtPath(const char* path, bool* found, bool* openFailed);
|
||||
static void showHelp();
|
||||
static int gameDbInit();
|
||||
static void showSplash();
|
||||
|
||||
@@ -1185,21 +1186,12 @@ static void gameFreeGlobalVars()
|
||||
}
|
||||
|
||||
// 0x443F74
|
||||
void showHelp()
|
||||
static void showHelp()
|
||||
{
|
||||
ScopedGameMode gm(GameMode::kHelp);
|
||||
|
||||
bool isoWasEnabled = isoDisable();
|
||||
bool gameMouseWasVisible;
|
||||
if (isoWasEnabled) {
|
||||
gameMouseWasVisible = gameMouseObjectsIsVisible();
|
||||
} else {
|
||||
gameMouseWasVisible = false;
|
||||
}
|
||||
|
||||
if (gameMouseWasVisible) {
|
||||
gameMouseObjectsHide();
|
||||
}
|
||||
gameMouseObjectsHide();
|
||||
|
||||
gameMouseSetCursor(MOUSE_CURSOR_NONE);
|
||||
|
||||
@@ -1265,9 +1257,7 @@ void showHelp()
|
||||
colorCycleEnable();
|
||||
}
|
||||
|
||||
if (gameMouseWasVisible) {
|
||||
gameMouseObjectsShow();
|
||||
}
|
||||
gameMouseObjectsShow();
|
||||
|
||||
if (isoWasEnabled) {
|
||||
isoEnable();
|
||||
|
||||
@@ -50,7 +50,6 @@ int showQuitConfirmationDialog();
|
||||
int gameLoadGlobalVars();
|
||||
int gameShowDeathDialog(const char* message);
|
||||
void gameHandleSkilldexResult(int rc);
|
||||
void showHelp();
|
||||
void* gameGetGlobalPointer(int var);
|
||||
int gameSetGlobalPointer(int var, void* value);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user