Jump to content

Recommended Posts

tumblr_ovlnofjYLE1w01el4o1_250.gif

 

So my mod is almost done. Did it mostly myself, and I'm super proud. :D I just need to finish the sprites, really, and make the custom voice. A feature of my mod is my character can switch between three states to represent the different hounds, and each state has a different appearance and abilities. 

Spoiler

dmqkw5.png 

Hound: Standard stuff. Minor insulation against cold, slightly susceptible to overheating. Eat a purple gem to go back to hound form.
Red hound: Immune to overheating and fire damage, but freezes and gets hungry faster and takes more damage from freezing. Automatically cooks food in the inventory. Eat a red gem to go into red hound form.
Blue hound: My personal favorite. Immune to freezing and acts as an ice box, but overheats and gets hungry faster. Speaks with a pretty blue text. Eat a blue gem to go into blue hound form. Would like to take more damage from overheating, but I can't find a TUNING.OVERHEAT_KILL_TIME or similar in tuning.lua, only TUNING.FREEZING_KILL_TIME.

I just need help with one last thing. Two, actually. First off, I am trying to get it so that red hound Wilkas automatically cooks food in his inventory. I have tried to find character mods that do something similar, but I was not able to find any. This is the code I have now.

Spoiler

local function OnEat(inst, food)
    if food.components.edible
       and food.components.edible.foodtype == "GEMBLUE" then
            inst.AnimState:SetBuild("wilkas_ICE")
			inst.components.temperature.maxtemp = ( 80 )
			inst.components.temperature.mintemp = ( 30 )
			inst.components.talker.colour = Vector3(.6, .6, .9, 1)
			inst.components.hunger.hungerrate = 1.25 * TUNING.WILSON_HUNGER_RATE
			inst:AddTag("fridge")
		end
	if food.components.edible
       and food.components.edible.foodtype == "GEMRED" then
            inst.AnimState:SetBuild("wilkas_FIRE")
			inst.components.temperature.maxtemp = ( 60 )
			inst.components.temperature.mintemp = ( -10 )
			inst.components.health.fire_damage_scale = 0
			inst.components.temperature.hurtrate = TUNING.WILSON_HEALTH / TUNING.FREEZING_KILL_TIME * 1.5 
			inst.components.talker.colour = Vector3(.9, .4, .4, 1)
			inst.components.hunger.hungerrate = 1.25 * TUNING.WILSON_HUNGER_RATE
			--In case was ice Wilkas before becoming fire Wilkas, thus has a "fridge" tag.
			inst:RemoveTag("fridge")
		end
	if food.components.edible
       and food.components.edible.foodtype == "GEMPURP" then
            inst.AnimState:SetBuild("wilkas")
			inst.components.talker.colour = Vector3(.9, .4, .4, 1)
			inst.components.hunger.hungerrate = 1 * TUNING.WILSON_HUNGER_RATE
			--In case was ice Wilkas before becoming normal Wilkas, thus has a "fridge" tag.
		    inst:RemoveTag("fridge")
		end
end

 

I know that Packim Baggims' fire form automatically cooks food, so I looked into his (its?) code for insight. I found this in Packim's code.

Spoiler

		for i = 1, container:GetNumSlots() do
	        local item = container:GetItemInSlot(i)
	     	if item then 
	     		local replacement = nil 
		     	if item.components.cookable then 
		     		replacement = item.components.cookable:GetProduct()
		     	elseif item.components.burnable then 
		     		replacement = "ash"
		     	end  
		     	if replacement then 
	     			local stacksize = 1 
	     			if item.components.stackable then 
	     				stacksize = item.components.stackable:StackSize()
	     			end 
	     			local newprefab = SpawnPrefab(replacement)
	     			if newprefab.components.stackable then 
	     				newprefab.components.stackable:SetStackSize(stacksize)
	     			end 
	     			container:RemoveItemBySlot(i)
	     			item:Remove()
	     			container:GiveItem(newprefab, i)
	     		end 
		     end 
		end 

 

Now, when I tried cobbling this in with Wilkas' code...

    if food.components.edible
       and food.components.edible.foodtype == "GEMRED" then
            inst.AnimState:SetBuild("wilkas_FIRE")
            --it went here
        end

