diff --git a/src/base/qrs.cpp b/src/base/qrs.cpp index 758568d03b..6c9f5e75a9 100644 --- a/src/base/qrs.cpp +++ b/src/base/qrs.cpp @@ -4,20 +4,22 @@ byte quest_rules[QUESTRULES_NEW_SIZE]; byte extra_rules[EXTRARULES_SIZE]; -bool get_qr(int index) +bool get_qr(int index,byte* qrptr) { - return get_bit(quest_rules,index)!=0; + if(!qrptr) qrptr = quest_rules; + return get_bit(qrptr,index)!=0; } -void set_qr(int index,bool state) +void set_qr(int index,bool state,byte* qrptr) { - set_bit(quest_rules,index,state); + if(!qrptr) qrptr = quest_rules; + set_bit(qrptr,index,state); } bool get_er(int index) { - return get_bit(extra_rules,index)!=0; + return get_qr(index,extra_rules); } void set_er(int index,bool state) { - set_bit(extra_rules,index,state); + set_qr(index,state,extra_rules); } diff --git a/src/base/qrs.h b/src/base/qrs.h index 5761c14bc9..a5e653dc3f 100644 --- a/src/base/qrs.h +++ b/src/base/qrs.h @@ -177,6 +177,8 @@ enum //52 qr_FREEFORM_SUBSCREEN_CURSOR, qr_SUBSCR_PRESS_TO_EQUIP, qr_FAIRY_FLAG_COMPAT, qr_MIRROR_PRISM_LAYERS, qr_OLD_LENS_LAYEREFFECT, qr_PUSHBLOCK_SPRITE_LAYER, qr_OLD_SUBSCR, qr_ITM_0_INVIS_ON_BTNS, + //53 + qr_NO_BUTTON_VERIFY, //EMILY SPOT //60 //CONNOR SPOT qr_ = 60*8, @@ -221,10 +223,25 @@ enum extraRules er_MAX }; -bool get_qr(int index); -void set_qr(int index,bool state); +enum //Rulesets +{ + rulesetNONE, rulesetNES, rulesetFixedNES, rulesetBSZ, rulesetZ3, rulesetModern, rulesetLast +}; + +enum //Rule Templates +{ + ruletemplateFixCompat, ruletemplateFixZSCompat, + ruletemplateNewSubscreen, ruletemplateOldSubscreen, + sz_ruletemplate +}; + +bool get_qr(int index,byte* qrptr = nullptr); +void set_qr(int index,bool state,byte* qrptr = nullptr); bool get_er(int index); void set_er(int index,bool state); +//Want to move these here, but looks complicated... +// void applyRuleset(int32_t ruleset, byte* qrptr = nullptr); +// void applyRuleTemplate(int32_t ruleTemplate, byte* qrptr = nullptr); #endif diff --git a/src/base/util.cpp b/src/base/util.cpp index b989b1a7f5..0ca725a330 100644 --- a/src/base/util.cpp +++ b/src/base/util.cpp @@ -1050,25 +1050,33 @@ void zc_trace_clear() ASSERT(trace_file); } -std::string QRHINT(std::vector qrs) +static std::string HINT_TY(std::vector vals, dword ty) { - if(qrs.empty()) return ""; + if(vals.empty()) return ""; std::ostringstream oss; bool comma = false; - oss << "$"; - for(int qr : qrs) + oss << "$#" << ty << "#"; + for(int v : vals) { if(comma) - oss << "," << qr; + oss << "," << v; else { comma = true; - oss << qr; + oss << v; } } oss << "$"; return oss.str(); } +std::string QRHINT(std::vector qrs) +{ + return HINT_TY(qrs,INFOHINT_T_QR); +} +std::string RULETMPL_HINT(std::vector tmpls) +{ + return HINT_TY(tmpls,INFOHINT_T_RULETMPL); +} int binary_search_int(int b1, int b2, std::function proc, int defval) { diff --git a/src/base/util.h b/src/base/util.h index bd90666e6b..65bfcea9ed 100644 --- a/src/base/util.h +++ b/src/base/util.h @@ -84,6 +84,13 @@ int32_t zc_trace_handler(const char *); void zc_trace_clear(); std::string QRHINT(std::vector qrs); +std::string RULETMPL_HINT(std::vector tmpls); +enum //special insert types +{ + INFOHINT_T_QR, + INFOHINT_T_RULETMPL, + INFOHINT_T_MAX +}; enum { diff --git a/src/base/zdefs.h b/src/base/zdefs.h index a0889f65fe..df9cf118ed 100644 --- a/src/base/zdefs.h +++ b/src/base/zdefs.h @@ -2624,8 +2624,7 @@ struct gamedata int32_t global_d[MAX_SCRIPT_REGISTERS]; // script-controlled global variables std::vector< ZCArray > globalRAM; - byte awpn, bwpn, xwpn, ywpn; // Currently selected weapon slots - byte awpnpg, bwpnpg, xwpnpg, ywpnpg; + word awpn = 255, bwpn = 255, xwpn = 255, ywpn = 255; int16_t abtn_itm = -1, bbtn_itm = -1, xbtn_itm = -1, ybtn_itm = -1; int16_t forced_awpn = -1, forced_bwpn = -1, forced_xwpn = -1, forced_ywpn = -1; bool isclearing; // The gamedata is being cleared @@ -3035,6 +3034,8 @@ enum controls //Args for 'getInput()' #define INT_BTN_EX2 0x20 #define INT_BTN_EX3 0x40 #define INT_BTN_EX4 0x80 +#define INT_BTN_X INT_BTN_EX1 +#define INT_BTN_Y INT_BTN_EX2 /////////////// /// MODULES /// diff --git a/src/dialog/about.cpp b/src/dialog/about.cpp index 4343a46f02..ed74a606f4 100644 --- a/src/dialog/about.cpp +++ b/src/dialog/about.cpp @@ -67,8 +67,7 @@ bool AboutDialog::handleMessage(const GUI::DialogMessage& msg) { switch(msg.message) { - case message::OK; - case message::CANCEL; + case message::OK: return true; } return false; diff --git a/src/dialog/alert.cpp b/src/dialog/alert.cpp index 1743c520b0..bd2bd80f63 100644 --- a/src/dialog/alert.cpp +++ b/src/dialog/alert.cpp @@ -106,7 +106,7 @@ bool AlertDialog::handleMessage(const GUI::DialogMessage& msg) case message::OK: onEnd(true,dontshowagain); return true; - case message::CANCEL + case message::CANCEL: onEnd(false,dontshowagain); return true; } diff --git a/src/dialog/info.cpp b/src/dialog/info.cpp index 43b9755aee..8ba76cd5df 100644 --- a/src/dialog/info.cpp +++ b/src/dialog/info.cpp @@ -5,6 +5,9 @@ #ifdef IS_ZQUEST #include "quest_rules.h" +#include "zq/zq_files.h" + +extern const GUI::ListData ruletemplatesList; #endif void displayinfo(std::string title, std::string text) @@ -59,6 +62,17 @@ void InfoDialog::postinit() std::string sub = dlgText.substr(pos+1,nextpos-pos-1); dlgText.erase(pos,nextpos-pos+1); #ifdef IS_ZQUEST + dword special_type = 0; //qr by default + if(sub[0] == '#') //Special type id given + { + auto nexthash = sub.find_first_of("#",1); + if(nexthash == std::string::npos || nexthash == 1) + continue; //invalid + if(sub.find_first_not_of("0123456789",1) != nexthash) + continue; //invalid + special_type = atoi(sub.substr(1,nexthash).c_str()); + sub.erase(0,nexthash+1); + } bool running = true; while(running) { @@ -77,12 +91,21 @@ void InfoDialog::postinit() if(sub2.size() < 1 || sub2.find_first_not_of("0123456789") != std::string::npos) continue; //invalid int val = atoi(sub2.c_str()); - qrs.insert(val); + + switch(special_type) + { + case INFOHINT_T_QR: + qrs.insert(val); + break; + case INFOHINT_T_RULETMPL: + ruleTemplates.insert(val); + break; + } } #endif } - if(qrs.size()) + if(qrs.size() || ruleTemplates.size()) { dest_qrs = next_dest_qr; next_dest_qr = local_qrs; @@ -94,29 +117,64 @@ std::shared_ptr InfoDialog::view() { using namespace GUI::Builder; using namespace GUI::Props; - std::shared_ptr widg; + std::shared_ptr gr; std::shared_ptr closeRow; - + bool add_grid = false, addok = false; #ifdef IS_ZQUEST + add_grid = addok = qrs.size() || ruleTemplates.size(); + if(add_grid) + gr = Row(padding = 0_px); if(qrs.size()) { - GUI::ListData tosearch = combinedQRList()+combinedZSRList(); - widg = Frame(title = "Related QRs", - QRPanel( - padding = 3_px, - onToggle = message::TOGGLE_QR, - onCloseInfo = message::REFRESH, - initializer = local_qrs, - count = 0, - data = tosearch.filter( - [&](GUI::ListItem& itm) + GUI::ListData tosearch = (combinedQRList()+combinedZSRList()).filter( + [&](GUI::ListItem& itm) + { + if(qrs.contains(itm.value)) + return true; + return false; + }); + if(tosearch.size()) + { + gr->add(Frame(title = "Related QRs", + QRPanel( + padding = 3_px, + onToggle = message::TOGGLE_QR, + onCloseInfo = message::REFR_INFO, + initializer = local_qrs, + count = 0, + data = tosearch + ) + )); + } + } + if(ruleTemplates.size()) + { + std::shared_ptr cboxes = Rows<2>(); + cboxes->add(Label(colSpan = 2, text = "Note: Selecting a rule template" + "\nwill write to numerous QRs.")); + int cnt = 0; + for(size_t q = 0; q < ruletemplatesList.size(); ++q) + { + if(!ruleTemplates.contains(q)) + continue; + std::string infostr = ruletemplatesList.getInfo(q); + cboxes->add(infostr.size() ? INFOBTN(infostr) : DINFOBTN()); + cboxes->add(Checkbox( + hAlign = 0.0, checked = false, + text = ruletemplatesList.getText(q), + onToggleFunc = [=](bool state) { - if(qrs.contains(itm.value)) - return true; - return false; - }) - ) - ); + on_templates[q] = state; + } + )); + ++cnt; + } + if(cnt) + gr->add(Frame(title = "Related Rule Templates",cboxes)); + } + #endif + if(addok) + { closeRow = Row(padding = 0_px, Button( text = "OK", @@ -130,9 +188,7 @@ std::shared_ptr InfoDialog::view() ); } else - #endif { - widg = DummyWidget(padding=0_px); closeRow = Row(padding = 0_px, Button( text = "&Close", @@ -141,23 +197,26 @@ std::shared_ptr InfoDialog::view() focused = true) ); } - - return Window( + + std::shared_ptr main_col; + window = Window( title = dlgTitle, - onClose = 0, + onClose = message::CANCEL, hPadding = 0_px, - Column( + main_col = Column( hPadding = 0_px, Label(noHLine = true, hPadding = 2_em, maxLines = 20, maxwidth = Size::pixels(zq_screen_w)-12_px-5_em, textAlign = 1, - text = dlgText), - widg, - closeRow + text = dlgText) ) ); + if(add_grid) + main_col->add(gr); + main_col->add(closeRow); + return window; } bool InfoDialog::handleMessage(const GUI::DialogMessage& msg) @@ -168,10 +227,20 @@ bool InfoDialog::handleMessage(const GUI::DialogMessage& msg) toggle_bit(local_qrs, msg.argument); return false; case message::OK: + #ifdef IS_ZQUEST if(dest_qrs) { + if(ruleTemplates.size()) + { + for(int q = 0; q < sz_ruletemplate; ++q) + { + if(on_templates[q]) + applyRuleTemplate(q,local_qrs); + } + } memcpy(dest_qrs, local_qrs, sizeof(local_qrs)); } + #endif [[fallthrough]]; case message::CANCEL: if(dest_qrs) @@ -179,7 +248,7 @@ bool InfoDialog::handleMessage(const GUI::DialogMessage& msg) next_dest_qr = dest_qrs; } return true; - case message::REFRESH: + case message::REFR_INFO: rerun_dlg = true; return true; } diff --git a/src/dialog/info.h b/src/dialog/info.h index 1bd2d97983..88f142e624 100644 --- a/src/dialog/info.h +++ b/src/dialog/info.h @@ -3,6 +3,7 @@ #include "base/qrs.h" #include +#include #include #include #include @@ -17,7 +18,7 @@ void displayinfo(std::string title, std::string text); class InfoDialog: public GUI::Dialog { public: - enum class message { REFR_INFO, OK, CANCEL, TOGGLE_QR, REFRESH, BTN }; + enum class message { REFR_INFO, OK, CANCEL, TOGGLE_QR, BTN }; InfoDialog(std::string title, std::string text); InfoDialog(std::string title, std::vector lines); @@ -26,12 +27,17 @@ class InfoDialog: public GUI::Dialog virtual bool handleMessage(const GUI::DialogMessage& msg); protected: + std::shared_ptr window; std::string dlgTitle; std::string dlgText; - std::set qrs; + + std::set qrs; //related qrs + std::set ruleTemplates; //related rule templates + byte local_qrs[QR_SZ]; byte* dest_qrs; byte* old_dest_qrs; + bool on_templates[sz_ruletemplate] = {false}; void postinit(); }; diff --git a/src/dialog/pickruleset.cpp b/src/dialog/pickruleset.cpp index d177bf5d98..7122505ae1 100644 --- a/src/dialog/pickruleset.cpp +++ b/src/dialog/pickruleset.cpp @@ -39,7 +39,7 @@ static const GUI::ListData rulesetsList "All but a few rules are off.\n" } }; -PickRulesetDialog::PickRulesetDialog(std::function setRuleset): +PickRulesetDialog::PickRulesetDialog(std::function setRuleset): setRuleset(setRuleset) {} @@ -114,7 +114,7 @@ bool PickRulesetDialog::handleMessage(const GUI::DialogMessage& msg) } //Exiting messages case message::OK: - setRuleset(rulesetChoice->getChecked()); + setRuleset(rulesetChoice->getChecked(),nullptr); return true; case message::CANCEL: return true; diff --git a/src/dialog/pickruleset.h b/src/dialog/pickruleset.h index 6d6df7dd05..af80a4254e 100644 --- a/src/dialog/pickruleset.h +++ b/src/dialog/pickruleset.h @@ -14,7 +14,7 @@ class PickRulesetDialog: public GUI::Dialog public: enum class message { REFR_INFO, OK, CANCEL, RULESET }; - PickRulesetDialog(std::function setRuleset); + PickRulesetDialog(std::function setRuleset); std::shared_ptr view() override; bool handleMessage(const GUI::DialogMessage& msg); @@ -22,7 +22,7 @@ class PickRulesetDialog: public GUI::Dialog private: std::shared_ptr rulesetChoice; std::shared_ptr rulesetInfo; - std::function setRuleset; + std::function setRuleset; }; #endif diff --git a/src/dialog/pickruletemplate.cpp b/src/dialog/pickruletemplate.cpp index a80369ac61..30d99c4e64 100644 --- a/src/dialog/pickruletemplate.cpp +++ b/src/dialog/pickruletemplate.cpp @@ -10,15 +10,20 @@ void call_ruletemplate_dlg() PickRuleTemplateDialog(applyRuleTemplate).show(); } -static const GUI::ListData ruletemplatesList +const GUI::ListData ruletemplatesList { - { "Bugfix", ruletemplateCompat, + { "Bugfix", ruletemplateFixCompat, "Removes all 'Compat' rules" }, - { "ZScript Bugfix", ruletemplateZSCompat, - "Remove ZScript compatibility rules" } + { "ZScript Bugfix", ruletemplateFixZSCompat, + "Remove ZScript compatibility rules" }, + { "New Subscreen", ruletemplateNewSubscreen, + "Set a variety of rules for newer engine subscreen functionality." }, + { "Old Subscreen", ruletemplateOldSubscreen, + "The exact opposite of 'New Subscreen', reverts to old" + " engine subscreen functionality." }, }; -PickRuleTemplateDialog::PickRuleTemplateDialog(std::function setRuleTemplate): +PickRuleTemplateDialog::PickRuleTemplateDialog(std::function setRuleTemplate): setRuleTemplate(setRuleTemplate) {} @@ -86,7 +91,7 @@ bool PickRuleTemplateDialog::handleMessage(const GUI::DialogMessage& ms for(size_t q = 0; q < ruletemplatesList.size(); ++q) { if(templates[q]->getChecked()) - setRuleTemplate(ruletemplatesList.getValue(q)); + setRuleTemplate(ruletemplatesList.getValue(q),nullptr); } return true; case message::CANCEL: diff --git a/src/dialog/pickruletemplate.h b/src/dialog/pickruletemplate.h index ebc1c83186..d36dab5d18 100644 --- a/src/dialog/pickruletemplate.h +++ b/src/dialog/pickruletemplate.h @@ -4,25 +4,27 @@ #include #include "gui/checkbox.h" #include "gui/label.h" +#include "base/qrs.h" #include #include #include "zq/zq_files.h" void call_ruletemplate_dlg(); +extern const GUI::ListData ruletemplatesList; class PickRuleTemplateDialog: public GUI::Dialog { public: enum class message { REFR_INFO, OK, CANCEL }; - PickRuleTemplateDialog(std::function setRuleTemplate); + PickRuleTemplateDialog(std::function setRuleTemplate); std::shared_ptr view() override; bool handleMessage(const GUI::DialogMessage& msg); private: std::shared_ptr templates[sz_ruletemplate]; - std::function setRuleTemplate; + std::function setRuleTemplate; }; #endif diff --git a/src/dialog/quest_rules.cpp b/src/dialog/quest_rules.cpp index 977429a1a2..9257190413 100644 --- a/src/dialog/quest_rules.cpp +++ b/src/dialog/quest_rules.cpp @@ -40,6 +40,7 @@ enum rules_misc, rules_nesfix, rules_player, + rules_subscr, rules_weapon, rules_zs_script, rules_zs_instruction, @@ -856,11 +857,6 @@ static GUI::ListData compatRulesList " they will use the Z axis up to 40 pixels away and go higher up than before, but still be hittable when close to the Player."}, { "No Pols Voice/Vire Shadows with Z axis", qr_POLVIRE_NO_SHADOW, "If enabled, Pols Voice and Vires won't have shadows when jumping in the Z axis."}, - { "Old Subscreen Selector", qr_SUBSCR_OLD_SELECTOR, - "If disabled, the subscreen selector will stretch to fit the item it is selecting." }, - { "Old Subscreen Item ID order", qr_SUBSCR_BACKWARDS_ID_ORDER, - "If enabled, the subscreen will prioritize lower-ID items when there is a 'Level' tie, instead" - " of prioritizing higher-ID items like everything else in the engine." }, { "Decorations -2 yoffset", qr_DECO_2_YOFFSET, "If enabled, all 'decoration' type objects will have a yoffset of '-2' instead of '0'." }, { "Screen->State[] 0x80 bug", qr_SCREENSTATE_80s_BUG, @@ -926,10 +922,6 @@ static GUI::ListData compatRulesList { "Old (Buggy) ZScript Volume Access", qr_OLD_SCRIPT_VOLUME, "If enabled, Audio->AdjustMusicVolume() and Audio->AdjustSFXVolume() will use their old behavior," " which was bugged and wrote directly to the volume sliders." }, - { "Old Engine Subscreen Quirks", qr_OLD_SUBSCR, - "If enabled, the subscreen behaves in a way needed for compat."}, - { "Item 0 is invisible on buttons", qr_ITM_0_INVIS_ON_BTNS, - "If enabled, Item 0 will not be drawn if equipped to a button."}, }; static GUI::ListData enemiesRulesList @@ -1122,21 +1114,6 @@ static GUI::ListData itemRulesList static GUI::ListData miscRulesList { - { "Allow Setting A Button Items", qr_SELECTAWPN, - "If enabled, you can select what item goes on the A button on the subscreen." - " If disabled, the A Button is hardcoded to the highest leveled Sword item" - " that you possess, and you are prevented from equipping Sword-class items" - " on the B button."}, - { "Allow Setting X Button Items", qr_SET_XBUTTON_ITEMS, - "If enabled, allows setting items to the X (Ex1) button. If disabled, the" - " X/Ex1 button has no usage outside of scripting."}, - { "Allow Setting Y Button Items", qr_SET_YBUTTON_ITEMS, - "If enabled, allows setting items to the Y (Ex2) button. If disabled, the" - " Y/Ex2 button has no usage outside of scripting."}, - { "Freeform Subscreen Cursor", qr_FREEFORM_SUBSCREEN_CURSOR, - "If enabled, the subscreen cursor can move freely even to empty spots."}, - { "Always Press To Equip", qr_SUBSCR_PRESS_TO_EQUIP, - "If enabled, you must always press a button to equip an item, even if only B items are enabled."}, { "Messages Can Be Sped Up With The A Button", qr_ALLOWFASTMSG, "If enabled, holding the A button will prevent any message delay from occuring, displaying" " 60 characters per second."}, @@ -1170,9 +1147,6 @@ static GUI::ListData miscRulesList { "Fast Heart Refill", qr_FASTFILL, "If enabled, potions and fairy rings will restore half a heart every 6 frames while healing." " If disabled, they will restore half a heart every 22 frames."}, - { "Enable 1/4 Heart Life Bar", qr_QUARTERHEART, - "If enabled, the Life Meter subscreen item will display quarter hearts if the Player" - " has that much life. Otherwise, it will only display half and full hearts, rounding up."}, { "Show Time On Subscreen", qr_TIME, "If enabled, current Game Time can be shown on the subscreen. This displays how long you've" " been playing on that save file. Note that having cheats turned on will prevent the Game Time" @@ -1239,14 +1213,6 @@ static GUI::ListData miscRulesList { "Screen->Wavy Speed is not affected by Epilepsy Protection", qr_WAVY_NO_EPILEPSY_2, "If enabled, the speed of wavy effects is not halved by epilepsy protection. Epilepsy protection normally halves" " the speed of wavy effects; enabling this will bypass this behavior."}, - { "No L/R Inventory Shifting", qr_NO_L_R_BUTTON_INVENTORY_SWAP, - "If enabled, L/R item switching is disabled. Normally, you can quickly change what item is selected to the B button" - " by pressing L and R to shift the selection left and right. Enabling this disables this behavior, allowing the usage" - " of L and R for more scripted purposes."}, - { "Ex3 and Ex4 Shift A-Button Items", qr_USE_EX1_EX2_INVENTORYSWAP, - "If enabled, Ex3 and Ex4 will shift the item equipped on the A button to whatever item is left or right of it on the" - " subscreen, without having to open the subscreen. This is similar to the existing L/R B-Button shifting, but for the" - " A button. Disabling this leaves Ex3 and Ex4 open for scripted usage."}, { "Disable Fast Mode (Uncap)", qr_NOFASTMODE, "If enabled, the built in fast-forward key ('~', or Tilde) is prevented from working while the quest is loaded," " and FPS is forced to be throttled at 60 FPS. Many players fast forward to speed things up, especially during" @@ -1265,9 +1231,6 @@ static GUI::ListData miscRulesList "If enabled, you cannot scroll the screen while the player is carrying something with a Lift Glove."}, { "Carryables Can't Leave Screen", qr_CARRYABLE_NO_ACROSS_SCREEN, "If enabled, leaving a screen while carrying something with a Lift Glove will delete the carried object."}, - { "Higher Maximum Playtime", qr_GREATER_MAX_TIME, - "Bumps up the Max Playtime from 99 hours, 5 minutes, and 54 seconds, to 9000 hours." - "Has no downsides, is only here for compatibility sake."}, { "New Dark Rooms", qr_NEW_DARKROOM, "If enabled, Dark Rooms behave less like Z1 and more like LttP/Minish Cap, having light circles around torches and giving a customizeable" " spotlight around the Player. If disabled, Z1-styled dark rooms are used, which only darken the screen until lit up with a candle."}, @@ -1459,6 +1422,54 @@ static GUI::ListData playerRulesList "If enabled, the Player will flicker when invincible or after taking damage instead of flashing colors."} }; +static GUI::ListData subscrRulesList +{ + //Compat stuff first + { "Old Engine Subscreen Quirks", qr_OLD_SUBSCR, + "If enabled, the subscreen behaves in a way needed for compat."}, + { "Old Subscreen Selector", qr_SUBSCR_OLD_SELECTOR, + "If disabled, the subscreen selector will stretch to fit the item it is selecting." }, + { "Old Subscreen Item ID order", qr_SUBSCR_BACKWARDS_ID_ORDER, + "If enabled, the subscreen will prioritize lower-ID items when there is a 'Level' tie, instead" + " of prioritizing higher-ID items like everything else in the engine." }, + //Then more option-y stuff + { "Item 0 is invisible on buttons", qr_ITM_0_INVIS_ON_BTNS, + "If enabled, Item 0 will not be drawn if equipped to a button."}, + { "Freeform Subscreen Cursor", qr_FREEFORM_SUBSCREEN_CURSOR, + "If enabled, the subscreen cursor can move freely even to empty spots."}, + { "Always Press To Equip", qr_SUBSCR_PRESS_TO_EQUIP, + "If enabled, you must always press a button to equip an item, even if only B items are enabled."}, + { "No Button Verification", qr_NO_BUTTON_VERIFY, + "If enabled, the engine won't attempt to forcibly fill empty buttons with items." + "\nAlso allows unequipping items by trying to equip it to the same button again."}, + + { "Allow Setting A Button Items", qr_SELECTAWPN, + "If enabled, you can select what item goes on the A button on the subscreen." + " If disabled, the A Button is hardcoded to the highest leveled Sword item" + " that you possess, and you are prevented from equipping Sword-class items" + " on the B button."}, + { "Allow Setting X Button Items", qr_SET_XBUTTON_ITEMS, + "If enabled, allows setting items to the X (Ex1) button. If disabled, the" + " X/Ex1 button has no usage outside of scripting."}, + { "Allow Setting Y Button Items", qr_SET_YBUTTON_ITEMS, + "If enabled, allows setting items to the Y (Ex2) button. If disabled, the" + " Y/Ex2 button has no usage outside of scripting."}, + { "Enable 1/4 Heart Life Bar", qr_QUARTERHEART, + "If enabled, the Life Meter subscreen widget will display quarter hearts if the Player" + " has that much life. Otherwise, it will only display half and full hearts, rounding up."}, + { "No L/R Inventory Shifting", qr_NO_L_R_BUTTON_INVENTORY_SWAP, + "If enabled, L/R item switching is disabled. Normally, you can quickly change what item is selected to the B button" + " by pressing L and R to shift the selection left and right. Enabling this disables this behavior, allowing the usage" + " of L and R for more scripted purposes."}, + { "Ex3 and Ex4 Shift A-Button Items", qr_USE_EX1_EX2_INVENTORYSWAP, + "If enabled, Ex3 and Ex4 will shift the item equipped on the A button to whatever item is left or right of it on the" + " subscreen, without having to open the subscreen. This is similar to the existing L/R B-Button shifting, but for the" + " A button. Disabling this leaves Ex3 and Ex4 open for scripted usage."}, + { "Higher Maximum Playtime", qr_GREATER_MAX_TIME, + "Bumps up the Max Playtime from 99 hours, 5 minutes, and 54 seconds, to 9000 hours." + "Has no downsides, is only here for compatibility sake."}, +}; + static GUI::ListData weaponsRulesList { { "Prisms Reflect Angular Weapons At Angles", qr_ANGULAR_REFLECTED_WEAPONS, @@ -1527,11 +1538,12 @@ GUI::ListData const& combinedQRList() miscRulesList.tag(rules_misc); nesfixesRulesList.tag(rules_nesfix); playerRulesList.tag(rules_player); + subscrRulesList.tag(rules_subscr); weaponsRulesList.tag(rules_weapon); combinedRulesList = animRulesList + comboRulesList + compatRulesList + enemiesRulesList + itemRulesList + miscRulesList + nesfixesRulesList - + playerRulesList + weaponsRulesList; + + playerRulesList + subscrRulesList + weaponsRulesList; combinedRulesList.alphabetize(); inited_combined_rules = true; } @@ -1645,11 +1657,12 @@ bool hasCompatRulesEnabled() } return false; } -void applyRuleTemplate(int32_t ruleTemplate) +void applyRuleTemplate(int32_t ruleTemplate, byte* qrptr) { + bool inv = false; switch(ruleTemplate) { - case ruletemplateCompat: + case ruletemplateFixCompat: { for(size_t q = 0; q < compatRulesList.size(); ++q) { @@ -1660,14 +1673,14 @@ void applyRuleTemplate(int32_t ruleTemplate) case qr_STRING_FRAME_OLD_WIDTH_HEIGHT: continue; //Don't auto-unset, use 'onStrFix()' instead } - set_qr(rule, 0); + set_qr(rule, 0, qrptr); } onStrFix(); break; } - case ruletemplateZSCompat: + case ruletemplateFixZSCompat: { - int32_t zsOnRules[] = { + int zsOnRules[] = { qr_PARSER_SHORT_CIRCUIT, qr_PARSER_TRUE_INT_SIZE, qr_ITEMSCRIPTSKEEPRUNNING, qr_CLEARINITDONSCRIPTCHANGE, qr_COMBOSCRIPTS_LAYER_0, qr_PASSIVE_SUBSCRIPT_RUNS_WHEN_GAME_IS_FROZEN, @@ -1676,7 +1689,7 @@ void applyRuleTemplate(int32_t ruleTemplate) qr_SPRITEXY_IS_FLOAT, qr_WEAPONS_EXTRA_FRAME, qr_FIXSCRIPTSDURINGSCROLLING, qr_ALWAYS_DEALLOCATE_ARRAYS, }; - int32_t zsOffRules[] = { + int zsOffRules[] = { qr_PARSER_250DIVISION, qr_PARSER_NO_LOGGING, qr_PARSER_BOOL_TRUE_DECIMAL, qr_PARSER_BINARY_32BIT, qr_OLD_INIT_SCRIPT_TIMING, qr_NOITEMWAITDRAW, qr_NOFFCWAITDRAW, @@ -1687,19 +1700,36 @@ void applyRuleTemplate(int32_t ruleTemplate) qr_OLDQUESTMISC, qr_DO_NOT_DEALLOCATE_INIT_AND_SAVELOAD_ARRAYS, qr_BROKEN_GETPIXEL_VALUE, qr_ZS_NO_NEG_ARRAY, }; - for(int32_t qr : zsOnRules) - { - set_qr(qr, 1); - } - for(int32_t qr : zsOffRules) - { - set_qr(qr, 0); - } + for(int qr : zsOnRules) + set_qr(qr, 1, qrptr); + for(int qr : zsOffRules) + set_qr(qr, 0, qrptr); + break; + } + case ruletemplateOldSubscreen: + inv = true; + [[fallthrough]]; + case ruletemplateNewSubscreen: + { + int subscr_rules_off[] = { + qr_OLD_SUBSCR, qr_ITM_0_INVIS_ON_BTNS, + qr_SUBSCR_OLD_SELECTOR, qr_SUBSCR_BACKWARDS_ID_ORDER, + }; + int subscr_rules_on[] = { + qr_SUBSCR_PRESS_TO_EQUIP, qr_FREEFORM_SUBSCREEN_CURSOR, + qr_NO_BUTTON_VERIFY, + }; + //'inv' inverts the selection, to reverse to the old subscreen setup. + for(int qr : subscr_rules_off) + set_qr(qr,inv?1:0, qrptr); + for(int qr : subscr_rules_on) + set_qr(qr,inv?0:1, qrptr); break; } default: return; } - saved = false; + if(qrptr == quest_rules) + saved = false; } void QRDialog::reloadQRs() @@ -1965,6 +1995,16 @@ std::shared_ptr QRDialog::view() data = playerRulesList ) ), + TabRef( + name = "Subscreen", + QRPanel( + padding = 3_px, + onToggle = message::TOGGLE_QR, + initializer = local_qrs, + count = qrs_per_tab, + data = subscrRulesList + ) + ), TabRef( name = "Weapon", QRPanel( diff --git a/src/dialog/subscr_props.cpp b/src/dialog/subscr_props.cpp index 1f8448f84d..541baa2fd8 100644 --- a/src/dialog/subscr_props.cpp +++ b/src/dialog/subscr_props.cpp @@ -3,6 +3,7 @@ #include "info.h" #include #include +#include #include "zq/zq_subscr.h" #include "zc_list_data.h" #include "gui/use_size.h" @@ -10,6 +11,7 @@ #include "base/misctypes.h" extern script_data *genericscripts[NUMSCRIPTSGENERIC]; +extern ZCSubscreen subscr_edit; static bool dlg_retval = false; bool call_subscrprop_dialog(SubscrWidget* widg, int32_t obj_ind) @@ -18,6 +20,7 @@ bool call_subscrprop_dialog(SubscrWidget* widg, int32_t obj_ind) return dlg_retval; } +static const int btn_flags[4] = {INT_BTN_A,INT_BTN_B,INT_BTN_X,INT_BTN_Y}; SubscrPropDialog::SubscrPropDialog(SubscrWidget* widg, int32_t obj_ind) : local_subref(widg->clone()), subref(widg), index(obj_ind), list_font(GUI::ZCListData::fonts(false,true,true)), @@ -28,7 +31,20 @@ SubscrPropDialog::SubscrPropDialog(SubscrWidget* widg, int32_t obj_ind) : list_counters(GUI::ZCListData::ss_counters()), list_itemclass(GUI::ZCListData::itemclass(true)), list_genscr(GUI::ZCListData::generic_script()) -{} +{ + byte pg = subscr_edit.curpage, ind = index; + start_default_btnslot = 0; + if(widg->getType() == widgITEMSLOT) + { + for(int q = 0; q < 4; ++q) + { + if((subscr_edit.def_btns[q]&0xFF) == pg + && (subscr_edit.def_btns[q]>>8) == ind) + start_default_btnslot |= btn_flags[q]; + } + } + set_default_btnslot = start_default_btnslot; +} static const GUI::ListData two_three_rows { @@ -96,6 +112,18 @@ Checkbox( \ } \ ) +#define _EX_RBOX hAlign = 1.0,boxPlacement = GUI::Checkbox::boxPlacement::RIGHT +#define CBOX_EX(var, bit, txt, ...) \ +Checkbox( \ + __VA_ARGS__, \ + text = txt, \ + checked = var & bit, \ + onToggleFunc = [=](bool state) \ + { \ + SETFLAG(var, bit, state); \ + } \ +) + #define DDL(var, lister) \ DropDownList(data = lister, \ fitParent = true, \ @@ -145,6 +173,27 @@ Frame(fitParent = true, Column(fitParent = true, \ CBOX(vModflag,bit,"Mod",1) \ )) +#define DEFEQUP_CBOX(ind,btnstr,qrhint) \ +def_eqp_cboxes[ind] = Checkbox( \ + text = fmt::format("Default {} Equipment",btnstr), hAlign = 0.0, \ + checked = set_default_btnslot&btn_flags[ind], \ + onToggleFunc = [=](bool state) \ + { \ + if(state) \ + set_default_btnslot = btn_flags[ind]; \ + else set_default_btnslot &= ~btn_flags[ind]; \ + for(int cb = 0; cb < 4; ++cb) \ + { \ + if(cb==ind) continue; \ + def_eqp_cboxes[cb]->setChecked(false); \ + } \ + }), \ +INFOBTN_F("Sets this ItemSlot to be the default equipped to the '{0}' button." \ + " This applies only for the active subscreen on the Starting DMap." \ + " Setting this will unset it for all other ItemSlots." \ + "\nThis can only be set if items can be equipped to the {0} button," \ + " and 'qr_OLD_SUBSCR' is disabled.{1}",btnstr,qrhint) + //Tile block max preview tiledim #define TB_LA 12 @@ -626,7 +675,7 @@ std::shared_ptr SubscrPropDialog::view() } case widgITEMSLOT: { - SW_CurrentItem* w = dynamic_cast(local_subref); + SW_ItemSlot* w = dynamic_cast(local_subref); attrib_grid = Rows<3>( labels[0] = Label(text = "Item Class:", hAlign = 1.0), ddl = DDL(w->iclass, list_itemclass), @@ -644,13 +693,25 @@ std::shared_ptr SubscrPropDialog::view() } ), INFOBTN("The specified item ID will be tied to this item slot (OVERRIDES 'Item Class' if set)"), - DummyWidget(), - CBOX(w->flags,SUBSCR_CURITM_INVIS,"Invisible",1), + // + Rows<2>(rowSpan = 4, padding = 0_px, + DEFEQUP_CBOX(0,"A",QRHINT({qr_OLD_SUBSCR,qr_SELECTAWPN})+RULETMPL_HINT({ruletemplateNewSubscreen})), + DEFEQUP_CBOX(1,"B",QRHINT({qr_OLD_SUBSCR})+RULETMPL_HINT({ruletemplateNewSubscreen})), + DEFEQUP_CBOX(2,"X",QRHINT({qr_OLD_SUBSCR,qr_SET_XBUTTON_ITEMS})+RULETMPL_HINT({ruletemplateNewSubscreen})), + DEFEQUP_CBOX(3,"Y",QRHINT({qr_OLD_SUBSCR,qr_SET_YBUTTON_ITEMS})+RULETMPL_HINT({ruletemplateNewSubscreen})) + ), + // + CBOX_EX(w->flags,SUBSCR_CURITM_INVIS,"Invisible",_EX_RBOX), INFOBTN("If checked, the item is invisible on the subscreen"), - DummyWidget(), - CBOX(w->flags,SUBSCR_CURITM_NONEQP,"Non-Equippable",1), + CBOX_EX(w->flags,SUBSCR_CURITM_NONEQP,"Non-Equippable",_EX_RBOX), INFOBTN("If checked, the item cannot be equipped to a button." - " 'Always Press To Equip' is recommended if this is used." + QRHINT({qr_SUBSCR_PRESS_TO_EQUIP})) + " 'Always Press To Equip' is recommended if this is used." + QRHINT({qr_SUBSCR_PRESS_TO_EQUIP})), + CBOX_EX(w->flags,SUBSCR_CURITM_IGNR_SP_SELTEXT,"Ignore Special Selection Text",_EX_RBOX), + INFOBTN("If checked, special selection text (like heart piece count on the" + " heart piece display, or bow name on bow&arrow) will not be added for this widget."), + CBOX_EX(w->flags,SUBSCR_CURITM_IGNR_SP_DISPLAY,"Ignore Special Display",_EX_RBOX), + INFOBTN("If checked, special display properties (like the hardcoded map, compass, boss key" + " displays and changing heart pieces into the heart piece display) will not occur for this widget.") ); break; } @@ -686,8 +747,8 @@ std::shared_ptr SubscrPropDialog::view() Label(text = "Delay:", hAlign = 1.0), Label(text = "Container:", hAlign = 1.0), CBOX(w->flags,SUBSCR_LGAUGE_UNQLAST,"Unique Last",2), - NUM_FIELD(w->frames, 0, 999), - NUM_FIELD(w->speed, 0, 999), + NUM_FIELD(w->frames, 1, 999), + NUM_FIELD(w->speed, 1, 999), NUM_FIELD(w->delay, 0, 999), NUM_FIELD(w->container, 0, 9999), DummyWidget(rowSpan=3), @@ -736,8 +797,8 @@ std::shared_ptr SubscrPropDialog::view() Label(text = "Container:", hAlign = 1.0), Label(text = "Show:", hAlign = 1.0), CBOX(w->flags,SUBSCR_MGAUGE_UNQLAST,"Unique Last",2), - NUM_FIELD(w->frames, 0, 999), - NUM_FIELD(w->speed, 0, 999), + NUM_FIELD(w->frames, 1, 999), + NUM_FIELD(w->speed, 1, 999), NUM_FIELD(w->delay, 0, 999), NUM_FIELD(w->container, 0, 9999), NUM_FIELD(w->showdrain, -1, 9999), @@ -1166,19 +1227,20 @@ std::shared_ptr SubscrPropDialog::view() }), selgs[0] = Rows<3>( Label(text = "Position:", hAlign = 1.0), - NUM_FIELD(local_subref->pos, -9999, 9999), - INFOBTN("The unique position ID of this slot"), + NUM_FIELD(local_subref->pos, 0, 254), + INFOBTN("The unique position ID of this slot. Setting this to a number" + " that is already in use on this page may cause buggy behavior."), Label(text = "Up Select:", hAlign = 1.0), - NUM_FIELD(local_subref->pos_up, -9999, 9999), + NUM_FIELD(local_subref->pos_up, 0, 254), INFOBTN("The unique position ID to move to when pressing 'Up'"), Label(text = "Down Select:", hAlign = 1.0), - NUM_FIELD(local_subref->pos_down, -9999, 9999), + NUM_FIELD(local_subref->pos_down, 0, 254), INFOBTN("The unique position ID to move to when pressing 'Down'"), Label(text = "Left Select:", hAlign = 1.0), - NUM_FIELD(local_subref->pos_left, -9999, 9999), + NUM_FIELD(local_subref->pos_left, 0, 254), INFOBTN("The unique position ID to move to when pressing 'Left' / 'L' quickswap"), Label(text = "Right Select:", hAlign = 1.0), - NUM_FIELD(local_subref->pos_right, -9999, 9999), + NUM_FIELD(local_subref->pos_right, 0, 254), INFOBTN("The unique position ID to move to when pressing 'Right' / 'R' quickswap") ) ) @@ -1248,6 +1310,7 @@ std::shared_ptr SubscrPropDialog::view() ) ); updateSelectable(); + refr_info(); return window; } @@ -1298,12 +1361,52 @@ void SubscrPropDialog::update_wh() } } +void SubscrPropDialog::refr_info() +{ + switch(local_subref->getType()) + { + case widgITEMSLOT: + { + bool dis = get_qr(qr_OLD_SUBSCR); + def_eqp_cboxes[0]->setDisabled(dis || !get_qr(qr_SELECTAWPN)); + def_eqp_cboxes[1]->setDisabled(dis); + def_eqp_cboxes[2]->setDisabled(dis || !get_qr(qr_SET_XBUTTON_ITEMS)); + def_eqp_cboxes[3]->setDisabled(dis || !get_qr(qr_SET_YBUTTON_ITEMS)); + break; + } + } +} bool SubscrPropDialog::handleMessage(const GUI::DialogMessage& msg) { switch(msg.message) { + case message::REFR_INFO: + refr_info(); + break; case message::OK: subref->copy_prop(local_subref,true); + if(set_default_btnslot != start_default_btnslot) //Changed default equipment + { + byte pg = subscr_edit.curpage, ind = index; + for(int q = 0; q < 4; ++q) + { + if((start_default_btnslot&btn_flags[q]) + && !(set_default_btnslot&btn_flags[q])) + { //Unset it entirely + subscr_edit.def_btns[q] = 255; + } + else if(!(start_default_btnslot&btn_flags[q]) + && (set_default_btnslot&btn_flags[q])) + { //Set this to be the default + subscr_edit.def_btns[q] = pg | (byte(subref->pos)<<8); + } + else if((start_default_btnslot&btn_flags[q]) + && byte(subref->pos)!=subscr_edit.def_btns[q]>>8) + { //Update the 'pos' value + subscr_edit.def_btns[q] = pg | (byte(subref->pos)<<8); + } + } + } dlg_retval = true; return true; case message::CANCEL: diff --git a/src/dialog/subscr_props.h b/src/dialog/subscr_props.h index 50fdb15570..9de6181f7f 100644 --- a/src/dialog/subscr_props.h +++ b/src/dialog/subscr_props.h @@ -47,9 +47,13 @@ class SubscrPropDialog: public GUI::Dialog std::shared_ptr geninitd_lbl[8]; std::shared_ptr geninitd_btn[8]; + + std::shared_ptr def_eqp_cboxes[4]; SubscrWidget* subref; SubscrWidget* local_subref; int32_t index; + byte set_default_btnslot; + byte start_default_btnslot; zasm_meta local_gen_meta; @@ -59,6 +63,7 @@ class SubscrPropDialog: public GUI::Dialog void updateSelectable(); void updateColors(); void update_wh(); + void refr_info(); }; #endif diff --git a/src/gui/builder.h b/src/gui/builder.h index 34785cdb91..c718f1b05b 100644 --- a/src/gui/builder.h +++ b/src/gui/builder.h @@ -687,6 +687,13 @@ Button(forceFitH = true, text = "?", \ { \ InfoDialog("Info",inf).show(); \ }) +#define INFOBTN_F(inf,...) \ +Button(forceFitH = true, text = "?", \ + onClick = message::REFR_INFO, \ + onPressFunc = [=]() \ + { \ + InfoDialog("Info",fmt::format(inf,__VA_ARGS__)).show(); \ + }) #define INFOBTN_EX(inf, ...) \ Button(text = "?", \ onClick = message::REFR_INFO, \ diff --git a/src/items.cpp b/src/items.cpp index b5f9ccfc5b..b7c3422f75 100644 --- a/src/items.cpp +++ b/src/items.cpp @@ -609,6 +609,48 @@ void putitem2(BITMAP *dest,int32_t x,int32_t y,int32_t item_id, int32_t &aclk, i temp.unget_UID(); } +void dummyitem_animate(item* dummy, int32_t clk) +{ + int fr = dummy->frames, spd = dummy->o_speed, del = dummy->o_delay; + if(fr < 1) fr = 1; + if(spd < 1) spd = 1; + int clkwid = spd*(fr+del); + clk %= clkwid; + + //To counter needing to call animate, calculate one clk back + clk = clk ? clk-1 : clkwid-1; + + dummy->aframe = clk < (del*spd) ? 0 : (clk-del*spd)/spd; + dummy->aclk=dummy->aframe ? (clk-del*spd)%spd : clk; + + auto item_id = dummy->id; + if ( itemsbuf[item_id].overrideFLAGS > 0 ) + { + dummy->extend = 3; + if ( itemsbuf[item_id].overrideFLAGS&itemdataOVERRIDE_TILEWIDTH ) {dummy->txsz = itemsbuf[item_id].tilew;} + if ( itemsbuf[item_id].overrideFLAGS&itemdataOVERRIDE_TILEHEIGHT ) {dummy->tysz = itemsbuf[item_id].tileh;} + if ( itemsbuf[item_id].overrideFLAGS&itemdataOVERRIDE_HIT_WIDTH ) {dummy->hit_width = itemsbuf[item_id].hxsz;} + if ( itemsbuf[item_id].overrideFLAGS&itemdataOVERRIDE_HIT_HEIGHT ) {dummy->hit_height = itemsbuf[item_id].hysz;} + if ( itemsbuf[item_id].overrideFLAGS&itemdataOVERRIDE_HIT_Z_HEIGHT ) {dummy->hzsz = itemsbuf[item_id].hzsz;} + if ( itemsbuf[item_id].overrideFLAGS&itemdataOVERRIDE_HIT_X_OFFSET ) {dummy->hxofs = itemsbuf[item_id].hxofs;} + if ( itemsbuf[item_id].overrideFLAGS&itemdataOVERRIDE_HIT_Y_OFFSET ) {dummy->hyofs = itemsbuf[item_id].hyofs;} + if ( itemsbuf[item_id].overrideFLAGS&itemdataOVERRIDE_DRAW_X_OFFSET ) {dummy->xofs = itemsbuf[item_id].xofs;} + if ( itemsbuf[item_id].overrideFLAGS&itemdataOVERRIDE_DRAW_Y_OFFSET ) {dummy->yofs = itemsbuf[item_id].yofs;} + } + + dummy->animate(0); +} +void putitem3(BITMAP *dest,int32_t x,int32_t y,int32_t item_id, int32_t clk) +{ + item temp((zfix)x,(zfix)y,(zfix)0,item_id,0,0,true); + temp.yofs=0; + temp.hide_hitbox = true; + + dummyitem_animate(&temp, clk); + temp.draw(dest); + temp.unget_UID(); +} + //some methods for dealing with items int32_t getItemFamily(itemdata* items, int32_t item) { @@ -875,8 +917,7 @@ ALLEGRO_COLOR item::hitboxColor(byte opacity) const return al_map_rgba(0,255,255,opacity); } -std::string get_subscr_arrow_name(int itemid); -std::string itemdata::get_name(bool init) const +std::string itemdata::get_name(bool init, bool plain) const { std::string name; if(display_name[0]) @@ -923,22 +964,27 @@ std::string itemdata::get_name(bool init) const } } name = id > -1 ? item_string[id] : ""; - std::string overname; - switch(family) + if(!plain) { - case itype_arrow: - overname = get_subscr_arrow_name(id); - break; - case itype_bottle: + std::string overname; + switch(family) + { + case itype_arrow: + { + auto bowid = current_item_id(itype_bow,false); + if(bowid>-1 && checkmagiccost(id)) + overname = itemsbuf[bowid].get_name() + " & " + name; + break; + } + case itype_bottle: #ifndef IS_ZQUEST - overname = bottle_slot_name(misc1,""); -#else - overname = ""; + overname = bottle_slot_name(misc1,""); #endif - break; + break; + } + if(!overname.empty()) + return overname; } - if(!overname.empty()) - return overname; } return name; } diff --git a/src/items.h b/src/items.h index 03a6a48257..881a40e513 100644 --- a/src/items.h +++ b/src/items.h @@ -18,6 +18,8 @@ int32_t item_pits(zfix& x, zfix& y, int32_t& fallclk); int32_t select_dropitem(int32_t item_set); int32_t select_dropitem(int32_t item_set, int32_t x, int32_t y); int32_t get_progressive_item(itemdata const& itm, bool lastOwned = false); +bool checkmagiccost(int32_t itemid, bool checkTime = false); +void paymagiccost(int32_t itemid, bool ignoreTimer = false, bool onlyTimer = false); class item : public sprite { @@ -79,6 +81,8 @@ class item : public sprite // easy way to draw an item void putitem(BITMAP *dest,int32_t x,int32_t y,int32_t item_id); void putitem2(BITMAP *dest,int32_t x,int32_t y,int32_t item_id, int32_t &aclk, int32_t &aframe, int32_t flash); +void putitem3(BITMAP *dest,int32_t x,int32_t y,int32_t item_id, int32_t clk); +void dummyitem_animate(item* dummy, int32_t clk); //Now itemdata lives here too! @@ -218,7 +222,7 @@ struct itemdata char display_name[256]; - std::string get_name(bool init = false) const; + std::string get_name(bool init = false, bool plain = false) const; //helper functions because stupid shit int32_t misc(size_t ind) const { diff --git a/src/new_subscr.cpp b/src/new_subscr.cpp index 7fbafed0fd..501318155a 100644 --- a/src/new_subscr.cpp +++ b/src/new_subscr.cpp @@ -13,6 +13,7 @@ #include "items.h" #include "sprite.h" #include +#include #ifdef IS_PLAYER extern int32_t directItem; @@ -27,15 +28,40 @@ int32_t get_homescr(); bool has_item(int32_t item_type, int32_t item); //!TODO subscr.h/subscr.cpp trim -extern item *sel_a, *sel_b; -void subscreenitem(BITMAP *dest, int32_t x, int32_t y, int32_t itemtype); int32_t subscreen_color(int32_t c1, int32_t c2); void draw_textbox(BITMAP *dest, int32_t x, int32_t y, int32_t w, int32_t h, FONT *tempfont, char const*thetext, bool wword, int32_t tabsize, int32_t alignment, int32_t textstyle, int32_t color, int32_t shadowcolor, int32_t backcolor); -void lifegauge(BITMAP *dest,int32_t x,int32_t y, int32_t container, int32_t notlast_tile, int32_t notlast_cset, bool notlast_mod, int32_t last_tile, int32_t last_cset, bool last_mod, - int32_t cap_tile, int32_t cap_cset, bool cap_mod, int32_t aftercap_tile, int32_t aftercap_cset, bool aftercap_mod, int32_t frames, int32_t speed, int32_t delay, bool unique_last); void magicgauge(BITMAP *dest,int32_t x,int32_t y, int32_t container, int32_t notlast_tile, int32_t notlast_cset, bool notlast_mod, int32_t last_tile, int32_t last_cset, bool last_mod, int32_t cap_tile, int32_t cap_cset, bool cap_mod, int32_t aftercap_tile, int32_t aftercap_cset, bool aftercap_mod, int32_t frames, int32_t speed, int32_t delay, bool unique_last, int32_t show); +int subscr_item_clk = 0; +int btnitem_clks[4] = {0}; +int btnitem_ids[4] = {0}; + +void reset_subscr_items() +{ + for(int q = 0; q < 4; ++q) + { + btnitem_clks[q] = 0; + btnitem_ids[q] = -1; + } +} + +void update_subscr_items() +{ + int nullval = get_qr(qr_ITM_0_INVIS_ON_BTNS) ? 0 : -1; + int ids[] = {Awpn,Bwpn,Xwpn,Ywpn}; + for(int q = 0; q < 4; ++q) + { + if(btnitem_ids[q] != ids[1]) + { + btnitem_ids[q] = ids[q]; + btnitem_clks[q] = 0; + } + if(ids[q] > nullval) + ++btnitem_clks[q]; + } +} + int32_t to_real_font(int32_t ss_font) { switch(ss_font) @@ -335,7 +361,7 @@ int32_t SubscrColorInfo::write(PACKFILE *f) const if(!p_putc(type,f)) new_return(1); if(!p_iputw(color,f)) - new_return(2); + new_return(1); return 0; } @@ -384,7 +410,7 @@ int32_t SubscrMTInfo::write(PACKFILE *f) const if(!p_iputl(tilecrn,f)) new_return(1); if(!p_putc(cset,f)) - new_return(2); + new_return(1); return 0; } @@ -436,7 +462,11 @@ byte SubscrWidget::getType() const { return widgNULL; } -int32_t SubscrWidget::getItemVal(bool display) const +int32_t SubscrWidget::getItemVal() const +{ + return -1; +} +int32_t SubscrWidget::getDisplayItem() const { return -1; } @@ -529,42 +559,42 @@ int32_t SubscrWidget::write(PACKFILE *f) const if(!p_putc(getType(),f)) new_return(1); if(!p_putc(type,f)) - new_return(2); + new_return(1); if(!p_putc(posflags,f)) - new_return(3); + new_return(1); if(!p_iputw(x,f)) - new_return(4); + new_return(1); if(!p_iputw(y,f)) - new_return(5); + new_return(1); if(!p_iputw(w,f)) - new_return(6); + new_return(1); if(!p_iputw(h,f)) - new_return(7); + new_return(1); if(!p_iputl(flags,f)) - new_return(8); + new_return(1); if(flags&SUBSCRFLAG_SELECTABLE) { if(!p_iputl(pos,f)) - new_return(9); + new_return(1); if(!p_iputl(pos_up,f)) - new_return(10); + new_return(1); if(!p_iputl(pos_down,f)) - new_return(11); + new_return(1); if(!p_iputl(pos_left,f)) - new_return(12); + new_return(1); if(!p_iputl(pos_right,f)) - new_return(13); + new_return(1); if(!p_putwstr(override_text,f)) - new_return(14); + new_return(1); if(!p_iputw(generic_script,f)) - new_return(15); + new_return(1); if(generic_script) { if(!p_putc(gen_script_btns,f)) - new_return(16); + new_return(1); for(int q = 0; q < 8; ++q) if(!p_iputl(generic_initd[q],f)) - new_return(17); + new_return(1); } } return 0; @@ -744,11 +774,11 @@ int32_t SW_Text::write(PACKFILE *f) const if(!p_iputl(fontid,f)) new_return(1); if(!p_putc(align,f)) - new_return(2); + new_return(1); if(!p_putc(shadtype,f)) - new_return(3); + new_return(1); if(!p_putwstr(text,f)) - new_return(4); + new_return(1); if(auto ret = c_text.write(f)) return ret; if(auto ret = c_shadow.write(f)) @@ -1000,9 +1030,9 @@ int32_t SW_Time::write(PACKFILE *f) const if(!p_iputl(fontid,f)) new_return(1); if(!p_putc(align,f)) - new_return(2); + new_return(1); if(!p_putc(shadtype,f)) - new_return(3); + new_return(1); if(auto ret = c_text.write(f)) return ret; if(auto ret = c_shadow.write(f)) @@ -1163,7 +1193,30 @@ void SW_ButtonItem::draw(BITMAP* dest, int32_t xofs, int32_t yofs, SubscrPage& p if(flags&SUBSCR_BTNITM_TRANSP) drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); - buttonitem(dest, btn, x, y); + int nullval = get_qr(qr_ITM_0_INVIS_ON_BTNS) ? 0 : -1; + int ids[] = {Awpn,Bwpn,Xwpn,Ywpn}; + + if(ids[btn] > nullval) + { + bool dodraw = true; + switch(itemsbuf[ids[btn]].family) + { + case itype_arrow: + if(ids[btn]&0xF000) + { + int bow = current_item_id(itype_bow); + if(bow>-1) + { + putitem3(dest,x,y,bow,subscr_item_clk); + if(!get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN) + && !checkmagiccost(ids[btn]&0xFF)) + dodraw = false; + } + } + break; + } + putitem3(dest,x,y,ids[btn]&0xFF,btnitem_clks[btn]); + } if(flags&SUBSCR_BTNITM_TRANSP) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); @@ -1323,9 +1376,9 @@ int32_t SW_Counter::write(PACKFILE *f) const if(!p_iputl(fontid,f)) new_return(1); if(!p_putc(align,f)) - new_return(2); + new_return(1); if(!p_putc(shadtype,f)) - new_return(3); + new_return(1); if(auto ret = c_text.write(f)) return ret; if(auto ret = c_shadow.write(f)) @@ -1333,17 +1386,17 @@ int32_t SW_Counter::write(PACKFILE *f) const if(auto ret = c_bg.write(f)) return ret; if(!p_iputl(ctrs[0],f)) - new_return(4); + new_return(1); if(!p_iputl(ctrs[1],f)) - new_return(5); + new_return(1); if(!p_iputl(ctrs[2],f)) - new_return(6); + new_return(1); if(!p_putc(digits,f)) - new_return(7); + new_return(1); if(!p_iputl(infitm,f)) - new_return(8); + new_return(1); if(!p_putc(infchar,f)) - new_return(9); + new_return(1); return 0; } @@ -1443,7 +1496,7 @@ int32_t SW_Counters::write(PACKFILE *f) const if(!p_iputl(fontid,f)) new_return(1); if(!p_putc(shadtype,f)) - new_return(2); + new_return(1); if(auto ret = c_text.write(f)) return ret; if(auto ret = c_shadow.write(f)) @@ -1451,11 +1504,11 @@ int32_t SW_Counters::write(PACKFILE *f) const if(auto ret = c_bg.write(f)) return ret; if(!p_putc(digits,f)) - new_return(3); + new_return(1); if(!p_iputl(infitm,f)) - new_return(4); + new_return(1); if(!p_putc(infchar,f)) - new_return(5); + new_return(1); return 0; } @@ -1550,9 +1603,9 @@ int32_t SW_MMapTitle::write(PACKFILE *f) const if(!p_iputl(fontid,f)) new_return(1); if(!p_putc(align,f)) - new_return(2); + new_return(1); if(!p_putc(shadtype,f)) - new_return(3); + new_return(1); if(auto ret = c_text.write(f)) return ret; if(auto ret = c_shadow.write(f)) @@ -1766,11 +1819,11 @@ int32_t SW_Clear::write(PACKFILE *f) const return 0; } -SW_CurrentItem::SW_CurrentItem(subscreen_object const& old) : SW_CurrentItem() +SW_ItemSlot::SW_ItemSlot(subscreen_object const& old) : SW_ItemSlot() { load_old(old); } -bool SW_CurrentItem::load_old(subscreen_object const& old) +bool SW_ItemSlot::load_old(subscreen_object const& old) { if(old.type != ssoCURRENTITEM) return false; @@ -1787,20 +1840,170 @@ bool SW_CurrentItem::load_old(subscreen_object const& old) SETFLAG(flags,SUBSCR_CURITM_NONEQP,old.d2&0x2); return true; } -word SW_CurrentItem::getW() const +word SW_ItemSlot::getW() const { return 16; } -word SW_CurrentItem::getH() const +word SW_ItemSlot::getH() const { return 16; } -byte SW_CurrentItem::getType() const +byte SW_ItemSlot::getType() const { return widgITEMSLOT; } -int32_t SW_CurrentItem::getItemVal(bool display) const +int32_t SW_ItemSlot::getItemVal() const +{ +#ifdef IS_PLAYER + if(iid > -1) + { + bool select = false; + switch(itemsbuf[iid].family) + { + case itype_bomb: + if((game->get_bombs() || + // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. + (itemsbuf[iid].misc1==0 && findWeaponWithParent(iid, wLitBomb))) || + current_item_power(itype_bombbag)) + { + select=true; + } + break; + case itype_bowandarrow: + case itype_arrow: + if(current_item_id(itype_bow)>-1) + { + select=true; + } + break; + case itype_letterpotion: + break; + case itype_sbomb: + { + int32_t bombbagid = current_item_id(itype_bombbag); + + if((game->get_sbombs() || + // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. + (itemsbuf[iid].misc1==0 && findWeaponWithParent(iid, wLitSBomb))) || + (current_item_power(itype_bombbag) && bombbagid>-1 && (itemsbuf[bombbagid].flags & ITEM_FLAG1))) + { + select=true; + } + break; + } + case itype_sword: + { + if(get_qr(qr_SELECTAWPN)) + select=true; + break; + } + default: + select = true; + break; + } + if(select && !item_disabled(iid) && game->get_item(iid)) + { + directItem = iid; + auto ret = iid; + if(ret>-1 && itemsbuf[ret].family == itype_arrow) + ret += 0xF000; //bow + return ret; + } + else return -1; + } + int32_t family = -1; + switch(iclass) + { + case itype_bomb: + { + int32_t bombid = current_item_id(itype_bomb); + + if((game->get_bombs() || + // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. + (bombid>-1 && itemsbuf[bombid].misc1==0 && Lwpns.idCount(wLitBomb)>0)) || + current_item_power(itype_bombbag)) + { + family=itype_bomb; + } + break; + } + case itype_bowandarrow: + case itype_arrow: + if(current_item_id(itype_bow)>-1 && current_item_id(itype_arrow)>-1) + { + family=itype_arrow; + } + break; + case itype_letterpotion: + if(current_item_id(itype_potion)>-1) + family=itype_potion; + else if(current_item_id(itype_letter)>-1) + family=itype_letter; + break; + case itype_sbomb: + { + int32_t bombbagid = current_item_id(itype_bombbag); + int32_t sbombid = current_item_id(itype_sbomb); + + if((game->get_sbombs() || + // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. + (sbombid>-1 && itemsbuf[sbombid].misc1==0 && Lwpns.idCount(wLitSBomb)>0)) || + (current_item_power(itype_bombbag) && bombbagid>-1 && (itemsbuf[bombbagid].flags & ITEM_FLAG1))) + { + family=itype_sbomb; + } + break; + } + case itype_sword: + { + if(get_qr(qr_SELECTAWPN)) + family=itype_sword; + break; + } + default: + family = iclass; + break; + } + if(family < 0) + return -1; + int32_t itemid = current_item_id(family, false); + if(item_disabled(itemid)) + return -1; + if(iclass == itype_bowandarrow) + return itemid|0xF000; + return itemid; +#else + if(iid > -1) return iid; + int fam = iclass; + switch(fam) + { + case itype_letterpotion: + if(current_item_id(itype_potion)==-1) + fam = itype_letter; + else fam = itype_potion; + break; + case itype_bowandarrow: + fam = itype_arrow; + break; + case itype_map: + return iMap; + case itype_compass: + return iCompass; + case itype_bosskey: + return iBossKey; + case itype_heartpiece: + return iHCPiece; + } + int itemid = current_item_id(fam,false); + if(itemid == -1) return -1; + if(fam == itype_bowandarrow) + itemid |= 0xF000; + return itemid; +#endif +} +int32_t SW_ItemSlot::getDisplayItem() const { + bool nosp = flags&SUBSCR_CURITM_IGNR_SP_DISPLAY; #ifdef IS_PLAYER if(iid > -1) { @@ -1808,7 +2011,7 @@ int32_t SW_CurrentItem::getItemVal(bool display) const switch(itemsbuf[iid].family) { case itype_bomb: - if(display && get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN)) + if(get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN)) select = true; else if((game->get_bombs() || // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. @@ -1831,7 +2034,7 @@ int32_t SW_CurrentItem::getItemVal(bool display) const { int32_t bombbagid = current_item_id(itype_bombbag); - if(display && get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN)) + if(get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN)) select = true; else if((game->get_sbombs() || // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. @@ -1869,7 +2072,7 @@ int32_t SW_CurrentItem::getItemVal(bool display) const { int32_t bombid = current_item_id(itype_bomb); - if(display && get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN)) + if(get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN)) family=itype_bomb; else if((game->get_bombs() || // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. @@ -1898,7 +2101,7 @@ int32_t SW_CurrentItem::getItemVal(bool display) const int32_t bombbagid = current_item_id(itype_bombbag); int32_t sbombid = current_item_id(itype_sbomb); - if(display && get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN)) + if(get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN)) family=itype_sbomb; else if((game->get_sbombs() || // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. @@ -1915,6 +2118,22 @@ int32_t SW_CurrentItem::getItemVal(bool display) const family=itype_sword; break; } + //Super Special Cases for display + case itype_map: + if(nosp) break; + return has_item(itype_map, get_dlevel()) ? iMap : -1; + case itype_compass: + if(nosp) break; + return has_item(itype_compass, get_dlevel()) ? iCompass : -1; + case itype_bosskey: + if(nosp) break; + return has_item(itype_bosskey, get_dlevel()) ? iBossKey : -1; + case itype_heartpiece: + if(nosp) break; + if(QMisc.colors.HCpieces_tile) + return iHCPiece; + break; + default: family = iclass; break; @@ -1925,7 +2144,7 @@ int32_t SW_CurrentItem::getItemVal(bool display) const if(item_disabled(itemid)) return -1; if(iclass == itype_bowandarrow) - return itemid+0xF000; + return itemid|0xF000; return itemid; #else if(iid > -1) return iid; @@ -1941,12 +2160,16 @@ int32_t SW_CurrentItem::getItemVal(bool display) const fam = itype_arrow; break; case itype_map: + if(nosp) break; return iMap; case itype_compass: + if(nosp) break; return iCompass; case itype_bosskey: + if(nosp) break; return iBossKey; case itype_heartpiece: + if(nosp) break; return iHCPiece; } int itemid = current_item_id(fam,false); @@ -1956,7 +2179,7 @@ int32_t SW_CurrentItem::getItemVal(bool display) const return itemid; #endif } -void SW_CurrentItem::draw(BITMAP* dest, int32_t xofs, int32_t yofs, SubscrPage& page) const +void SW_ItemSlot::draw(BITMAP* dest, int32_t xofs, int32_t yofs, SubscrPage& page) const { #ifdef IS_PLAYER if(flags&SUBSCR_CURITM_INVIS) @@ -1965,23 +2188,44 @@ void SW_CurrentItem::draw(BITMAP* dest, int32_t xofs, int32_t yofs, SubscrPage& if((flags&SUBSCR_CURITM_INVIS) && !(zinit.ss_flags&ssflagSHOWINVIS)) return; #endif - subscreenitem(dest, getX()+xofs,getY()+yofs, iid > -1 ? (iid|0x8000) : iclass); + int id = getDisplayItem(); + if(id > -1) + { + bool nosp = flags&SUBSCR_CURITM_IGNR_SP_DISPLAY; + if(!nosp && QMisc.colors.HCpieces_tile && id == iHCPiece) + { + int hcpphc = game->get_hcp_per_hc(); + int numhpc = vbound(game->get_HCpieces(),0,hcpphc > 0 ? hcpphc-1 : 0); + int t = QMisc.colors.HCpieces_tile + numhpc; + overtile16(dest,t,x+xofs,y+yofs,QMisc.colors.HCpieces_cset,0); + } + else + { + putitem3(dest,x+xofs,y+yofs,id&0xFF,subscr_item_clk); + if(!nosp && (id&0xF000)) + { + int id2 = current_item_id(itype_bow,false); + if(id2 > -1) + putitem3(dest,x+xofs,y+yofs,id2,subscr_item_clk); + } + } + } } -SubscrWidget* SW_CurrentItem::clone() const +SubscrWidget* SW_ItemSlot::clone() const { - return new SW_CurrentItem(*this); + return new SW_ItemSlot(*this); } -bool SW_CurrentItem::copy_prop(SubscrWidget const* src, bool all) +bool SW_ItemSlot::copy_prop(SubscrWidget const* src, bool all) { if(src->getType() != getType() || src == this) return false; - SW_CurrentItem const* other = dynamic_cast(src); + SW_ItemSlot const* other = dynamic_cast(src); SubscrWidget::copy_prop(other,all); iid = other->iid; iclass = other->iclass; return true; } -int32_t SW_CurrentItem::read(PACKFILE *f, word s_version) +int32_t SW_ItemSlot::read(PACKFILE *f, word s_version) { if(auto ret = SubscrWidget::read(f,s_version)) return ret; @@ -1991,14 +2235,14 @@ int32_t SW_CurrentItem::read(PACKFILE *f, word s_version) return qe_invalid; return 0; } -int32_t SW_CurrentItem::write(PACKFILE *f) const +int32_t SW_ItemSlot::write(PACKFILE *f) const { if(auto ret = SubscrWidget::write(f)) return ret; if(!p_iputl(iclass,f)) new_return(1); if(!p_iputl(iid,f)) - new_return(2); + new_return(1); return 0; } @@ -2083,11 +2327,11 @@ int32_t SW_TriFrame::write(PACKFILE *f) const if(!p_iputl(frame_tile,f)) new_return(1); if(!p_iputl(piece_tile,f)) - new_return(2); + new_return(1); if(!p_putc(frame_cset,f)) - new_return(3); + new_return(1); if(!p_putc(piece_cset,f)) - new_return(4); + new_return(1); if(auto ret = c_outline.write(f)) return ret; if(auto ret = c_number.write(f)) @@ -2166,9 +2410,9 @@ int32_t SW_McGuffin::write(PACKFILE *f) const if(!p_iputl(tile,f)) new_return(1); if(!p_iputl(number,f)) - new_return(2); + new_return(1); if(!p_putc(cset,f)) - new_return(3); + new_return(1); if(auto ret = cs.write(f)) return ret; return 0; @@ -2241,7 +2485,7 @@ int32_t SW_TileBlock::write(PACKFILE *f) const if(!p_iputl(tile,f)) new_return(1); if(!p_putc(flip,f)) - new_return(2); + new_return(1); if(auto ret = cs.write(f)) return ret; return 0; @@ -2361,11 +2605,11 @@ int32_t SW_MiniTile::write(PACKFILE *f) const if(!p_iputl(tile,f)) new_return(1); if(!p_iputl(special_tile,f)) - new_return(2); + new_return(1); if(!p_putc(crn,f)) - new_return(3); + new_return(1); if(!p_putc(flip,f)) - new_return(4); + new_return(1); if(auto ret = cs.write(f)) return ret; return 0; @@ -2407,12 +2651,12 @@ void SW_Selector::draw(BITMAP* dest, int32_t xofs, int32_t yofs, SubscrPage& pag if(!widg) return; bool big_sel=flags&SUBSCR_SELECTOR_LARGE; - item *tempsel=(flags&SUBSCR_SELECTOR_USEB)?sel_b:sel_a; - int32_t temptile=tempsel->tile; - tempsel->drawstyle=0; - - if(flags&SUBSCR_SELECTOR_TRANSP) - tempsel->drawstyle=1; + item tempsel(0,0,0,(flags&SUBSCR_SELECTOR_USEB)?iSelectB:iSelectA,0,0,true); + tempsel.hide_hitbox = true; + tempsel.yofs = 0; + dummyitem_animate(&tempsel,subscr_item_clk); + if(!tempsel.tile) return; + tempsel.drawstyle = (flags&SUBSCR_SELECTOR_TRANSP) ? 1 : 0; int32_t id = widg->getItemVal(); itemdata const& tmpitm = itemsbuf[id]; bool oldsel = get_qr(qr_SUBSCR_OLD_SELECTOR); @@ -2421,28 +2665,28 @@ void SW_Selector::draw(BITMAP* dest, int32_t xofs, int32_t yofs, SubscrPage& pag int sxofs, syofs, dxofs, dyofs; if(oldsel) { - sw = (tempsel->extend > 2 ? tempsel->txsz*16 : 16); - sh = (tempsel->extend > 2 ? tempsel->txsz*16 : 16); + sw = (tempsel.extend > 2 ? tempsel.txsz*16 : 16); + sh = (tempsel.extend > 2 ? tempsel.txsz*16 : 16); sxofs = 0; syofs = 0; - dw = (tempsel->extend > 2 ? tempsel->txsz*16 : 16); - dh = (tempsel->extend > 2 ? tempsel->txsz*16 : 16); - dxofs = (tempsel->extend > 2 ? (int)tempsel->xofs : 0); - dyofs = (tempsel->extend > 2 ? (int)tempsel->yofs : 0); + dw = (tempsel.extend > 2 ? tempsel.txsz*16 : 16); + dh = (tempsel.extend > 2 ? tempsel.txsz*16 : 16); + dxofs = (tempsel.extend > 2 ? (int)tempsel.xofs : 0); + dyofs = (tempsel.extend > 2 ? (int)tempsel.yofs : 0); } else { - sw = (tempsel->extend > 2 ? tempsel->hit_width : 16); - sh = (tempsel->extend > 2 ? tempsel->hit_height : 16); - sxofs = (tempsel->extend > 2 ? tempsel->hxofs : 0); - syofs = (tempsel->extend > 2 ? tempsel->hyofs : 0); + sw = (tempsel.extend > 2 ? tempsel.hit_width : 16); + sh = (tempsel.extend > 2 ? tempsel.hit_height : 16); + sxofs = (tempsel.extend > 2 ? tempsel.hxofs : 0); + syofs = (tempsel.extend > 2 ? tempsel.hyofs : 0); } if(widg->getType() == widgITEMSLOT) { dw = ((tmpitm.overrideFLAGS & itemdataOVERRIDE_HIT_WIDTH) ? tmpitm.hxsz : 16); dh = ((tmpitm.overrideFLAGS & itemdataOVERRIDE_HIT_HEIGHT) ? tmpitm.hysz : 16); - dxofs = widg->getX()+((tmpitm.overrideFLAGS & itemdataOVERRIDE_HIT_X_OFFSET) ? tmpitm.hxofs : 0) + (tempsel->extend > 2 ? (int)tempsel->xofs : 0); - dyofs = widg->getY()+((tmpitm.overrideFLAGS & itemdataOVERRIDE_HIT_Y_OFFSET) ? tmpitm.hyofs : 0) + (tempsel->extend > 2 ? (int)tempsel->yofs : 0); + dxofs = widg->getX()+((tmpitm.overrideFLAGS & itemdataOVERRIDE_HIT_X_OFFSET) ? tmpitm.hxofs : 0) + (tempsel.extend > 2 ? (int)tempsel.xofs : 0); + dyofs = widg->getY()+((tmpitm.overrideFLAGS & itemdataOVERRIDE_HIT_Y_OFFSET) ? tmpitm.hyofs : 0) + (tempsel.extend > 2 ? (int)tempsel.yofs : 0); } else { @@ -2455,23 +2699,20 @@ void SW_Selector::draw(BITMAP* dest, int32_t xofs, int32_t yofs, SubscrPage& pag for(int32_t j=0; j<4; ++j) { clear_bitmap(tmpbmp); - tempsel->x=0; - tempsel->y=0; + tempsel.x=0; + tempsel.y=0; + tempsel.draw(tmpbmp); + tempsel.tile+=zc_max(itemsbuf[tempsel.id].frames,1); + int32_t tmpx = xofs+(big_sel?(j%2?8:-8):0); int32_t tmpy = yofs+(big_sel?(j>1?8:-8):0); - tempsel->tile+=(zc_max(itemsbuf[tempsel->id].frames,1)*j); - - if(temptile) - { - tempsel->drawzcboss(tmpbmp); - tempsel->tile=temptile; - } masked_stretch_blit(tmpbmp, dest, vbound(sxofs, 0, sw), vbound(syofs, 0, sh), sw-vbound(sxofs, 0, sw), sh-vbound(syofs, 0, sh), tmpx+dxofs, tmpy+dyofs, dw, dh); if(!big_sel) break; } destroy_bitmap(tmpbmp); + tempsel.unget_UID(); } SubscrWidget* SW_Selector::clone() const { @@ -2520,9 +2761,9 @@ bool SW_LifeGaugePiece::load_old(subscreen_object const& old) SETFLAG(flags, SUBSCR_LGAUGE_MOD3, old.d10&0x04); SETFLAG(flags, SUBSCR_LGAUGE_MOD4, old.d10&0x08); SETFLAG(flags, SUBSCR_LGAUGE_UNQLAST, old.d10&0x10); - frames = old.d6; - speed = old.d7; - delay = old.d8; + frames = 1; + speed = 0; + delay = 0; container = old.d1; return true; } @@ -2540,12 +2781,58 @@ byte SW_LifeGaugePiece::getType() const } void SW_LifeGaugePiece::draw(BITMAP* dest, int32_t xofs, int32_t yofs, SubscrPage& page) const { - lifegauge(dest, x, y, container, - mts[0].tilecrn, mts[0].cset, flags&SUBSCR_LGAUGE_MOD1, - mts[1].tilecrn, mts[1].cset, flags&SUBSCR_LGAUGE_MOD2, - mts[2].tilecrn, mts[2].cset, flags&SUBSCR_LGAUGE_MOD3, - mts[3].tilecrn, mts[3].cset, flags&SUBSCR_LGAUGE_MOD4, - frames, speed, delay, flags&SUBSCR_LGAUGE_UNQLAST); + if(replay_version_check(0,19)) + { + zc_oldrand();zc_oldrand();zc_oldrand(); + } + + int32_t containers=game->get_maxlife()/game->get_hp_per_heart(); + int32_t tile, cset; + bool mod_value; + + int ind = 3; + if(containercontainers+1) + + int mtile=mts[ind].tilecrn; + cset=mts[ind].cset; + mod_value=(flags&(SUBSCR_LGAUGE_MOD1<>2; + + int hp_ofs = 0; + if(mod_value) //Change the tile based on HP + { + if(game->get_life()>=container*game->get_hp_per_heart()) + { + if((flags&SUBSCR_LGAUGE_UNQLAST) && game->get_life()==container*game->get_hp_per_heart()) + hp_ofs=game->get_hp_per_heart()+3; + } + else + { + if(((container-1)*game->get_hp_per_heart())>game->get_life()) + hp_ofs=4; + else + hp_ofs=4+((game->get_life()-((container-1)*game->get_hp_per_heart()))%game->get_hp_per_heart()); + } + } + + int anim_offs = 0; + int fr = frames ? frames : 1; + int spd = speed ? speed : 1; + // if(fr > 1) + // { + // auto t = (subscritem_frame%((spd*fr)+(spd*delay)))-(delay*spd); + // if(t > -1) + // anim_offs = t/spd; + // } + int offs = (hp_ofs*fr)+anim_offs; + + overtile8(dest,mtile+offs,x,y,cset,0); } SubscrWidget* SW_LifeGaugePiece::clone() const { @@ -2594,11 +2881,11 @@ int32_t SW_LifeGaugePiece::write(PACKFILE *f) const if(!p_iputw(frames, f)) new_return(1); if(!p_iputw(speed, f)) - new_return(2); + new_return(1); if(!p_iputw(delay, f)) - new_return(3); + new_return(1); if(!p_iputw(container, f)) - new_return(4); + new_return(1); return 0; } @@ -2701,13 +2988,13 @@ int32_t SW_MagicGaugePiece::write(PACKFILE *f) const if(!p_iputw(frames, f)) new_return(1); if(!p_iputw(speed, f)) - new_return(2); + new_return(1); if(!p_iputw(delay, f)) - new_return(3); + new_return(1); if(!p_iputw(container, f)) - new_return(4); + new_return(1); if(!p_iputw(showdrain, f)) - new_return(5); + new_return(1); return 0; } @@ -2793,13 +3080,13 @@ int32_t SW_TextBox::write(PACKFILE *f) const if(!p_iputl(fontid,f)) new_return(1); if(!p_putc(align,f)) - new_return(2); + new_return(1); if(!p_putc(shadtype,f)) - new_return(3); + new_return(1); if(!p_putc(tabsize,f)) - new_return(4); + new_return(1); if(!p_putwstr(text,f)) - new_return(5); + new_return(1); if(auto ret = c_text.write(f)) return ret; if(auto ret = c_shadow.write(f)) @@ -2842,7 +3129,7 @@ void SW_SelectedText::draw(BITMAP* dest, int32_t xofs, int32_t yofs, SubscrPage& str = widg->override_text; else { - int32_t itemid=widg->getItemVal(true); + int32_t itemid=widg->getDisplayItem(); if(itemid > -1) { // If it's a combined bow and arrow, the item ID will have 0xF000 added. @@ -2851,16 +3138,22 @@ void SW_SelectedText::draw(BITMAP* dest, int32_t xofs, int32_t yofs, SubscrPage& itemid&=~0xF000; #if IS_PLAYER - // 0 can mean either the item with index 0 is selected or there's no - // valid item to select, so be sure Hero has whatever it would be. - if(!game->get_item(itemid)) + if(replay_version_check(0,19) && !game->get_item(itemid)) return; #endif itemdata const& itm = itemsbuf[itemid]; - str = itm.get_name(); - if(bowarrow) - str = "Bow & " + str; + str = itm.get_name(false,itm.family==itype_arrow && !bowarrow); + if(widg->getType() == widgITEMSLOT && (widg->flags&SUBSCR_CURITM_IGNR_SP_SELTEXT)) + { + //leave the name as-is + } + else if(QMisc.colors.HCpieces_tile && itemid == iHCPiece) + { + int hcpphc = game->get_hcp_per_hc(); + int numhpc = vbound(game->get_HCpieces(),0,hcpphc > 0 ? hcpphc-1 : 0); + str = fmt::format("{}/{} {}{}", numhpc, hcpphc, str, hcpphc==1?"":"s"); + } } } if(str.size()) @@ -2914,11 +3207,11 @@ int32_t SW_SelectedText::write(PACKFILE *f) const if(!p_iputl(fontid,f)) new_return(1); if(!p_putc(align,f)) - new_return(2); + new_return(1); if(!p_putc(shadtype,f)) - new_return(3); + new_return(1); if(!p_putc(tabsize,f)) - new_return(4); + new_return(1); if(auto ret = c_text.write(f)) return ret; if(auto ret = c_shadow.write(f)) @@ -2964,7 +3257,7 @@ SubscrWidget* SubscrWidget::fromOld(subscreen_object const& old) case ssoCLEAR: return new SW_Clear(old); case ssoCURRENTITEM: - return new SW_CurrentItem(old); + return new SW_ItemSlot(old); case ssoTRIFRAME: return new SW_TriFrame(old); case ssoMCGUFFIN: @@ -3069,7 +3362,7 @@ SubscrWidget* SubscrWidget::newType(byte ty) widg = new SW_Clear(); break; case widgITEMSLOT: - widg = new SW_CurrentItem(); + widg = new SW_ItemSlot(); break; case widgMCGUFF_FRAME: widg = new SW_TriFrame(); @@ -3102,11 +3395,9 @@ SubscrWidget* SubscrWidget::newType(byte ty) return widg; } +//For moving on the subscreen. Never called with 'VERIFY' options, so don't worry about them. void SubscrPage::move_cursor(int dir, bool item_only) { - //what will be returned when all else fails. - //don't return the forbiddenpos... no matter what -DD - // verify startpos if(cursor_pos < 0 || cursor_pos >= 0xFF) cursor_pos = 0; @@ -3114,17 +3405,9 @@ void SubscrPage::move_cursor(int dir, bool item_only) auto& objects = contents; item_only = item_only || !get_qr(qr_FREEFORM_SUBSCREEN_CURSOR); - bool verify = dir==SEL_VERIFY_RIGHT || dir==SEL_VERIFY_LEFT; - if(verify) - { - SubscrWidget* widg = get_widg_pos(cursor_pos,item_only); - if(widg && widg->getType() == widgITEMSLOT - && (widg->flags & SUBSCRFLAG_SELECTABLE) - && !(widg->flags & SUBSCR_CURITM_NONEQP) - && widg->getItemVal() > -1) - return; - } + if(dir==SEL_VERIFY_RIGHT || dir==SEL_VERIFY_LEFT) + return; int32_t p=-1; int32_t curpos = cursor_pos; @@ -3206,21 +3489,21 @@ void SubscrPage::move_cursor(int dir, bool item_only) } } } -int32_t SubscrPage::move_legacy(int dir, int startp, int fp, int fp2, int fp3, bool equip_only, bool item_only) +int32_t SubscrPage::movepos_legacy(int dir, word startp, word fp, word fp2, word fp3, bool equip_only, bool item_only) { //what will be returned when all else fails. //don't return the forbiddenpos... no matter what -DD - int32_t failpos(0); - - if(startp == fp || startp == fp2 || startp == fp3) + bool start_empty = (startp&0xFF)==0xFF; + if(start_empty) + { + failpos = startp; + startp = 0; + } + else if(startp == fp || startp == fp2 || startp == fp3) failpos = 0xFF; else failpos = startp; - // verify startpos - if(startp < 0 || startp >= 0xFF) - startp = 0; - auto& objects = contents; item_only = item_only || !get_qr(qr_FREEFORM_SUBSCREEN_CURSOR); @@ -3228,18 +3511,21 @@ int32_t SubscrPage::move_legacy(int dir, int startp, int fp, int fp2, int fp3, b if(verify) { - equip_only = item_only = true; + equip_only = true; + item_only = !get_qr(qr_NO_BUTTON_VERIFY); + if(start_empty && !item_only) + return startp; //empty is valid if(startp != fp && startp != fp2 && startp != fp3) - if(SubscrWidget* widg = get_widg_pos(startp,item_only)) - { - if(widg->getType() == widgITEMSLOT && !(widg->flags&SUBSCR_CURITM_NONEQP) - && widg->getItemVal() > -1) - return startp; - } + if(SubscrWidget* widg = get_widg_pos(startp>>8,item_only)) + if(widg->getType() == widgITEMSLOT + && !(widg->flags&SUBSCR_CURITM_NONEQP) + && (widg->flags & SUBSCRFLAG_SELECTABLE) + && (!item_only || widg->getItemVal() > -1)) + return startp; //Valid selectable slot } int32_t p=-1; - int32_t curpos = startp; + int32_t curpos = startp>>8; int32_t firstValidPos=-1, firstValidEquipPos=-1; for(int32_t i=0; i < contents.size(); ++i) @@ -3265,9 +3551,9 @@ int32_t SubscrPage::move_legacy(int dir, int startp, int fp, int fp2, int fp3, b // Switch to a valid weapon if there is one; otherwise, // the selector can simply disappear if(firstValidEquipPos>=0) - return contents[firstValidEquipPos]->pos; + return (contents[firstValidEquipPos]->pos<<8)|index; if(firstValidPos>=0) - return contents[firstValidPos]->pos; + return (contents[firstValidPos]->pos<<8)|index; //FAILURE else return failpos; } @@ -3322,26 +3608,30 @@ int32_t SubscrPage::move_legacy(int dir, int startp, int fp, int fp2, int fp3, b //Valid stop point? if(widg->flags & SUBSCRFLAG_SELECTABLE) if(curpos != fp && curpos != fp2 && curpos != fp3) - if(!equip_only || !(widg->flags & SUBSCR_CURITM_NONEQP)) + if(!equip_only || widg->getType()!=widgITEMSLOT || !(widg->flags & SUBSCR_CURITM_NONEQP)) if(!item_only || widg->getItemVal()>-1) - return curpos; + return (curpos<<8)|index; } } -SubscrWidget* SubscrPage::get_widg_pos(int32_t pos, bool item_only) +void SubscrPage::move_legacy(int dir, bool equip_only, bool item_only) +{ + cursor_pos = movepos_legacy(dir,(cursor_pos<<8)|index,255,255,255,equip_only,item_only); +} +SubscrWidget* SubscrPage::get_widg_pos(byte pos, bool item_only) { for(size_t q = 0; q < contents.size(); ++q) { if(!(contents[q]->flags & SUBSCRFLAG_SELECTABLE)) continue; if (item_only && contents[q]->getType() == widgITEMSLOT) - if (static_cast(contents[q])->flags & SUBSCR_CURITM_NONEQP) + if (static_cast(contents[q])->flags & SUBSCR_CURITM_NONEQP) continue; if(contents[q]->pos == pos) return contents[q]; } return nullptr; } -int32_t SubscrPage::get_item_pos(int32_t pos, bool item_only) +int32_t SubscrPage::get_item_pos(byte pos, bool item_only) { auto* w = get_widg_pos(pos,item_only); if(w) @@ -3356,7 +3646,7 @@ int32_t SubscrPage::get_sel_item(bool display) { auto* w = get_sel_widg(); if(w) - return w->getItemVal(display); + return display ? w->getDisplayItem() : w->getItemVal(); return -1; } int32_t SubscrPage::get_pos_of_item(int32_t id) @@ -3368,6 +3658,7 @@ int32_t SubscrPage::get_pos_of_item(int32_t id) } return -1; } + SubscrWidget* SubscrPage::get_widget(int indx) { if(unsigned(indx) >= contents.size()) @@ -3375,6 +3666,29 @@ SubscrWidget* SubscrPage::get_widget(int indx) return contents[indx]; } +void SubscrPage::delete_widg(word ind) +{ + if(ind >= contents.size()) + return; + for(auto it = contents.begin(); it != contents.end();) + { + if(ind--) ++it; + else + { + it = contents.erase(it); + break; + } + } + //curr_subscreen_object is handled outside of here +} +void SubscrPage::swap_widg(word ind1, word ind2) +{ + if(ind1 >= contents.size() || ind2 >= contents.size()) + return; + zc_swap(contents[ind1],contents[ind2]); + //curr_subscreen_object is handled outside of here +} + void SubscrPage::clear() { cursor_pos = 0; @@ -3396,6 +3710,7 @@ void SubscrPage::swap(SubscrPage& other) contents.swap(other.contents); zc_swap(cursor_pos,other.cursor_pos); zc_swap(init_cursor_pos,other.init_cursor_pos); + zc_swap(index,other.index); } SubscrPage::~SubscrPage() { @@ -3438,13 +3753,17 @@ int32_t SubscrPage::write(PACKFILE *f) const new_return(1); word sz = zc_min(65535,contents.size()); if(!p_iputw(sz,f)) - new_return(2); + new_return(1); for(word q = 0; q < sz; ++q) if(auto ret = contents[q]->write(f)) return ret; return 0; } +word SubscrPage::getIndex() const +{ + return index; +} SubscrPage& ZCSubscreen::cur_page() { @@ -3458,58 +3777,68 @@ SubscrPage* ZCSubscreen::get_page(byte id) if(id >= pages.size()) return nullptr; return &pages[id]; } -bool ZCSubscreen::get_page_pos(int32_t itmid, byte& pg, byte& pos) +bool ZCSubscreen::get_page_pos(int32_t itmid, word& pgpos) { for(byte q = 0; q < pages.size(); ++q) { - int p = pages[q].get_pos_of_item(itmid); + byte p = pages[q].get_pos_of_item(itmid); if(p > -1) { - pg = q; - pos = p; + pgpos = q | (p<<8); return true; } } + pgpos = 255; return false; } -int32_t ZCSubscreen::get_item_pos(byte pos, byte pg) +int32_t ZCSubscreen::get_item_pos(word pgpos) { - if(pg >= pages.size()) return -1; - return pages[pg].get_item_pos(pos, false); + if(pgpos&0xFF >= pages.size()) return -1; + return pages[pgpos&0xFF].get_item_pos(pgpos>>8, false); } void ZCSubscreen::delete_page(byte id) { if(id >= pages.size()) return; if(pages.size()==1) + { pages[0].clear(); + pages[0].index = 0; + } else { if(curpage >= id) --curpage; - for(auto it = pages.begin(); it != pages.end(); ++it) + for(int q = 0; q < 4; ++q) { - if(id-- == 0) - { - pages.erase(it); - break; - } + if((def_btns[q]&0xFF) > id) + --def_btns[q]; + else if((def_btns[q]&0xFF) == id) + def_btns[q] = 255; + } + auto ind = 0; + for(auto it = pages.begin(); it != pages.end();) + { + if(ind < id) + ++it; + else if(ind == id) + it = pages.erase(it); + else it->index--; + ++ind; } } } void ZCSubscreen::add_page(byte id) { if(id >= pages.size()) - { - pages.emplace_back(); - curpage = pages.size()-1; - } - else - { - pages.emplace_back(); - for(byte ind = pages.size()-1; ind > id; --ind) - swap_pages(ind,ind-1); - } + id = pages.size()-1; //add new page at end + if(id >= MAX_SUBSCR_PAGES) //no more room! + return; + auto& pg = pages.emplace_back(); + pg.index = pages.size()-1; + for(byte ind = pages.size()-1; ind > id; --ind) + swap_pages(ind,ind-1); + curpage = id; } void ZCSubscreen::swap_pages(byte ind1, byte ind2) { @@ -3518,6 +3847,13 @@ void ZCSubscreen::swap_pages(byte ind1, byte ind2) pages[ind1].swap(pages[ind2]); if(curpage == ind1) curpage = ind2; else if(curpage == ind2) curpage = ind1; + for(int q = 0; q < 4; ++q) + { + if((def_btns[q]&0xFF) == ind1) + def_btns[q] = (def_btns[q]&0xFF00)|ind2; + else if((def_btns[q]&0xFF) == ind2) + def_btns[q] = (def_btns[q]&0xFF00)|ind1; + } } void ZCSubscreen::clear() { @@ -3537,6 +3873,7 @@ void ZCSubscreen::load_old(subscreen_group const& g) sub_type = g.ss_type; pages.clear(); SubscrPage& p = pages.emplace_back(); + p.index = 0; for(int ind = 0; ind < MAXSUBSCREENITEMS && g.objects[ind].type != ssoNULL; ++ind) { auto* w = SubscrWidget::fromOld(g.objects[ind]); @@ -3548,6 +3885,7 @@ void ZCSubscreen::load_old(subscreen_object const* arr) { pages.clear(); SubscrPage& p = pages.emplace_back(); + p.index = 0; for(int ind = 0; ind < MAXSUBSCREENITEMS && arr[ind].type != ssoNULL; ++ind) { SubscrWidget* w = SubscrWidget::fromOld(arr[ind]); @@ -3566,6 +3904,9 @@ int32_t ZCSubscreen::read(PACKFILE *f, word s_version) return qe_invalid; if(!p_getc(&sub_type,f)) return qe_invalid; + for(int q = 0; q < 4; ++q) + if(!p_igetw(&def_btns[q],f)) + return qe_invalid; if(!p_igetw(&script,f)) return qe_invalid; if(script) @@ -3581,6 +3922,7 @@ int32_t ZCSubscreen::read(PACKFILE *f, word s_version) for(byte q = 0; q < pagecnt; ++q) { SubscrPage& pg = pages.emplace_back(); + pg.index = pages.size()-1; if(auto ret = pg.read(f, s_version)) return ret; } @@ -3591,18 +3933,21 @@ int32_t ZCSubscreen::write(PACKFILE *f) const if(!p_putcstr(name,f)) new_return(1); if(!p_putc(sub_type,f)) - new_return(2); + new_return(1); + for(int q = 0; q < 4; ++q) + if(!p_iputw(def_btns[q],f)) + new_return(1); if(!p_iputw(script,f)) - new_return(3); + new_return(1); if(script) { for(int q = 0; q < 8; ++q) if(!p_iputl(initd[q],f)) - new_return(4); + new_return(1); } byte pagecnt = zc_min(255,pages.size()); if(!p_putc(pagecnt,f)) - new_return(5); + new_return(1); for(byte q = 0; q < pagecnt; ++q) if(auto ret = pages[q].write(f)) return ret; diff --git a/src/new_subscr.h b/src/new_subscr.h index 008175290b..b3e0bdbe17 100644 --- a/src/new_subscr.h +++ b/src/new_subscr.h @@ -12,6 +12,8 @@ struct PACKFILE; #define NEG_OR_MASK(v,mask) (v < 0 ? v : (v&mask)) +extern int subscr_item_clk; + //Old subscreen stuff struct subscreen_object { @@ -217,6 +219,8 @@ struct SubscrWidget dword flags; //if SUBSCRFLAG_SELECTABLE... + //...storing these as ints, but they could probably be bytes? + //...might expand size later, so I'll leave it as ints. int32_t pos; int32_t pos_up; int32_t pos_down; @@ -240,7 +244,8 @@ struct SubscrWidget virtual int16_t getXOffs() const; //Returns any special x-offset virtual int16_t getYOffs() const; //Returns any special y-offset virtual byte getType() const; - virtual int32_t getItemVal(bool display = false) const; + virtual int32_t getItemVal() const; + virtual int32_t getDisplayItem() const; virtual void draw(BITMAP* dest, int32_t xofs, int32_t yofs, SubscrPage& page) const; virtual bool visible(byte pos, bool showtime) const; virtual SubscrWidget* clone() const; @@ -571,20 +576,23 @@ struct SW_Clear : public SubscrWidget virtual int32_t read(PACKFILE *f, word s_version) override; }; -#define SUBSCR_CURITM_INVIS SUBSCRFLAG_SPEC_01 -#define SUBSCR_CURITM_NONEQP SUBSCRFLAG_SPEC_02 -struct SW_CurrentItem : public SubscrWidget +#define SUBSCR_CURITM_INVIS SUBSCRFLAG_SPEC_01 +#define SUBSCR_CURITM_NONEQP SUBSCRFLAG_SPEC_02 +#define SUBSCR_CURITM_IGNR_SP_SELTEXT SUBSCRFLAG_SPEC_03 +#define SUBSCR_CURITM_IGNR_SP_DISPLAY SUBSCRFLAG_SPEC_04 +struct SW_ItemSlot : public SubscrWidget { int32_t iclass, iid; - SW_CurrentItem() = default; - SW_CurrentItem(subscreen_object const& old); + SW_ItemSlot() = default; + SW_ItemSlot(subscreen_object const& old); virtual bool load_old(subscreen_object const& old) override; virtual word getW() const override; //Returns width in pixels virtual word getH() const override; //Returns height in pixels virtual byte getType() const override; - virtual int32_t getItemVal(bool display = false) const override; + virtual int32_t getItemVal() const override; + virtual int32_t getDisplayItem() const override; virtual void draw(BITMAP* dest, int32_t xofs, int32_t yofs, SubscrPage& page) const override; virtual SubscrWidget* clone() const override; virtual bool copy_prop(SubscrWidget const* src, bool all = false) override; @@ -713,6 +721,7 @@ struct SW_Selector : public SubscrWidget #define SUBSCR_LGAUGE_MOD3 SUBSCRFLAG_SPEC_03 #define SUBSCR_LGAUGE_MOD4 SUBSCRFLAG_SPEC_04 #define SUBSCR_LGAUGE_UNQLAST SUBSCRFLAG_SPEC_05 +#define SUBSCR_LGAUGE_FULLTILE SUBSCRFLAG_SPEC_06 struct SW_LifeGaugePiece : public SubscrWidget { SubscrMTInfo mts[4]; @@ -800,21 +809,25 @@ struct SW_SelectedText : public SubscrWidget virtual int32_t read(PACKFILE *f, word s_version) override; }; -#define MAX_SUBSCR_PAGES 50 +#define MAX_SUBSCR_PAGES 254 struct SubscrPage { std::vector contents; int32_t cursor_pos, init_cursor_pos; void move_cursor(int dir, bool item_only = false); - int32_t move_legacy(int dir, int startp, int fp=-1, int fp2=-1, int fp3=-1, bool equip_only=true, bool item_only=true); - SubscrWidget* get_widg_pos(int32_t pos, bool item_only); + int32_t movepos_legacy(int dir, word startp, word fp = 255, word fp2 = 255, word fp3 = 255, bool equip_only=true, bool item_only=true); + void move_legacy(int dir, bool equip_only=true, bool item_only=true); + SubscrWidget* get_widg_pos(byte pos, bool item_only); SubscrWidget* get_sel_widg(); - int32_t get_item_pos(int32_t pos, bool item_only = true); + int32_t get_item_pos(byte pos, bool item_only = true); int32_t get_sel_item(bool display = false); int32_t get_pos_of_item(int32_t itemid); SubscrWidget* get_widget(int indx); + void delete_widg(word ind); + //add_widg? + void swap_widg(word ind1, word ind2); void clear(); void draw(BITMAP* dest, int32_t xofs, int32_t yofs, byte pos, bool showtime); void swap(SubscrPage& other); @@ -826,6 +839,11 @@ struct SubscrPage int32_t read(PACKFILE *f, word s_version); int32_t write(PACKFILE *f) const; + + word getIndex() const; +private: + word index; + friend struct ZCSubscreen; }; struct ZCSubscreen { @@ -833,14 +851,17 @@ struct ZCSubscreen byte curpage, sub_type; std::string name; + word def_btns[4]={255,255,255,255}; + //!TODO Subscreen Scripts word script; int32_t initd[8]; + SubscrPage& cur_page(); SubscrPage* get_page(byte ind); - bool get_page_pos(int32_t itmid, byte& pg, byte& pos); - int32_t get_item_pos(byte pos, byte pg); + bool get_page_pos(int32_t itmid, word& pgpos); + int32_t get_item_pos(word pgpos); void delete_page(byte ind); void add_page(byte ind); void swap_pages(byte ind1, byte ind2); diff --git a/src/subscr.cpp b/src/subscr.cpp index b16a6190c7..792d5fbafd 100644 --- a/src/subscr.cpp +++ b/src/subscr.cpp @@ -31,7 +31,7 @@ bool show_subscreen_items=true; bool show_subscreen_life=true; bool new_sel=false; -extern sprite_list guys, items, Ewpns, Lwpns, Sitems, chainlinks, decorations; +extern sprite_list guys, items, Ewpns, Lwpns, chainlinks, decorations; extern HeroClass Hero; extern FFScript FFCore; @@ -2759,74 +2759,6 @@ void magicgauge(BITMAP *dest,int32_t x,int32_t y, int32_t container, int32_t not } -void lifegauge(BITMAP *dest,int32_t x,int32_t y, int32_t container, int32_t notlast_tile, int32_t notlast_cset, bool notlast_mod, int32_t last_tile, int32_t last_cset, bool last_mod, - int32_t cap_tile, int32_t cap_cset, bool cap_mod, int32_t aftercap_tile, int32_t aftercap_cset, bool aftercap_mod, int32_t frames, int32_t speed, int32_t delay, bool unique_last) -{ - //these are here to bypass compiler warnings about unused arguments - frames=frames; - speed=speed; - delay=delay; - - int32_t containers=game->get_maxlife()/game->get_hp_per_heart(); - int32_t tile=zc_oldrand()%32767, cset=zc_oldrand()%15; - bool mod_value=(zc_oldrand()%2)!=0; - - if(containercontainers+1) - { - tile=aftercap_tile; - cset=aftercap_cset; - mod_value=aftercap_mod; - } - - if(mod_value) - { - if(game->get_life()>=container*game->get_hp_per_heart()) - { - //tile=tile; //full block - if(game->get_life()==container*game->get_hp_per_heart()) - { - if(unique_last) - { - tile+=game->get_hp_per_heart()+3; - } - } - } - else - { - if(((container-1)*game->get_hp_per_heart())>game->get_life()) - { - tile+=4; //empty block - } - else - { - tile+=4+((game->get_life()-((container-1)*game->get_hp_per_heart()))%game->get_hp_per_heart()); - } - } - } - - overtile8(dest,tile,x,y,cset,0); - -} - - void magicmeter(BITMAP *dest,int32_t x,int32_t y) { if(!get_qr(qr_ENABLEMAGIC)) return; @@ -2915,206 +2847,6 @@ void putxnum(BITMAP *dest,int32_t x,int32_t y,int32_t num,FONT *tempfont,int32_t } */ -/**** Subscr items code ****/ - -item *Bitem = NULL, *Aitem = NULL, *Yitem = NULL, *Xitem = NULL; -int32_t Bid = 0, Aid = 0, Xid = 0, Yid = 0; - -void reset_subscr_items() -{ - if(Aitem) - { - delete Aitem; - Aitem = NULL; - } - - if(Bitem) - { - delete Bitem; - Bitem = NULL; - } - if(Yitem) - { - delete Yitem; - Yitem = NULL; - } - - if(Xitem) - { - delete Xitem; - Xitem = NULL; - } - - Aid = Bid = Yid = Xid = 0; -} - - -void update_subscr_items() -{ - int nullval = get_qr(qr_ITM_0_INVIS_ON_BTNS) ? 0 : -1; - if(Bid != Bwpn) - { - Bid = 0; - - if(Bitem) - { - delete Bitem; - Bitem = NULL; - } - - if(Bwpn > nullval) - { - Bitem = new item((zfix)0, (zfix)0, (zfix)0, Bwpn&0x0FFF, 0, 0); - Bitem->dummy_bool[0]=false; - - switch(itemsbuf[Bwpn&0x0FFF].family) - { - case itype_arrow: - if((Bwpn&0xF000)==0xF000) - { - Bitem->dummy_bool[0]=true; - } - - break; - //default: break; - } - - // Bitem = new item((zfix)(zinit.subscreenyofs = 0; - Bitem->pickup |= ipDUMMY; - } - } - } - - if(Aid != Awpn) - { - Aid = 0; - - if(Aitem) - { - delete Aitem; - Aitem = NULL; - } - - if(Awpn > nullval) - { - Aitem = new item((zfix)0, (zfix)0,(zfix)0,Awpn&0x0FFF, 0, 0); - - switch(itemsbuf[Awpn&0x0FFF].family) - { - case itype_arrow: - if((Awpn&0xF000)==0xF000) - { - Aitem->dummy_bool[0]=true; - } - - break; - //default: break; - } - - if(Aitem != NULL) - { - Aid = Awpn; - Aitem->yofs = 0; - Aitem->pickup |= ipDUMMY; - } - } - } - - if(Xid != Xwpn) - { - Xid = 0; - - if(Xitem) - { - delete Xitem; - Xitem = NULL; - } - - if(Xwpn > nullval) - { - Xitem = new item((zfix)0, (zfix)0,(zfix)0,Xwpn&0x0FFF, 0, 0); - - switch(itemsbuf[Xwpn&0x0FFF].family) - { - case itype_arrow: - if((Xwpn&0xF000)==0xF000) - { - Xitem->dummy_bool[0]=true; - } - - break; - //default: break; - } - - if(Xitem != NULL) - { - Xid = Xwpn; - Xitem->yofs = 0; - Xitem->pickup |= ipDUMMY; - } - } - } - - if(Yid != Ywpn) - { - Yid = 0; - - if(Yitem) - { - delete Yitem; - Yitem = NULL; - } - - if(Ywpn > nullval) - { - Yitem = new item((zfix)0, (zfix)0,(zfix)0,Ywpn&0x0FFF, 0, 0); - - switch(itemsbuf[Ywpn&0x0FFF].family) - { - case itype_arrow: - if((Ywpn&0xF000)==0xF000) - { - Yitem->dummy_bool[0]=true; - } - - break; - //default: break; - } - - if(Yitem != NULL) - { - Yid = Ywpn; - Yitem->yofs = 0; - Yitem->pickup |= ipDUMMY; - } - } - } - - if(Bitem) - Bitem->animate(0); - - if(Aitem) - Aitem->animate(0); - - if(Xitem) - Xitem->animate(0); - - if(Yitem) - Yitem->animate(0); -} - -void add_subscr_item(item *newItem) -{ - //al_trace("Adding a subscreen item, ID: %d\n",newItem->id); //Logging stuff to remove, later. - newItem->subscreenItem=true; - newItem->hide_hitbox=true; - Sitems.add(newItem); -} - /****/ int32_t stripspaces(char *source, char *target, int32_t stop) { @@ -3162,123 +2894,6 @@ int32_t countWeaponWithParent(int32_t id, int32_t type) return count; } -// The conditions on which a subcreen item should be displayed. -bool displaysubscreenitem(int32_t itemtype, int32_t d, int32_t id) -{ - if(game==NULL) //ZQuest - return true; - if (get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN)) return true; - //Okay, so the problem is that remote bombs are getting flagged with misc1 50, because - //current item id is referring to your highest levelled item instead of the actual item. - //Solution here is to have code for override items. - if (id < 0) - { - if((itemtype == itype_bomb && - !(game->get_bombs() - // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. - || (itemsbuf[current_item_id(itype_bomb,replay_version_check(0,19))].misc1==0 && Lwpns.idCount(wLitBomb)>0) - || current_item_power(itype_bombbag))) - || (itemtype == itype_sbomb && - !(game->get_sbombs() - || (itemsbuf[current_item_id(itype_sbomb,replay_version_check(0,19))].misc1==0 && Lwpns.idCount(wLitSBomb)>0) - || (current_item_power(itype_bombbag) - && itemsbuf[current_item_id(itype_bombbag)].flags & ITEM_FLAG1)))) - return false; - - if(itemtype!=itype_bowandarrow || - d!=itype_arrow || - ((get_qr(qr_TRUEARROWS)&&game->get_arrows()) || - (!get_qr(qr_TRUEARROWS)&&game->get_rupies()))) - return true; - - return false; - } - else - { - if((itemtype == itype_bomb && - !(game->get_bombs() - // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. - || (itemsbuf[id].misc1==0 && findWeaponWithParent(id, wLitBomb)) - || current_item_power(itype_bombbag))) - || (itemtype == itype_sbomb && - !(game->get_sbombs() - || (itemsbuf[id].misc1==0 && findWeaponWithParent(id, wLitSBomb)) - || (current_item_power(itype_bombbag) - && itemsbuf[current_item_id(itype_bombbag)].flags & ITEM_FLAG1)))) - return false; - - if(itemtype!=itype_bowandarrow || - d!=itype_arrow || - ((get_qr(qr_TRUEARROWS)&&game->get_arrows()) || - (!get_qr(qr_TRUEARROWS)&&game->get_rupies()))) - return true; - - return false; - } -} - -void subscreenitem(BITMAP *dest, int32_t x, int32_t y, int32_t itemtype) -{ - // We need to do a reverse loop to prevent the Bow from being drawn above the Arrow (Bow & Arrow). - int32_t overridecheck = 0xFFFF; - - for(int32_t i=Sitems.Count()-1; i>=0; i--) - { - if(itemtype & 0x8000) // if 0x8000, then itemtype is actually an item ID. - { - if(overridecheck==0xFFFF) - { - //al_trace("Found an override item at subscreen.cpp linere 3084, id: %d\n",Sitems.spr(i)->id); - if(Sitems.spr(i)->id == (itemtype&0xFFF) && Sitems.spr(i)->misc==-1) - overridecheck = i; - } - } - else if(Sitems.spr(i)->misc!=-1) - { - int32_t d= itemsbuf[Sitems.spr(i)->id].family; - - if((d==itemtype)|| - (itemtype==itype_letterpotion&&((d==itype_letter && current_item_id(itype_potion)==-1)||d==itype_potion))|| - (itemtype==itype_bowandarrow&&(d==itype_bow||d==itype_arrow))) - { - Sitems.spr(i)->x = x; - Sitems.spr(i)->y = y; - Sitems.spr(i)->yofs=0; - - if(displaysubscreenitem(itemtype, d, -1)) - { - Sitems.spr(i)->drawzcboss(dest); - } - - if(itemtype!=itype_bowandarrow) - { - return; - } - } - } - } - - //Item Override stuff here - if((itemtype & 0x8000) && - (get_app_id() == App::zelda ? game->item[itemtype&0xFFF] : true) && - !item_disabled(itemtype&0xFFF) && displaysubscreenitem(itemsbuf[itemtype&0xFFF].family, 0, (itemtype&0xFFF))) - { - if(overridecheck == 0xFFFF) - { - //al_trace("Found an override item at subscreen.cpp linere 3120, itemtype: %d\n",itemtype); - - add_subscr_item(new item((zfix)x,(zfix)y,(zfix)0,(itemtype&0xFFF),0,0)); - overridecheck = Sitems.Count()-1; - Sitems.spr(overridecheck)->misc = -1; - } - - Sitems.spr(overridecheck)->x = x; - Sitems.spr(overridecheck)->y = y; - Sitems.spr(overridecheck)->yofs=0; - Sitems.spr(overridecheck)->drawzcboss(dest); - } -} - int32_t subscreen_color(int32_t c1, int32_t c2) { int32_t ret; @@ -3421,45 +3036,6 @@ int32_t subscreen_cset(int32_t c1, int32_t c2) return ret; } -item *sel_a=NULL, *sel_b=NULL; - -void delete_selectors() -{ - if(sel_a) - { - delete sel_a; - sel_a=NULL; - } - - if(sel_b) - { - delete sel_b; - sel_b=NULL; - } -} - -void animate_selectors() -{ - if(new_sel) - { - delete_selectors(); - new_sel = false; - } - - if(!sel_a) - sel_a = new item((zfix)0, (zfix)0, (zfix)0, iSelectA, 0, 0); - - if(!sel_b) - sel_b = new item((zfix)0, (zfix)0, (zfix)0, iSelectB, 0, 0); - - sel_a->yofs=0; - sel_a->subscreenItem=true; - sel_a->animate(0); - sel_b->yofs=0; - sel_b->subscreenItem=true; - sel_b->animate(0); -} - void show_custom_subscreen(BITMAP *dest, ZCSubscreen* subscr, int32_t xofs, int32_t yofs, bool showtime, int32_t pos2) { if(!subscr) return; @@ -3471,167 +3047,16 @@ void show_custom_subscreen(BITMAP *dest, ZCSubscreen* subscr, int32_t xofs, int3 set_trans_blender(0, 0, 0, 128); #ifdef IS_ZQUEST - bool animate_sel = true; //ZQ needs to always animate -Em - /* ZQ also has no 'advanceframe' to increment the global frame counter, + /* ZQ has no 'advanceframe' to increment the global frame counter, * so we need to increment that here, as flashing items use it for their draw. * -Em - */ + */ //!TODO SUBSCR change this to subscr_item_clk? ++frame; - #else - /* Animating in ZC every frame causes doubled animation speed, due to - * animating both for the passive and active subscreen. - * So, only call it if new selectors are needed. ZC doesn't use 'bool new_sel'. - * -Em - */ - bool animate_sel = !sel_a || !sel_b; #endif - if(animate_sel) - animate_selectors(); subscr->draw(dest,xofs,yofs,pos2,showtime); } -std::string get_subscr_arrow_name(int itemid) -{ - char itemname[256]=""; - if(Bitem && Bitem->dummy_bool[0]==true) //if we also have a bow - { - if(current_item_id(itype_bow)>-1) - { - bool hasarrows=checkmagiccost(itemid); - sprintf(itemname, "%s%s%s", item_string[current_item_id(itype_bow)], hasarrows?" & ":"",hasarrows?item_string[Bitem->id]:""); - } - } - return std::string(itemname); -} - -void buttonitem(BITMAP *dest, int32_t button, int32_t x, int32_t y) -{ - switch(button) - { - case 0: //A button - if(Aitem&&show_subscreen_items) - { - Aitem->x=x; - Aitem->y=y; - Aitem->hide_hitbox = true; - - switch(itemsbuf[Aitem->id].family) - { - case itype_arrow: - if(Aitem->dummy_bool[0]==true) - { - if(current_item_id(itype_bow)>-1) - { - subscreenitem(dest, x, y, itype_bow); - if(get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN)) break; - if(!checkmagiccost(Aitem->id)) return; - } - } - - break; - } - - Aitem->drawzcboss(dest); - } - - break; - - case 1: //B button - if(Bitem&&show_subscreen_items) - { - Bitem->x=x; - Bitem->y=y; - Bitem->hide_hitbox = true; - - switch(itemsbuf[Bitem->id].family) - { - case itype_arrow: - if(Bitem && Bitem->dummy_bool[0]==true) - { - if(current_item_id(itype_bow)>-1) - { - subscreenitem(dest, x, y, itype_bow); - if(get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN)) break; - if(!checkmagiccost(Bitem->id)) return; - } - } - - break; - } - - Bitem->drawzcboss(dest); - } - - break; - - case 2: //X button - if(Xitem&&show_subscreen_items) - { - //Y button - //zprint2("Drawing X Item\n"); - Xitem->x=x; - Xitem->y=y; - Xitem->hide_hitbox = true; - - switch(itemsbuf[Xitem->id].family) - { - case itype_arrow: - if(Xitem && Xitem->dummy_bool[0]==true) - { - if(current_item_id(itype_bow)>-1) - { - subscreenitem(dest, x, y, itype_bow); - if(get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN)) break; - if(!checkmagiccost(Xitem->id)) return; - } - } - - break; - } - - Xitem->drawzcboss(dest); - } - //else zprint2("Xitem is NULL\n"); - - break; - - case 3: - if(Yitem&&show_subscreen_items) - { - //Y button - //zprint2("Drawing Y Item\n"); - Yitem->x=x; - Yitem->y=y; - Yitem->hide_hitbox = true; - - switch(itemsbuf[Yitem->id].family) - { - case itype_arrow: - if(Yitem && Yitem->dummy_bool[0]==true) - { - if(current_item_id(itype_bow)>-1) - { - subscreenitem(dest, x, y, itype_bow); - if(get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN)) break; - if(!checkmagiccost(Yitem->id)) return; - } - } - - break; - } - - Yitem->drawzcboss(dest); - } - //else zprint2("Yitem is NULL\n"); - - break; - - default: - break; - } -} - void defaultcounters(BITMAP *dest, int32_t x, int32_t y, FONT *tempfont, int32_t color, int32_t shadowcolor, int32_t bgcolor, bool usex, int32_t textstyle, int32_t digits, char idigit) { int32_t yofs = (game==NULL || (game->get_sbombs() && current_item_id(itype_sbomb)>-1)) ? 8 : 0; @@ -3839,10 +3264,13 @@ void counter(BITMAP *dest, int32_t x, int32_t y, FONT *tempfont, int32_t color, sprintf(valstring,"01234567890123456789"); sprintf(formatstring, "%%0%dd", digits); - if(onlyselected && !(((Bitem&&(is_counter_item(Bitem->id,itemtype1)||is_counter_item(Bitem->id,itemtype2)||is_counter_item(Bitem->id,itemtype3)))||(Aitem&&(is_counter_item(Aitem->id,itemtype1)||is_counter_item(Aitem->id,itemtype2)||is_counter_item(Aitem->id,itemtype3)))))) - { + if(onlyselected && !( + (Bwpn>-1&&(is_counter_item(Bwpn&0xFF,itemtype1)||is_counter_item(Bwpn&0xFF,itemtype2)||is_counter_item(Bwpn&0xFF,itemtype3))) + || (Awpn>-1&&(is_counter_item(Awpn&0xFF,itemtype1)||is_counter_item(Awpn&0xFF,itemtype2)||is_counter_item(Awpn&0xFF,itemtype3))) + || (Xwpn>-1&&(is_counter_item(Xwpn&0xFF,itemtype1)||is_counter_item(Xwpn&0xFF,itemtype2)||is_counter_item(Xwpn&0xFF,itemtype3))) + || (Ywpn>-1&&(is_counter_item(Ywpn&0xFF,itemtype1)||is_counter_item(Ywpn&0xFF,itemtype2)||is_counter_item(Ywpn&0xFF,itemtype3))) + )) return; - } int32_t itemtype; /* @@ -3967,9 +3395,7 @@ void minimaptitle(BITMAP *dest, int32_t x, int32_t y, FONT *tempfont, int32_t co void put_passive_subscr(BITMAP *dest,int32_t x,int32_t y,bool showtime,int32_t pos2) { - // uncomment this? - // load_Sitems(); - Sitems.animate(); + ++subscr_item_clk; update_subscr_items(); BITMAP *subscr = create_sub_bitmap(dest,x,y,256,passive_subscreen_height); @@ -4342,52 +3768,7 @@ void putBmap(BITMAP *dest, int32_t x, int32_t y,bool showmap, bool showrooms, bo void load_Sitems() { - Sitems.clear(); - - // HC Pieces - if(QMisc.colors.HCpieces_tile) - { - // item *HCP = new item((zfix)(inventory_x[5]-ofs),(zfix)y,MAXITEMS,0,0); - item *HCP = new item((zfix)0,(zfix)0,(zfix)0,iHCPiece,0,0); - - if(HCP) - { - int32_t hcpphc = game->get_hcp_per_hc(); - HCP->tile = QMisc.colors.HCpieces_tile + vbound(game->get_HCpieces(),0,hcpphc > 0 ? hcpphc-1 : 0); - HCP->o_tile = HCP->tile; - HCP->cs = QMisc.colors.HCpieces_cset; - HCP->frames = 0; - add_subscr_item(HCP); - } - } - - if(has_item(itype_map, get_dlevel())) - { - add_subscr_item(new item((zfix)0,(zfix)0,(zfix)0,iMap,0,0)); - } - - if(has_item(itype_compass, get_dlevel())) - { - add_subscr_item(new item((zfix)0,(zfix)0,(zfix)0,iCompass,0,0)); - } - - if(has_item(itype_bosskey, get_dlevel())) - { - add_subscr_item(new item((zfix)0,(zfix)0,(zfix)0,iBossKey,0,0)); - } - - for(int32_t i=0; i-1 && itemsbuf[j].tile) - add_subscr_item(new item((zfix)0, (zfix)0,(zfix)0,j,0,0)); - } - //al_trace("Finished load_Sitems(%d)\n",0); - + subscr_item_clk = 0; new_sel=true; } diff --git a/src/zc/ffscript.cpp b/src/zc/ffscript.cpp index 99cfee074a..6007fe638b 100644 --- a/src/zc/ffscript.cpp +++ b/src/zc/ffscript.cpp @@ -13849,13 +13849,13 @@ void set_register(int32_t arg, int32_t value) //zprint("A is: %d\n", setb); Awpn = seta; - game->awpn = game->awpnpg = 0; + game->awpn = 255; game->forced_awpn = seta; game->items_off[seta] = 0; directItemA = seta; Bwpn = setb; - game->bwpn = game->bwpnpg = 0; + game->bwpn = 255; game->forced_bwpn = setb; game->items_off[setb] = 0; directItemB = setb; @@ -13896,7 +13896,7 @@ void set_register(int32_t arg, int32_t value) case 0: //b Bwpn = itm; game->items_off[itm] = 0; - game->bwpn = game->bwpnpg = 0; + game->bwpn = 255; game->forced_bwpn = itm; directItemB = itm; break; @@ -13904,7 +13904,7 @@ void set_register(int32_t arg, int32_t value) case 1: //a Awpn = itm; game->items_off[itm] = 0; - game->awpn = game->awpnpg = 0; + game->awpn = 255; game->forced_awpn = itm; directItemA = itm; break; @@ -13912,7 +13912,7 @@ void set_register(int32_t arg, int32_t value) case 2: //x Xwpn = itm; game->items_off[itm] = 0; - game->xwpn = game->xwpnpg = 0; + game->xwpn = 255; game->forced_xwpn = itm; directItemX = itm; break; @@ -13920,7 +13920,7 @@ void set_register(int32_t arg, int32_t value) case 3: //y Ywpn = itm; game->items_off[itm] = 0; - game->ywpn = game->ywpnpg = 0; + game->ywpn = 255; game->forced_ywpn = itm; directItemX = itm; break; @@ -13935,7 +13935,7 @@ void set_register(int32_t arg, int32_t value) case 0: //b Bwpn = itm; game->items_off[itm] = 0; - game->bwpn = game->bwpnpg = 0; + game->bwpn = 255; game->forced_bwpn = itm; directItemB = itm; break; @@ -13943,7 +13943,7 @@ void set_register(int32_t arg, int32_t value) case 1: //a Awpn = itm; game->items_off[itm] = 0; - game->awpn = game->awpnpg = 0; + game->awpn = 255; game->forced_awpn = itm; directItemA = itm; break; @@ -13951,7 +13951,7 @@ void set_register(int32_t arg, int32_t value) case 2: //x Xwpn = itm; game->items_off[itm] = 0; - game->xwpn = game->xwpnpg = 0; + game->xwpn = 255; game->forced_xwpn = itm; directItemX = itm; break; @@ -13959,7 +13959,7 @@ void set_register(int32_t arg, int32_t value) case 3: //y Ywpn = itm; game->items_off[itm] = 0; - game->ywpn = game->ywpnpg = 0; + game->ywpn = 255; game->forced_ywpn = itm; directItemY = itm; break; @@ -13973,7 +13973,7 @@ void set_register(int32_t arg, int32_t value) case 0: //b Bwpn = itm; game->items_off[itm] = 0; - game->bwpn = game->bwpnpg = 0; + game->bwpn = 255; game->forced_bwpn = itm; directItemB = itm; break; @@ -13983,7 +13983,7 @@ void set_register(int32_t arg, int32_t value) { Awpn = itm; game->items_off[itm] = 0; - game->awpn = game->awpnpg = 0; + game->awpn = 255; game->forced_awpn = itm; directItemA = itm; } @@ -13992,7 +13992,7 @@ void set_register(int32_t arg, int32_t value) case 2: //x Xwpn = itm; game->items_off[itm] = 0; - game->xwpn = game->xwpnpg = 0; + game->xwpn = 255; game->forced_xwpn = itm; directItemX = itm; break; @@ -14000,7 +14000,7 @@ void set_register(int32_t arg, int32_t value) case 3: //y Ywpn = itm; game->items_off[itm] = 0; - game->ywpn = game->ywpnpg = 0; + game->ywpn = 255; game->forced_ywpn = itm; directItemY = itm; break; @@ -14015,7 +14015,7 @@ void set_register(int32_t arg, int32_t value) case 0: //b Bwpn = itm; game->items_off[itm] = 0; - game->bwpn = game->bwpnpg = 0; + game->bwpn = 255; game->forced_bwpn = itm; directItemB = itm; break; @@ -14025,7 +14025,7 @@ void set_register(int32_t arg, int32_t value) { Awpn = itm; game->items_off[itm] = 0; - game->awpn = game->awpnpg = 0; + game->awpn = 255; game->forced_awpn = itm; directItemA = itm; } @@ -14034,7 +14034,7 @@ void set_register(int32_t arg, int32_t value) case 2: //x Xwpn = itm; game->items_off[itm] = 0; - game->xwpn = game->xwpnpg = 0; + game->xwpn = 255; game->forced_xwpn = itm; directItemX = itm; break; @@ -14042,7 +14042,7 @@ void set_register(int32_t arg, int32_t value) case 3: //y Ywpn = itm; game->items_off[itm] = 0; - game->ywpn = game->ywpnpg = 0; + game->ywpn = 255; game->forced_ywpn = itm; directItemY = itm; break; @@ -14236,7 +14236,7 @@ void set_register(int32_t arg, int32_t value) { Bwpn = value/10000; if(new_subscreen_active) - new_subscreen_active->get_page_pos(Bwpn, game->bwpn, game->bwpnpg); + new_subscreen_active->get_page_pos(Bwpn, game->bwpn); game->forced_bwpn = value/10000; game->items_off[value/10000] = 0; } @@ -14262,7 +14262,7 @@ void set_register(int32_t arg, int32_t value) { Awpn = value/10000; if(new_subscreen_active) - new_subscreen_active->get_page_pos(Awpn, game->awpn, game->awpnpg); + new_subscreen_active->get_page_pos(Awpn, game->awpn); game->items_off[value/10000] = 0; game->forced_awpn = value/10000; } @@ -14287,7 +14287,7 @@ void set_register(int32_t arg, int32_t value) { Xwpn = value/10000; if(new_subscreen_active) - new_subscreen_active->get_page_pos(Xwpn, game->xwpn, game->xwpnpg); + new_subscreen_active->get_page_pos(Xwpn, game->xwpn); game->items_off[value/10000] = 0; game->forced_xwpn = value/10000; } @@ -14311,7 +14311,7 @@ void set_register(int32_t arg, int32_t value) { Ywpn = value/10000; if(new_subscreen_active) - new_subscreen_active->get_page_pos(Ywpn, game->ywpn, game->ywpnpg); + new_subscreen_active->get_page_pos(Ywpn, game->ywpn); game->items_off[value/10000] = 0; game->forced_ywpn = value/10000; } diff --git a/src/zc/hero.cpp b/src/zc/hero.cpp index 98b96490bf..cf88f9df2d 100644 --- a/src/zc/hero.cpp +++ b/src/zc/hero.cpp @@ -10138,48 +10138,57 @@ void HeroClass::solid_push(solid_object* obj) obj->setTempNonsolid(t); } +#define COND_AWPN (get_qr(qr_SELECTAWPN) ? game->awpn : 255) +#define COND_BWPN (game->bwpn) +#define COND_XWPN (get_qr(qr_SET_XBUTTON_ITEMS) ? game->xwpn : 255) +#define COND_YWPN (get_qr(qr_SET_YBUTTON_ITEMS) ? game->ywpn : 255) +//Helper function +static void deselectbombsWPN(word& wpos, int32_t& BTNwpn, int32_t& directItemBTN, + word f1 = 255, word f2 = 255, word f3 = 255) +{ + byte pgn = wpos&0xFF, pos = wpos>>8; + bool empty = pgn==255; + if(empty && get_qr(qr_NO_BUTTON_VERIFY)) return; //intentional nothingness + SubscrPage* pg = new_subscreen_active->get_page(pgn==255?new_subscreen_active->curpage:pgn); + if(!pg) + { + wpos = 255; //set to nothingness + return; + } + + auto temp = pg->movepos_legacy(SEL_VERIFY_LEFT, wpos, f1, f2, f3); + BTNwpn = pg->get_item_pos(temp>>8); + directItemBTN = NEG_OR_MASK(BTNwpn,0xFFF); + wpos = temp; +} // A routine used exclusively by startwpn, // to switch Hero's weapon if his current weapon (bombs) was depleted. void HeroClass::deselectbombs(int32_t super) { if ( get_qr(qr_NEVERDISABLEAMMOONSUBSCREEN) || itemsbuf[game->forced_awpn].family == itype_bomb || itemsbuf[game->forced_bwpn].family == itype_bomb || itemsbuf[game->forced_xwpn].family == itype_bomb || itemsbuf[game->forced_ywpn].family == itype_bomb) return; - SubscrPage* pg = nullptr; - if(getItemFamily(itemsbuf,Bwpn)==(super? itype_sbomb : itype_bomb) && (directWpn<0 || Bwpn==directWpn)) + if(getItemFamily(itemsbuf,Bwpn)==(super? itype_sbomb : itype_bomb) && (directWpn<0 || Bwpn==directWpn)) { - if(!new_subscreen_active || !(pg = new_subscreen_active->get_page(game->bwpnpg))) + if(!new_subscreen_active) return; - int32_t temp = pg->move_legacy(SEL_VERIFY_LEFT, game->bwpn, game->awpn, get_qr(qr_SET_XBUTTON_ITEMS) ? game->xwpn : -1, get_qr(qr_SET_YBUTTON_ITEMS) ? game->ywpn : -1); - Bwpn = pg->get_item_pos(temp); - directItemB = NEG_OR_MASK(Bwpn,0xFFF); - game->bwpn = temp; + deselectbombsWPN(game->bwpn, Bwpn, directItemB, COND_AWPN, COND_XWPN, COND_YWPN); } - else if (getItemFamily(itemsbuf,Xwpn)==(super? itype_sbomb : itype_bomb) && (directWpn<0 || Xwpn==directWpn)) { - if(!new_subscreen_active || !(pg = new_subscreen_active->get_page(game->xwpnpg))) + if(!new_subscreen_active) return; - int32_t temp = pg->move_legacy(SEL_VERIFY_LEFT, game->xwpn, game->bwpn, game->awpn, get_qr(qr_SET_YBUTTON_ITEMS) ? game->ywpn : -1); - Xwpn = pg->get_item_pos(temp); - directItemX = NEG_OR_MASK(Xwpn,0xFFF); - game->xwpn = temp; + deselectbombsWPN(game->xwpn, Xwpn, directItemX, COND_AWPN, COND_BWPN, COND_YWPN); } else if (getItemFamily(itemsbuf,Ywpn)==(super? itype_sbomb : itype_bomb) && (directWpn<0 || Ywpn==directWpn)) { - if(!new_subscreen_active || !(pg = new_subscreen_active->get_page(game->ywpnpg))) + if(!new_subscreen_active) return; - int32_t temp = pg->move_legacy(SEL_VERIFY_LEFT, game->ywpn, game->bwpn, get_qr(qr_SET_XBUTTON_ITEMS) ? game->xwpn : -1, game->awpn); - Ywpn = pg->get_item_pos(temp); - directItemY = NEG_OR_MASK(Ywpn,0xFFF); - game->ywpn = temp; + deselectbombsWPN(game->ywpn, Ywpn, directItemY, COND_AWPN, COND_XWPN, COND_BWPN); } else { - if(!new_subscreen_active || !(pg = new_subscreen_active->get_page(game->awpnpg))) + if(!new_subscreen_active) return; - int32_t temp = pg->move_legacy(SEL_VERIFY_LEFT, game->awpn, game->bwpn, get_qr(qr_SET_XBUTTON_ITEMS) ? game->xwpn : -1, get_qr(qr_SET_YBUTTON_ITEMS) ? game->ywpn : -1); - Awpn = pg->get_item_pos(temp); - directItemA = NEG_OR_MASK(Awpn,0xFFF); - game->awpn = temp; + deselectbombsWPN(game->awpn, Awpn, directItemA, COND_BWPN, COND_XWPN, COND_YWPN); } } @@ -28538,32 +28547,35 @@ bool isItmPressed(int32_t itmid) return false; } -void selectNextAWpn(int32_t type) +//helper function +static void selectNextBTNWpn(int32_t type, word& wpos, int32_t& BTNwpn, + int32_t& directItemBTN, word f1 = 255, word f2 = 255, word f3 = 255) { - if(!get_qr(qr_SELECTAWPN)) - return; if(!new_subscreen_active) return; - SubscrPage* pg = new_subscreen_active->get_page(game->awpnpg); + byte pgn = wpos&0xFF, pos = wpos>>8; + bool empty = pgn==255; + if(empty && get_qr(qr_NO_BUTTON_VERIFY)) return; //intentional nothingness + SubscrPage* pg = new_subscreen_active->get_page(pgn==255?new_subscreen_active->curpage:pgn); if(!pg) return; - int32_t ret = pg->move_legacy(type, game->awpn, game->bwpn, get_qr(qr_SET_XBUTTON_ITEMS) ? game->xwpn : -1, get_qr(qr_SET_YBUTTON_ITEMS) ? game->ywpn : -1); - Awpn = pg->get_item_pos(ret); - directItemA = NEG_OR_MASK(Awpn,0xFFF); - game->awpn = ret; + auto ret = pg->movepos_legacy(type, wpos, f1, f2, f3); + BTNwpn = pg->get_item_pos(ret>>8); + directItemBTN = NEG_OR_MASK(BTNwpn,0xFFF); + wpos = ret; +} +void selectNextAWpn(int32_t type) +{ + if(!get_qr(qr_SELECTAWPN)) + return; + selectNextBTNWpn(type, game->awpn, Awpn, directItemA, COND_BWPN, COND_XWPN, COND_YWPN); } void selectNextBWpn(int32_t type) { if(!new_subscreen_active) return; - SubscrPage* pg = new_subscreen_active->get_page(game->bwpnpg); - if(!pg) - return; - int32_t ret = pg->move_legacy(type, game->bwpn, game->awpn, get_qr(qr_SET_XBUTTON_ITEMS) ? game->xwpn : -1, get_qr(qr_SET_YBUTTON_ITEMS) ? game->ywpn : -1); - Bwpn = pg->get_item_pos(ret); - directItemB = NEG_OR_MASK(Bwpn,0xFFF); - game->bwpn = ret; + selectNextBTNWpn(type, game->bwpn, Bwpn, directItemB, COND_AWPN, COND_XWPN, COND_YWPN); } void selectNextXWpn(int32_t type) @@ -28571,13 +28583,7 @@ void selectNextXWpn(int32_t type) if(!get_qr(qr_SET_XBUTTON_ITEMS)) return; if(!new_subscreen_active) return; - SubscrPage* pg = new_subscreen_active->get_page(game->xwpnpg); - if(!pg) - return; - int32_t ret = pg->move_legacy(type, game->xwpn, game->awpn, game->bwpn, get_qr(qr_SET_YBUTTON_ITEMS) ? game->ywpn : -1); - Xwpn = pg->get_item_pos(ret); - directItemX = NEG_OR_MASK(Xwpn,0xFFF); - game->xwpn = ret; + selectNextBTNWpn(type, game->xwpn, Xwpn, directItemX, COND_BWPN, COND_AWPN, COND_YWPN); } void selectNextYWpn(int32_t type) @@ -28585,13 +28591,26 @@ void selectNextYWpn(int32_t type) if(!get_qr(qr_SET_YBUTTON_ITEMS)) return; if(!new_subscreen_active) return; - SubscrPage* pg = new_subscreen_active->get_page(game->ywpnpg); + selectNextBTNWpn(type, game->ywpn, Ywpn, directItemY, COND_BWPN, COND_XWPN, COND_AWPN); +} + +//helper function +static void verifyWpn(word& wpos, int32_t& BTNwpn, int32_t& directItemBTN, word f1 = 255, word f2 = 255, word f3 = 255) +{ + if(!new_subscreen_active) + return; + byte pgn = wpos&0xFF, pos = wpos>>8; + bool empty = pgn==255; + if(empty && get_qr(qr_NO_BUTTON_VERIFY)) return; //intentional nothingness + SubscrPage* pg = new_subscreen_active->get_page(pgn==255?new_subscreen_active->curpage:pgn); if(!pg) return; - int32_t ret = pg->move_legacy(type, game->ywpn, game->awpn, game->bwpn, get_qr(qr_SET_XBUTTON_ITEMS) ? game->xwpn : -1); - Ywpn = pg->get_item_pos(ret); - directItemY = NEG_OR_MASK(Ywpn,0xFFF); - game->ywpn = ret; + auto fp1 = ((f1&0xFF)==255) ? 255 : ((empty || (f1&0xFF)==(wpos&0xFF)) ? f1>>8 : 255); + auto fp2 = ((f2&0xFF)==255) ? 255 : ((empty || (f2&0xFF)==(wpos&0xFF)) ? f2>>8 : 255); + auto fp3 = ((f3&0xFF)==255) ? 255 : ((empty || (f3&0xFF)==(wpos&0xFF)) ? f3>>8 : 255); + wpos = pg->movepos_legacy(SEL_VERIFY_RIGHT, wpos, fp1, fp2, fp3); + BTNwpn = pg->get_item_pos(wpos>>8); + directItemBTN = NEG_OR_MASK(BTNwpn,0xFFF); } void verifyAWpn() @@ -28601,18 +28620,11 @@ void verifyAWpn() if(!get_qr(qr_SELECTAWPN)) { Awpn = selectSword(); - game->awpn = 0xFF; + game->awpn = 255; } else { - if(!new_subscreen_active) - return; - SubscrPage* pg = new_subscreen_active->get_page(game->awpnpg); - if(!pg) - return; - game->awpn = pg->move_legacy(SEL_VERIFY_RIGHT, game->awpn, game->bwpn, game->xwpn, game->ywpn); - Awpn = pg->get_item_pos(game->awpn); - directItemA = NEG_OR_MASK(Awpn,0xFFF); + verifyWpn(game->awpn, Awpn, directItemA, COND_BWPN, COND_XWPN, COND_YWPN); } } @@ -28620,46 +28632,25 @@ void verifyBWpn() { if (game->forced_bwpn != -1) return; - if(!new_subscreen_active) - return; - SubscrPage* pg = new_subscreen_active->get_page(game->bwpnpg); - if(!pg) - return; - game->bwpn = pg->move_legacy(SEL_VERIFY_RIGHT, game->bwpn, game->awpn, game->xwpn, game->ywpn); - Bwpn = pg->get_item_pos(game->bwpn); - directItemB = NEG_OR_MASK(Bwpn,0xFFF); + verifyWpn(game->bwpn, Bwpn, directItemB, COND_AWPN, COND_XWPN, COND_YWPN); } void verifyXWpn() { if (game->forced_xwpn != -1) return; - if(!new_subscreen_active) - return; - SubscrPage* pg = new_subscreen_active->get_page(game->xwpnpg); - if(!pg) + if(!get_qr(qr_SET_XBUTTON_ITEMS)) return; - if(get_qr(qr_SET_XBUTTON_ITEMS)) - game->xwpn = pg->move_legacy(SEL_VERIFY_RIGHT, game->xwpn, game->awpn, game->bwpn, game->ywpn); - else game->xwpn = -1; - Xwpn = pg->get_item_pos(game->xwpn); - directItemX = NEG_OR_MASK(Xwpn,0xFFF); + verifyWpn(game->xwpn, Xwpn, directItemX, COND_BWPN, COND_AWPN, COND_YWPN); } void verifyYWpn() { if (game->forced_ywpn != -1) return; - if(!new_subscreen_active) - return; - SubscrPage* pg = new_subscreen_active->get_page(game->ywpnpg); - if(!pg) + if(!get_qr(qr_SET_YBUTTON_ITEMS)) return; - if(get_qr(qr_SET_YBUTTON_ITEMS)) - game->ywpn = pg->move_legacy(SEL_VERIFY_RIGHT, game->ywpn, game->awpn, game->xwpn, game->bwpn); - else game->ywpn = -1; - Ywpn = pg->get_item_pos(game->ywpn); - directItemY = NEG_OR_MASK(Ywpn,0xFFF); + verifyWpn(game->ywpn, Ywpn, directItemY, COND_BWPN, COND_XWPN, COND_AWPN); } void verifyBothWeapons() @@ -29961,7 +29952,6 @@ void HeroClass::getTriforce(int32_t id2) items.clear(); Ewpns.clear(); Lwpns.clear(); - Sitems.clear(); chainlinks.clear(); //decorations.clear(); @@ -30417,7 +30407,6 @@ void HeroClass::heroDeathAnimation() items.clear(); Ewpns.clear(); Lwpns.clear(); - Sitems.clear(); chainlinks.clear(); decorations.clear(); Playing = false; diff --git a/src/zc/zc_subscr.cpp b/src/zc/zc_subscr.cpp index 5740c95c4d..bb0dc615d1 100644 --- a/src/zc/zc_subscr.cpp +++ b/src/zc/zc_subscr.cpp @@ -35,8 +35,6 @@ extern int32_t directItemX; void put_active_subscr(int32_t y, int32_t pos) { - //Don't call Sitems.animate() - that gets called somewhere else, somehow. -L - animate_selectors(); show_custom_subscreen(framebuf, new_subscreen_active, 0, 6-y, game->should_show_time(), pos); } @@ -87,18 +85,19 @@ void dosubscr() //Set the selector to the correct position before bringing up the subscreen -DD if(!new_subscreen_active) return; bool compat = get_qr(qr_OLD_SUBSCR); + bool noverify = get_qr(qr_NO_BUTTON_VERIFY); if(compat) { new_subscreen_active->curpage = 0; auto& pg = new_subscreen_active->pages[0]; if(Bwpn > -1) - pg.cursor_pos = zc_max(game->bwpn,0); + pg.cursor_pos = game->bwpn>>8; else if(use_a && Awpn > -1) - pg.cursor_pos = zc_max(game->awpn,0); + pg.cursor_pos = game->awpn>>8; else if(use_x && Xwpn > -1) - pg.cursor_pos = zc_max(game->xwpn,0); + pg.cursor_pos = game->xwpn>>8; else if(use_y && Ywpn > -1) - pg.cursor_pos = zc_max(game->ywpn,0); + pg.cursor_pos = game->ywpn>>8; else pg.cursor_pos = 0; } @@ -155,14 +154,14 @@ void dosubscr() { if (!get_qr(qr_NO_L_R_BUTTON_INVENTORY_SWAP)) { - pg.cursor_pos = pg.move_legacy(SEL_LEFT, pos, -1, -1, -1, false, true); + pg.cursor_pos = pg.movepos_legacy(SEL_LEFT, (pos<<8)|pg.getIndex(), -1, -1, -1, false, true); } } else if(rRbtn() ) { if (!get_qr(qr_NO_L_R_BUTTON_INVENTORY_SWAP)) { - pg.cursor_pos = pg.move_legacy(SEL_RIGHT, pos, -1, -1, -1, false, true); + pg.cursor_pos = pg.movepos_legacy(SEL_RIGHT, (pos<<8)|pg.getIndex(), -1, -1, -1, false, true); } } else if(rEx3btn() ) @@ -202,132 +201,159 @@ void dosubscr() { if(b_only || (btn_press&INT_BTN_B)) { - int32_t t = eqwpn; - if(use_a && t == Awpn) + if(noverify && !b_only && eqwpn == Bwpn) { - Awpn = Bwpn; - game->awpn = game->bwpn; - game->awpnpg = game->bwpnpg; - directItemA = directItemB; + Bwpn = -1; + game->forced_bwpn = -1; + sfx(QMisc.miscsfx[sfxSUBSCR_ITEM_ASSIGN]); + + game->bwpn = 255; + directItemB = -1; } - else if(use_x && t == Xwpn) + else { - Xwpn = Bwpn; - game->xwpn = game->bwpn; - game->xwpnpg = game->bwpnpg; - directItemX = directItemB; + if(use_a && eqwpn == Awpn) + { + Awpn = Bwpn; + game->awpn = game->bwpn; + directItemA = directItemB; + } + else if(use_x && eqwpn == Xwpn) + { + Xwpn = Bwpn; + game->xwpn = game->bwpn; + directItemX = directItemB; + } + else if(use_y && eqwpn == Ywpn) + { + Ywpn = Bwpn; + game->ywpn = game->bwpn; + directItemY = directItemB; + } + + Bwpn = eqwpn; + game->forced_bwpn = -1; //clear forced if the item is selected using the actual subscreen + if(!b_only) sfx(QMisc.miscsfx[sfxSUBSCR_ITEM_ASSIGN]); + game->bwpn = ((pg.cursor_pos)<<8) | new_subscreen_active->curpage; + directItemB = eqwpn; } - else if(use_y && t == Ywpn) - { - Ywpn = Bwpn; - game->ywpn = game->bwpn; - game->ywpnpg = game->bwpnpg; - directItemY = directItemB; - } - - Bwpn = t; - game->forced_bwpn = -1; //clear forced if the item is selected using the actual subscreen - if(!b_only) sfx(QMisc.miscsfx[sfxSUBSCR_ITEM_ASSIGN]); - - game->bwpn = pg.cursor_pos; - game->bwpnpg = new_subscreen_active->curpage; - directItemB = eqwpn; } else if(use_a && (btn_press&INT_BTN_A)) { - int32_t t = eqwpn; - if(t == Bwpn) - { - Bwpn = Awpn; - game->bwpn = game->awpn; - game->bwpnpg = game->awpnpg; - directItemB = directItemA; - } - else if(use_x && t == Xwpn) + if(noverify && eqwpn == Awpn) { - Xwpn = Awpn; - game->xwpn = game->awpn; - game->xwpnpg = game->awpnpg; - directItemX = directItemA; + Awpn = -1; + game->forced_awpn = -1; + sfx(QMisc.miscsfx[sfxSUBSCR_ITEM_ASSIGN]); + + game->awpn = 255; + directItemA = -1; } - else if(use_y && t == Ywpn) + else { - Ywpn = Awpn; - game->ywpn = game->awpn; - game->ywpnpg = game->awpnpg; - directItemY = directItemA; + if(eqwpn == Bwpn) + { + Bwpn = Awpn; + game->bwpn = game->awpn; + directItemB = directItemA; + } + else if(use_x && eqwpn == Xwpn) + { + Xwpn = Awpn; + game->xwpn = game->awpn; + directItemX = directItemA; + } + else if(use_y && eqwpn == Ywpn) + { + Ywpn = Awpn; + game->ywpn = game->awpn; + directItemY = directItemA; + } + + Awpn = eqwpn; + sfx(QMisc.miscsfx[sfxSUBSCR_ITEM_ASSIGN]); + game->awpn = ((pg.cursor_pos)<<8) | new_subscreen_active->curpage; + game->forced_awpn = -1; //clear forced if the item is selected using the actual subscreen + directItemA = eqwpn; } - - Awpn = t; - sfx(QMisc.miscsfx[sfxSUBSCR_ITEM_ASSIGN]); - game->awpn = pg.cursor_pos; - game->awpnpg = new_subscreen_active->curpage; - game->forced_awpn = -1; //clear forced if the item is selected using the actual subscreen - directItemA = eqwpn; } else if(use_x && (btn_press&INT_BTN_EX1)) { - int32_t t = eqwpn; - if(t == Bwpn) + if(noverify && eqwpn == Xwpn) { - Bwpn = Xwpn; - game->bwpn = game->xwpn; - game->bwpnpg = game->xwpnpg; - directItemB = directItemX; + Xwpn = -1; + game->forced_xwpn = -1; + sfx(QMisc.miscsfx[sfxSUBSCR_ITEM_ASSIGN]); + + game->xwpn = 255; + directItemX = -1; } - else if(use_a && t == Awpn) + else { - Awpn = Xwpn; - game->awpn = game->xwpn; - game->awpnpg = game->xwpnpg; - directItemA = directItemX; + if(eqwpn == Bwpn) + { + Bwpn = Xwpn; + game->bwpn = game->xwpn; + directItemB = directItemX; + } + else if(use_a && eqwpn == Awpn) + { + Awpn = Xwpn; + game->awpn = game->xwpn; + directItemA = directItemX; + } + else if(use_y && eqwpn == Ywpn) + { + Ywpn = Xwpn; + game->ywpn = game->xwpn; + directItemY = directItemX; + } + + Xwpn = eqwpn; + sfx(QMisc.miscsfx[sfxSUBSCR_ITEM_ASSIGN]); + game->xwpn = ((pg.cursor_pos)<<8) | new_subscreen_active->curpage; + game->forced_xwpn = -1; //clear forced if the item is selected using the actual subscreen + directItemX = eqwpn; } - else if(use_y && t == Ywpn) - { - Ywpn = Xwpn; - game->ywpn = game->xwpn; - game->ywpnpg = game->xwpnpg; - directItemY = directItemX; - } - - Xwpn = t; - sfx(QMisc.miscsfx[sfxSUBSCR_ITEM_ASSIGN]); - game->xwpn = pg.cursor_pos; - game->xwpnpg = new_subscreen_active->curpage; - game->forced_xwpn = -1; //clear forced if the item is selected using the actual subscreen - directItemX = eqwpn; } else if(use_y && (btn_press&INT_BTN_EX2)) { - int32_t t = eqwpn; - if(t == Bwpn) - { - Bwpn = Ywpn; - game->bwpn = game->ywpn; - game->bwpnpg = game->ywpnpg; - directItemB = directItemY; - } - else if(use_a && t == Awpn) + if(noverify && eqwpn == Ywpn) { - Awpn = Ywpn; - game->awpn = game->ywpn; - game->awpnpg = game->ywpnpg; - directItemA = directItemY; + Ywpn = -1; + game->forced_ywpn = -1; + sfx(QMisc.miscsfx[sfxSUBSCR_ITEM_ASSIGN]); + + game->ywpn = 255; + directItemY = -1; } - else if(use_x && t == Xwpn) + else { - Xwpn = Ywpn; - game->xwpn = game->ywpn; - game->xwpnpg = game->ywpnpg; - directItemX = directItemY; + if(eqwpn == Bwpn) + { + Bwpn = Ywpn; + game->bwpn = game->ywpn; + directItemB = directItemY; + } + else if(use_a && eqwpn == Awpn) + { + Awpn = Ywpn; + game->awpn = game->ywpn; + directItemA = directItemY; + } + else if(use_x && eqwpn == Xwpn) + { + Xwpn = Ywpn; + game->xwpn = game->ywpn; + directItemX = directItemY; + } + + Ywpn = eqwpn; + sfx(QMisc.miscsfx[sfxSUBSCR_ITEM_ASSIGN]); + game->ywpn = ((pg.cursor_pos)<<8) | new_subscreen_active->curpage; + game->forced_ywpn = -1; //clear forced if the item is selected using the actual subscreen + directItemY = eqwpn; } - - Ywpn = t; - sfx(QMisc.miscsfx[sfxSUBSCR_ITEM_ASSIGN]); - game->ywpn = pg.cursor_pos; - game->ywpnpg = new_subscreen_active->curpage; - game->forced_ywpn = -1; //clear forced if the item is selected using the actual subscreen - directItemY = eqwpn; } } } @@ -406,7 +432,6 @@ void dosubscr() return; } - // Sitems.clear(); if(usebombpal) { memcpy(RAMpal, temppal, PAL_SIZE*sizeof(RGB)); diff --git a/src/zc/zelda.cpp b/src/zc/zelda.cpp index 1ebd5ec1fd..28ba6991b1 100644 --- a/src/zc/zelda.cpp +++ b/src/zc/zelda.cpp @@ -1123,7 +1123,7 @@ bool blockmoving; movingblock mblock2; //mblock[4]? portal mirror_portal; -sprite_list guys, items, Ewpns, Lwpns, Sitems, chainlinks, decorations, portals; +sprite_list guys, items, Ewpns, Lwpns, chainlinks, decorations, portals; particle_list particles; #include "zc/zc_custom.h" @@ -2153,13 +2153,19 @@ int32_t init_game() if(firstplay) { - int wval = get_qr(qr_OLD_SUBSCR) ? -1 : 0; - game->awpn=game->bwpn=game->ywpn=game->xwpn=wval; - game->awpnpg=game->bwpnpg=game->ywpnpg=game->xwpnpg=0; - game->forced_awpn = -1; - game->forced_bwpn = -1; - game->forced_xwpn = -1; - game->forced_ywpn = -1; + if(!get_qr(qr_OLD_SUBSCR) && new_subscreen_active) + { + game->awpn = new_subscreen_active->def_btns[0]; + game->bwpn = new_subscreen_active->def_btns[1]; + game->xwpn = new_subscreen_active->def_btns[2]; + game->ywpn = new_subscreen_active->def_btns[3]; + } + else + { + game->awpn=game->bwpn=game->ywpn=game->xwpn=255; + } + game->forced_awpn = game->forced_bwpn = + game->forced_xwpn = game->forced_ywpn = -1; } update_subscreens(); @@ -2169,7 +2175,7 @@ int32_t init_game() //load the previous weapons -DD bool usesaved = (game->get_quest() == 0xFF); //What was wrong with firstplay? - int32_t apos = -1, bpos = -1, xpos = -1, ypos = -1; + int32_t apos = 0xFF, bpos = 0xFF, xpos = 0xFF, ypos = 0xFF; //Setup button items { @@ -2182,48 +2188,39 @@ int32_t init_game() if(!get_qr(qr_SELECTAWPN)) { Awpn = selectSword(); - bpos = pg.move_legacy(SEL_VERIFY_RIGHT, usesaved ? game->bwpn : 0xFF); + bpos = pg.movepos_legacy(SEL_VERIFY_RIGHT, usesaved ? game->bwpn : 0xFF); if(use_x) - xpos = pg.move_legacy(SEL_VERIFY_RIGHT, usesaved ? game->xwpn : 0xFF, bpos); + xpos = pg.movepos_legacy(SEL_VERIFY_RIGHT, usesaved ? game->xwpn : 0xFF, bpos); if(use_y) - ypos = pg.move_legacy(SEL_VERIFY_RIGHT, usesaved ? game->ywpn : 0xFF, bpos, xpos); + ypos = pg.movepos_legacy(SEL_VERIFY_RIGHT, usesaved ? game->ywpn : 0xFF, bpos, xpos); directItem = -1; directItemA = -1; } else { - apos = pg.move_legacy(SEL_VERIFY_RIGHT, usesaved ? game->awpn : 0xFF); - bpos = pg.move_legacy(SEL_VERIFY_RIGHT, usesaved ? game->bwpn : 0xFF, apos); + apos = pg.movepos_legacy(SEL_VERIFY_RIGHT, usesaved ? game->awpn : 0xFF); + bpos = pg.movepos_legacy(SEL_VERIFY_RIGHT, usesaved ? game->bwpn : 0xFF, apos); if(use_x) - xpos = pg.move_legacy(SEL_VERIFY_RIGHT, usesaved ? game->xwpn : 0xFF, apos, bpos); + xpos = pg.movepos_legacy(SEL_VERIFY_RIGHT, usesaved ? game->xwpn : 0xFF, apos, bpos); if(use_y) - ypos = pg.move_legacy(SEL_VERIFY_RIGHT, usesaved ? game->ywpn : 0xFF, apos, bpos, xpos); + ypos = pg.movepos_legacy(SEL_VERIFY_RIGHT, usesaved ? game->ywpn : 0xFF, apos, bpos, xpos); - if(bpos==0xFF) - bpos=-1; - if(apos==0xFF) - apos=-1; - if(xpos==0xFF) - xpos=-1; - if(ypos==0xFF) - ypos=-1; - - Awpn = pg.get_item_pos(apos); + Awpn = pg.get_item_pos(apos>>8); directItemA = NEG_OR_MASK(Awpn,0xFF); } game->awpn = apos; game->bwpn = bpos; - Bwpn = pg.get_item_pos(bpos); + Bwpn = pg.get_item_pos(bpos>>8); directItemB = NEG_OR_MASK(Bwpn,0xFF); game->xwpn = xpos; - Xwpn = pg.get_item_pos(xpos); + Xwpn = pg.get_item_pos(xpos>>8); directItemX = NEG_OR_MASK(Xwpn,0xFF); game->ywpn = ypos; - Ywpn = pg.get_item_pos(ypos); + Ywpn = pg.get_item_pos(ypos>>8); directItemY = NEG_OR_MASK(Ywpn,0xFF); update_subscr_items(); @@ -2235,28 +2232,28 @@ int32_t init_game() if(!get_qr(qr_SELECTAWPN)) { Awpn = selectSword(); - apos = -1; - bpos = pg.move_legacy(SEL_VERIFY_RIGHT, usesaved ? game->bwpn : 0xFF, -1); + apos = 0xFF; + bpos = pg.movepos_legacy(SEL_VERIFY_RIGHT, usesaved ? game->bwpn : 0xFF); directItemA = directItem = -1; } else { - apos = pg.move_legacy(SEL_VERIFY_RIGHT, usesaved ? game->awpn : 0xFF); - bpos = pg.move_legacy(SEL_VERIFY_RIGHT, usesaved ? game->bwpn : 0xFF, apos); + apos = pg.movepos_legacy(SEL_VERIFY_RIGHT, usesaved ? game->awpn : 0xFF); + bpos = pg.movepos_legacy(SEL_VERIFY_RIGHT, usesaved ? game->bwpn : 0xFF, apos); if(bpos==0xFF) { bpos=apos; - apos=-1; + apos=0xFF; } - Awpn = pg.get_item_pos(apos); + Awpn = pg.get_item_pos(apos>>8); directItemA = NEG_OR_MASK(Awpn,0xFF); } game->awpn = apos; game->bwpn = bpos; - Bwpn = pg.get_item_pos(bpos); + Bwpn = pg.get_item_pos(bpos>>8); directItemB = NEG_OR_MASK(Bwpn,0xFF); update_subscr_items(); @@ -2265,17 +2262,14 @@ int32_t init_game() } else if(new_subscreen_active) { - if(get_qr(qr_SELECTAWPN)) - { - Awpn = new_subscreen_active->get_item_pos(game->awpn,game->awpnpg); - directItemA = NEG_OR_MASK(Awpn,0xFF); - } - else selectSword(); - Bwpn = new_subscreen_active->get_item_pos(game->bwpn,game->bwpnpg); + Awpn = get_qr(qr_SELECTAWPN) ? new_subscreen_active->get_item_pos(game->awpn) + : selectSword(); + directItemA = NEG_OR_MASK(Awpn,0xFF); + Bwpn = new_subscreen_active->get_item_pos(game->bwpn); directItemB = NEG_OR_MASK(Bwpn,0xFF); - Xwpn = new_subscreen_active->get_item_pos(game->xwpn,game->xwpnpg); + Xwpn = new_subscreen_active->get_item_pos(game->xwpn); directItemX = NEG_OR_MASK(Xwpn,0xFF); - Ywpn = new_subscreen_active->get_item_pos(game->ywpn,game->ywpnpg); + Ywpn = new_subscreen_active->get_item_pos(game->ywpn); directItemY = NEG_OR_MASK(Ywpn,0xFF); } } @@ -5678,9 +5672,6 @@ void delete_everything_else() //blarg. { delete_combo_aliases(); reset_subscr_items(); - delete_selectors(); - Sitems.clear(); - } void quit_game() diff --git a/src/zq/zq_class.cpp b/src/zq/zq_class.cpp index fccad3cd7f..a684cb6ed9 100644 --- a/src/zq/zq_class.cpp +++ b/src/zq/zq_class.cpp @@ -6930,7 +6930,7 @@ void popup_bugfix_dlg(const char* cfg) { if(ret) { - applyRuleTemplate(ruletemplateCompat); + applyRuleTemplate(ruletemplateFixCompat); } if(dsa) { diff --git a/src/zq/zq_files.cpp b/src/zq/zq_files.cpp index 92df5c5a32..f51f61ae38 100644 --- a/src/zq/zq_files.cpp +++ b/src/zq/zq_files.cpp @@ -565,7 +565,7 @@ void alwaysOnRules() } int32_t onStrFix(); -void applyRuleset(int32_t newRuleset) +void applyRuleset(int32_t newRuleset, byte *qrptr) { ruleset = newRuleset; for(int32_t i=0; i= 0 && curr_subscreen_object 0 && curr_subscreen_object @@ -29654,7 +29654,9 @@ command_pair commands[cmdMAX]= { "Redo", 0, (intF) onRedo }, { "Combo Pool Mode", 0, (intF) onDrawingModePool }, { "Quest Rules Search", 0, (intF) onRulesSearch }, - { "Quick Compile ZScript", 0, (intF) onQuickCompile } + { "Quick Compile ZScript", 0, (intF) onQuickCompile }, + { "Rulesets", 0, (intF) PickRuleset }, + { "Rule Templates", 0, (intF) PickRuleTemplate }, }; /********************************/ diff --git a/src/zq/zquest.h b/src/zq/zquest.h index 3f080dcaad..3dad76b709 100644 --- a/src/zq/zquest.h +++ b/src/zq/zquest.h @@ -751,6 +751,8 @@ enum cmdDrawingModePool, cmdQRSearch, cmdQuickCompile, + cmdRuleset, + cmdRuleTemplate, cmdMAX }; @@ -1148,7 +1150,6 @@ int32_t get_bmaps(int32_t si); bool no_subscreen(); extern int32_t Awpn, Bwpn, Xwpn, Ywpn; -extern sprite_list Sitems; int32_t main(int32_t argc,char **argv); int32_t d_nbmenu_proc(int32_t msg,DIALOG *d,int32_t c);