Script listing items?

Post » Sun Jun 24, 2012 10:01 am

Hi.

I have a script that runs a lot of comparisons, and I realized that using Skyrim's useless properties/variables -system will take way too much time and effort.
I want to know if there's a way to check items using text, instead of properties/variables?

For example, if I could change my script:

MiscObject[] Property HT_TrapReplaceItemCheck  AutoMiscObject  Property HT_TrapReplacement  Autoif (HT_TrapReplacement == HT_TrapReplaceItemCheck[0])	  damage = (15 + worldlevel * 3)	  ;Iron Trap   elseIf (HT_TrapReplacement == HT_TrapReplaceItemCheck[1])	  damage = (20 + worldlevel * 4)	  ;Steel Trap   elseIf (HT_TrapReplacement == HT_TrapReplaceItemCheck[2])	  damage = (25 + worldlevel * 4)	  ;Dwarf Trap   elseIf (HT_TrapReplacement == HT_TrapReplaceItemCheck[3])	  damage = (30 + worldlevel * 4)	  ;Orc Trap   elseIf (HT_TrapReplacement == HT_TrapReplaceItemCheck[4])	  damage = (35 + worldlevel * 5)	  ;Ebony Trapendif

to something like this:


MiscObject  Property HT_TrapReplacement  Autoif (HT_TrapReplacement == HT_ItemWhatever01 as MiscObject)	  damage = (15 + worldlevel * 3)	  ;Iron Trap   elseIf (HT_TrapReplacement == HT_ItemWhatever02 as MiscObject)	  damage = (20 + worldlevel * 4)	  ;Steel Trap   elseIf (HT_TrapReplacement == HT_ItemWhatever03 as MiscObject)	  damage = (25 + worldlevel * 4)	  ;Dwarf Trap   elseIf (HT_TrapReplacement == HT_ItemWhatever04 as MiscObject)	  damage = (30 + worldlevel * 4)	  ;Orc Trap   elseIf (HT_TrapReplacement == HT_ItemWhatever05 as MiscObject)	  damage = (35 + worldlevel * 5)	  ;Ebony Trapendif

-This would make it a lot easier to update and less time consuming, then having to edit the damn property-list every time.

I don't quite know what keywords do, but could they be of use here?
User avatar
kitten maciver
 
Posts: 3472
Joined: Fri Jun 30, 2006 2:36 pm

Post » Sun Jun 24, 2012 10:14 am

Where is HT_ItemWhatever01 to HT_ItemWhatever05 defined? Eg, what do these objects contain?

Papyrus, like 99% of all programming languages, require you to declare variables/objects before using them. This isn't useless, it's actually extremely useful. All variables in Papyrus are essentially objects, this wouldn't work without declarations. Python, JAVA and other OOP languages are all the same.

In your original script why is the array HT_TrapReplaceItemCheck there? What does it contain?
User avatar
Gaelle Courant
 
Posts: 3465
Joined: Fri Apr 06, 2007 11:06 pm

Post » Sun Jun 24, 2012 1:13 pm

Where is HT_ItemWhatever01 to HT_ItemWhatever05 defined? Eg, what do these objects contain?

They are not defined, they are not supposed to be properties or variables.
I am asking if it's possible to do this without using properties or variables.

In your original script why is the array HT_TrapReplaceItemCheck there? What does it contain?

It contains the MiscObjects I want to use for comparison.
User avatar
Rhiannon Jones
 
Posts: 3423
Joined: Thu Sep 21, 2006 3:18 pm

Post » Sun Jun 24, 2012 11:48 am

You've lost me now, how can you compare something without using variables or properties?

Perhaps I've misunderstood completely what you're trying to ask. Can you explain differently what you're wanting to do?
User avatar
Bellismydesi
 
Posts: 3360
Joined: Sun Jun 18, 2006 7:25 am

Post » Sun Jun 24, 2012 2:54 pm

