16:28:38 8 July 2007 |
|
NatVac
Senior Resident
On forum: 06/15/2007
Messages: 3579
|
Treasure Manager Hack to Reduce Stash Spam
When you save and then reload the saved game, the game engine remembers the spots, but the script engine doesn't (so to speak), so you get the same novice bandit secrets all over again. This means that you get the same "A good place"* secret with three medkits over and over on the beginning Escape level, or the "Drunkard's backpack" secret with the 10 bottles of vodka in Agroprom, over and over. If you don't clear the stashes, you get a really laggy game after a bit, with long freezing pauses.
The best answer to this is a persistent treasure manager like the one implemented in bardak's patch, but it does involve changes to three different files and it renders any save-games that use it incompatible with future changes/patches.
Here's a workaround for either patch 1.0001 or patch 1.0003 to keep stashes from becoming overpopulated. It works by keeping the script engine in sync with the game engine. Save-games are not affected by this change.
In new games, or for new secrets in current games, it should also fix that annoyance whereby you remove the items from a stash, but the stash marker stays. (The workaround if it doesn't in older marked stashes is to keep putting an item in the stash and then taking it out until the spot goes away.)
Drawback: Once you remove all from a stash, the marker is removed. A reload of a game saved after the marker is removed doesn't know not to use the stash again. But you will still get it only once each time after cleaning out the stash. You can exploit this by not completely clearing junk stashes (leave the marker) and clearing cool stashes...
In gamedata\scripts\treasure_manager.script, at the end of the function CTreasure:__init(), change this code:
self.treasure_by_target = {}
for k,v in pairs(self.treasure_info) do
self.treasure_by_target[v.target] = k
end
to this:
self.treasure_by_target = {}
if alife ~= nil then
for k,v in pairs(self.treasure_info) do
self.treasure_by_target[v.target] = k
local obj = alife():story_object(v.target)
if obj ~= nil then
if tonumber(level.map_has_object_spot(obj.id, "treasure" )) > 0 then
v.done = true
end
end
end
else
for k,v in pairs(self.treasure_info) do
self.treasure_by_target[v.target] = k
end
end
How it works: If there's a spot, the secret associated with it is marked "done" during the game load. This is the part that's forgotten when a game is saved/reloaded.
While this is not optimized code, I don't think you'll have any trouble with it.
*Most of the time when they say "cellar" in the English translation, they mean the attic. |
03:04:56 10 July 2007 |
|
NatVac
Senior Resident
On forum: 06/15/2007
Messages: 3579
|
Feedback is welcomed.
I've been playing with this for a couple of days now, and I have a couple of observations myself:
1) If you get a stash secret you know you've seen before, you really aren't getting the same secret unless you've cleared out that stash in a previous save. Some stashes have the same name, at least in the English translation. For example, "Secret stash" is used for nine stashes, while "Secret stash under the cross" names six different stashes.
2) If you do not completely clear stashes*, you will get more stashes than you ever saw before. Previously, this was only true if you played non-stop; reloading a saved game meant getting the same beginning secrets again.
I think the game devs intended you to find each secret only once, but the persistence stuff doesn't work as of version 1.0003. This meant you could get the first bandit secret 10 times while never getting the last.
*Tip: The stash marker remains if the stash is not completely emptied. To reduce list-processing lag even further, you can put a useless item in the stash, then remove the rest, or take all but one item. |
15:14:21 10 July 2007 |
|
NatVac
Senior Resident
On forum: 06/15/2007
Messages: 3579
|
Ceano, what changes in what ltx file? This change is only to the script file; I think that's what you meant.
What error message? The "attempt to index global 'treasure_manager' (a nil value)" message is usually due to a syntax error, as D_akbar found out.
This code block is meant to replace the four lines shown, at the end of the CTreasure:__init() function, but that does not include the closing "end" of the function itself. When the replacement is done, there are three "end" statements in a row, before the comment that separates the CTreasure:__init() function from the function CTreasure:use(npc) that follows.
Now I know you have a lot of other modifications in your stuff, Ceano. But I wouldn't think this change would be affected by anything else out there except for other persistent treasure manager code like that in bardak's patch, which already (as I pointed out in the original post) fixes the problem. If that's the case, you don't need this patch.
If that's not the case: What is in the treasure_manager.script file you are using that's different from the 1.0001/1.0003 file? |
09:43:51 11 July 2007 |
|
NatVac
Senior Resident
On forum: 06/15/2007
Messages: 3579
|
D_akbar's right; it is easy to replace one "end" too many. And I can't edit the original post to make it clearer. So here is a repost of the critical section with clarifications:
In gamedata\scripts\treasure_manager.script, at the end of the function CTreasure:__init(), replace this code block:
self.treasure_by_target = {}
for k,v in pairs(self.treasure_info) do
self.treasure_by_target[v.target] = k
end
end
--' Þçàíèå èíèöèàòîðà (âîçìîæíîñòü âûäàòü òàéíèê)
with this code block:
self.treasure_by_target = {}
if alife ~= nil then
for k,v in pairs(self.treasure_info) do
self.treasure_by_target[v.target] = k
local obj = alife():story_object(v.target)
if obj ~= nil then
if tonumber(level.map_has_object_spot(obj.id, "treasure" )) > 0 then
v.done = true
end
end
end
else
for k,v in pairs(self.treasure_info) do
self.treasure_by_target[v.target] = k
end
end
end
--' Þçàíèå èíèöèàòîðà (âîçìîæíîñòü âûäàòü òàéíèê)
I hope that helps make it easier to implement. |
|