Jump to content

Recommended Posts

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")
 

 

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.

  • Like 1

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...