You've lost me now, how can you compare something without using variables or properties?

Perhaps I've misunderstood completely what you're trying to ask. Can you explain differently what you're wanting to do?

I want to compare two things, one that is a variable and one that is just text.
I have seen stuff like "0x000F37A" - can't I use that to compare with?
Or as I mentioned earlier keywords (I don't know how those work).
User avatar
Isabell Hoffmann
 
Posts: 3463
Joined: Wed Apr 18, 2007 11:34 pm

Post » Sun Jun 24, 2012 12:00 pm

Oh I get you now :)

In programming you can only compare things that are similar (same type). This makes sense, for instance you couldn't in real life compare a door to a thought or a bottle to a noise.
When a variable has text in programming speak we say that the type of the variable is a string.

In theory this would work:
if ((object.gettype() as String) == "type")    do somethingendif
Sadly this probably wont work very often in Papyrus... Papyrus is very strict about types and there's no auto-conversion between types. A language like PHP is incredibly loose and flexible with types and a language like C is even stricter than Papyrus.

"0x000F37A" is a String which can only be compared to another String (or an object which can be converted to a string).
One way that Papyrus is a little bit clever is that it knows "1" is an Int, "abc" is a String and "1.0" is a Float.
User avatar
Claire Lynham
 
Posts: 3432
Joined: Mon Feb 12, 2007 9:42 am

Post » Sun Jun 24, 2012 6:46 am

your asking if you can compare a literal string to an object by making three string the oIbject name essential, right? no you can't you have to compare variables and objects of the same type.
User avatar
Claudz
 
Posts: 3484
Joined: Thu Sep 07, 2006 5:33 am

Post » Sun Jun 24, 2012 9:27 am

"0x000F37A" is a String which can only be compared to another String (or an object which can be converted to a string).

I believe this might be what I'm looking for.
As you can see in the first script I posted (the one I use) I compare MiscObject to MiscObject. What I want to do is compare MiscObject to "string that points to a MiscObject".

I'm thinking something like the console command: "Player.AddItem FoodMead 11" -As seen in this example: http://www.creationkit.com/AddItem
In this example the game can take the ObjectID "FoodMead" and make something out of it.
I want to do the same thing, but change the name of the ObjectID to my traps and use it in a comparison.

For example:

if (HT_TrapReplacement == FoodMead)          ; This is food, fool!   elseIf (HT_TrapReplacement == TrapItemTypeIron)   ; Whatever the ObjectID name might be..          damage = (15 + worldlevel * 3)          ; This is a trap! Success!endif
User avatar
Siobhan Thompson
 
Posts: 3443
Joined: Sun Nov 12, 2006 10:40 am

Post » Sun Jun 24, 2012 9:17 am

That's a console command. I don't think Papyrus is aware of the string EditorID's at all. So you'd have to use a property anyway.


Another function you can use, is GetFormID().
This will give you the FormID as an integer, that would make it easy to compare.

Using this is normally a bad thing. In the last game formID's were known to change when new DLC's were released. (that's what the whole patch 1.4 breaking your mod thing is about in my sig.)
All these ID's are from your own esp by the look of it, so at least in this case you'd have control of when the ID's could change.

So you could just write some variable declarations like...
int HT_ItemWhatever01 = 0x00001001int HT_ItemWhatever02 = 0x00001007int HT_ItemWhatever03 = 0x000010a4

It's not that simple though, as these formID's highest byte will vary according to load order. So you'd have to discover your own mods load order first.
I posted some bitwise operators in this forum a while back that would help if you want to go down this path.
User avatar
Killah Bee
 
Posts: 3484
Joined: Sat Oct 06, 2007 12:23 pm

Post » Sun Jun 24, 2012 3:49 am

Firstly: Instead of using a series of if statement you should use a while loop in your original script to step through the array and compare the elemnts to your variable. Saves you all the writting in the script.

Secondly: If you have to attach that script to numerous actors you should look the forums for the magic effect and quest alias approaches and consider using that. If you have to attach the script to other objects the questalias approach might work aswell (As far as I understood it should work on any item type that can be passed to the quest as an alias) or you simply put your items into a FormList, pass that to the script as the only property and step through that FormList for comparison. This way you only have to add all the items once.
User avatar
Jesus Duran
 
Posts: 3444
Joined: Wed Aug 15, 2007 12:16 am

Post » Sat Jun 23, 2012 11:45 pm

^^ The formlist idea is a much better idea :)
User avatar
Isabella X
 
