Decane / SRP

Sky Reclamation Project for S.T.A.L.K.E.R.: Clear Sky
http://www.moddb.com/mods/srp
119 stars 20 forks source link

Fixed sim_eliminate_resource_smart quest never activating #118

Closed SurDno closed 3 years ago

SurDno commented 3 years ago

In the original game, when the point to capture is target_resource_smart ('resource' or 'territory' points), the game is supposed to give the player a different quest that sim_eliminate_smart. It works fine with sim_eliminate_path_smart (which has a different name - "Clear the road" - and description - "Help the friendly squad get through"), however, for whatever reason, it does not work with sim_eliminate_resource_smart (which has the same name but a different description - "Chase the enemy away from the area. This will weaken him.")

This commit fixes that issue.

image

Decane commented 3 years ago

Nice one.

It works fine with sim_eliminate_path_smart [...] however, for whatever reason, it does not work with sim_eliminate_resource_smart

All eliminate_smart task sections are always written to CRandomTask.eliminate_smart_tasks in the order in which they appear in tm_sim.ltx. However, pairs iterates over the values in an arbitrary order in CRandomTask:select_task, which chooses one from among several possible task sections whose type is 'eliminate_smart' by iterating over table CRandomTask.eliminate_smart_tasks and finding the one with the highest 'prior' value (priority) whose target_cond is met. In my game, the iteration order of generic eliminate_smart task sections available from Clear Sky is:

sim_eliminate_path_smart sim_eliminate_smart sim_eliminate_resource_smart sim_eliminate_smart_csky sim_eliminate_path_smart_csky sim_eliminate_resource_smart_csky

In the case of a resource/territory smart which is not also a 'clear the road' target for the faction, the game would select sim_eliminate_smart here instead of sim_eliminate_resource_smart simply because the former is iterated over first and its target_cond is satisfied. OTOH, in the case of a 'clear the road' target, the game would select sim_eliminate_path_smart for the same reason.

However, there seems to be another bug hiding here: each of the above sections has the same 'prior' value in tm_sim.ltx, which means the first of them whose target_cond is satisfied becomes the task template used by the game.

In other words, given the iteration order above, Clear Sky would give the player the faction-agnostic sim_eliminate_path_smart for a 'clear the road' task instead of the faction-specific sim_eliminate_path_smart_csky which GSC likely intended.

I've made a note to fix this.

SurDno commented 3 years ago

Does that make my workaround useless, then?

Decane commented 3 years ago

Does that make my workaround useless, then?

Not at all. Your fix is still valid for making the game choose correctly between the three eliminate_smart sections within a faction-agnostic/-specific set. For example, suppose I fix the 2nd bug I described above. Then when the game considers which eliminate_task section to use for the Clear Sky faction, it would have to select from among:

sim_eliminate_smart_csky sim_eliminate_path_smart_csky sim_eliminate_resource_smart_csky

This is where your fix comes in.

SurDno commented 3 years ago

I misunderstood you then - your fix is not making these quests go in a specific order but rather still having them in an arbitrary order but excluding those that are not faction unique, right?

Decane commented 3 years ago

your fix is not making these quests go in a specific order but rather still having them in an arbitrary order but excluding those that are not faction unique, right?

Roughly, yes, although rather than my prospective fix "excluding" those that are faction-agnostic, I would instead say it will make the game systematically prefer the faction-specific ones over the faction-agnostic ones. Currently, the game prefers whichever Lua happens to iterate over first.

SurDno commented 3 years ago

I tested that 7 times with 7 different spots and every time I received reward for faction-agnostic quest (500 RU). Are you sure there is even a chance for the non-agnostic quest to appear?

Decane commented 3 years ago

I wasn't claiming that there is ever a chance for the faction-specific quest to appear. On the contrary, I was saying that the one that appears may consistently be the wrong one. Your experience supports this hypothesis, assuming your reward consisted only of the money and no items.

I edited my original https://github.com/Decane/SRP/pull/118#issuecomment-662022750 a few times to better explain the bug. You may wish to re-read it to gain a better understanding of the problem.

Anyway, this bug is now also fixed: https://github.com/Decane/SRP/commit/a956833c7da819331460bb99e018129600899252.

SurDno commented 3 years ago

Thanks for the explanation. Is there any need for those quests if the only time they are used in vanilla is due to a bug? Or are they here for the same reason device_pda exists - just so that the entries that are based on it/them do not have the same lines copied over and over?

Is it possible to tell without testing if the bug also always applied to other factions (I tested Clear Sky only) and other quests (I tested eliminate_smart only)?

Decane commented 3 years ago

Is there any need for those quests if the only time they are used in vanilla is due to a bug? Or are they here for the same reason device_pda exists - just so that the entries that are based on it/them do not have the same lines copied over and over?

They do serve the latter purpose and also act as a fallback for factions that don't have their own unique variants thereof, like the renegades and mercs. (I'm not sure if it's possible to take e.g. a 'capture' task via dialogue from renegades at the Swamps or from Leshiy's merc squad at the Red Forest after the bridge blitz.)

Is it possible to tell without testing if the bug also always applied to other factions (I tested Clear Sky only) and other quests (I tested eliminate_smart only)?

You could insert some debug code into task_manager.script to find out the order in which the game iterates over the various task type tables populated in CRandomTask:__init. In particular, you could add this loop to the end of the function:

local task_tables =
{
    self.general_tasks,
    self.eliminate_smart_tasks,
    self.capture_smart_tasks,
    self.defend_smart_tasks,
    self.defend_smart_delay_tasks,
    self.reward_tasks,
    self.bring_item_tasks,
    self.recover_item_tasks,
    self.find_upgrade_tasks,
    self.hide_from_surge,
--  self.eliminate_squad_tasks,
    self.inited_find_upgrade_tasks,
}

for i = 1, #task_tables do
    dbglog("Table %u:", i)
    for k, task in pairs (task_tables[i]) do
        dbglog(task.id) -- prints task section name to console
    end
end

I'm not sure the ordering this would reveal would persist into CRandomTask:select_task, though: none of the task type tables are mutated after they're populated, but I don't know enough about Lua's/LuaJIT's inner workings to say if mutation of a table is necessary for pairs to iterate over its hash part in a different order.

IIRC, NatVac once tested this for the array part and concluded that mutation is necessary for a change in pairs's traversal sequence of the array part. If the same applies to the hash part, then the debug code above would yield an accurate picture of the order in which the game selects from among possible task sections for a given task type.

Once you know the order, you can deduce which one would actually be selected by checking whether their target_cond is satisfied - the first such task section with the highest 'prior' in its table (several task sections in a table can be tied for this) would be selected by the game, provided it doesn't have a non-matching 'faction' entry.

SurDno commented 3 years ago

It's possible to take a capture quest from renegades but you can't receive any reward for it anyway. Not sure about Leshiy, but in vanilla it should never be possible because it's just once squad at the smart terrain. It might be possible in SRP due to the fact that you changed the requirements for the dialogue-taken Capture quest.