mirror of
https://github.com/fallout2-ce/fallout2-ce.git
synced 2026-07-27 16:47:11 -07:00
Compare commits
2
Commits
continious
...
hook-steal
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b649c416c | ||
|
|
1a50bebff1 |
@@ -98,7 +98,7 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
|
|||||||
| KeyPress | `HOOK_KEYPRESS` | âś… | Third hook arg is currently `0`; CE doesn't use VK codes. |
|
| KeyPress | `HOOK_KEYPRESS` | âś… | Third hook arg is currently `0`; CE doesn't use VK codes. |
|
||||||
| MouseClick | `HOOK_MOUSECLICK` | âś… | - |
|
| MouseClick | `HOOK_MOUSECLICK` | âś… | - |
|
||||||
| UseSkill | `HOOK_USESKILL` | đźš« | - |
|
| UseSkill | `HOOK_USESKILL` | đźš« | - |
|
||||||
| Steal | `HOOK_STEAL` | đźš« | Et tu |
|
| Steal | `HOOK_STEAL` | âś… | - |
|
||||||
| WithinPerception | `HOOK_WITHINPERCEPTION` | âś… | - |
|
| WithinPerception | `HOOK_WITHINPERCEPTION` | âś… | - |
|
||||||
| InventoryMove | `HOOK_INVENTORYMOVE` | âś… | - |
|
| InventoryMove | `HOOK_INVENTORYMOVE` | âś… | - |
|
||||||
| InvenWield | `HOOK_INVENWIELD` | âś… | - |
|
| InvenWield | `HOOK_INVENWIELD` | âś… | - |
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ auto_quick_save=3
|
|||||||
display_bonus_damage=1
|
display_bonus_damage=1
|
||||||
;Set to 1 to get notification of karma changes in the notification window
|
;Set to 1 to get notification of karma changes in the notification window
|
||||||
display_karma_changes=0
|
display_karma_changes=0
|
||||||
|
;Set to 1 to use the hi-res dialog border/background at resolutions above 640x480. Requires art\intrface\HR_ALLTLK.FRM (for example from f2_res.dat)
|
||||||
|
enable_dialog_border=1
|
||||||
;Set to one to hide areas outside map bounds when using higher than 640x480 resolution, and to zero to disable
|
;Set to one to hide areas outside map bounds when using higher than 640x480 resolution, and to zero to disable
|
||||||
enable_high_resolution_stencil=1
|
enable_high_resolution_stencil=1
|
||||||
;Set to 1 to extend the action points bar to show up to 16 AP instead of 10 (requires iface_apbar_e.frm)
|
;Set to 1 to extend the action points bar to show up to 16 AP instead of 10 (requires iface_apbar_e.frm)
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
#include "sfall.h"
|
||||||
|
#include "dik.h"
|
||||||
|
#include "lib.arrays.h"
|
||||||
|
|
||||||
|
variable steal_mode := 0;
|
||||||
|
|
||||||
|
procedure steal_mode_name(variable mode) begin
|
||||||
|
if (mode == 1) then return "force_success";
|
||||||
|
if (mode == 2) then return "caught_fail";
|
||||||
|
if (mode == 3) then return "silent_fail";
|
||||||
|
if (mode == 4) then return "xp_override";
|
||||||
|
return "vanilla";
|
||||||
|
end
|
||||||
|
|
||||||
|
procedure steal_handler begin
|
||||||
|
variable
|
||||||
|
args := get_sfall_args,
|
||||||
|
thief := args[0],
|
||||||
|
target := args[1],
|
||||||
|
item := args[2],
|
||||||
|
is_planting := args[3],
|
||||||
|
quantity := args[4],
|
||||||
|
thief_name := "<null>",
|
||||||
|
target_name := "<null>",
|
||||||
|
item_name := "<null>";
|
||||||
|
|
||||||
|
if (thief) then thief_name := obj_name(thief);
|
||||||
|
if (target) then target_name := obj_name(target);
|
||||||
|
if (item) then item_name := obj_name(item);
|
||||||
|
|
||||||
|
display_msg(string_format6("steal mode=%s thief=%s target=%s item=%s planting=%d qty=%d",
|
||||||
|
steal_mode_name(steal_mode),
|
||||||
|
thief_name,
|
||||||
|
target_name,
|
||||||
|
item_name,
|
||||||
|
is_planting,
|
||||||
|
quantity));
|
||||||
|
display_msg(string_format1("steal args=%s", debug_array_str(args)));
|
||||||
|
|
||||||
|
if (thief != dude_obj) then return;
|
||||||
|
|
||||||
|
if (steal_mode == 1) then begin
|
||||||
|
display_msg("steal forcing success");
|
||||||
|
display_msg(sprintf(mstr_skill(571 + is_planting * 2), item_name));
|
||||||
|
set_sfall_return(1);
|
||||||
|
end else if (steal_mode == 2) then begin
|
||||||
|
display_msg("steal forcing caught failure");
|
||||||
|
display_msg(sprintf(mstr_skill(570 + is_planting * 2), item_name));
|
||||||
|
set_sfall_return(0);
|
||||||
|
end else if (steal_mode == 3) then begin
|
||||||
|
display_msg("steal forcing silent failure");
|
||||||
|
set_sfall_return(2);
|
||||||
|
end else if (steal_mode == 4) then begin
|
||||||
|
display_msg("steal forcing success with xp override 77");
|
||||||
|
display_msg(sprintf(mstr_skill(571 + is_planting * 2), item_name));
|
||||||
|
set_sfall_return(1);
|
||||||
|
set_sfall_return(77);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
procedure keypress_handler begin
|
||||||
|
variable
|
||||||
|
pressed := get_sfall_arg_at(0),
|
||||||
|
key := get_sfall_arg_at(1);
|
||||||
|
|
||||||
|
if (not pressed) then return;
|
||||||
|
if (key != DIK_X) then return;
|
||||||
|
|
||||||
|
steal_mode += 1;
|
||||||
|
if (steal_mode > 4) then steal_mode := 0;
|
||||||
|
|
||||||
|
display_msg(string_format1("steal mode -> %s", steal_mode_name(steal_mode)));
|
||||||
|
end
|
||||||
|
|
||||||
|
procedure start begin
|
||||||
|
if (not game_loaded) then return;
|
||||||
|
|
||||||
|
display_msg("steal manual test ready: press X to cycle vanilla / force_success / caught_fail / silent_fail / xp_override");
|
||||||
|
display_msg("open a steal screen and move an item in either direction; mode 4 should award 77 XP for a successful action");
|
||||||
|
|
||||||
|
register_hook_proc(HOOK_KEYPRESS, keypress_handler);
|
||||||
|
register_hook_proc(HOOK_STEAL, steal_handler);
|
||||||
|
end
|
||||||
+85
-29
@@ -279,6 +279,8 @@ static int gGameDialogBackgroundWindow = -1;
|
|||||||
// 0x518744
|
// 0x518744
|
||||||
static int gGameDialogWindow = -1;
|
static int gGameDialogWindow = -1;
|
||||||
|
|
||||||
|
static bool gameDialogUseHrArt = false;
|
||||||
|
|
||||||
// 0x518748
|
// 0x518748
|
||||||
static Rect _backgrndRects[8] = {
|
static Rect _backgrndRects[8] = {
|
||||||
{ 126, 14, 152, 40 },
|
{ 126, 14, 152, 40 },
|
||||||
@@ -291,6 +293,37 @@ static Rect _backgrndRects[8] = {
|
|||||||
{ 504, 40, 514, 188 },
|
{ 504, 40, 514, 188 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool gameDialogShouldUseHrArt()
|
||||||
|
{
|
||||||
|
return settings.ui.enable_dialog_border
|
||||||
|
&& (screenGetWidth() > GAME_DIALOG_WINDOW_WIDTH || screenGetHeight() > GAME_DIALOG_WINDOW_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gameDialogHrArtYOffset()
|
||||||
|
{
|
||||||
|
return gameDialogUseHrArt ? 5 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Rect gameDialogGetBackgroundRect(int index)
|
||||||
|
{
|
||||||
|
Rect rect = _backgrndRects[index];
|
||||||
|
int yOffset = gameDialogHrArtYOffset();
|
||||||
|
rect.top += yOffset;
|
||||||
|
rect.bottom += yOffset;
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gameDialogGetBackgroundWindowY()
|
||||||
|
{
|
||||||
|
// center onplay area if large enough, else center on screen
|
||||||
|
int visibleHeight = screenGetVisibleHeight();
|
||||||
|
if (visibleHeight >= GAME_DIALOG_WINDOW_HEIGHT) {
|
||||||
|
return (visibleHeight - GAME_DIALOG_WINDOW_HEIGHT) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (screenGetHeight() - GAME_DIALOG_WINDOW_HEIGHT) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
// 0x5187C8
|
// 0x5187C8
|
||||||
static bool _talk_need_to_center = true;
|
static bool _talk_need_to_center = true;
|
||||||
|
|
||||||
@@ -2494,31 +2527,35 @@ int _gdCreateHeadWindow()
|
|||||||
int windowWidth = GAME_DIALOG_WINDOW_WIDTH;
|
int windowWidth = GAME_DIALOG_WINDOW_WIDTH;
|
||||||
|
|
||||||
// NOTE: Uninline.
|
// NOTE: Uninline.
|
||||||
talk_to_create_background_window();
|
if (talk_to_create_background_window() == -1 || gameDialogWindowRenderBackground() == -1) {
|
||||||
gameDialogWindowRenderBackground();
|
_gdDestroyHeadWindow();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned char* buf = windowGetBuffer(gGameDialogBackgroundWindow);
|
ConstBuffer2D backgroundBuf = windowGetBuffer2D(gGameDialogBackgroundWindow);
|
||||||
|
|
||||||
for (int index = 0; index < 8; index++) {
|
for (int index = 0; index < 8; index++) {
|
||||||
soundContinueAll();
|
soundContinueAll();
|
||||||
|
|
||||||
Rect* rect = &(_backgrndRects[index]);
|
Rect rect = gameDialogGetBackgroundRect(index);
|
||||||
int width = rect->right - rect->left;
|
int width = rect.right - rect.left;
|
||||||
int height = rect->bottom - rect->top;
|
int height = rect.bottom - rect.top;
|
||||||
_backgrndBufs[index] = (unsigned char*)internal_malloc(width * height);
|
_backgrndBufs[index] = (unsigned char*)internal_malloc(width * height);
|
||||||
if (_backgrndBufs[index] == nullptr) {
|
if (_backgrndBufs[index] == nullptr) {
|
||||||
|
_gdDestroyHeadWindow();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* src = buf;
|
Buffer2D savedBackgroundBuf { _backgrndBufs[index], width, height };
|
||||||
src += windowWidth * rect->top + rect->left;
|
blitBuffer2D(backgroundBuf, rect.left, rect.top, width, height, savedBackgroundBuf);
|
||||||
|
|
||||||
blitBufferToBuffer(src, width, height, windowWidth, _backgrndBufs[index], width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_gdialog_window_create();
|
if (_gdialog_window_create() == -1) {
|
||||||
|
_gdDestroyHeadWindow();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
gGameDialogDisplayBuffer = windowGetBuffer(gGameDialogBackgroundWindow) + windowWidth * 14 + 126;
|
gGameDialogDisplayBuffer = windowGetBuffer(gGameDialogBackgroundWindow) + windowWidth * (14 + gameDialogHrArtYOffset()) + 126;
|
||||||
|
|
||||||
// TODO: jnz at 0x447275 without cmp or test, not sure what that means.
|
// TODO: jnz at 0x447275 without cmp or test, not sure what that means.
|
||||||
if (false) {
|
if (false) {
|
||||||
@@ -2547,10 +2584,12 @@ void _gdDestroyHeadWindow()
|
|||||||
gGameDialogBackgroundWindow = -1;
|
gGameDialogBackgroundWindow = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gameDialogUseHrArt = false;
|
||||||
gExpandedBarterEnabled = false;
|
gExpandedBarterEnabled = false;
|
||||||
|
|
||||||
for (int index = 0; index < 8; index++) {
|
for (int index = 0; index < 8; index++) {
|
||||||
internal_free(_backgrndBufs[index]);
|
internal_free(_backgrndBufs[index]);
|
||||||
|
_backgrndBufs[index] = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4551,13 +4590,14 @@ static const char* expandedBarterFrmName()
|
|||||||
// 0x44AAD8
|
// 0x44AAD8
|
||||||
static int talk_to_create_background_window()
|
static int talk_to_create_background_window()
|
||||||
{
|
{
|
||||||
|
gameDialogUseHrArt = false;
|
||||||
|
|
||||||
gExpandedBarterEnabled = settings.ui.expand_barter_window
|
gExpandedBarterEnabled = settings.ui.expand_barter_window
|
||||||
&& screenGetHeight() >= GAME_DIALOG_WINDOW_HEIGHT + kExpandedBarterExtraHeight
|
&& screenGetHeight() >= GAME_DIALOG_WINDOW_HEIGHT + kExpandedBarterExtraHeight
|
||||||
&& FrmImage().lock(OBJ_TYPE_INTERFACE, expandedBarterFrmName());
|
&& FrmImage().lock(OBJ_TYPE_INTERFACE, expandedBarterFrmName());
|
||||||
|
|
||||||
int backgroundWindowX = (screenGetWidth() - GAME_DIALOG_WINDOW_WIDTH) / 2;
|
int backgroundWindowX = (screenGetWidth() - GAME_DIALOG_WINDOW_WIDTH) / 2;
|
||||||
int effectiveBgHeight = GAME_DIALOG_WINDOW_HEIGHT + (gExpandedBarterEnabled ? kExpandedBarterExtraHeight : 0);
|
int backgroundWindowY = gameDialogGetBackgroundWindowY();
|
||||||
int backgroundWindowY = (screenGetHeight() - effectiveBgHeight) / 2;
|
|
||||||
|
|
||||||
gGameDialogBackgroundWindow = windowCreate(backgroundWindowX,
|
gGameDialogBackgroundWindow = windowCreate(backgroundWindowX,
|
||||||
backgroundWindowY,
|
backgroundWindowY,
|
||||||
@@ -4577,15 +4617,29 @@ static int talk_to_create_background_window()
|
|||||||
int gameDialogWindowRenderBackground()
|
int gameDialogWindowRenderBackground()
|
||||||
{
|
{
|
||||||
FrmImage backgroundFrmImage;
|
FrmImage backgroundFrmImage;
|
||||||
// alltlk.frm - dialog screen background
|
|
||||||
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 103, 0, 0, 0);
|
if (gameDialogShouldUseHrArt()) {
|
||||||
if (!backgroundFrmImage.lock(backgroundFid)) {
|
if (backgroundFrmImage.lock(OBJ_TYPE_INTERFACE, "HR_ALLTLK.frm")
|
||||||
return -1;
|
&& backgroundFrmImage.getWidth() >= GAME_DIALOG_WINDOW_WIDTH
|
||||||
|
&& backgroundFrmImage.getHeight() >= GAME_DIALOG_WINDOW_HEIGHT) {
|
||||||
|
gameDialogUseHrArt = true;
|
||||||
|
} else {
|
||||||
|
backgroundFrmImage.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int windowWidth = GAME_DIALOG_WINDOW_WIDTH;
|
if (!backgroundFrmImage.isLocked()) {
|
||||||
unsigned char* windowBuffer = windowGetBuffer(gGameDialogBackgroundWindow);
|
// alltlk.frm - dialog screen background
|
||||||
blitBufferToBuffer(backgroundFrmImage.getData(), windowWidth, 480, windowWidth, windowBuffer, windowWidth);
|
FrmId backgroundFid(OBJ_TYPE_INTERFACE, 103);
|
||||||
|
if (!backgroundFrmImage.lock(backgroundFid)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
gameDialogUseHrArt = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstBuffer2D backgroundFrmBuf = backgroundFrmImage.getBuffer();
|
||||||
|
Buffer2D windowBuf = windowGetBuffer2D(gGameDialogBackgroundWindow);
|
||||||
|
blitBuffer2D(backgroundFrmBuf, 0, 0, GAME_DIALOG_WINDOW_WIDTH, GAME_DIALOG_WINDOW_HEIGHT, windowBuf);
|
||||||
|
|
||||||
if (!_dialogue_just_started) {
|
if (!_dialogue_just_started) {
|
||||||
windowRefresh(gGameDialogBackgroundWindow);
|
windowRefresh(gGameDialogBackgroundWindow);
|
||||||
@@ -4734,11 +4788,13 @@ void gameDialogRenderTalkingHead(Art* headFrm, int frame)
|
|||||||
GAME_DIALOG_WINDOW_WIDTH);
|
GAME_DIALOG_WINDOW_WIDTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int yOffset = gameDialogHrArtYOffset();
|
||||||
|
|
||||||
Rect headRect;
|
Rect headRect;
|
||||||
headRect.left = 126;
|
headRect.left = 126;
|
||||||
headRect.top = 14;
|
headRect.top = 14 + yOffset;
|
||||||
headRect.right = 514;
|
headRect.right = 514;
|
||||||
headRect.bottom = 214;
|
headRect.bottom = 214 + yOffset;
|
||||||
|
|
||||||
unsigned char* dest = windowGetBuffer(gGameDialogBackgroundWindow);
|
unsigned char* dest = windowGetBuffer(gGameDialogBackgroundWindow);
|
||||||
|
|
||||||
@@ -4748,7 +4804,7 @@ void gameDialogRenderTalkingHead(Art* headFrm, int frame)
|
|||||||
_upperHighlightFrmImage.getWidth(),
|
_upperHighlightFrmImage.getWidth(),
|
||||||
dest,
|
dest,
|
||||||
426,
|
426,
|
||||||
15,
|
15 + yOffset,
|
||||||
GAME_DIALOG_WINDOW_WIDTH,
|
GAME_DIALOG_WINDOW_WIDTH,
|
||||||
_light_BlendTable,
|
_light_BlendTable,
|
||||||
_light_GrayTable);
|
_light_GrayTable);
|
||||||
@@ -4759,20 +4815,20 @@ void gameDialogRenderTalkingHead(Art* headFrm, int frame)
|
|||||||
_lowerHighlightFrmImage.getWidth(),
|
_lowerHighlightFrmImage.getWidth(),
|
||||||
dest,
|
dest,
|
||||||
129,
|
129,
|
||||||
214 - _lowerHighlightFrmImage.getHeight() - 2,
|
214 + yOffset - _lowerHighlightFrmImage.getHeight() - 2,
|
||||||
GAME_DIALOG_WINDOW_WIDTH,
|
GAME_DIALOG_WINDOW_WIDTH,
|
||||||
_dark_BlendTable,
|
_dark_BlendTable,
|
||||||
_dark_GrayTable);
|
_dark_GrayTable);
|
||||||
|
|
||||||
for (int index = 0; index < 8; ++index) {
|
for (int index = 0; index < 8; ++index) {
|
||||||
Rect* rect = &(_backgrndRects[index]);
|
Rect rect = gameDialogGetBackgroundRect(index);
|
||||||
int width = rect->right - rect->left;
|
int width = rect.right - rect.left;
|
||||||
|
|
||||||
blitBufferToBufferTrans(_backgrndBufs[index],
|
blitBufferToBufferTrans(_backgrndBufs[index],
|
||||||
width,
|
width,
|
||||||
rect->bottom - rect->top,
|
rect.bottom - rect.top,
|
||||||
width,
|
width,
|
||||||
dest + GAME_DIALOG_WINDOW_WIDTH * rect->top + rect->left,
|
dest + GAME_DIALOG_WINDOW_WIDTH * rect.top + rect.left,
|
||||||
GAME_DIALOG_WINDOW_WIDTH);
|
GAME_DIALOG_WINDOW_WIDTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-10
@@ -330,7 +330,7 @@ static void inventoryDrawCenteredText(unsigned char* buffer, int pitch, int widt
|
|||||||
static void inventoryExamineItem(Object* critter, Object* item);
|
static void inventoryExamineItem(Object* critter, Object* item);
|
||||||
static void inventorySetLeftPaneCritter(Object* critter, Object* target, int inventoryWindowType);
|
static void inventorySetLeftPaneCritter(Object* critter, Object* target, int inventoryWindowType);
|
||||||
static void inventoryWindowOpenContextMenu(int eventCode, int inventoryWindowType);
|
static void inventoryWindowOpenContextMenu(int eventCode, int inventoryWindowType);
|
||||||
static InventoryMoveResult _move_inventory(Object* item, int slotIndex, Object* targetObj, bool isPlanting);
|
static InventoryMoveResult _move_inventory(Object* item, int slotIndex, Object* targetObj, bool isPlanting, int* stealXpOverridePtr);
|
||||||
static std::pair<int, int> barterComputeTablesValue(Object* dude, Object* npc, bool offerButton = false);
|
static std::pair<int, int> barterComputeTablesValue(Object* dude, Object* npc, bool offerButton = false);
|
||||||
static std::pair<int, int> barterComputeTablesWeight(Object* dude, Object* npc);
|
static std::pair<int, int> barterComputeTablesWeight(Object* dude, Object* npc);
|
||||||
static int barterAttemptTransaction(Object* dude, Object* offerTable, Object* npc, Object* barterTable);
|
static int barterAttemptTransaction(Object* dude, Object* offerTable, Object* npc, Object* barterTable);
|
||||||
@@ -4622,11 +4622,12 @@ int inventoryOpenLooting(Object* looter, Object* target)
|
|||||||
_gStealSize += itemGetSize(_stack[_curr_stack]);
|
_gStealSize += itemGetSize(_stack[_curr_stack]);
|
||||||
|
|
||||||
InventoryItem* inventoryItem = &(_pud->items[_pud->length - (slotIndex + _stack_offset[_curr_stack] + 1)]);
|
InventoryItem* inventoryItem = &(_pud->items[_pud->length - (slotIndex + _stack_offset[_curr_stack] + 1)]);
|
||||||
InventoryMoveResult rc = _move_inventory(inventoryItem->item, slotIndex, _target_stack[_target_curr_stack], true);
|
int stealXpOverride = -1;
|
||||||
|
InventoryMoveResult rc = _move_inventory(inventoryItem->item, slotIndex, _target_stack[_target_curr_stack], true, &stealXpOverride);
|
||||||
if (rc == INVENTORY_MOVE_RESULT_CAUGHT_STEALING) {
|
if (rc == INVENTORY_MOVE_RESULT_CAUGHT_STEALING) {
|
||||||
isCaughtStealing = true;
|
isCaughtStealing = true;
|
||||||
} else if (rc == INVENTORY_MOVE_RESULT_SUCCESS) {
|
} else if (rc == INVENTORY_MOVE_RESULT_SUCCESS) {
|
||||||
stealingXp += stealingXpBonus;
|
stealingXp += stealXpOverride >= 0 ? stealXpOverride : stealingXpBonus;
|
||||||
stealingXpBonus += 10;
|
stealingXpBonus += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4646,11 +4647,12 @@ int inventoryOpenLooting(Object* looter, Object* target)
|
|||||||
_gStealSize += itemGetSize(_stack[_curr_stack]);
|
_gStealSize += itemGetSize(_stack[_curr_stack]);
|
||||||
|
|
||||||
InventoryItem* inventoryItem = &(_target_pud->items[_target_pud->length - (slotIndex + _target_stack_offset[_target_curr_stack] + 1)]);
|
InventoryItem* inventoryItem = &(_target_pud->items[_target_pud->length - (slotIndex + _target_stack_offset[_target_curr_stack] + 1)]);
|
||||||
InventoryMoveResult rc = _move_inventory(inventoryItem->item, slotIndex, _target_stack[_target_curr_stack], false);
|
int stealXpOverride = -1;
|
||||||
|
InventoryMoveResult rc = _move_inventory(inventoryItem->item, slotIndex, _target_stack[_target_curr_stack], false, &stealXpOverride);
|
||||||
if (rc == INVENTORY_MOVE_RESULT_CAUGHT_STEALING) {
|
if (rc == INVENTORY_MOVE_RESULT_CAUGHT_STEALING) {
|
||||||
isCaughtStealing = true;
|
isCaughtStealing = true;
|
||||||
} else if (rc == INVENTORY_MOVE_RESULT_SUCCESS) {
|
} else if (rc == INVENTORY_MOVE_RESULT_SUCCESS) {
|
||||||
stealingXp += stealingXpBonus;
|
stealingXp += stealXpOverride >= 0 ? stealXpOverride : stealingXpBonus;
|
||||||
stealingXpBonus += 10;
|
stealingXpBonus += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4764,8 +4766,11 @@ int inventoryOpenStealing(Object* thief, Object* target)
|
|||||||
|
|
||||||
// 0x474708
|
// 0x474708
|
||||||
// note: this is looting and stealing, not the inventory screen
|
// note: this is looting and stealing, not the inventory screen
|
||||||
static InventoryMoveResult _move_inventory(Object* item, int slotIndex, Object* targetObj, bool isPlanting)
|
static InventoryMoveResult _move_inventory(Object* item, int slotIndex, Object* targetObj, bool isPlanting, int* stealXpOverridePtr)
|
||||||
{
|
{
|
||||||
|
assert(stealXpOverridePtr != nullptr);
|
||||||
|
*stealXpOverridePtr = -1;
|
||||||
|
|
||||||
bool needRefresh = true;
|
bool needRefresh = true;
|
||||||
|
|
||||||
Rect rect;
|
Rect rect;
|
||||||
@@ -4827,13 +4832,17 @@ static InventoryMoveResult _move_inventory(Object* item, int slotIndex, Object*
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (quantityToMove != -1) {
|
if (quantityToMove != -1) {
|
||||||
|
bool skipMove = false;
|
||||||
if (_gIsSteal && _inven_dude == gDude) {
|
if (_gIsSteal && _inven_dude == gDude) {
|
||||||
if (skillsPerformStealing(_inven_dude, targetObj, item, true) == 0) {
|
SkillStealResult stealResult = skillsPerformStealing(_inven_dude, targetObj, item, quantityToMove, true, stealXpOverridePtr);
|
||||||
|
if (stealResult == SkillStealResult::caught) {
|
||||||
result = INVENTORY_MOVE_RESULT_CAUGHT_STEALING;
|
result = INVENTORY_MOVE_RESULT_CAUGHT_STEALING;
|
||||||
|
} else if (stealResult == SkillStealResult::fail) {
|
||||||
|
skipMove = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != INVENTORY_MOVE_RESULT_CAUGHT_STEALING) {
|
if (!skipMove && result != INVENTORY_MOVE_RESULT_CAUGHT_STEALING) {
|
||||||
if (itemMove(_inven_dude, targetObj, item, quantityToMove) != -1) {
|
if (itemMove(_inven_dude, targetObj, item, quantityToMove) != -1) {
|
||||||
result = INVENTORY_MOVE_RESULT_SUCCESS;
|
result = INVENTORY_MOVE_RESULT_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
@@ -4854,13 +4863,17 @@ static InventoryMoveResult _move_inventory(Object* item, int slotIndex, Object*
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (quantityToMove != -1) {
|
if (quantityToMove != -1) {
|
||||||
|
bool skipMove = false;
|
||||||
if (_gIsSteal && _inven_dude == gDude) {
|
if (_gIsSteal && _inven_dude == gDude) {
|
||||||
if (skillsPerformStealing(_inven_dude, targetObj, item, false) == 0) {
|
SkillStealResult stealResult = skillsPerformStealing(_inven_dude, targetObj, item, quantityToMove, false, stealXpOverridePtr);
|
||||||
|
if (stealResult == SkillStealResult::caught) {
|
||||||
result = INVENTORY_MOVE_RESULT_CAUGHT_STEALING;
|
result = INVENTORY_MOVE_RESULT_CAUGHT_STEALING;
|
||||||
|
} else if (stealResult == SkillStealResult::fail) {
|
||||||
|
skipMove = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != INVENTORY_MOVE_RESULT_CAUGHT_STEALING) {
|
if (!skipMove && result != INVENTORY_MOVE_RESULT_CAUGHT_STEALING) {
|
||||||
if (itemMove(targetObj, _inven_dude, item, quantityToMove) == 0) {
|
if (itemMove(targetObj, _inven_dude, item, quantityToMove) == 0) {
|
||||||
if ((item->flags & OBJECT_IN_RIGHT_HAND) != 0) {
|
if ((item->flags & OBJECT_IN_RIGHT_HAND) != 0) {
|
||||||
targetObj->fid = buildFid(FID_TYPE(targetObj->fid), targetObj->fid & 0xFFF, FID_ANIM_TYPE(targetObj->fid), 0, targetObj->rotation + 1);
|
targetObj->fid = buildFid(FID_TYPE(targetObj->fid), targetObj->fid & 0xFFF, FID_ANIM_TYPE(targetObj->fid), 0, targetObj->rotation + 1);
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ void initSettingsRegistry(bool isMapper)
|
|||||||
SETTING(display_karma_changes);
|
SETTING(display_karma_changes);
|
||||||
SETTING(display_bonus_damage);
|
SETTING(display_bonus_damage);
|
||||||
SETTING(numbers_in_dialogue);
|
SETTING(numbers_in_dialogue);
|
||||||
|
SETTING(enable_dialog_border);
|
||||||
SETTING_P(auto_quick_save, clamp(0, 10));
|
SETTING_P(auto_quick_save, clamp(0, 10));
|
||||||
SETTING(enable_high_resolution_stencil);
|
SETTING(enable_high_resolution_stencil);
|
||||||
SETTING(extend_ap_bar);
|
SETTING(extend_ap_bar);
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ struct UISettings {
|
|||||||
bool display_karma_changes = false;
|
bool display_karma_changes = false;
|
||||||
bool display_bonus_damage = false;
|
bool display_bonus_damage = false;
|
||||||
bool numbers_in_dialogue = false;
|
bool numbers_in_dialogue = false;
|
||||||
|
bool enable_dialog_border = true;
|
||||||
int auto_quick_save = 0;
|
int auto_quick_save = 0;
|
||||||
bool enable_high_resolution_stencil = true;
|
bool enable_high_resolution_stencil = true;
|
||||||
int inventory_columns = 1;
|
int inventory_columns = 1;
|
||||||
|
|||||||
@@ -324,6 +324,54 @@ int scriptHooks_AmmoCost(Object* weapon, int rounds, int ammoCost, AmmoCostHookT
|
|||||||
return overrideAmmoCost >= 0 ? overrideAmmoCost : ammoCost;
|
return overrideAmmoCost >= 0 ? overrideAmmoCost : ammoCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Runs when checking an attempt to steal or plant an item.
|
||||||
|
|
||||||
|
Critter arg0 - The thief
|
||||||
|
Obj arg1 - The target
|
||||||
|
Item arg2 - The item being stolen/planted
|
||||||
|
int arg3 - 0 when stealing, 1 when planting
|
||||||
|
int arg4 - Quantity being stolen/planted
|
||||||
|
|
||||||
|
int ret0 - Override the handler:
|
||||||
|
2 - fail without being caught
|
||||||
|
1 - success
|
||||||
|
0 - fail and get caught
|
||||||
|
-1 - use engine handler
|
||||||
|
int ret1 - Override XP gained for this action. Values below 0 are ignored.
|
||||||
|
*/
|
||||||
|
int scriptHooks_Steal(Object* thief, Object* target, Object* item, bool isPlanting, int quantity, int* xpOverride)
|
||||||
|
{
|
||||||
|
assert(thief != nullptr);
|
||||||
|
assert(target != nullptr);
|
||||||
|
assert(item != nullptr);
|
||||||
|
assert(quantity >= 0);
|
||||||
|
assert(xpOverride != nullptr);
|
||||||
|
|
||||||
|
*xpOverride = -1;
|
||||||
|
|
||||||
|
ScriptHookCall hook(HOOK_STEAL, 2, { thief, target, item, isPlanting ? 1 : 0, quantity });
|
||||||
|
hook.call();
|
||||||
|
|
||||||
|
if (hook.numReturnValues() <= 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hook.numReturnValues() > 1) {
|
||||||
|
int overrideXp = hook.getReturnValueAt(1).asInt();
|
||||||
|
if (overrideXp >= 0) {
|
||||||
|
*xpOverride = overrideXp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int overrideResult = hook.getReturnValueAt(0).asInt();
|
||||||
|
if (overrideResult >= 0 && overrideResult <= 2) {
|
||||||
|
return overrideResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Runs immediately after a critter dies for any reason.
|
Runs immediately after a critter dies for any reason.
|
||||||
|
|
||||||
|
|||||||
@@ -267,6 +267,7 @@ enum AmmoCostHookType {
|
|||||||
bool scriptHooksRegister(Program* program, HookType hookType, int procedureIndex);
|
bool scriptHooksRegister(Program* program, HookType hookType, int procedureIndex);
|
||||||
bool scriptHooks_StdProcedure(int procedureNumber, Object* self, Object* source, Object* target, int fixedParam, bool after);
|
bool scriptHooks_StdProcedure(int procedureNumber, Object* self, Object* source, Object* target, int fixedParam, bool after);
|
||||||
int scriptHooks_AmmoCost(Object* weapon, int rounds, int ammoCost, AmmoCostHookType hookType);
|
int scriptHooks_AmmoCost(Object* weapon, int rounds, int ammoCost, AmmoCostHookType hookType);
|
||||||
|
int scriptHooks_Steal(Object* thief, Object* target, Object* item, bool isPlanting, int quantity, int* xpOverride);
|
||||||
|
|
||||||
bool scriptHooksInit();
|
bool scriptHooksInit();
|
||||||
void scriptHooksReset();
|
void scriptHooksReset();
|
||||||
|
|||||||
+30
-5
@@ -4,6 +4,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "actions.h"
|
#include "actions.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "combat.h"
|
#include "combat.h"
|
||||||
@@ -24,6 +26,7 @@
|
|||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "scripts.h"
|
#include "scripts.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "sfall_script_hooks.h"
|
||||||
#include "stat.h"
|
#include "stat.h"
|
||||||
#include "trait.h"
|
#include "trait.h"
|
||||||
|
|
||||||
@@ -1028,8 +1031,30 @@ int skillUse(Object* obj, Object* target, int skill, int skillBonus)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 0x4ABBE4
|
// 0x4ABBE4
|
||||||
int skillsPerformStealing(Object* thief, Object* target, Object* item, bool isPlanting)
|
SkillStealResult skillsPerformStealing(Object* thief, Object* target, Object* item, int quantity, bool isPlanting, int* xpOverride)
|
||||||
{
|
{
|
||||||
|
assert(thief != nullptr);
|
||||||
|
assert(target != nullptr);
|
||||||
|
assert(item != nullptr);
|
||||||
|
assert(quantity >= 0);
|
||||||
|
assert(xpOverride != nullptr);
|
||||||
|
|
||||||
|
*xpOverride = -1;
|
||||||
|
|
||||||
|
int hookXpOverride = -1;
|
||||||
|
int hookResult = scriptHooks_Steal(thief, target, item, isPlanting, quantity, &hookXpOverride);
|
||||||
|
if (hookXpOverride >= 0) {
|
||||||
|
*xpOverride = hookXpOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hookResult == static_cast<int>(SkillStealResult::fail)) {
|
||||||
|
return SkillStealResult::fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hookResult == static_cast<int>(SkillStealResult::success) || hookResult == static_cast<int>(SkillStealResult::caught)) {
|
||||||
|
return static_cast<SkillStealResult>(hookResult);
|
||||||
|
}
|
||||||
|
|
||||||
int howMuch;
|
int howMuch;
|
||||||
|
|
||||||
int stealModifier = -_gStealCount + 1;
|
int stealModifier = -_gStealCount + 1;
|
||||||
@@ -1087,25 +1112,25 @@ int skillsPerformStealing(Object* thief, Object* target, Object* item, bool isPl
|
|||||||
// 573: You plant the %s.
|
// 573: You plant the %s.
|
||||||
messageListItem.num = isPlanting ? 573 : 571;
|
messageListItem.num = isPlanting ? 573 : 571;
|
||||||
if (!messageListGetItem(&gSkillsMessageList, &messageListItem)) {
|
if (!messageListGetItem(&gSkillsMessageList, &messageListItem)) {
|
||||||
return -1;
|
return SkillStealResult::fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(text, sizeof(text), messageListItem.text, objectGetName(item));
|
snprintf(text, sizeof(text), messageListItem.text, objectGetName(item));
|
||||||
displayMonitorAddMessage(text);
|
displayMonitorAddMessage(text);
|
||||||
|
|
||||||
return 1;
|
return SkillStealResult::success;
|
||||||
} else {
|
} else {
|
||||||
// 570: You're caught stealing the %s.
|
// 570: You're caught stealing the %s.
|
||||||
// 572: You're caught planting the %s.
|
// 572: You're caught planting the %s.
|
||||||
messageListItem.num = isPlanting ? 572 : 570;
|
messageListItem.num = isPlanting ? 572 : 570;
|
||||||
if (!messageListGetItem(&gSkillsMessageList, &messageListItem)) {
|
if (!messageListGetItem(&gSkillsMessageList, &messageListItem)) {
|
||||||
return -1;
|
return SkillStealResult::fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(text, sizeof(text), messageListItem.text, objectGetName(item));
|
snprintf(text, sizeof(text), messageListItem.text, objectGetName(item));
|
||||||
displayMonitorAddMessage(text);
|
displayMonitorAddMessage(text);
|
||||||
|
|
||||||
return 0;
|
return SkillStealResult::caught;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-1
@@ -12,6 +12,12 @@ extern int _gIsSteal;
|
|||||||
extern int _gStealCount;
|
extern int _gStealCount;
|
||||||
extern int _gStealSize;
|
extern int _gStealSize;
|
||||||
|
|
||||||
|
enum class SkillStealResult {
|
||||||
|
caught = 0,
|
||||||
|
success = 1,
|
||||||
|
fail = 2,
|
||||||
|
};
|
||||||
|
|
||||||
int skillsInit();
|
int skillsInit();
|
||||||
void skillsReset();
|
void skillsReset();
|
||||||
void skillsExit();
|
void skillsExit();
|
||||||
@@ -35,7 +41,7 @@ char* skillGetDescription(int skill);
|
|||||||
char* skillGetAttributes(int skill);
|
char* skillGetAttributes(int skill);
|
||||||
int skillGetFrmId(int skill);
|
int skillGetFrmId(int skill);
|
||||||
int skillUse(Object* obj, Object* target, int skill, int skillBonus);
|
int skillUse(Object* obj, Object* target, int skill, int skillBonus);
|
||||||
int skillsPerformStealing(Object* thief, Object* target, Object* item, bool isPlanting);
|
SkillStealResult skillsPerformStealing(Object* thief, Object* target, Object* item, int quantity, bool isPlanting, int* xpOverride);
|
||||||
int skillGetGameDifficultyModifier(int skill);
|
int skillGetGameDifficultyModifier(int skill);
|
||||||
int skillUpdateLastUse(int skill);
|
int skillUpdateLastUse(int skill);
|
||||||
int skillsUsageSave(File* stream);
|
int skillsUsageSave(File* stream);
|
||||||
|
|||||||
Reference in New Issue
Block a user