Jump to content

Coding - killing mobs penalty


Recommended Posts

So I am making my character and I wanted for him to have something like Wormwood, but instead of losing sanity if nearby plants/flowers/trees get destroyed I wanted to lose sanity when the specified mobs(hounds{all kind, besides "horror hounds"}) gets killed nearby him.

Also I wanted to know if character tag     inst:AddTag("houndfriend")     is including all the hounds(normal/red hounds/blue hounds) or just normal hounds, and in this new update for DST they added "horror hounds" I wanted for them to stay hostile to my character.

Link to comment
Share on other sites

You can find out a lot by just searching for the tag "houndfriend". It appears in the retargetfn function in hound.lua, which is used by all hounds for finding targets. Only exception is the moon_hound, which uses the moon_retargetfn function, but that, too, makes an exception for entities with the "houndfriend" tag. Looking at the bottom of the hound.lua file, you can see which hounds are affected.

Prefab("hound", fndefault, assets, prefabs),
Prefab("firehound", fnfire, assets, prefabs),
Prefab("icehound", fncold, assets, prefabs),
Prefab("moonhound", fnmoon, assets, prefabs_moon),
Prefab("clayhound", fnclay, assets_clay, prefabs_clay),
Prefab("mutatedhound", fnmutated, assets, prefabs),

 

To solve your problem of giving your character a penalty whenever something dies in their vicinity, there are some different ways to go about it, but since the health-component actually pushes an event, "entity_death", whenever anything with a health-component dies, you can just listen for that event, and use the data being passed by that event to do any checks you want. You get the dying entity, the cause (usually just a string), and the entity that afflicted the killing blow. You can then do a FindEntities call with a certain radius, looking specifically for entities with the "player" tag or even better a tag unique to your character, and then apply whatever penalty you want to all the instances found that are your character.

Link to comment
Share on other sites

@Ultroman I don't know why, but you are always on my posts... it's not that I don't like it but, thanks for your help... So I am trying to do the code but I am almost sure that it will not work

 

local WATCH_WORLD_HOUNDS_DIST_SQ = 20 * 20

local function SanityRateFn(inst, dt)
    local amt = 0
    for i = #inst.houndpenalties, 1, -1 do
        local v = inst.houndpenalties
        if v.t > dt then
            v.t = v.t - dt
        else
            table.remove(inst.houndpenalties, i)
        end
        amt = amt + v.amt
    end
    return amt
end

local function DoKillHoundPenalty(inst, penalty, overtime)
    if overtime then
        table.insert(inst.houndpenalties, { amt = -penalty / SANITY_DRAIN_TIME, t = SANITY_DRAIN_TIME })
    else
        while #inst.houndbonuses > 0 do
            table.remove(inst.houndbonuses)
        end
        inst.components.sanity:DoDelta(-penalty)
        inst.components.talker:Say(GetString(inst, "ANNOUNCE_KILLEDHOUND"))
    end
end

local function CalcSanityMult(distsq)
    distsq = 1 - math.sqrt(distsq / WATCH_WORLD_HOUNDS_DIST_SQ)
    return distsq * distsq
end

local function WatchWorldHounds(inst)
    if inst._onhoundkilled == nil then
        inst._onhoundkilled = function(src, data)
            if data == nil then
            elseif data.doer == inst then
                DoKillHoundPenalty(inst, data.workaction ~= nil and data.workaction ~= ACTIONS.DIG and TUNING.SANITY_MED or TUNING.SANITY_TINY)
            elseif data.pos ~= nil then
                local distsq = inst:GetDistanceSqToPoint(data.pos)
                if distsq < WATCH_WORLD_HOUNDS_DIST_SQ then
                    DoKillHoundPenalty(inst, CalcSanityMult(distsq) * TUNING.SANITY_SUPERTINY * 2, true)
                end
            end
        end
        inst:ListenForEvent("houndkilled", inst._onhoundkilled, TheWorld)
    end
end

local function StopWatchingWorldHounds(inst)
    if inst._onhoundkilled ~= nil then
        inst:RemoveEventCallback("houndkilled", inst._onhoundkilled, TheWorld)
        inst._onhoundkilled = nil
    end
end

 

I originally took this code from wormwood, so I have no clue if it will work but as far as I tried to do it my self I don't know what to replace ACTIONS.DIG    

 

And back to hounds... If I understood correctly... ALL hounds that are in this hound.lua file will be affected by tag "houndfriend"... If so could you make a specific hound stay hostile to you? etc. moon hound, clay hound, and mutated hound still be hostile to you with houndfriend tag

Edited by Veketh
Link to comment
Share on other sites

Ehm, there's no event called "houndkilled". Where do you get that from?

You've already done a lot of work here, so I'll fix up your code for you. It looks like you're trying to only make the hound deaths count if your character is the one killing them, is that correct? I thought you wanted your character to get a penalty whenever a hound died near him, regardless of whether he was the one killing them.

Link to comment
Share on other sites

Sorry for making you wait... and yes I wanted to get a penalty whenever a hound died near him but I don't really know how to do that from scrap so I used wormwood as a base, but as you can see I didn't get what I was expected. 

I want that if any hound dies near my character then he receives sanity penalty. If it was possible I wanted a different amount for every hound but that will come next when I am done with the basics.

Edited by Veketh
Link to comment
Share on other sites

