Add op_list_as_array
This commit is contained in:
parent
bb3513956c
commit
427672741a
|
@ -11,6 +11,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
#include "sfall_lists.h"
|
||||||
|
|
||||||
namespace fallout {
|
namespace fallout {
|
||||||
|
|
||||||
|
@ -647,6 +648,25 @@ ProgramValue ScanArray(ArrayId arrayId, const ProgramValue& val, Program* progra
|
||||||
return arr->ScanArray(val, program);
|
return arr->ScanArray(val, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayId ListAsArray(int type)
|
||||||
|
{
|
||||||
|
std::vector<Object*> objects;
|
||||||
|
sfall_lists_fill(type, objects);
|
||||||
|
|
||||||
|
int count = static_cast<int>(objects.size());
|
||||||
|
ArrayId arrayId = CreateTempArray(count, 0);
|
||||||
|
auto arr = get_array_by_id(arrayId);
|
||||||
|
|
||||||
|
// A little bit ugly and likely inefficient.
|
||||||
|
for (int index = 0; index < count; index++) {
|
||||||
|
arr->SetArray(ProgramValue { index },
|
||||||
|
ArrayElement { ProgramValue { objects[index] }, nullptr },
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return arrayId;
|
||||||
|
}
|
||||||
|
|
||||||
ArrayId StringSplit(const char* str, const char* split)
|
ArrayId StringSplit(const char* str, const char* split)
|
||||||
{
|
{
|
||||||
size_t splitLen = strlen(split);
|
size_t splitLen = strlen(split);
|
||||||
|
|
|
@ -26,6 +26,7 @@ void ResizeArray(ArrayId arrayId, int newLen);
|
||||||
void DeleteAllTempArrays();
|
void DeleteAllTempArrays();
|
||||||
int StackArray(const ProgramValue& key, const ProgramValue& val, Program* program);
|
int StackArray(const ProgramValue& key, const ProgramValue& val, Program* program);
|
||||||
ProgramValue ScanArray(ArrayId arrayId, const ProgramValue& val, Program* program);
|
ProgramValue ScanArray(ArrayId arrayId, const ProgramValue& val, Program* program);
|
||||||
|
ArrayId ListAsArray(int type);
|
||||||
|
|
||||||
ArrayId StringSplit(const char* str, const char* split);
|
ArrayId StringSplit(const char* str, const char* split);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "sfall_lists.h"
|
#include "sfall_lists.h"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "scripts.h"
|
#include "scripts.h"
|
||||||
|
@ -66,46 +65,7 @@ int sfallListsCreate(int listType)
|
||||||
int listId = _state->nextListId++;
|
int listId = _state->nextListId++;
|
||||||
List& list = _state->lists[listId];
|
List& list = _state->lists[listId];
|
||||||
|
|
||||||
if (listType == LIST_TILES) {
|
sfall_lists_fill(listType, list.objects);
|
||||||
// For unknown reason this list type is not implemented in Sfall.
|
|
||||||
} else if (listType == LIST_SPATIAL) {
|
|
||||||
for (int elevation = 0; elevation < ELEVATION_COUNT; elevation++) {
|
|
||||||
Script* script = scriptGetFirstSpatialScript(elevation);
|
|
||||||
while (script != nullptr) {
|
|
||||||
Object* obj = script->owner;
|
|
||||||
if (obj == nullptr) {
|
|
||||||
obj = scriptGetSelf(script->program);
|
|
||||||
}
|
|
||||||
list.objects.push_back(obj);
|
|
||||||
script = scriptGetNextSpatialScript();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// CE: Implementation is slightly different. Sfall manually loops thru
|
|
||||||
// elevations (3) and hexes (40000) and use |objectFindFirstAtLocation|
|
|
||||||
// (originally |obj_find_first_at_tile|) to obtain next object. This
|
|
||||||
// functionality is already implemented in |objectFindFirst| and
|
|
||||||
// |objectFindNext|.
|
|
||||||
//
|
|
||||||
// As a small optimization |LIST_ALL| is handled separately since there
|
|
||||||
// is no need to check object type.
|
|
||||||
if (listType == LIST_ALL) {
|
|
||||||
Object* obj = objectFindFirst();
|
|
||||||
while (obj != nullptr) {
|
|
||||||
list.objects.push_back(obj);
|
|
||||||
obj = objectFindNext();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Object* obj = objectFindFirst();
|
|
||||||
while (obj != nullptr) {
|
|
||||||
int objectType = PID_TYPE(obj->pid);
|
|
||||||
if (objectType < kObjectTypeToListTypeSize && kObjectTypeToListType[objectType] == listType) {
|
|
||||||
list.objects.push_back(obj);
|
|
||||||
}
|
|
||||||
obj = objectFindNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return listId;
|
return listId;
|
||||||
}
|
}
|
||||||
|
@ -131,4 +91,54 @@ void sfallListsDestroy(int listId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sfall_lists_fill(int type, std::vector<Object*>& objects)
|
||||||
|
{
|
||||||
|
if (type == LIST_TILES) {
|
||||||
|
// For unknown reason this list type is not implemented in Sfall.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects.reserve(100);
|
||||||
|
|
||||||
|
if (type == LIST_SPATIAL) {
|
||||||
|
for (int elevation = 0; elevation < ELEVATION_COUNT; elevation++) {
|
||||||
|
Script* script = scriptGetFirstSpatialScript(elevation);
|
||||||
|
while (script != nullptr) {
|
||||||
|
Object* obj = script->owner;
|
||||||
|
if (obj == nullptr) {
|
||||||
|
obj = scriptGetSelf(script->program);
|
||||||
|
}
|
||||||
|
objects.push_back(obj);
|
||||||
|
script = scriptGetNextSpatialScript();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// CE: Implementation is slightly different. Sfall manually loops thru
|
||||||
|
// elevations (3) and hexes (40000) and use |objectFindFirstAtLocation|
|
||||||
|
// (originally |obj_find_first_at_tile|) to obtain next object. This
|
||||||
|
// functionality is already implemented in |objectFindFirst| and
|
||||||
|
// |objectFindNext|.
|
||||||
|
//
|
||||||
|
// As a small optimization |LIST_ALL| is handled separately since there
|
||||||
|
// is no need to check object type.
|
||||||
|
if (type == LIST_ALL) {
|
||||||
|
Object* obj = objectFindFirst();
|
||||||
|
while (obj != nullptr) {
|
||||||
|
objects.push_back(obj);
|
||||||
|
obj = objectFindNext();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Object* obj = objectFindFirst();
|
||||||
|
while (obj != nullptr) {
|
||||||
|
int objectType = PID_TYPE(obj->pid);
|
||||||
|
if (objectType < kObjectTypeToListTypeSize
|
||||||
|
&& kObjectTypeToListType[objectType] == type) {
|
||||||
|
objects.push_back(obj);
|
||||||
|
}
|
||||||
|
obj = objectFindNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace fallout
|
} // namespace fallout
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef FALLOUT_SFALL_LISTS_H_
|
#ifndef FALLOUT_SFALL_LISTS_H_
|
||||||
#define FALLOUT_SFALL_LISTS_H_
|
#define FALLOUT_SFALL_LISTS_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "obj_types.h"
|
#include "obj_types.h"
|
||||||
|
|
||||||
namespace fallout {
|
namespace fallout {
|
||||||
|
@ -22,6 +24,7 @@ void sfallListsExit();
|
||||||
int sfallListsCreate(int listType);
|
int sfallListsCreate(int listType);
|
||||||
Object* sfallListsGetNext(int listId);
|
Object* sfallListsGetNext(int listId);
|
||||||
void sfallListsDestroy(int listId);
|
void sfallListsDestroy(int listId);
|
||||||
|
void sfall_lists_fill(int type, std::vector<Object*>& objects);
|
||||||
|
|
||||||
} // namespace fallout
|
} // namespace fallout
|
||||||
|
|
||||||
|
|
|
@ -556,6 +556,14 @@ static void op_force_encounter_with_flags(Program* program)
|
||||||
wmForceEncounter(map, flags);
|
wmForceEncounter(map, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// list_as_array
|
||||||
|
static void op_list_as_array(Program* program)
|
||||||
|
{
|
||||||
|
int type = programStackPopInteger(program);
|
||||||
|
int arrayId = ListAsArray(type);
|
||||||
|
programStackPushInteger(program, arrayId);
|
||||||
|
}
|
||||||
|
|
||||||
// atoi
|
// atoi
|
||||||
static void opParseInt(Program* program)
|
static void opParseInt(Program* program)
|
||||||
{
|
{
|
||||||
|
@ -953,6 +961,7 @@ void sfallOpcodesInit()
|
||||||
interpreterRegisterOpcode(0x8233, opTempArray);
|
interpreterRegisterOpcode(0x8233, opTempArray);
|
||||||
interpreterRegisterOpcode(0x8234, opFixArray);
|
interpreterRegisterOpcode(0x8234, opFixArray);
|
||||||
interpreterRegisterOpcode(0x8235, opStringSplit);
|
interpreterRegisterOpcode(0x8235, opStringSplit);
|
||||||
|
interpreterRegisterOpcode(0x8236, op_list_as_array);
|
||||||
interpreterRegisterOpcode(0x8237, opParseInt);
|
interpreterRegisterOpcode(0x8237, opParseInt);
|
||||||
interpreterRegisterOpcode(0x8238, op_atof);
|
interpreterRegisterOpcode(0x8238, op_atof);
|
||||||
interpreterRegisterOpcode(0x8239, opScanArray);
|
interpreterRegisterOpcode(0x8239, opScanArray);
|
||||||
|
|
Loading…
Reference in New Issue