Scripting Tutorial: Modify Weapon On Equip
Intro
This article covers modifying a weapon when equipped. After searching many websites including this one I decided to write an article on what I learned about onEquip and OBSE 18. onEquip has its own challenges for what it can run and OBSE works great when applied properly. Lets get to it.
The scope of what I was trying to accomplish was: equip a weapon, have the weapon modify itself and become enchanted conditionally, and to not need a user action to make this happen other than equip.
Because I am a novice Oblivion scripter I went for the first solution. Run everything from the onEquip function attached to the object's script. Wrong! I spent a lot of time trying various things only to get strange results or simply it didn't work. At one point I found I could create a cloneform of the base form of an object, but when enchanting inside the onEquip function it would enchant base forms and clone forms alike. Not what I wanted to say the least. So once I realized the folly was putting everything in the onEquip call it was time to look outside the event.
The next step I took was trying to get onEquip to "Cast" an enchantment that did exactly what I wanted. However, like before I ran into it just won't work from onEquip syndrome. The next thing I tried was adding an object to the players inventory (a ring) that had the spell. This created a whole bunch of issues and still didn't work. I even tried calling EquipItem2 but that crashed Oblivion. What to do...
Finally I figured it out. Don't try to do much of anything inside onEquip! Don't daisy chain calls, spells, etc. Set a flag and let another script service the flag/event. What would be able to do that? A quest script can. So, here is some basic code to show you what I mean.
Part 1: OnEquip Method
OnEquip method for object script sets event flag in quest.
begin OnEquip Player Set WOLEvents.EvEquipWOL to 1 ; Set event flag end
Part 2: Event Flag
Event flag detected in quest.
if (EvEquipWOL) ; Detecting event flag PrintC "Cloning weapon" set Weapon to Player.GetEquippedObject 16 ; Get the equipped weapon base type. Call WOLCloneWeapon Weapon ; OBSE 18 Function call. Reduces code in scripts. set EvEquipWOL to 0 ; Event flag reset endif
Part 3: OBSE 18 Function call
This is our OBSE 18 "Function" call to do the dirty work. The handy part of this function is that I use the exact same function in a spell designed to do the same thing. Only change the important code once. Code reuse. I know, sick and wrong.
begin Function { Weapon } set test to IsClonedForm Weapon if ( test ) PrintC "Already cloned: %i", Weapon else set TWeapon to CloneForm Weapon SetEnchantment WOLWeaponStrike TWeapon set ClonedWeapon to TWeapon Player.RemoveItemNS Weapon 1 Player.AddItemNS ClonedWeapon 1 Player.EquipItemNS ClonedWeapon PrintC "New clone: %i, Old: %i" ClonedWeapon Weapon set Weapon to ClonedWeapon endif SetFunctionValue Weapon sv_Destruct ctext end
Sweet isn't it?! OBSE 18 is certainly making this a lot easier with the new features.
Conclusion
I sure hope this article saves someone some headache. OBSE is a great tool to do some neat things with Oblivion, but sometimes understanding exactly how to do something helps tremendously. I know it took me quite a while to understand some of the intricacies. The one that really threw me was this:
TWeapon.SetEnchantment WOLWeaponStrike
OR
SetEnchantment WOLWeaponStrike TWeapon
The first one "sort of" works in the onEquip function. It doesn't do what it is supposed to, but it sort of works. But the first one would not work at all in the code I laid out above. The second one is the proper way to do it for an objectID and works well. For what I was doing the second one is what I should have been using. Unfortunately it took a few hours to understand one was a 'refID' and the other was a 'objectID'. Anyway, that is how we learn...