Posts: 3373
Joined: Sat Dec 02, 2006 3:44 am

Post » Sun Jun 24, 2012 4:02 am

You can do that in the console because the console is a totally different thing.

HT_TrapReplacement is like a box. The box has a name, shape, material type, content, etc etc. If you say "is the box metal?" you could mean "is the box named metal", "is the box made of metal?", "is there metal in the box?". The box might also have a lock on it and this lock perhaps has a name and material and type too.

All this stuff isn't something you should be annoyed at Bethesda for, this is just general programming stuff.
User avatar
Marie
 
Posts: 3405
Joined: Thu Jun 29, 2006 12:05 am

Post » Sun Jun 24, 2012 2:24 pm

The wiki says:

; Place a horker at player. Use 0x.ObjectReference Horker = Game.GetPlayer().PlaceAtMe(Game.GetForm(0x00023ab1))

I want to use "Game.GetForm(0x00023ab1)" to compare with my MiscObject property. I don't necessary want to use it exactly like that, but in a similar way. -So that I can type in manually which FormID or ObjectID or whatever it's called to compare with "MiscObject Property HT_TrapReplacement Auto"

For example:

if (HT_TrapReplacement == Game.GetForm(0x00023ab1))   ; This is a Horker..endif

Or as tunaisafish mentioned:

int HT_ItemWhatever01 = 0x00023ab1if (HT_TrapReplacement == HT_ItemWhatever01)	; I am guessing that a MiscObject can't be compared with an integer, though..   ; This is still a Horker..endif


Firstly: Instead of using a series of if statement you should use a while loop in your original script to step through the array and compare the elemnts to your variable. Saves you all the writting in the script.

How can I use a loop when the actions I use are different for each comparison?

Secondly: If you have to attach that script to numerous actors you should look the forums for the magic effect and quest alias approaches and consider using that. If you have to attach the script to other objects the questalias approach might work aswell (As far as I understood it should work on any item type that can be passed to the quest as an alias) or you simply put your items into a FormList, pass that to the script as the only property and step through that FormList for comparison. This way you only have to add all the items once.

FormList sounds interesting, sadly I don't know anything about those things. Could you please explain how they work?

EDIT: I have started by creating a new FormList called "HT_ListTrapReplacement" how can I compare my "HT_TrapReplacement" property with whatever is in my FormList?
I'm thinking something along the lines of:

if (HT_TrapReplacement == Game.GetFormListInfo(HT_ListTrapReplacement[0]))   ; Yes, I just made this up - I don't have a clue..   elseif (HT_TrapReplacement == Game.GetFormListInfo(HT_ListTrapReplacement[1]))   elseif (HT_TrapReplacement == Game.GetFormListInfo(HT_ListTrapReplacement[2]))   ; etc..endif

EDIT #2: After reading a bit on the wiki it seems that I can check if my item is in the FormList or not. But I want to check which number in the list the item is. -In order to do the correct actions for that item.
User avatar
Saul C
 
Posts: 3405
Joined: Wed Oct 17, 2007 12:41 pm

Post » Sun Jun 24, 2012 10:43 am

How can I use a loop when the actions I use are different for each comparison?

Ah sorry I didn't see that. If you put the items in the correct order into the array or FormList you could base the calculation on the Index variable.

FormList sounds interesting, sadly I don't know anything about those things. Could you please explain how they work?