It worked, somewhat, but only cooked food that was either already in Wilkas' inventory upon transforming into red hound Wilkas, or food that was spawned in via console commands. Food that was picked up off the ground, off bushes, etc. did not get cooked. I assume this is because with Packim, whom I ripped the code from, how it works is you put the food in him, close him, and when you open him again you get cooked food where your raw stuff was. Which is fine and all, but you can't exactly "open and close" a character's inventory. Though I could easily be wrong.

If anyone could help me with this, I'd much appreciate it. These are just the last things I need to do before my mod's done. Minus finishing the sprites and stuff, of course. :) I'm still not great at all with coding, so the solution may be much simpler than I think.

Wilkas the Hound's Friend.zip

Edited by Whitefang45
HAM compatibility issue fixed

Hello again, m8 :) In order to help with the RoG/SW compatibility, I'd need to see your modinfo.lua and a crash log from when the crash happens.

Now, that Packim Baggims code is pretty cool, but as your code is only called whenever your character changes form, the code obviously also only runs when changing form. What you nee to do, is figure our when your character should cook the food, and then find a function to hook the code up to...or make one yourself :) I looked into what things you can hook up to in the inventory, like if there were functions or events in place which we could have your code triggered by, but didn't find any that would suffice. GiveItem doesn't push events every time, only when e.g. getting an item you don't have any of and such. Not when you add to a stack etc. But we can extend e.g. the GiveItem function because it's not local, and run our own code after it. Look at this. Careful. Read the comments. These code snippets go three different places.

-- We put all the code in a function that takes a container as a parameter.
local cookFoodFn = function(container)
	for i = 1, container:GetNumSlots() do
		local item = container:GetItemInSlot(i)
		if item then 
			local replacement = nil 
			if item.components.cookable then 
				replacement = item.components.cookable:GetProduct()
			elseif item.components.burnable then 
				replacement = "ash"
			end  
			if replacement then 
				local stacksize = 1 
				if item.components.stackable then 
					stacksize = item.components.stackable:StackSize()
				end 
				local newprefab = SpawnPrefab(replacement)
				if newprefab.components.stackable then 
					newprefab.components.stackable:SetStackSize(stacksize)
				end 
				container:RemoveItemBySlot(i)
				item:Remove()
				container:GiveItem(newprefab, i)
			end 
		 end 
	end 
end


-- Do this at the bottom of your master_postinit.
-- We extend the GiveItem function of your inventory.
local oldGiveItem = inst.components.inventory.GiveItem
function inst.components.inventory:GiveItem(inst, slot, src_pos, ...)
	-- We call the original function first, and save its return value.
	local returnValue = oldGiveItem(self, inst, slot, src_pos, ...)
	
	-- Whatever happened, we trigger the cooking of all cookables in the inventory slots,
	-- but only if the function is available on the inventory component (this is key!).
	if self.giveItemExtension then
		self.giveItemExtension(self.inventorySlots)
		-- If you also want to cook all items in your backpack, uncomment the next lines.
		local backpack = self:GetOverflowContainer()
		if backpack ~= nil then
			self.giveItemExtension(backpack)
		end
	end
	
	-- Then we return the result of the original function.
	return returnValue
end


-- Now, in your code that changes between the different hound states,
-- just put in this line for the fire-hound:
inst.components.inventory.giveItemExtensionFn = cookFoodFn

-- ...and for the others, put in this:
inst.components.inventory.giveItemExtensionFn = nil

 

Hello again! :) It's nice to see you! How've you been? Well, I hope?

I genuinely appreciate you helping me yet again. The code doesn't crash, which is good I suppose, and Wilkas still becomes fire Wilkas when he eats a red gem, but things aren't getting cooked. Should I have changed "container" to "inventory"?

And sorry about that! It slipped my mind. Here's my log and modmain.lua. I'm pretty sure the issue lies in wilkas.lua within the "shedding" function where I try to call on the Hamlet seasons, but I'll include my modmain.lua just in case.

modmain.lua

wilkas.lua

log.txt

That's good! Glad to hear you're doing well! :D And you could say I'm having fun. ;) Been working a lot on Wilkas' sprites, which is pretty fun in my book. It's a bit of a challenge to replicate the DS art style, but I'm enjoying the challenge a lot. Doing the sprites is my favorite part.

