Jump to content

A 'Smeltdown' mod -- how to enable smelter 'recipe' only when input item not a favorite?


mattrk

Recommended Posts

Hello,

 

This is my first post. I'll try to provide sufficient details and not write a hopeless request.

 

I have decided to make a "Smeltdown" mod. After some research, it turns out there are at least three others in existence. However, they each have drawbacks and I want to make one that does not have these drawbacks and learn about modding at the same time.

 

Essentially I am making a number of recipes that convert metal-containing items back in to a certain number of ingots.

 

However, I would like these reciped to be:

  1. Only visible when the required items are at hand
  2. Only visible when there are at least 1+ non-equipped required items
  3. Only visibile when, in addition to point 2, there are at least 1+ non-favorited required items

At the moment I have managed to find information relating to 1 and 2, to work out it is something like the following (in the recipe's Constructible Object window):

Target		Function Name		Function Info	Comp    Value   Operator
PL		GetItemCount		Item: 'Foo'	>=	1	AND
S		IsEquipped				>=	1	AND
S               IsInFavorState                          >=      1       AND
...

However, I know this won't work, since lines two and three are not right as they are. I suspect IsInFavorState is entirely the wrong function, but it is the most appropraite-sounding one I could find.

 

So, my questions:

  1. Is what I am trying to do possible?
  2. How do I go about doing it? What mistakes did I make?
  3. Where should I have found the information, rather than posting here?

Thank you & regards,

-- quixotic-cynic

Link to comment
Share on other sites

I think all of those requirements would be possible to implement. The first two can be done with condition functions, but the third one would probably require a combination of scripting and a condition function.
First two:
PL	GetItemCount	ITEM > 1	OR
PL	GetItemCount	ITEM >= 1	AND
PL	GetEquipped	ITEM == 0	OR/AND
- Player has to have two or more of the item
or
- Player has to have one or more of the item AND not have said item equipped
The documentation for GetEquipped states that it does not work for items equipped in the left hand.
I think IsInFavorState has to do with AI, but that is a guess.
The third requirement could be done by adding a copy of favorited items to a container and using the GetItemCount condition function to see if the container, which stores the copies of favorited items, contains the item. The script would require SKSE. In this example the script would be attached to a quest, but it could be attached to the container instead (in which case you would have to change the first line to be "Scriptname SOMENAMEHERE Extends ObjectReference").
Scriptname SOMENAMEHERE Extends Quest

Actor Property PlayerRef Auto
ObjectReference Property kFavoritesContainer Auto ;Points at the container in the isolated cell
Bool bUpdateFavorites

Event OnInit()
	RegisterForMenu("InventoryMenu")
EndEvent

Event OnMenuOpen(String asMenuName)
	RegisterForKey(Input.GetMappedKey("Toggle POV"))
EndEvent

Event OnKeyDown(Int aiKey)
	bUpdateFavorites = True
EndEvent

Event OnMenuClose(String asMenuName)
        UnregisterForAllKeys()
	If(bUpdateFavorites)
		UpdateFavorites()
	EndIf
	bUpdateFavorites = False
EndEvent

Function UpdateFavorites()
	Int iSize = PlayerRef.GetNumItems()
	While(iSize >= 0)
		Form kForm = PlayerRef.GetNthForm(iSize)
		Int iCount = kFavoritesContainer.GetItemCount(kForm)
		Bool bFavorited = Game.IsObjectFavorited(kForm)
		If((bFavorited) && (iCount == 0))
			kFavoritesContainer.AddItem(kForm)
		ElseIf((!bFavorited) && (iCount > 0))
			kFavoritesContainer.RemoveItem(kForm, iCount)
		EndIf
		iSize -= 1
	EndWhile
EndFunction

This is something I just wrote based on what I use in All Geared Up, so it may or may not work as is.

 

The condition function stack would then be:

R	GetItemCount	ITEM == 0	AND
PL	GetItemCount	ITEM > 1	OR
PL	GetItemCount	ITEM >= 1	AND
PL	GetEquipped	ITEM == 0	OR/AND

The reference in the first GetItemCount would be the container that exists in the isolated cell.

 

- Item is not favorited
and
- Player has to have two or more of the item
or
- Player has to have one or more of the item AND not have said item equipped
Edited by mrpwn
Link to comment
Share on other sites

Thank you, mrpwn, for the extremely detailed response.

 

Fortunately, I can program in Java a bit so I understand the script (just about) so I think I may actually be able to implement this (which is important, since there is little point in making another meltdown mod that is the same as all the others).

 

The only thing I worry about is getting people to install SKSE, but then again, a lot of mods use this already.

 

Thanks again. I shall do my best to make use of the information provided.

 

Regards, --quixoticynic

Link to comment
Share on other sites

  • 2 weeks later...

 

I think all of those requirements would be possible to implement. The first two can be done with condition functions, but the third one would probably require a combination of scripting and a condition function.
First two:
PL	GetItemCount	ITEM > 1	OR
PL	GetItemCount	ITEM >= 1	AND
PL	GetEquipped	ITEM == 0	OR/AND
- Player has to have two or more of the item
or
- Player has to have one or more of the item AND not have said item equipped

 

Edit: The order as shown above does not function correctly. It processes the rules as follows: ((is the item count > 1 OR is the item count >= 1) AND is the item not equipped) hence the recipe will never show up if you have one of the items equipped. A functioning order is as follows:

PL	GetItemCount	ITEM >= 1	AND
PL	GetEquipped	ITEM == 0	OR
PL	GetItemCount	ITEM > 1	AND

I hope this helps people.

 

I still appreciate the help or I would not have seen how to do the 2nd part. Thanks, --QC

Link to comment
Share on other sites

Update: I have spent a few hours trying to get the last part working.

 

I couldn't get the script to work at all when attached to the chest, using Extends ObjectReference, so I tried attaching the script to a quest.

 

The script runs when attached to the quest, but I don't understand how to get the object reference for the chest, to then use further within the script.

 

I think it relates to the line:

ObjectReference Property kFavoritesContainer Auto ;Points at the container in the isolated cell

However, I can't see how it will associate kFavoritesContainer with the chest item.

 

Edit: I worked out a bit more:

 

 

A property allows your script to use information in a data file by providing a special interface that they can both access. From your script's point of view, a property is an arbitrary piece of information of a certain specified type, like "Actor" or "Quest". From the Creation Kit's point of view, it is a point at which information of that type can be inserted into the instance of your script attached to the object you're editing.

 

[...]

 

Once you've defined your property, you can use it in your script as though it points to the object that you want to use. Once you've attached your script to the right object in the Creation Kit, you will then need to use it to associate your property with the right object via a drop-down list of all objects of your property's type.

(Source: http://www.cipscis.com/skyrim/tutorials/beginners.aspx)

 

I have now set the property by right clicking on the script in the Construction Kit, clicking edit, and choosing the correct cell + chest. Unfortunately I still can't get it working.

 

If someone understands what I need to do, could they please be kind enough to point me in the right direction.

 

Thanks, --QC

Link to comment
Share on other sites

Thank you for the suggestion. I think I have just done that just now -- I'll Google a bit more to see if I have done it correctly. Thanks, --QC

 

Edit: It is now almost completely working. I have checked the chest in the cell I created and has the relevant items. That suggests to me that it is the conditional rules that are not quite right now -- tweaking.

 

Edit 2: Fully Working. The following conditional rules work perfectly, in conjunction with mrpwn's script: The following rules turned out to be bugged (see post below):

R     GetItemCount    Armor:'ArmorDwarvenBoots'    ==    0.00    OR
PL    GetItemCount    Armor:'ArmorDwarvenBoots'    >     1.00    AND
RL    GetItemCount    Armor:'ArmorDwarvenBoots'    ==    0.00    OR
PL    GetItemCount    Armor:'ArmorDwarvenBoots'    >     1.00    AND

Obviously, change ArmorDwarvenBoots to the item of interest.

 

Bug (can anyone fix?): If you access the smelter really fast after setting a favorite item you can still smelt the favorite item (i.e. the script works a bit slowly). Any suggestions anyone?

 

Thanks all, --QC

Link to comment
Share on other sites

Updated the scripted posted earlier

 

 

Scriptname SOMENAMEHERE Extends Quest

Actor Property PlayerRef Auto
ObjectReference Property kFavoritesContainer Auto ;Points at the container in the isolated cell
Bool bUpdateFavorites

Event OnInit()
	RegisterForMenu("InventoryMenu")
	RegisterforCrosshairRef()
EndEvent

Event OnMenuOpen(String asMenuName)
	RegisterForKey(Input.GetMappedKey("Toggle POV"))
EndEvent

Event OnKeyDown(Int aiKey)
	bUpdateFavorites = True
EndEvent

Event OnMenuClose(String asMenuName)
        UnregisterForAllKeys()
	If(bUpdateFavorites)
		UpdateFavorites()
	EndIf
	Utility.Wait(1)
	bUpdateFavorites = False
EndEvent

Function UpdateFavorites()
	Int iSize = PlayerRef.GetNumItems()
	While(iSize >= 0)
		Form kForm = PlayerRef.GetNthForm(iSize)
		Int iCount = kFavoritesContainer.GetItemCount(kForm)
		Bool bFavorited = Game.IsObjectFavorited(kForm)
		If((bFavorited) && (iCount == 0))
			kFavoritesContainer.AddItem(kForm)
		ElseIf((!bFavorited) && (iCount > 0))
			kFavoritesContainer.RemoveItem(kForm, iCount)
		EndIf
		iSize -= 1
	EndWhile
EndFunction

Keyword Property SmelterKYWD Auto
Form RefBase
Event OnCrosshairRefChange(ObjectReference ref)
	If ref
		RefBase = ref as form
		If RefBase.HasKeyword(SmelterKYWD) ;is a valid smelter
			While bUpdateFavorites == false
				ref.BlockActivation(true)
			EndWhile
			If bUpdateFavorites == true
				ref.BlockActivation(false)
			EndIf
		EndIf
	EndIf
EndEvent 

 

 

Added a wait statement in the OnMenuClose event after the UpdateFavorites function has been called if needed. Also registered for a crosshair event and when the player mouses over a smelter and the bUpdateFavorites bool is false it will block the activation of the smelter so the player cannot smelt until after the UpdateFavorites function has finished and the bool flipped back to true. Do be sure to assign the keyword for the smelter (the same one used on the recipes) in the added property.

 

I'm thinking it might work. Worth a try at least.

Link to comment
Share on other sites

Wow, thank you very much for the updated script. I'll try it out now and post the result.

 

Edit: The above script works really well. It requires a small change, however, with the ref.BlockActivation(false) being replaced with ref.BlockActivation(true) and vice versa.

 

The above conditional rules that I proposed in my previous post now appear to be bugged: equipping an item stops any of that type from being smelted.

 

Am in the process of fixing the conditional bug. The pages http://creationkit.com/conditions and http://en.wikipedia.org/wiki/Distributive_property#Propositional_logic have been very useful. However, unfortunately there is still a bug: when there is a single non-favorite, non-eqipped item it will not smelt. It is very puzzling at the moment -- perhaps I am overlooking something obvious?

 

Edit: I think I have worked out the correct combination of rules: Another attempt (still broken):

PL    GetItemCount    Armor:'ArmorDwarvenBoots'    >=    1.00    AND
R     GetItemCount    Armor:'ArmorDwarvenBoots'    ==    0.00    AND
RL    GetItemCount    Armor:'ArmorDwarvenBoots'    ==    0.00    OR
PL    GetItemCount    Armor:'ArmorDwarvenBoots'    >     1.00    AND

Once I alter all of the rules in the mod and upload it. I will also upload a separate .esp file for people who want to include 'favorite item protection' in their own mod. I will of course credit mrpwn and IsharaMeredin -- I could never have done it otherwise.

 

Thanks again, --QC

Link to comment
Share on other sites

In an attempt to cut down on the conditionals, I started trying to integrate the 'equipped check' into the script.

 

My attempt is [Edit: removed due to it being incorrect -- see correct version on page 2 of the thread]

 

It is currently flawed since GetNthForm() gets the form of the item whereas IsEquipped() requires the actual object (i.e. it is the difference between a class and an object in Java) -- if I understand correctly.

 

I'll try again tomorrow night. ^_^

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...