/* start README
//==========================\\
|| TEMPORARY NO RETURN ITEM ||
\\==========================//
Author: Orithan
ZC Version: 2.55
This pair of scripts work in tandem allow the quest maker to drop an item that temporarily does not return once collected, like the fixed pot drops in A Link to the Past and Ocarina of Time. The items respawn when you F6 -> Continue, Load the quest file or change to a DMap with a different level number.
Two scripts are used for this:
A Combodata script that spawns the item.
A Generic script that stores the No Return flags, which is reset whenever needed.
/--------------------\
| SETUP INSTRUCTIONS |
\--------------------/
1) Enable the "Combos run Scripts on Layer #" checkboxes from ZScript -> Quest Script Settings, under the "Script" tab. You will probably want to enable them for at least Layers 0, 1 and 2.
2) Import the scripts or add them to your script file, set ITEMSPR_MISC_TEMPNORETURN_ID to an unused itemsprite->Misc[] index and compile.
3) Assign the scripts in the Assign Compiled Scripts window, either automatically by clicking the "Smart Assign" option on the compile success screen or by manually assigning them. If you manually assign them, TempNoReturnItemCombo can be found under the Combodata tab, TempNoReturnItemGeneric can be found under the Generic tab."
4) Go into Quest -> Init Data and navigate to the GenScript tab. Click on "TempNoReturnItemGeneric" in the list and click on the "Edit" button. Check the "Run from Start" box and nothing else - The script handles the rest for you.
5) To make the item spawn, make a combo and assign it the "TempNoReturnItemCombo" script under the scripts tab. Set the ItemID and Mode (click on the ? button if you want more information). The item will spawn when that combo is revealed on the screen, be placed directly or if another combo changes to show it via slashing a bush combo or whatever. Do this for any items you wish to spawn.
6) Enjoy!
/-------\
| NOTES |
\-------/
Combodata scripts do not function on FFCs, therefore this script does not work on FFCs.
This will not work on Screen 80 and up due to the way the script stores combo/screen/map coordinates - Functionality on those screens is disabled due to them exceeding the memory allocated to screens in the script. This was set up this way because these screens are unlikely to be relevant given how rarely these screens are visited in a quest and how unlikely you'd use this script on them.
A limit of 214748 items can be memorized by this script but this limit is unlikely to be relevant unless you spawn excessive amounts of items using this script.
end README */
//#include "std.zh"
namespace TempNoReturnItem
{
//start SETTINGS
CONFIG ITEMSPR_MISC_TEMPNORETURN_ID = 31; //Set this to an unused index.
//end SETTINGS
//start SCRIPTS
@Author("Orithan Fox"),
@InitDHelp0("ID of the item to be dropped."),
@InitDHelp1("How the dropped item operates. Leave at 0 for default dropped item behaviour (reccomended for if this combo is revealed by slashing stuff like pots, bushes, etc), set to 1 to make it be collectable immeidately and not time out (reccomended for if this combo is placed directly onto the screen), any other value drops the item on the screen immediately but cannot be picked up with any weapons.")
//Set this combo script onto any combo that you wish to drop a set item
combodata script TempNoReturnItemCombo
{
void run(int ItemID, int Mode)
{
/*
The conditions to spawn the item are:
The Generic script is running
There is no index in the data array that corresponds to the combo's position on the screen on the map in the game world.
*/
genericdata gd = Game->LoadGenericData(Game->GetGenericScript("TempNoReturnItemGeneric"));
unless(Game->GetCurScreen() < 0x80 && gd->Running && !FindValue(gd, ReturnValue(this->Pos)))
Quit();
itemsprite drop = CreateItemAt(ItemID, this->X, this->Y);
drop->Misc[ITEMSPR_MISC_TEMPNORETURN_ID] = ReturnValue(this->Pos);
drop->Pickup |= (Mode == 0 ? IP_TIMEOUT : (Mode == 1 ? IP_ALWAYSGRAB : 0));
}
//Searches the Generic Script's data array for the given value.
bool FindValue(genericdata gd, long value)
{
for(int index = 0; index < gd->DataSize; ++index)
{
//Correct value found, return true
if(gd->Data[index] == value)
return true;
}
return false;
}
}
//This generic script passively runs throughout the quest and resets upon change of level and on continue.
@Author("Orithan Fox")
generic script TempNoReturnItemGeneric
{
void run()
{
//Automatically set up the relevant reload states and event listens.
this->ReloadState[GENSCR_ST_RELOAD] = true;
this->ReloadState[GENSCR_ST_CONTINUE] = true;
this->ReloadState[GENSCR_ST_CHANGE_LEVEL] = true;
this->EventListen[GENSCR_EVENT_COLLECT_ITEM] = true;
this->DataSize = 0;
while(true)
{
//Wait until an item that is flagged by the system is picked up.
WaitEvent();
unless(Game->EventData[GENEV_ITEMCOL_TYPE] != GENEVT_ICTYPE_RANGED_DRAG && <itemsprite>(Game->EventData[GENEV_ITEMCOL_ITEMPTR])->Misc[ITEMSPR_MISC_TEMPNORETURN_ID] > 0)
continue;
//Add it to the array
++this->DataSize;
this->Data[this->DataSize-1] = <itemsprite>(Game->EventData[GENEV_ITEMCOL_ITEMPTR])->Misc[ITEMSPR_MISC_TEMPNORETURN_ID];
}
}
}
//end SCRIPTS
//start FUNCTIONS
//Returns the appropariate grid index value using just the position of the combo on the current screen and map
long ReturnValue(int pos)
{
return ReturnValue(pos, Game->GetCurScreen(), Game->GetCurMap());
}
//Returns the appropriate grid index value by combining a combo, screen and map reference.
long ReturnValue(int combo_id, int screen_id, int map_id)
{
return (map_id*1L << 15) | (screen_id*1L << 8) | combo_id*1L;
}
//These are included for debugging purposes and for the user to read the values stored in the Generic Script's data array.
//Returns the combo portion of the grid index value
long ReturnCombo(long index)
{
return (index & 0xFFL);
}
//Returns the screen portion of the grid index value
long ReturnScreen(long index)
{
return ((index >> 8) & 0x7FL);
}
//Returns the map portion of the grid index value
long ReturnMap(long index)
{
return (index >> 15);
}
//end FUNCTIONS
}