Ooh, I didn't even notice that. Okay, so I gave it a fix, calling it giveItemExtension instead of giveItemExtensionFn in the OnEat function, but now I've a new problem. Yet again, it doesn't crash, that is until you eat a red gem. Doesn't crash on eating the gem, but does if you pick anything up afterwards, claiming local 'container' to be a nil value. I recalled seeing this in Packim's code just above the cooking code (not sure what to call it, lol):

	local container = inst.components.container

Which I assume is what I want? However, it continues to claim 'container' a nil value if I put it in fn(), but in the main bit of code, it claims 'inst' to be the problem. I remember you writing in the handy little notes last time that "What happens, is that MakePlayerCharacter sets up all the stuff ... it calls the given postinit function (in this case fn) giving it the player character it has just created as a parameter (called "inst" in this case)."

Ok so, it should look like this? Just clarifying before I try it and complain it doesn't work lol. My reading comprehension is not the best, so I'd like to be sure this is all in the right spot and looking okay.

Spoiler

local cookFoodFn = function(container)
	for i = 1, container:GetNumSlots() do
		local item = container:GetItemInSlot(i)
		if item then 
			local replacement = nil 
			if item.components.cookable then 
				replacement = item.components.cookable:GetProduct()
			elseif item.components.burnable then 
				replacement = "ash"
			end  
			if replacement then 
				local stacksize = 1 
				if item.components.stackable then 
					stacksize = item.components.stackable:StackSize()
				end 
				local newprefab = SpawnPrefab(replacement)
				if newprefab.components.stackable then 
					newprefab.components.stackable:SetStackSize(stacksize)
				end 
				container:RemoveItemBySlot(i)
				item:Remove()
				container:GiveItem(newprefab, i)
			end 
		 end 
	end 
end

local function OnEat(inst, food)
    if food.components.edible
       and food.components.edible.foodtype == "GEMBLUE" then
            inst.AnimState:SetBuild("wilkas_ICE")
			inst.components.temperature.maxtemp = ( 80 )
			inst.components.temperature.mintemp = ( 30 )
			inst.components.talker.colour = Vector3(.6, .6, .9, 1)
			inst.components.hunger.hungerrate = 1.25 * TUNING.WILSON_HUNGER_RATE
			inst:AddTag("fridge")
			inst.components.inventory.giveItemExtension = nil
		end
	if food.components.edible
       and food.components.edible.foodtype == "GEMRED" then
            inst.AnimState:SetBuild("wilkas_FIRE")
			inst.components.temperature.maxtemp = ( 60 )
			inst.components.temperature.mintemp = ( -10 )
			inst.components.health.fire_damage_scale = 0
			inst.components.temperature.hurtrate = TUNING.WILSON_HEALTH / TUNING.FREEZING_KILL_TIME * 1.5 
			inst.components.talker.colour = Vector3(.9, .4, .4, 1)
			inst.components.hunger.hungerrate = 1.25 * TUNING.WILSON_HUNGER_RATE
			inst:RemoveTag("fridge")
			inst.components.inventory.giveItemExtension = cookFoodFn
		end
	if food.components.edible
       and food.components.edible.foodtype == "GEMPURP" then
            inst.AnimState:SetBuild("wilkas")
			inst.components.talker.colour = Vector3(.9, .4, .4, 1)
			inst.components.hunger.hungerrate = 1 * TUNING.WILSON_HUNGER_RATE
		    inst:RemoveTag("fridge")
			inst.components.inventory.giveItemExtension = nil
		end
end

local fn = function(inst)
	--other stuff like stats went here
local oldGiveItem = inst.components.inventory.GiveItem
function inst.components.inventory:GiveItem(inst, slot, src_pos, ...)
	local returnValue = oldGiveItem(self, inst, slot, src_pos, ...)
	if self.giveItemExtension then
		self.giveItemExtension(self.itemslots)
		local backpack = self:GetOverflowContainer()
		if backpack ~= nil then
			self.giveItemExtension(backpack)
		end
	end
	return returnValue
end

end

 

 

Okay, I gave that a go. Didn't complain about the GetNumSlots thing anymore, but gave me this now.

Wilkas the Hound's Friend/scripts/prefabs/wilkas.lua:394: attempt to call method 'GetOverflowContainer' (a nil value)

