Jump to content

How To Create Armor as a Useable Item?


Recommended Posts

Edit1 : Should have write Edible Item as title instead of Useable - Potions can't be Useable...

           How To Create Armor As a Edible Item .... ?

 

Hello,

 

I'm trying to make a character which can create its own potions. At first, I tried to put :

 

inst:AddComponent("useableitem")

 

But it seems that command does not work anymore because none of the potions was Useable.

Instead, I used Edible command... so every potion are Eatable. See?

 

inst:AddComponent("edible")

 

Everything works fine until I reach a point where I can't understand how to create the right script for that potion.

 

I want to create a potion that "changes skin into stone." (I looked up at the marble armor and such...) When its used, I dont want the armor to be equipped, but instead, having it working in "background" with a timer that will set the skin to normal. (Messages should popup to indicate the player when the potion worn off)

 

I guess I have to put some armor script in the "oneat" function? Some armor condition? A timer, but how?

I understand what I read in the armor script, but still, I dont know how to organize all of it in my own script. It seems everything I write down is not correct in form.

 

D4rkh0bb1T

local function fn()(...)inst:AddComponent("armor")inst.components.armor:InitCondition(TUNING.ARMORMARBLE)inst.components.armor:SetAbsorption(TUNING.ARMORMARBLE_ABSORPTION)local function oneaten(inst, owner) ???????????? WHAT TO WRITE DOWN ?????????????
Edited by D4rkh0bb1T
Link to comment
Share on other sites

Wigfrid takes 25% less damage to her health

inst.components.health:SetAbsorptionAmount(0.25)

thanks to this.

 

Simple example:

local POTION_DURATION = 30local function makemarble(owner)	owner.components.health:SetAbsorptionAmount(TUNING.ARMORMARBLE_ABSORPTION)endlocal function makenormal(owner)	owner.components.health:SetAbsorptionAmount(0)endlocal function oneaten(inst, owner)	makemarble(owner)	owner:DoTaskInTime(POTION_DURATION, makenormal)end

Here, on the oneaten function, we give the guy who took the potion, marble like absorption.

We also schedule a function to run after 30 seconds, which will bring the absorption back to 0 (default for most characters).

Link to comment
Share on other sites

I tried to put these functions and it works perfeclty. I tried to study how it works and noticed in the health.lua the part with SetAbsorptionAmount.

 

Things make sense.

 

Now, i'm trying the same thing with a waterproof function. With what I learned from your script, I went to study the waterproofer.lua. There, I see SetEffectiveness(val) - Rather than SetAbsorptionAmount(amount).

 

I writed down these :

local POTION_DURATION = 60 local function makewaterproof(owner)local inst = GetPlayer()	inst:AddComponent("waterproofer")    owner.components.waterproofer:SetEffectiveness(TUNING.WATERPROOFNESS_HUGE)	inst.components.talker:Say("Smells like fish in my cells!", 4)end local function makenormal(owner)local inst = GetPlayer()    owner.components.waterproofer:SetEffectiveness(0)	inst.components.talker:Say("I can get wet again.", 4)end local function oneaten(inst, owner)    makewaterproof(owner)    owner:DoTaskInTime(POTION_DURATION, makenormal)end(...)inst:AddComponent("edible")inst.components.edible.hungervalue = 0inst.components.edible:SetOnEatenFn(oneaten)

The crash report to this : attempt to index field 'waterproofer' (a nil value)

What do I miss?

 

D4rkh0bb1T

 

Link to comment
Share on other sites

@D4rkh0bb1T,

your issue lies here:

	local inst = GetPlayer()    inst:AddComponent("waterproofer")    owner.components.waterproofer:SetEffectiveness(TUNING.WATERPROOFNESS_HUGE)

You add waterproofer to inst, and then you refer to owner, which doesn't have that component.

 

The real issue here is that in server ran code, GetPlayer() refers to the server or the player hosting.

Which means only one guy would receive the bonuses.

 

That is why you use the owner variable passed via oneaten which holds the entity that will be affected.

 

Besides, you having waterproofness does nothing, since the game doesn't take that into account when calculating moisture.

 

If we check the moisture component, we can find an inherent waterproofness variable that helps us achieve what we want, thus

