[WIP] Need help with Ingredient picker script

Post » Sun Aug 09, 2009 1:29 pm

Hello,

I made a house mod for myself, with a chest that can hold many... maaany ingredients, for I like the roleplay part of the game so much that all these years I have played only one char, maxed at almost every skills.
With some of all the ingredients available in the game inside the container, It is such a pain to hover the mouse over each when trying to pick them for a mixture, just to remember the magical properties, that I have decided a couple of weeks ago, to code a script with:

- The intention of the script:
Upon activation of the chest, a menu that shows the intended magical property, which after selected, automatically gets all the ingredients that match to the player inventory.

- Limitations:
First I was very frustrated for not being able to simply do a loop through all the contents of the chest and find some property or method that shows their magical properties, that'd be neat, so all i had left was to tell the script to recognize each ingredient available in the game, excluding ingredients created by external mods, to keep it clean. Ok, that shouldn't be hard, but would greatly increase the time to do this. So i've even created a program to generate the scripts for me given a list of the ingredients that I've downloaded, and then revised.
The next limitation, the output was so big, TESCS only accepts like 800 lines in each script, and I believe that is what is causing me the problem I am to bored to try and figure out myself already: I had to break up the script in smaller files and do that startscript thing.

- Please help me who can:
When I test the script in the game, the menu shows up ok in the first time, on rare occasions it gets the ingredients, and on others, it closes, and in the next activation doesn't open again....... it is really hard to explain, thats why ...:
I've uploaded the script to the below URL, and would like for someone who likes the idea behind the script, try and help me debug it to see where I am missing. I believe it has to do with some other limitation of TESCS that I am not being able to see.
Please note that you may see a missing endif or something like that, because I was doing code in an external editor, and maybe forgot to sync with something I was doing directly in the TESCS, but don't take that as the cause of the problem, because it ain't.

http://www.easy-share.com/1910244681/mwIngredSrc.zip (10Kb, really small file, it is all text after all)

This should be a weekend's work tops, and took me some more than that, until I've kinda shove it away for some time, and decided to ask for help here. I was intending to release it as a free work after completion anyways, maybe someone even have something similar anyways, so I don't really care if you figure the problem out and use it for you, just share with me please :)

Thanks !
User avatar
N Only WhiTe girl
 
Posts: 3353
Joined: Mon Oct 30, 2006 2:30 pm

Post » Sun Aug 09, 2009 9:03 am

The download link apperars to be 0 size to me, maybe try reuploading?
User avatar
Jeff Turner
 
Posts: 3458
Joined: Tue Sep 04, 2007 5:35 pm

Post » Sun Aug 09, 2009 2:54 am

The download link apperars to be 0 size to me, maybe try reuploading?


That is correct, the zip file is 10Kb, so it shows with 0 Mb. The download is working, I just tested.

Thanks !
User avatar
A Lo RIkIton'ton
 
Posts: 3404
Joined: Tue Aug 21, 2007 7:22 pm

Post » Sun Aug 09, 2009 9:05 am

@abot: The file exists. It is just so small compared to what such services are used to accommodating that it shows up as zero MB.

@Ser: I do not recognize the file type so I have not had a look at your work to see what the difficulty is. I have written similar scripts for my own ingredient retriever and your approach is sound. I had a master menu that then called seven or eight sub-menus representing different types of potion effects (cures, restores, fortifies, etc.). It is not too difficult (albeit tedious) to transfer the appropriate ingredients to the player's inventory once the specific potion has been chosen.

When I test the script in the game, the menu shows up ok in the first time, on rare occasions it gets the ingredients, and on others, it closes, and in the next activation doesn't open again....... it is really hard to explain, thats why

Since you are using StartScript to call the satellite scripts you may not be closing them properly, or in a timely manner, or after resetting all of the variables to their initial states for the next time the script is started. I had to introduce delays for when starting and stopping my scripts before they would work together properly.

Since you are using Morrowind scripting rather than an external program that could check the ingredient's properties directly you will have to associate specific effects with each ingredient. This will make your (and my) mod incompatible with mods that add new ingredients and/or alter existing ingredients, and limit its appeal to the community at large.
User avatar
oliver klosoff
 
Posts: 3436
Joined: Sun Nov 25, 2007 1:02 am

Post » Sun Aug 09, 2009 12:00 am

Hello,

