Merge branch 'main' into InterfaceBar
This commit is contained in:
commit
7ce28efb61
|
@ -1396,7 +1396,7 @@ int actionUseSkill(Object* a1, Object* a2, int skill)
|
|||
|
||||
return -1;
|
||||
case SKILL_SNEAK:
|
||||
dudeToggleState(0);
|
||||
dudeToggleState(DUDE_STATE_SNEAKING);
|
||||
return 0;
|
||||
default:
|
||||
debugPrint("\nskill_use: invalid skill used.");
|
||||
|
|
|
@ -690,7 +690,7 @@ int animationRegisterRunToObject(Object* owner, Object* destination, int actionP
|
|||
animationDescription->destination = destination;
|
||||
|
||||
if ((FID_TYPE(owner->fid) == OBJ_TYPE_CRITTER && (owner->data.critter.combat.results & DAM_CRIP_LEG_ANY) != 0)
|
||||
|| (owner == gDude && dudeHasState(0) && !perkGetRank(gDude, PERK_SILENT_RUNNING))
|
||||
|| (owner == gDude && dudeHasState(DUDE_STATE_SNEAKING) && !perkGetRank(gDude, PERK_SILENT_RUNNING))
|
||||
|| !artExists(buildFid(FID_TYPE(owner->fid), owner->fid & 0xFFF, ANIM_RUNNING, 0, owner->rotation + 1))) {
|
||||
animationDescription->anim = ANIM_WALK;
|
||||
} else {
|
||||
|
@ -786,7 +786,7 @@ int animationRegisterRunToTile(Object* owner, int tile, int elevation, int actio
|
|||
animationDescription->elevation = elevation;
|
||||
|
||||
if ((FID_TYPE(owner->fid) == OBJ_TYPE_CRITTER && (owner->data.critter.combat.results & DAM_CRIP_LEG_ANY) != 0)
|
||||
|| (owner == gDude && dudeHasState(0) && !perkGetRank(gDude, PERK_SILENT_RUNNING))
|
||||
|| (owner == gDude && dudeHasState(DUDE_STATE_SNEAKING) && !perkGetRank(gDude, PERK_SILENT_RUNNING))
|
||||
|| !artExists(buildFid(FID_TYPE(owner->fid), owner->fid & 0xFFF, ANIM_RUNNING, 0, owner->rotation + 1))) {
|
||||
animationDescription->anim = ANIM_WALK;
|
||||
} else {
|
||||
|
@ -3043,7 +3043,7 @@ int _dude_run(int a1)
|
|||
}
|
||||
|
||||
if (!perkGetRank(gDude, PERK_SILENT_RUNNING)) {
|
||||
dudeDisableState(0);
|
||||
dudeDisableState(DUDE_STATE_SNEAKING);
|
||||
}
|
||||
|
||||
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
|
||||
|
|
|
@ -1186,8 +1186,8 @@ int characterEditorShow(bool isCreationMode)
|
|||
characterEditorRestorePlayer();
|
||||
}
|
||||
|
||||
if (dudeHasState(0x03)) {
|
||||
dudeDisableState(0x03);
|
||||
if (dudeHasState(DUDE_STATE_LEVEL_UP_AVAILABLE)) {
|
||||
dudeDisableState(DUDE_STATE_LEVEL_UP_AVAILABLE);
|
||||
}
|
||||
|
||||
interfaceRenderHitPoints(false);
|
||||
|
|
|
@ -338,7 +338,7 @@ int fileReadInt32(File* stream, int* valuePtr)
|
|||
return -1;
|
||||
}
|
||||
|
||||
*valuePtr = ((value >> 24) & 0xFF) | ((value >> 8) & 0xFF00) | ((value << 8) & 0xFF0000) | ((value << 24) & 0xFF000000);
|
||||
*valuePtr = ((value & 0xFF000000) >> 24) | ((value & 0xFF0000) >> 8) | ((value & 0xFF00) << 8) | ((value & 0xFF) << 24);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -511,7 +511,7 @@ int fileReadInt32List(File* stream, int* arr, int count)
|
|||
|
||||
for (int index = 0; index < count; index++) {
|
||||
int value = arr[index];
|
||||
arr[index] = ((value >> 24) & 0xFF) | ((value >> 8) & 0xFF00) | ((value << 8) & 0xFF0000) | ((value << 24) & 0xFF000000);
|
||||
arr[index] = ((value & 0xFF000000) >> 24) | ((value & 0xFF0000) >> 8) | ((value & 0xFF00) << 8) | ((value & 0xFF) << 24);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
13
src/debug.cc
13
src/debug.cc
|
@ -5,10 +5,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <SDL.h>
|
||||
|
||||
#include "memory.h"
|
||||
#include "platform_compat.h"
|
||||
|
@ -148,13 +145,7 @@ int debugPrint(const char* format, ...)
|
|||
rc = gDebugPrintProc(string);
|
||||
} else {
|
||||
#ifdef _DEBUG
|
||||
char string[260];
|
||||
vsprintf(string, format, args);
|
||||
#ifdef _WIN32
|
||||
OutputDebugStringA(string);
|
||||
#else
|
||||
printf("%s", string);
|
||||
#endif
|
||||
SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, format, args);
|
||||
#endif
|
||||
rc = -1;
|
||||
}
|
||||
|
|
|
@ -123,60 +123,85 @@ static int interfaceFontLoad(int font_index)
|
|||
|
||||
File* stream = fileOpen(path, "rb");
|
||||
if (stream == NULL) {
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fileSize = fileGetSize(stream);
|
||||
|
||||
int sig;
|
||||
if (fileRead(&sig, 4, 1, stream) != 1) goto err;
|
||||
if (fileRead(&sig, 4, 1, stream) != 1) {
|
||||
fileClose(stream);
|
||||
return -1;
|
||||
}
|
||||
|
||||
interfaceFontByteSwapInt32(&sig);
|
||||
if (sig != 0x41414646) goto err;
|
||||
if (sig != 0x41414646) {
|
||||
fileClose(stream);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fileRead(&(fontDescriptor->maxHeight), 2, 1, stream) != 1) goto err;
|
||||
if (fileRead(&(fontDescriptor->maxHeight), 2, 1, stream) != 1) {
|
||||
fileClose(stream);
|
||||
return -1;
|
||||
}
|
||||
interfaceFontByteSwapInt16(&(fontDescriptor->maxHeight));
|
||||
|
||||
if (fileRead(&(fontDescriptor->letterSpacing), 2, 1, stream) != 1) goto err;
|
||||
if (fileRead(&(fontDescriptor->letterSpacing), 2, 1, stream) != 1) {
|
||||
fileClose(stream);
|
||||
return -1;
|
||||
}
|
||||
interfaceFontByteSwapInt16(&(fontDescriptor->letterSpacing));
|
||||
|
||||
if (fileRead(&(fontDescriptor->wordSpacing), 2, 1, stream) != 1) goto err;
|
||||
if (fileRead(&(fontDescriptor->wordSpacing), 2, 1, stream) != 1) {
|
||||
fileClose(stream);
|
||||
return -1;
|
||||
}
|
||||
interfaceFontByteSwapInt16(&(fontDescriptor->wordSpacing));
|
||||
|
||||
if (fileRead(&(fontDescriptor->lineSpacing), 2, 1, stream) != 1) goto err;
|
||||
if (fileRead(&(fontDescriptor->lineSpacing), 2, 1, stream) != 1) {
|
||||
fileClose(stream);
|
||||
return -1;
|
||||
}
|
||||
interfaceFontByteSwapInt16(&(fontDescriptor->lineSpacing));
|
||||
|
||||
for (int index = 0; index < 256; index++) {
|
||||
InterfaceFontGlyph* glyph = &(fontDescriptor->glyphs[index]);
|
||||
|
||||
if (fileRead(&(glyph->width), 2, 1, stream) != 1) goto err;
|
||||
if (fileRead(&(glyph->width), 2, 1, stream) != 1) {
|
||||
fileClose(stream);
|
||||
return -1;
|
||||
}
|
||||
interfaceFontByteSwapInt16(&(glyph->width));
|
||||
|
||||
if (fileRead(&(glyph->height), 2, 1, stream) != 1) goto err;
|
||||
if (fileRead(&(glyph->height), 2, 1, stream) != 1) {
|
||||
fileClose(stream);
|
||||
return -1;
|
||||
}
|
||||
interfaceFontByteSwapInt16(&(glyph->height));
|
||||
|
||||
if (fileRead(&(glyph->offset), 4, 1, stream) != 1) goto err;
|
||||
if (fileRead(&(glyph->offset), 4, 1, stream) != 1) {
|
||||
fileClose(stream);
|
||||
return -1;
|
||||
}
|
||||
interfaceFontByteSwapInt32(&(glyph->offset));
|
||||
}
|
||||
|
||||
fileSize -= sizeof(InterfaceFontDescriptor);
|
||||
int glyphDataSize = fileSize - 2060;
|
||||
|
||||
fontDescriptor->data = (unsigned char*)internal_malloc_safe(fileSize, __FILE__, __LINE__); // FONTMGR.C, 259
|
||||
if (fontDescriptor->data == NULL) goto err;
|
||||
fontDescriptor->data = (unsigned char*)internal_malloc_safe(glyphDataSize, __FILE__, __LINE__); // FONTMGR.C, 259
|
||||
if (fontDescriptor->data == NULL) {
|
||||
fileClose(stream);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fileRead(fontDescriptor->data, fileSize, 1, stream) != 1) {
|
||||
if (fileRead(fontDescriptor->data, glyphDataSize, 1, stream) != 1) {
|
||||
internal_free_safe(fontDescriptor->data, __FILE__, __LINE__); // FONTMGR.C, 268
|
||||
goto err;
|
||||
fileClose(stream);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fileClose(stream);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
fileClose(stream);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 0x442120
|
||||
|
@ -211,26 +236,22 @@ static int interfaceFontGetStringWidthImpl(const char* string)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const char* pch = string;
|
||||
int width = 0;
|
||||
int stringWidth = 0;
|
||||
|
||||
while (*pch != '\0') {
|
||||
int v3;
|
||||
int v4;
|
||||
while (*string != '\0') {
|
||||
unsigned char ch = static_cast<unsigned char>(*string++);
|
||||
|
||||
if (*pch == ' ') {
|
||||
v3 = gCurrentInterfaceFontDescriptor->letterSpacing;
|
||||
v4 = gCurrentInterfaceFontDescriptor->wordSpacing;
|
||||
int characterWidth;
|
||||
if (ch == ' ') {
|
||||
characterWidth = gCurrentInterfaceFontDescriptor->wordSpacing;
|
||||
} else {
|
||||
v3 = gCurrentInterfaceFontDescriptor->glyphs[*pch & 0xFF].width;
|
||||
v4 = gCurrentInterfaceFontDescriptor->letterSpacing;
|
||||
characterWidth = gCurrentInterfaceFontDescriptor->glyphs[ch].width;
|
||||
}
|
||||
width += v3 + v4;
|
||||
|
||||
pch++;
|
||||
stringWidth += characterWidth + gCurrentInterfaceFontDescriptor->letterSpacing;
|
||||
}
|
||||
|
||||
return width;
|
||||
return stringWidth;
|
||||
}
|
||||
|
||||
// 0x4421DC
|
||||
|
@ -322,13 +343,13 @@ static void interfaceFontDrawImpl(unsigned char* buf, const char* string, int le
|
|||
|
||||
unsigned char* ptr = buf;
|
||||
while (*string != '\0') {
|
||||
char ch = *string++;
|
||||
unsigned char ch = static_cast<unsigned char>(*string++);
|
||||
|
||||
int characterWidth;
|
||||
if (ch == ' ') {
|
||||
characterWidth = gCurrentInterfaceFontDescriptor->wordSpacing;
|
||||
} else {
|
||||
characterWidth = gCurrentInterfaceFontDescriptor->glyphs[ch & 0xFF].width;
|
||||
characterWidth = gCurrentInterfaceFontDescriptor->glyphs[ch].width;
|
||||
}
|
||||
|
||||
unsigned char* end;
|
||||
|
@ -343,7 +364,7 @@ static void interfaceFontDrawImpl(unsigned char* buf, const char* string, int le
|
|||
break;
|
||||
}
|
||||
|
||||
InterfaceFontGlyph* glyph = &(gCurrentInterfaceFontDescriptor->glyphs[ch & 0xFF]);
|
||||
InterfaceFontGlyph* glyph = &(gCurrentInterfaceFontDescriptor->glyphs[ch]);
|
||||
unsigned char* glyphDataPtr = gCurrentInterfaceFontDescriptor->data + glyph->offset;
|
||||
|
||||
// Skip blank pixels (difference between font's line height and glyph height).
|
||||
|
|
|
@ -693,7 +693,7 @@ int gameHandleKey(int eventCode, bool isInCombatMode)
|
|||
}
|
||||
|
||||
if (gIsMapper) {
|
||||
tileSetCenter(gDude->tile, TILE_SET_CENTER_FLAG_0x01);
|
||||
tileSetCenter(gDude->tile, TILE_SET_CENTER_REFRESH_WINDOW);
|
||||
} else {
|
||||
_tile_scroll_to(gDude->tile, 2);
|
||||
}
|
||||
|
|
|
@ -3498,7 +3498,7 @@ void partyMemberControlWindowUpdate()
|
|||
|
||||
FrmImage backgroundFrmImage;
|
||||
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 390, 0, 0, 0);
|
||||
if (!backgroundFrmImage.lock(backgroundFid)) {
|
||||
if (backgroundFrmImage.lock(backgroundFid)) {
|
||||
int width = backgroundFrmImage.getWidth();
|
||||
unsigned char* buffer = backgroundFrmImage.getData();
|
||||
|
||||
|
@ -4104,86 +4104,78 @@ int _gdCustomSelect(int a1)
|
|||
sharedFpsLimiter.mark();
|
||||
|
||||
int keyCode = inputGetInput();
|
||||
if (keyCode == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (keyCode == KEY_CTRL_Q || keyCode == KEY_CTRL_X || keyCode == KEY_F10) {
|
||||
showQuitConfirmationDialog();
|
||||
}
|
||||
|
||||
if (_game_user_wants_to_quit != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (keyCode == KEY_RETURN) {
|
||||
STRUCT_5189E4* ptr = &(_custom_settings[a1][value]);
|
||||
_custom_current_selected[a1] = value;
|
||||
_gdCustomUpdateSetting(a1, ptr->value);
|
||||
done = true;
|
||||
} else if (keyCode == KEY_ESCAPE) {
|
||||
done = true;
|
||||
} else if (keyCode == -2) {
|
||||
if ((mouseGetEvent() & MOUSE_EVENT_LEFT_BUTTON_UP) == 0) {
|
||||
continue;
|
||||
if (keyCode != -1) {
|
||||
if (keyCode == KEY_CTRL_Q || keyCode == KEY_CTRL_X || keyCode == KEY_F10) {
|
||||
showQuitConfirmationDialog();
|
||||
}
|
||||
|
||||
// No need to use mouseHitTestInWindow as these values are already
|
||||
// in screen coordinates.
|
||||
if (!_mouse_click_in(minX, minY, maxX, maxY)) {
|
||||
continue;
|
||||
if (_game_user_wants_to_quit != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
int mouseX;
|
||||
int mouseY;
|
||||
mouseGetPosition(&mouseX, &mouseY);
|
||||
if (keyCode == KEY_RETURN) {
|
||||
STRUCT_5189E4* ptr = &(_custom_settings[a1][value]);
|
||||
_custom_current_selected[a1] = value;
|
||||
_gdCustomUpdateSetting(a1, ptr->value);
|
||||
done = true;
|
||||
} else if (keyCode == KEY_ESCAPE) {
|
||||
done = true;
|
||||
} else if (keyCode == -2) {
|
||||
if ((mouseGetEvent() & MOUSE_EVENT_LEFT_BUTTON_UP) != 0) {
|
||||
// No need to use mouseHitTestInWindow as these values are already
|
||||
// in screen coordinates.
|
||||
if (_mouse_click_in(minX, minY, maxX, maxY)) {
|
||||
int mouseX;
|
||||
int mouseY;
|
||||
mouseGetPosition(&mouseX, &mouseY);
|
||||
|
||||
int lineHeight = fontGetLineHeight();
|
||||
int newValue = (mouseY - minY) / lineHeight;
|
||||
if (newValue >= 6) {
|
||||
continue;
|
||||
}
|
||||
int lineHeight = fontGetLineHeight();
|
||||
int newValue = (mouseY - minY) / lineHeight;
|
||||
if (newValue < 6) {
|
||||
unsigned int timestamp = getTicks();
|
||||
if (newValue == value) {
|
||||
if (getTicksBetween(timestamp, v53) < 250) {
|
||||
_custom_current_selected[a1] = newValue;
|
||||
_gdCustomUpdateSetting(a1, newValue);
|
||||
done = true;
|
||||
}
|
||||
} else {
|
||||
STRUCT_5189E4* ptr = &(_custom_settings[a1][newValue]);
|
||||
if (ptr->messageId != -1) {
|
||||
bool enabled = false;
|
||||
switch (a1) {
|
||||
case PARTY_MEMBER_CUSTOMIZATION_OPTION_AREA_ATTACK_MODE:
|
||||
enabled = partyMemberSupportsAreaAttackMode(gGameDialogSpeaker, ptr->value);
|
||||
break;
|
||||
case PARTY_MEMBER_CUSTOMIZATION_OPTION_RUN_AWAY_MODE:
|
||||
enabled = partyMemberSupportsRunAwayMode(gGameDialogSpeaker, ptr->value);
|
||||
break;
|
||||
case PARTY_MEMBER_CUSTOMIZATION_OPTION_BEST_WEAPON:
|
||||
enabled = partyMemberSupportsBestWeapon(gGameDialogSpeaker, ptr->value);
|
||||
break;
|
||||
case PARTY_MEMBER_CUSTOMIZATION_OPTION_DISTANCE:
|
||||
enabled = partyMemberSupportsDistance(gGameDialogSpeaker, ptr->value);
|
||||
break;
|
||||
case PARTY_MEMBER_CUSTOMIZATION_OPTION_ATTACK_WHO:
|
||||
enabled = partyMemberSupportsAttackWho(gGameDialogSpeaker, ptr->value);
|
||||
break;
|
||||
case PARTY_MEMBER_CUSTOMIZATION_OPTION_CHEM_USE:
|
||||
enabled = partyMemberSupportsChemUse(gGameDialogSpeaker, ptr->value);
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int timestamp = getTicks();
|
||||
if (newValue == value) {
|
||||
if (getTicksBetween(timestamp, v53) < 250) {
|
||||
_custom_current_selected[a1] = newValue;
|
||||
_gdCustomUpdateSetting(a1, newValue);
|
||||
done = true;
|
||||
}
|
||||
} else {
|
||||
STRUCT_5189E4* ptr = &(_custom_settings[a1][newValue]);
|
||||
if (ptr->messageId != -1) {
|
||||
bool enabled = false;
|
||||
switch (a1) {
|
||||
case PARTY_MEMBER_CUSTOMIZATION_OPTION_AREA_ATTACK_MODE:
|
||||
enabled = partyMemberSupportsAreaAttackMode(gGameDialogSpeaker, ptr->value);
|
||||
break;
|
||||
case PARTY_MEMBER_CUSTOMIZATION_OPTION_RUN_AWAY_MODE:
|
||||
enabled = partyMemberSupportsRunAwayMode(gGameDialogSpeaker, ptr->value);
|
||||
break;
|
||||
case PARTY_MEMBER_CUSTOMIZATION_OPTION_BEST_WEAPON:
|
||||
enabled = partyMemberSupportsBestWeapon(gGameDialogSpeaker, ptr->value);
|
||||
break;
|
||||
case PARTY_MEMBER_CUSTOMIZATION_OPTION_DISTANCE:
|
||||
enabled = partyMemberSupportsDistance(gGameDialogSpeaker, ptr->value);
|
||||
break;
|
||||
case PARTY_MEMBER_CUSTOMIZATION_OPTION_ATTACK_WHO:
|
||||
enabled = partyMemberSupportsAttackWho(gGameDialogSpeaker, ptr->value);
|
||||
break;
|
||||
case PARTY_MEMBER_CUSTOMIZATION_OPTION_CHEM_USE:
|
||||
enabled = partyMemberSupportsChemUse(gGameDialogSpeaker, ptr->value);
|
||||
break;
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
value = newValue;
|
||||
_gdCustomSelectRedraw(windowBuffer, backgroundFrmWidth, a1, newValue);
|
||||
windowRefresh(win);
|
||||
if (enabled) {
|
||||
value = newValue;
|
||||
_gdCustomSelectRedraw(windowBuffer, backgroundFrmWidth, a1, newValue);
|
||||
windowRefresh(win);
|
||||
}
|
||||
}
|
||||
}
|
||||
v53 = timestamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v53 = timestamp;
|
||||
}
|
||||
|
||||
renderPresent();
|
||||
|
|
|
@ -284,6 +284,10 @@ int gameMoviePlay(int movie, int flags)
|
|||
|
||||
windowDestroy(win);
|
||||
|
||||
// CE: Destroying a window redraws only content it was covering (centered
|
||||
// 640x480). This leads to everything outside this rect to remain black.
|
||||
windowRefreshAll(&_scr_size);
|
||||
|
||||
if ((flags & GAME_MOVIE_PAUSE_MUSIC) != 0) {
|
||||
backgroundSoundResume();
|
||||
}
|
||||
|
|
|
@ -307,6 +307,8 @@ bool heapBlockAllocate(Heap* heap, int* handleIndexPtr, int size, int a4)
|
|||
int blockSize;
|
||||
HeapHandle* handle;
|
||||
|
||||
size += 4 - size % 4;
|
||||
|
||||
if (heap == NULL || handleIndexPtr == NULL || size == 0) {
|
||||
goto err;
|
||||
}
|
||||
|
|
|
@ -1127,6 +1127,16 @@ static void opConditionalOperatorLessThanEquals(Program* program)
|
|||
assert(false && "Should be unreachable");
|
||||
}
|
||||
break;
|
||||
// Nevada folks tend to use "object <= 0" to test objects for nulls.
|
||||
case VALUE_TYPE_PTR:
|
||||
switch (value[0].opcode) {
|
||||
case VALUE_TYPE_INT:
|
||||
result = (intptr_t)value[1].pointerValue <= (intptr_t)value[0].integerValue;
|
||||
break;
|
||||
default:
|
||||
assert(false && "Should be unreachable");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(false && "Should be unreachable");
|
||||
}
|
||||
|
|
|
@ -545,7 +545,7 @@ static void opSetMapStart(Program* program)
|
|||
}
|
||||
|
||||
int tile = 200 * y + x;
|
||||
if (tileSetCenter(tile, TILE_SET_CENTER_FLAG_0x01 | TILE_SET_CENTER_FLAG_0x02) != 0) {
|
||||
if (tileSetCenter(tile, TILE_SET_CENTER_REFRESH_WINDOW | TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS) != 0) {
|
||||
scriptError("\nScript Error: %s: op_set_map_start: tile_set_center failed", program->name);
|
||||
return;
|
||||
}
|
||||
|
@ -584,7 +584,7 @@ static void opOverrideMapStart(Program* program)
|
|||
}
|
||||
}
|
||||
|
||||
tileSetCenter(tile, TILE_SET_CENTER_FLAG_0x01);
|
||||
tileSetCenter(tile, TILE_SET_CENTER_REFRESH_WINDOW);
|
||||
tileWindowRefresh();
|
||||
}
|
||||
|
||||
|
@ -866,7 +866,7 @@ static void opMoveTo(Program* program)
|
|||
Rect rect;
|
||||
newTile = objectSetLocation(object, tile, elevation, &rect);
|
||||
if (newTile != -1) {
|
||||
tileSetCenter(object->tile, TILE_SET_CENTER_FLAG_0x01);
|
||||
tileSetCenter(object->tile, TILE_SET_CENTER_REFRESH_WINDOW);
|
||||
}
|
||||
|
||||
if (tileLimitingEnabled) {
|
||||
|
@ -2061,7 +2061,7 @@ static void opMetarule3(Program* program)
|
|||
}
|
||||
break;
|
||||
case METARULE3_TILE_SET_CENTER:
|
||||
result.integerValue = tileSetCenter(param1.integerValue, TILE_SET_CENTER_FLAG_0x01);
|
||||
result.integerValue = tileSetCenter(param1.integerValue, TILE_SET_CENTER_REFRESH_WINDOW);
|
||||
break;
|
||||
case METARULE3_109:
|
||||
result.integerValue = aiGetChemUse(static_cast<Object*>(param1.pointerValue));
|
||||
|
@ -3158,7 +3158,7 @@ static void opFloatMessage(Program* program)
|
|||
color = _colorTable[31744];
|
||||
a5 = _colorTable[0];
|
||||
font = 103;
|
||||
tileSetCenter(gDude->tile, TILE_SET_CENTER_FLAG_0x01);
|
||||
tileSetCenter(gDude->tile, TILE_SET_CENTER_REFRESH_WINDOW);
|
||||
break;
|
||||
case FLOATING_MESSAGE_TYPE_NORMAL:
|
||||
case FLOATING_MESSAGE_TYPE_YELLOW:
|
||||
|
|
|
@ -1465,8 +1465,9 @@ static void opSetTextColor(Program* program)
|
|||
}
|
||||
|
||||
for (int arg = 0; arg < 3; arg++) {
|
||||
if (((value[arg].opcode & VALUE_TYPE_MASK) != VALUE_TYPE_FLOAT && (value[arg].opcode & VALUE_TYPE_MASK) != VALUE_TYPE_INT)
|
||||
|| value[arg].floatValue == 0.0) {
|
||||
if ((value[arg].opcode & VALUE_TYPE_MASK) != VALUE_TYPE_FLOAT
|
||||
&& (value[arg].opcode & VALUE_TYPE_MASK) == VALUE_TYPE_INT
|
||||
&& value[arg].integerValue != 0) {
|
||||
programFatalError("Invalid type given to settextcolor");
|
||||
}
|
||||
}
|
||||
|
@ -1492,8 +1493,9 @@ static void opSayOptionColor(Program* program)
|
|||
}
|
||||
|
||||
for (int arg = 0; arg < 3; arg++) {
|
||||
if (((value[arg].opcode & VALUE_TYPE_MASK) != VALUE_TYPE_FLOAT && (value[arg].opcode & VALUE_TYPE_MASK) != VALUE_TYPE_INT)
|
||||
|| value[arg].floatValue == 0.0) {
|
||||
if ((value[arg].opcode & VALUE_TYPE_MASK) != VALUE_TYPE_FLOAT
|
||||
&& (value[arg].opcode & VALUE_TYPE_MASK) == VALUE_TYPE_INT
|
||||
&& value[arg].integerValue != 0) {
|
||||
programFatalError("Invalid type given to sayoptioncolor");
|
||||
}
|
||||
}
|
||||
|
@ -1519,8 +1521,9 @@ static void opSayReplyColor(Program* program)
|
|||
}
|
||||
|
||||
for (int arg = 0; arg < 3; arg++) {
|
||||
if (((value[arg].opcode & VALUE_TYPE_MASK) != VALUE_TYPE_FLOAT && (value[arg].opcode & VALUE_TYPE_MASK) != VALUE_TYPE_INT)
|
||||
|| value[arg].floatValue == 0.0) {
|
||||
if ((value[arg].opcode & VALUE_TYPE_MASK) != VALUE_TYPE_FLOAT
|
||||
&& (value[arg].opcode & VALUE_TYPE_MASK) == VALUE_TYPE_INT
|
||||
&& value[arg].integerValue != 0) {
|
||||
programFatalError("Invalid type given to sayreplycolor");
|
||||
}
|
||||
}
|
||||
|
@ -1546,8 +1549,9 @@ static void opSetHighlightColor(Program* program)
|
|||
}
|
||||
|
||||
for (int arg = 0; arg < 3; arg++) {
|
||||
if (((value[arg].opcode & VALUE_TYPE_MASK) != VALUE_TYPE_FLOAT && (value[arg].opcode & VALUE_TYPE_MASK) != VALUE_TYPE_INT)
|
||||
|| value[arg].floatValue == 0.0) {
|
||||
if ((value[arg].opcode & VALUE_TYPE_MASK) != VALUE_TYPE_FLOAT
|
||||
&& (value[arg].opcode & VALUE_TYPE_MASK) == VALUE_TYPE_INT
|
||||
&& value[arg].integerValue != 0) {
|
||||
programFatalError("Invalid type given to sayreplycolor");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2434,13 +2434,13 @@ static int _SlotMap2Game(File* stream)
|
|||
{
|
||||
debugPrint("LOADSAVE: in SlotMap2Game\n");
|
||||
|
||||
int v2;
|
||||
if (fileReadInt32(stream, &v2) == 1) {
|
||||
int fileNameListLength;
|
||||
if (fileReadInt32(stream, &fileNameListLength) == -1) {
|
||||
debugPrint("LOADSAVE: returning 1\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (v2 == 0) {
|
||||
if (fileNameListLength == 0) {
|
||||
debugPrint("LOADSAVE: returning 2\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -2467,46 +2467,42 @@ static int _SlotMap2Game(File* stream)
|
|||
sprintf(_str0, "%s\\%s\\%s", _patches, "MAPS", "AUTOMAP.DB");
|
||||
compat_remove(_str0);
|
||||
|
||||
if (gPartyMemberDescriptionsLength > 1) {
|
||||
for (int index = 1; index < gPartyMemberDescriptionsLength; index += 1) {
|
||||
int pid = gPartyMemberPids[index];
|
||||
if (pid != -2) {
|
||||
char protoPath[COMPAT_MAX_PATH];
|
||||
if (_proto_list_str(pid, protoPath) == 0) {
|
||||
const char* basePath = pid >> 24 == OBJ_TYPE_CRITTER
|
||||
? PROTO_DIR_NAME "\\" CRITTERS_DIR_NAME
|
||||
: PROTO_DIR_NAME "\\" ITEMS_DIR_NAME;
|
||||
sprintf(_str0, "%s\\%s\\%s", _patches, basePath, protoPath);
|
||||
sprintf(_str1, "%s\\%s\\%s%.2d\\%s\\%s", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1, basePath, protoPath);
|
||||
for (int index = 1; index < gPartyMemberDescriptionsLength; index += 1) {
|
||||
int pid = gPartyMemberPids[index];
|
||||
if (pid != -2) {
|
||||
char protoPath[COMPAT_MAX_PATH];
|
||||
if (_proto_list_str(pid, protoPath) == 0) {
|
||||
const char* basePath = PID_TYPE(pid) == OBJ_TYPE_CRITTER
|
||||
? PROTO_DIR_NAME "\\" CRITTERS_DIR_NAME
|
||||
: PROTO_DIR_NAME "\\" ITEMS_DIR_NAME;
|
||||
sprintf(_str0, "%s\\%s\\%s", _patches, basePath, protoPath);
|
||||
sprintf(_str1, "%s\\%s\\%s%.2d\\%s\\%s", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1, basePath, protoPath);
|
||||
|
||||
if (_gzdecompress_file(_str1, _str0) == -1) {
|
||||
debugPrint("LOADSAVE: returning 6\n");
|
||||
return -1;
|
||||
}
|
||||
if (_gzdecompress_file(_str1, _str0) == -1) {
|
||||
debugPrint("LOADSAVE: returning 6\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (v2 > 0) {
|
||||
for (int index = 0; index < v2; index += 1) {
|
||||
char v11[64]; // TODO: Size is probably wrong.
|
||||
if (_mygets(v11, stream) == -1) {
|
||||
break;
|
||||
}
|
||||
for (int index = 0; index < fileNameListLength; index += 1) {
|
||||
char fileName[COMPAT_MAX_PATH];
|
||||
if (_mygets(fileName, stream) == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(_str0, "%s\\%s\\%s%.2d\\%s", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1, v11);
|
||||
sprintf(_str1, "%s\\%s\\%s", _patches, "MAPS", v11);
|
||||
sprintf(_str0, "%s\\%s\\%s%.2d\\%s", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1, fileName);
|
||||
sprintf(_str1, "%s\\%s\\%s", _patches, "MAPS", fileName);
|
||||
|
||||
if (_gzdecompress_file(_str0, _str1) == -1) {
|
||||
debugPrint("LOADSAVE: returning 7\n");
|
||||
return -1;
|
||||
}
|
||||
if (_gzdecompress_file(_str0, _str1) == -1) {
|
||||
debugPrint("LOADSAVE: returning 7\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const char* v9 = _strmfe(_str1, "AUTOMAP.DB", "SAV");
|
||||
sprintf(_str0, "%s\\%s\\%s%.2d\\%s", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1, v9);
|
||||
const char* automapFileName = _strmfe(_str1, "AUTOMAP.DB", "SAV");
|
||||
sprintf(_str0, "%s\\%s\\%s%.2d\\%s", _patches, "SAVEGAME", "SLOT", _slot_cursor + 1, automapFileName);
|
||||
sprintf(_str1, "%s\\%s\\%s", _patches, "MAPS", "AUTOMAP.DB");
|
||||
if (fileCopyDecompressed(_str0, _str1) == -1) {
|
||||
debugPrint("LOADSAVE: returning 8\n");
|
||||
|
|
|
@ -707,7 +707,7 @@ int mapSetEnteringLocation(int elevation, int tile_num, int orientation)
|
|||
void mapNewMap()
|
||||
{
|
||||
mapSetElevation(0);
|
||||
tileSetCenter(20100, TILE_SET_CENTER_FLAG_0x02);
|
||||
tileSetCenter(20100, TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS);
|
||||
memset(&gMapTransition, 0, sizeof(gMapTransition));
|
||||
gMapHeader.enteringElevation = 0;
|
||||
gMapHeader.enteringRotation = 0;
|
||||
|
@ -894,7 +894,7 @@ static int mapLoad(File* stream)
|
|||
}
|
||||
|
||||
error = "Error setting tile center";
|
||||
if (tileSetCenter(gEnteringTile, TILE_SET_CENTER_FLAG_0x02) != 0) {
|
||||
if (tileSetCenter(gEnteringTile, TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS) != 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -1240,7 +1240,7 @@ int mapHandleTransition()
|
|||
objectSetRotation(gDude, gMapTransition.rotation, NULL);
|
||||
}
|
||||
|
||||
if (tileSetCenter(gDude->tile, TILE_SET_CENTER_FLAG_0x01) == -1) {
|
||||
if (tileSetCenter(gDude->tile, TILE_SET_CENTER_REFRESH_WINDOW) == -1) {
|
||||
debugPrint("\nError: map: attempt to center out-of-bounds!");
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ static void* memoryBlockMallocImpl(size_t size)
|
|||
|
||||
if (size != 0) {
|
||||
size += sizeof(MemoryBlockHeader) + sizeof(MemoryBlockFooter);
|
||||
size += sizeof(int) - size % sizeof(int);
|
||||
|
||||
unsigned char* block = (unsigned char*)malloc(size);
|
||||
if (block != NULL) {
|
||||
|
@ -123,6 +124,7 @@ static void* memoryBlockReallocImpl(void* ptr, size_t size)
|
|||
|
||||
if (size != 0) {
|
||||
size += sizeof(MemoryBlockHeader) + sizeof(MemoryBlockFooter);
|
||||
size += sizeof(int) - size % sizeof(int);
|
||||
}
|
||||
|
||||
unsigned char* newBlock = (unsigned char*)realloc(block, size);
|
||||
|
|
|
@ -185,7 +185,7 @@ static int _obj_last_roof_y = -1;
|
|||
static int _obj_last_elev = -1;
|
||||
|
||||
// 0x51977C
|
||||
static int _obj_last_is_empty = 1;
|
||||
static bool _obj_last_is_empty = true;
|
||||
|
||||
// 0x519780
|
||||
unsigned char* _wallBlendTable = NULL;
|
||||
|
@ -1492,21 +1492,24 @@ int objectSetLocation(Object* obj, int tile, int elevation, Rect* rect)
|
|||
// NOTE: Uninline.
|
||||
obj_set_seen(tile);
|
||||
|
||||
int v14 = tile % 200 / 2;
|
||||
int v15 = tile / 200 / 2;
|
||||
if (v14 != _obj_last_roof_x || v15 != _obj_last_roof_y || elevation != _obj_last_elev) {
|
||||
int v16 = _square[elevation]->field_0[v14 + 100 * v15];
|
||||
int v31 = buildFid(OBJ_TYPE_TILE, (v16 >> 16) & 0xFFF, 0, 0, 0);
|
||||
int v32 = _square[elevation]->field_0[_obj_last_roof_x + 100 * _obj_last_roof_y];
|
||||
int v34 = buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0) == v31;
|
||||
int roofX = tile % 200 / 2;
|
||||
int roofY = tile / 200 / 2;
|
||||
if (roofX != _obj_last_roof_x || roofY != _obj_last_roof_y || elevation != _obj_last_elev) {
|
||||
int currentSquare = _square[elevation]->field_0[roofX + 100 * roofY];
|
||||
int currentSquareFid = buildFid(OBJ_TYPE_TILE, (currentSquare >> 16) & 0xFFF, 0, 0, 0);
|
||||
// CE: Add additional checks for -1 to prevent array lookup at index -101.
|
||||
int previousSquare = _obj_last_roof_x != -1 && _obj_last_roof_y != -1
|
||||
? _square[elevation]->field_0[_obj_last_roof_x + 100 * _obj_last_roof_y]
|
||||
: 0;
|
||||
bool isEmpty = buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0) == currentSquareFid;
|
||||
|
||||
if (v34 != _obj_last_is_empty || (((v16 >> 16) & 0xF000) >> 12) != (((v32 >> 16) & 0xF000) >> 12)) {
|
||||
if (_obj_last_is_empty == 0) {
|
||||
if (isEmpty != _obj_last_is_empty || (((currentSquare >> 16) & 0xF000) >> 12) != (((previousSquare >> 16) & 0xF000) >> 12)) {
|
||||
if (!_obj_last_is_empty) {
|
||||
_tile_fill_roof(_obj_last_roof_x, _obj_last_roof_y, elevation, 1);
|
||||
}
|
||||
|
||||
if (v34 == 0) {
|
||||
_tile_fill_roof(v14, v15, elevation, 0);
|
||||
if (!isEmpty) {
|
||||
_tile_fill_roof(roofX, roofY, elevation, 0);
|
||||
}
|
||||
|
||||
if (rect != NULL) {
|
||||
|
@ -1514,10 +1517,10 @@ int objectSetLocation(Object* obj, int tile, int elevation, Rect* rect)
|
|||
}
|
||||
}
|
||||
|
||||
_obj_last_roof_x = v14;
|
||||
_obj_last_roof_y = v15;
|
||||
_obj_last_roof_x = roofX;
|
||||
_obj_last_roof_y = roofY;
|
||||
_obj_last_elev = elevation;
|
||||
_obj_last_is_empty = v34;
|
||||
_obj_last_is_empty = isEmpty;
|
||||
}
|
||||
|
||||
if (rect != NULL) {
|
||||
|
@ -1530,7 +1533,7 @@ int objectSetLocation(Object* obj, int tile, int elevation, Rect* rect)
|
|||
|
||||
if (elevation != oldElevation) {
|
||||
mapSetElevation(elevation);
|
||||
tileSetCenter(tile, TILE_SET_CENTER_FLAG_0x01 | TILE_SET_CENTER_FLAG_0x02);
|
||||
tileSetCenter(tile, TILE_SET_CENTER_REFRESH_WINDOW | TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS);
|
||||
if (isInCombat()) {
|
||||
_game_user_wants_to_quit = 1;
|
||||
}
|
||||
|
@ -2183,7 +2186,7 @@ void _obj_remove_all()
|
|||
|
||||
_obj_last_roof_y = -1;
|
||||
_obj_last_elev = -1;
|
||||
_obj_last_is_empty = 1;
|
||||
_obj_last_is_empty = true;
|
||||
_obj_last_roof_x = -1;
|
||||
}
|
||||
|
||||
|
@ -3335,7 +3338,7 @@ static int _obj_offset_table_init()
|
|||
}
|
||||
}
|
||||
|
||||
if (tileSetCenter(gCenterTile + 1, 2) == -1) {
|
||||
if (tileSetCenter(gCenterTile + 1, TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS) == -1) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
@ -3753,7 +3756,7 @@ int _obj_load_dude(File* stream)
|
|||
return -1;
|
||||
}
|
||||
|
||||
tileSetCenter(tile, TILE_SET_CENTER_FLAG_0x01 | TILE_SET_CENTER_FLAG_0x02);
|
||||
tileSetCenter(tile, TILE_SET_CENTER_REFRESH_WINDOW | TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -107,7 +107,6 @@ typedef enum PreferencesWindowFrm {
|
|||
PREFERENCES_WINDOW_FRM_COUNT,
|
||||
} PreferencesWindowFrm;
|
||||
|
||||
#pragma pack(2)
|
||||
typedef struct PreferenceDescription {
|
||||
// The number of options.
|
||||
short valuesCount;
|
||||
|
@ -129,7 +128,6 @@ typedef struct PreferenceDescription {
|
|||
double maxValue;
|
||||
int* valuePtr;
|
||||
} PreferenceDescription;
|
||||
#pragma pack()
|
||||
|
||||
static int optionsWindowInit();
|
||||
static int optionsWindowFree();
|
||||
|
@ -496,7 +494,7 @@ int showOptionsWithInitialKeyCode(int initialKeyCode)
|
|||
case KEY_UPPERCASE_S:
|
||||
case KEY_LOWERCASE_S:
|
||||
case 500:
|
||||
if (lsgSaveGame(1) != 1) {
|
||||
if (lsgSaveGame(LOAD_SAVE_MODE_NORMAL) == 1) {
|
||||
rc = 1;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -239,7 +239,7 @@ int _proto_list_str(int pid, char* proto_path)
|
|||
*pch = '\0';
|
||||
}
|
||||
|
||||
pch = strchr(string, '\n');
|
||||
pch = strpbrk(string, "\r\n");
|
||||
if (pch != NULL) {
|
||||
*pch = '\0';
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <random>
|
||||
|
||||
#include "debug.h"
|
||||
#include "platform_compat.h"
|
||||
#include "scripts.h"
|
||||
|
@ -37,7 +39,7 @@ static int _idum;
|
|||
void randomInit()
|
||||
{
|
||||
unsigned int randomSeed = randomGetSeed();
|
||||
srand(randomSeed);
|
||||
std::srand(randomSeed);
|
||||
|
||||
int pseudorandomSeed = randomInt32();
|
||||
randomSeedPrerandomInternal(pseudorandomSeed);
|
||||
|
@ -183,10 +185,7 @@ void randomSeedPrerandom(int seed)
|
|||
// 0x4A31C4
|
||||
static int randomInt32()
|
||||
{
|
||||
int high = rand() << 16;
|
||||
int low = rand();
|
||||
|
||||
return (high + low) & INT_MAX;
|
||||
return std::rand();
|
||||
}
|
||||
|
||||
// 0x4A31E0
|
||||
|
|
|
@ -2354,6 +2354,11 @@ int _scr_remove_all()
|
|||
} else {
|
||||
next = scriptListExtent->next;
|
||||
scriptRemove(script->sid);
|
||||
|
||||
// CE: Current extent is freed in |scriptRemove|. Break
|
||||
// to prevent next iteration which needs to dereference
|
||||
// extent to obtain it's length.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace fallout {
|
|||
#define SFALL_CONFIG_GAME_DIALOG_FIX_KEY "DialogueFix"
|
||||
#define SFALL_CONFIG_TWEAKS_FILE_KEY "TweaksFile"
|
||||
#define SFALL_CONFIG_GAME_DIALOG_GENDER_WORDS_KEY "DialogGenderWords"
|
||||
#define SFALL_CONFIG_TOWN_MAP_HOTKEYS_FIX "TownMapHotkeysFix"
|
||||
#define SFALL_CONFIG_TOWN_MAP_HOTKEYS_FIX_KEY "TownMapHotkeysFix"
|
||||
|
||||
#define SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_MULTIPLIER 1
|
||||
#define SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_DIVISOR 3
|
||||
|
|
62
src/tile.cc
62
src/tile.cc
|
@ -207,7 +207,7 @@ static Rect gTileWindowRect;
|
|||
static unsigned char _tile_grid[32 * 16];
|
||||
|
||||
// 0x66BDE4
|
||||
static int _square_rect;
|
||||
static int _square_y;
|
||||
|
||||
// 0x66BDE8
|
||||
static int _square_x;
|
||||
|
@ -433,7 +433,7 @@ int tileInit(TileData** a1, int squareGridWidth, int squareGridHeight, int hexGr
|
|||
gTileWindowWidth = ORIGINAL_ISO_WINDOW_WIDTH;
|
||||
gTileWindowHeight = ORIGINAL_ISO_WINDOW_HEIGHT;
|
||||
|
||||
tileSetCenter(hexGridWidth * (hexGridHeight / 2) + hexGridWidth / 2, 2);
|
||||
tileSetCenter(hexGridWidth * (hexGridHeight / 2) + hexGridWidth / 2, TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS);
|
||||
tileSetBorder(windowWidth, windowHeight, hexGridWidth, hexGridHeight);
|
||||
|
||||
// Restore actual window size and set center one more time to calculate
|
||||
|
@ -442,7 +442,7 @@ int tileInit(TileData** a1, int squareGridWidth, int squareGridHeight, int hexGr
|
|||
gTileWindowWidth = windowWidth;
|
||||
gTileWindowHeight = windowHeight;
|
||||
|
||||
tileSetCenter(hexGridWidth * (hexGridHeight / 2) + hexGridWidth / 2, 2);
|
||||
tileSetCenter(hexGridWidth * (hexGridHeight / 2) + hexGridWidth / 2, TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS);
|
||||
|
||||
if (compat_stricmp(settings.system.executable.c_str(), "mapper") == 0) {
|
||||
gTileWindowRefreshElevationProc = tileRefreshMapper;
|
||||
|
@ -533,29 +533,31 @@ int tileSetCenter(int tile, int flags)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if ((gTileScrollLimitingEnabled & ((flags & TILE_SET_CENTER_FLAG_0x02) == 0)) != 0) {
|
||||
int tileScreenX;
|
||||
int tileScreenY;
|
||||
tileToScreenXY(tile, &tileScreenX, &tileScreenY, gElevation);
|
||||
if ((flags & TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS) == 0) {
|
||||
if (gTileScrollLimitingEnabled) {
|
||||
int tileScreenX;
|
||||
int tileScreenY;
|
||||
tileToScreenXY(tile, &tileScreenX, &tileScreenY, gElevation);
|
||||
|
||||
int dudeScreenX;
|
||||
int dudeScreenY;
|
||||
tileToScreenXY(gDude->tile, &dudeScreenX, &dudeScreenY, gElevation);
|
||||
int dudeScreenX;
|
||||
int dudeScreenY;
|
||||
tileToScreenXY(gDude->tile, &dudeScreenX, &dudeScreenY, gElevation);
|
||||
|
||||
int dx = abs(dudeScreenX - tileScreenX);
|
||||
int dy = abs(dudeScreenY - tileScreenY);
|
||||
int dx = abs(dudeScreenX - tileScreenX);
|
||||
int dy = abs(dudeScreenY - tileScreenY);
|
||||
|
||||
if (dx > abs(dudeScreenX - _tile_offx)
|
||||
|| dy > abs(dudeScreenY - _tile_offy)) {
|
||||
if (dx >= 480 || dy >= 400) {
|
||||
return -1;
|
||||
if (dx > abs(dudeScreenX - _tile_offx)
|
||||
|| dy > abs(dudeScreenY - _tile_offy)) {
|
||||
if (dx >= 480 || dy >= 400) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((gTileScrollBlockingEnabled & ((flags & TILE_SET_CENTER_FLAG_0x02) == 0)) != 0) {
|
||||
if (_obj_scroll_blocking_at(tile, gElevation) == 0) {
|
||||
return -1;
|
||||
if (gTileScrollBlockingEnabled) {
|
||||
if (_obj_scroll_blocking_at(tile, gElevation) == 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -579,7 +581,7 @@ int tileSetCenter(int tile, int flags)
|
|||
}
|
||||
|
||||
_square_x = _tile_x / 2;
|
||||
_square_rect = _tile_y / 2;
|
||||
_square_y = _tile_y / 2;
|
||||
_square_offx = _tile_offx - 16;
|
||||
_square_offy = _tile_offy - 2;
|
||||
|
||||
|
@ -590,7 +592,7 @@ int tileSetCenter(int tile, int flags)
|
|||
|
||||
gCenterTile = tile;
|
||||
|
||||
if (flags & TILE_SET_CENTER_FLAG_0x01) {
|
||||
if ((flags & TILE_SET_CENTER_REFRESH_WINDOW) != 0) {
|
||||
// NOTE: Uninline.
|
||||
tileWindowRefresh();
|
||||
}
|
||||
|
@ -1080,7 +1082,7 @@ int squareTileToScreenXY(int squareTile, int* coordX, int* coordY, int elevation
|
|||
*coordX += 48 * v8;
|
||||
*coordY -= 12 * v8;
|
||||
|
||||
v9 = v6 - _square_rect;
|
||||
v9 = v6 - _square_y;
|
||||
*coordX += 32 * v9;
|
||||
*coordY += 24 * v9;
|
||||
|
||||
|
@ -1111,7 +1113,7 @@ int squareTileToRoofScreenXY(int squareTile, int* screenX, int* screenY, int ele
|
|||
*screenX += 48 * v8;
|
||||
*screenY -= 12 * v8;
|
||||
|
||||
v9 = v6 - _square_rect;
|
||||
v9 = v6 - _square_y;
|
||||
*screenX += 32 * v9;
|
||||
v10 = 24 * v9 + *screenY;
|
||||
*screenY = v10;
|
||||
|
@ -1149,12 +1151,10 @@ void squareTileScreenToCoord(int screenX, int screenY, int elevation, int* coord
|
|||
*coordX = v6 >= 0 ? (v6 / 192) : ((v6 + 1) / 192 - 1);
|
||||
|
||||
v8 = 4 * v5 + v4;
|
||||
*coordY = v8 >= 0
|
||||
? ((v8 - ((v8 >> 31) << 7)) >> 7)
|
||||
: ((((v8 + 1) - (((v8 + 1) >> 31) << 7)) >> 7) - 1);
|
||||
*coordY = v8 >= 0 ? (v8 / 128) : ((v8 + 1) / 128 - 1);
|
||||
|
||||
*coordX += _square_x;
|
||||
*coordY += _square_rect;
|
||||
*coordY += _square_y;
|
||||
|
||||
*coordX = gSquareGridWidth - 1 - *coordX;
|
||||
}
|
||||
|
@ -1174,12 +1174,10 @@ void squareTileScreenToCoordRoof(int screenX, int screenY, int elevation, int* c
|
|||
*coordX = (v6 >= 0) ? (v6 / 192) : ((v6 + 1) / 192 - 1);
|
||||
|
||||
v8 = 4 * v5 + v4;
|
||||
*coordY = (v8 >= 0)
|
||||
? ((v8 - ((v8 >> 31) << 7)) >> 7)
|
||||
: ((((v8 + 1) - (((v8 + 1) >> 31) << 7)) >> 7) - 1);
|
||||
*coordY = v8 >= 0 ? (v8 / 128) : ((v8 + 1) / 128 - 1);
|
||||
|
||||
*coordX += _square_x;
|
||||
*coordY += _square_rect;
|
||||
*coordY += _square_y;
|
||||
|
||||
*coordX = gSquareGridWidth - 1 - *coordX;
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
namespace fallout {
|
||||
|
||||
#define TILE_SET_CENTER_FLAG_0x01 0x01
|
||||
#define TILE_SET_CENTER_FLAG_0x02 0x02
|
||||
#define TILE_SET_CENTER_REFRESH_WINDOW 0x01
|
||||
#define TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS 0x02
|
||||
|
||||
typedef void(TileWindowRefreshProc)(Rect* rect);
|
||||
typedef void(TileWindowRefreshElevationProc)(Rect* rect, int elevation);
|
||||
|
|
|
@ -887,7 +887,7 @@ int _selectWindow(const char* windowName)
|
|||
}
|
||||
}
|
||||
|
||||
if (!_selectWindowID(index)) {
|
||||
if (_selectWindowID(index)) {
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@ -1725,7 +1725,7 @@ bool _windowAddButtonGfx(const char* buttonName, char* pressedFileName, char* no
|
|||
// 0x4BA11C
|
||||
bool _windowAddButtonProc(const char* buttonName, Program* program, int mouseEnterProc, int mouseExitProc, int mouseDownProc, int mouseUpProc)
|
||||
{
|
||||
if (gCurrentManagedWindowIndex != -1) {
|
||||
if (gCurrentManagedWindowIndex == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -847,7 +847,16 @@ int wmWorldMap_init()
|
|||
|
||||
// SFALL
|
||||
gTownMapHotkeysFix = true;
|
||||
configGetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_TOWN_MAP_HOTKEYS_FIX, &gTownMapHotkeysFix);
|
||||
configGetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_TOWN_MAP_HOTKEYS_FIX_KEY, &gTownMapHotkeysFix);
|
||||
|
||||
// CE: City size fids should be initialized during startup. They are used
|
||||
// during |wmTeleportToArea| to calculate worldmap position when jumping
|
||||
// from Temple to Arroyo - before giving a chance to |wmInterfaceInit| to
|
||||
// initialize it.
|
||||
for (int citySize = 0; citySize < CITY_SIZE_COUNT; citySize++) {
|
||||
CitySizeDescription* citySizeDescription = &(wmSphereData[citySize]);
|
||||
citySizeDescription->fid = buildFid(OBJ_TYPE_INTERFACE, 336 + citySize, 0, 0, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1397,7 +1406,17 @@ static int wmParseEncounterTableIndex(EncounterEntry* entry, char* string)
|
|||
|
||||
if (strstr(string, "special")) {
|
||||
entry->flags |= ENCOUNTER_ENTRY_SPECIAL;
|
||||
string += 8;
|
||||
|
||||
// CE: Original code unconditionally consumes 8 characters, which is
|
||||
// right when "special" is followed by conditions (separated with
|
||||
// comma). However when "special" is the last keyword (which I guess
|
||||
// is wrong, but present in worldmap.txt), consuming 8 characters
|
||||
// sets pointer past NULL terminator, which can lead to many bad
|
||||
// things (UB).
|
||||
string += 7;
|
||||
if (*string != '\0') {
|
||||
string++;
|
||||
}
|
||||
}
|
||||
|
||||
if (string != NULL) {
|
||||
|
@ -4459,11 +4478,7 @@ static int wmInterfaceInit()
|
|||
|
||||
for (int citySize = 0; citySize < CITY_SIZE_COUNT; citySize++) {
|
||||
CitySizeDescription* citySizeDescription = &(wmSphereData[citySize]);
|
||||
|
||||
fid = buildFid(OBJ_TYPE_INTERFACE, 336 + citySize, 0, 0, 0);
|
||||
citySizeDescription->fid = fid;
|
||||
|
||||
if (!citySizeDescription->frmImage.lock(fid)) {
|
||||
if (!citySizeDescription->frmImage.lock(citySizeDescription->fid)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -6530,9 +6545,21 @@ int wmTeleportToArea(int areaIdx)
|
|||
// locations.
|
||||
// CE: See `wmWorldMapFunc` for explanation.
|
||||
CitySizeDescription* citySizeDescription = &(wmSphereData[city->size]);
|
||||
|
||||
// CE: This function might be called outside |wmWorldmapFunc|, so it's
|
||||
// image might not be locked.
|
||||
bool wasLocked = citySizeDescription->frmImage.isLocked();
|
||||
if (!wasLocked) {
|
||||
citySizeDescription->frmImage.lock(citySizeDescription->fid);
|
||||
}
|
||||
|
||||
wmGenData.worldPosX = city->x + citySizeDescription->frmImage.getWidth() / 2 - WM_VIEW_X;
|
||||
wmGenData.worldPosY = city->y + citySizeDescription->frmImage.getHeight() / 2 - WM_VIEW_Y;
|
||||
|
||||
if (!wasLocked) {
|
||||
citySizeDescription->frmImage.unlock();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue