Trying to fix a bug with the Uvirith's Legacy Enchanting tom

Post » Sun May 06, 2012 9:50 pm

For those of you who have not played the Uvirith's Legacy mod, at a certain point during a quest in it, you get access to tomes that allow you to make spells and enchant items at a discount price. During one of my playthroughs in the mod, I discovered that when you try to use the tome to chant items over a certain expense, the tome works but then blocks any future attempts to use it. This happened when I tried to enchant an Extravagant Ring with a Cast on use enchantment that fortified speed 100 pts. for 10 seconds, which cost 50,000 gold. I've never been very good at solving problems with loops, but I'm guessing the tome somehow gets trapped in an infinite loop when you use it to make an expensive enchantment and never resets.

From what I gather, the enchanting tome works in the following way. When the PC activates the item, it creates an invisible creature that forces a greeting with the PC, allowing the PC to do the enchantment. Once you enchant an item, this creature is disabled and the script attached to the book uses an algorithm to refund you part of the cost, so the items is effectively enchanted at a discount. The scripts for the "Book" and the "Creature" are posted below. These tomes are Suporstar's creations, not mine; I'm just trying to figure out how to fix them.

Book
Begin Enchant_Tome_Book
;restores some of the player's gold used in the Enchanting Tome's service

short Phase
short Button
short OnPCEquip
float Timer
Long CurrentGold
Long StartGold
short ETomeActivated

if ( GetJournalIndex HT_Spellbook < 70 )
If ( GetDisabled == 0 )
disable
Endif
endif

if ( GetJournalIndex HT_Spellbook >= 70 )
If ( GetDisabled == 1 )
enable
Endif
endif

if ( OnActivate == 1 )
If ( Phase == 0 )
If ( ETomeActivated==0)
PlaceAtPC Enchant_Tome 1 256 1
set Phase to 4
Set StartGold to player-> GetItemCount "Gold_001"
Player->AddItem Gold_001 30000
Set ETomeActivated to 1
Else
Set Phase to 1
Endif
Endif
Elseif(Phase==0)
Return
Elseif(Phase==3)
If(Timer < 5)
Set Timer to Timer + getSecondsPassed
Else
Set EnchantUsed to 1
Endif
Elseif (Phase == 4)
Set Phase to 5
Elseif (Phase == 5)
If(menuMode==0)
Set CurrentGold to player-> GetItemCount "Gold_001"
If(CurrentGold > StartGold + 2048)
Player->RemoveItem Gold_001 2048
ElseIf(CurrentGold > StartGold + 1024)
Player->RemoveItem Gold_001 1024
ElseIf(CurrentGold > StartGold + 512)
Player->RemoveItem Gold_001 512
ElseIf(CurrentGold > StartGold + 248)
Player->RemoveItem Gold_001 248
ElseIf(CurrentGold > StartGold + 124)
Player->RemoveItem Gold_001 124
ElseIf(CurrentGold > StartGold + 64)
Player->RemoveItem Gold_001 64
ElseIf(CurrentGold > StartGold + 32)
Player->RemoveItem Gold_001 32
ElseIf(CurrentGold > StartGold + 16)
Player->RemoveItem Gold_001 16
ElseIf(CurrentGold > StartGold + 8)
Player->RemoveItem Gold_001 8
ElseIf(CurrentGold > StartGold + 4)
Player->RemoveItem Gold_001 4
ElseIf(CurrentGold > StartGold + 2)
Player->RemoveItem Gold_001 2
ElseIf(CurrentGold > StartGold)
Player->RemoveItem Gold_001 1
ElseIf(CurrentGold==StartGold)
Set Phase to 0
Endif
Endif
Endif

If(Phase==1)
; MessageBox, "What do you want to do with the tome?" "Pick it up", "Study it"
; set Phase to 2
;elseif ( Phase == 2 )
; set button to GetButtonPressed
; if ( button == 0)
; set Phase to 0
; MessageBox "Sorry, fooled ya, can't pick it up yet."
; Disable
; set Phase to 3
; elseif ( button == 1 )
PlaceAtPC Enchant_Tome 1 256 1
set Phase to 4
Set StartGold to player-> GetItemCount "Gold_001"
Player->AddItem Gold_001 30000
; endif
endif

End Enchant_Tome_Book



Creature

Begin Enchant_Tome_Creature
;attached to creature version of Enchanting Tome
short DoOnce

If ( DoOnce == 0 )
ForceGreeting
Disable
Set DoOnce to 1
Endif

if ( EnchantUsed == 1 )
Set EnchantUsed to 0
Disable
Endif

End Enchant_Tome_Creature

I have very minimal experience scripting and in any event, was never adept and sifting my way through if/else loops to find errors. If anyone with more experience is able to help me figure out what the problem is so I can forward it to Gaius Atrius (who is developing a patch for UL) I would greatly appreciate it. Thanks so much!
User avatar
x a million...
 
Posts: 3464
Joined: Tue Jun 13, 2006 2:59 pm

Post » Mon May 07, 2012 5:01 am

