Add op_set_self

This commit is contained in:
Alexander Batalov 2023-09-03 18:23:19 +03:00
parent ad3e0eb752
commit 6e9f1ae517
4 changed files with 39 additions and 2 deletions

View File

@ -1580,12 +1580,22 @@ static void opPickup(Program* program)
return; return;
} }
if (script->target == NULL) { Object* self = script->target;
// SFALL: Override `self` via `op_set_self`.
// CE: Implementation is different. Sfall integrates via `scriptGetSid` by
// returning fake script with overridden `self` (and `target` in this case).
if (script->overriddenSelf != nullptr) {
self = script->overriddenSelf;
script->overriddenSelf = nullptr;
}
if (self == NULL) {
scriptPredefinedError(program, "pickup_obj", SCRIPT_ERROR_OBJECT_IS_NULL); scriptPredefinedError(program, "pickup_obj", SCRIPT_ERROR_OBJECT_IS_NULL);
return; return;
} }
actionPickUp(script->target, object); actionPickUp(self, object);
} }
// drop_obj // drop_obj
@ -4548,6 +4558,15 @@ static void opUseObjectOnObject(Program* program)
} }
Object* self = scriptGetSelf(program); Object* self = scriptGetSelf(program);
// SFALL: Override `self` via `op_set_self`.
// CE: Implementation is different. Sfall integrates via `scriptGetSid` by
// returning fake script with overridden `self`.
if (script->overriddenSelf != nullptr) {
self = script->overriddenSelf;
script->overriddenSelf = nullptr;
}
if (PID_TYPE(self->pid) == OBJ_TYPE_CRITTER) { if (PID_TYPE(self->pid) == OBJ_TYPE_CRITTER) {
_action_use_an_item_on_object(self, target, item); _action_use_an_item_on_object(self, target, item);
} else { } else {

View File

@ -2214,6 +2214,8 @@ int scriptAdd(int* sidPtr, int scriptType)
scr->procs[index] = SCRIPT_PROC_NO_PROC; scr->procs[index] = SCRIPT_PROC_NO_PROC;
} }
scr->overriddenSelf = nullptr;
scriptListExtent->length++; scriptListExtent->length++;
return 0; return 0;

View File

@ -143,6 +143,8 @@ typedef struct Script {
int field_D4; int field_D4;
int field_D8; int field_D8;
int field_DC; int field_DC;
Object* overriddenSelf;
} Script; } Script;
extern const char* gScriptProcNames[SCRIPT_PROC_COUNT]; extern const char* gScriptProcNames[SCRIPT_PROC_COUNT];

View File

@ -345,6 +345,19 @@ static void op_set_proto_data(Program* program)
*reinterpret_cast<int*>(reinterpret_cast<unsigned char*>(proto) + offset) = value; *reinterpret_cast<int*>(reinterpret_cast<unsigned char*>(proto) + offset) = value;
} }
// set_self
static void op_set_self(Program* program)
{
Object* obj = static_cast<Object*>(programStackPopPointer(program));
int sid = scriptGetSid(program);
Script* scr;
if (scriptGetScript(sid, &scr) == 0) {
scr->overriddenSelf = obj;
}
}
// list_begin // list_begin
static void opListBegin(Program* program) static void opListBegin(Program* program)
{ {
@ -1055,6 +1068,7 @@ void sfallOpcodesInit()
interpreterRegisterOpcode(0x81F5, op_get_script); interpreterRegisterOpcode(0x81F5, op_get_script);
interpreterRegisterOpcode(0x8204, op_get_proto_data); interpreterRegisterOpcode(0x8204, op_get_proto_data);
interpreterRegisterOpcode(0x8205, op_set_proto_data); interpreterRegisterOpcode(0x8205, op_set_proto_data);
interpreterRegisterOpcode(0x8206, op_set_self);
interpreterRegisterOpcode(0x820D, opListBegin); interpreterRegisterOpcode(0x820D, opListBegin);
interpreterRegisterOpcode(0x820E, opListNext); interpreterRegisterOpcode(0x820E, opListNext);
interpreterRegisterOpcode(0x820F, opListEnd); interpreterRegisterOpcode(0x820F, opListEnd);