WickedGoblin Posted May 3 Share Posted May 3 Scriptname LimitedSpellLearningScript extends ReferenceAlias GlobalVariable Property MaximumLearning Auto GlobalVariable Property CurrentLearning Auto Actor Property PlayerRef Auto Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference) Book b = (akBaseObject as Book) if b Spell s = b.GetSpell() if s if !PlayerRef.HasSpell(s) && CurrentLearning.GetValue() < MaximumLearning.GetValue() Int Temp = CurrentLearning.GetValue() as Int CurrentLearning.SetValue(Temp + 1) elseif !PlayerRef.HasSpell(s) && CurrentLearning.GetValue() >= MaximumLearning.GetValue() PlayerRef.RemoveSpell(s) Debug.Notification("This Spell Cant be learned") else return endif endif endif EndEvent Global Variables like MaximumLearning and CurrentLearning arent changed When I read a spell book What did I miss? Link to comment Share on other sites More sharing options...
scorrp10 Posted May 3 Share Posted May 3 What exactly does this script attach to? My assumption it is to Player Alias in the owning quest. Is the quest running? Are the properties loaded in the 'Properties' page with their corresponding forms? I would enable Papyrus logging, and add a Debug.Trace statement at the beginning of your function to make sure that is is indeed being called. I also assume that your CurrentLearning and MaximumLearning GVs are initialized somewhere to proper values. Now, to the actual logic of your code: when a player reads a book that teaches a spell, the book is consumed and the spell is added to the player. This is done in-engine, which is much faster than papyrus, which means that by the time this event handler gets called, the spell potentially was already added to the player. Meaning that '!PlayerRef.HasSpell(s)' clause is going to fail since by that time, player already has the spell. I suggest you add a clause that verifies it and do a Debug.Trace If PlayerRef.HasSpell(s) Debug.Trace(Self + "Player already has spell " + s) EndIf What can you do: Normal books in the world, when activated, open up for you to read, and from there you can choose to take the book. But spell books are added to your inventory, and you need to use a book from inventory to learn the spell. In other words, before a spell book can be read, it has to be added to your inventory. Thus, what you can do: First, in your mod, you create an empty FormList. Then, your script: Scriptname LimitedSpellLearningScript extends ReferenceAlias GlobalVariable Property MaximumLearning Auto GlobalVariable Property CurrentLearning Auto FormList Property PendingSpells Auto Actor Property PlayerRef Auto Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) Book b = (akBaseItem as Book) If b Spell s = b.GetSpell() If s If !PlayerRef.HasSpell(s) && !PendingSpells.HasForm(s) PendingSpells.AddForm(s) EndIf EndIf EndIf EndEvent Event OnMenuOpen("InventoryMenu") Int n = PendingSpells.GetSize() While n > 0 n = n - 1 Spell s = (PendingSpells.GetAt(n) as Spell) If PlayerRef.HasSpell(s) PendingSpells.RemoveAddedForm(s) EndIf EndWhile EndEvent Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference) Book b = (akBaseObject as Book) If b Spell s = b.GetSpell() If s If PendingSpells.HasForm(s) Int Temp = CurrentLearning.GetValueInt() If Temp < MaximumLearning.GetValueInt() CurrentLearning.SetValueInt(Temp + 1) PendingSpells.RemoveAddedForm(s) Else Debug.Notification("This Spell Cant be learned") PlayerRef.RemoveSpell(s) PlayerRef.AddItem(b, 1, true) ; the book has been consumed, so need to re-add EndIf EndIf EndIf EndIf EndEvent The logic here is that if player ever gains a spellbook with a spell he does not know yet, that spell goes into PendingSpells formlist. Anytime player accesses inventory, the PendingSpells list is checked to see if player potentially learned any spells on that list via alternate means. Then if player attempts to read a book and spell is on pending list, a successful learn removes the spell from list, and failed one removes spell and restores book in inventory. 1 Link to comment Share on other sites More sharing options...
WickedGoblin Posted May 4 Author Share Posted May 4 13 hours ago, scorrp10 said: What exactly does this script attach to? My assumption it is to Player Alias in the owning quest. Is the quest running? Are the properties loaded in the 'Properties' page with their corresponding forms? I would enable Papyrus logging, and add a Debug.Trace statement at the beginning of your function to make sure that is is indeed being called. I also assume that your CurrentLearning and MaximumLearning GVs are initialized somewhere to proper values. Now, to the actual logic of your code: when a player reads a book that teaches a spell, the book is consumed and the spell is added to the player. This is done in-engine, which is much faster than papyrus, which means that by the time this event handler gets called, the spell potentially was already added to the player. Meaning that '!PlayerRef.HasSpell(s)' clause is going to fail since by that time, player already has the spell. I suggest you add a clause that verifies it and do a Debug.Trace If PlayerRef.HasSpell(s) Debug.Trace(Self + "Player already has spell " + s) EndIf What can you do: Normal books in the world, when activated, open up for you to read, and from there you can choose to take the book. But spell books are added to your inventory, and you need to use a book from inventory to learn the spell. In other words, before a spell book can be read, it has to be added to your inventory. Thus, what you can do: First, in your mod, you create an empty FormList. Then, your script: Scriptname LimitedSpellLearningScript extends ReferenceAlias GlobalVariable Property MaximumLearning Auto GlobalVariable Property CurrentLearning Auto FormList Property PendingSpells Auto Actor Property PlayerRef Auto Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) Book b = (akBaseItem as Book) If b Spell s = b.GetSpell() If s If !PlayerRef.HasSpell(s) && !PendingSpells.HasForm(s) PendingSpells.AddForm(s) EndIf EndIf EndIf EndEvent Event OnMenuOpen("InventoryMenu") Int n = PendingSpells.GetSize() While n > 0 n = n - 1 Spell s = (PendingSpells.GetAt(n) as Spell) If PlayerRef.HasSpell(s) PendingSpells.RemoveAddedForm(s) EndIf EndWhile EndEvent Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference) Book b = (akBaseObject as Book) If b Spell s = b.GetSpell() If s If PendingSpells.HasForm(s) Int Temp = CurrentLearning.GetValueInt() If Temp < MaximumLearning.GetValueInt() CurrentLearning.SetValueInt(Temp + 1) PendingSpells.RemoveAddedForm(s) Else Debug.Notification("This Spell Cant be learned") PlayerRef.RemoveSpell(s) PlayerRef.AddItem(b, 1, true) ; the book has been consumed, so need to re-add EndIf EndIf EndIf EndIf EndEvent The logic here is that if player ever gains a spellbook with a spell he does not know yet, that spell goes into PendingSpells formlist. Anytime player accesses inventory, the PendingSpells list is checked to see if player potentially learned any spells on that list via alternate means. Then if player attempts to read a book and spell is on pending list, a successful learn removes the spell from list, and failed one removes spell and restores book in inventory. It works now!! Thank you for answer!! Link to comment Share on other sites More sharing options...
Recommended Posts