/[skyui_scripts]/branch/skyui_510/Source/ski_favoritesmanager.psc
ViewVC logotype

Contents of /branch/skyui_510/Source/ski_favoritesmanager.psc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (show annotations) (download)
Sat Aug 12 15:05:05 2017 UTC (23 months ago) by william
File size: 30360 byte(s)
commit scripts for skyui 5.1
1 scriptname SKI_FavoritesManager extends SKI_QuestBase
2
3 import Math
4
5 ; SCRIPT VERSION ----------------------------------------------------------------------------------
6 ;
7 ; History
8 ;
9 ; 1: - Initial version
10 ;
11 ; 2: - Added check for vampire lord
12 ;
13 ; 3: - Less eagerly clearing of invalid entries
14
15 int function GetVersion()
16 return 3
17 endFunction
18
19
20 ; CONSTANTS ---------------------------------------------------------------------------------------
21
22 string property FAVORITES_MENU = "FavoritesMenu" autoReadonly
23 string property MENU_ROOT = "_root.MenuHolder.Menu_mc" autoReadonly
24
25 int property GROUP_FLAG_UNEQUIP_ARMOR = 1 autoReadonly
26 int property GROUP_FLAG_UNEQUIP_HANDS = 2 autoReadonly
27
28
29 ; PROPERTIES --------------------------------------------------------------------------------------
30
31 ; -- Version 1 --
32
33 Actor Property PlayerREF auto
34
35 bool property ButtonHelpEnabled = true auto
36
37 int property GroupAddKey
38 int function get()
39 return _groupAddKey
40 endFunction
41
42 function set(int a_val)
43 SwapControlKey(a_val, _groupAddKey)
44 _groupAddKey = a_val
45 endFunction
46 endProperty
47
48 int property GroupUseKey
49 int function get()
50 return _groupUseKey
51 endFunction
52
53 function set(int a_val)
54 SwapControlKey(a_val, _groupUseKey)
55 _groupUseKey = a_val
56 endFunction
57 endProperty
58
59 int property SetIconKey
60 int function get()
61 return _setIconKey
62 endFunction
63
64 function set(int a_val)
65 SwapControlKey(a_val, _setIconKey)
66 _setIconKey = a_val
67 endFunction
68 endProperty
69
70 int property SaveEquipStateKey
71 int function get()
72 return _saveEquipStateKey
73 endFunction
74
75 function set(int a_val)
76 SwapControlKey(a_val, _saveEquipStateKey)
77 _saveEquipStateKey = a_val
78 endFunction
79 endProperty
80
81 int property ToggleFocusKey
82 int function get()
83 return _toggleFocusKey
84 endFunction
85
86 function set(int a_val)
87 SwapControlKey(a_val, _toggleFocusKey)
88 _toggleFocusKey = a_val
89 endFunction
90 endProperty
91
92
93 ; PRIVATE VARIABLES -------------------------------------------------------------------------------
94
95 ; -- Version 1 --
96
97 Form[] _items1
98 Form[] _items2
99 int[] _itemIds1
100 int[] _itemIds2
101
102 int[] _groupFlags
103
104 Form[] _groupMainHandItems
105 int[] _groupMainHandItemIds
106
107 Form[] _groupOffHandItems
108 int[] _groupOffHandItemIds
109
110 Form[] _groupIconItems
111 int[] _groupIconItemIds
112
113 bool _silenceEquipSounds = false
114
115 SoundCategory _audioCategoryUI
116
117 ; Forms to support EquipSlot comparisons
118 EquipSlot _rightHandSlot
119 EquipSlot _eitherHandSlot
120 EquipSlot _leftHandSlot
121 EquipSlot _bothHandsSlot
122 EquipSlot _voiceSlot
123
124 ; State variables for Group Use
125 bool _usedRightHand = false
126 bool _usedLeftHand = false
127 bool _usedVoice = false
128 int _usedOutfitMask = 0
129
130 ; Keys
131 int _groupAddKey = 33 ; F
132 int _groupUseKey = 19 ; R
133 int _setIconKey = 56 ; LAlt
134 int _saveEquipStateKey = 20 ; T
135 int _toggleFocusKey = 57 ; Space
136
137 int[] _groupHotkeys
138
139 ; -- Version 2 --
140
141 Race _vampireLordRace
142
143 ; -- Version 3 --
144
145 bool[] _itemInvalidFlags1
146 bool[] _itemInvalidFlags2
147
148
149 ; INITIALIZATION ----------------------------------------------------------------------------------
150
151 event OnInit()
152 _items1 = new Form[128]
153 _items2 = new Form[128]
154 _itemIds1 = new int[128]
155 _itemIds2 = new int[128]
156
157 _groupFlags = new int[8]
158
159 _groupMainHandItems = new Form[8]
160 _groupMainHandItemIds = new int[8]
161
162 _groupOffHandItems = new Form[8]
163 _groupOffHandItemIds = new int[8]
164
165 _groupIconItems = new Form[8]
166 _groupIconItemIds = new int[8]
167
168 _groupHotkeys = new int[8]
169 _groupHotkeys[0] = 59 ; F1
170 _groupHotkeys[1] = 60 ; F2
171 _groupHotkeys[2] = 61 ; F3
172 _groupHotkeys[3] = 62 ; F4
173 _groupHotkeys[4] = -1
174 _groupHotkeys[5] = -1
175 _groupHotkeys[6] = -1
176 _groupHotkeys[7] = -1
177
178 _audioCategoryUI = Game.GetFormFromFile(0x00064451, "Skyrim.esm") as SoundCategory
179
180 _rightHandSlot = Game.GetFormFromFile(0x00013f42, "Skyrim.esm") as EquipSlot
181 _leftHandSlot = Game.GetFormFromFile(0x00013f43, "Skyrim.esm") as EquipSlot
182 _eitherHandSlot = Game.GetFormFromFile(0x00013f44, "Skyrim.esm") as EquipSlot
183 _bothHandsSlot = Game.GetFormFromFile(0x00013f45, "Skyrim.esm") as EquipSlot
184 _voiceSlot = Game.GetFormFromFile(0x00025bee, "Skyrim.esm") as EquipSlot
185
186 OnGameReload()
187 endEvent
188
189 ; @implements SKI_QuestBase
190 event OnGameReload()
191 CheckVersion()
192
193 RegisterForModEvent("SKIFM_groupAdd", "OnGroupAdd")
194 RegisterForModEvent("SKIFM_groupRemove", "OnGroupRemove")
195 RegisterForModEvent("SKIFM_groupUse", "OnGroupUse")
196 RegisterForModEvent("SKIFM_saveEquipState", "OnSaveEquipState")
197 RegisterForModEvent("SKIFM_setGroupIcon", "OnSetGroupIcon")
198 RegisterForModEvent("SKIFM_foundInvalidItem", "OnFoundInvalidItem")
199
200 RegisterForMenu(FAVORITES_MENU)
201
202 RegisterHotkeys()
203
204 CleanUp()
205 endEvent
206
207 ; @implements SKI_QuestBase
208 event OnVersionUpdate(int a_version)
209
210 ; Version 2
211 if (a_version >= 2 && CurrentVersion < 2)
212 Debug.Trace(self + ": Updating to script version 2")
213
214 _vampireLordRace = Game.GetFormFromFile(0x0000283A, "Dawnguard.esm") as Race
215 endIf
216
217 ; Version 3
218 if (a_version >= 3 && CurrentVersion < 3)
219 Debug.Trace(self + ": Updating to script version 3")
220
221 _itemInvalidFlags1 = new bool[128]
222 _itemInvalidFlags2 = new bool[128]
223 endIf
224
225 endEvent
226
227
228 ; EVENTS ------------------------------------------------------------------------------------------
229
230 event OnMenuOpen(string a_menuName)
231
232 int i = 0
233 while (i < 128)
234 _itemInvalidFlags1[i] = false
235 i += 1
236 endWhile
237
238 i = 0
239 while (i < 128)
240 _itemInvalidFlags2[i] = false
241 i += 1
242 endWhile
243
244 InitControls()
245 InitMenuGroupData()
246 endEvent
247
248 event OnFoundInvalidItem(string a_eventName, string a_strArg, float a_numArg, Form a_sender)
249 InvalidateItem(a_strArg as int,true)
250 endEvent
251
252 event OnGroupAdd(string a_eventName, string a_strArg, float a_numArg, Form a_sender)
253 int groupIndex = a_numArg as int
254 int itemId = a_strArg as int
255 Form item = a_sender
256
257 if (GroupAdd(groupIndex, itemId, item))
258 UpdateMenuGroupData(groupIndex)
259 else
260 UI.InvokeBool(FAVORITES_MENU, MENU_ROOT + ".unlock", true)
261 Debug.Notification("Group full!")
262 endIf
263 endEvent
264
265 event OnGroupRemove(string a_eventName, string a_strArg, float a_numArg, Form a_sender)
266 int groupIndex = a_numArg as int
267 int itemId = a_strArg as int
268
269 if (GroupRemove(groupIndex, itemId))
270 UpdateMenuGroupData(groupIndex)
271 else
272 UI.InvokeBool(FAVORITES_MENU, MENU_ROOT + ".unlock", true)
273 endIf
274 endEvent
275
276 ; Read the player's current equipment and save it to the target group
277 event OnSaveEquipState(string a_eventName, string a_strArg, float a_numArg, Form a_sender)
278 int groupIndex = a_numArg as int
279
280 int mainHandItemId = UI.GetInt(FAVORITES_MENU, MENU_ROOT + ".rightHandItemId")
281 int offHandItemId = UI.GetInt(FAVORITES_MENU, MENU_ROOT + ".leftHandItemId")
282
283 form mainHandForm = GetFormFromItemId(groupIndex,mainHandItemId) ; will return none if not in group
284 if (mainHandForm)
285 _groupMainHandItemIds[groupIndex] = mainHandItemId
286 _groupMainHandItems[groupIndex] = mainHandForm
287 else
288 _groupMainHandItemIds[groupIndex] = 0
289 _groupMainHandItems[groupIndex] = none
290 endIf
291
292 form offHandForm = GetFormFromItemId(groupIndex,offHandItemId)
293 if (offHandForm)
294 _groupOffHandItemIds[groupIndex] = offHandItemId
295 _groupOffHandItems[groupIndex] = offHandForm
296 else
297 _groupOffHandItemIds[groupIndex] = 0
298 _groupOffHandItems[groupIndex] = none
299 endIf
300
301 UpdateMenuGroupData(groupIndex)
302 endEvent
303
304 ; This will set a form as the icon form for a group
305 event OnSetGroupIcon(string a_eventName, string a_strArg, float a_numArg, Form a_sender)
306 int groupIndex = a_numArg as int
307 int itemId = a_strArg as int
308 Form item = a_sender
309
310 _groupIconItems[groupIndex] = item
311 _groupIconItemIds[groupIndex] = itemId
312
313 UpdateMenuGroupData(groupIndex)
314 endEvent
315
316 event OnGroupUse(string a_eventName, string a_strArg, float a_numArg, Form a_sender)
317 gotoState("PROCESSING")
318
319 GroupUse(a_numArg as int)
320
321 gotoState("")
322 endEvent
323
324 event OnKeyDown(int a_keyCode)
325 gotoState("PROCESSING")
326
327 int groupIndex = _groupHotkeys.Find(a_keyCode)
328 if (groupIndex != -1 && !Utility.IsInMenuMode())
329 GroupUse(groupIndex)
330 endIf
331
332 gotoState("")
333 endEvent
334
335 state PROCESSING
336
337 event OnGroupUse(string a_eventName, string a_strArg, float a_numArg, Form a_sender)
338 endEvent
339
340 event OnKeyDown(int a_keyCode)
341 endEvent
342
343 endState
344
345
346 ; FUNCTIONS ---------------------------------------------------------------------------------------
347
348 ;get whether a flag is set for the specified group
349 bool function GetGroupFlag(int a_groupIndex, int a_flag)
350 return LogicalAnd(_groupFlags[a_groupIndex], a_flag) as bool
351 endFunction
352
353 ;set a flag for the specified group
354 function SetGroupFlag(int a_groupIndex, int a_flag, bool a_value)
355 if (a_value)
356 _groupFlags[a_groupIndex] = LogicalOr(_groupFlags[a_groupIndex], a_flag)
357 else
358 _groupFlags[a_groupIndex] = LogicalAnd(_groupFlags[a_groupIndex], LogicalNot(a_flag))
359 endIf
360 endFunction
361
362 int[] function GetGroupHotkeys()
363 ; Return a copy
364 int[] result = new int[8]
365 int i = 0
366 while (i<8)
367 result[i] = _groupHotkeys[i]
368 i += 1
369 endWhile
370 return result
371 endFunction
372
373 bool function SetGroupHotkey(int a_groupIndex, int a_keycode)
374
375 ; Special case for unmap
376 if (a_keycode == -1)
377 _groupHotkeys[a_groupIndex] = -1
378 UnregisterForKey(oldKeycode)
379 return true
380 endIf
381
382 ; Old group index this keycode was bound to
383 int oldIndex = _groupHotkeys.Find(a_keycode)
384 ; Old keycode at the target position
385 int oldKeycode = _groupHotkeys[a_groupIndex]
386
387 ; Already assigned, no need to do anything
388 if (oldIndex == a_groupIndex)
389 return false
390 endIf
391
392 ; Swap
393 if (oldIndex != -1 && oldKeycode != -1)
394 _groupHotkeys[oldIndex] = oldKeycode
395 else
396 ; Unset previous group this key was assigned to
397 if (oldIndex != -1)
398 _groupHotkeys[oldIndex] = -1
399 endIf
400
401 ; If we replaced a key, unregister it
402 if (oldKeycode != -1)
403 UnregisterForKey(oldKeycode)
404 endIf
405
406 RegisterForKey(a_keycode)
407 endIf
408
409 _groupHotkeys[a_groupIndex] = a_keycode
410
411 return true
412 endFunction
413
414 ; Send the group data to the UI, so that when the user selects a group, it can filter its entries.
415 function InitControls()
416 int[] args = new int[6]
417 args[0] = ButtonHelpEnabled as int
418 args[1] = _groupAddKey
419 args[2] = _groupUseKey
420 args[3] = _setIconKey
421 args[4] = _saveEquipStateKey
422 args[5] = _toggleFocusKey
423
424 UI.InvokeIntA(FAVORITES_MENU, MENU_ROOT + ".initControls", args)
425 endFunction
426
427 ; Send the group data to the UI, so that when the user selects a group, it can filter its entries.
428 function InitMenuGroupData()
429 ; Don't send group data if vampire lord
430 if (_vampireLordRace == PlayerRef.GetRace())
431 return
432 endIf
433
434 ; groupCount, mainHandFormId[8], offHandFormId[8], iconFormId[8]
435 int[] args = new int[25]
436 args[0] = 8
437
438 int c = 1
439
440 int i = 0
441 while (i<8)
442 args[c] = _groupMainHandItemIds[i]
443 i += 1
444 c += 1
445 endWhile
446
447 i = 0
448 while (i<8)
449 args[c] = _groupOffHandItemIds[i]
450 i += 1
451 c += 1
452 endWhile
453
454 i = 0
455 while (i<8)
456 args[c] = _groupIconItemIds[i]
457 i += 1
458 c += 1
459 endWhile
460
461 UI.InvokeIntA(FAVORITES_MENU, MENU_ROOT + ".pushGroupItems", _itemIds1)
462 UI.InvokeIntA(FAVORITES_MENU, MENU_ROOT + ".pushGroupItems", _itemIds2)
463 UI.InvokeIntA(FAVORITES_MENU, MENU_ROOT + ".finishGroupData", args)
464 endFunction
465
466 function UpdateMenuGroupData(int a_groupIndex)
467 int offset = 32 * a_groupIndex
468
469 int[] itemIds
470
471 if (offset >= 128)
472 offset -= 128
473 itemIds = _itemIds2
474 else
475 itemIds = _itemIds1
476 endIf
477
478 ; groupIndex, mainHandItemId, offHandItemID, iconItemId, itemIds[32]
479 int[] args = new int[36]
480
481 args[0] = a_groupIndex
482 args[1] = _groupMainHandItemIds[a_groupIndex]
483 args[2] = _groupOffHandItemIds[a_groupIndex]
484 args[3] = _groupIconItemIds[a_groupIndex]
485
486 int i = 4
487 int j = offset
488
489 while (i<36)
490 args[i] = itemIds[j]
491
492 i += 1
493 j += 1
494 endWhile
495
496 ; This also unlocks the menu, so no need to call unlock
497 UI.InvokeIntA(FAVORITES_MENU, MENU_ROOT + ".updateGroupData", args)
498 endFunction
499
500 ; Ensure that our data is still valid. Might not be the case if a mod was uninstalled
501 function CleanUp()
502
503 ; Note on thread safety:
504 ; Since we don't manage an explicit group count, items can just be set or unset from multiple threads
505
506 int i = 0
507 while (i < _items1.length)
508
509 if (_items1[i] == none || _items1[i].GetFormID() == 0)
510 _items1[i] = none
511 _itemIds1[i] = 0
512 endIf
513
514 i += 1
515 endWhile
516
517 i = 0
518 while (i < _items2.length)
519
520 if (_items2[i] == none || _items2[i].GetFormID() == 0)
521 _items2[i] = none
522 _itemIds2[i] = 0
523 endIf
524
525 i += 1
526 endWhile
527 endFunction
528
529 bool function GroupAdd(int a_groupIndex, int a_itemId, Form a_item)
530 int offset = 32 * a_groupIndex
531
532 ; Select the target set of arrays, adjust offset
533 Form[] items
534 int[] itemIds
535 bool[] itemInvalidFlags
536
537 if (offset >= 128)
538 offset -= 128
539 items = _items2
540 itemIds = _itemIds2
541 itemInvalidFlags = _itemInvalidFlags2
542 else
543 items = _items1
544 itemIds = _itemIds1
545 itemInvalidFlags = _itemInvalidFlags1
546 endIf
547
548 ; Prevent the same itemId being added to a group twice
549 if (IsItemIdInGroup(a_groupIndex,a_itemId))
550 return true
551 endIf
552
553 ; Pick next free slot
554 int index = FindFreeIndex(itemIds, itemInvalidFlags, offset)
555
556 ; No more space in group?
557 if (index == -1)
558 return false
559 endIf
560
561 ; Store received data
562 items[index] = a_item
563 itemIds[index] = a_itemId
564 itemInvalidFlags[index] = false
565
566 ; If there's no icon item set yet, use this one
567 if (_groupIconItems[a_groupIndex] == none)
568 _groupIconItems[a_groupIndex] = a_item
569 _groupIconItemIds[a_groupIndex] = a_itemId
570 endIf
571
572 return true
573 endFunction
574
575 bool function GroupRemove(int a_groupIndex, int a_itemId)
576 int offset = 32 * a_groupIndex
577
578 ; Select the target set of arrays, adjust offset
579 Form[] items
580 int[] itemIds
581 bool[] itemInvalidFlags
582
583 if (offset >= 128)
584 offset -= 128
585 items = _items2
586 itemIds = _itemIds2
587 itemInvalidFlags = _itemInvalidFlags2
588 else
589 items = _items1
590 itemIds = _itemIds1
591 itemInvalidFlags = _itemInvalidFlags1
592 endIf
593
594 int i = offset
595 int n = offset+32
596 while (i < n)
597 if (itemIds[i] == a_itemId)
598 items[i] = none
599 itemIds[i] = 0
600 itemInvalidFlags[i] = false
601 i = n
602 else
603 i += 1
604 endIf
605 endWhile
606
607 if (a_itemId == _groupMainHandItemIds[a_groupIndex])
608 _groupMainHandItems[a_groupIndex] = none
609 _groupMainHandItemIds[a_groupIndex] = 0
610 endIf
611
612 if (a_itemId == _groupOffHandItemIds[a_groupIndex])
613 _groupOffHandItems[a_groupIndex] = none
614 _groupOffHandItemIds[a_groupIndex] = 0
615 endIf
616
617 if (a_itemId == _groupIconItemIds[a_groupIndex])
618 ReplaceGroupIcon(a_groupIndex)
619 endIf
620
621 return true
622 endFunction
623
624 function GroupUse(int a_groupIndex)
625 int offset = 32 * a_groupIndex
626
627 ; Select the target set of arrays, adjust offset
628 Form[] items
629 int[] itemIds
630 bool[] itemInvalidFlags
631
632 if (offset >= 128)
633 offset -= 128
634 items = _items2
635 itemIds = _itemIds2
636 itemInvalidFlags = _itemInvalidFlags2
637 else
638 items = _items1
639 itemIds = _itemIds1
640 itemInvalidFlags = _itemInvalidFlags1
641 endIf
642
643 ; Reset state
644 _usedRightHand = false
645 _usedLeftHand = false
646 _usedVoice = false
647 _usedOutfitMask = 0
648
649 ; These items are equipped later
650 form[] deferredItems = new Form[32]
651 int deferredIdx = 0
652
653 ; Encountered invalid items are removed at the end when speed is no longer an issue
654 int[] invalidItemIds = new int[32]
655 int invalidIdx = 0
656
657 ; Turn off UI sounds to avoid annoying clicking noise while swapping spells
658 _audioCategoryUI.Mute()
659
660 ; Unequip hands first?
661 if (GetGroupFlag(a_groupIndex,GROUP_FLAG_UNEQUIP_HANDS))
662 UnequipHand(0)
663 UnequipHand(1)
664 endIf
665
666 ; Process main and offhand items
667
668 ; Left first, to avoid problems when equipping the same weapon twice
669 Form offHandItem = _groupOffHandItems[a_groupIndex]
670 int offHandItemId = _groupOffHandItemIds[a_groupIndex]
671 if (offHandItem)
672 int itemType = offHandItem.GetType()
673 if (IsItemValid(offHandItem, itemType))
674 ProcessItem(offHandItem, itemType, false, true, offHandItemId)
675 endIf
676 endIf
677
678 Form mainHandItem = _groupMainHandItems[a_groupIndex]
679 int mainHandItemId = _groupMainHandItemIds[a_groupIndex]
680 if (mainHandItem)
681 int itemType = mainHandItem.GetType()
682 if (IsItemValid(mainHandItem, itemType))
683 ProcessItem(mainHandItem, itemType, false, false, mainHandItemId)
684 endIf
685 endIf
686
687 ; Validate & process items
688 int i = offset
689 int n = offset + 32
690 while (i < n)
691 Form item = items[i]
692 int itemId = itemIds[i]
693
694 if (item && item != mainHandItem && item != offHandItem && !itemInvalidFlags[i])
695 int itemType = item.GetType()
696
697 if (! IsItemValid(item, itemType))
698 invalidItemIds[invalidIdx] = itemId
699 invalidIdx += 1
700 elseIf (! ProcessItem(item, itemType, a_itemId = itemId))
701 deferredItems[deferredIdx] = item
702 deferredIdx += 1
703 endIf
704 endIf
705
706 i += 1
707 endWhile
708
709 ; Process deferred items
710 i = 0
711 while (i < deferredIdx)
712 Form item = deferredItems[i]
713 int itemType = item.GetType()
714
715 ProcessItem(item, itemType, false)
716
717 i += 1
718 endWhile
719
720 ; Unequip any armor not belonging to current outfit mask
721 if (GetGroupFlag(a_groupIndex,GROUP_FLAG_UNEQUIP_ARMOR))
722 int h = 0x00000001
723 while (h < 0x80000000)
724 Form wornForm = PlayerREF.GetWornForm(h)
725 if (wornForm)
726 if (!LogicalAND(h, _usedOutfitMask))
727 PlayerREF.UnEquipItemEX(wornForm)
728 endIf
729 endIf
730 h = LeftShift(h,1)
731 endWhile
732 endIf
733
734 _audioCategoryUI.UnMute() ; Turn UI sounds back on
735
736 i = 0
737 while (i<invalidIdx)
738 InvalidateItem(invalidItemIds[i])
739 i += 1
740 endWhile
741 endFunction
742
743 function UnequipHand(int a_hand)
744 int a_handEx = 1
745 if (a_hand == 0)
746 a_handEx = 2 ; unequipspell and *ItemEx need different hand args
747 endIf
748
749 Form handItem = PlayerREF.GetEquippedObject(a_hand)
750 if (handItem)
751 int itemType = handItem.GetType()
752 if (itemType == 22)
753 PlayerREF.UnequipSpell(handItem as Spell, a_hand)
754 else
755 PlayerREF.UnequipItemEx(handItem, a_handEx)
756 endIf
757 endIf
758 endFunction
759
760 bool function IsItemValid(Form a_item, int a_itemType)
761 ; Player has removed this item from Favorites, so don't use it and queue it for removal
762 if (! Game.IsObjectFavorited(a_item))
763 return false
764 endIf
765
766 ; This is a Spell or Shout and can't be counted like an item
767 if (a_itemType == 22 || a_itemType == 119)
768 return PlayerREF.HasSpell(a_item)
769 ; This is an inventory item
770 else
771 return PlayerREF.GetItemCount(a_item) > 0
772 endIf
773 endFunction
774
775 bool function ProcessItem(Form a_item, int a_itemType, bool a_allowDeferring = true, bool a_offHandOnly = false, int a_itemId = 0)
776
777 ; WEAPON ------------
778 if (a_itemType == 41)
779
780 ; Any weapon needs at least one free hand
781 if (_usedRightHand && _usedLeftHand)
782 return true
783 endIf
784
785 Weapon itemWeapon = a_item as Weapon
786 int weaponType = itemWeapon.GetweaponType()
787
788 ; It's one-handed and the player has a free hand
789 if (weaponType <= 4 || weaponType == 8) ; Fists(0), Swords(1), Daggers(2), War Axes(3), Maces(4), Staffs(8)
790 if (!_usedRightHand && !a_offHandOnly)
791
792 if (a_item == PlayerREF.GetEquippedObject(1) && a_itemId != PlayerREF.GetEquippedItemId(1))
793 UnequipHand(1) ; avoid damage-related bug when swapping for enhanced item
794 endIf
795 PlayerREF.EquipItemById(itemWeapon, a_itemId, 1, equipSound = _silenceEquipSounds)
796 _usedRightHand = true
797 elseIf (!_usedLeftHand)
798 if (a_item == PlayerREF.GetEquippedObject(0) && a_itemId != PlayerREF.GetEquippedItemId(0))
799 UnequipHand(0)
800 endIf
801 PlayerREF.EquipItemById(itemWeapon, a_itemId, 2, equipSound = _silenceEquipSounds)
802 _usedLeftHand = true
803 endIf
804
805 ; It's two-handed and both hands are free
806 elseIf (weaponType > 4 && !_usedRightHand && !_usedLeftHand)
807 if (a_item == PlayerREF.GetEquippedObject(0) && a_itemId != PlayerREF.GetEquippedItemId(0))
808 UnequipHand(0)
809 endIf
810 PlayerREF.EquipItemById(itemWeapon, a_itemId, equipSlot = 0, equipSound = _silenceEquipSounds)
811
812 _usedRightHand = true
813 _usedLeftHand = true
814 endIf
815
816 return true
817
818 ; ARMOR ------------
819 elseIf (a_itemType == 26)
820 int slotMask = (a_item as Armor).GetslotMask()
821
822 ; It's a shield...
823 if (slotMask == 512)
824 if (!_usedLeftHand)
825 PlayerREF.EquipItemById(a_item, a_itemId, equipSlot = 0, equipSound = _silenceEquipSounds)
826 _usedLeftHand = true
827 _usedOutfitMask += slotMask
828 endIf
829 ; It's not a shield, just equip it if slot is free
830 elseIf (! LogicalAnd(_usedOutfitMask,slotMask))
831 if (a_item == PlayerREF.GetWornForm(slotMask) && a_itemId != PlayerREF.GetWornItemId(slotMask))
832 PlayerREF.UnequipItemEx(a_item)
833 endIf
834
835 PlayerREF.EquipItemById(a_item, a_itemId, equipSlot = 0, equipSound = _silenceEquipSounds)
836 _usedOutfitMask += slotMask
837 endIf
838
839 return true
840
841 ; AMMO ------------
842 elseIf (a_itemType == 42) ;kAmmo
843 PlayerREF.EquipItemEX(a_item, equipSlot = 0, equipSound = _silenceEquipSounds)
844 return true
845
846 ; SPELL ------------
847 elseIf (a_itemType == 22)
848
849 Spell itemSpell = a_item as Spell
850 EquipSlot spellEquipSlot = itemSpell.GetEquipType()
851
852 if (spellEquipSlot != _voiceSlot)
853
854 ; Any non power spell needs at least one free hand
855 if (_usedRightHand && _usedLeftHand)
856 return true
857 endIf
858
859 ; spell is eitherhanded
860 if (spellEquipSlot == _eitherHandSlot)
861 if (!_usedRightHand && !a_offHandOnly)
862 PlayerREF.EquipSpell(itemSpell, 1)
863 _usedRightHand = true
864 elseIf (!_usedLeftHand)
865 PlayerREF.EquipSpell(itemSpell, 0)
866 _usedLeftHand = true
867 endIf
868
869 ; Spell requires two hands ...
870 elseIf (spellEquipSlot == _bothHandsSlot)
871 if (!_usedRightHand && !_usedLeftHand)
872 PlayerREF.EquipSpell(itemSpell, 1)
873 _usedRightHand = true
874 _usedLeftHand = true
875 endIf
876
877 ; a lot of NPC spells are left-hand only, so if the player is using PSB they'll need this
878 elseIf (spellEquipSlot == _leftHandSlot)
879 if (!_usedLeftHand)
880 PlayerREF.EquipSpell(itemSpell, 0)
881 _usedLeftHand = true
882 endIf
883 endIf
884
885 else
886 if (!_usedVoice)
887 PlayerREF.EquipSpell(itemSpell, 2)
888 _usedVoice = true
889 endIf
890 endIf
891
892 return true
893
894 ; SCROLL ------------
895 elseIf (a_itemType == 23)
896 Scroll itemScroll = a_item as Scroll
897
898 ; Any scroll needs at least one free hand
899 if (_usedRightHand && _usedLeftHand)
900 return true
901 endIf
902 ;FIXME - GetEquipType seems to be broken for scrolls
903 ;If (itemScroll.GetEquipType() == _bothHandsSlot && !_usedLeftHand && !_usedRightHand)
904 ; PlayerREF.EquipItemEX(itemScroll, equipSlot = 0, equipSound = _silenceEquipSounds)
905 ; _usedLeftHand = true
906 ; _usedRightHand = true
907 if (!_usedRightHand && !a_offHandOnly)
908 PlayerREF.EquipItemEX(itemScroll, equipSlot = 1, equipSound = _silenceEquipSounds)
909 _usedRightHand = true
910 elseIf (!_usedLeftHand)
911 PlayerREF.EquipItemEX(itemScroll, equipSlot = 2, equipSound = _silenceEquipSounds)
912 _usedLeftHand = true
913 endIf
914
915 return true
916
917 ; SHOUT ------------
918 elseIf (a_itemType == 119)
919 if (!_usedVoice)
920 PlayerREF.EquipShout(a_item as Shout)
921 _usedVoice = true
922 endIf
923
924 return true
925
926 ; POTION ------------
927 elseIf (a_itemType == 46)
928 if ((a_item as Potion).IsHostile()) ; This is a poison and should only be applied after new weapons have been equipped.
929 if (a_allowDeferring)
930 return false
931 endIf
932
933 ; This will fail if a poisonable weapon is only equipped in the offhand. That's a Skyrim bug, not my bug.
934 PlayerREF.EquipItem(a_item, abSilent = True)
935
936 return true
937 endiF
938
939 ; This is a non-hostile potion, food, or... something? and can be used immediately
940 PlayerREF.EquipItem(a_item as Potion, abSilent = True)
941
942 return true
943
944 ; INGREDIENT ------------
945 elseIf (a_itemType == 30) ;kIngredient
946 PlayerREF.EquipItem(a_item as Ingredient, abSilent = True)
947 return true
948
949 ; LIGHT (TORCH) ------------
950 elseIf (a_itemType == 31)
951 if (!_usedLeftHand)
952 PlayerREF.EquipItemEX(a_item, equipSlot = 0, equipSound = _silenceEquipSounds)
953 _usedLeftHand = true
954 endIf
955
956 return true
957 endIf
958
959 return true
960 endFunction
961
962 function InvalidateItem(int a_itemId, bool redrawIcon = false)
963 int index
964
965 ; GroupData
966 index = _itemIds1.Find(a_itemId)
967 if (index != -1)
968 _itemInvalidFlags1[index] = true
969 endIf
970
971 index = _itemIds2.Find(a_itemId)
972 if (index != -1)
973 _itemInvalidFlags2[index] = true
974 endIf
975
976 ; Main hand
977 index = _groupMainHandItemIds.Find(a_itemId)
978 if (index != -1)
979 _groupMainHandItems[index] = none
980 _groupMainHandItemIds[index] = 0
981 endIf
982
983 ; Off hand
984 index = _groupOffHandItemIds.Find(a_itemId)
985 if (index != -1)
986 _groupOffHandItems[index] = none
987 _groupOffHandItemIds[index] = 0
988 endIf
989
990 ; Icon
991 index = _groupIconItemIds.Find(a_itemId)
992 if (index != -1)
993 ReplaceGroupIcon(index)
994 if (redrawIcon)
995 UpdateMenuGroupData(index)
996 endIf
997 endIf
998 endFunction
999
1000 int function FindFreeIndex(int[] a_itemIds, bool[] a_itemInvalidFlags, int offset)
1001 int i = a_itemIds.Find(0,offset)
1002
1003 ; First try to find an entry that is 0
1004 if (i >= offset && i < offset + 32)
1005 return i
1006 endIf
1007
1008 ; Failed. Now try to claim an entry flagged as invalid.
1009 i = offset
1010 int n = offset + 32
1011 while (i < n)
1012 if (a_itemInvalidFlags[i])
1013 return i
1014 endIf
1015
1016 i += 1
1017 endWhile
1018
1019 return -1
1020 endFunction
1021
1022 function ReplaceGroupIcon(int a_groupIndex)
1023
1024 ; If player has MH or OH set for the group, use it first
1025 if (_groupMainHandItemIds[a_groupIndex])
1026 _groupIconItems[a_groupIndex] = _groupMainHandItems[a_groupIndex]
1027 _groupIconItemIds[a_groupIndex] = _groupMainHandItemIds[a_groupIndex]
1028 return
1029 elseIf (_groupOffHandItemIds[a_groupIndex])
1030 _groupIconItems[a_groupIndex] = _groupOffHandItems[a_groupIndex]
1031 _groupIconItemIds[a_groupIndex] = _groupOffHandItemIds[a_groupIndex]
1032 return
1033 endIf
1034
1035 int offset = a_groupIndex * 32
1036
1037 ; Select the target set of arrays, adjust offset
1038 Form[] items
1039 int[] itemIds
1040 bool[] itemInvalidFlags
1041
1042 if (offset >= 128)
1043 offset -= 128
1044 items = _items2
1045 itemIds = _itemIds2
1046 itemInvalidFlags = _itemInvalidFlags2
1047 else
1048 items = _items1
1049 itemIds = _itemIds1
1050 itemInvalidFlags = _itemInvalidFlags1
1051 endIf
1052
1053 int i = offset
1054 int n = offset+32
1055
1056 ; Use icon of first found item
1057 while (i < n)
1058 if (items[i] != none && !itemInvalidFlags[i])
1059 _groupIconItems[a_groupIndex] = items[i]
1060 _groupIconItemIds[a_groupIndex] = itemIds[i]
1061 return
1062 else
1063 i += 1
1064 endIf
1065 endWhile
1066
1067 _groupIconItems[a_groupIndex] = none
1068 _groupIconItemIds[a_groupIndex] = 0
1069 endFunction
1070
1071 ; utility function to see if form is in the specified group.
1072 bool function IsFormInGroup(int a_groupIndex, form a_item)
1073 int offset = 32 * a_groupIndex
1074
1075 ; Select the target set of arrays, adjust offset
1076 Form[] items
1077
1078 if (offset >= 128)
1079 offset -= 128
1080 items = _items2
1081 else
1082 items = _items1
1083 endIf
1084
1085 int i = items.Find(a_item,offset)
1086 if (i >= offset && i < offset+32)
1087 return true
1088 endIf
1089
1090 return false
1091 endFunction
1092
1093 ; utility function to see how many of the form are in a group
1094 int function GetNumFormsInGroup(int a_groupIndex,form a_item)
1095 int offset = 32 * a_groupIndex
1096
1097 ; Select the target set of arrays, adjust offset
1098 form[] items
1099
1100 if (offset >= 128)
1101 offset -= 128
1102 items = _items2
1103 else
1104 items = _items1
1105 endIf
1106
1107 int i = offset
1108 int n = offset + 32
1109 int count
1110 while (i < n)
1111 if (items[i] == a_item)
1112 count += 1
1113 endIf
1114 i += 1
1115 endWhile
1116
1117 return count
1118 endFunction
1119
1120 form function GetFormFromItemId(int a_groupIndex,int itemId)
1121 int offset = 32 * a_groupIndex
1122 ; Select the target set of arrays, adjust offset
1123 form[] items
1124 int[] itemIds
1125
1126 if (offset >= 128)
1127 offset -= 128
1128 items = _items2
1129 itemIds = _itemIds2
1130 else
1131 items = _items1
1132 itemIds = _itemIds1
1133 endIf
1134
1135 int i = itemIds.Find(itemId,offset)
1136 if (i >= offset && i < offset + 32)
1137 return items[i]
1138 else
1139 return none
1140 endIf
1141 endFunction
1142
1143 ; return the Nth itemId
1144 int function GetNthItemIdInGroup(int a_groupIndex,form a_item,int a_num = 1)
1145 int offset = 32 * a_groupIndex
1146 ; Select the target set of arrays, adjust offset
1147 form[] items
1148 int[] itemIds
1149
1150 if (offset >= 128)
1151 offset -= 128
1152 items = _items2
1153 itemIds = _itemIds2
1154 else
1155 items = _items1
1156 itemIds = _itemIds1
1157 endIf
1158
1159 int i = offset
1160 int n = offset + 32
1161 int count = 0
1162
1163 int result = offset
1164 while (result >= offset && result < n && count < a_num)
1165 result = items.Find(a_item,i)
1166 i = result + 1
1167 count += 1
1168 endWhile
1169 if (result >= offset && result < n)
1170 return itemIds[result]
1171 endIf
1172 return 0
1173 endFunction
1174
1175 ; utility function to see if itemId is in the specified group.
1176 bool function IsItemIdInGroup(int a_groupIndex, int a_itemId)
1177 int offset = 32 * a_groupIndex
1178
1179 ; Select the target set of arrays, adjust offset
1180 int[] itemIds
1181
1182 if (offset >= 128)
1183 offset -= 128
1184 itemIds = _itemIds2
1185 else
1186 itemIds = _itemIds1
1187 endIf
1188
1189 int i = itemIds.Find(a_itemId,offset)
1190 if (i >= offset && i < offset+32)
1191 return true
1192 endIf
1193
1194 return false
1195 endFunction
1196
1197 function RegisterHotkeys()
1198 int i = 0
1199
1200 while (i < _groupHotkeys.Length)
1201
1202 if (_groupHotkeys[i] != -1)
1203 RegisterForKey(_groupHotkeys[i])
1204 endIf
1205
1206 i += 1
1207 endWhile
1208 endFunction
1209
1210 function SwapControlKey(int a_newKey, int a_curKey)
1211 if (a_newKey == _groupAddKey)
1212 _groupAddKey = a_curKey
1213 elseIf (a_newKey == _groupUseKey)
1214 _groupUseKey = a_curKey
1215 elseIf (a_newKey == _setIconKey)
1216 _setIconKey = a_curKey
1217 elseIf (a_newKey == _saveEquipStateKey)
1218 _saveEquipStateKey = a_curKey
1219 elseIf (a_newKey == _toggleFocusKey)
1220 _toggleFocusKey = a_curKey
1221 endIf
1222 endFunction
1223
1224 ; DEBUG ------------------------------------------------------------------------------------------
1225
1226 function PrintGroupItems(int a_groupIndex)
1227 ;This is here so I can see what's in the group, because the UI is currently broken
1228 Debug.Trace("PrintGroupItems called on group " + a_groupIndex)
1229
1230 int offset = 32 * a_groupIndex
1231
1232 ; Select the target set of arrays, adjust offset
1233 Form[] items
1234 int[] itemIds
1235
1236 if (offset >= 128)
1237 offset -= 128
1238 items = _items2
1239 itemIds = _itemIds2
1240 else
1241 items = _items1
1242 itemIds = _itemIds1
1243 endIf
1244
1245 int i = offset
1246 int n = offset + 32
1247 while (i < n)
1248 if (items[i])
1249 Debug.Trace(i + " is " + itemIds[i] + ", form is " + items[i] + ": " + items[i].GetName())
1250 endIf
1251 i += 1
1252 endWhile
1253 if (_groupIconItemIds[a_groupIndex])
1254 Debug.Trace("Group icon is " + _groupIconItemIds[a_groupIndex] + ", form is " + _groupIconItems[a_groupIndex] + ": " + _groupIconItems[a_groupIndex].GetName())
1255 endIf
1256 if (_groupMainHandItemIds[a_groupIndex])
1257 Debug.Trace("Group MH is " + _groupMainHandItemIds[a_groupIndex] + ", form is " + _groupMainHandItems[a_groupIndex] + ": " + _groupMainHandItems[a_groupIndex].GetName())
1258 endIf
1259 if (_groupOffHandItemIds[a_groupIndex])
1260 Debug.Trace("Group OH is " + _groupOffHandItemIds[a_groupIndex] + ", form is " + _groupOffHandItems[a_groupIndex] + ": " + _groupOffHandItems[a_groupIndex].GetName())
1261 endIf
1262 endFunction

  ViewVC Help
Powered by ViewVC 1.1.22