Jump to content

Creating an object with complicated unique effect


Recommended Posts

Hello there!

 

I'm new here, and I've been more than happy to discover The Getting Started topic to create a character, since it's something I really want to do since I tried Don't Starve. I'm on Mac, and apparently it's a problem to make characters (since the program used is only for windows it seems), but that's not really my first problem, strangely.

 

Actually, this is my character (based on myself, how original):

 

dont__starve___wrystan_by_zetrystan-d78q

 

The "object with complicated unique effect" his the camera. to make it, apparently, I can simply use a copy of a staff from the game... but there's two things that don't look easy to make: the visual effect and the actual effect on the game.

 

Here are two possibilities of the visual effect I was thinking about:

 

wrystan_power_1_by_zetrystan-d78yx0n.png

 

wrystan_power_2_by_zetrystan-d78ywxk.png

 

I seriously don't know if that's makable.

 

The actual effect is that the camera creates night time during the day, and daytime during the night, only for what is in it's view. With this, events from each specific time of the day can be generated (as making some creature fall asleep, getting the bats out of the cave, the mushrooms getting out of the ground, etc).

 

Am I dreaming about impossible things?  :spidercowers:

 

(Also, if someone willing to help me create the mod, I'll be more than happy to work with people. My mac is a traitor.)

Link to comment
Share on other sites

Wow - I mean, I know "day-for-night" shoots are much more viable than actual night scenes, but this is a little extreme! xD

 

I think this is a neat idea, and I'm almost certain it will be possible.

That said, I don't know how to do it, and I think it might be a fairly tricky thing.

I suggest looking at the mushrooms' code... since they alter depending on state of day, and otherwise shouldn't be very complex. So I'd wager it'll be easier to isolate day/night dependent code.

Link to comment
Share on other sites

As far I have seen most things,mobs etc sleep or makes other time based actions basing on events send by game like "nighttime" , "daytime" etc. So you could make your camera to  emit "fake" events on area of effect. Thats how I would try to do this. Ofcourse im not sure if that could work.

Link to comment
Share on other sites

It's probably possible but it'll take quite a bit of work.

In looking at the code a bit, you might be able to push a fake time of day event to specific entities like this:

-- inst: prefab to push the event to-- timeofday: either "day", "dusk", or "night"local function PushFakeTimeOfDayEventTo(inst, timeofday)    if inst.event_listening and inst.event_listening[timeofday.."time"] then        for entity, fns in pairs(inst.event_listening[timeofday.."time"]) do            for i,fn in ipairs(fns) do                print("sending fake "..timeofday.."time to "..tostring(inst))                -- need to send the same data that the normal event from clock.lua would                fn(inst, {day=GetClock().numcycles})            end        end    endend
If that works (I didn't test it), then you would just need to get a list of all the entities in the camera's viewport, and then make sure to push the appropriate fake event whenever an entity enters/leaves that viewport.

EDIT: Updated with tested/working function.

Link to comment
Share on other sites

Thanks for the quick replies!

 

Actually, I'm noticing there's a simple problem I wasn't thinking about: the power is useless if the character can't stop the camera for a moment to interact with what he changed. (for example, if he shoots a mushroom to get it out of the ground, the mushroom will go back in the ground as soon as the camera stops). If it possible to give to an effect a certain time of effect, so that when something changes because of the camera, it stays like that for a little moment even when the camera stops?

 

 

Hehe. Seriously, I'm starting to think my idea isn't simple. At ALL. Hehehe.

 

------

 

For the mushroom code, how can I get to it?

That's a great idea, since they are directly influenced by the time of day.

 

------

 

For the area of effect, would it possible to make one like the one on the second fake print-screen? I don't recall any other element of the game working that way...

 

------

 

As for the code... it looks great! If we found a way to add a physical area of effect, we could create a "when an entities touches this zone, the time of day changes for them". Like for a fire, or projectiles. Right? 

Link to comment
Share on other sites

Actually, I'm noticing there's a simple problem I wasn't thinking about: the power is useless if the character can't stop the camera for a moment to interact with what he changed. (for example, if he shoots a mushroom to get it out of the ground, the mushroom will go back in the ground as soon as the camera stops). If it possible to give to an effect a certain time of effect, so that when something changes because of the camera, it stays like that for a little moment even when the camera stops?

 

 

Hehe. Seriously, I'm starting to think my idea isn't simple. At ALL. Hehehe.

------

For the mushroom code, how can I get to it?

That's a great idea, since they are directly influenced by the time of day.

 

You can make camera as placeable item. Your character leaving it on ground and then, for example, picking that mushroom.

------------------

In dont_starve\data\scripts\prefabs you can find mushrooms prefab file.

Link to comment
Share on other sites

You can make camera as placeable item. Your character leaving it on ground and then, for example, picking that mushroom.

------------------

In dont_starve\data\scripts\prefabs you can find mushrooms prefab file.

 

Could be way easier to use like this, yes. We install it, and then create a little zone of day/night on a zone next to it.

 

Can't seem to find the dont_starve\data\scripts\prefabs folder, though. I only have access to "contents" and then "MacOS" and "Resources".

Link to comment
Share on other sites

Could be way easier to use like this, yes. We install it, and then create a little zone of day/night on a zone next to it.

 

Can't seem to find the dont_starve\data\scripts\prefabs folder, though. I only have access to "contents" and then "MacOS" and "Resources".

post-267484-0-14990800-1394034420_thumb.

if you're on Mac, it should look like this. (Starting with the Contents folder.)

Link to comment
Share on other sites

if you're on Mac, it should look like this. (Starting with the Contents folder.)

 

I've been trying to find it, but the only thing I always get is this:

capture_d_eacute_cran_2014_03_05__agrave

 

Where is my data folder? (and all the other folders too, haha)

I'll check again. Maybe this is only a shortcut, or maybe I can't see everything in the folder for some reason.

Link to comment
Share on other sites

I've been trying to find it, but the only thing I always get is this:

capture_d_eacute_cran_2014_03_05__agrave

 

Where is my data folder? (and all the other folders too, haha)

I'll check again. Maybe this is only a shortcut, or maybe I can't see everything in the folder for some reason.

That looks like some sort of shortcut, yeah...

Steam Desktop shortcut, I'm guessing?

 

This should help you find what you need:

http://forums.kleientertainment.com/topic/29658-how-to-install-a-mod-from-the-klei-downloads-page/page-3#entry410912

Link to comment
Share on other sites

Apparently, the interesting parts about the mushroom are:

 

local function onregenfn(inst)
        if (data.open_time == "day" and GetClock():IsDay()) or
            (data.open_time == "dusk" and GetClock():IsDusk()) or
            (data.open_time == "night" and GetClock():IsNight()) then
            open(inst)
        end
 
 
 
and
 
 
 
 local function close(inst)
        if inst.components.pickable and inst.components.pickable:CanBePicked() then
            if inst.growtask then
                inst.growtask:Cancel()
            end
            inst.growtask = inst:DoTaskInTime(3+math.random()*6, function() 
                    inst.AnimState:PlayAnimation("close_"..data.animname)
                    inst.AnimState:PushAnimation("inground")
                    inst:DoTaskInTime(.25, function() inst.SoundEmitter:PlaySound("dontstarve/common/mushroom_down") end )
                    
                    inst.growtask = nil
                    if inst.components.pickable then
                        inst.components.pickable.caninteractwith = false
                    end
 
 
 
and
 
 
 
local openevent = "daytime"
        local closeevent = "nighttime"
        
        
        local isopen = false
        if data.open_time == "night" then
            openevent = "nighttime"
            closeevent = "daytime"    
            isopen = GetClock():IsNight()
        elseif data.open_time == "day" then
            openevent = "daytime"
            closeevent = "dusktime"    
            isopen = GetClock():IsDay()
        else
            openevent = "dusktime"
            closeevent = "nighttime"
            isopen = GetClock():IsDusk()    
        end

 

 

 

 

I also checked for the attitude of spiders:

 

 

local function ShouldSleep(inst)
    return GetClock():IsDay()
           and not (inst.components.combat and inst.components.combat.target)
           and not (inst.components.homeseeker and inst.components.homeseeker:HasHome() )
           and not (inst.components.burnable and inst.components.burnable:IsBurning() )
           and not (inst.components.follower and inst.components.follower.leader)
end
 
local function ShouldWake(inst)
    return GetClock():IsNight()
           or (inst.components.combat and inst.components.combat.target)
           or (inst.components.homeseeker and inst.components.homeseeker:HasHome() )
           or (inst.components.burnable and inst.components.burnable:IsBurning() )
           or (inst.components.follower and inst.components.follower.leader)
           or (inst:HasTag("spider_warrior") and FindEntity(inst, TUNING.SPIDER_WARRIOR_WAKE_RADIUS, function(...) return FindWarriorTargets(inst, ...) end ))
end
Link to comment
Share on other sites

I played around with this a bit; this should give you a starting point. The component below (see spoilered code) will get entities within a radius and send fake time of day events as they enter/leave the area (and only reset their time of day after a configurable delay [see self.fadetime]). It 'works', but in practice it's probably not exactly what you want (for example, mushrooms react with a random delay of 3-9 seconds to the time of day change). Also, you'll need to handle dusk, as some things react to dusk, so just using a binary day/night system won't work as well as you might have thought.

For the affected area to be cone, you'll want to set the timeofdayswitcher component's testfn to a function that looks something like this (example pseudocode):

local function IsInCameraViewport(inst, camera)	local ent_pos = Vector3(inst.Transform:GetPosition())	local camera_pos = Vector3(inst.Transform:GetPosition())	-- calc dot product and compare angle	if angle is within camera viewport then		return true	else		return false	endend
And here's the component (note: you'll have to call inst.components.timeofdayswitcher:TurnOn() to start it):

-- components/timeofdayswitcher.lualocal TimeOfDaySwitcher = Class(function(self, inst)	self.inst = inst	self.affectedentities = {}	self.radius = TILE_SCALE * 2	self.radiusfn = nil	self.testfn = nil	self.fadetime = 5	self.fadetasks = {}	self.enabled = falseend)-- begin time of day helper functions-- should probably be moved to a separate filelocal function PushFakeTimeOfDayEventTo(inst, timeofday)	if inst.event_listening and inst.event_listening[timeofday.."time"] then		for entity, fns in pairs(inst.event_listening[timeofday.."time"]) do			for i,fn in ipairs(fns) do				print("sending fake "..timeofday.."time to "..tostring(inst))				-- need to send the same data that the normal event from clock.lua would				fn(inst, {day=GetClock().numcycles})			end		end	endendlocal function GetOppositeTimeOfDay(timeofday)	return timeofday == "night" and "day" or "night"endlocal function GetCurrentBinaryTimeOfDay(timeofday)	local curtimeofday = GetClock():GetPhase()	-- treat dusk as day	if curtimeofday == "dusk" then curtimeofday = "day" end	return curtimeofdayend-- end time of day event helper functionsfunction TimeOfDaySwitcher:TurnOn()	self.inst:StartUpdatingComponent(self)	self.enabled = trueendfunction TimeOfDaySwitcher:TurnOff()	self.inst:StopUpdatingComponent(self)	for guid,ent in pairs(self.affectedentities) do		self:OnEntityLeaveAffectedArea(ent)	end	self.enabled = falseendfunction TimeOfDaySwitcher:GetRadius()	return self.radiusfn and self.radiusfn(self.radius) or self.radiusendfunction TimeOfDaySwitcher:OnUpdate(dt)	local x, y, z = self.inst.Transform:GetWorldPosition()	-- get all entities in radius	local allaffectedentities = TheSim:FindEntities(x, y, z, self:GetRadius())	local validaffectedentities = {}	-- filter by self.testfn and check for newly affected entities	for k,ent in pairs(allaffectedentities) do		if ent.entity:IsValid() and ent.entity:IsVisible() then			local is_self = self.inst == ent			local is_owner = self.inst.components.inventoryitem and self.inst.components.inventoryitem.owner == ent			if not is_self and not is_owner and (not self.testfn or self.testfn(ent, self.inst)) then				validaffectedentities[ent.GUID] = ent				if self.affectedentities[ent.GUID] == nil then					self:OnEntityEnterAffectedArea(ent)				end			end		end	end	-- loop through all currently affected entities to find things no longer affected	for guid,ent in pairs(self.affectedentities) do		if validaffectedentities[guid] == nil then			self:OnEntityLeaveAffectedArea(ent)		end	endendlocal function ResetTimeOfDay(inst, entity, lasttimeofday)	if lasttimeofday == GetCurrentBinaryTimeOfDay() then		inst.components.timeofdayswitcher:SetTimeOfDay(entity, GetCurrentBinaryTimeOfDay())	end	inst.components.timeofdayswitcher.fadetasks[entity.GUID] = nilendfunction TimeOfDaySwitcher:SetTimeOfDay(entity, timeofday)	PushFakeTimeOfDayEventTo(entity, timeofday)endfunction TimeOfDaySwitcher:OnEntityEnterAffectedArea(entity)	self.affectedentities[entity.GUID] = entity	if self.fadetasks[entity.GUID] ~= nil then		self.fadetasks[entity.GUID]:Cancel()		self.fadetasks[entity.GUID] = nil	end	self:SetTimeOfDay(entity, GetOppositeTimeOfDay(GetClock():GetPhase()))endfunction TimeOfDaySwitcher:OnEntityLeaveAffectedArea(entity)	self.affectedentities[entity.GUID] = nil	if self.fadetasks[entity.GUID] ~= nil then		self.fadetasks[entity.GUID]:Cancel()		self.fadetasks[entity.GUID] = nil	end	self.fadetasks[entity.GUID] = self.inst:DoTaskInTime(self.fadetime, ResetTimeOfDay, entity, GetCurrentBinaryTimeOfDay())endfunction TimeOfDaySwitcher:GetDebugString()	local str = self.enabled and "enabled" or "disabled"	str = str.." ("..GetTableSize(self.affectedentities).." affected entities)"	str = str.." ("..GetTableSize(self.fadetasks).." running fadetasks)"	return strendreturn TimeOfDaySwitcher

EDIT: I was testing with the component added to the player. To do that just add this to your modmain.lua:

AddSimPostInit( function(inst)	inst:AddComponent("timeofdayswitcher")	inst.components.timeofdayswitcher:TurnOn()end)
EDIT#2: This is going to get complicated really fast. Your best bet here might be to go with a semi-manual approach; instead of pushing generic fake events and hoping for the right result, you might want to force specific things to happen directly. Like, for spiders, you could do, in TimeOfDaySwitcher:SetTimeOfDay, something like

if entity.components.sleeper then  if timeofday == "day" then    entity.components.sleeper:GoToSleep()  elseif timeofday == "night" then    entity.components.sleeper:WakeUp()  endend
You'll also have to deal with potential time of day changes while an entity is in the affected area. It's going to be a mess. :-)
Link to comment
Share on other sites

Wow. That's incredible. Seriously.

 

About the "dealing with potential time of day changing while an entity is in the affected area", I don't know if it's that much of a deal, since the camera is supposed to change its mode as well (day-night to night-day).

 

As for the dusk... ooops. Forgot about it. Maybe it could be included in the night, so that the camera makes entities react to a day situation while it's dusk or night, and react to a night situation (or a dusk... then a night?) while it's the day. I'm getting lost here. Hehe.

 

Your proposition in EDIT#2 seems quite more manageable... The zone would be the source of the change, and not actually the time of day. 

 

 

I kneeeeew my idea was going to be a big happy mess. Hahaha.

Link to comment
Share on other sites

As for the dusk... ooops. Forgot about it. Maybe it could be included in the night, so that the camera makes entities react to a day situation while it's dusk or night, and react to a night situation (or a dusk... then a night?) while it's the day. I'm getting lost here. Hehe.

Yeah, it gets weird with dusk. As seronis pointed out, the 3 mushroom types all sort of require all 3 times of day, because some will only appear after a "dusktime" event and other will only go away after a "daytime" event. Something that you may want to consider is to have the camera change the time of day to the next phase in order, meaning during the day it'd switch the affected area to dusk, during dusk it'd switch it to night, and during night it'd switch it to day. This may also solve some weird behaviors that happen when you "skip" a phase (like mushrooms playing their hide animation even though they're already hidden, etc).

 

