diff --git a/artifacts/scripting/headers/define_extra.h b/artifacts/scripting/headers/define_extra.h
index 6547646f..245ea5d8 100644
--- a/artifacts/scripting/headers/define_extra.h
+++ b/artifacts/scripting/headers/define_extra.h
@@ -287,6 +287,7 @@
#define WPN_ANIM_ROCKET_LAUNCHER (0x0A) // (M)
// common object data offsets
+#define OBJ_DATA_ID (0x00)
#define OBJ_DATA_TILENUM (0x04)
#define OBJ_DATA_CUR_FRM (0x18) // current frame number
#define OBJ_DATA_ROTATION (0x1C)
diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h
index d47d20dc..5cbe517c 100644
--- a/artifacts/scripting/headers/sfall.h
+++ b/artifacts/scripting/headers/sfall.h
@@ -243,6 +243,7 @@
#define set_map_enter_position(tile, elev, rot) sfall_func3("set_map_enter_position", tile, elev, rot)
#define set_object_data(obj, offset, value) sfall_func3("set_object_data", obj, offset, value)
#define set_outline(obj, color) sfall_func2("set_outline", obj, color)
+#define set_unique_id(object) sfall_func1("set_unique_id", object)
#define spatial_radius(obj) sfall_func1("spatial_radius", obj)
#define tile_refresh_display sfall_func0("tile_refresh_display")
#define unjam_lock(obj) sfall_func1("unjam_lock", obj)
diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt
index 4d9cf958..aafe9127 100644
--- a/artifacts/scripting/sfall function notes.txt
+++ b/artifacts/scripting/sfall function notes.txt
@@ -472,6 +472,12 @@ Some utility/math functions are available:
> void sfall_func0("art_cache_clear")
- clears the cache of FRM image files loaded into memory
+> int sfall_func1("set_unique_id", object)
+- assigns an unique ID number to the object and returns it. If an unique ID number has already been assigned to an object, then ID number is returned without reassignment
+- to just get the current ID number of an object, use sfall_func2("get_object_data", object, OBJ_DATA_ID)
+- unique ID numbers are saved in your savegame, and have a range from 0x10000000 to 0x7FFFFFFF
+- there is also an unique ID number range for the player and party members from 18000 to 83535
+
------------------------
------ MORE INFO -------
------------------------
diff --git a/sfall/Perks.cpp b/sfall/Perks.cpp
index 14b68240..e5f0698d 100644
--- a/sfall/Perks.cpp
+++ b/sfall/Perks.cpp
@@ -556,23 +556,27 @@ end:
// Adds the selected perk to the player
static void _stdcall AddFakePerk(DWORD perkID) {
+ size_t count;
+ bool matched = false;
+ // behavior for fake perk/trait
perkID -= PERK_count;
- if (addPerkMode & 1) {
- bool matched = false;
- for (DWORD d = 0; d < fakeTraits.size(); d++) {
+ if (addPerkMode & 1) { // add perk to trait
+ count = fakeTraits.size();
+ for (size_t d = 0; d < count; d++) {
if (!strcmp(fakeTraits[d].Name, fakeSelectablePerks[perkID].Name)) {
matched = true;
break;
}
}
if (!matched) {
- if (RemoveTraitID == -1) RemoveTraitID = fakeTraits.size();
+ if (RemoveTraitID == -1) RemoveTraitID = count; // index of the added trait
fakeTraits.push_back(fakeSelectablePerks[perkID]);
}
}
- if (addPerkMode & 2) {
- bool matched = false;
- for (DWORD d = 0; d < fakePerks.size(); d++) {
+ if (addPerkMode & 2) { // default mode
+ matched = false;
+ count = fakePerks.size();
+ for (size_t d = 0; d < count; d++) {
if (!strcmp(fakePerks[d].Name, fakeSelectablePerks[perkID].Name)) {
RemovePerkID.push_back(d);
fakePerks[d].Level++;
@@ -580,12 +584,12 @@ static void _stdcall AddFakePerk(DWORD perkID) {
break;
}
}
- if (!matched) {
- RemovePerkID.push_back(fakePerks.size());
+ if (!matched) { // add to fakePerks
+ RemovePerkID.push_back(count); // index of the added perk
fakePerks.push_back(fakeSelectablePerks[perkID]);
}
}
- if (addPerkMode & 4) {
+ if (addPerkMode & 4) { // delete from selectable perks
RemoveSelectableID.push_back(perkID);
//fakeSelectablePerks.remove_at(perkID);
}
diff --git a/sfall/ScriptExtender.cpp b/sfall/ScriptExtender.cpp
index 51914834..21cede4e 100644
--- a/sfall/ScriptExtender.cpp
+++ b/sfall/ScriptExtender.cpp
@@ -402,6 +402,7 @@ static const SfallOpcodeMetadata opcodeMetaArray[] = {
{sf_set_map_enter_position, "set_map_enter_position", {DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
{sf_set_object_data, "set_object_data", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
{sf_set_outline, "set_outline", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
+ {sf_set_unique_id, "set_unique_id", {DATATYPE_MASK_VALID_OBJ}},
{sf_spatial_radius, "spatial_radius", {DATATYPE_MASK_VALID_OBJ}},
{sf_unjam_lock, "unjam_lock", {DATATYPE_MASK_VALID_OBJ}},
#ifndef NDEBUG
diff --git a/sfall/ScriptOps/MetaruleOp.hpp b/sfall/ScriptOps/MetaruleOp.hpp
index 8f23d21a..10c77725 100644
--- a/sfall/ScriptOps/MetaruleOp.hpp
+++ b/sfall/ScriptOps/MetaruleOp.hpp
@@ -133,6 +133,7 @@ static const SfallMetarule metaruleArray[] = {
{"set_map_enter_position", sf_set_map_enter_position, 3, 3},
{"set_object_data", sf_set_object_data, 3, 3},
{"set_outline", sf_set_outline, 2, 2},
+ {"set_unique_id", sf_set_unique_id, 1, 1},
{"spatial_radius", sf_spatial_radius, 1, 1},
{"tile_refresh_display", sf_tile_refresh_display, 0, 0},
{"unjam_lock", sf_unjam_lock, 1, 1},
diff --git a/sfall/ScriptOps/ObjectsOps.hpp b/sfall/ScriptOps/ObjectsOps.hpp
index 52881a87..74757db4 100644
--- a/sfall/ScriptOps/ObjectsOps.hpp
+++ b/sfall/ScriptOps/ObjectsOps.hpp
@@ -643,3 +643,7 @@ static void sf_set_object_data() {
BYTE* object_ptr = (BYTE*)opHandler.arg(0).asObject();
*(long*)(object_ptr + opHandler.arg(1).asInt()) = opHandler.arg(2).asInt();
}
+
+static void sf_set_unique_id() {
+ opHandler.setReturn(SetObjectUniqueID(opHandler.arg(0).asObject()), DATATYPE_INT);
+}
diff --git a/sfall/ddraw.sln b/sfall/ddraw.sln
index 4b77dd93..d0738105 100644
--- a/sfall/ddraw.sln
+++ b/sfall/ddraw.sln
@@ -6,12 +6,15 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
+ DevXP|Win32 = DevXP|Win32
Release|Win32 = Release|Win32
Win2K|Win32 = Win2K|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FB9023DA-CA5E-4704-B601-407810963EF0}.Debug|Win32.ActiveCfg = Debug|Win32
{FB9023DA-CA5E-4704-B601-407810963EF0}.Debug|Win32.Build.0 = Debug|Win32
+ {FB9023DA-CA5E-4704-B601-407810963EF0}.DevXP|Win32.ActiveCfg = DevXP|Win32
+ {FB9023DA-CA5E-4704-B601-407810963EF0}.DevXP|Win32.Build.0 = DevXP|Win32
{FB9023DA-CA5E-4704-B601-407810963EF0}.Release|Win32.ActiveCfg = Release|Win32
{FB9023DA-CA5E-4704-B601-407810963EF0}.Release|Win32.Build.0 = Release|Win32
{FB9023DA-CA5E-4704-B601-407810963EF0}.Win2K|Win32.ActiveCfg = Win2K|Win32
diff --git a/sfall/ddraw.vcxproj b/sfall/ddraw.vcxproj
index 5eda34f9..612708ec 100644
--- a/sfall/ddraw.vcxproj
+++ b/sfall/ddraw.vcxproj
@@ -5,6 +5,10 @@
Debug
Win32
+
+ DevXP
+ Win32
+
Release
Win32
@@ -26,6 +30,12 @@
true
v100
+
+ DynamicLibrary
+ NotSet
+ true
+ v100
+
DynamicLibrary
NotSet
@@ -44,6 +54,9 @@
+
+
+
@@ -57,12 +70,16 @@
$(Configuration)\
true
$(SolutionDir)$(Configuration)\
+ $(SolutionDir)$(Configuration)\
$(SolutionDir)$(Configuration)\
$(Configuration)\
+ $(Configuration)\
$(Configuration)\
false
+ false
false
true
+ true
false
@@ -147,6 +164,54 @@
"$(ProjectDir)postbuild.cmd" release "$(TargetPath)"
+
+
+ Full
+ AnySuitable
+ true
+ Speed
+ true
+ true
+ INITGUID;WIN32;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+ Sync
+ MultiThreaded
+ false
+ NotSet
+ Fast
+ false
+ false
+ Use
+ Level3
+ ProgramDatabase
+ Cdecl
+ stdafx.h;%(ForcedIncludeFiles)
+ true
+ false
+
+
+ kernel32.lib;user32.lib;d3d9.lib;d3dx9.lib;Strmiids.lib;dinput.lib;ws2_32.lib;%(AdditionalDependencies)
+ $(OutDir)$(ProjectName).dll
+ %(IgnoreSpecificDefaultLibraries)
+ exports.def
+ ws2_32.dll;d3d9.dll;d3dx9_43.dll;%(DelayLoadDLLs)
+ false
+ Console
+ true
+ true
+
+
+ false
+ false
+
+
+ MachineX86
+ false
+
+
+ "$(ProjectDir)postbuild.cmd" devxp "$(TargetPath)"
+
+
Full
@@ -307,6 +372,7 @@
Create
+ Create
Create
Create