Jump to content

Item baseID problem


ppl47

Recommended Posts

I see...!

 

The only way I can see to use EditorID strings is by hardcoding the conversion by pre-creating a table EditorIDstring<> FormID (like a stringmap array with entries like "let myArray["MS31BlackWaterBlade01] := MS31BlackWaterBlade01 ). With it you could get the FormID of the item placed in the chest, convert it to the correspondent EditorID, rebuild the EditorID string and convert it back to a FormID to be used in AddItem.

 

Another way (without using EditorID strings) would be a table PlayerLevel <> FormID (like an array or map with entries created by MyArray[1] = MS31BlackWaterBlade01 . . . MyArray[14] = MS31BlackWaterBlade10 . . . etc...

 

A third way would be using leveled items. I am not familiar with them, but maybe there is a way to (after removing the placed item) AddItem a leveled item which the engine would dynamically adjust to the playet level. Not sure if this would work, thou.

Link to comment
Share on other sites

I built two scripts like this:

The fisrt one is attached to a custom chest, which i placed in arcane univeristy lobby:

scn aaFnMagicChest
ref chest
ref iter
ref baseRef
string_var name
begin OnActivate
if IsActionRef player == 1
Activate
let chest := GetSelf
foreach iter <- chest
let name := iter.GetName
if eval( name == "BlackWater Blade")
Call aaFnMagicChestBlackWaterBlade chest iter
endif
if eval( name == "Blade of Woe")
Call aaFnMagicChestBladeOfWoe chest iter
endif
; etc.....
loop
endif
end

Then i defined, for each leveled item( till now I built 2 of them...there are over 20 in the game!), a function which takes care of analysing the item( get the ID, Name,ecc... ) remove it if low level and substitue it with a better version according to the player level, like this:


scn aaFnMagicChestBlackWaterBlade
ref objectRef
ref chest
ref itemRef
string_var id
short itemLevel
short playerLevel
begin Function {chest, itemRef}
let objectRef := itemRef.GetBaseObject
let id := GetEditorID objectRef
let itemLevel := 99
if eval( id == "0000C201")
let itemLevel := 4
elseif eval( id == "0006B697")
let itemLevel := 9
elseif eval( id == "0006B698")
let itemLevel := 14
elseif eval( id == "0006B699")
let itemLevel :=19
elseif eval( id == "0006B69A")
let itemLevel :=24
elseif eval( id == "0006B69B")
let itemLevel := 99
endif
let playerLevel := player.GetLevel
if playerLevel>itemLevel
itemRef.RemoveMeIR
if playerLevel <10
chest.AddItem 0006B697 1
elseif playerLevel <15
chest.AddItem 0006B698 1
elseif playerLevel <20
chest.AddItem 0006B699 1
elseif playerLevel <25
chest.AddItem 0006B69A 1
elseif playerLevel >=25
chest.AddItem 0006B69B 1
endif
endif
End

The previuos code works, but I'm looking for a more "automatic" way to tell the level of the weapon, and build its IDeditor code without using so many if statements

Edited by ppl47
Link to comment
Share on other sites

Maybe something with a leveled list would be handy. There exists already the Auto Update Leveled Items and Spells mod that might have something in it that you could use as a reference. I have no idea how it works, but it seems to update leveled items.

 

If you do not mind typing the items to a list yourself, you could try something like this to update an item:

scriptname ItemUpdateTest

short PlayerLevel
ref BaseObject
ref NewObject
array_var Items
array_var Iter

begin _Function { BaseObject }

    let PlayerLevel := PlayerRef.GetLevel
    let NewObject := BaseObject

    ; the idea is to make an array of
    ; arr = [ [0,ItemEditorIDLevel0], [10,ItemEditorIDLevel10], ...]

    let Items := ar_Construct "Array"
    ar_Append Items ( ar_List 0, ItemEditorIDLevel0 )
    ar_Append Items ( ar_List 10, ItemEditorIDLevel10 )
    ar_Append Items ( ar_List 30, ItemEditorIDLevel30 )

    foreach Iter <- Items
        if eval ( Iter["value"][0] < PlayerLevel )  ; assuming it goes 0 -> 1 -> 2 -> ...
            let NewObject := Iter["value"][1]
        endif
    loop

    if eval ( BaseObject != NewObject )
        RemoveItem BaseObject 1
        AddItem NewObject 1
    endif

    ; assuming the contained arrays are also deleted, then this might work,
    ; but you could probably store the arrays somewhere else... or not?
    let Items := ar_Null

end

I have not tested that! It is just an idea. And with arrays, one needs to be somewhat more careful than usual (moreso with string_vars). But also, if you hardcode the item levels, and another mod adjusts the leveled item levels, then your hardcoded system will work according to the original arrangement. For example a mod that removes all level scaling (if there is any) would be negated by your mod swapping the item. Or not. Or a nerfing mod would be useless if a chest gives the best one possible always, regardless of what the levels input in the leveled list are. :huh:

 

Also, you can use the editor ID in the script editor of the CS(E). For example an imaginary item UberSwordObject01 with a form ID of 000012D3 could be referenced either with the editor ID

PlayerRef.AddItem UberSwordObject01 1

or with the form ID

PlayerRef.AddItem 000012D3 1

although the editor ID is the more readable one, and in case your form has an ID of 010012D3 originally and you add a new master to it (making the index of the mod where the sword comes from 02), then the script would need to be adjusted to say 020012D3 when compiling the script or else the object referenced would be something in the added master file.

 

If there is anything odd in my post, feel free to point it out, I am writing it with very limited time to spend. :sweat:

Link to comment
Share on other sites

I followed you suggestion about leveled list and they seems like the object i need. Now I encountered a new problem: i need to get the index or level of an entry of the leveled list through its base object ID, but I cant find the proper function
The code is something like this

scn aaFnMagicChestNorthwind
ref chest
ref itemRefOld
ref itemRefNew
ref baseItemOld
string_var itemIdOld
ref leveledListRef
short indexOld
short itemLevelOld
short itemLevelNew
short nItems
short i
begin Function {itemRefOld, leveledListRef} ; itemRefOld is a reference from an item in a container, leveledListRef ( MQ09AkaviriFrostSword for example)
let nItems := GetNumLevItems leveledListRef <---- works
let baseItemOld := itemRefOld.GetBaseObject <--- reference to base object of my item
let indexOld := GetLevItemIndexbyForm leveledListRef baseItemOld <------ doenst work!
let itemLevelOld := GetNthLevItemLevel indexOld leveledListRef
Print "nItems= " +$nItems+" , indexOld= " +$indexOld+" , itemLevelOld = " +$itemLevelOld

end

 

 

Any idea?

Link to comment
Share on other sites

I was able to solve the problem regarding the indentification of my item inside a leveld list. Now I got a new problem making an array work as I expect it to.
The codes are the following:

The first script runs at the start of the game and deal with creating a database of the leveled list i'm intereset in , inspired by the mod you have linked

scn aaMagicChestDB
array_var itemDB
Begin MenuMode 1044
if GetGameRestarted
let itemDB := ar_Construct Array
ar_append itemDB MQ09AkaviriFrostSword ;Northwind
; .....
Message "database loaded"
endif
End


The second script is attached to the chest and triggers a Function each time it finds that the item stored belong to a leveled list. This function take care of : check if the item belongs to the list, substitue it with a better version if the level of the player is high enough. But this code doesnt work ( look below)

scn aaFnMagicChest
ref chest
ref iterChest
array_var iterDB
array_var itemDB
ref baseRef
string_var name
ref leveledList
begin OnActivate
if IsActionRef player == 1
Activate
let chest := GetSelf
let itemDB := ar_Construct array
let itemDB := aaMagicChestDBQuest.itemDB
foreach iterChest <- chest
foreach iterDB <- itemDB <-------- I get an error in the debug console
let leveledList := iterDB["value"]
Call aaFnMagicChestSwap chest iter leveledList
loop
loop
endif
end

Any idea what is causing this error in the loop?
Link to comment
Share on other sites

What is the error message?

 

Are you sure the array was created? (did the message "database loaded" show?)

 

A couple of comments (not related to the error):

(1) If the array contents are always the same, you only need to load the array once. Once created, it is saved in the savegame. So, instead of " if GetGameRestarted" you could use a doonce switch (I usually use the very array as the switch with something like "if itemDB == 0 ")

 

(2) you don't need to initialize ItemDB ("let itemDB := ar_Construct array") as you are assigning the variable to a different array in the next line.

 

(3) You do not need the ItemDB var in the second script. You may refer directly to the quest array as in "foreach iterDB <- aaMagicChestDBQuest.itemDB" (but this is a matter of personal preference)

 

Link to comment
Share on other sites

  • Recently Browsing   0 members

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