A FormList simply is a List that can contain any Form (Everything you can create in the CK is a Form) simple as that.

To create a FormList is fairly simple. In the CK's Object Window navigate to "Miscellaneous->FormList", in the righthand list right-click and select "new". Enter an EditorID for your new FormList. Add new Items to the List by draging them out of the Object Window into the FormList Window.

To access the FormList in a script simply add a FormList property and attach your FormList to it. To acces elements you use the http://www.creationkit.com/GetAt_-_FormList function on the property. Note though that GetAt() returns a Form type object. So in order to access higher level functions or want to compare it you need to do a cast accordingly (example: if the list contains actors and you need to access actor-specific function you first need to cast the returned object into an actor).
User avatar
James Baldwin
 
Posts: 3366
Joined: Tue Jun 05, 2007 11:11 am

Post » Sun Jun 24, 2012 11:50 am

EDIT:
I did this to my script:

Function ResolveLeveledDamage()   int worldlevel = CalculateEncounterLevel(0)   int damage = 0   int listindex = GetFormIndex(HT_ListTrapCheck, HT_TrapReplacement)   if (listindex == 0)	  damage = (15 + worldlevel * 3)	  ;Iron Trap   elseIf (listindex == 1)	  damage = (20 + worldlevel * 4)	  ;Steel Trap   elseIf (listindex == 2)	  damage = (25 + worldlevel * 4)	  ;Dwarf Trap   elseIf (listindex == 3)	  damage = (30 + worldlevel * 4)	  ;Orc Trap   elseIf (listindex == 4)	  damage = (35 + worldlevel * 5)	  ;Ebony Trapendif   hitBase.damage = damageEndFunctionint Function GetFormIndex(FormList List, Form Member) global     ; Why isn't this function already in the game?{Gets the index of Member in List. Returns -1 if not found}		; What will happen to my script if this function returns -1?   if (!List.HasForm(Member))	  Return -1   endif   int Index = 0   While (List.GetAt(Index) != Member)	  Index += 1   EndWhile   Return IndexEndFunction

Will this work as I intend?
User avatar
Klaire
 
Posts: 3405
Joined: Wed Sep 27, 2006 7:56 am

Post » Sun Jun 24, 2012 3:23 am

Well the FormList is what you could call an "ordered List". This means the order in which items are put into the list is stored thus each item in the list has an "index" identifying it's position in the list. The function you've quoted returns that index if the object you pass to the function is in that list at all.

What the function does is: It first uses the HasForm() function to see if the object is contained in the list. If this is the case the loop then runs through the list item by item compares it to the target object until the target object is found. The index variable then is exactly the indexnumber of the targetobject in the list.

This is not quite what you need. Since you will fill the list manually you'll already know the index of each item. So in youre script to compare the HT_TrapReplacement to a particular item in the list you use the GetAt() function and that item's index (position) in the list to get that item from the list. It basically works like an array you simply replace the "[]" function with "GetAt()".
User avatar
Ash
 
Posts: 3392
Joined: Tue Jun 13, 2006 8:59 am

Post » Sun Jun 24, 2012 7:18 am

Oh, I see.

Which way is more effective?
Calling a GetAt() function for each comparison or use the loop in "GetFormIndex" once, assign it to an integer and compare that integer to a number? -Like I did in my last post (edited.)

EDIT: I'm planning on adding a few more comparisons in the future. This is why I'm re-working the old comparison system I had, which was very cumbersome. I am guessing that more comparisons and more function calls = less optimized code.
User avatar
keri seymour
 
Posts: 3361
Joined: Thu Oct 19, 2006 4:09 am

Post » Sun Jun 24, 2012 1:03 pm

Hmm. I don't know really. GetFormIndex steps through the list. SInce it would be logical to implement the GetAt() function similar to array element access it is definetly faster to use GetAt() if it is implemented with direct element access.
User avatar
adam holden
 