local POTION_DURATION = 60  local function makewaterproof(eater)	eater.components.moisture:SetInherentWaterproofness(TUNING.WATERPROOFNESS_HUGE)end  local function makenormal(eater)	eater.components.moisture:SetInherentWaterproofness(0)end  local function oneaten(inst, eater)	makewaterproof(eater)	eater:DoTaskInTime(POTION_DURATION, makenormal)end
Link to comment
Share on other sites

Woah, I would never find this out.

 

I wonder what if I put the name of my char in GetPlayer(nameofthechar) then? Potions should only be useable by my character? Without names inbetween () and as a client, I could not use potions in a friend server?  And no one can drink potions?

 

Second, what if I had ''eater'' thing to other potions instead of ''owner''? I understand that every character have Health, so ''owner'' makes sense, but why not ''eater'', would it work too?

 

I wrote local inst = GetPlayer() to be able to activate the custom speech, beginning with ''inst''.component.talker ... ...

I could just write down eater.component.talker? ''owner'' in case the function calls that just before?

 

Thanks

 

D4rkh0bb1T

Edited by D4rkh0bb1T
Link to comment
Share on other sites

I wrote local inst = GetPlayer() to be able to activate the custom speech, beginning with ''inst''.component.talker ... ...

 

The code runs server side.

GetPlayer() refers to the server machine or the player hosting the game.

 

I could just write down eater.component.talker? ''owner'' in case the function calls that just before?

 

Yes.

local function makewaterproof(eater)    eater.components.moisture:SetInherentWaterproofness(TUNING.WATERPROOFNESS_HUGE)	eater.components.talker:Say("Smells like fish in my cells!", 4)end
what if I had ''eater'' thing to other potions instead of ''owner''? I understand that every character have Health, so ''owner'' makes sense, but why not ''eater'', would it work too?

 

I can make it like this.

local POTION_DURATION = 60   local function makewaterproof(wowavariable)    wowavariable.components.moisture:SetInherentWaterproofness(TUNING.WATERPROOFNESS_HUGE)end   local function makenormal(thisisavar)    thisisavar.components.moisture:SetInherentWaterproofness(0)end   local function oneaten(itementity, entitypassedduringeating)    makewaterproof(entitypassedduringeating)    entitypassedduringeating:DoTaskInTime(POTION_DURATION, makenormal)end

and it works the same.

 

I used eater because the oneaten function is called on the edible component like this

    if self.oneaten ~= nil then        self.oneaten(self.inst, eater)    end

and it gets passed the item being eaten, and the entity that does the eating.

 

owner is used for inventory items, mostly.

 

Those are still variable names that could be different.

 

Potions should only be useable by my character?

 

Declare in modmain your new foodtype.

GLOBAL.FOODTYPE.POTION = "POTION"

Make your potions be FOODTYPE.POTION, in your potion's prefab.

inst.components.edible.foodtype = FOODTYPE.POTION

Then allow your character to eat FOODTYPE.POTION, putting in master_postinit.

local _eater = inst.components.eatertable.insert(_eater.preferseating, FOODTYPE.POTION)table.insert(_eater.caneat, FOODTYPE.POTION)_eater.inst:AddTag(FOODTYPE.POTION.."_eater")

Others characters wouldn't be able to eat them then.

 

Without names inbetween () and as a client, I could not use potions in a friend server? And no one can drink potions?

 

The potion code is ran in the server.

The only thing that runs client side is the message you emit to the server "I want to eat this item".

Then the server makes you eat it, triggers the effect, and shows you the effects if you can see them.

You will notice the marble absorption when you see you take less damage, and the waterproofness when you don't gain moisture.

 

But those commands affecting the component won't be ran by you.

Link to comment
Share on other sites

Thanx! Very precise answers, mate!

 

100% working

 

I tried to put the potions effects in the oneat function above + talker thing. Unfortunately, it was not working. Had to get the edible effect below just like before and keep the saying part in the oneat function, beginning with "eater" or "owner", depending of the variable used.

 

Talker Function&Tutorials

 

I did copy-paste the talker function from another script to be sure it is well written, but, there, I can't figure out what is the "4" at the end? I think we can make talker components without it, but still, I wonder what is its purpose. Do you know any good tutorials I can read, been searching for a lot of things without precise answers.

 

GetPlayer() VS ThePlayer? DS VS DST?

 