Your proposition in EDIT#2 seems quite more manageable... The zone would be the source of the change, and not actually the time of day. 

 

 

I kneeeeew my idea was going to be a big happy mess. Hahaha.

If you keep the fake events, you're still going to have to do some manual interactions, because, for example, there's no easy way to fake a time of day in order to get a spider to wake up/sleep.
Link to comment
Share on other sites

Yeah, it gets weird with dusk. As seronis pointed out, the 3 mushroom types all sort of require all 3 times of day, because some will only appear after a "dusktime" event and other will only go away after a "daytime" event. Something that you may want to consider is to have the camera change the time of day to the next phase in order, meaning during the day it'd switch the affected area to dusk, during dusk it'd switch it to night, and during night it'd switch it to day. This may also solve some weird behaviors that happen when you "skip" a phase (like mushrooms playing their hide animation even though they're already hidden, etc).

 

Damn you, dusk.

 

The day to dusk to night to day solution seems to be the most viable then. By far.

 

If you keep the fake events, you're still going to have to do some manual interactions, because, for example, there's no easy way to fake a time of day in order to get a spider to wake up/sleep.

 
I was thinking of a full manual interactions, where I copy and modify the codes of everything I want to change, one by one. Is it possible?
Link to comment
Share on other sites

I was thinking of a full manual interactions, where I copy and modify the codes of everything I want to change, one by one. Is it possible?