Cyran0:
- About the file types, they are plain text, I use notepad++ to edit it and it doesn't enforce an extension, so i forgot to put the ".txt" in the end of it's name. You could just rename it or tell windows notepad to open it.
- What you mentioned is exactly what I tried to say I had to do. I think our files are pretty much the same, or very similar, let me give you an example of the file that is associated with the chest below:
- About all the other things you said, I agree with them all, thanks for the help. It makes sense what you said about the delay, that could be actually the cause of the problem, particularly if the game operates in any kind of multithreaded manner.

- This is the main script file:
begin _sw_sh_ingredChestshort stateshort buttonif ( OnActivate == 1 )	MessageBox "Choose the effect, and the ingredients you shall have", "Just open the Chest !", "No thanks, just Close it.", "Positive Effects", "Negative Effects"	set state to 1	endifif ( state == 1 )	set button to GetButtonPressed	if ( button == -1 )		return	elseif ( button == 0 )		set state to 100	elseif ( button == 1 )		return	elseif ( button == 2 )		MessageBox "Positive Effects", "Cancel", "Cure Blight ... Feather", "Fire Shield ... Fortify Luck", "Fortify Max Magicka ... Invisibility", "Levitate ... Resist Fire", "Resist Frost ... Restore Fatigue", "Restore Health ... Restore Willpower", "Spell Absorption ... Water Walking"		set state to 2	elseif ( button == 3 )		MessageBox "Negative Effects", "Cancel", "Blind ... Drain Alteration", "Drain Endurance ... Drain Speed", "Drain Strength and Weaknesses"		set state to 3	endif;Positive Effectselseif ( state == 2 )  	set button to GetButtonPressed	if ( button == -1 )		return	elseif ( button == 0 )		set state to 100	elseif ( button == 1 )		startscript _sw_sh_menu_p1			return	elseif ( button == 2 )		startscript _sw_sh_menu_p2		return	elseif ( button == 3 )		startscript _sw_sh_menu_p3		return	elseif ( button == 4 )		startscript _sw_sh_menu_p4		return	elseif ( button == 5 )		startscript _sw_sh_menu_p5		return	elseif ( button == 6 )		startscript _sw_sh_menu_p6		return			elseif ( button == 7 )		startscript _sw_sh_menu_p7		return					endif;Negative Effectselseif ( state == 3 )	set button to GetButtonPressed	if ( button == 0 )		set state to 100	elseif ( button == 1 )		startscript _sw_sh_menu_pn1		return			elseif ( button == 2 )		startscript _sw_sh_menu_pn2		return	elseif ( button == 3 )		startscript _sw_sh_menu_pn3		return			endif	elseif ( state == 100 )	Activate	set state to 0endifEnd


- This is one of the called files (some obvious code replaced by "..." because it is too big):

Begin _sw_sh_menu_p1short stateshort buttonshort ingredCountif ( state == 0 )	MessageBox "Cure Blight ... Feather", "Cancel", "Cure Blight Disease", "Cure Paralyzation", "Cure Poison", "Detect Animal", "Detect Enchantment", "Detect Key", "Dispel", "Feather"	set state to 20elseif ( state == 20 )	set button to GetButtonPressed	if ( button == 0 )		set state to 100	; Cure Blight Disease	elseif ( button == 1 )		set ingredCount to ( GetItemCount, "ingred_ash_salts_01" )		while ( ingredCount > 0 )			set ingredCount to ( ingredCount - 1 )			player->AddItem, "ingred_ash_salts_01", 1			RemoveItem, "ingred_ash_salts_01", 1		endwhile		set ingredCount to ( GetItemCount, "ingred_scrib_jelly_02" )		while ( ingredCount > 0 )			set ingredCount to ( ingredCount - 1 )			player->AddItem, "ingred_scrib_jelly_02", 1			RemoveItem, "ingred_scrib_jelly_02", 1		endwhile		set ingredCount to ( GetItemCount, "ingred_scrib_jelly_01" )		while ( ingredCount > 0 )			set ingredCount to ( ingredCount - 1 )			player->AddItem, "ingred_scrib_jelly_01", 1			RemoveItem, "ingred_scrib_jelly_01", 1		endwhile	;Cure Paralyzation	elseif ( button == 2 )		set ingredCount to ( GetItemCount, "ingred_corkbulb_root_01" )		while ( ingredCount > 0 )			set ingredCount to ( ingredCount - 1 )			player->AddItem, "ingred_corkbulb_root_01", 1			RemoveItem, "ingred_corkbulb_root_01", 1		endwhile		set ingredCount to ( GetItemCount, "ingred_scamp_skin_01" )		while ( ingredCount > 0 )			set ingredCount to ( ingredCount - 1 )			player->AddItem, "ingred_scamp_skin_01", 1			RemoveItem, "ingred_scamp_skin_01", 1		endwhile		set ingredCount to ( GetItemCount, "ingred_netch_leather_01" )		while ( ingredCount > 0 )			set ingredCount to ( ingredCount - 1 )			player->AddItem, "ingred_netch_leather_01", 1			RemoveItem, "ingred_netch_leather_01", 1		endwhile		set ingredCount to ( GetItemCount, "ingred_willow_anther_01" )		while ( ingredCount > 0 )			set ingredCount to ( ingredCount - 1 )			player->AddItem, "ingred_willow_anther_01", 1			RemoveItem, "ingred_willow_anther_01", 1		endwhile	;Cure Poison	elseif ( button == 3 )		...	;Detect Animal	elseif ( button == 4 )		...	;Detect Enchantment	elseif ( button == 5 )		...	;Detect Key	elseif ( button == 6 )		...	;Dispel	elseif ( button == 7 )		...	;Feather	elseif ( button == 8 )		...			endif	endifEnd