I figured okay, since 'GetOverflowContainer' was in a part that could be commented out if I wanted things inside a backpack to get cooked too, I could try that and hopefully it'd fix it. Commenting out these three lines

		local backpack = self:GetOverflowContainer()
		if backpack ~= nil then
			self.giveItemExtension(backpack)

led to a crash, but only commenting out "= self:GetOverflowContainer()" worked. Stuff got cooked as intended. I had to remove the thing where burnables get turned into ash, as it was converting even things that were cookable into ash, such as watermelons and seeds. The only thing is, things that can get cooked and were already in a stack before getting cooked, were cooked and stayed as a stack. But, if I were to pick up another one, it would get cooked but form its own stack of one.

It's starting to work, which gives me hope?

Edited by Whitefang45

Your crash was probably caused by you not commenting out the "end" of that if-statement.

But it can work with backpacks as well. Damn, it's because I've been looking at DST code again. Just replace this:

		local backpack = self:GetOverflowContainer()
		if backpack ~= nil then
			self.giveItemExtension(backpack)
		end

with this:

		if self.overflow ~= nil then
			self.giveItemExtension(self.overflow)
		end

 

Oh, I see. That would make sense, haha. Went back and commented out the 'end' this time, didn't get a crash, so you were right.

Doing that makes the GetNumSlots issue come back, however, I do think I'll leave it so stuff in backpacks doesn't get cooked. Perhaps backpacks could be used for carrying meats and fishes and etc. you'd like to turn into jerky, and the inventory could be used to cook them? I really am sorry you went through all that work just for me to say this. :( It does work as intended now, though, which is good! Thank you!

That's OK. I choose to. It's interesting :)

For the record, I just found out that the overflow works very differently in DS, so you'd instead have to do:

		if self.overflow ~= nil then
			self.giveItemExtension(self.overflow.components.container)
		end

 

Personally, I think it's kind of funny, how similar DS and DST code is, yet how different it is.

Aah, that works just fine! Thanks! :) If I ever decide down the road that I'd like to have stuff in backpacks get cooked after all, I'm all set!

Sure thing. :D I'll put it in a spoiler so the page isn't a mile long.

Spoiler

local cookFoodFn = function(container)
	for i = 1, container:GetNumSlots() do
		local item = container:GetItemInSlot(i)
		if item then 
			local replacement = nil 
			if item.components.cookable then 
				replacement = item.components.cookable:GetProduct()
			end  
			if replacement then 
				local stacksize = 1 
				if item.components.stackable then 
					stacksize = item.components.stackable:StackSize()
				end 
				local newprefab = SpawnPrefab(replacement)
				if newprefab.components.stackable then 
					newprefab.components.stackable:SetStackSize(stacksize)
				end 
				container:RemoveItemBySlot(i)
				item:Remove()
				container:GiveItem(newprefab, i)
			end 
		 end 
	end 
end

local function OnEat(inst, food)
    if food.components.edible
       and food.components.edible.foodtype == "GEMBLUE" then
			--stuff
			inst.components.inventory.giveItemExtension = nil
		end
	if food.components.edible
       and food.components.edible.foodtype == "GEMRED" then
			--stuff
			inst.components.inventory.giveItemExtension = cookFoodFn
		end
	if food.components.edible
       and food.components.edible.foodtype == "GEMPURP" then
			--stuff
			inst.components.inventory.giveItemExtension = nil
		end
end

local oldGiveItem = inst.components.inventory.GiveItem
function inst.components.inventory:GiveItem(inst, slot, src_pos, ...)
	local returnValue = oldGiveItem(self, inst, slot, src_pos, ...)
	if self.giveItemExtension then
		self.giveItemExtension(self)
		-- If you also want to cook all items in your backpack, uncomment the next lines.
		--if self.overflow ~= nil then
			--self.giveItemExtension(self.overflow.components.container)
		--end
	end
	return returnValue
end

 

Stuff's all working just fine now, aside from the stacking thing, but everything that gets picked up and is cookable, gets cooked, so long as it's in the inventory. :)

Edited by Whitefang45

Sorry, I guess I didn't explain it very well. :( Sorry! Say I have a stack of three limpets in my inventory already. That stack of three will get cooked and stay as a stack of three cooked limpets, but if I were to pick a limpet rock, giving me another limpet, that limpet would get cooked but form its own separate stack of one.

