cfh85 Posted August 31, 2012 Author Share Posted August 31, 2012 (edited) What I had in mind was to set the weapon as non playable. The ability will scan the NPCs inventory every 10minutes (maybe more), evaluate the weapons in the NPCs inventory. Of the ones that fit the right criteria (Bows for archers, any blade for swordsman etc) the script will pick the best one, if it's different from the last one it picked it will change the clone to match. It the unequips and re-equips the weapon so the changes take effect. This will cause some issues. Firstly I don't think I can account for enchantments (I haven't looked into it yet) so currently it's just Damage, reach and speed.Secondly if you change the NPCs weapons it may take 10 minutes to change - the alternative is to run the script more often, but I don't think it's too much of a problem.Thirdly, when you reload the game it should (due to the way the functions work) revert back to the original clone, until the script runs and changes it. the script I have so far, that needs finishing as I wrote it without internet access so I need to check/improve/finish lots of it Scriptname CFHCompanionsClass13AbilityScript ;Knife Dancer - Lightning Speed Ref Self Ref Weapon1 ;The base weapon. Ref Weapon1Base Ref Weapon2 ;The current weapon the base is copying Ref WeaponBase ;Base object of original cloned weapon Ref TempWeapon ;The new weapon to be copied Ref InventoryItem Float Timer Float Counter Float IISpeed Float IIReach Float IIDamage Float IIRating Float TempWeaponRating Float Level Float SpeedMod Float Fame Float Infamy Float Renown Begin ScriptEffectUpdate If Timer > 0 Set Timer to (Timer - GetSecondsPassed) Return Else USE ARRAY TO SEE WHAT ITEMS ARE IN THE NPCS INVENTORY While Counter > 0 Let Counter -= 1 If (InventoryItem.IsWeapon == 0) Continue ElseIf (InventoryItem.GetWeaponType != 0) Continue ElseIf ((GetWeaponReach InventoryItem) > 0.7) Continue Else Set IISpeed to (GetWeaponSpeed InventoryItem) Set IIReach to (GetWeaponReach InventoryItem) Set IIDamage to (GetAttackDamage InventoryItem) Set IIRating to (IIDamage * IISpeed * IIReach * IIReach) If IIRating > TempWeaponRating Set TempWeapon to InventoryItem Set TempWeaponRating to IIRating EndIf EndIf SET NEXT REFERENCE Loop If TempWeapon == Weapon2 Set Timer to 600 Return Else Set Fame to GetPCFame set Infamy to GetPCInfamy Set Renown to (Fame + Infamy) Set Level to (Self.GetFactionRank CFHCompanionLevelFaction) If (Level > (Renown / 3)) Set Level to (Renown / 3) EndIf Set SpeedMod to (1 + (Level / 50)) SETMODELPATH Set IISpeed to ((GetWeaponSpeed TempWeapon) * SpeedMod) Set IIReach to (GetWeaponReach TempWeapon) Set IIDamage to (GetAttackDamage TempWeapon) SetWeaponSpeed IISpeed Weapon1 SetWeaponReach IIReach Weapon1 SetAttackDamage IIDamage Weapon1 Self.UnequipItemNS Weapon1 Self.EquipItemNS Weapon1 Set Timer to 600 Return EndIf EndIf End Begin ScriptEffectStart Set Self to GetSelf Set Timer to 600 USE ARRAY TO SEE WHAT ITEMS ARE IN THE NPCS INVENTORY While Counter > 0 Let Counter -= 1 If (InventoryItem.IsWeapon == 0) Continue ElseIf (InventoryItem.GetWeaponType != 0) Continue ElseIf ((GetWeaponReach InventoryItem) > 0.7) Continue Else Set IISpeed to (GetWeaponSpeed InventoryItem) Set IIReach to (GetWeaponReach InventoryItem) Set IIDamage to (GetAttackDamage InventoryItem) Set IIRating to (IIDamage * IISpeed * IIReach * IIReach) If IIRating > TempWeaponRating Set TempWeapon to InventoryItem Set TempWeaponRating to IIRating EndIf EndIf SET NEXT REFERENCE Loop Set Weapon2 to TempWeapon Set WeaponBase to Weapon2.GetBaseObject Set Weapon1Base to CloneForm WeaponBase MOVE A REF OF WEAPON1BASE INTO NPCS INVENTORY, SET WEAPON1 AS REF AND EQUIP ITEM End EDITI think this is the array function I need to use GetItems . It says about using form types to restrict the results. Not to sure about form types, could I set it to only return weapons? Edited August 31, 2012 by cfh85 Link to comment Share on other sites More sharing options...
WarRatsG Posted August 31, 2012 Share Posted August 31, 2012 Wouldnt you be much better off using an OnAdd Event handler? It would remove a lot of those problems and streamline the entire process. No arrays either. It would allow you to just draw the variable straight from the event instead of evaluating the entire contents of someones inventory. But yes, the form codes for OBSE commands are listed on the OBSE documentation website. Link to comment Share on other sites More sharing options...
cfh85 Posted August 31, 2012 Author Share Posted August 31, 2012 I'm not entirely sure what you mean by using OnAdd. Wouldn't an OnAdd script need to be attached to the weapons? Link to comment Share on other sites More sharing options...
WarRatsG Posted August 31, 2012 Share Posted August 31, 2012 (edited) You misunderstand. Not an OnAdd block, but an OnAdd Event Handler. Event Handlers are independent scripts. Event Handlers run whenever the "event" that you state occurs in game. For example, I could make an event handler that runs whenever NPC X uses a healing spell, or when the player is hit, or when a type of guard sees a murder. They don't have a source like other scripts, as in a quest, object or magic effect - they're just there, running only when needed. Not only that, but the parameters of an event can be passed to the Event Handler script directly as arguements, removing a lot of the checks you would normally need. For example, going back to the event where the player is hit, I can obtain a reference to the attacker by passing the arguement to the Event Handler. You would be better off reading it from the OBSE website. They'll explain better than I will. Edited September 1, 2012 by WarRatsG Link to comment Share on other sites More sharing options...
cfh85 Posted September 1, 2012 Author Share Posted September 1, 2012 I had read some of the command documentation for V0020 and have since double checked and there is nothing on there for OnAdd. There is a lot in there that I need to add into my scripts. Every time I feel like I'm making progress with this mod I get more work to do :facepalm: though (primarily thanks to your help) I am learning a lot of things to improve my mod. I think I've got the idea of the event handlers, I just can't find the parameters for OnAdd. Would it be actor.ref item.ref ? Link to comment Share on other sites More sharing options...
WarRatsG Posted September 2, 2012 Share Posted September 2, 2012 You're right, there is no OnAdd Event. My apologies - since a lot of them matched standard blocktypes, I assumed OnAdd was among them. :rolleyes: So if we back up a little bit... GetItems seems like the best way to go. The form code for weapons is 33. Enchantments can be modified. You can find most of the related functions here. Note that Enchantments count as Magic Effects, so some of the functions you need may not specifically refer to enchantments. Without event handlers, the 10 minute wait problem remains. There is a solution, although it isn't quite clear yet. I recommend you look into User-Defined Functions as one possible solution. My first thought would be to switch on a bool in a gamemode blocktype, on the frame that the companions inventory is opened. This would prevent the gamemode block from running until the inventory window is closed. When it does close, the gamemode block immediately detects the switched on bool and uses the UD function to run all the checks, then switches off the bool. ScriptEffectUpdate blocks would probably work too. Instead of using SetModelPath, you may prefer:CopyModelPath - sets the model path of the calling reference or passed objectID to the model path from Object (nothing) reference.CopyModelPath fromObject:ref toObject:ref I really should just let you mod how you like, instead of backseat driving like this :P So long as you're learning something I guess 8) Link to comment Share on other sites More sharing options...
cfh85 Posted September 2, 2012 Author Share Posted September 2, 2012 The event handlers look fantastic, though limited for what I'm doing (primarily because I want my mod to be used in the same was a CM Partners is, by other modders) as the abilities are each given to several NPCs, so I can't filter it much. The one I have used is OnRelease as it's the only way I've found to detect when an NPC shoots an arrow.I'll read up on the user defined functions. This ability has flaws in the way it's implemented, some of the others I'm still unsure of where to start, so help and advice is always welcome Link to comment Share on other sites More sharing options...
cfh85 Posted September 2, 2012 Author Share Posted September 2, 2012 Just a quick question regarding user defined functions, do I need to attach the script to anything? Link to comment Share on other sites More sharing options...
WarRatsG Posted September 2, 2012 Share Posted September 2, 2012 Nope, think of it like an internal batch file, or a quest stage result script 8) Just call it and it will run. With Event Handlers and UD functions, you're getting to know just how useful OBSE really is ;) Link to comment Share on other sites More sharing options...
cfh85 Posted September 3, 2012 Author Share Posted September 3, 2012 This is the script I've got so far. I plan on using it a topic instead that will add the NPC to a faction used to trigger certain abilities, this will allow the script to run as the first 'if' in scripteffectupdate will be GetInfaction...return, once the NPC has chosen the new weapon to copy it will remove itself from the faction. Also I'll move most of the script into a UD function. I'm pretty sure these updates will be quick and easy and make it more efficient Scriptname CFHCompanionsClass13AbilityScript;Knife Dancer - Lightning SpeedArray_var WeaponsRef SelfRef Weapon1 ;The base weapon.Ref Weapon1BaseRef Weapon2 ;The current weapon the base is copyingRef WeaponBase ;Base object of original cloned weaponRef TempWeapon ;The new weapon to be copiedRef InventoryItemFloat TimerFloat IISpeedFloat IIReachFloat IIDamageFloat IIRatingFloat TempWeaponRatingFloat LevelFloat SpeedModFloat FameFloat InfamyFloat RenownFloat EquipShort KeyBegin ScriptEffectUpdate If Equip == 1 Self.EquipItemNS Weapon1 Set Equip to 0 EndIf If Timer > 0 Set Timer to (Timer - GetSecondsPassed) Return Else Let Weapons := (Self.GetItems 33) Let Key := ar_Size Weapons While Key > 0 Let Key -= 1 Let InventoryItem := Weapons[Key] If (InventoryItem.IsWeapon == 0) Continue ElseIf (InventoryItem.GetWeaponType != 0) Continue ElseIf (InventoryItem == Weapon1) Continue ElseIf ((GetWeaponReach InventoryItem) > 0.7) Continue Else Set IISpeed to (GetWeaponSpeed InventoryItem) Set IIReach to (GetWeaponReach InventoryItem) Set IIDamage to (GetAttackDamage InventoryItem) Set IIRating to (IIDamage * IISpeed * IIReach * IIReach) If IIRating > TempWeaponRating Set TempWeapon to InventoryItem Set TempWeaponRating to IIRating EndIf EndIf Loop If TempWeapon == Weapon2 Set Timer to 600 Return Else Set Fame to GetPCFame set Infamy to GetPCInfamy Set Renown to (Fame + Infamy) Set Level to (Self.GetFactionRank CFHCompanionLevelFaction) If (Level > (Renown / 3)) Set Level to (Renown / 3) EndIf Set SpeedMod to (1 + (Level / 50)) Weapon1.CopyModelPath TempWeapon Set Weapon2 to TempWeapon Set IISpeed to ((GetWeaponSpeed TempWeapon) * SpeedMod) Set IIReach to (GetWeaponReach TempWeapon) Set IIDamage to (GetAttackDamage TempWeapon) SetWeaponSpeed IISpeed Weapon1 SetWeaponReach IIReach Weapon1 SetAttackDamage IIDamage Weapon1 Self.UnequipItemNS Weapon1 Set Equip to 1 Set Timer to 600 Return EndIf EndIfEndBegin ScriptEffectStart Set Self to GetSelf Set Timer to 600 Let Weapons := (Self.GetItems 33) Let Key := ar_Size Weapons While Key > 0 Let Key -= 1 Let InventoryItem := Weapons[Key] If (InventoryItem.IsWeapon == 0) Continue ElseIf (InventoryItem.GetWeaponType != 0) Continue ElseIf ((GetWeaponReach InventoryItem) > 0.7) Continue Else Set IISpeed to (GetWeaponSpeed InventoryItem) Set IIReach to (GetWeaponReach InventoryItem) Set IIDamage to (GetAttackDamage InventoryItem) Set IIRating to (IIDamage * IISpeed * IIReach * IIReach) If IIRating > TempWeaponRating Set TempWeapon to InventoryItem Set TempWeaponRating to IIRating EndIf EndIf Loop Set Weapon2 to TempWeapon Set WeaponBase to Weapon2.GetBaseObject Set Weapon1Base to CloneForm WeaponBase Set Weapon1 to (Self.PlaceAtMe Weapon1Base 1, 0, 0,) Weapon1.Activate Self Self.EquipItem Weapon1End[/Code] Link to comment Share on other sites More sharing options...
Recommended Posts