Posts: 3339
Joined: Tue Jun 19, 2007 9:34 pm

Post » Sun Jun 24, 2012 10:44 am

I'm gonna go with GetFormIndex for now.
Thanks a lot for your help. =)
User avatar
Sheila Esmailka
 
Posts: 3404
Joined: Wed Aug 22, 2007 2:31 am

Post » Sun Jun 24, 2012 7:23 am

Oh I get you now :) In programming you can only compare things that are similar (same type). This makes sense, for instance you couldn't in real life compare a door to a thought or a bottle to a noise. When a variable has text in programming speak we say that the type of the variable is a string. In theory this would work:
 if ((object.gettype() as String) == "type") do something endif 
Sadly this probably wont work very often in Papyrus... Papyrus is very strict about types and there's no auto-conversion between types. A language like PHP is incredibly loose and flexible with types and a language like C is even stricter than Papyrus. "0x000F37A" is a String which can only be compared to another String (or an object which can be converted to a string). One way that Papyrus is a little bit clever is that it knows "1" is an Int, "abc" is a String and "1.0" is a Float.
Just to clarify this a bit - there is no "GetType" function in Papyrus, and Papyrus does auto-cast to ancestor types when appropriate so it's perfectly fine to compare a MiscObject to a Form and expect the result to be true.

Also, scripts should never ever deal with formIDs unless you're printing them to the screen for debugging purposes. Ideally, all scripts should be completely ignorant of the content of all data files, and use properties as interfaces through which they can interact with data files. The only exception to this, which isn't really a proper exception, is using editorIDs for property names to allow the Creation Kit to auto-fill properties.

Cipscis
User avatar
Adam Kriner
 
Posts: 3448
Joined: Mon Aug 06, 2007 2:30 am

Post » Sun Jun 24, 2012 1:41 pm

Also, scripts should never ever deal with formIDs unless you're printing them to the screen for debugging purposes. Ideally, all scripts should be completely ignorant of the content of all data files, and use properties as interfaces through which they can interact with data files. The only exception to this, which isn't really a proper exception, is using editorIDs for property names to allow the Creation Kit to auto-fill properties.

lol, I knew that suggestion would make you cringe when I was writing it. I was glad when Jason P suggested going with FormLists as I agree it's one to avoid if at all possible.
User avatar
Franko AlVarado
 
Posts: 3473
Joined: Sun Nov 18, 2007 7:49 pm

Post » Sun Jun 24, 2012 3:05 pm

Just to clarify this a bit - there is no "GetType" function in Papyrus, and Papyrus does auto-cast to ancestor types when appropriate so it's perfectly fine to compare a MiscObject to a Form and expect the result to be true.

Also, scripts should never ever deal with formIDs unless you're printing them to the screen for debugging purposes. Ideally, all scripts should be completely ignorant of the content of all data files, and use properties as interfaces through which they can interact with data files. The only exception to this, which isn't really a proper exception, is using editorIDs for property names to allow the Creation Kit to auto-fill properties.

Cipscis
Yes yes I know Cipscis >_< I was writing quasi-code, perhaps I should have made that clearer. You can't compare an object to a literal though can you?
User avatar
joeK
 
Posts: 3370
Joined: Tue Jul 10, 2007 10:22 am

Post » Sun Jun 24, 2012 2:12 pm

Yes yes I know Cipscis >_< I was writing quasi-code, perhaps I should have made that clearer. You can't compare an object to a literal though can you?
Yeah, I noticed that but there really is no way to get any of an object's types as a string. The closest thing you can do is attempt to cast it to a particular type and check if the result is not None.

You can compare an object to a literal if the literal is http://www.creationkit.com/Literals_Reference#None_Literal, but that's it.

Cipscis
User avatar
Chelsea Head
 
Posts: 3433
Joined: Thu Mar 08, 2007 6:38 am


Return to V - Skyrim