ItemHandling.zh
SubmittedDecember 14, 2016
ZoriaRPG
Grayswandir originally created (most of) these functions for me, to use in conjunction with the Generic FFC Trigger script. As I rely on them for many of my scripts, when handling collision between LWeapons, and FFCs, and for other detection of item usage, I'm turning them into a library set, so that I need not duplicate them in future script postings.
If your compiler gives you an error, that these functions already exist, then you may be using one of my other scripts, that calls to, and includes them. If so, you can either remove them from other scripts, or simply discard this library as a separate file.
The library also includes item handling functions by SUCESSOR, and some ffc scripts, that I believe were made by MoscowModder, and Saffith.
Import into your main script file, somewhere after the line:
import "std.zh"...with this command:
import "ItemHandling.zh"Be sure that this import occurs before anything that calls to these functions, and global variables & constants.
Future updates will retain all extant functions, but may modify them.
I plan to correct this in a future update.
//import "std.zh"
///////////////////////////////////////
/// ItemHandling.zh ///
/// v6.7, originally by grayswandir ///
/// 23rd September, 2014 ///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// This is a global function set for handling item interaction. ///
/// The original authors of this function set are grayswandir, who provided it to me, for use in TGC, ///
/// and SUCCESSOR, who contributed item use functions. I use it for so many components, that in sharing ///
/// other scripts, I may as well make it a header, to provide the functionality needed for many FFC scripts ///
/// that I make available to others, operable without duplicating these functions in every instance. ///
/// I may expand on it at some future point. ///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////
/// Global Constants ///
////////////////////////
const int MISC_LWEAPON_ITEM = 0; // The id of the item used to create an lweapon.
////////////////////////
/// Global Variables ///
////////////////////////
int LastItemUsed = 0; // The item id of the last item Link has used.
bool itemActivate = false;
////////////////////////
/// Global Functions ///
////////////////////////
void UpdateLWeapons() { //// Updates every LWeapon on screen. Call in the active script.
for (int i = 1; i NumLWeapons(); i++) {
UpdateLWeapon(Screen->LoadLWeapon(i));
}
}
void UpdateLWeapon(lweapon lw) { //// Update a given LWeapon.
// If the weapon does not have it's source item marked, mark it as being created by the last item that Link has used.
if (lw->Misc[MISC_LWEAPON_ITEM] == 0) {
lw->Misc[MISC_LWEAPON_ITEM] = LastItemUsed;
}
}
/////////////////////////////////////////////////////////////////////////
/// Updates the LastItemUsed variable to our best guess at what was ///
/// most recently used. This should be called at the end of the loop, ///
/// right before Waitdraw or Waitframe, because the item marked in ///
/// LastItemUsed isn't actually used until after the Waitdraw or ///
/// Waitframe. ///
/////////////////////////////////////////////////////////////////////////
void UpdateLastItem() {
// Since we don't know which button has priority if both are pressed
// at once, cancel the B button press if A has also been pressed
// this frame.
if (Link->PressA && Link->PressB) {
Link->PressB = false;
}
// If Link is currently in an action where he obviously can't use items, then ignore his button presses.
if (Link->Action != LA_NONE &&
Link->Action != LA_WALKING) {
return;
}
// Check which button is being pressed, if any. Also check for the appopriate Jinx.
if (Link->PressA && Link->SwordJinx == 0) {
LastItemUsed = GetEquipmentA();
}
else if (Link->PressB && Link->ItemJinx == 0) {
LastItemUsed = GetEquipmentB();
}
}
bool IsFromItem(lweapon lw, int itemNumber) { //// Return true if the given lweapon is from the given item.
return lw->Misc[MISC_LWEAPON_ITEM] == itemNumber;
}
bool IsFromItemClass(lweapon lw, int itemClass) { //// Return true if the given lweapon is from the given item class.
itemdata data = Game->LoadItemData(lw->Misc[MISC_LWEAPON_ITEM]);
return data->Family == itemClass;
}
//Changes B to specified item
void SetItemB(int it){
if (Link->Item[it] == true) {
//save current item to mark where we started
int storeB = GetEquipmentB();
//move to next item before checking conditions
do Link->SelectBWeapon(DIR_RIGHT);
//if Item B is the right item or the item we started at stop
while(GetEquipmentB() != it && storeB != GetEquipmentB())
//added check to confirm
//return GetEquipmentB() == it;
}
}
void UseItemOnB(int input){
int EquipB = GetEquipmentB();
SetItemB(input);
Link->InputB = true;
Waitframe();
SetItemB(EquipB);
itemActivate = false;
}
bool SetCheckItemB(int it){
SetItemB(it);
return GetEquipmentB() == it;
}
//Change A to specified item
void SetItemA(int it){
if (Link->Item[it] == true) {
//save current item to mark where we started
int storeA = GetEquipmentA();
//move to next item before checking conditions
do Link->SelectAWeapon(DIR_RIGHT);
//stop if Item A is the right item or the item we started at
while(GetEquipmentA() != it && storeA != GetEquipmentA())
//added check to confirm
//return GetEquipmentA() == it;
}
}
void UseItemOnA(int input){
int EquipA = GetEquipmentA();
SetItemA(input);
Link->InputA = true;
Waitframe();
SetItemA(EquipA);
}
bool SetCheckItemA(int it){
SetItemA(it);
return GetEquipmentA() == it;
}
int buttonItems[11]={0,0,0,0,0,0,0,0,0,0,0};
const int BUTTON_A = 0;
const int BUTTON_B = 1;
const int EXTRA_BTN_L = 2;
const int EXTRA_BTN_R = 3;
const int EXTRA_BTN_EX1 = 4;
const int EXTRA_BTN_EX2 = 5;
const int EXTRA_BTN_EX3 = 6;
const int EXTRA_BTN_EX4 = 7;
const int STORED_ITEM_A = 8;
const int STORED_ITEM_B = 9;
const int STORED_ITEM_EXTRA = 10;
// Functions to keep items in array current for A and B items.
void updateButtonA(){
buttonItems[BUTTON_A] = GetEquipmentA();
}
void updateButtonB(){
buttonItems[BUTTON_A] = GetEquipmentB();
}
//Functions to store items for each button.
void storeItemA(int itemStored){
buttonItems[STORED_ITEM_A] = itemStored;
}
void storeItemB(int itemStored){
buttonItems[STORED_ITEM_B] = itemStored;
}
void storeItemL(int itemStored){
buttonItems[EXTRA_BTN_L] = itemStored;
}
void storeItemR(int itemStored){
buttonItems[EXTRA_BTN_R] = itemStored;
}
void storeItemEx1(int itemStored){
buttonItems[EXTRA_BTN_EX1] = itemStored;
}
void storeItemEx2(int itemStored){
buttonItems[EXTRA_BTN_EX2] = itemStored;
}
void storeItemEx3(int itemStored){
buttonItems[EXTRA_BTN_EX3] = itemStored;
}
void storeItemEx4(int itemStored){
buttonItems[EXTRA_BTN_EX4] = itemStored;
}
void swapItemsAB(){
buttonItems[STORED_ITEM_A] = GetEquipmentA();
buttonItems[STORED_ITEM_B] = GetEquipmentB();
SetItemA(buttonItems[STORED_ITEM_B]);
SetItemB(buttonItems[STORED_ITEM_A]);
}
//Use items.
void useItem(int itemToUse){
buttonItems[STORED_ITEM_EXTRA] = GetEquipmentB();
SetItemB(itemToUse);
Link->InputB = true;
Waitframe();
SetItemB(buttonItems[STORED_ITEM_EXTRA]);
}
void useButtonA() {
buttonItems[STORED_ITEM_B] = GetEquipmentB();
SetItemB(buttonItems[BUTTON_A]);
Link->InputB = true;
Waitframe();
SetItemB(buttonItems[STORED_ITEM_B]);
}
void useButtonB() {
buttonItems[STORED_ITEM_B] = GetEquipmentB();
SetItemB(buttonItems[BUTTON_B]);
Link->InputB = true;
Waitframe();
SetItemB(buttonItems[STORED_ITEM_B]);
}
void useButtonL() {
buttonItems[STORED_ITEM_B] = GetEquipmentB();
SetItemB(buttonItems[EXTRA_BTN_L]);
Link->InputB = true;
Waitframe();
SetItemB(buttonItems[STORED_ITEM_B]);
}
void useButtonR() {
buttonItems[STORED_ITEM_B] = GetEquipmentB();
SetItemB(buttonItems[EXTRA_BTN_R]);
Link->InputB = true;
Waitframe();
SetItemB(buttonItems[STORED_ITEM_B]);
}
void useButtonEx1() {
buttonItems[STORED_ITEM_B] = GetEquipmentB();
SetItemB(buttonItems[EXTRA_BTN_EX1]);
Link->InputB = true;
Waitframe();
SetItemB(buttonItems[STORED_ITEM_B]);
}
void useButtonEx2() {
buttonItems[STORED_ITEM_B] = GetEquipmentB();
SetItemB(buttonItems[EXTRA_BTN_EX2]);
Link->InputB = true;
Waitframe();
SetItemB(buttonItems[STORED_ITEM_B]);
}
void useButtonEx3() {
buttonItems[STORED_ITEM_B] = GetEquipmentB();
SetItemB(buttonItems[EXTRA_BTN_EX3]);
Link->InputB = true;
Waitframe();
SetItemB(buttonItems[STORED_ITEM_B]);
}
void useButtonEx4() {
buttonItems[STORED_ITEM_B] = GetEquipmentB();
SetItemB(buttonItems[EXTRA_BTN_EX4]);
Link->InputB = true;
Waitframe();
SetItemB(buttonItems[STORED_ITEM_B]);
}
//We need a PressR (set item to R), script.
void useR_Item(int itemToUse){
buttonItems[BUTTON_B] = GetEquipmentB();
SetItemB(itemToUse);
Link->InputB = true;
Waitframe();
SetItemB(buttonItems[BUTTON_B]);
}
bool lWeaponExists(int LType){
for (int i = Screen->NumLWeapons(); i > 0; i--){
lweapon e = Screen->LoadLWeapon(i);
if ( e->ID == LType ){
return true;
}
else {
return false;
}
}
}
ffc script useRItem{
void run(int input){
//store B
int EquipB = GetEquipmentB();
//set B to "R" item
SetItemB(input);
//tell game that B was pressed
Link->InputB = true;
//wait a frame so game triggers B
Waitframe();
//reset B
SetItemB(EquipB);
}
}
//Shouldn't this just be a function?
///////////////////////////
/// General Use Scripts ///
///////////////////////////
ffc script NoDrops {
void run() {
npc en;
while(true) {
for(int i=1; iNumNPCs(); i++)
{
en=Screen->LoadNPC(i);
if(en->ItemSet!=IS_NONE)
en->ItemSet=IS_NONE;
}
Waitframe();
}
}
}
ffc script removeDrops{
void run(){
while(true){
for(int i = 1; i NumItems(); i++){
item drop = Screen->LoadItem(i);
if(drop->Pickup & IP_TIMEOUT){
Remove(drop);
}
}
Waitframe();
}
}
}
item script playMessage{
void run(int message){
Screen->Message(message);
}
}
item script playSound{
void run(int soundEffect){
Game->PlaySound(soundEffect);
}
}
///Generic FFC Lweapon (or Item) Trigger, from grayswandir
//D0 Item to Trigger Event
//D1 Combo to Change (- Flags to Change)
//D2 COmbo to become (- Map & Screen to use to change flagged combos)
//D3 ???
//D4 Sound to Play
//D5 Message to Display.
//D6
//D7
////////////////
//// When hit by an LWeapon satisfying the condition, change
//// all combos on screen that match the condition to what
//// specifies.
////
//// : This is what kind of LWeapon will trigger the combo
//// change. If positive, it specifies the item number that will
//// trigger this (e.g. I_ARROW2 will make Silver Arrows trigger
//// this). If negative or 0, it specifies the item class that will
//// trigger this (e.g. -IC_ARROW will make any arrow trigger this).
////
//// : This is what combos that this trigger will change when
//// it is actually triggered. If positive, it specifies that all
//// combos on screen with the given Combo ID will be changed (e.g. a
//// 12 means change all instances of combo 12). If negative, it
//// specifies that all combos on screen with the given flag will be
//// changed (e.g. a -CF_SECRETS01 means to change all combos with the
//// Secret 1 flag on them).
////
//// : This is what the target combos are changed to. If
//// positive, it specifies a combo id to change them to. If negative,
//// it instead specifies a map and screen to grab combos from. The
//// format is "-MMMYXX", where MMM is the map number, Y is the
//// screen's Y position on that map (from 0 to 7), and XX is the
//// screen's X position on that map (from 0 to 15). Every target
//// combo is changed to whatever combo is at the same coordinates on
//// that screen.
////
//// : If positive, this causes this ffc to cancel
//// if the combo underneath the ffc every changes its Combo ID.
////
//// : If this is non-zero, it causes the given sound to be
//// played when the trigger occurs.
////
//// : If this is non-zero, it causes the given message to be
//// displayed when the trigger occurs.
ffc script GenericFFCTrigger {
void run(int trigger, int target, int result, int dieOnComboChange, int sound, int message) {
// Grab the combo id underneath us so we can tell when it changes.
int loc = ComboAt(CenterX(this), CenterY(this));
int underComboId = Screen->ComboD[loc];
// Interpret if it is negative.
int map;
int screen;
if (result > 0;
screen = ((result * -0.01 % 10) >> 0) * 16 + (-result % 100);
}
// Wait for something to happen.
bool waiting = true;
while (waiting) {
// If is set and the combo does change, terminate.
if (dieOnComboChange > 0 && Screen->ComboD[loc] != underComboId) {
return;
}
// Loop through all LWeapons on screen.
for (int i = 1; i NumLWeapons(); i++) {
lweapon lw = Screen->LoadLWeapon(i);
// If the LWeapon is touching us.
if (lw->CollDetection && Collision(this, lw)) {
// If is positive, test the lweapon for being the
// right item type.
if (trigger > 0) {
if (IsFromItem(lw, trigger)) {
waiting = false;
}
}
// If is negative, test the lweapon for being the
// right item class.
else {
if (IsFromItemClass(lw, -trigger)) {
waiting = false;
}
}
}
}
// Advance to next frame.
Waitframe();
}
// If we reach this point, it means that we've successfully been
// hit by an acceptable LWeapon.
// Now loop through every combo on screen looking for combos
// matching .
for (loc = 0; loc < 176; loc++) {
bool match = false;
// If is positive, test for Combo ID.
if (target > 0) {
if (Screen->ComboD[loc] == target) {
match = true;
}
}
// If is negative, test for the flag being present.
else if (target < 0) {
if (ComboFI(loc, -target)) {
match = true;
}
}
// If the current combo is a match, then transform the combo
// according to .
if (match) {
// If is positive, just change the target to .
if (result > 0) {
Screen->ComboD[loc] = result;
}
// If is negative, grab the combo from the given screen.
else if (result ComboD[loc] = Game->GetComboData(map, screen, loc);
}
}
}
// Now play the message and sound, if appropriate.
if (sound != 0) {
Game->PlaySound(sound);
}
if (message != 0) {
Screen->Message(message);
}
}
}
//////////////////////////////
/// CREDITS (ALPHABETICAL) ///
//////////////////////////////
///////////////////////////
/// Programming Credits ///
/////////////////////////////////////////////////////////////////////////
/// Aevin ///
/// Alucard ///
/// blackbishop89 ///
/// Gleeok (Assorted functions, that led to this.) ///
/// grayswandir (Original creatorof most funtions herein.) ///
/// jsm116 (FFCs and FFC functions.) ///
/// MasterManiac ///
/// MoscowModder (Too much to list; possible also UseRItem) ///
/// Saffith (Tango, Ghost, FFCs, etc.) ///
/// SUCCESSOR (Set/Use Item Funtions) ///
/// Zecora (Forum discussions, and assistance.) ///
/// ZoriaRPG (Library Maintainer, packaging, testing, some code etc.) ///
/////////////////////////////////////////////////////////////////////////
Review this entry
You must be logged in to post a comment.