roro88216 Posted July 12, 2021 Share Posted July 12, 2021 I make a custom follower, she is working good in a normal world. But, if the world has a cave, she can't talk anymore. I think inst.components.talker:Say code is not working in cave world. this is my code local brain = require "brains/summonayamibrain" local prefabs = { "ririsu", "statue_transition_2", "nesan1", } local function OnSave(inst, data) end local function OnLoad(inst, data) end SetSharedLootTable('ayami', { {"nesan1", 1.000}, }) local function linktoplayer(inst, player) inst.persists = false inst._playerlink = player player.summonayami = inst -- no idea player.components.leader:AddFollower(inst, true) for k, v in pairs(player.blaster) do k:Refresh() end end local function ShouldAcceptItem(inst, item) local currenthealth = inst.components.health.currenthealth / inst.components.health.maxhealth if item.components.edible and (item.components.edible.foodtype == FOODTYPE.MEAT or item.components.edible.foodtype == FOODTYPE.VEGGIE or item.components.edible.foodtype == FOODTYPE.GOODIES)then return true end if item.components.equippable and (item.components.equippable.equipslot == EQUIPSLOTS.HEAD or item.components.equippable.equipslot == EQUIPSLOTS.HANDS or item.components.equippable.equipslot == EQUIPSLOTS.BODY) and not item.components.projectile then if item.prefab == "batbat" then print("refusing batbat") return false end return true end end local function OnGetItemFromPlayer(inst, giver, item) if item.components.equippable and (item.components.equippable.equipslot == EQUIPSLOTS.HEAD or item.components.equippable.equipslot == EQUIPSLOTS.HANDS or item.components.equippable.equipslot == EQUIPSLOTS.BODY) then local newslot = item.components.equippable.equipslot local current = inst.components.inventory:GetEquippedItem(newslot) if current then inst.components.inventory:DropItem(current) end inst.components.inventory:Equip(item) elseif item.components.edible then inst:PushEvent("oneatsomething", {food = item}) end end local function OnRefuseItem(inst, item) inst.sg:GoToState("refuse") inst.components.talker:Say("I don't need this") end local function NormalRetargetFn(inst) return FindEntity(inst, TUNING.PIG_TARGET_DIST, function(guy) return guy:HasTag("monster") and guy.components.health and not guy.components.health:IsDead() and inst.components.combat:CanTarget(guy) end, nil, { "character" }, nil) end local function OnAttacked(inst, data) local attacker = data.attacker inst.components.combat:SetTarget(attacker) inst.components.combat:ShareTarget(attacker, 30, function(dude) return dude:HasTag("summonedbyplayer") and dude.components.follower.leader == inst.components.follower.leader end, 5) end local function OnAttackOther(inst, data) local target = data.target inst.components.combat:ShareTarget(target, 30, function(dude) return dude:HasTag("summonedbyplayer") and dude.components.follower.leader == inst.components.follower.leader end, 5) end local function spearfn(inst) return inst end local function MakeMinion(prefab, master_postinit) local assets = { Asset("ATLAS", "images/inventoryimages/summonayami.xml"), Asset("ANIM", "anim/ayami.zip"), Asset("ANIM", "anim/player_boat_jump.zip"), Asset("ANIM", "anim/player_boat_jumpheavy.zip"), } local function fn() local inst = CreateEntity() inst.entity:AddTransform() inst.entity:AddAnimState() inst.entity:AddMiniMapEntity() inst.entity:AddSoundEmitter() inst.entity:AddDynamicShadow() inst.entity:AddNetwork() MakeCharacterPhysics(inst, 75, .5) inst.DynamicShadow:SetSize(1.3, .6) inst.Transform:SetFourFaced() inst.Transform:SetScale(1, 1, 1) inst.AnimState:SetBank("wilson") inst.AnimState:SetBuild("ayami") inst.AnimState:PlayAnimation("idle_loop", true) inst.AnimState:Hide("ARM_carry") inst.AnimState:Show("ARM_normal") inst.MiniMapEntity:SetIcon("summonayami.tex") inst.MiniMapEntity:SetPriority(9) inst:AddTag("character") inst:AddTag("summonayami") inst:AddTag("sheltercarrier") inst:AddTag("summonedbyplayer") inst:AddTag("ayami") inst:AddTag("girl") inst:AddTag("nesan") inst:AddTag("debuffable") inst:AddComponent("talkerex") inst:AddComponent("talker") inst.entity:SetPristine() if not TheWorld.ismastersim then return inst end MakeMediumBurnableCharacter(inst, "pig_torso") inst:AddComponent("ayamicracker") inst:AddComponent("ayamisleep") inst:AddComponent("ayamihungry") inst:AddComponent("combat") inst.components.combat:SetDefaultDamage(10) inst.components.combat:SetAttackPeriod(2) inst.components.combat:SetRetargetFunction(3, NormalRetargetFn) local self = inst.components.combat local old = self.GetAttacked function self:GetAttacked(attacker, damage, weapon, stimuli) if attacker and (attacker.prefab == "tentacle" or attacker:HasTag("player")) then return true end return old(self, attacker, damage, weapon, stimuli) end inst:AddComponent("follower") inst.components.follower:KeepLeaderOnAttacked() inst.components.follower.keepdeadleader = true inst.components.follower.keepleaderduringminigame = true inst:AddComponent("followersitcommand") inst:AddComponent("health") inst.components.health:SetMaxHealth(150) inst.components.health:StartRegen(1, 10) inst.components.health.fire_damage_scale = 0 --inst.components.health.absorb = 0.35 inst:AddComponent("inspectable") inst:AddComponent("debuffable") inst:AddComponent("hunger") inst.components.hunger:SetMax(60) inst.components.hunger.hungerrate = 0.25 * TUNING.WILSON_HUNGER_RATE inst.components.hunger:SetKillRate(TUNING.WILSON_HEALTH / TUNING.STARVE_KILL_TIME) inst:AddComponent("crittertraits") inst:AddComponent("timer") inst:AddComponent("eater") inst.components.eater:SetDiet({FOODGROUP.OMNI}, {FOODGROUP.OMNI}) inst:AddComponent("inventory") inst:AddComponent("locomotor") inst.components.locomotor.runspeed = 7 inst.components.locomotor.walkspeed = 5 -- boat hopping setup inst.components.locomotor:SetAllowPlatformHopping(true) inst:AddComponent("embarker") inst.components.embarker.embark_speed = inst.components.locomotor.runspeed inst.components.locomotor.pathcaps = { allowocean = false } inst:AddComponent("drownable") inst:AddComponent("lootdropper") inst.components.lootdropper:SetChanceLootTable('ayami') inst:AddComponent("trader") inst.components.trader:SetAcceptTest(ShouldAcceptItem) inst.components.trader.deleteitemonaccept = false inst.components.trader.onaccept = OnGetItemFromPlayer inst.components.trader.onrefuse = OnRefuseItem inst.components.trader:Enable() inst:ListenForEvent("equip", function() inst.AnimState:Show("hair") end) inst.cangroundpound = false inst.OnSave = OnSave inst.OnLoad = OnLoad inst:SetBrain(brain) inst:SetStateGraph("SGsummonayami") inst:WatchWorldState("startnight", function() inst.components.health:DoDelta(0) end) inst:ListenForEvent("attacked", OnAttacked) inst:ListenForEvent("onattackother", OnAttackOther) inst:AddTag("companion") inst.LinkToPlayer = linktoplayer return inst end return Prefab("common/summonayami", fn, assets, prefabs) end -------------------------------------------------------------------------- local function NoHoles(pt) return not TheWorld.Map:IsPointNearHole(pt) end local function onbuilt(inst, builder) local theta = math.random() * 2 * PI local pt = builder:GetPosition() local radius = math.random(3, 6) local offset = FindWalkableOffset(pt, theta, radius, 12, true, true, NoHoles) if offset ~= nil then pt.x = pt.x + offset.x pt.z = pt.z + offset.z end builder.components.petleash:SpawnPetAt(pt.x, 0, pt.z, inst.pettype) inst:Remove() end local function MakeBuilder(prefab) --These shadows are summoned this way because petleash needs to --be the component that summons the pets, not the builder. local function fn() local inst = CreateEntity() inst.entity:AddTransform() inst:AddTag("CLASSIFIED") --[[Non-networked entity]] inst.persists = false --Auto-remove if not spawned by builder inst:DoTaskInTime(0, inst.Remove) if not TheWorld.ismastersim then return inst end inst.pettype = "summonayami" inst.OnBuiltFn = onbuilt return inst end return Prefab(prefab.."_builder", fn, nil, { "summonayami" }) end -------------------------------------------------------------------------- return MakeMinion("summonayami", spearfn), MakeBuilder("summonayami") Link to comment https://forums.kleientertainment.com/forums/topic/131779-my-custom-follower-cant-talk-in-a-cave-world/ Share on other sites More sharing options...
CarlZalph Posted July 12, 2021 Share Posted July 12, 2021 The talker component is existing on the client, but the trader component does not, so it won't fire off the talker's say in the onrefuseitem callback. However, Klei has a wrapper function to make the string sent networked by having the talker component be a chatter type: inst.components.talker:MakeChatter() Doing this will handle the netvars for you. 1 Link to comment https://forums.kleientertainment.com/forums/topic/131779-my-custom-follower-cant-talk-in-a-cave-world/#findComment-1478098 Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now