It's possible, but it's not the most flexible or ideal solution, as you'll have to make sure that your copied code stays up-to-date with the game's code which would be a real pain (and it'd leave little room for interaction with other mods unless you copy their code into your mod and keep it up to date as well [double nightmare]). Try to think of ways to make your code as self-contained and flexible as possible, and, luckily, the component system makes that much easier. For example, the code I posted above to check for the sleeper component would be very flexible, as it'd work on everything that sleeps (however, you should also check for entity.components.sleeper.nocturnal to determine whether to to sleep or wake up).

It's not always easy to code things in the most ideal way, but it's definitely the best thing in the long run as it means less necessary support on your end and more possible applications on the user's.

Link to comment
Share on other sites

I've never looked into it,  but how do you REMOVE an event listener?  Can we deregister them once created?

 

If so, once the camera is turned on it can deregister the time listeners on all creatures within its Area of Effect and possibly schedule a timed task that will keep rechecking those affected to re-register if they wander outside the AOE. You'll already need a periodic task on the camera itself to check for when new creatures enter the area while active. 

 

In the end there are some creatures that just react to what the absolute world time is and not the 'change of phase' events. In those cases you will need to have your mod override those creatures behaviors on a case by case basis and keep the mod updated if creature behavior is changed.

Link to comment
Share on other sites

I've never looked into it,  but how do you REMOVE an event listener?  Can we deregister them once created?

You can, but it's complicated, because each entity can have multiple callback functions per event, so to differentiate between them, the EntityScript:RemoveEventCallback function takes the eventname, the source prefab, and the function itself as parameters. It's very unlikely that a mod would have access to the callback function to be able to pass it to the function (as most of those are either anonymous functions or local functions in the prefab files), and without it you'd basically have to clear the event's key in the listening and listener table of both the source and listener prefabs, which would probably be really bad (as you don't want to clear all listeners of the "daytime" event from the world prefab).

However, you could loop through the listener's listening functions and sort of guess as to which one is the correct one (or maybe you'd get lucky and it'd only have one callback function per time of day event) and then pass that into the EntityScript:RemoveEventCallback function.

But, yeah, it's complicated unless you have access to the callback function.

Link to comment
Share on other sites

I'm new to modding myself, but I was browsing and this idea looks INCREDIBLY cool. One thing that came to mind for the visual effect itself is to look at the code for the miners hat. I'm posting this late-night without checking in-game, but I'm almost positive the miner hat light comes out in a cone. You could probably find something in the code there, or another function that code leads to that might help you with the lighting. I was thinking the dark might be harder, but it's probably just a matter of changing the color of the light(really not sure, I'm very new to this). And I'm guessing when you find how the cone is made, you can just adjust some parameters to change the size/shape of it.

 

Couple other ideas..

 

On other things it would be hard, but with the mushroom example when you talked about it going right back in the ground as soon as you try to pick it, keep in mind that you can harvest resources while holding another item. For example, if I'm holding a torch, I can still harvest grass.

 

Another thought is that some items can be used but don't have to be equipped, like the razor. With it, you can shave your own beard as Wilson, or shave a Beefalo, but it's not even possible to equip it. You just do it from your inventory.

 

You could also, though not as realistic(although it IS Don't starve, so anything can work) make it a headslot item or even a bodyslot item so you could use weapons and tools while it's equipped.

 

As for finding bits and pieces of code, if you find a function or variable, etc in ANY script and want to understand it better, on Windows I have changed my file search to index the full contents of all lua files. I have no idea how this works on a Mac, but I'm sure you could google it and this has helped me a lot in delving through code and understanding things. I have yet to finish my first mod as I'm completely obsesive about understanding every bit of code I write, but hopefully I've learned enough that these ideas aren't completely out of whack.

Link to comment
Share on other sites

I'm new to modding myself, but I was browsing and this idea looks INCREDIBLY cool. One thing that came to mind for the visual effect itself is to look at the code for the miners hat. I'm posting this late-night without checking in-game, but I'm almost positive the miner hat light comes out in a cone. You could probably find something in the code there, or another function that code leads to that might help you with the lighting. I was thinking the dark might be harder, but it's probably just a matter of changing the color of the light(really not sure, I'm very new to this). And I'm guessing when you find how the cone is made, you can just adjust some parameters to change the size/shape of it.

 

Maybe we can do that... but it seems the code of the miner's hat works like a normal light in the game. The shape doesn't seem to be changeable. 

 

But I can't confirm it, I wasn't able to find the miner's hat prefabs.

 

 

On other things it would be hard, but with the mushroom example when you talked about it going right back in the ground as soon as you try to pick it, keep in mind that you can harvest resources while holding another item. For example, if I'm holding a torch, I can still harvest grass.

 

Another thought is that some items can be used but don't have to be equipped, like the razor. With it, you can shave your own beard as Wilson, or shave a Beefalo, but it's not even possible to equip it. You just do it from your inventory.

 

You could also, though not as realistic(although it IS Don't starve, so anything can work) make it a headslot item or even a bodyslot item so you could use weapons and tools while it's equipped.

 

The first option could work, but it would need some visual tweaking as well.

Kinda hard to define if we can't find the way to make appear the light. The position of the camera depends on that. Gnh.

 

 

As for finding bits and pieces of code, if you find a function or variable, etc in ANY script and want to understand it better, on Windows I have changed my file search to index the full contents of all lua files. I have no idea how this works on a Mac, but I'm sure you could google it and this has helped me a lot in delving through code and understanding things. I have yet to finish my first mod as I'm completely obsesive about understanding every bit of code I write, but hopefully I've learned enough that these ideas aren't completely out of whack.

 

I can see (most of) the codes in the lua files, I think! That's how I was able to search for some of them before. But everything seems quite easier on Windows! I knows I won't be able to code that alone, since it seems we needs a programlinked to Don't Starve that's only for Windows.

 

And the codes for the game are quite funny to read sometimes! Haha. The little comments here and there help.

Link to comment
Share on other sites

Maybe we can do that... but it seems the code of the miner's hat works like a normal light in the game. The shape doesn't seem to be changeable. 

 

But I can't confirm it, I wasn't able to find the miner's hat prefabs.

 

All the hats share a single prefab.

It's a little annoying.

Check out hats.lua.

Link to comment
Share on other sites

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.

×
  • Create New...