I might not put GetPlayer() at all, cuz I want the potions useable for anyone if the player wants to share... anyway. I'll keep your little script above for further creation if you don't mind. I have three other potions which use GetPlayer() function, and everything under it begin with "inst". In my crash log (even with no crash!) it says that :

 Warning: GetPlayer() is deprecated. Please use ThePlayer instead. (@../mods/Druid/scripts/prefabs/blackpotion.lua:17 in makemarble)	[00:01:56]: WARNING! Could not find region 'FROMNUM' from atlas 'FROMNUM'. Is the region specified in the atlas?[00:01:56]: Looking for default texture '' from atlas 'FROMNUM'.[00:01:56]: images/inventoryimages.xml

No crash, but, I have to know why. hehe. I haven't try online with other ppl, I hope it won't crash then.

 

D4rkh0bb1T

Edited by D4rkh0bb1T
Link to comment
Share on other sites

I can't figure out what is the "4" at the end?

 

The talker component file has

function Talker:Say(script, time, noanim, force, nobroadcast, colour)

where you can see that time is the variable that is used to determine for how many seconds the message will float before disappearing.

 

No crash, but, I have to know why.

 

GetPlayer() is deprecated and now ThePlayer is used.

Essentially, GetPlayer() does the same as ThePlayer.

It gets you the player entity.

 

ThePlayer is DST only.

Link to comment
Share on other sites

Ok ! Didn't even know we can change colour of the messages there. I see we can find a lot of answer by digging up data files, which I do a lot of time, but can never put fingers on what I really need.

 

As for the Foodtype thing, I bet we need to understand the GLOBAL system at first and I guess you find out "table.insert" or "_eater" in the eater data files, along with preferseating.

 

I really need to understand how to organize scripts together...

 

Thanx for your help!

 

D4rkh0bb1T

 

 

Link to comment
Share on other sites

As for the Foodtype thing, I bet we need to understand the GLOBAL system at first and I guess you find out "table.insert" or "_eater" in the eater data files, along with preferseating.

 

table.insert is from lua.

 

_eater is nothing, just a variable named that to store the inst.components.eater table.

local function master_postinit(inst)	table.insert(inst.components.eater.preferseating, FOODTYPE.POTION)	table.insert(inst.components.eater.caneat, FOODTYPE.POTION)	inst:AddTag(FOODTYPE.POTION.."_eater")end

Instead of writing inst.components.eater again and again, I just put it in _eater.

 

Those three lines are a variation of

function Eater:SetCanEatGears()    table.insert(self.preferseating, FOODTYPE.GEARS)    table.insert(self.caneat, FOODTYPE.GEARS)    self.inst:AddTag(FOODTYPE.GEARS.."_eater")end

the eater component function that lets WX-78 eat gears.

 

 

So yeah, just practice. You start looking at ingame behaviour and matching the code that enables it, and then you start reading code and then predicting what it will do.

Edited by DarkXero
Link to comment
Share on other sites

Wigfrid takes 25% less damage to her health

inst.components.health:SetAbsorptionAmount(0.25)

thanks to this.

 

Simple example:

local POTION_DURATION = 30local function makemarble(owner)	owner.components.health:SetAbsorptionAmount(TUNING.ARMORMARBLE_ABSORPTION)endlocal function makenormal(owner)	owner.components.health:SetAbsorptionAmount(0)endlocal function oneaten(inst, owner)	makemarble(owner)	owner:DoTaskInTime(POTION_DURATION, makenormal)end

Here, on the oneaten function, we give the guy who took the potion, marble like absorption.

We also schedule a function to run after 30 seconds, which will bring the absorption back to 0 (default for most characters).

 

Mmmmm, exist any chance make an character inmune from be stunlocked on the makemarble state?

I'm doing my item and i'm using this for make an item who knocks you for a lot of time (an half day ingame).

Edited by Neutral_Steve
Link to comment
Share on other sites

local POTION_DURATION = 30

local function makemarble(owner)

owner.components.combat:SetPlayerStunlock(PLAYERSTUNLOCK.NEVER)

end

local function makenormal(owner)

owner.components.combat:SetPlayerStunlock(PLAYERSTUNLOCK.NORMAL)

end

local function oneaten(inst, owner)

makemarble(owner)

owner:DoTaskInTime(POTION_DURATION, makenormal)

end

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