I'd try replacing
ElseIf(CurrentGold > StartGold + 248)Player->RemoveItem Gold_001 248ElseIf(CurrentGold > StartGold + 124)Player->RemoveItem Gold_001 124
with
ElseIf(CurrentGold >= StartGold + 256)Player->RemoveItem Gold_001 256ElseIf(CurrentGold >= StartGold + 128)Player->RemoveItem Gold_001 128
and every other
CurrentGold > StartGold
with
CurrentGold >= StartGold
first, then eventually cleaning a little the whole script, e. g.
Begin Enchant_Tome_Book; restores some of the Player's gold used in the Enchanting Tome's serviceshort Phaseshort Buttonshort OnPCEquipfloat Timerlong CurrentGoldlong StartGoldshort ETomeActivatedif ( GetDisabled )	if ( GetJournalIndex HT_Spellbook >= 70 )		Enable	endifelseif ( GetJournalIndex HT_Spellbook < 70 )	Disableendifif ( OnActivate )	if ( Phase == 0 )		if ( ETomeActivated )			set Phase to 1		else			PlaceAtPC "Enchant_Tome" 1 256 1			set Phase to 4			set StartGold to Player->GetItemCount "Gold_001"			Player->AddItem "Gold_001" 30000			set ETomeActivated to 1		endif	endif	returnendif	if ( Phase == 0 )	returnelseif ( Phase == 3 )	if ( Timer < 5 )		set Timer to ( Timer + GetSecondsPassed )	else		set Timer to 0		set EnchantUsed to 1	endif	returnelseif ( Phase == 4 )	set Phase to 5	returnelseif ( Phase == 5 )	if ( MenuMode == 0 )		set CurrentGold to ( Player->GetItemCount "Gold_001" )		set CurrentGold to ( CurrentGold - StartGold )		if ( CurrentGold >= 2048 )			Player->RemoveItem "Gold_001" 2048		elseif ( CurrentGold >= 1024 )			Player->RemoveItem "Gold_001" 1024		elseif ( CurrentGold >= 512 )			Player->RemoveItem "Gold_001" 512		elseif ( CurrentGold >= 256 )			Player->RemoveItem "Gold_001" 256		elseif ( CurrentGold >= 128 )			Player->RemoveItem "Gold_001" 128		elseif ( CurrentGold >= 64 )			Player->RemoveItem "Gold_001" 64		elseif ( CurrentGold >= 32 )			Player->RemoveItem "Gold_001" 32		elseif ( CurrentGold >= 16 )			Player->RemoveItem "Gold_001" 16		elseif ( CurrentGold >= 8 )			Player->RemoveItem "Gold_001" 8		elseif ( CurrentGold >= 4 )			Player->RemoveItem "Gold_001" 4		elseif ( CurrentGold >= 2 )			Player->RemoveItem "Gold_001" 2		elseif ( CurrentGold > 0 )			Player->RemoveItem "Gold_001" 1		else			set Phase to 0		endif	endif	returnendifif ( Phase == 1 )	; MessageBox, "What do you want to do with the tome?" "Pick it up", "Study it"	; set Phase to 2	; elseif ( Phase == 2 )	; set button to GetButtonPressed	; if ( button == 0)	; set Phase to 0	; MessageBox "Sorry, fooled ya, can't pick it up yet."	; Disable	; set Phase to 3	; elseif ( button == 1 )	PlaceAtPC "Enchant_Tome" 1 256 1	set Phase to 4	set StartGold to ( Player->GetItemCount "Gold_001" )	Player->AddItem "Gold_001" 30000	; endifendifEnd Enchant_Tome_Book
User avatar
He got the
 
Posts: 3399
Joined: Sat Nov 17, 2007 12:19 pm

Post » Mon May 07, 2012 12:52 am

Abot my friend, you are a genius. The script worked perfectly. I tried both making several small enchantments, and a few large ones, and the book did not freeze up on me again. The only thing I noticed differently about how the script works is that the forced "greeting" with the enchanting tome doesn't happen quite as fast, but that's a negligible discrepancy.

Just our of curiosity, was I correct in my suspicion that the book was getting trapped in an infinite loop? If so, how did your changes solve the problem? I'm always trying to learn a little bit more about scripting :P
User avatar
Mimi BC
 
Posts: 3282
Joined: Sat Oct 07, 2006 10:30 pm

Post » Sun May 06, 2012 10:48 pm

Just our of curiosity, was I correct in my suspicion that the book was getting trapped in an infinite loop?
probably, yes, the condition to stop was not satisfied. Probably a
Messagebox "CurrentGold = %g" CurrentGold
line could have been useful to find where the looping was exactly
If so, how did your changes solve the problem? I'm always trying to learn a little bit more about scripting :P
if you look at the logic, to cover every possible value the quantity removed was halved each pass. I've replaced for instance 248 (probably a typo) with 256=512/2.
Another example, this time not binary but decimal and doing all work in a single frame
begin AddRandomGoldScriptlong goldset gold to Random 10001while ( gold >= 1000 )	player->AddItem "gold_001" 1000 	set gold to ( gold - 1000 )endwhilewhile ( gold >= 100 )	player->AddItem "gold_001" 100 	set gold to ( gold - 100 )endwhilewhile ( gold >= 10 )	player->AddItem "gold_001" 10 	set gold to ( gold - 10 )endwhilewhile ( gold > 0 )	player->AddItem "gold_001" 1	set gold to ( gold - 1 )endwhilestopscript AddRandomGoldScriptend
User avatar
rolanda h
 
Posts: 3314
Joined: Tue Mar 27, 2007 9:09 pm


Return to III - Morrowind