local WATCH_WORLD_HOUNDS_DIST_SQ = 20 * 20

-- A nice little function for checking whether an object is in a list.
-- First parameter is your list, and the second parameter is the thing you're checking for.
-- It returns true as soon as it finds the thing, or false if it doesn't find the thing.
function contains(list, x)
	for _, v in pairs(list) do
		if v == x then return true end
	end
	return false
end

local entitiesThatYieldPenalty = {
	"hound",
	"firehound",
	"icehound",
	"clayhound",
	"mutatedhound",
}

local function ApplyHoundPenalty(inst, data)
	-- If you look up where "entity_death" is pushed with a PushEvent call,
	-- you'll see that data contains:
	-- inst = self.inst, cause = cause, afflicter = afflicter
	-- So, inst is the dead entity. You don't really care about the others.
	-- We check our list of hounds that count, and if the victim's prefab is one of those,
	-- we apply our penalty.
	if data and data.inst and contains(entitiesThatYieldPenalty, data.inst.prefab) then
		-- There is a built-in proximity function called IsNear, so we just use that.
		-- We call it on the player (inst) and ast if the dead hound (data.inst) is within our range.
		if inst:IsNear(data.inst, WATCH_WORLD_HOUNDS_DIST_SQ) then
			inst.components.sanity:DoDelta(5)
		end
	end
end

-- Put these lines into your character prefab Lua, inside the master_postinit function.
-- All of the above goes outside any of the functions, and above the master_postinit function.
-- The inst we pass into ApplyHoundPenalty is our player's own inst, which is available within
-- master_postinit, and the data is simply passed on from the event listener parameters.
inst._onentitydeathfn = function(src, data) ApplyHoundPenalty(inst, data) end
inst:ListenForEvent("entity_death", inst._onentitydeathfn, TheWorld)

 

Edited by Ultroman
Link to comment
Share on other sites

Thank you so much for your help... I know you did a lot for me, but I would like to know how to make that my character is being wet and burn longer... Like when it's raining, I want him to stay wet longer... and when he's on fire, I want for that fire to least longer on him.

Link to comment
Share on other sites

inst.components.moisture.maxDryingRate =(your choice of value) -- this is for him staying wet longer

fire damage seems not to have a specific component for it so it might be harder, it's located in the health component tho so if you wish to try to create your component you should start there

 

Link to comment
Share on other sites

I tried out the code and I forgot that my character is still frightened by monsters... can I do that he is not scared by hounds?

32 minutes ago, thomas4845 said:

no prob it's cool

ACTUALLY              can i see it when it's done UwU

 

@thomas4845 Oh, and sorry didn't saw that text below... you mean my character?

Link to comment
Share on other sites

@thomas4845

34 minutes ago, thomas4845 said:

    inst.components.sanityaura.aurafn = CalcSanityAura

local function CalcSanityAura(inst, observer)
    return observer:HasTag("character tag") and 0 or inst.components.sanityaura.aura
end

add that to hounds

Hmm, I don't really know if I am doing something wrong or it's just this code... I tried to put this code but first thing: I have no idea with you saying "add that to hounds" and second when I put code into my character's the game crashed with an error that said it couldn't find sanityaura or something like that.

I assume in "character tag" I suppose to put in MY CHARACTER'S tag so I did it, but I don't know why it doesn't work ;-;

Link to comment
Share on other sites

You should rather extend the existing aurafn on the hounds instead of overwriting it. Granted, the hounds do not have an aurafn, but you don't know whether another mod adds one, so for added compatibility we want to make sure to call any existing aurafn in the event that it's not your character. This also works for DST. Add this to your modmain.lua

local entitiesThatShouldGiveCharacterNoSanityAura = {
	"hound",
	"firehound",
	"icehound",
	"moonhound",
	"clayhound",
	"mutatedhound",
}

for i,v in ipairs(entitiesThatShouldGiveCharacterNoSanityAura) do
	AddPrefabPostInit(v, function(inst)
		local origAura = inst.components.sanityaura.aurafn
		local function CalcSanityAura(inst, observer)
			return observer:HasTag("character tag") and 0 or origAura ~= nil and origAura(inst, observer) or inst.components.sanityaura.aura
		end
		
		inst.components.sanityaura.aurafn = CalcSanityAura
	end)
end

 

Edited by Ultroman
Link to comment
Share on other sites

For the fire damage lasting longer, you can actually prolong it quite easily. Put this in your character prefab's Lua in the master_postinit.

local origDoFireDamage = inst.components.health.DoFireDamage
local function DoFireDamage(self, amount, doer, instant, ...)
	origDoFireDamage(self, amount, doer, instant, ...)
	self.lastfiredamagetime = self.lastfiredamagetime + 1.0
end

inst.components.health.DoFireDamage = DoFireDamage

The over-time fire damage is stopped by the health-component's OnUpdate when it has been longer than the local (and therefore unmoddable variable, unless employing Upvalue Hacker) FIRE_TIMEOUT variable, which is set to 0.5 seconds. This is checked against the lastfiredamagetime variable, which is set to the current time whenever a fire damage is started. The code above moves the set start-time forward by 1.0 seconds, which makes the fire last 1.5 seconds instead of 0.5 seconds.

Oops, just fixed the code.

Edited by Ultroman
Link to comment
Share on other sites

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
 Share

×
  • Create New...