Jump to content

Help with the potions


Recommended Posts

Hi everyone, working on a very watered down version of Korrigan's potions and I noticed that his stat enhancing potions stack making it so you can do basically reach infinite in that stat. 

Korrigans example:

 

local assets=
{
    Asset("ANIM", "anim/violencepotion.zip"),
    Asset("ATLAS", "images/inventoryimages/violencepotion.xml"),
    Asset("IMAGE", "images/inventoryimages/violencepotion.tex"),
   
}

--Normal Potions Value
local violencevalue = TUNING.VIOLENCEVALUE

local function ondrinkviolence(inst, eater)
    eater.components.talker:Say("ROID RAGE!", 4)
    if eater.components.combat.damagemultiplier == nil then
        eater.components.combat.damagemultiplier = 1
    end
    eater.components.combat.damagemultiplier = eater.components.combat.damagemultiplier * violencevalue
    eater:DoTaskInTime(180,
    function()
        eater.components.combat.damagemultiplier = .50
        eater.components.talker:Say("-Damage Multiplier Removed-", 10)
    end)
end
 
local function fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddNetwork()
    MakeInventoryPhysics(inst)
      
    inst.AnimState:SetBank("violencepotion")
    inst.AnimState:SetBuild("violencepotion")
    inst.AnimState:PlayAnimation("idle")
   
    inst.entity:SetPristine()
 
    if not TheWorld.ismastersim then
        return inst
    end
 
    inst:AddComponent("inspectable")
    inst:AddComponent("stackable")
    inst.components.stackable.maxsize = TUNING.STACK_SIZE_SMALLITEM
	
    inst:AddComponent("edible")
    inst.components.edible.foodtype = FOODTYPE.MEAT
    inst.components.edible.hungervalue = 0 --gives 10 by default
    inst.components.edible:SetOnEatenFn(ondrinkviolence)
   
    inst:AddComponent("inventoryitem")
    inst.components.inventoryitem.imagename = "violencepotion"
    inst.components.inventoryitem.atlasname = "images/inventoryimages/violencepotion.xml"
      
    --inst:AddComponent("edible")
    --inst.components.edible.hungervalue = 0 --gives 10 by default
   
    inst:AddComponent("tradable")
 
    MakeHauntableLaunch(inst)
     
    return inst
end

return Prefab("common/inventory/violencepotion", fn, assets)

I know Felix's Marvelous Potions Mod had a way to remedy this problem but it looked way beyond my comprehension. Isn't there an easier way to make it so if person uses this potion once, he can't use it again until the cooldown is finished(Different from Felix's approach). Or is Felix's solution the best way to go at it?

Felix Example:

 

local assets=
{
	Asset("ANIM", "anim/healthpotion.zip"),
	Asset("ATLAS", "images/inventoryimages/armorpotion.xml"),
	Asset("IMAGE", "images/inventoryimages/armorpotion.tex"),
		Asset("ATLAS", "images/inventoryimages/armorpotion_off.xml"),
	Asset("IMAGE", "images/inventoryimages/armorpotion_off.tex"),
	Asset("SOUNDPACKAGE", "sound/potion_sounds.fev"),
	Asset("SOUND", "sound/potion_sounds.fsb")
}

local prefabs = 
{

}	


local function endeffect(inst)
    if inst:HasTag("potioncooldown") then
						local olddefense = inst.components.health.absorb
			local newdefense = (olddefense - TUNING.ARMORPOTIONBUFF)
			  inst.components.health:SetAbsorptionAmount(newdefense)
			
	inst:RemoveTag("potioncooldown")

  inst._fx2 = SpawnPrefab("attune_ghost_in_fx")
    inst._fx2.entity:SetParent(inst.entity)
    inst._fx2.Transform:SetPosition(0, 0, 0)
	
	if inst._fx ~= nil then
	inst._fx:Remove() end
       inst:PushEvent("potioncheck")
	   else
	   end
end


local function onbecameghost(inst)
if inst:HasTag("potioncooldown") then
	inst:RemoveTag("potioncooldown")
 inst:PushEvent("potioncheck")
 
			local olddefense = inst.components.health.absorb
			local newdefense = (olddefense - TUNING.ARMORPOTIONBUFF)
			  inst.components.health:SetAbsorptionAmount(newdefense)
if inst._fx ~= nil then
	inst._fx:Remove() end

			end
					

end

local function givepotion(inst)
local potion = "powerpotion"
local item = SpawnPrefab(potion)
if inst.components.inventory ~= nil then

		 item.components.inventoryitem:SetOwner(inst)
		 inst.components.inventory:GiveItem(item)

end

end

