Sign in to follow this  
identitypollution

Help Coding- Mod Mushroom Effect

Recommended Posts

I've been working on an Alice in Wonderland character and I would like to make mushrooms have different effects for her. I'd like blue caps to make her glow, green to speed her up and red to increase strength all for limited times. How should I go about this? Would it be easier to have her craft the mushrooms into an entirely new edible item? This is my first character mod sorry if this question seems silly. 

HO1kul1.png

Share this post


Link to post
Share on other sites
rezecib    3157

@identitypollution, It's definitely feasible to have those effects in the mushrooms themselves. For the blue caps, you can take the code from glowberries, and the other two are pretty simple. Something like this in your character's master_postinit should work:


local speed_task = nillocal strength_task = nillocal mushroomfns = {}mushroomfns.blue_cap = function(eater)	-- I copied this from prefabs/wormlight.lua, the glowberry file	-- I'm not sure if this really works in DST, though. Some testing might be needed	--  to make sure it works for both clients and hosts	if eater.wormlight then        eater.wormlight.components.spell.lifetime = 0        eater.wormlight.components.spell:ResumeSpell()    else        local light = SpawnPrefab("wormlight_light")        light.components.spell:SetTarget(eater)        if not light.components.spell.target then            light:Remove()        end        light.components.spell:StartSpell()    endendmushroomfns.green_cap = function(eater)	-- It depends on how you want this to work...	-- but because it's easier, I just wrote sudden start and stop	local key = "alice speedy mushroom"	eater.components.locomotor:SetExternalSpeedMultiplier(eater, key, 1.5) -- change 1.5 to the multiplier you want    if speed_task then speed_task:Cancel() end	speed_task = eater:DoTaskInTime(30, function() -- change the 30 to the number of seconds you want it to last		eater.components.locomotor:RemoveExternalSpeedMultiplier(eater, key)        speed_task = nil	end)endmushroomfns.red_cap = function(eater)	eater.components.combat.damagemultiplier = 1.5 -- change 1.5 to the multiplier you want    if strength_task then strength_task:Cancel() end	strength_task = eater:DoTaskInTime(30, function() -- change the 30 to the number of seconds you want it to last		eater.components.combat.damagemultiplier = 1        strength_task = nil
 

end) end -- The way I wrote this, only the raw mushrooms have effects -- If you want both the cooked and raw to work, uncomment these: -- mushroomfns.red_cap_cooked = mushroomfns.red_cap -- mushroomfns.green_cap_cooked = mushroomfns.green_cap -- mushroomfns.blue_cap_cooked = mushroomfns.blue_cap local oldoneat = inst.components.eater.oneatfn inst.components.eater.oneatfn = function(inst, food) if oldoneat then oldoneat(inst, food) end local oneaten = mushroomfns[food.prefab] if oneaten then oneaten(inst) end end

Edit: Fixed the oldoneat part-- it could crash there before. Edited again to fix maintaining the buffs.

 

I should probably explain my process a bit so it's something you or others can follow:

 

Because we want the effect to occur on eating, there are two possible places to hook into it: from the perspective of the thing being eaten (the edible component), or from the perspective of the character eating (the eater component). You can really use either of these, but I chose to use the eater component because it centralizes more of the code in the character's file.

 

So, looking at the eater component, I found the oneatfn; this is a variable that can be given a function, and when something is eaten, if there is an oneatfn, it will call the oneatfn-- you can see it do this in the Eat function. So at the bottom of my code I give it an oneatfn that checks if the food is one of the ones we want to have special effects, and if so, run the function for that food.

 

In the top part, I make a table that has as its keys the foods that cause effects, and as its values the functions to carry out the effects (which are then run in the oneatfn). So the way the table is set up, you give it the food's prefab name, and it will either give you one of the functions I wrote, or nil (which is what a table gives you when you give it a key that hasn't been paired). So in the oneatfn, I ask the table to look for that food prefab, and store the result in oneaten. If oneaten is nil, that means the food wasn't in the table, so I don't want to try to run oneaten as a function. Otherwise, I want to run oneaten, which will cause the effects of the food to take place.

 

In the commented area, I bind the same functions to additional keys in the table for the cooked mushrooms.

 

If you're confused about the key/value stuff I talked about, you can think of it this way: let's say you have a numbered list. I can say "give me the third list element" and you'll know which one to give me. Tables work like this, except instead of just numbers, you can use any variable's value to label the list (but each value can only point to one thing). In this case, I label the list with strings (text) with the prefab names for the foods that have effects.

Edited by rezecib

Share this post


Link to post
Share on other sites
rezecib    3157

@DarkXero, Go ahead and post your component solution, it'd make handling the gradual dropoff of the speed/strength easier. And it's always good to see different options when you're learning something!

Share this post


Link to post
Share on other sites
DarkXero    2887

Well, as soon as I saw what you posted, I paused.

But I will resume and make linear scalings to introduce a dropoff.

 

Another thing to evaluate is if buffs stack on themselves, or if you can have one blue buff at a time.

Another, is, if eating a blue cap adds 10 seconds to a timer, or if it resets the timer to 10 seconds.

 

rezecib, in your functions, if I eat a second mushroom in the 29 second mark, the task in time would get executed at 30 and then the first and second mushroom effects would be invalidated. This doesn't solve buff stacking, but it doesn't matter because it's static. It doesn't stack tme or reset a timer.

Share this post


Link to post
Share on other sites
DarkXero    2887

Update.

 

After constantly screwing up the math with easing and the numbers with lighttweener, I decided to simply make the light get set again and again and again while the component updated.

 

Edit: I also checked the wormlight. It lacks network things and it needs to be ported. However it would be wise to get it from the mod that ported ruins things into the overworld.

 

Here's my contribution to this.

 

fungusfanatic.zip

Edited by DarkXero

Share this post


Link to post
Share on other sites
rezecib    3157
rezecib, in your functions, if I eat a second mushroom in the 29 second mark, the task in time would get executed at 30 and then the first and second mushroom effects would be invalidated.
 Oh, good point. I'll edit it to keep track of the task and cancel it.

Share this post


Link to post
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
Sign in to follow this