I should thank you, though, for helping me so much. :) Thank you again!

EDIT: On another note, I believe I have fixed the Hamlet problem?

Edited by Whitefang45

You're welcome, m8 :)

What is...the Hamlet problem? Do you have code specific to Hamlet? It's important to notice, that each newer DLC completely overwrites many game files from the previous DLCs. So, in your case, you're using some code in inventory.lua, and if that code is not the same in e.g. RoG, then you have to write new code which does the same thing but "in the RoG way", and make sure that when the game being played is RoG, then the Hamlet version of the code is not used, but the RoG version instead.

For the stacking thing, you could use GetNextAvailableSlot like this. That'll even put it in the backpack, if you have a stack of the product there:

local cookFoodFn = function(container)
	for i = 1, container:GetNumSlots() do
		local item = container:GetItemInSlot(i)
		if item then 
			local replacement = nil 
			if item.components.cookable then 
				replacement = item.components.cookable:GetProduct()
			end  
			if replacement then 
				local stacksize = 1 
				if item.components.stackable then 
					stacksize = item.components.stackable:StackSize()
				end 
				local slotFound = i
				local newprefab = SpawnPrefab(replacement)
				if newprefab.components.stackable then 
					newprefab.components.stackable:SetStackSize(stacksize)
					slotFound = container:GetNextAvailableSlot(newprefab)
				end 
				container:RemoveItemBySlot(i)
				item:Remove()
				container:GiveItem(newprefab, slotFound)
			end 
		 end 
	end 
end

 

Edited by Ultroman
Fixed typo

Ah, no. The Hamlet problem lied(?) in the shedding feature. The idea is, in spring and summer, monsoon and dry seasons, and humid and lush seasons Wilkas will drop a beard hair every few days, depending on the season. It worked as intended in all worlds, so that was good. However, on starting a Shipwrecked world with Hamlet enabled, it would crash. That's all fixed now. Works just fine with Hamlet enabled or not.

Thank you for that. :) However, it claims 'GetNextAvailableSlot' is not declared... I noticed stuff like 'local slotFound = i' and 'local newprefab = SpawnPrefab(replacement)' in the code, so would I have to do something like 'local GetNextAvailableSlot'?

Also, I have a small question... What is the difference between 'local function name()' and 'local name = function()', and what do the things like 'inst' and 'data' in the parentheses do? I see these two functions used a lot, but I'm not sure what the difference between them is. I saw someone saying after Googling it that they were pretty much the same thing, but then, why have two functions that are the same instead of just one? Apologies, I'm still trying to get a grasp on lua and what stuff does, and the way you explain things is pretty helpful...

On 23.4.2019 at 6:07 AM, Whitefang45 said:

Also, I have a small question... What is the difference between 'local function name()' and 'local name = function()', and what do the things like 'inst' and 'data' in the parentheses do? I see these two functions used a lot, but I'm not sure what the difference between them is. I saw someone saying after Googling it that they were pretty much the same thing, but then, why have two functions that are the same instead of just one? Apologies, I'm still trying to get a grasp on lua and what stuff does, and the way you explain things is pretty helpful...

They're just two different ways of declaring (describing and creating) a function. No difference whatsoever.

How have you gotten this far without knowing what inst and data are? OK...ehm...they are called parameters. We write functions to trivialize a query or do some activity. Take a chest as an example. We would like the chest to be able to answer whether it contains a certain item, or do some activity like locking the chest. For locking it, the chest might not need any information, it can just do it when you call a function on it declared as e.g. Lock(). No parameters needed. If the chest can only be locked using a key, it doesn't know whether you have the key if you don't tell the chest about it. So we put a parameter on the function declaration Lock(key), and now when you call Lock(key) you have to fill the key-parameter with a key (what key is does not matter for the purpose of this explanation). Now the lock function can check whether the given key is the right key, to see if it can lock itself using it. In this case, it might be nice to know whether the query was carried out, so the chest can return "true" if it locked itself, and it can return "false" if it did not. The caller of the function can react to the value returned, perhaps by making the character say "That's the wrong key." if the return-value was false, or "Nice loot!" if it was true.