local function OnEaten(inst, eater)

if eater:HasTag("potioncooldown") and eater:HasTag("player") then
 eater:DoTaskInTime(0, givepotion)
			eater.components.talker:Say("My body is still recovering from the last potion.") 
 eater.sg:GoToState("refuseeat")


else


eater._fx = SpawnPrefab("armorpotionfx")
    eater._fx.entity:SetParent(eater.entity)
    eater._fx.Transform:SetPosition(0, 3, 0)
	
	eater:AddTag("potioncooldown")
    eater:ListenForEvent("ms_becameghost", onbecameghost)
			    eater:DoTaskInTime(TUNING.BUFFPOTIONCD , endeffect)	
	eater.SoundEmitter:PlaySound("potion_sounds/potion/drink_potion")
	
			if eater.components.health then
				
			local olddefense = eater.components.health.absorb
			local newdefense = (olddefense + TUNING.ARMORPOTIONBUFF)
			  eater.components.health:SetAbsorptionAmount(newdefense)
	
			
			end			
  eater:PushEvent("potioncheck")		
			
			end		
end
   
   ------------------------------------------------------===========================

local function UpdateInventoryState(inst)
    local viewer = inst.components.inventoryitem:GetGrandOwner()
    while viewer ~= nil and viewer.components.container ~= nil do
        viewer = viewer.components.container.opener
    end
    if viewer ~= nil then
	if viewer:HasTag("potioncooldown") then
       inst:RemoveComponent("edible") 
	inst.components.inventoryitem.imagename = "armorpotion_off"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/armorpotion_off.xml"	   
	   inst:PushEvent("imagechange")
    else
if inst.components.edible == nil then	inst:AddComponent("edible") end	 	
	if inst.components.edible.foodtype == FOODTYPE.GENERIC then inst.components.edible.foodtype = FOODTYPE.GOODIES	end
	inst.components.inventoryitem.imagename = "armorpotion"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/armorpotion.xml" 
	inst:PushEvent("imagechange")
	inst.components.edible.healthvalue = 0
    inst.components.edible.hungervalue = 0
	inst.components.edible.sanityvalue = 0
	inst.components.edible:SetOnEatenFn(OnEaten)

    end
	end
end

local function StopWatchingSanity(inst)
    if inst._sanitywatching ~= nil then
        inst:RemoveEventCallback("potioncheck", inst.OnWatchSanityDelta, inst._sanitywatching)
        inst._sanitywatching = nil
    end
end

local function WatchSanity(inst, target)
    StopWatchingSanity(inst)
    if target ~= nil then
        inst:ListenForEvent("potioncheck", inst.OnWatchSanityDelta, target)
        inst._sanitywatching = target
    end
end

local function StopWatchingForOpener(inst)
    if inst._openerwatching ~= nil then
        inst:RemoveEventCallback("onopen", inst.OnContainerOpened, inst._openerwatching)
        inst:RemoveEventCallback("onclose", inst.OnContainerClosed, inst._openerwatching)
        inst._openerwatching = nil
    end
end

local function WatchForOpener(inst, target)
    StopWatchingForOpener(inst)
    if target ~= nil then
        inst:ListenForEvent("onopen", inst.OnContainerOpened, target)
        inst:ListenForEvent("onclose", inst.OnContainerClosed, target)
        inst._openerwatching = target
    end
end


local function BeginWatch(inst)
     inst.components.inventoryitem:SetOnPutInInventoryFn(function(inst, owner)
    if owner.components.container ~= nil then
        WatchForOpener(inst, owner)
        WatchSanity(inst, owner.components.container.opener)
    else
        StopWatchingForOpener(inst)
        WatchSanity(inst, owner)
    end
    UpdateInventoryState(inst)
    end)
	
	    inst.components.inventoryitem:SetOnDroppedFn(function(inst)
 
         StopWatchingSanity(inst)
    UpdateInventoryState(inst)
    end)
end

local function onload(inst, data)


end



----------------------------------------------==========================
	
local function fn(Sim)
    local inst = CreateEntity()
	local trans = inst.entity:AddTransform()
	local anim = inst.entity:AddAnimState()
	inst.entity:AddSoundEmitter()

	inst.entity:AddNetwork()
    MakeInventoryPhysics(inst)
    
    anim:SetBank("healthpotion")
    anim:SetBuild("healthpotion")
    anim:PlayAnimation("armor")
    
      inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    
	

	inst.entity:SetPristine()
	
    inst:AddComponent("inspectable")
	

    inst:AddComponent("inventoryitem")
	inst.components.inventoryitem.imagename = "armorpotion"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/armorpotion.xml"
	

	 inst:AddComponent("stackable")

	 
	 		inst:AddTag("waterproofer")
	    inst:AddComponent("waterproofer")
    inst.components.waterproofer:SetEffectiveness(0.01)
