mirror of
https://github.com/fallout2-ce/fallout2-ce.git
synced 2026-07-27 16:47:11 -07:00
Implement obj_is_carrying_obj Sfall opcode (#362)
Note: does not include the sfall fix to fix stack counts
This commit is contained in:
@@ -32,10 +32,10 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
|
||||
| Art and appearance | art_exists<br>refresh_pc_art<br>art_cache_clear<br>set_hero_race<br>set_hero_style | implemented: art_exists, refresh_pc_art, art_cache_clear | - |
|
||||
| Tiles and paths | get_tile_fid<br>tile_under_cursor<br>tile_light<br>tile_get_objs<br>tile_refresh_display<br>obj_blocking_tile<br>tile_by_position<br>get_tile_ground_fid<br>get_tile_roof_fid<br>obj_blocking_line<br>path_find_to<br>objects_in_radius | ✅ except objects_in_radius | - |
|
||||
| Utility | sprintf<br>typeof<br>atoi<br>atof | ✅ | - |
|
||||
| Utility / Strings | string_split<br>substr<br>strlen<br>charcode<br>get_string_pointer<br>string_find<br>string_find_from<br>string_format<br>string_format_array<br>string_replace<br>string_to_case<br>string_compare | ✅ except get_string_pointer | `get_string_pointer` is deprecated and intentionally omitted. |
|
||||
| Interface / Tags | show_iface_tag<br>hide_iface_tag<br>is_iface_tag_active<br>set_iface_tag_text<br>add_iface_tag | implemented: all except set_iface_tag_text, add_iface_tag | CE only handles built-in interface tags here; custom tag creation/text is not supported yet. |
|
||||
| Global variables | set_sfall_global<br>get_sfall_global_int<br>get_sfall_global_float | implemented: all except get_sfall_global_float | Current CE storage is int-backed; `set_sfall_global` stores integer values and there is no float getter yet. |
|
||||
| Hooks / Hook functions | init_hook<br>get_sfall_arg<br>get_sfall_args<br>get_sfall_arg_at<br>set_sfall_return<br>set_sfall_arg<br>register_hook<br>register_hook_proc<br>register_hook_proc_spec | ✅ except init_hook | See below for implemented hooks. `init_hook` is deprecated and will not be implemented. register_hook_proc and register_hook_proc_spec both add hooks to the *end* of the hook list, instead of beginning and end, respectively. |
|
||||
| Utility / Strings | string_split<br>substr<br>strlen<br>charcode<br>get_string_pointer<br>string_find<br>string_find_from<br>string_format<br>string_format_array<br>string_replace<br>string_to_case<br>string_compare | ✅ | `get_string_pointer` is deprecated and intentionally omitted. |
|
||||
| Interface / Tags | show_iface_tag<br>hide_iface_tag<br>is_iface_tag_active<br>set_iface_tag_text<br>add_iface_tag | ✅ except set_iface_tag_text, add_iface_tag | CE only handles built-in interface tags here; custom tag creation/text is not supported yet. |
|
||||
| Global variables | set_sfall_global<br>get_sfall_global_int<br>get_sfall_global_float | ✅ except get_sfall_global_float | Current CE storage is int-backed; `set_sfall_global` stores integer values |
|
||||
| Hooks / Hook functions | init_hook<br>get_sfall_arg<br>get_sfall_args<br>get_sfall_arg_at<br>set_sfall_return<br>set_sfall_arg<br>register_hook<br>register_hook_proc<br>register_hook_proc_spec | ✅ | See below for implemented hooks. `init_hook` is deprecated and will not be implemented. register_hook_proc and register_hook_proc_spec both add hooks to the *end* of the hook list, instead of beginning and end, respectively. |
|
||||
| Arrays / Array functions | create_array<br>temp_array<br>fix_array<br>get/set_array<br>resize_array<br>free_array<br>scan_array<br>len_array<br>save/load_array<br>array_key<br>arrayexpr | ✅ except save_array, load_array | - |
|
||||
| Perks and traits / NPC perks | set_fake_perk_npc<br>set_fake_trait_npc<br>set_selectable_perk_npc<br>has_fake_perk_npc<br>has_fake_trait_npc | not implemented | - |
|
||||
| Global scripts / Global script functions | set_global_script_repeat<br>set_global_script_type<br>available_global_script_types | implemented: all except available_global_script_types | - |
|
||||
@@ -48,7 +48,7 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
|
||||
| Interface / Cursor | get/set_cursor_mode | ✅ | - |
|
||||
| Locks | lock_is_jammed<br>unjam_lock<br>set_unjam_locks_time | not implemented | - |
|
||||
| INI settings | modified_ini<br>get_ini_setting<br>get_ini_string<br>get_ini_section<br>get_ini_sections<br>get_ini_config<br>get_ini_config_db<br>set_ini_setting | ✅ except modified_ini, get_ini_config, get_ini_config_db | `modified_ini` is intentionally omitted as deprecated. |
|
||||
| Objects and scripts | set_self<br>set_dude_obj<br>real_dude_obj<br>remove_script<br>set_script<br>get_script<br>obj_is_carrying_obj<br>loot_obj<br>dialog_obj<br>obj_under_cursor<br>get_object_data<br>set_object_data<br>get_flags<br>set_flags<br>set_unique_id<br>set_scr_name<br>obj_is_openable<br>get/set_proto_data<br>get_object_ai_data | implemented: set_self, get_script, loot_obj, dialog_obj, obj_under_cursor, get_object_data, get_flags, set_flags, get_proto_data, set_proto_data | - |
|
||||
| Objects and scripts | set_self<br>set_dude_obj<br>real_dude_obj<br>remove_script<br>set_script<br>get_script<br>obj_is_carrying_obj<br>loot_obj<br>dialog_obj<br>obj_under_cursor<br>get_object_data<br>set_object_data<br>get_flags<br>set_flags<br>set_unique_id<br>set_scr_name<br>obj_is_openable<br>get/set_proto_data<br>get_object_ai_data | implemented: set_self, get_script, obj_is_carrying_obj, loot_obj, dialog_obj, obj_under_cursor, get_object_data, get_flags, set_flags, get_proto_data, set_proto_data | - |
|
||||
| Other / Game management | set_movie_path<br>stop_game<br>resume_game<br>mark_movie_played<br>game_loaded<br>get_game_mode<br>get_uptime<br>signal_close_game | implemented: game_loaded, get_game_mode, get_uptime | - |
|
||||
| Other | input_funcs_available<br>get_year<br>set_dm_model<br>set_df_model<br>set_pipboy_available<br>get_kill_counter<br>mod_kill_counter<br>active_hand<br>toggle_active_hand<br>set_pickpocket_max<br>set_hit_chance_max<br>set_xp_mod<br>set_critter_hit_chance_mod<br>set_base_hit_chance_mod<br>inc_npc_level<br>get_npc_level<br>get/set_viewport_x/y<br>set_hp_per_level_mod<br>get/set_unspent_ap_bonus<br>get/set_unspent_ap_perk_bonus<br>hero_select_win<br>create_message_window<br>get_light_level<br>gdialog_get_barter_mod<br>set_inven_ap_cost<br>set_base_pickpocket_mod<br>set_critter_pickpocket_mod<br>message_str_game<br>sneak_success<br>create_spatial<br>unwield_slot<br>get_inven_ap_cost<br>add_g_timer_event<br>add_extra_msg_file<br>get_metarule_table<br>metarule_exist<br>npc_engine_level_up<br>remove_timer_event<br>set_drugs_data<br>spatial_radius | implemented: get_year, active_hand, toggle_active_hand, create_message_window, message_str_game, add_extra_msg_file, metarule_exist | `input_funcs_available`, `nb_create_char` are deprecated in sfall and intentionally absent in CE. `add_extra_msg_file` does not support the explicit `fileNumber` form in CE. |
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "define_lite.h"
|
||||
#include "sfall.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
#define TEST_ITEM_PID 40
|
||||
|
||||
procedure start begin
|
||||
variable item_a;
|
||||
variable item_b;
|
||||
variable item_c;
|
||||
variable pid_total;
|
||||
|
||||
display_msg("Testing inventory functions...");
|
||||
|
||||
item_a := create_object_sid(TEST_ITEM_PID, 0, 0, -1);
|
||||
item_b := create_object_sid(TEST_ITEM_PID, 0, 0, -1);
|
||||
item_c := create_object_sid(TEST_ITEM_PID, 0, 0, -1);
|
||||
|
||||
add_obj_to_inven(dude_obj, item_a);
|
||||
call assertEquals("single carried object count", obj_is_carrying_obj(dude_obj, item_a), 1);
|
||||
add_obj_to_inven(dude_obj, item_b);
|
||||
|
||||
call assertEquals("merged stack no longer matches original object pointer", obj_is_carrying_obj(dude_obj, item_a), 0);
|
||||
call assertEquals("merged stack matches replacement object pointer", obj_is_carrying_obj(dude_obj, item_b), 2);
|
||||
|
||||
pid_total := obj_is_carrying_obj_pid(dude_obj, TEST_ITEM_PID);
|
||||
call assertTrue("pid total covers both stacks", pid_total >= 2);
|
||||
call assertEquals("pid total matches merged carried stack quantity", pid_total, obj_is_carrying_obj(dude_obj, item_b));
|
||||
|
||||
call assertEquals("object not in inventory returns zero", obj_is_carrying_obj(dude_obj, item_c), 0);
|
||||
call assertEquals("null inventory object returns zero", obj_is_carrying_obj(0, item_a), 0);
|
||||
call assertEquals("null item object returns zero", obj_is_carrying_obj(dude_obj, 0), 0);
|
||||
|
||||
call assertEquals("remove merged stack quantity", rm_mult_objs_from_inven(dude_obj, item_b, 2), 2);
|
||||
destroy_object(item_c);
|
||||
|
||||
call report_test_results("inventory");
|
||||
end
|
||||
@@ -64,6 +64,34 @@ static void op_art_exists(Program* program)
|
||||
programStackPushInteger(program, artExists(fid));
|
||||
}
|
||||
|
||||
static void op_obj_is_carrying_obj(Program* program)
|
||||
{
|
||||
Object* itemObj = static_cast<Object*>(programStackPopPointer(program));
|
||||
Object* invenObj = static_cast<Object*>(programStackPopPointer(program));
|
||||
|
||||
int count = 0;
|
||||
if (invenObj != nullptr && itemObj != nullptr) {
|
||||
Inventory* inventory = &(invenObj->data.inventory);
|
||||
for (int index = 0; index < inventory->length; index++) {
|
||||
InventoryItem* inventoryItem = &(inventory->items[index]);
|
||||
if (inventoryItem->item == itemObj) {
|
||||
if (inventoryItem->quantity <= 0) {
|
||||
debugPrint("%s: obj_is_carrying_obj found non-positive inventory quantity for item %p in owner %p",
|
||||
program->name,
|
||||
itemObj,
|
||||
invenObj);
|
||||
count = 1;
|
||||
} else {
|
||||
count = inventoryItem->quantity;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
programStackPushInteger(program, count);
|
||||
}
|
||||
|
||||
// read_byte
|
||||
static void op_read_byte(Program* program)
|
||||
{
|
||||
@@ -1948,6 +1976,7 @@ void sfallOpcodesInit()
|
||||
// 0x8274 - int art_exists(int artFID)
|
||||
interpreterRegisterOpcode(0x8274, op_art_exists);
|
||||
// 0x8275 - int obj_is_carrying_obj(object invenObj, object itemObj)
|
||||
interpreterRegisterOpcode(0x8275, op_obj_is_carrying_obj);
|
||||
|
||||
// 0x8276 - any sfall_func0(string funcName)
|
||||
interpreterRegisterOpcode(0x8276, op_sfall_func0);
|
||||
|
||||
Reference in New Issue
Block a user