Jump to content

Recommended Posts

Hi all,

I'm trying to get a prefab to trigger a "talker:say" command on client side, although the text will not appear when the prefab calls upon it for anyone other than the host (usually the case for most network issues though). 

The following code is hooked onto the reward factor of the trader component:

	giver.AnimState:OverrideMultColour(1, 0.65, 0.058, 1)
	giver.components.talker:Say("Text",1)

I'm really trying to expand my understanding into how client/network relationships work precisely (and what implementation methods I can get away with), although nothing has quite "cracked" it for me.

Link to comment
https://forums.kleientertainment.com/forums/topic/79565-client-side-talkersay/
Share on other sites

The giver will always have a talker component (it's the player) and works fine for the host, the problem might come from the fact that the code handling the giver only exists as part of the prefab that is initialised after the "not world" return.

Here's some expanded code:

  Hide contents

----
-- Tag on functions for trader component
----

local function OnGetItemFromPlayer(inst, giver, item)

	local x,y,z = giver.Transform:GetWorldPosition()
	local atk_pwr = giver.components.combat.damagemultiplier -- succeeds on read
	
	-- Delay trader
	inst.components.trader:Disable()
	if inst.signal ~= nil then -- let's ensure we aren't constantly looping for 4 minutes
		inst.signal:Cancel()
		inst.signal = nil
	end
	
	-- fx
	giver.SoundEmitter:PlaySound("dontstarve/common/fireBurstSmall")
	SpawnPrefab("firesplash_fx").Transform:SetPosition(x,y,z)
    -- point of failure for client
		giver.AnimState:OverrideMultColour(1, 0.65, 0.058, 1)
		giver.components.talker:Say("* Placeholder *",1, true, true, true, {1, 0.65, 0.058, 1})
    -- point of failure for client

	--[[ -- sending the task doesn't seem to work (maybe this function isn't getting through to client?)
	giver:DoTaskInTime(0, function(inst)
		inst.AnimState:OverrideMultColour(1, 0.65, 0.058, 1)
		inst.components.talker:Say("* FURY * ",1, true, true, true, {1, 0.65, 0.058, 1})
	end)
    ]]
	
	-- bonus
	giver.components.combat.damagemultiplier = atk_pwr * 1.5
	
	-- return to normal
	inst:DoTaskInTime(120, function(inst)
		giver.AnimState:OverrideMultColour(1, 1, 1, 1) -- This fails on client.
		giver.components.combat.damagemultiplier = atk_pwr -- This works on client.
		inst:DoTaskInTime(120, function(inst) -- 4 minutes cooldown
			inst.components.trader:Enable()
			inst.signal = inst:DoPeriodicTask(2 + 3 * math.random(), readySign) -- reset ready animation
		end)
	end)
end

local function OnRefuseItem(inst, giver, item)
	-- This fails on client.
	giver.components.talker:Say(ANNOUNCE_FREJECT[math.random(#ANNOUNCE_FREJECT)],3, true, true, true)
end

----
-- Prefab structure, Main fn
----
local function fn()
    local inst = CreateEntity()
	
    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddSoundEmitter()
    inst.entity:AddMiniMapEntity()
    inst.entity:AddNetwork()

    MakeObstaclePhysics(inst, 1.5)

	inst:AddTag("structure")
	inst:AddTag("boulder") -- allows world bosses to destroy/work on contact
	inst:AddTag("isObeliskMagic")
	
    inst.MiniMapEntity:SetIcon("obelisk.png")
	
	inst.AnimState:SetBank("fire_obelisk")
    inst.AnimState:SetBuild("fire_obelisk")
    inst.AnimState:PlayAnimation("Construction")
    inst.AnimState:PushAnimation("Idle")
	
	-- ^ this does the same on each client
	inst.entity:SetPristine()
	
	-- based in world
    if not TheWorld.ismastersim then
        return inst
    end
	
    -- Destruction related
	inst:AddComponent("lootdropper")
    inst:AddComponent("workable")
    
	-- Can be examined
    inst:AddComponent("inspectable")

	inst:AddComponent("trader")
    inst.components.trader:SetAcceptTest(AcceptTest)
    inst.components.trader.onaccept = OnGetItemFromPlayer
    inst.components.trader.onrefuse = OnRefuseItem
	
	-- Indicate ready
	inst.signal = inst:DoPeriodicTask(2 + 3 * math.random(), readySign)
	
	-- Check for specials
	inst:ListenForEvent("OnHit", DoInferno)
	inst:ListenForEvent("OnHitFinal", DoInferno)
	inst:WatchWorldState("issummer", OnIsSummer)
		
    return inst
end

 

I've investigated quite a few things,  but I'll look at the pigman's file and stalker_atrium side to see if I cannot gather why I'm failing. Thank you for the response; lost hope here. T^T

Edited by MorickClive

before trying to understand your code, please elaborate a bit more what exactly you want to achieve.

You want a "trader" like the pigking, to say something when he gives you gold?

Or you want the player to say "thank you"?

Or what do you want?

And what exactly is the problem? It sound like the talker:say thing is executed only for client.
But why do you do that? Why can't you execute it at server?

The player gives and item to structure, the structure accepts the item and grants a "boon" by giving an additional power up on the player's attack. When the boon is applied, the player then remarks on the situation with a message and begins to take on an overlay colour effect. Once the 2 minutes are up, the player loses this boost and then returns to their default/unmodified graphic to represent the passing of the bonus.

So far the power attack increase works, the resetting of the attack power works and the trader being disabled and re-enabled works for both client and server.

I'm not 100% sure, but it could be related to what I found out in the following thread:
http://forums.kleientertainment.com/topic/75905-solved-how-to-get-rid-of-characters-text-on-examine/?do=findComment&comment=894716

Although the talking itself worked when executed only at server. But duration and colour of the text did not work for clients.
You could try the solution with netvars I wrote there, but at the moment I have no clue why not even the text appears, like in my tests...
Try it, and maybe it solves all problems :)

edit:
when you "set()" the netvar, the value of it will update on all clients too and the "OnDirtyEvent" function is called at client. So you could put the talker stuff in this "OnDirtyEvent" function.


And about your damage boost:
It is very critical to change damagemultiplier. Cause what if another mod changes this value, while your boost is active? The result will be total mess, if every mod changes it back to the "value before".
One solution would be to multiply the the damagemultiplier with 2 and after you boost is over, divide it by 2. That way it could also deal with other mods which changes the damagemultiplier the same way.

Edited by Serpens

I'm aware of the damage boost problem - it's something in the works, but it's rather pointless if the main purpose isn't met, I discovered it by curiously testing to see how two of these structures might work in conjunction. Thanks for pointing it out though!

It might be that the network component parts are triggering because the component supports client side, but when I access other data directly it ignores it for client because I've not added the net vars to push the events client side; I wasn't sure though so I asked if anyone might be able to help point it out. ^^'

--

I have written net vars to influence character specific talking before, it worked, however my issue was that I was controlling the text colour based on the value of the var I was passing(in a switch/case situation). I decided to remove it after noticing a surprising amount of lag during testing despite it being only a 3 bit message.

Something that always puzzled me with net vars is that it responds to change in data to trigger a dirty function, yet there doesn't seem to be much of a "just activate/trigger dirty" method. Not sure if I should just switch a boolean or some such to trigger it (but there must be a better way surely?).

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
  • Create New...