In an example more related to what we're working with, we want to use the function declared as GiveItem(item, slot) to give an item to the container. If we don't give it an item, then there's nothing for the function to do, so we have to fill that parameter when calling the function. The function also takes a slot parameter, and will try to put the item in that slot, but if the slot is occupied and the item is not stackable or the stack is full, it will try to find another slot to put it in. If we do not fill the slot parameter, the function will try to find a slot. So we can call the function like this GiveItem(myItem, nil) and it will try to find a slot for the item.

In LUA, you can completely omit all the parameters which you would have filled with nils, as long as all the parameters to the right of them are also to be filled with nils, so we can shorten it to GiveItem(item) and it will still work. A better example would be this function in the health-component:

Health:DoDelta(amount, overtime, cause, ignore_invincible, afflicter, ignore_absorb)

That's a lot of parameters! But we usually only use it with the first one or two parameters filled, like

inst.components.health:DoDelta(5) -- Gives 5 health, and makes the health badge pulse and make a sound

or

inst.components.health:DoDelta(5, true) -- Gives 5 health, without making the health badge pulse or make a sound

We can omit the rest of the parameters, in which case LUA automatically fills them with nil. Now, when the DoDelta function uses e.g. the afflicter parameter, it first asks:

if afflicter then

When we are using an if-statement, we need to ask a true/false question, like "is my health higher than 50" (health > 50), so why does this work? That's because LUA considers nil to be false, so if something was passed to the function in the afflicter parameter, in which case it is not nil, we will enter this if-statement (if we haven't passed in false, that is). Now, if we wanted to give only the amount and the afflicter, then we would have to do this:

inst.components.health:DoDelta(5, nil, nil, nil, player)

We can only omit the last parameter, because we are filling out the second-to-last parameter, and in order to tell the function which parameter player is supposed to be, we have to maintain the number of parameters before it.

Anyway, when listening for events, you often see this:

inst:ListenForEvent("healthdelta", function(inst, data)
	-- do something
end

In order to understand where inst and data are coming from, you need to look at where the event is pushed. In this case, it is pushed in the health component like this:

self.inst:PushEvent("healthdelta", { oldpercent = old_percent, newpercent = self:GetPercent(), overtime = overtime, cause = cause, afflicter = afflicter, amount = amount })

Now, PushEvent always includes the entity (inst) it is being pushed by as the first parameter, and the data it was passed as the second parameter. Here, the data being passed on is the table {} of variables with their values.

Why does it work this way? You can just look at the entityscript.lua where you'll find the declaration of the PushEvent function, and many, many of the other functions we take for granted.

-- The function receives an event, which is a string identifier,
-- and a data parameter, which may or may not be filled.
-- Technically, event may not be filled, in which case it won't find any listeners,
-- or will maybe crash the code below.
function EntityScript:PushEvent(event, data)
	-- If there are any event listeners at all (very likely, hehe)
	if self.event_listeners then
		-- Get all the listeners registered for the given event.
		local listeners = self.event_listeners[event]
		-- If there are any listeners...
		if listeners then
			--(Klei comment) make a copy list of all callbacks first in case
			--(Klei comment) listener tables become altered in some handlers
			-- Find all the functions which the listeners have registered to be called when the given event happens.
			local tocall = {}
			for entity, fns in pairs(listeners) do
				for i, fn in ipairs(fns) do
					table.insert(tocall, fn)
				end
			end
			-- Call all the functions registered by the  listeners,
			-- and pass on "self" (an entity, "inst", since we are in the entityscript)
			-- as the first parameter, and the data received, as the second parameter.
			for i, fn in ipairs(tocall) do
				fn(self, data)
			end
		end
	end
	-- bla bla bla, more stuff omitted
end

 

Edited by Ultroman

Hello! I know it's been a while, as it was my birthday last week and my best friend surprised me by coming up here for two weeks, but I just wanted to take the time to say thank you for all your help. I thought it would be quite rude of me not to do so after you were so helpful and patient with me. I bookmarked this page and jotted down some notes from what you told me, as I found them helpful. Hope you don't mind!

One thing I wanted to point out though, for anyone else who may come looking, is there was a tiny typo. It should be

container:GetNextAvailableSlot(newprefab)

as the P in prefab was capitalized. :) 

Again, thank you for all your help yet again. I hope you have a good day! :D 

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
×
  • Create New...