User avatar
Ashley Clifft
 
Posts: 3468
Joined: Thu Jul 26, 2007 5:56 am

Post » Sun Aug 09, 2009 6:23 am

In the script _sw_sh_menu_p1, I do not see that you are resetting state to 0 after the global script has retrieved appropriate ingredients. The next time the script _sw_sh_ingredChest called the global it will process from whatever value state was previously set (unless Morrowind is closed and the game restarted). That prevents the menu from being displayed in successive attempts. For that matter, I do not see that you stop the global scripts from running after they have served their purpose, but perhaps that is in part of the code that you did not post. At the same time as you use StopScript to terminate the script you can set state back to 0 for the next time the script is started.

Another potential issue is running a while loop under button == 1, etc. Presumably the while loop runs in a single frame, but sometimes problems are reported with how it processes. Since button == 1 will only be true for the one frame in which the player makes the choice it might be safer to create a new variable to manage the inventory that will not be frame-dependent. That is just a precaution. While is supposed to work as you are using it.

You can make _sw_sh_ingredChest run more efficiently if you were to reset state to zero after a menu choice is made and add a check for state just after the OnActivate check:

if ( state == 0 )   returnendif

Place the reset after the last of the elseifs in each block that checks for button and move all of the returns (except for when button == -1) to the end of that logical block:

   elseif ( button == 7 )      startscript _sw_sh_menu_p7   endif   set state to 0   return;Negative Effectselseif ( state == 3 )

User avatar
tiffany Royal
 
Posts: 3340
Joined: Mon Dec 25, 2006 1:48 pm

Post » Sun Aug 09, 2009 12:37 am

Hello,

Your observations make a lot of sense, but I wanted to fix and test before posting it, and finally did that yesterday.
What you said about the resetting state variable made me notice that I was wrong in assuming that everytime a "satellite" script ends the variable's values are destroyed and thus redeclared once you call it again.
My 2 mistakes were the lack of: a stopscript in the script file itself and resetting of state to 0, in all the script files. I was testing the use of stopscript already, but it wasn't working still because i was not resetting the variable. i knew I was missing something fairly simple, and I am so used to conventional programming that it passed right through me the intrincancies of scripting inside a "big loop for every frame". Besides, TESCS has so many flaws that I was affraid of being touching one of them. Turns out it behaved exactly how it should, and I was being unfair with the lil' ol' construction kit.

I didn't need to add a delay to the while loops tho, the game simply freezes while it is collecting like 600 ash yams, 800 trama roots, etc, seeming that it is waiting for the loop before running another frame, like it should. Later when I have the ballz i'll add a messagebox with some kinda of "wait..." message, like windows' hourglass :)

Thats exactly the kind of help I was expecting for, thank you very much Cyran0, it works now, and i'll reupload the fixed files later today in case someone ever needs something like this.
User avatar
Hannah Barnard
 
Posts: 3421
Joined: Fri Feb 09, 2007 9:42 am


Return to III - Morrowind