----------------------------------------   

   
   
	  inst.OnWatchSanityDelta = function(viewer)
        if viewer:HasTag("potioncooldown") then
       inst:RemoveComponent("edible") 	 
	   	inst.components.inventoryitem.imagename = "armorpotion_off"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/armorpotion_off.xml"
	   inst:PushEvent("imagechange")
        else 
if inst.components.edible == nil then	inst:AddComponent("edible") end	  
	inst.components.inventoryitem.imagename = "armorpotion"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/armorpotion.xml"
			inst:PushEvent("imagechange")
	inst.components.edible.healthvalue = 0
    inst.components.edible.hungervalue = 0
	inst.components.edible.sanityvalue = 0
	if inst.components.edible.foodtype == FOODTYPE.GENERIC then
		inst.components.edible.foodtype = FOODTYPE.GOODIES
	end
	inst.components.edible:SetOnEatenFn(OnEaten)
        end
    end
	
	
	    inst.OnContainerOpened = function(container, data)
        WatchSanity(inst, data.doer)
        UpdateInventoryState(inst)
    end

    inst.OnContainerClosed = function()
        StopWatchingSanity(inst)
        UpdateInventoryState(inst)
    end
	
	
	    inst._sanitywatching = nil
    inst._openerwatching = nil
	
	
	    inst.OnLoad = onload
	
	inst:AddComponent("edible")
	inst.components.edible.healthvalue = 0
    inst.components.edible.hungervalue = 0
	inst.components.edible.sanityvalue = 0
	inst.components.edible.foodtype = FOODTYPE.GOODIES
	inst.components.edible:SetOnEatenFn(OnEaten)

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

    BeginWatch(inst)

    
    return inst
end

return Prefab( "common/inventory/armorpotion", fn, assets) 
Edited by rons0n
Link to comment
Share on other sites

Well I finally found my solution, just a matter of using tags and a component that drops item if they dont have the tag.

But Im now confused on how to add a global tag for all characters to who join the server, lose tag when they become ghost, and gain tag when becoming human. 

Last step before I could get this bad boy done, much appreciated if anyone can help! 

Link to comment
Share on other sites

On 9/5/2017 at 12:45 PM, rons0n said:

Hi everyone, working on a very watered down version of Korrigan's potions and I noticed that his stat enhancing potions stack making it so you can do basically reach infinite in that stat. 

Korrigans example:

  Hide contents


local assets=
{
    Asset("ANIM", "anim/violencepotion.zip"),
    Asset("ATLAS", "images/inventoryimages/violencepotion.xml"),
    Asset("IMAGE", "images/inventoryimages/violencepotion.tex"),
   
}

--Normal Potions Value
local violencevalue = TUNING.VIOLENCEVALUE

local function ondrinkviolence(inst, eater)
    eater.components.talker:Say("ROID RAGE!", 4)
    if eater.components.combat.damagemultiplier == nil then
        eater.components.combat.damagemultiplier = 1
    end
    eater.components.combat.damagemultiplier = eater.components.combat.damagemultiplier * violencevalue
    eater:DoTaskInTime(180,
    function()
        eater.components.combat.damagemultiplier = .50
        eater.components.talker:Say("-Damage Multiplier Removed-", 10)
    end)
end
 
local function fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddNetwork()
    MakeInventoryPhysics(inst)
      
    inst.AnimState:SetBank("violencepotion")
    inst.AnimState:SetBuild("violencepotion")
    inst.AnimState:PlayAnimation("idle")
   
    inst.entity:SetPristine()
 
    if not TheWorld.ismastersim then
        return inst
    end
 
    inst:AddComponent("inspectable")
    inst:AddComponent("stackable")
    inst.components.stackable.maxsize = TUNING.STACK_SIZE_SMALLITEM
	
    inst:AddComponent("edible")
    inst.components.edible.foodtype = FOODTYPE.MEAT
    inst.components.edible.hungervalue = 0 --gives 10 by default
    inst.components.edible:SetOnEatenFn(ondrinkviolence)
   
    inst:AddComponent("inventoryitem")
    inst.components.inventoryitem.imagename = "violencepotion"
    inst.components.inventoryitem.atlasname = "images/inventoryimages/violencepotion.xml"
      
    --inst:AddComponent("edible")
    --inst.components.edible.hungervalue = 0 --gives 10 by default
   
    inst:AddComponent("tradable")
 
    MakeHauntableLaunch(inst)
     
    return inst
