Jump to content
⚠ Known Issue: Media on User Profiles ×

Eillis

Members
  • Posts

    14
  • Joined

  • Last visited

Everything posted by Eillis

  1. There's nothing to be sorry about. We're all here to share knowledge. A lot of this stuff is very confusing. Setting unplayable will work in case of armor/clothing. Other item types don't have this option. So this leaves the problem for non-armor/clothing quest items of NPC.
  2. @GamerRick Just hiding quest items on player is not enough in my case. I'd gladly go with leaving quest and unplayable items where they are, and in fact, that is what I'm trying to do. It's just not that simple. NPC will transfer his/her quest items to player. That requires workarounds. @RomaR Forgot to mention it earlier, but GetItems does in fact return object IDs. I recently tested it to be 100% sure.
  3. @RomanR Thanks for the info about magical items. I'll probably be doing more tests with scripted item and enchantment blocks to get a better understanding of any potential issues, but I'll be sure to keep your findings in mind. If that's just the way it is, I won't be too worried if I end up with similar results to yours. @GamerRick Does this flag actually affect how RemoveAllItems work? Or it's just visibility? Also, what is MS05?
  4. Yes. It's just as RomanR says. GetEquippedItems returns object IDs. Removing items during iteration is also fine, since I am iterating backwards. Could you elaborate about the problems you mentioned? It is actually quite important for me to get all items transferred without skipping frames, if possible. I'd be very interested to know any possible risks and consequences of doing it all in one frame. I did some testing with RemoveAllItems transfer. Here are my findings: - unplayable items are never transferred, - quest items are not transferred from player. They are transferred from other containers though. As we expected, NPC quest items get transferred from NPC to the player but they won't be transferred back. I haven't tested scripted item blocks extensively. The small tests I did on OnAdd, OnDrop, OnEquip, OnUnequip blocks behavior seemed weird. OnUnequip block was called very often. Other blocks rarely or not at all. Although, it seems that block calling behavior was not much different when I tried to use RemoveAllItems and RemoveMeIR. Both of them seemed weird. Perhaps the real issue here is that I am doing all the unequipping and transfer at once. Anyway, I can't say anything for certain here, as I didn't focus on it yet. Speaking of RemoveMeIR, I tried using it instead of RemoveAllItems but it was causing bugs. Very often, RemoveMeIR was duplicating stackable items. (It's an issue I saw mentioned in other forum threads too.) At other times, some items were skipped and not transferred at all. Going back to RemoveAllItems, it seems quite reliable as far as item transfer goes - no duplication or other such bugs. There are the specific quirks that I mentioned, which can possibly be worked around or taken advantage of. I try to manipulate "playable" and "quest item" flags to control which items to transfer and which not. (Of course, after the transfer I restore flags to their original state.) If item is an armor or clothing, transfer can be prevented by setting the unplayable flag. If item is on player, transfer can be prevented by setting the quest item flag. If neither of these two cases, transfer can't be prevented. Best I can do is let the transfer happen and just avoid NPC quest items getting stuck on player - I temporarily deactivate their quest item flag. Summing all that up, I am only left with a problem that NPC's quest items will temporarily be moved to the player. Well, that and the chaotic behavior of scripted item blocks. (But I might still get to look more into it.) Extra note: I looked up script of CM Partners. It uses plain RemoveAllItems, like it's no big deal. They only do it between NPC and a container though. As I mentioned, I constantly get issues (item duplication, skipping some items) when trying to move items with RemoveMeIR. Has anyone been able to use this function to transfer items reliably, with no bugs? Maybe there's something I'm missing... I tried using "foreach itemRef <- container" and "GetInvRefsForItem". Both caused the same issues. If anyone needs it, here are the two functions that I wrote for transferring items. scn ECTTransferItemsAllFunction ref transferFrom ref transferTo array_var restoreQuestItems array_var restoreUnplayableItems array_var arrayRow ref itemTypeRef Begin Function{transferFrom, transferTo} Let restoreQuestItems := Ar_Construct Array Let restoreUnplayableItems := Ar_Construct Array foreach arrayRow <- transferFrom.GetItems Let itemTypeRef := arrayRow["value"] if IsPlayable2 itemTypeRef == 0 ; Set item as playable to allow transfer. SetIsPlayable 1 itemTypeRef Ar_Append restoreUnplayableItems itemTypeRef endif if (IsQuestItem itemTypeRef == 1) && (transferFrom.GetIsReference Player == 1) ; Set player quest item as non-quest to allow transfer. SetQuestItem 0 itemTypeRef Ar_Append restoreQuestItems itemTypeRef endif loop transferFrom.RemoveAllItems transferTo 0 ; Restore quest item states. foreach arrayRow <- restoreQuestItems Let itemTypeRef := arrayRow["value"] SetQuestItem 1 itemTypeRef loop ; Restore unplayable states. foreach arrayRow <- restoreUnplayableItems Let itemTypeRef := arrayRow["value"] SetIsPlayable 0 itemTypeRef loop End scn ECTTransferItemsSkipSpecialFunction ref transferFrom ref transferTo short skipScriptedItems array_var inOutTransferredQuestItems array_var restoreQuestItems array_var restoreNonQuestItems array_var restorePlayableItems short isSpecialItem short isTransferrableItem array_var arrayRow ref itemTypeRef ; inOutTransferredQuestItems - as input: should contain list of quest items which should be allowed to transfer. (Most likely: quest items transferred to player earlier.) ; inOutTransferredQuestItems - as output: contains list of quest items, whichs transfer was not prevented. ; In practice, just provide a single, shared array here when transferring items back and forth between two containers. Begin Function{transferFrom, transferTo, skipScriptedItems, inOutTransferredQuestItems} Let restoreQuestItems := Ar_Copy inOutTransferredQuestItems Let restoreNonQuestItems := Ar_Construct Array Let restorePlayableItems := Ar_Construct Array Ar_Erase inOutTransferredQuestItems ; Remove state of quest items returned from player to allow their transfer. if (transferFrom.GetIsReference Player == 1) foreach arrayRow <- restoreQuestItems Let itemTypeRef := arrayRow["value"] SetQuestItem 0 itemTypeRef loop endif ; Identify special items and attempt to prevent their transfer. foreach arrayRow <- transferFrom.GetItems Let itemTypeRef := arrayRow["value"] set isSpecialItem to ((IsPlayable2 itemTypeRef == 0) || (IsQuestItem itemTypeRef == 1) || (HasName itemTypeRef == 0) || ((skipScriptedItems == 1) && (IsScripted itemTypeRef == 1))) set isTransferrableItem to ((IsPlayable2 itemTypeRef == 1) && ((IsQuestItem itemTypeRef == 0) || (transferFrom.GetIsReference Player == 0))) if (isSpecialItem == 1) && (isTransferrableItem == 1) if ((GetObjectType itemTypeRef == 20) || (GetObjectType itemTypeRef == 22)) ; Set armor/clothing item as unplayable to prevent transfer. SetIsPlayable 0 itemTypeRef Ar_Append restorePlayableItems itemTypeRef elseif (transferFrom.GetIsReference Player == 1) ; Set player non-quest item as quest item to prevent transfer. SetQuestItem 1 itemTypeRef Ar_Append restoreNonQuestItems itemTypeRef elseif (IsQuestItem itemTypeRef == 1) ; There is no way to prevent transfer. Store item type in output. if eval (Ar_Size inOutTransferredQuestItems) >= 0 Ar_Append inOutTransferredQuestItems itemTypeRef PrintToConsole "ECT: Unable to prevent transfer of quest item: [%n]: %n => %n" itemTypeRef transferFrom transferTo else PrintToConsole "ECT: Warning! Unreported transferred quest item: [%n]: %n => %n" itemTypeRef transferFrom transferTo endif else PrintToConsole "ECT: Transferred special item: [%n]: %n => %n" itemTypeRef transferFrom transferTo endif endif loop ; Transfer items. transferFrom.RemoveAllItems transferTo 0 ; Restore quest items state. foreach arrayRow <- restoreQuestItems Let itemTypeRef := arrayRow["value"] SetQuestItem 1 itemTypeRef loop ; Restore non-quest items state. foreach arrayRow <- restoreNonQuestItems Let itemTypeRef := arrayRow["value"] SetQuestItem 0 itemTypeRef loop ; Restore playable items state. foreach arrayRow <- restorePlayableItems Let itemTypeRef := arrayRow["value"] SetIsPlayable 1 itemTypeRef loop End
  5. As I understand: - AddItem creates new items. - RemoveMe and RemoveAllItems transfer the existing items (when providing a target container). That means that OnAdd block behavior is very counter-intuitive in this case. RemoveMe and RemoveAllItems do pretty much the same thing, except one of them will call the block and the other won't. Are you certain that this is how it works though? Wiki states that "quest items are not removed when this function is called on the player". So they are in fact removed? Or is OnAdd called despite them not being removed? As I mentioned, my code works fine so far. I have no issue with it. I am only asking about any general pitfalls and gotcha's of transferring items - potential problems that you wouldn't notice at first. Maybe I'm more worried than it's worth, but I just felt that it may be risky to move quest and scripted items indiscriminately. I mean to say that I'd rather focus on general tips and advice rather than specifically on my code. Having said that, of course I don't mind sharing my code, so here it is. I am sending all player items to a container, then transferring all NPC items to player. Next, I open a menu. After closing the menu, all items are returned to their owners. So, in other words, I want player to hold NPC's items while the menu is active. Begin GameMode if phase == 0 ; Unequip all player items. Let playerEquipment := Player.GetEquippedItems Let i := ((Ar_Size playerEquipment) - 1) while i >= 0 Let tempRef := playerEquipment[i] if tempRef != 0 if IsQuestItem tempRef == 0 Player.UnequipItemSilent tempRef 0 else Ar_Erase playerEquipment i endif endif set i to (i - 1) loop ; Unequip all companion items. Let companionEquipment := companion.GetEquippedItems Let i := ((Ar_Size companionEquipment) - 1) while i >= 0 Let tempRef := companionEquipment[i] if tempRef != 0 if IsQuestItem tempRef == 0 companion.UnequipItemSilent tempRef 0 else Ar_Erase companionEquipment i endif endif set i to (i - 1) loop ; Transfer items. Player.RemoveAllItems ECTCompanionTransferContainer 0 companion.RemoveAllItems Player 0 set phase to 1 endif ; ----------------- ; Phase 1 is in the menus. ; Switches to phase 2 when finished. ; ----------------- if phase == 2 ; Transfer items back. Player.RemoveAllItems companion 0 ECTCompanionTransferContainer.RemoveAllItems Player 0 ; Re-equip player items. Let i := ((Ar_Size playerEquipment) - 1) while i >= 0 Let tempRef := playerEquipment[i] if tempRef != 0 Player.EquipItemSilent tempRef 0 endif set i to (i - 1) loop ; Re-equip companion items. Let i := ((Ar_Size companionEquipment) - 1) while i >= 0 Let tempRef := companionEquipment[i] if tempRef != 0 companion.EquipItemSilent tempRef 0 endif set i to (i - 1) loop set phase to -1 endif End
  6. I do actually iterate to unequip all items from both player and the NPC before I call RemoveAllItems. I'm guessing that this should safeguard me from the enchantment problem. Also, I understand that the enchantment bug does not occur since OBSE 21. (?) I also thought that using quest item flag is an intuitive way to say "don't touch me". I'm guessing many mods would use that. I do wonder about "Quest items are not removed when this function is called on the player". It sounds like quest items will get removed from the NPC, given to player and then they won't be transferred back. I'll have to test this later. I did try to use all those Remove functions in all combinations but I couldn't get them to work. Maybe there was something I missed though... To clarify, I am running all my code from Activator. Maybe that is what's complicating things.
  7. I am trying to temporarily exchange all items of Player and any NPC (including, or rather: especially companions). Soon after, I perform the exchange again to give all the items back to the original owner. I tried a few ways to do this, but so far only RemoveAllItems worked for me. (Of course, I had to make use of a persistent container to perform the exchange.) I tried using manual iteration in different ways but nothing worked for me. (Possibly, I was doing something wrong.) Anyway, it all looks good so far, but I am wondering about quest items or scripted items from various mods. The wiki page mentions some issues with quest items. Actually, I don't care about quest items much. I totally wouldn't mind leaving them where they are. Is there a chance that there could be bugs or stability issues caused by using RemoveAllItems (for transfer) on player or NPCs?
  8. I eventually figured out how to work with scripting. I wanted to use Activators as "objects" to contain some data and perform operations on it. To be exact, I wanted my Activators to control assigned NPCs in accordance with how they are configured. As I mentioned, from references we can only read local variables but cannot modify them. This prevented me from parametrizing my Activators in other scripts. I solved this by moving Activators' "parameters" or, so to say "public variables" into quest script arrays. Each Activator has it's own index, which is used to read "public data" assigned to it. Since that data is inside a single quest script (a static singleton), I can read and modify it from anywhere, without needing to access it from a reference. So this is probably the same thing that QQuix did. Just wanted to share my final solution in case someone else has these problems.
  9. I figured out a better way to do what I wanted. Basically I was trying to use one activator as data-holding "object" and use the other as a "function" to make operations on that data. I recently learned that you can make actual functions in script. That makes my use case much easier. Still, thank you for your help guys!
  10. I keep getting more confused and disappointed with the scripting language. It appears that you simply cannot access a local variable from a reference. (I tried moving those activators to player with MoveTo. That didn't help either.) EDIT: GetVariable and GetRefVariable seem to allow me to retrieve data from a reference. This code works perfectly: set refVariable to temp.GetRefVariable "horseController" Now I am still missing an ability to set local variables through references.
  11. I know you can directly access variables of quest and persistent object scripts but only if you specify their exact name (editor ID). You can't seem to be able to do that if you're calling from a reference though. Or do you mean to say that it's actually possible? Arrays could do as a workaround I guess... It's an interesting approach. The "OOP object" would only need to hold it's own index. Then you could access it's "data" from global arrays. I will keep it in mind, in case I can't figure it out the way I want. Thanks! Actually, I noticed a strange behavior in TES4CS Extended script editor. This just adds up to my confusion... (Check attached image.)
  12. Oh. So persistent activators need to be in the same cell as player as well? This would mean that I need to move them to player constantly, right? (Assuming that player can use the spell at any time.) To clarify, I only need the OnActivate call. I don't need to run other sections. Actually, the code worked as expected when I used Player as the activating user, instead of the other Activator. It worked, even though the used Activator was not in player's cell. Anyway, I just tried with moving all these activators towards the player and that didn't help. I think you slightly misunderstood what I'm trying to do. Now I notice, that the topic title is misleading. Sorry. I have spell X and activators A and B. Inside spell X I want to activate A, while passing B as it's activating object. I am not trying to activate one activator inside another. Only one of the activators is activated. The other does nothing, excepting being passed over by reference. TL; DR is that I can't use GetSelf. The code is inside a spell. I included complete code in my first post. By the way, I tried passing the activator from reference variable. That made no difference.
  13. From what I tried to figure it, it seems to modifying local variables of other scripts is not possible. (?) I'd appreciate it, if somene could confirm this for me. I also wonder about the reasons for this. Is TES scripting engine this dreadful? Externally modifying variables of other objects' scripts would be a powerful tool. Is that not something that OBSE could overcome? I have a second question I want to ask. In my mod I am using persistent activators to hold variables and do some logic on them. (In a sense, I'm trying to use them like simple objects of object-oriented programming.) I know that I can modify local variables of a persistent activator by calling it's editor ID, like: set SomePersistentID.localVar to 0 But it surprises me that I can't do the same thing by calling that same persistent object from a reference: ref someRef ... set someRef to SomePersistentID ... set someRef.localVar to 0 (Being able to use references like this would allow me a more elegant handling of persistent activators that I'm using.) Is that really the case? Am I missing something here?
  14. I have a hard time getting an Activator passed as user activating another Activator. This page suggests that it should be possible: https://cs.elderscrolls.com/index.php?title=Activator Here is a line that I'm trying to use. ECTCompanionNonCombatOrderExecution.Activate ECTCompanionController01 1 - It is being called from ScriptEffectStart block of a self-cast spell. - I am 100% sure that both ECTCompanionNonCombatOrderExecution and ECTCompanionController01 are persistent references. - ECTCompanionController01 in it's OnActivate does nothing else, other than printing a debug console message. - The code line works if I replace ECTCompanionController01 with Player. Is there something I'm missing/misunderstanding about Activators? Here is the complete code that I'm trying to use: scn ECTCompanionCombatOrderMenu01Script ref companionController Begin ScriptEffectStart ;// Works - OnActivate is executed. ECTCompanionNonCombatOrderExecution.Activate Player, 1 ;// Doesnt work - nothing happens. ; set companionController to ECTCompanionController01 ; ECTCompanionNonCombatOrderExecution.Activate companionController, 1 End
×
×
  • Create New...