CrEaToXx Posted April 27, 2017 Share Posted April 27, 2017 I'm currently working on a plugin to make Skyrim a tad bit harder. Basically I'm trying to lower the items base damage/gold value, when looted. I'm using a perk entry point, so the script processes when activating the corpse. It works flawlessly, but unfortunately, all instances in the game of said weapon/armor will have its stats lowered. I understand this is because I'm calling on the base object. I also understand there's the usual way of dropping the item from inventory, calling the script, and then put the item back into the players inventory, which is inconvenient to say the least, as you'd figure something is going on with the inventory closing and then opening again. I came across the term "persistent", though I'm not fully aware of what it means, I understand that it happens once you force the item to a reference alias. So basically the questions are: 1. Can you force a weapon/armor to a reference alias?2. Will it then adequatly get its stats changed without affecting all instances, and without closing inventory process?3. If 1+2 == false, is there any other convenient method, or any sort of SKSE plugin that does the job? Link to comment Share on other sites More sharing options...
foamyesque Posted April 27, 2017 Share Posted April 27, 2017 In the general case, as far as I've ever been able to find, you cannot. Stuff in containers ceases to be object references, and as such cannot be added to quest aliases. SKSE's gold and damage changing functions are exclusive to the base forms and cannot be called on ObjectReferences. SKSE also provides the WornObject script object, which allows you to call certain functions on equipped armors, but those functions do not include altering gold values or damage (and in any case seem to be armour exclusive). As an alternate method, you could simply add hidden debuff perks to the player, on barter and on damage, which would achieve what I think you're aiming for with a lot less horsing around. You'd slow down player gold accumulation and, of course, change damage just like the difficulty settings do. Link to comment Share on other sites More sharing options...
CrEaToXx Posted April 27, 2017 Author Share Posted April 27, 2017 I guess I've found something working for my case. I didn't know you could drop and modifie items with menus still open... https://forums.nexusmods.com/index.php?/topic/2789614-creating-an-object-reference-for-an-item-in-a-container/ ...the moment my items leave inventory, they should be recognizable as ObjectReference, and thus capable of being modified to my likes. Link to comment Share on other sites More sharing options...
NagusQuark Posted April 27, 2017 Share Posted April 27, 2017 You can't change the value of an ObjectReference, only that of a base object. What's wrong with all instances changing at once anyway? Link to comment Share on other sites More sharing options...
CrEaToXx Posted April 27, 2017 Author Share Posted April 27, 2017 You can't change the value of an ObjectReference, only that of a base object. What's wrong with all instances changing at once anyway? I want to lower value/damage/armor rating of looted objects, not those you can craft yourself or buy with vendors. This should simulate weapon/armor degradation aka used weapons/armors, and thus making the game much harder. The initial perk entry script looked like this: Actor akTarget = akTargetRef as Actor If akTargetRef.HasKeyword(ActorTypeNPC) && akTarget.IsDead() If akTarget.GetItemCount(SITE_LootDummy) >= 1 ElseIf akTarget.GetItemCount(SITE_LootDummy) <= 0 Weapon akLeftWeapon = akTarget.GetEquippedWeapon(false) as Weapon Weapon akRightWeapon = akTarget.GetEquippedWeapon(true) as Weapon Armor akShield = akTarget.GetEquippedShield() as Armor Armor akHelmet = akTarget.GetWornForm(0x00000002) as Armor Armor akCuirass = akTarget.GetWornForm(0x00000004) as Armor Armor akGauntlets = akTarget.GetWornForm(0x00000008) as Armor Armor akBoots = akTarget.GetWornForm(0x00000080) as Armor If akLeftWeapon != none akLeftWeapon.SetBaseDamage(akLeftWeapon.GetBaseDamage() / 3) akLeftWeapon.SetGoldValue(akLeftWeapon.GetGoldValue() / 3) EndIf If akRightWeapon != none akRightWeapon.SetBaseDamage(akRightWeapon.GetBaseDamage() / 3 akRightWeapon.SetGoldValue(akLeftWeapon.GetGoldValue() / 3) EndIf If akShield != none akShield.SetArmorRating(akShield.GetArmorRating() / 3) akShield.SetGoldValue(akLeftWeapon.GetGoldValue() / 3) EndIf If akHelmet != none akHelmet.SetArmorRating(akHelmet.GetArmorRating() / 3) akHelmet.SetGoldValue(akLeftWeapon.GetGoldValue() / 3) EndIf If akCuirass != none akCuirass.SetArmorRating(akCuirass.GetArmorRating() / 3) akCuirass.SetGoldValue(akLeftWeapon.GetGoldValue() / 3) EndIf If akGauntlets != none akGauntlets.SetArmorRating(akGauntlets.GetArmorRating() / 3) akGauntlets.SetGoldValue(akLeftWeapon.GetGoldValue() / 3) EndIf If akBoots != none akBoots.SetArmorRating(akBoots.GetArmorRating() / 3) akBoots.SetGoldValue(akLeftWeapon.GetGoldValue() / 3) EndIf akTarget.AddItem(SITE_LootDummy) EndIf EndIf That's when I figured all instances of the item in the game world are affected. Now I came up with this(ignore all the various variables, it's just for testing), which doesn't compile: Actor akTarget = akTargetRef as Actor If akTargetRef.HasKeyword(ActorTypeNPC) && akTarget.IsDead() If akTarget.GetItemCount(SITE_LootDummy) >= 1 ElseIf akTarget.GetItemCount(SITE_LootDummy) <= 0 Weapon akLeftWeapon = akTarget.GetEquippedWeapon(false) as Weapon Weapon akRightWeapon = akTarget.GetEquippedWeapon(true) as Weapon Armor akShield = akTarget.GetEquippedShield() as Armor Armor akHelmet = akTarget.GetWornForm(0x00000002) as Armor Armor akCuirass = akTarget.GetWornForm(0x00000004) as Armor Armor akGauntlets = akTarget.GetWornForm(0x00000008) as Armor Armor akBoots = akTarget.GetWornForm(0x00000080) as Armor If akCuirass != none ObjectReference akCuirassRef = akTarget.DropObject(akCuirass) as ObjectReference Utility.WaitMenuMode(0.1) Weapon akCuirassRefWep = (akCuirassRef.GetBaseObject() as Form) as Weapon akCuirassRefWep.SetArmorRating(akCuirass.GetArmorRating() / 3) ;If akCuirassRef ;akCuirass.SetArmorRating(akCuirass.GetArmorRating() / 3) ;akCuirass.SetGoldValue(akCuirass.GetGoldValue() / 3) ;EndIf akTarget.AddItem(akCuirassRef) EndIf akTarget.AddItem(SITE_LootDummy) EndIf EndIf Either I'm now trying to do it like @foamyesque proposed, though I'm quite sure it doesn't do it the way I want it, or I will end up making copys of every single armor and exchange during the activation process. Unfortunately this would limit the whole idea to vanilla objects. The thing is, I do absolutely not understand why it affects all instances of the item in game, while the wiki site clearly says it only affects the equipped weapon... http://www.creationkit.com/index.php?title=SetBaseDamage_-_Weapon So again, what would happen if I try to add the said item to a reference alias and get its form as weapon? Would this also affect all instances? Edit: On a second note. I figured I could apply a invisible enchantment debuff lowering value and damage/armor rate? Link to comment Share on other sites More sharing options...
NagusQuark Posted April 27, 2017 Share Posted April 27, 2017 The thing is, I do absolutely not understand why it affects all instances of the item in game, while the wiki site clearly says it only affects the equipped weapon... http://www.creationkit.com/index.php?title=SetBaseDamage_-_Weapon So again, what would happen if I try to add the said item to a reference alias and get its form as weapon? Would this also affect all instances? The wiki says nothing about it only changing the specific weapon. The wiki's use of the word "this weapon" means the base record of it, not just this copy of it.A weapon form always points to the base object, your only way to do it is to make a copy of every single item you want changed in the game, then scanning the loot container and swapping out the appropriate items with your copies upon npc's death.If you want there to be the possibility for a weapon to exist in several different degradation states at the same time, you'll need a separate copy for each and every state. It's more hassle than it's worth tbh. Link to comment Share on other sites More sharing options...
CrEaToXx Posted April 27, 2017 Author Share Posted April 27, 2017 Ha! Got it working. Add an enchanment after droping. Don't forget that .setEnchantment() will replace any original enchantment on the item, so you probably want to exclude enchantent weapons from restriction. Make sure to not use setEnchantment() for the base item type. You probably also want to make it a hidden enchantment and unique weapons should be excluded inside a formlist. Here's proof of concept, with visual active enchantment still applied. I did a detrimental of 50 for testing purposes... :smile: http://i.imgur.com/2rWLru1.jpg Notice there's still the original description and other default stuff. The indicator for working success is down low where it says "Armor Rating". This perfectly works for armor rate, weapon damage and sell prizes(in combination with a perk). Skyrim is to Easy - Equipment&Loot should be ready to release by tomorrow... :smile: Link to comment Share on other sites More sharing options...
foamyesque Posted April 27, 2017 Share Posted April 27, 2017 (edited) If you were after just looted gear, yeah, my method won't work; it would apply to anything and everything the player used. There's a case the drop method has real problems with though: What happens if a player already has one piece of kit, an iron helmet or whatever, and they pick up a second one? You're using enchantments, so you can figure out whether or not you've proc'd the thing before, but dropobject doesn't guarantee which copy of a form is dropped. This means to guarantee applicability, every time the player picks up something, you'd need to drop every one of those items, including anything they might happen to have equipped, out into the world, check them all, then put them back, and restore the the equip status. This is a slow process and it will be noticeable and intrusive to the player whenever it happens. Edited April 27, 2017 by foamyesque Link to comment Share on other sites More sharing options...
CrEaToXx Posted April 27, 2017 Author Share Posted April 27, 2017 See upside. I'm injecting a dummy miscobject check to not apply this to the same dead actor again. Also, if you're talking about picking up from your next victim. Yes, that's what I want. Every piece of looted equipment/weapon will have the enchantment applied. And if you pick up two of the same kits, they will simply stack, just as the unaffected version would. See the script snippet: If akCuirass != none ObjectReference akCuirassRef = akTarget.DropObject(akCuirass) as ObjectReference If akCuirassRef.GetEnchantment() == none Utility.WaitMenuMode(0.1) akCuirassRef.SetEnchantment(SITE_ArmorRateEnch, 0.0) akTarget.AddItem(akCuirassRef) EndIf EndIf The check for an enchantment already applied is enough to make sure that the enchantment doesn't get applied a second time, and also maing sure, that unique and already enchanted weapons are not affected. Basically I just want to handle the ordinary plunder. I want to enforce players to either build or buy equipment. Looting is way to easy in Skyrim. Link to comment Share on other sites More sharing options...
foamyesque Posted April 27, 2017 Share Posted April 27, 2017 (edited) See upside. I'm injecting a dummy miscobject check to not apply this to the same dead actor again. Also, if you're talking about picking up from your next victim. Yes, that's what I want. Every piece of looted equipment/weapon will have the enchantment applied. And if you pick up two of the same kits, they will simply stack, just as the unaffected version would. See the script snippet: If akCuirass != none ObjectReference akCuirassRef = akTarget.DropObject(akCuirass) as ObjectReference If akCuirassRef.GetEnchantment() == none Utility.WaitMenuMode(0.1) akCuirassRef.SetEnchantment(SITE_ArmorRateEnch, 0.0) akTarget.AddItem(akCuirassRef) EndIf EndIfThe check for an enchantment already applied is enough to make sure that the enchantment doesn't get applied a second time, and also maing sure, that unique and already enchanted weapons are not affected. Basically I just want to handle the ordinary plunder. I want to enforce players to either build or buy equipment. Looting is way to easy in Skyrim. The check is enough to make sure it's not applied a second time. It is not enough to make sure it is applied every time. Here's something that can happen: 1. Player loots Iron Helmet, has none in inventory. It gets dropped, enchantment applied to debuff it, and added back to the player inventory. This is your code flow working as intended.2. Player loots a second Iron Helmet, and has one in inventory. One gets dropped. You don't know, and can't control, which one. If it is the already enchanted one, your code notices this and returns it back to the inventory, leaving you with one enchanted and one unenchanted Iron Helmet. This is your code flow not working as intended. Or: Suppose the player equips that first helmet, and then loots a second one. Your code may drop the equipped helmet, and while it gives it back to the player, there's no provisions made to re-equip it. So whenever a player happens to loot something they already have equipped, there's a chance for their equipment to suddenly change on them. I'm a dummy, you're calling this on the looted target, not the player, so avoid objections are void. You'll still want some provision for multiple copies of the same item, I think, and any corpse activated by the player is going to have their kit unequipped... EDIT: Also, I believe calling GetEnchantment on an ObjectReference will only return player or script-added enchantments. It doesn't get at pre-existing enchantments from the base form. I don't know how SetEnchantment behaves when called on an ObjectRef whose base forms already have an enchantment set, so let me know your results. Edited April 27, 2017 by foamyesque Link to comment Share on other sites More sharing options...
Recommended Posts