end

return Prefab("common/inventory/violencepotion", fn, assets)

I know Felix's Marvelous Potions Mod had a way to remedy this problem but it looked way beyond my comprehension. Isn't there an easier way to make it so if person uses this potion once, he can't use it again until the cooldown is finished(Different from Felix's approach). Or is Felix's solution the best way to go at it?

Felix Example:

  Reveal hidden contents


local assets=
{
	Asset("ANIM", "anim/healthpotion.zip"),
	Asset("ATLAS", "images/inventoryimages/armorpotion.xml"),
	Asset("IMAGE", "images/inventoryimages/armorpotion.tex"),
		Asset("ATLAS", "images/inventoryimages/armorpotion_off.xml"),
	Asset("IMAGE", "images/inventoryimages/armorpotion_off.tex"),
	Asset("SOUNDPACKAGE", "sound/potion_sounds.fev"),
	Asset("SOUND", "sound/potion_sounds.fsb")
}

local prefabs = 
{

}	


local function endeffect(inst)
    if inst:HasTag("potioncooldown") then
						local olddefense = inst.components.health.absorb
			local newdefense = (olddefense - TUNING.ARMORPOTIONBUFF)
			  inst.components.health:SetAbsorptionAmount(newdefense)
			
	inst:RemoveTag("potioncooldown")

  inst._fx2 = SpawnPrefab("attune_ghost_in_fx")
    inst._fx2.entity:SetParent(inst.entity)
    inst._fx2.Transform:SetPosition(0, 0, 0)
	
	if inst._fx ~= nil then
	inst._fx:Remove() end
       inst:PushEvent("potioncheck")
	   else
	   end
end


local function onbecameghost(inst)
if inst:HasTag("potioncooldown") then
	inst:RemoveTag("potioncooldown")
 inst:PushEvent("potioncheck")
 
			local olddefense = inst.components.health.absorb
			local newdefense = (olddefense - TUNING.ARMORPOTIONBUFF)
			  inst.components.health:SetAbsorptionAmount(newdefense)
if inst._fx ~= nil then
	inst._fx:Remove() end

			end
					

end

local function givepotion(inst)
local potion = "powerpotion"
local item = SpawnPrefab(potion)
if inst.components.inventory ~= nil then

		 item.components.inventoryitem:SetOwner(inst)
		 inst.components.inventory:GiveItem(item)

end

end

local function OnEaten(inst, eater)

if eater:HasTag("potioncooldown") and eater:HasTag("player") then
 eater:DoTaskInTime(0, givepotion)
			eater.components.talker:Say("My body is still recovering from the last potion.") 
 eater.sg:GoToState("refuseeat")


else


eater._fx = SpawnPrefab("armorpotionfx")
    eater._fx.entity:SetParent(eater.entity)
    eater._fx.Transform:SetPosition(0, 3, 0)
	
	eater:AddTag("potioncooldown")
    eater:ListenForEvent("ms_becameghost", onbecameghost)
			    eater:DoTaskInTime(TUNING.BUFFPOTIONCD , endeffect)	
	eater.SoundEmitter:PlaySound("potion_sounds/potion/drink_potion")
	
			if eater.components.health then
				
			local olddefense = eater.components.health.absorb
			local newdefense = (olddefense + TUNING.ARMORPOTIONBUFF)
			  eater.components.health:SetAbsorptionAmount(newdefense)
	
			
			end			
  eater:PushEvent("potioncheck")		
			
			end		
end
   
   ------------------------------------------------------===========================

local function UpdateInventoryState(inst)
    local viewer = inst.components.inventoryitem:GetGrandOwner()
    while viewer ~= nil and viewer.components.container ~= nil do
        viewer = viewer.components.container.opener
    end
    if viewer ~= nil then
	if viewer:HasTag("potioncooldown") then
       inst:RemoveComponent("edible") 
	inst.components.inventoryitem.imagename = "armorpotion_off"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/armorpotion_off.xml"	   
	   inst:PushEvent("imagechange")
    else
if inst.components.edible == nil then	inst:AddComponent("edible") end	 	
	if inst.components.edible.foodtype == FOODTYPE.GENERIC then inst.components.edible.foodtype = FOODTYPE.GOODIES	end
	inst.components.inventoryitem.imagename = "armorpotion"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/armorpotion.xml" 
	inst:PushEvent("imagechange")
	inst.components.edible.healthvalue = 0
    inst.components.edible.hungervalue = 0
	inst.components.edible.sanityvalue = 0
	inst.components.edible:SetOnEatenFn(OnEaten)

    end
	end
end

