Archived

This topic is now archived and is closed to further replies.

Please be aware that the content of this thread may be outdated and no longer applicable.

RageLeague

[Suggestion] Custom negotiation behaviour for special negotiations

Recommended Posts

RageLeague    1485

Right now, there's a bunch of special negotiation with unique negotiation patterns. For example, the auction negotiation, the weakness negotiation against Flekfis or Arint, and vix's negotiation. I'm not counting the ones that are just modifying the base negotiation behaviour of a character, like the existential crisis negotiation against the assassin or the ally grab negotiations when dealing with the flead queen or bossbit.

These negotiations are defined on the character you are negotiating with, and thus, the behaviour is tied to the character. If you negotiate with another character, the behaviour obviously isn't working as intended. However, a bigger problem comes when you try to reuse the character in a side quest, whether for a base game or for a mod. In that case, you get this very unbalanced negotiation that also doesn't make much sense.

An existing workaround is the weakness negotiation tied to Arint and Flekfis. The game decides that they get the regular negotiation behaviour when they are negotiated during a side quest and they get the weakness behaviour during the day 3 boss fight. However, the trigger for this is rather arbitrary, as it checks whether NEGOTIATION_FLAGS.NO_CORE_RESOLVE is true. You can see why it could lead to other problems when a special negotiation gives NEGOTIATION_FLAGS.NO_CORE_RESOLVE to the negotiation.

When I made my mod, I made a workaround patch, which is this:

Spoiler

--[[
    NEGOTIATOR_ALLOW_TEMP_BEHAVIOUR:
    Addendum to existing negotiatior initialization.
    If an agent has temp_negotiation_behaviour defined, will instead use that behaviour instead of the usual
    behaviour.
    An agent's temp_negotiation_behaviour is cleared once intialized.
    This allows for special scenarios when you want a different behaviour for an agent's usual behaviour
--]]
local patch_id = "NEGOTIATOR_ALLOW_TEMP_BEHAVIOUR"
if rawget(_G, patch_id) then
    return
end
rawset(_G, patch_id, true)
print("Loaded patch:"..patch_id)
-- print(Negotiation.Negotiator)
local old_init = Negotiation.Negotiator.InitBehaviour
Negotiation.Negotiator.InitBehaviour = function(self)
    if self.agent.temp_negotiation_behaviour then
        local enc = TheGame:GetGameState():GetCaravan():GetCurrentEncounter()
        local temp_enc = self.agent.temp_negotiation_behaviour.current_encounter
        if temp_enc == nil or enc == temp_enc then
            self.behaviour = NegotiationBehaviour( self, self.agent.temp_negotiation_behaviour )
            self.agent.temp_negotiation_behaviour = nil
            return
        else
            self.agent.temp_negotiation_behaviour = nil
        end
        
    end
    return old_init(self)
end

function Agent:SetTempNegotiationBehaviour(data, enc)
    self.temp_negotiation_behaviour = shallowcopy(data)
    -- added an encounter check so that if you exit from current encounter, the temp behaviour won't work
    self.temp_negotiation_behaviour.current_encounter = enc or TheGame:GetGameState():GetCaravan():GetCurrentEncounter()
end

(If you are interested, you can copy the code. The usage is something like this: cxt:GetAgent():SetTempNegotiationBehaviour(CUSTOM_BEHAVIOUR))

It assign a temporary negotiation behaviour to an agent for the current encounter. This is the best I can do to make as little change to the game's code with the modding system. It works perfectly fine, but it is not exactly foolproof. It must be called before the negotiation starts for it to take effect, but is separate from the negotiation function. It will fail if you call it, but the user selects a different negotiation option that does not want the special behaviour.What I would do to change this behaviour if I can directly modify the base game source code is something like this(It is a bad practice to completely replace game functions, as it leads to incompatibility issues):

Spoiler



function MiniGame:init( start_params, caravan )
    --- ...
    self.player_negotiator:InitBehaviour()
    self.opponent_negotiator:InitBehaviour(start_params.custom_negotiation_behaviour)
    --- ...
end

And modify


function Negotiator:InitBehaviour(custom_behaviour)
    if custom_behaviour then
        self.behaviour = NegotiationBehaviour( self, custom_behaviour )
    elseif self.agent.negotiation_data and self.agent.negotiation_data.behaviour then
        self.behaviour = NegotiationBehaviour( self, self.agent.negotiation_data.behaviour )
    else
        self.behaviour = NegotiationBehaviour( self, table.empty )
    end
end


 

This has a lot of benefits. Custom negotiations doesn't need to be tied to a specific character anymore, so characters can retain their existing negotiation patterns, while still having them have special patterns during special negotiations. Vixmalli no longer overwhelms you immediately if your mod requires you to negotiate with him on day 1. Mods can go ham with special negotiation behaviours without worrying about modifying the behaviours of existing characters, and base game can make crazy behaviours without worrying about the balancing of that character's negotiation behaviour in a normal scenario.

You can probably do the same with combat, but combat is more nuanced, as you can have multiple enemies with different behaviours. For negotiations, you are always going to be negotiating with exactly one person with the current game system, so the modification is probably easier to do.

Share this post


Link to post
Share on other sites