local function StopWatchingSanity(inst)
    if inst._sanitywatching ~= nil then
        inst:RemoveEventCallback("potioncheck", inst.OnWatchSanityDelta, inst._sanitywatching)
        inst._sanitywatching = nil
    end
end

local function WatchSanity(inst, target)
    StopWatchingSanity(inst)
    if target ~= nil then
        inst:ListenForEvent("potioncheck", inst.OnWatchSanityDelta, target)
        inst._sanitywatching = target
    end
end

local function StopWatchingForOpener(inst)
    if inst._openerwatching ~= nil then
        inst:RemoveEventCallback("onopen", inst.OnContainerOpened, inst._openerwatching)
        inst:RemoveEventCallback("onclose", inst.OnContainerClosed, inst._openerwatching)
        inst._openerwatching = nil
    end
end

local function WatchForOpener(inst, target)
    StopWatchingForOpener(inst)
    if target ~= nil then
        inst:ListenForEvent("onopen", inst.OnContainerOpened, target)
        inst:ListenForEvent("onclose", inst.OnContainerClosed, target)
        inst._openerwatching = target
    end
end


local function BeginWatch(inst)
     inst.components.inventoryitem:SetOnPutInInventoryFn(function(inst, owner)
    if owner.components.container ~= nil then
        WatchForOpener(inst, owner)
        WatchSanity(inst, owner.components.container.opener)
    else
        StopWatchingForOpener(inst)
        WatchSanity(inst, owner)
    end
    UpdateInventoryState(inst)
    end)
	
	    inst.components.inventoryitem:SetOnDroppedFn(function(inst)
 
         StopWatchingSanity(inst)
    UpdateInventoryState(inst)
    end)
end

local function onload(inst, data)


end



----------------------------------------------==========================
	
local function fn(Sim)
    local inst = CreateEntity()
	local trans = inst.entity:AddTransform()
	local anim = inst.entity:AddAnimState()
	inst.entity:AddSoundEmitter()

	inst.entity:AddNetwork()
    MakeInventoryPhysics(inst)
    
    anim:SetBank("healthpotion")
    anim:SetBuild("healthpotion")
    anim:PlayAnimation("armor")
    
      inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    
	

	inst.entity:SetPristine()
	
    inst:AddComponent("inspectable")
	

    inst:AddComponent("inventoryitem")
	inst.components.inventoryitem.imagename = "armorpotion"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/armorpotion.xml"
	

	 inst:AddComponent("stackable")

	 
	 		inst:AddTag("waterproofer")
	    inst:AddComponent("waterproofer")
    inst.components.waterproofer:SetEffectiveness(0.01)
----------------------------------------   

   
   
	  inst.OnWatchSanityDelta = function(viewer)
        if viewer:HasTag("potioncooldown") then
       inst:RemoveComponent("edible") 	 
	   	inst.components.inventoryitem.imagename = "armorpotion_off"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/armorpotion_off.xml"
	   inst:PushEvent("imagechange")
        else 
if inst.components.edible == nil then	inst:AddComponent("edible") end	  
	inst.components.inventoryitem.imagename = "armorpotion"
	inst.components.inventoryitem.atlasname = "images/inventoryimages/armorpotion.xml"
			inst:PushEvent("imagechange")
	inst.components.edible.healthvalue = 0
    inst.components.edible.hungervalue = 0
	inst.components.edible.sanityvalue = 0
	if inst.components.edible.foodtype == FOODTYPE.GENERIC then
		inst.components.edible.foodtype = FOODTYPE.GOODIES
	end
	inst.components.edible:SetOnEatenFn(OnEaten)
        end
    end
	
	
	    inst.OnContainerOpened = function(container, data)
        WatchSanity(inst, data.doer)
        UpdateInventoryState(inst)
    end

    inst.OnContainerClosed = function()
        StopWatchingSanity(inst)
        UpdateInventoryState(inst)
    end
	
	
	    inst._sanitywatching = nil
    inst._openerwatching = nil
	
	
	    inst.OnLoad = onload
	
	inst:AddComponent("edible")
	inst.components.edible.healthvalue = 0
    inst.components.edible.hungervalue = 0
	inst.components.edible.sanityvalue = 0
	inst.components.edible.foodtype = FOODTYPE.GOODIES
	inst.components.edible:SetOnEatenFn(OnEaten)

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

    BeginWatch(inst)

    
    return inst
end

return Prefab( "common/inventory/armorpotion", fn, assets) 

You could always put a cap on the maximum they can drink. For example perform a check on how much their damage multiplier is before they consume the potion. 

 

If eater.components.combat.damagemultiplier < 3 then ...

 perform normal function

else

"Too much rage my belly hurts"

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