From b5a50d74cf042fa7fc874d8184dc37ae20bb74dd Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Sat, 23 Mar 2024 14:11:45 +0100 Subject: [PATCH] basic auto tracking --- icons.sh | 11 + public/item/aga.png | Bin 0 -> 2573 bytes public/item/armos.png | Bin 0 -> 4968 bytes public/item/arrghus.png | Bin 0 -> 3492 bytes public/item/blind.png | Bin 0 -> 3484 bytes public/item/bottle-bee.png | Bin 1363 -> 5131 bytes public/item/chest.png | Bin 0 -> 770 bytes public/item/heart-0.png | Bin 0 -> 689 bytes public/item/heart-1.png | Bin 0 -> 703 bytes public/item/heart-2.png | Bin 0 -> 707 bytes public/item/heart-3.png | Bin 0 -> 701 bytes public/item/helma.png | Bin 0 -> 4491 bytes public/item/kholdstare.png | Bin 0 -> 3446 bytes public/item/lanmolas.png | Bin 0 -> 3342 bytes public/item/moldorm.png | Bin 0 -> 4736 bytes public/item/mothula.png | Bin 0 -> 3425 bytes public/item/open-chest.png | Bin 0 -> 705 bytes public/item/red-crystal.png | Bin 0 -> 4350 bytes public/item/small-key.png | Bin 336 -> 9612 bytes public/item/sword-1.png | Bin 0 -> 762 bytes public/item/sword-2.png | Bin 0 -> 798 bytes public/item/sword-3.png | Bin 0 -> 792 bytes public/item/sword-4.png | Bin 0 -> 808 bytes public/item/trinexx.png | Bin 0 -> 3584 bytes public/item/vitreous.png | Bin 0 -> 3420 bytes public/items-v1.png | Bin 0 -> 45767 bytes public/items.png | Bin 0 -> 21356 bytes resources/js/app/Routes.js | 7 + resources/js/components/common/ZeldaIcon.js | 156 +- .../js/components/tracker/AutoTracking.js | 153 ++ .../js/components/tracker/CountDisplay.js | 22 + resources/js/components/tracker/Dungeons.js | 62 + resources/js/components/tracker/Equipment.js | 59 + resources/js/components/tracker/Items.js | 102 + resources/js/components/tracker/ToggleIcon.js | 218 ++ resources/js/components/tracker/Toolbar.js | 41 + resources/js/components/tracker/index.js | 17 + .../twitch-bot/GuessingGameAutoTracking.js | 68 +- resources/js/helpers/alttp-ram.js | 162 ++ resources/js/helpers/tracker.js | 1753 +++++++++++++++++ resources/js/hooks/tracker.js | 49 + resources/js/i18n/de.js | 6 + resources/js/i18n/en.js | 6 + resources/js/pages/Tracker.js | 17 + resources/sass/app.scss | 1 + resources/sass/common.scss | 8 + resources/sass/tracker.scss | 130 ++ 47 files changed, 2944 insertions(+), 104 deletions(-) create mode 100755 icons.sh create mode 100644 public/item/aga.png create mode 100644 public/item/armos.png create mode 100644 public/item/arrghus.png create mode 100644 public/item/blind.png create mode 100644 public/item/chest.png create mode 100644 public/item/heart-0.png create mode 100644 public/item/heart-1.png create mode 100644 public/item/heart-2.png create mode 100644 public/item/heart-3.png create mode 100644 public/item/helma.png create mode 100644 public/item/kholdstare.png create mode 100644 public/item/lanmolas.png create mode 100644 public/item/moldorm.png create mode 100644 public/item/mothula.png create mode 100644 public/item/open-chest.png create mode 100644 public/item/red-crystal.png create mode 100644 public/item/sword-1.png create mode 100644 public/item/sword-2.png create mode 100644 public/item/sword-3.png create mode 100644 public/item/sword-4.png create mode 100644 public/item/trinexx.png create mode 100644 public/item/vitreous.png create mode 100644 public/items-v1.png create mode 100644 public/items.png create mode 100644 resources/js/components/tracker/AutoTracking.js create mode 100644 resources/js/components/tracker/CountDisplay.js create mode 100644 resources/js/components/tracker/Dungeons.js create mode 100644 resources/js/components/tracker/Equipment.js create mode 100644 resources/js/components/tracker/Items.js create mode 100644 resources/js/components/tracker/ToggleIcon.js create mode 100644 resources/js/components/tracker/Toolbar.js create mode 100644 resources/js/components/tracker/index.js create mode 100644 resources/js/helpers/tracker.js create mode 100644 resources/js/hooks/tracker.js create mode 100644 resources/js/pages/Tracker.js create mode 100644 resources/sass/tracker.scss diff --git a/icons.sh b/icons.sh new file mode 100755 index 0000000..c9fe293 --- /dev/null +++ b/icons.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +gm montage -geometry '32x32>' -background transparent -gravity center -tile 8x100 public/item/*.png public/items-v1.png + +echo 'const ITEM_MAP = [' +for i in public/item/*.png +do + basename=$(basename "$i") + echo -e "\t'${basename/\.png/}'," +done +echo '];' diff --git a/public/item/aga.png b/public/item/aga.png new file mode 100644 index 0000000000000000000000000000000000000000..3eda6c851412a62a51795a9c36eda94541f78700 GIT binary patch literal 2573 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 STD(;N0000;(){e literal 0 HcmV?d00001 diff --git a/public/item/blind.png b/public/item/blind.png new file mode 100644 index 0000000000000000000000000000000000000000..875142d12283c8f25e5f68878fc8a4b078f81c0f GIT binary patch literal 3484 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 KMNUMnLSTY>sfm>U literal 0 HcmV?d00001 diff --git a/public/item/bottle-bee.png b/public/item/bottle-bee.png index 20ad511a1390d3548c82769d59b4a9ae2a2a9281..04a929b13fd723122b750dfca07ae9ec565367eb 100644 GIT binary patch literal 5131 zcmeHKX;f3!7LGs(g95E6XrYEcQLIUBW|I;WNPtkotfHWBlY0XJGLQrkP_&9l5u_>> z#iFPMR1i?03TmwiN|7px6HY)uO0`r)Dj+z#lYofpb*;Bt>-C?>%FVrd_|D$n*?T7^ zJ;2Xa8K+_oUk=EjsM<2&)Vn ze%$8wy1jjy9jlyNU^UTVd-&E&Kicq??p>R{A9%Ul7ypx#i{M@ACNRAzX#OSV6B2`?TMvr`qmTX4W}-9R>E~zMyt=vB3jz8o7Pc<3vB{Qigrwj`mN3&e3$*=OLuE79#yz+ z^qZc(&oKxSWBbEGeo#+)_xXlp*PO$oMvassUw+|Dbggv`j`qs zow_{SV)m;zz0Emdivy$C_WpVM+WG5-Ke_I|M&AA0Hk@EGwD)NX-t?^OM8?Iw*WaD? zyFAs9b35h4;Tv6;PaLYeDRJ(YYc0tZaUtAX2gGPk=Cvbh5W@-m%V%%3PW$U4Mxa;p z$$hSA8*O%&CR$TBKVd}X^Q-IZ5A6lil~L&dSyq{pd?XQVu3wY0CbbcnX)kxLeO zKcpXsxmLis{l~s<9bz)c=klDESPSw!nyrIRz#`jM)h?&QdZl5g*yW5;& zp5q^XZhJsg-B#bSASv(VfxR)C=-2O7!!GojE6oLAaR-|1ET9K7}WwOJwuH5Dfm-1<=@y}YD`!Y#Br#hO? zohEfQ6BI)VkMgHQmNzdP^Jq4Ev1xwWgv-7W+v|4a|9x?Hjk$ks>UVt&Yxj^0e0Oyo z%@W@FVgQzc3 zUoCL6pbzi=>bZ5A+ugpl9M#aK;z6tJW&S-$&x@GPUIejbzD_%Ji)1IM|9NuystF$D zY5l=bi%dbEuatOt21rCA(9d}(TR1+o^X<+>gcb5;n~AOBe+jU!BhKy!EeOA0KZWZf>z^&LaEpyo3bB6r(eiR#DiQJR6tZ)%?A@Ol$t3fW;GL z$pZQc;n&4Wyx1SxsGct*4{pR5O~kJ=P0vlHRPI>cJ$O9r+j33d?yi(aO;^gT7Z?w6 zJ8Z8`%Fw226R$S29#1wuG{>c`yDr;!+2+A5e^xZg^S-hePAZB-uJ+X#90`3WtjSn% zDs^V)=+KlntN@(XYtUiMQ$U5vJDvIO3CKz2^aG>Y4%SP?0O7HvhY{ z=BFPA;)gKE!IG{|+uN;dNrC;x>rZ&z`|0J1qI+$Yc^@l}HElC{2qti%1Wejc!2-5O zE+xWw&YtpXOsqH3HFjgrVX_{S%H#^WRi2fvsufCLIpG+N@5tVDy8 z{X#^^u_6|NpXX-gs$~NJDXNBXT4|h2#ny80dR#WR*NI7ZoZdto%fW{V0&t#kC5odF zX+(&?(@GL4csDbgs}d2jgScL!5a5Y}k5;P{Y!XSM(GWFMqFfn8BC}X55=0?UC8Jw1)(Z=f>MO?5>c7jaXbVf8uM2qDC6|$AR-bP zhf0B|3amsND$KKGy;oB5en%n3X{p8kAv`6 zNm+oIto##3>J-nq9Q#MB4T^Vl~NdN zr$h=zp(KSYO0Uon&UO#rbMO=*^i~oO2dl-v0rY@GhR8Llx2h0{6b)9xIzGuvGQ^^j z8BB=DfFOwV)@Tu`RDoL5p^_mYm7&+@Hiiw-0o1~}N(BIVImm|XsYGG5Tp1#l$8qqw zpl~|RF|`0R6auSZF04iYC`6&LAu5{!g^-zS3YiVDzJS1WoV^^8h?D-8wXS_|t|Oc7 zBT<3%lk}pIo(e|eN1jF=<0SfK!r}C7!G=X6DX8E?6w${Cutrp(Xjm47g84C8uy5p& ze<+5z46zuY2&n`i9YqN=h7cyOUMe7Ncj#*G-@HzEV03rs@N z*eD$33&i?wzDD=q-&_KR`>@D+@%w?U4|Kg31Mg-0p}IcM^?@;&a_YeCkCA&M4IO6?L=0D+uby77O=KBc1M7&WKpG8Np#KvCH!< z3}$pZnRd5pF2?U!v|Hf`%O&3|^oa@2Dr!EH?Q2@-7aq@v4svlUUAdugzhS$lS&CP& zKQ@A&T9WA$a--wIsmf4C(dUbm)TDe`34%6NHP`{~9RLvGtl2G=-#XR&=Q*MC#> zQ~SLy=4xZim3`Cp-ni3#u(v^43a|SG+@!@mHpSebEm!{DAGRFCjp6hBxMd!ZYySgk CxwYy5 literal 1363 zcmeAS@N?(olHy`uVBq!ia0vp^d_XL~!VDy@>&U|_7tbaoENOipHC(3n^|(bnUz zgUr$RU~ktbnKufLCM>jy)X=&VxGI8$d+FK>tC~+PjlXbY!jc^pT7CnU zwS%ka0ei>f#gi9xPx-Nb$pxij&5!H$?Eb!^nw?{Qv~;v+qzp z!yyj^J;PxC=VG5e$i#pD@bRnOvCVtV|Ft~ibuy*FUu9nEu0+B0!sm0Mte)3C;#lp) z_0jTUi=((o-IHB!K1o0CI?QywN8;xjnZlNcHD5N|IlLxo#gWTL0$s0a#B1zWQ*iIm znrqT)iv9l`3h<0RS2*{XMo@%{lw`+*iw?Y{5giv-O-xeq{_V;CzvJ=w3Epbqygf3X zZ!~b7{Mh{e;QPF@pRO#KE#k%0D1Q5&1as4FhuxXC?;qcG*N*Ye`2$n0ea+v}a76v( z*>z&JOl;d5yI-$Ud(SxC`oM?DdXkfre`az$HTqEJc0YurEw8aLbo=&mc7E~=HlI(3)EF2VS{N990fib~ zFff!FFfhDIU|_JC!N4G1FlSew4N!tVz$e6&frSBxe*F0HUAf83^QX7I;J!Gca%qgD@k*tT_@uLG}_)Usv{LOfsUz!fgN6 z@B;N5stSoH2}&$iC@9KL%gjktD5)$+RRE_Di{7Qd(S0(CJb#{xST=p!Z0W~u67;UV zQG)05t(zXRBb@F|>5VmW{S}-2%hZQgnCGzY7OhNUre&O&mrvgan9wWe$fsGP)DZjT zouJCTS^wpdXPanCN)`wwiMG{mco)jPcu%9-jdy42GG4ZS^qsqHqT9kA?zH@~w~e-B zXud9*FzaVa!sDkLHk&`&*2r+%XFrIT++W;hDD$@P0qg!(vfI^bgo|oalJ?JB&{fGR zeUQKA*#1uc=2Z)~-MCz~;rt=i4N(PU`WE?j%ChIktW*0{=lxr4byu8{)9(XC)lBk= z1s|`rEeSGN<(#Q!P}*K~LBeR;*8NIp9!>?S2g;dVzUTS$Gr^$6raMt&wyQ>$LABD` z$BsWv@w0uX5b`$@;mKzz^VJl5xLLtCq;K-2b#^@g&+eT{xe?vidHDU=wkehq)qO#)DexHfn{BD0|Y%jcgN?tf=wr$o-U3d9M^q&4~iZz;BYE!c2I8+y!E$S+i-ft&qvNHv>2vl z-qv2?kn8q(-*NG~Oeai*f-+9ct}(3H=lsdwpUt+-ZxmGWxt4!t|9zIj>BG4{89+l- zOI#yLQW8s2t&)pUffR$0fsv7}fsw9}MTn81m8qeXp@p`Aft7*5ntG#UC>nC}Q!>*k zacj7%)FlPfAPuqsnC7gK^9w4AGSf3k7y?R@ax#+@T=H`hGxN4hG>ir+Q-Uc=Ni9w; z$}A|!%+F(R_w)@=NGi?DDbdZ$Qz#B{ck)Sh1g3fhQJCu7#Jtk9#N?9FqSPX=a-Vq< hP5~A0!4>4Eq~a*Is;`GJYD@<);T3K0RZKOHj@AV diff --git a/public/item/chest.png b/public/item/chest.png new file mode 100644 index 0000000000000000000000000000000000000000..9bba19d735cda6da8dbe357eeb046776bbd23c82 GIT binary patch literal 770 zcmV+d1O5DoP)EX>4Tx04R}tkv&MmKpe$iQ>9WW4i*t{$k003#V;JCibb$c+6t{Ym|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfc5qU3krMxx6k5c1aNLh~_a1le0HIlBs@XFKsG4P@ z6LB$@Uljwd@M8!;L@_NfQ%`0Vv+x{W_we!cF2=LG&;2?2m4e9tpGZ8%bi*RvAfDN@ zbk6(4VOEwD;&bA0gDyz?$aUG}H_j!81)do;vgvu^FtJ$bV!4Z1*-(k6h$D)sQNECK zS>e3JS*_Mt`=0!Tp@O!O;X2JxB(Q`eQV=1djtZ)<5TjKi#YCF+;~xGI$DbmXOs)zT zITlcZ3d!+<|H1EW&En*Qn-q!zy)U-?5d{LfK&xTf-^aGyIsyF8z?IhV*P6iWC+Urj z7C8b2wteSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{007!aL_t(o!|hkQ6~iD5Jn}LCW4NSDnGrMsV`PMk!3d0y zk`X)x8zcpxuo9k;8;iu($R8aKok5(9bMA>9al+0x*Nbo~(ceoXYs-BI<-PX+fSB_l zze38Z`Fa#+fru8B^`e)jM*(|@b?yLw>ok?f2r(s=kBvOip};YL<}P^5^QHl%JUt5J zL|+qlM_bF6@{Ue8fC9qGr98a~)bm>kDNmmQ-05(9o`UbnV_$zzr+|^VV(#hIo{#T} zTdR9*t+e>#xZ>7+?)}ES{b0O4@N=Hf{QckY3#v$2Bis7u`v3p{07*qoM6N<$f}>OV literal 0 HcmV?d00001 diff --git a/public/item/heart-0.png b/public/item/heart-0.png new file mode 100644 index 0000000000000000000000000000000000000000..a9984d7cf08d06b0f06a5ca5cdd7dc193221cb28 GIT binary patch literal 689 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 literal 0 HcmV?d00001 diff --git a/public/item/kholdstare.png b/public/item/kholdstare.png new file mode 100644 index 0000000000000000000000000000000000000000..54f0f2e132f1bc1e450daa8441033854160dff4a GIT binary patch literal 3446 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 Y0ApJsP(n1-IsgCw07*qoM6N<$f<8E7-v9sr literal 0 HcmV?d00001 diff --git a/public/item/lanmolas.png b/public/item/lanmolas.png new file mode 100644 index 0000000000000000000000000000000000000000..86b80a3ab92cc950d1422d2547466af0b22d67e5 GIT binary patch literal 3342 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 Y0L?3QsP(xw=l}o!07*qoM6N<$f}OH5IsgCw literal 0 HcmV?d00001 diff --git a/public/item/moldorm.png b/public/item/moldorm.png new file mode 100644 index 0000000000000000000000000000000000000000..070d451ea3a134b8c0774f81d4b6d2594947a74c GIT binary patch literal 4736 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 IpDtVXAFfa#+5i9m literal 0 HcmV?d00001 diff --git a/public/item/small-key.png b/public/item/small-key.png index d38cc7ad37866c417b192d7fd237c9f89207ef68..66ac0a057d6198b3eaa14026691f37e12915dc01 100644 GIT binary patch literal 9612 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 mA${s|z(_M&`rlC9Tkr;?fRA*aj( literal 0 HcmV?d00001 diff --git a/public/item/trinexx.png b/public/item/trinexx.png new file mode 100644 index 0000000000000000000000000000000000000000..03217dbfd4e302488937de133c512b3cf2d0bc87 GIT binary patch literal 3584 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 YX%~@+f5%cxAyD+L8(+)Uc7F2z0Nz2HT>t<8 literal 0 HcmV?d00001 diff --git a/public/items.png b/public/items.png new file mode 100644 index 0000000000000000000000000000000000000000..51e21af64f4b81199a6f6b68ab6f06eb38f99017 GIT binary patch literal 21356 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 W`hS`eF0x*ldEwk8g91IL`~Ly-v2^SJ literal 0 HcmV?d00001 diff --git a/resources/js/app/Routes.js b/resources/js/app/Routes.js index b7269e2..0e35ddb 100644 --- a/resources/js/app/Routes.js +++ b/resources/js/app/Routes.js @@ -150,6 +150,13 @@ const router = createBrowserRouter( )} /> + import( + /* webpackChunkName: "tracker" */ + '../pages/Tracker' + )} + /> ) ); diff --git a/resources/js/components/common/ZeldaIcon.js b/resources/js/components/common/ZeldaIcon.js index ef07b92..13efe31 100644 --- a/resources/js/components/common/ZeldaIcon.js +++ b/resources/js/components/common/ZeldaIcon.js @@ -4,62 +4,101 @@ import { useTranslation } from 'react-i18next'; import Icon from './Icon'; +const ITEM_MAP = [ + 'aga', + 'armos', + 'arrghus', + 'big-key', + 'blind', + 'blue-boomerang', + 'blue-mail', + 'blue-pendant', + 'blue-potion', + 'bombos', + 'bomb', + 'book', + 'boots', + 'bottle-bee', + 'bottle', + 'bowless-silvers', + 'bow', + 'bugnet', + 'byrna', + 'cape', + 'chest', + 'compass', + 'crystal', + 'duck', + 'ether', + 'fairy', + 'fighter-shield', + 'fighter-sword', + 'fire-rod', + 'fire-shield', + 'flippers', + 'flute', + 'glove', + 'gold-sword', + 'green-mail', + 'green-pendant', + 'green-potion', + 'half-magic', + 'hammer', + 'heart-0', + 'heart-1', + 'heart-2', + 'heart-3', + 'heart-container', + 'heart-piece', + 'helma', + 'hookshot', + 'ice-rod', + 'kholdstare', + 'lamp', + 'lanmolas', + 'map', + 'master-sword', + 'mirror', + 'mirror-shield', + 'mitts', + 'moldorm', + 'moonpearl', + 'mothula', + 'mushroom', + 'open-chest', + 'powder', + 'quake', + 'quarter-magic', + 'red-bomb', + 'red-boomerang', + 'red-crystal', + 'red-mail', + 'red-pendant', + 'red-potion', + 'shovel', + 'silvers', + 'small-key', + 'somaria', + 'sword-1', + 'sword-2', + 'sword-3', + 'sword-4', + 'tempered-sword', + 'trinexx', + 'vitreous', +]; + +const isOnItemMap = name => ITEM_MAP.includes(name); + +const getItemMapStyle = name => { + const index = ITEM_MAP.indexOf(name); + const x = index % 8; + const y = Math.floor(index / 8); + return { backgroundPosition: `-${x * 100}% -${y * 100}%` }; +}; + const getIconURL = name => { switch (name) { - case 'big-key': - case 'blue-boomerang': - case 'blue-mail': - case 'blue-pendant': - case 'blue-potion': - case 'bombos': - case 'bomb': - case 'book': - case 'boots': - case 'bottle-bee': - case 'bottle': - case 'bow': - case 'bugnet': - case 'byrna': - case 'cape': - case 'compass': - case 'crystal': - case 'duck': - case 'ether': - case 'fairy': - case 'fighter-shield': - case 'fighter-sword': - case 'fire-rod': - case 'fire-shield': - case 'flippers': - case 'flute': - case 'glove': - case 'green-mail': - case 'green-pendant': - case 'green-potion': - case 'hammer': - case 'heart-container': - case 'heart-piece': - case 'hookshot': - case 'ice-rod': - case 'lamp': - case 'map': - case 'mirror': - case 'mirror-shield': - case 'mitts': - case 'moonpearl': - case 'mushroom': - case 'powder': - case 'quake': - case 'red-bomb': - case 'red-boomerang': - case 'red-mail': - case 'red-pendant': - case 'red-potion': - case 'shovel': - case 'silvers': - case 'small-key': - case 'somaria': - return `/item/${name}.png`; case 'dungeon-ct': case 'dungeon-dp': case 'dungeon-ep': @@ -93,6 +132,13 @@ const ZeldaIcon = ({ name, title }) => { const realTitle = title !== '' ? title || alt : null; return + {isOnItemMap(strippedName) ? + + : null} {src ? {alt} { }; ZeldaIcon.propTypes = { - name: PropTypes.string, + name: PropTypes.string.isRequired, title: PropTypes.string, }; diff --git a/resources/js/components/tracker/AutoTracking.js b/resources/js/components/tracker/AutoTracking.js new file mode 100644 index 0000000..8528856 --- /dev/null +++ b/resources/js/components/tracker/AutoTracking.js @@ -0,0 +1,153 @@ +import React from 'react'; +import { Button } from 'react-bootstrap'; +import { useTranslation } from 'react-i18next'; + +import Icon from '../common/Icon'; +import ToggleSwitch from '../common/ToggleSwitch'; +import { + IN_GAME_MODES, + RAM_ADDR, + SRAM_ADDR, + WRAM_ADDR, + buildPrizeMap, +} from '../../helpers/alttp-ram'; +import { computeState, mergeStates } from '../../helpers/tracker'; +import { useSNES } from '../../hooks/snes'; +import { useTracker } from '../../hooks/tracker'; + +const AutoTracking = () => { + const [enabled, setEnabled] = React.useState(false); + const [prizeMap, setPrizeMap] = React.useState(buildPrizeMap()); + + const { + disable: disableSNES, + enable: enableSNES, + openSettings, + sock, + status, + } = useSNES(); + const { config, setState } = useTracker(); + const { t } = useTranslation(); + + const enable = React.useCallback(() => { + enableSNES(); + setEnabled(true); + }, []); + + const disable = React.useCallback(() => { + disableSNES(); + setEnabled(false); + }, []); + + React.useEffect(() => { + const savedSettings = localStorage.getItem('tracker.settings'); + if (savedSettings) { + const settings = JSON.parse(savedSettings); + if (settings.autoTrack) { + enable(); + } + } + }, []); + + const saveSettings = React.useCallback((newSettings) => { + const savedSettings = localStorage.getItem('tracker.settings'); + const settings = savedSettings + ? { ...JSON.parse(savedSettings), ...newSettings } + : newSettings; + localStorage.setItem('tracker.settings', JSON.stringify(settings)); + }, []); + + const toggle = React.useCallback(() => { + if (enabled) { + disable(); + saveSettings({ autoTrack: false }); + } else { + enable(); + saveSettings({ autoTrack: true }); + } + }, [enabled]); + + // poll game and push state + React.useEffect(() => { + if (!enabled || status.error || !status.connected || !status.device) return; + const updateState = () => { + const saveStart = WRAM_ADDR.SAVE_DATA; + const saveSize = SRAM_ADDR.INV_END; + sock.current.readWRAM(saveStart, saveSize, (data) => { + const computed = computeState(data, prizeMap); + setState(s => mergeStates(config, s, computed)); + }); + }; + const fetchPrizes = () => { + sock.current.readBytes(RAM_ADDR.PRIZE_MAP, 13, (prizes) => { + sock.current.readBytes(RAM_ADDR.CRYSTAL_MAP, 13, (crystals) => { + setPrizeMap(m => { + const newMap = buildPrizeMap(prizes, crystals); + return JSON.stringify(m) === JSON.stringify(newMap) ? m : newMap; + }); + }); + }); + }; + const checkInGame = () => { + sock.current.readWRAM(WRAM_ADDR.GAME_MODE, 1, (data) => { + if (IN_GAME_MODES.includes(data[0])) { + fetchPrizes(); + updateState(); + } + }); + }; + const timer = setInterval(checkInGame, 1000); + return () => { + clearInterval(timer); + }; + }, [enabled && !status.error && status.connected && status.device, config, prizeMap, sock]); + + const statusMsg = React.useMemo(() => { + if (!enabled) { + return 'disabled'; + } + if (status.error) { + return 'error'; + } + if (!status.connected) { + return 'disconnected'; + } + if (!status.device) { + return 'no-device'; + } + return 'tracking'; + }, [enabled, status]); + + return
+ {['disconnected', 'error', 'no-device'].includes(statusMsg) ? + + : null} + {['not-applicable', 'not-in-game'].includes(statusMsg) ? + + : null} + + +
; +}; + +export default AutoTracking; diff --git a/resources/js/components/tracker/CountDisplay.js b/resources/js/components/tracker/CountDisplay.js new file mode 100644 index 0000000..ed9b91f --- /dev/null +++ b/resources/js/components/tracker/CountDisplay.js @@ -0,0 +1,22 @@ +import PropTypes from 'prop-types'; +import React from 'react'; + +const CountDisplay = ({ className, count }) => { + const classNames = ['count-display']; + if (className) { + classNames.push(className); + } + if (!count) { + classNames.push('is-zero'); + } + return + {count} + ; +}; + +CountDisplay.propTypes = { + className: PropTypes.string, + count: PropTypes.number, +}; + +export default CountDisplay; diff --git a/resources/js/components/tracker/Dungeons.js b/resources/js/components/tracker/Dungeons.js new file mode 100644 index 0000000..07b6638 --- /dev/null +++ b/resources/js/components/tracker/Dungeons.js @@ -0,0 +1,62 @@ +import React from 'react'; + +import CountDisplay from './CountDisplay'; +import ToggleIcon from './ToggleIcon'; +import { useTracker } from '../../hooks/tracker'; + +const Dungeons = () => { + const { dungeons, state } = useTracker(); + + return
+ {dungeons.map(dungeon => +
+ {dungeon.id.toUpperCase()} + + + + + + + + + + + + {dungeon.boss ? + + : null} + {dungeon.prize ? + + : null} +
+ )} +
; +}; + +export default Dungeons; diff --git a/resources/js/components/tracker/Equipment.js b/resources/js/components/tracker/Equipment.js new file mode 100644 index 0000000..bfb9b20 --- /dev/null +++ b/resources/js/components/tracker/Equipment.js @@ -0,0 +1,59 @@ +import React from 'react'; + +import CountDisplay from './CountDisplay'; +import ToggleIcon from './ToggleIcon'; +import { useTracker } from '../../hooks/tracker'; + +const Equipment = () => { + const { state } = useTracker(); + + return
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
; +}; + +export default Equipment; diff --git a/resources/js/components/tracker/Items.js b/resources/js/components/tracker/Items.js new file mode 100644 index 0000000..712ee6c --- /dev/null +++ b/resources/js/components/tracker/Items.js @@ -0,0 +1,102 @@ +import React from 'react'; + +import CountDisplay from './CountDisplay'; +import ToggleIcon from './ToggleIcon'; +import { useTracker } from '../../hooks/tracker'; + +const Items = () => { + const { state } = useTracker(); + + return
+
+ +
+
+ + +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+ +
+
+ +
+
; +}; + +export default Items; diff --git a/resources/js/components/tracker/ToggleIcon.js b/resources/js/components/tracker/ToggleIcon.js new file mode 100644 index 0000000..49375ef --- /dev/null +++ b/resources/js/components/tracker/ToggleIcon.js @@ -0,0 +1,218 @@ +import PropTypes from 'prop-types'; +import React from 'react'; + +import ZeldaIcon from '../common/ZeldaIcon'; +import { + decrement, + getDungeonBoss, + getDungeonPrize, + hasDungeonBoss, + hasDungeonPrize, + highestActive, + increment, + toggleBoolean, +} from '../../helpers/tracker'; +import { useTracker } from '../../hooks/tracker'; + +const ToggleIcon = ({ controller, className, icons }) => { + const { state, setState } = useTracker(); + const activeController = controller || ToggleIcon.nullController; + const active = activeController.getActive(state, icons); + const defaultIcon = activeController.getDefault(state, icons); + const classNames = ['toggle-icon']; + if (active) { + classNames.push('active'); + } else { + classNames.push('inactive'); + } + if (className) { + classNames.push(className); + } + return { + activeController.handlePrimary(state, setState, icons); + e.preventDefault(); + e.stopPropagation(); + }} + onContextMenu={(e) => { + activeController.handleSecondary(state, setState, icons); + e.preventDefault(); + e.stopPropagation(); + }} + > + + ; +}; + +const doNothing = () => { }; + +const firstIcon = (state, icons) => icons[0]; + +const nextIcon = (state, setState, icons) => { + const highest = highestActive(state, icons); + const highestIndex = highest ? icons.indexOf(highest) : -1; + if (highestIndex + 1 < icons.length) { + setState(toggleBoolean(icons[highestIndex + 1])); + } else { + const changes = {}; + icons.forEach(icon => { + changes[icon] = false; + }); + setState(s => ({ ...s, ...changes })); + } +}; + +const previousIcon = (state, setState, icons) => { + const highest = highestActive(state, icons); + const highestIndex = highest ? icons.indexOf(highest) : -1; + if (highestIndex >= 0) { + setState(toggleBoolean(icons[highestIndex])); + } else { + const changes = {}; + icons.forEach(icon => { + changes[icon] = true; + }); + setState(s => ({ ...s, ...changes })); + } +}; + +const nextString = property => (state, setState, icons) => { + const current = state[property] || icons[0]; + const currentIndex = icons.indexOf(current); + const nextIndex = (currentIndex + 1) % icons.length; + const next = icons[nextIndex]; + setState(s => ({ ...s, [property]: next })); +}; + +const previousString = property => (state, setState, icons) => { + const current = state[property] || icons[0]; + const currentIndex = icons.indexOf(current); + const previousIndex = (currentIndex + icons.length - 1) % icons.length; + const previous = icons[previousIndex]; + setState(s => ({ ...s, [property]: previous })); +}; + +ToggleIcon.countController = max => ({ + getActive: highestActive, + getDefault: firstIcon, + handlePrimary: (state, setState, icons) => { + setState(increment(icons[0], max)); + }, + handleSecondary: (state, setState, icons) => { + setState(decrement(icons[0], max)); + }, +}); + +ToggleIcon.dungeonBossController = (dungeon) => ({ + getActive: (state) => hasDungeonBoss(state, dungeon) ? getDungeonBoss(state, dungeon) : null, + getDefault: (state) => getDungeonBoss(state, dungeon), + handlePrimary: dungeon.bosses.length > 1 + ? nextString(`${dungeon.id}-boss`) + : (state, setState) => { + setState(toggleBoolean(`${dungeon.id}-boss-defeated`)); + }, + handleSecondary: dungeon.bosses.length > 1 ? + previousString(`${dungeon.id}-boss`) + : (state, setState) => { + setState(toggleBoolean(`${dungeon.id}-boss-defeated`)); + }, +}); + +ToggleIcon.dungeonCheckController = (dungeon, max) => ({ + getActive: (state, icons) => state[`${dungeon.id}-checks`] < max ? icons[1] : null, + getDefault: firstIcon, + handlePrimary: (state, setState) => { + setState(increment(`${dungeon.id}-checks`, max)); + }, + handleSecondary: (state, setState) => { + setState(decrement(`${dungeon.id}-checks`, max)); + }, +}); + +ToggleIcon.dungeonController = dungeon => ({ + getActive: (state, icons) => state[`${dungeon.id}-${icons[0]}`] ? icons[0] : null, + getDefault: firstIcon, + handlePrimary: (state, setState, icons) => { + setState(toggleBoolean(`${dungeon.id}-${icons[0]}`)); + }, + handleSecondary: (state, setState, icons) => { + setState(toggleBoolean(`${dungeon.id}-${icons[0]}`)); + }, +}); + +ToggleIcon.dungeonCountController = (dungeon, max) => ({ + getActive: (state, icons) => state[`${dungeon.id}-${icons[0]}`] ? icons[0] : null, + getDefault: firstIcon, + handlePrimary: (state, setState, icons) => { + setState(increment(`${dungeon.id}-${icons[0]}`, max)); + }, + handleSecondary: (state, setState, icons) => { + setState(decrement(`${dungeon.id}-${icons[0]}`, max)); + }, +}); + +ToggleIcon.dungeonPrizeController = (dungeon) => ({ + getActive: (state) => hasDungeonPrize(state, dungeon) ? getDungeonPrize(state, dungeon) : null, + getDefault: (state) => getDungeonPrize(state, dungeon), + handlePrimary: nextString(`${dungeon.id}-prize`), + handleSecondary: previousString(`${dungeon.id}-prize`), +}); + +ToggleIcon.medallionController = { + getActive: highestActive, + getDefault: firstIcon, + handlePrimary: nextIcon, + handleSecondary: doNothing, +}; + +ToggleIcon.modulusController = ctrl => ({ + getActive: (state, icons) => icons[(state[ctrl] || 0) % icons.length], + getDefault: firstIcon, + handlePrimary: (state, setState, icons) => { + setState(increment(icons[0], icons.length)); + }, + handleSecondary: (state, setState, icons) => { + setState(decrement(icons[0], icons.length)); + }, +}); + +ToggleIcon.nullController = { + getActive: () => null, + getDefault: firstIcon, + handlePrimary: doNothing, + handleSecondary: doNothing, +}; + +ToggleIcon.simpleController = { + getActive: highestActive, + getDefault: firstIcon, + handlePrimary: nextIcon, + handleSecondary: previousIcon, +}; + +ToggleIcon.progressiveController = (master, min, max) => ({ + getActive: (state, icons) => { + const count = Math.max(min, Math.min(max, state[master] || 0)); + return count ? icons[count - 1] : null; + }, + getDefault: firstIcon, + handlePrimary: (state, setState) => { + setState(increment(master, max, min)); + }, + handleSecondary: (state, setState) => { + setState(decrement(master, max, min)); + }, +}); + +ToggleIcon.propTypes = { + active: PropTypes.string, + className: PropTypes.string, + controller: PropTypes.shape({ + handlePrimary: PropTypes.func, + handleSecondary: PropTypes.func, + }), + icons: PropTypes.arrayOf(PropTypes.string), +}; + +export default ToggleIcon; diff --git a/resources/js/components/tracker/Toolbar.js b/resources/js/components/tracker/Toolbar.js new file mode 100644 index 0000000..169d7bc --- /dev/null +++ b/resources/js/components/tracker/Toolbar.js @@ -0,0 +1,41 @@ +import React from 'react'; +import { Container, Navbar } from 'react-bootstrap'; + +import AutoTracking from './AutoTracking'; +import ToggleIcon from './ToggleIcon'; +import { useTracker } from '../../hooks/tracker'; + +const mapWild = { + map: 'wildMap', + compass: 'wildCompass', + 'small-key': 'wildSmall', + 'big-key': 'wildBig', +}; + +const Toolbar = () => { + const { config, setConfig } = useTracker(); + + const controller = React.useMemo(() => ({ + getActive: (state, icons) => config[mapWild[icons[0]]] ? icons[0] : null, + getDefault: (state, icons) => icons[0], + handlePrimary: (state, setState, icons) => { + const prop = mapWild[icons[0]]; + setConfig(c => ({ ...c, [prop]: !c[prop] })); + }, + handleSecondary: () => null, + }), [config, setConfig]); + + return + +
+ + + + +
+ +
+
; +}; + +export default Toolbar; diff --git a/resources/js/components/tracker/index.js b/resources/js/components/tracker/index.js new file mode 100644 index 0000000..5a505b5 --- /dev/null +++ b/resources/js/components/tracker/index.js @@ -0,0 +1,17 @@ +import React from 'react'; + +import Dungeons from './Dungeons'; +import Equipment from './Equipment'; +import Items from './Items'; +import Toolbar from './Toolbar'; + +const Tracker = () => { + return
+ + + + +
; +}; + +export default Tracker; diff --git a/resources/js/components/twitch-bot/GuessingGameAutoTracking.js b/resources/js/components/twitch-bot/GuessingGameAutoTracking.js index 093e121..451c597 100644 --- a/resources/js/components/twitch-bot/GuessingGameAutoTracking.js +++ b/resources/js/components/twitch-bot/GuessingGameAutoTracking.js @@ -9,32 +9,14 @@ import { compareGTBasementState, countGTBasementState, getGTBasementState, + IN_GAME_MODES, + INV_ADDR, + RAM_ADDR, + SRAM_ADDR, + WRAM_ADDR, } from '../../helpers/alttp-ram'; import { useSNES } from '../../hooks/snes'; -const IN_GAME_MODES = [ - 0x05, // loading game - 0x06, // entering dungeon - 0x07, // dungeon - 0x08, // entering overworld - 0x09, // overworld - 0x0A, // entering special overworld - 0x0B, // special overworld - 0x0E, // text/menu/map - 0x0F, // closing spot - 0x10, // opening spot - 0x11, // falling - 0x12, // dying - 0x13, // fanfare - 0x15, // mirror - 0x16, // refill - 0x17, // S&Q - 0x18, // aga 2 cutscene - 0x19, // triforce room - 0x1A, // credits - 0x1B, // spawn select -]; - const GT_TYPES = [ 0x02, // all dungeons 0x03, // defeat ganon @@ -45,21 +27,6 @@ const GT_TYPES = [ 0x0B, // completionist ]; -const FREE_ITEM_MENU = 0x180045; -const GT_CRYSTALS = 0x18019A; -const GANON_TYPE = 0x1801A8; -const SEED_TYPE = 0x180210; -const INIT_SRAM = 0x183000; - -const GAME_MODE = 0x10; -const CURRENT_DUNGEON = 0x10E; -const SAVE_WRAM = 0xF000; -const ROOM_DATA_START = 0x000; -const ROOM_DATA_END = 0x140; -const PYRAMID_SCREEN = 0x2DB; -const BIG_KEYS_1 = 0x366; -const OWNED_CRYSTALS = 0x37A; - const GT_ENTRANCE_ID = 55; const GuessingGameAutoTracking = ({ onSolve, onStart, onStop }) => { @@ -167,7 +134,7 @@ const GuessingGameAutoTracking = ({ onSolve, onStart, onStop }) => { React.useEffect(() => { if (enabled && !status.error && status.connected && status.device) { const checkInGame = () => { - sock.current.readWRAM(GAME_MODE, 1, (data) => { + sock.current.readWRAM(WRAM_ADDR.GAME_MODE, 1, (data) => { setInGame(IN_GAME_MODES.includes(data[0])); }); }; @@ -184,19 +151,19 @@ const GuessingGameAutoTracking = ({ onSolve, onStart, onStop }) => { // refresh static game information React.useEffect(() => { if (!inGame) return; - sock.current.readBytes(SEED_TYPE, 1, (data) => { + sock.current.readBytes(RAM_ADDR.SEED_TYPE, 1, (data) => { setSeedType(data[0]); }); - sock.current.readBytes(GT_CRYSTALS, 1, (data) => { + sock.current.readBytes(RAM_ADDR.GT_CRYSTALS, 1, (data) => { setGTCrystals(data[0]); }); - sock.current.readBytes(GANON_TYPE, 1, (data) => { + sock.current.readBytes(RAM_ADDR.GANON_TYPE, 1, (data) => { setGanonType(data[0]); }); - sock.current.readBytes(FREE_ITEM_MENU, 1, (data) => { + sock.current.readBytes(RAM_ADDR.FREE_ITEM_MENU, 1, (data) => { setFreeItemMenu(data[0]); }); - sock.current.readBytes(INIT_SRAM + PYRAMID_SCREEN, 1, (data) => { + sock.current.readBytes(RAM_ADDR.INIT_SRAM + SRAM_ADDR.PYRAMID_SCREEN, 1, (data) => { setPyramidOpen(!!(data[0] & 0x20)); }); }, [inGame, sock]); @@ -213,7 +180,8 @@ const GuessingGameAutoTracking = ({ onSolve, onStart, onStop }) => { React.useEffect(() => { if (!applicable || !inGame || hasBigKey) return; const updateCrystals = () => { - sock.current.readWRAM(SAVE_WRAM + OWNED_CRYSTALS, 1, (data) => { + const crAddress = WRAM_ADDR.SAVE_DATA + SRAM_ADDR.INV_START + INV_ADDR.CRYSTALS; + sock.current.readWRAM(crAddress, 1, (data) => { let owned = 0; for (let i = 0; i < 7; ++i) { if (data[0] & Math.pow(2, i)) { @@ -235,7 +203,7 @@ const GuessingGameAutoTracking = ({ onSolve, onStart, onStop }) => { if (!applicable || hasBigKey || ownedCrystals !== gtCrystals || hasEntered) return; controls.current.onStart(); const updateDungeon = () => { - sock.current.readWRAM(CURRENT_DUNGEON, 2, (data) => { + sock.current.readWRAM(WRAM_ADDR.CURRENT_DUNGEON, 2, (data) => { setLastEntrance(data[0] + (data[1] * 256)); }); }; @@ -258,8 +226,9 @@ const GuessingGameAutoTracking = ({ onSolve, onStart, onStop }) => { React.useEffect(() => { if (!applicable || !hasEntered || hasBigKey) return; const updateGTState = () => { - const roomDataSize = ROOM_DATA_END - ROOM_DATA_START; - sock.current.readWRAM(SAVE_WRAM + ROOM_DATA_START, roomDataSize, (data) => { + const roomDataStart = WRAM_ADDR.SAVE_DATA + SRAM_ADDR.ROOM_DATA_START; + const roomDataSize = SRAM_ADDR.ROOM_DATA_END - SRAM_ADDR.ROOM_DATA_START; + sock.current.readWRAM(roomDataStart, roomDataSize, (data) => { const gtState = getGTBasementState(data); const gtCount = countGTBasementState(gtState); setBasement(old => { @@ -288,7 +257,8 @@ const GuessingGameAutoTracking = ({ onSolve, onStart, onStop }) => { const solution = basement.last === 'torch' ? basement.torch : basement.count; controls.current.onSolve(solution); } else { - sock.current.readWRAM(SAVE_WRAM + BIG_KEYS_1, 1, (data) => { + const bkAddr = WRAM_ADDR.SAVE_DATA + SRAM_ADDR.INV_START + INV_ADDR.BIG_KEY; + sock.current.readWRAM(bkAddr, 1, (data) => { setHasBigKey(!!(data[0] & 0x04)); }); } diff --git a/resources/js/helpers/alttp-ram.js b/resources/js/helpers/alttp-ram.js index 2ae71cf..d5bfa1b 100644 --- a/resources/js/helpers/alttp-ram.js +++ b/resources/js/helpers/alttp-ram.js @@ -1,3 +1,165 @@ +export const RAM_ADDR = { + PRIZE_MAP: 0x1209B, + FREE_ITEM_MENU: 0x180045, + CRYSTAL_MAP: 0x180050, + GT_CRYSTALS: 0x18019A, + GANON_TYPE: 0x1801A8, + SEED_TYPE: 0x180210, + INIT_SRAM: 0x183000, +}; + +export const SRAM_ADDR = { + ROOM_DATA_START: 0x000, + ROOM_DATA_END: 0x250, + OW_DATA_START: 0x280, + PYRAMID_SCREEN: 0x2DB, + OW_DATA_END: 0x300, + INV_START: 0x340, + INV_END: 0x4EF, +}; + +export const WRAM_ADDR = { + GAME_MODE: 0x10, + CURRENT_DUNGEON: 0x10E, + SAVE_DATA: 0xF000, +}; + +export const INV_ADDR = { + BOW: 0x00, + BOOM: 0x01, + HOOK: 0x02, + BOMB: 0x03, + POWDER: 0x04, + FROD: 0x05, + IROD: 0x06, + BOMBOS: 0x07, + ETHER: 0x08, + QUAKE: 0x09, + LAMP: 0x0A, + HAMMER: 0x0B, + FLUTE: 0x0C, + BUGNET: 0x0D, + BOOK: 0x0E, + BOTTLE: 0x0F, + SOMARIA: 0x10, + BYRNA: 0x11, + CAPE: 0x12, + MIRROR: 0x13, + GLOVE: 0x14, + BOOTS: 0x15, + FLIPPERS: 0x16, + MOONPEARL: 0x17, + SWORD: 0x19, + SHIELD: 0x1A, + ARMOR: 0x1B, + BOTTLE_1: 0x1C, + BOTTLE_2: 0x1D, + BOTTLE_3: 0x1E, + BOTTLE_4: 0x1F, + WALLET: 0x20, + RUPEES: 0x22, + COMPASS: 0x24, + BIG_KEY: 0x26, + MAP: 0x28, + HEART_PIECE: 0x2B, + HEALTH: 0x2C, + MAGIC: 0x2E, + KEYS: 0x2F, + PENDANTS: 0x34, + ARROWS: 0x37, + ABILITIES: 0x39, + CRYSTALS: 0x3A, + MAGIC_USE: 0x3B, + SMALL_KEY_START: 0x3C, + SMALL_KEY_END: 0x4C, + RANDO_BOOM: 0x4C, + RANDO_POWDER: 0x4C, + RANDO_FLUTE: 0x4C, + RANDO_BOW: 0x4E, + RANDO_KEY_START: 0x1A0, + RANDO_KEY_END: 0x1AF, +}; + +export const DUNGEON_IDS = { + SEWERS: 0, + HC: 1, + EP: 2, + DP: 3, + CT: 4, + SP: 5, + PD: 6, + MM: 7, + SW: 8, + IP: 9, + TH: 10, + TT: 11, + TR: 12, + GT: 13, +}; + +export const DUNGEON_MASKS = { + SEWERS: 0x0080, + HC: 0x0040, + EP: 0x0020, + DP: 0x0010, + CT: 0x0008, + SP: 0x0004, + PD: 0x0002, + MM: 0x0001, + SW: 0x8000, + IP: 0x4000, + TH: 0x2000, + TT: 0x1000, + TR: 0x0800, + GT: 0x0400, +}; + +export const ABILITY_MASKS = { + SWIM: 0x02, + DASH: 0x04, + PULL: 0x08, + TALK: 0x20, + READ: 0x40, +}; + +export const IN_GAME_MODES = [ + 0x05, // loading game + 0x06, // entering dungeon + 0x07, // dungeon + 0x08, // entering overworld + 0x09, // overworld + 0x0A, // entering special overworld + 0x0B, // special overworld + 0x0E, // text/menu/map + 0x0F, // closing spot + 0x10, // opening spot + 0x11, // falling + 0x12, // dying + 0x13, // fanfare + 0x15, // mirror + 0x16, // refill + 0x17, // S&Q + 0x18, // aga 2 cutscene + 0x19, // triforce room + 0x1B, // spawn select +]; + +export const getShort = (data, offset) => (data[offset] * 256) + data[offset + 1]; + +export const buildPrizeMap = (prizes, crystals) => { + const map = {}; + Object.entries(DUNGEON_IDS).forEach(([, id]) => { + const isCrystal = !!(crystals && crystals[id]); + const mask = (prizes && prizes[id]) || 0; + map[id] = { isCrystal, mask }; + }); + return map; +}; + +export const isBossDefeated = (data, room) => { + return !!(data && (data[(2 * room) + 1] & 0x08)); +}; + export const isChestOpen = (data, room, chest) => { if (chest < 4) { return !!(data && (data[2 * room] & Math.pow(2, chest + 4))); diff --git a/resources/js/helpers/tracker.js b/resources/js/helpers/tracker.js new file mode 100644 index 0000000..707e3f7 --- /dev/null +++ b/resources/js/helpers/tracker.js @@ -0,0 +1,1753 @@ +import { + DUNGEON_IDS, + DUNGEON_MASKS, + INV_ADDR, + SRAM_ADDR, + getShort, + isBossDefeated, + isChestOpen, +} from './alttp-ram'; + +export const BOOLEAN_STATES = [ + 'blue-boomerang', + 'bomb', + 'bombos', + 'bow', + 'bowless-silvers', + 'book', + 'boots', + 'bugnet', + 'byrna', + 'cape', + 'duck', + 'ether', + 'fire-rod', + 'flippers', + 'flute', + 'half-magic', + 'hammer', + 'hookshot', + 'ice-rod', + 'lamp', + 'mirror', + 'moonpearl', + 'mushroom', + 'powder', + 'quake', + 'quarter-magic', + 'red-boomerang', + 'shovel', + 'silvers', + 'somaria', +]; + +export const INTEGER_STATES = [ + 'bottle', + 'heart-piece', + 'lift', + 'mail', + 'shield', + 'sword', +]; + +export const INITIAL = { + mail: 1, +}; + +export const BOSSES = [ + 'armos', + 'lanmolas', + 'moldorm', + 'helma', + 'arrghus', + 'mothula', + 'blind', + 'kholdstare', + 'vitreous', + 'trinexx', +]; + +export const CONFIG = { + wildMap: false, + wildCompass: false, + wildSmall: false, + wildBig: false, + bossShuffle: false, +}; + +export const DUNGEONS = [ + { + id: 'hc', + map: true, + compass: false, + sk: 1, + bk: true, + dropBk: true, + items: 6, + boss: null, + bosses: [], + bossRoom: 0x80, + prize: false, + offset: DUNGEON_IDS.HC, + mask: DUNGEON_MASKS.HC, + checks: [ + 'dark-cross', + 'hc-map', + 'hc-boom', + 'hc-cell', + 'sanc', + 'sewers-left', + 'sewers-mid', + 'sewers-right', + ], + }, + { + id: 'ct', + map: false, + compass: false, + sk: 2, + bk: false, + items: 0, + boss: 'aga', + bosses: ['aga'], + bossRoom: 0x20, + prize: false, + offset: DUNGEON_IDS.CT, + mask: DUNGEON_MASKS.CT, + checks: [ + 'ct-1', + 'ct-2', + ], + }, + { + id: 'gt', + map: true, + compass: true, + sk: 4, + bk: true, + items: 20, + boss: 'aga', + bosses: ['aga'], + bossRoom: 0x0D, + prize: false, + offset: DUNGEON_IDS.GT, + mask: DUNGEON_MASKS.GT, + checks: [ + 'gt-hope-left', + 'gt-hope-right', + 'gt-tile-room', + 'gt-compass-tl', + 'gt-compass-tr', + 'gt-compass-bl', + 'gt-compass-br', + 'gt-torch', + 'gt-dm-tl', + 'gt-dm-tr', + 'gt-dm-bl', + 'gt-dm-br', + 'gt-map-chest', + 'gt-firesnake', + 'gt-rando-tl', + 'gt-rando-tr', + 'gt-rando-bl', + 'gt-rando-br', + 'gt-bobs-chest', + 'gt-ice-left', + 'gt-ice-mid', + 'gt-ice-right', + 'gt-big-chest', + 'gt-helma-left', + 'gt-helma-right', + 'gt-pre-moldorm', + 'gt-post-moldorm', + ], + }, + { + id: 'ep', + map: true, + compass: true, + sk: 0, + bk: true, + items: 3, + boss: 'armos', + bosses: ['armos'], + bossRoom: 0xC8, + prize: true, + isPendant: true, + prizeMask: 0x04, + offset: DUNGEON_IDS.EP, + mask: DUNGEON_MASKS.EP, + checks: [ + 'ep-cannonball', + 'ep-map-chest', + 'ep-compass-chest', + 'ep-big-chest', + 'ep-big-key-chest', + 'ep-boss-defeated', + ], + }, + { + id: 'dp', + map: true, + compass: true, + sk: 1, + bk: true, + items: 2, + boss: 'lanmolas', + bosses: ['lanmolas'], + bossRoom: 0x33, + prize: true, + isPendant: true, + prizeMask: 0x02, + offset: DUNGEON_IDS.DP, + mask: DUNGEON_MASKS.DP, + checks: [ + 'dp-torch', + 'dp-map-chest', + 'dp-big-chest', + 'dp-compass-chest', + 'dp-big-key-chest', + 'dp-boss-defeated', + ], + }, + { + id: 'th', + map: true, + compass: true, + sk: 1, + bk: true, + items: 2, + boss: 'moldorm', + bosses: ['moldorm'], + bossRoom: 0x07, + prize: true, + isPendant: true, + prizeMask: 0x01, + offset: DUNGEON_IDS.TH, + mask: DUNGEON_MASKS.TH, + checks: [ + 'th-basement-cage', + 'th-map-chest', + 'th-big-key-chest', + 'th-compass-chest', + 'th-big-chest', + 'th-boss-defeated', + ], + }, + { + id: 'pd', + map: true, + compass: true, + sk: 6, + bk: true, + items: 5, + boss: 'helma', + bosses: ['helma'], + bossRoom: 0x5A, + prize: true, + prizeMask: 0x02, + offset: DUNGEON_IDS.PD, + mask: DUNGEON_MASKS.PD, + checks: [ + 'pd-shooter-room', + 'pd-stalfos-basement', + 'pd-big-key-chest', + 'pd-arena-bridge', + 'pd-arena-ledge', + 'pd-map-chest', + 'pd-compass-chest', + 'pd-basement-left', + 'pd-basement-right', + 'pd-harmless-hellway', + 'pd-maze-top', + 'pd-maze-bottom', + 'pd-big-chest', + 'pd-boss-defeated', + ], + }, + { + id: 'sp', + map: true, + compass: true, + sk: 1, + bk: true, + items: 6, + boss: 'arrghus', + bosses: ['arrghus'], + bossRoom: 0x06, + prize: true, + prizeMask: 0x10, + offset: DUNGEON_IDS.SP, + mask: DUNGEON_MASKS.SP, + checks: [ + 'sp-lobby', + 'sp-map-chest', + 'sp-big-chest', + 'sp-compass-chest', + 'sp-west-chest', + 'sp-big-key-chest', + 'sp-flooded-left', + 'sp-flooded-right', + 'sp-waterfall', + 'sp-boss-defeated', + ], + }, + { + id: 'sw', + map: true, + compass: true, + sk: 3, + bk: true, + items: 2, + boss: 'mothula', + bosses: ['mothula'], + bossRoom: 0x29, + prize: true, + prizeMask: 0x40, + offset: DUNGEON_IDS.SW, + mask: DUNGEON_MASKS.SW, + checks: [ + 'sw-big-chest', + 'sw-map-chest', + 'sw-pot-prison', + 'sw-compass-chest', + 'sw-pinball-room', + 'sw-big-key-chest', + 'sw-bridge-chest', + 'sw-boss-defeated', + ], + }, + { + id: 'tt', + map: true, + compass: true, + sk: 1, + bk: true, + items: 4, + boss: 'blind', + bosses: ['blind'], + bossRoom: 0xAC, + prize: true, + prizeMask: 0x20, + offset: DUNGEON_IDS.TT, + mask: DUNGEON_MASKS.TT, + checks: [ + 'tt-map-chest', + 'tt-ambush-chest', + 'tt-compass-chest', + 'tt-big-key-chest', + 'tt-attic', + 'tt-cell', + 'tt-big-chest', + 'tt-boss-defeated', + ], + }, + { + id: 'ip', + map: true, + compass: true, + sk: 2, + bk: true, + items: 3, + boss: 'kholdstare', + bosses: ['kholdstare'], + bossRoom: 0xDE, + prize: true, + prizeMask: 0x04, + offset: DUNGEON_IDS.IP, + mask: DUNGEON_MASKS.IP, + checks: [ + 'ip-compass-chest', + 'ip-big-key-chest', + 'ip-map-chest', + 'ip-spike-chest', + 'ip-freezor-chest', + 'ip-big-chest', + 'ip-ice-t', + 'ip-boss-defeated', + ], + }, + { + id: 'mm', + map: true, + compass: true, + sk: 3, + bk: true, + items: 2, + boss: 'vitreous', + bosses: ['vitreous'], + bossRoom: 0x90, + prize: true, + prizeMask: 0x01, + offset: DUNGEON_IDS.MM, + mask: DUNGEON_MASKS.MM, + checks: [ + 'mm-bridge-chest', + 'mm-spike-chest', + 'mm-lobby-chest', + 'mm-compass-chest', + 'mm-big-key-chest', + 'mm-big-chest', + 'mm-map-chest', + 'mm-boss-defeated', + ], + }, + { + id: 'tr', + map: true, + compass: true, + sk: 4, + bk: true, + items: 5, + boss: 'trinexx', + bosses: ['trinexx'], + bossRoom: 0xA4, + prize: true, + prizeMask: 0x08, + offset: DUNGEON_IDS.TR, + mask: DUNGEON_MASKS.TR, + checks: [ + 'tr-roller-left', + 'tr-roller-right', + 'tr-compass-chest', + 'tr-chomps', + 'tr-big-key-chest', + 'tr-big-chest', + 'tr-crysta-roller', + 'tr-laser-bridge-top', + 'tr-laser-bridge-left', + 'tr-laser-bridge-right', + 'tr-laser-bridge-bottom', + 'tr-boss-defeated', + ], + }, +]; + +export const OVERWORLD_LOCATIONS = [ + { + id: 'blacksmith', + address: 0x411, + mask: 0x04, + }, + { + id: 'bombos-tablet', + address: 0x411, + mask: 0x02, + }, + { + id: 'bottle-vendor', + address: 0x3C9, + mask: 0x02, + }, + { + id: 'bumper-cave', + address: 0x2CA, + mask: 0x40, + }, + { + id: 'catfish', + address: 0x410, + mask: 0x20, + }, + { + id: 'desert-ledge', + address: 0x2B0, + mask: 0x40, + }, + { + id: 'digging-game', + address: 0x2E8, + mask: 0x40, + }, + { + id: 'ether-tablet', + address: 0x411, + mask: 0x01, + }, + { + id: 'floating-island', + address: 0x285, + mask: 0x40, + }, + { + id: 'flute-spot', + address: 0x2AA, + mask: 0x40, + }, + { + id: 'hobo', + address: 0x3C9, + mask: 0x01, + }, + { + id: 'lake-hylia-island', + address: 0x2B5, + mask: 0x40, + }, + { + id: 'library', + address: 0x410, + mask: 0x80, + }, + { + id: 'magic-bat', + address: 0x411, + mask: 0x80, + }, + { + id: 'mushroom-spot', + address: 0x411, + mask: 0x10, + }, + { + id: 'old-man', + address: 0x410, + mask: 0x01, + }, + { + id: 'pedestal', + address: 0x300, + mask: 0x40, + }, + { + id: 'potion-shop', + address: 0x411, + mask: 0x20, + }, + { + id: 'purple-chest', + address: 0x3C9, + mask: 0x10, + }, + { + id: 'pyramid', + address: 0x2DB, + mask: 0x40, + }, + { + id: 'race-game', + address: 0x2A8, + mask: 0x40, + }, + { + id: 'saha', + address: 0x410, + mask: 0x10, + }, + { + id: 'sick-kid', + address: 0x410, + mask: 0x04, + }, + { + id: 'spec-rock', + address: 0x283, + mask: 0x40, + }, + { + id: 'stumpy', + address: 0x410, + mask: 0x08, + }, + { + id: 'sunken-treasure', + address: 0x2BB, + mask: 0x40, + }, + { + id: 'uncle', + address: 0x3C6, + mask: 0x01, + }, + { + id: 'zora', + address: 0x410, + mask: 0x02, + }, + { + id: 'zora-ledge', + address: 0x301, + mask: 0x40, + }, +]; + +export const UNDERWORLD_LOCATIONS = [ + { + id: 'aginah', + room: 0x10A, + chest: 0, + }, + { + id: 'blinds-hut-top', + room: 0x11D, + chest: 0, + }, + { + id: 'blinds-hut-left', + room: 0x11D, + chest: 1, + }, + { + id: 'blinds-hut-right', + room: 0x11D, + chest: 2, + }, + { + id: 'blinds-hut-far-left', + room: 0x11D, + chest: 3, + }, + { + id: 'blinds-hut-far-right', + room: 0x11D, + chest: 4, + }, + { + id: 'bonk-rocks', + room: 0x124, + chest: 0, + }, + { + id: 'brewery', + room: 0x106, + chest: 0, + }, + { + id: 'c-house', + room: 0x11C, + chest: 0, + }, + { + id: 'cave-45', + room: 0x11B, + chest: 6, + }, + { + id: 'checkerboard', + room: 0x126, + chest: 5, + }, + { + id: 'chest-game', + room: 0x106, + chest: 6, + }, + { + id: 'chicken-house', + room: 0x108, + chest: 0, + }, + { + id: 'ct-1', + area: 'ct', + room: 0xE0, + chest: 0, + }, + { + id: 'ct-2', + area: 'ct', + room: 0xD0, + chest: 0, + }, + { + id: 'dark-cross', + area: 'hc', + room: 0x32, + chest: 0, + }, + { + id: 'dp-big-chest', + area: 'dp', + room: 0x73, + chest: 0, + }, + { + id: 'dp-big-key-chest', + area: 'dp', + room: 0x75, + chest: 0, + }, + { + id: 'dp-compass-chest', + area: 'dp', + room: 0x85, + chest: 0, + }, + { + id: 'dp-map-chest', + area: 'dp', + room: 0x74, + chest: 0, + }, + { + id: 'dp-torch', + area: 'dp', + room: 0x73, + chest: 6, + }, + { + id: 'ep-big-chest', + area: 'ep', + room: 0xA9, + chest: 0, + }, + { + id: 'ep-big-key-chest', + area: 'ep', + room: 0xB8, + chest: 0, + }, + { + id: 'ep-cannonball', + area: 'ep', + room: 0xB9, + chest: 0, + }, + { + id: 'ep-compass-chest', + area: 'ep', + room: 0xA8, + chest: 0, + }, + { + id: 'ep-map-chest', + area: 'ep', + room: 0xAA, + chest: 0, + }, + { + id: 'flooded-chest', + room: 0x10B, + chest: 0, + }, + { + id: 'graveyard-ledge', + room: 0x11B, + chest: 5, + }, + { + id: 'gt-hope-left', + area: 'gt', + room: 0x8C, + chest: 1, + }, + { + id: 'gt-hope-right', + area: 'gt', + room: 0x8C, + chest: 2, + }, + { + id: 'gt-tile-room', + area: 'gt', + room: 0x8D, + chest: 0, + }, + { + id: 'gt-compass-tl', + area: 'gt', + room: 0x9D, + chest: 0, + }, + { + id: 'gt-compass-tr', + area: 'gt', + room: 0x9D, + chest: 1, + }, + { + id: 'gt-compass-bl', + area: 'gt', + room: 0x9D, + chest: 2, + }, + { + id: 'gt-compass-br', + area: 'gt', + room: 0x9D, + chest: 3, + }, + { + id: 'gt-torch', + area: 'gt', + room: 0x8C, + chest: 6, + }, + { + id: 'gt-dm-tl', + area: 'gt', + room: 0x7B, + chest: 0, + }, + { + id: 'gt-dm-tr', + area: 'gt', + room: 0x7B, + chest: 1, + }, + { + id: 'gt-dm-bl', + area: 'gt', + room: 0x7B, + chest: 2, + }, + { + id: 'gt-dm-br', + area: 'gt', + room: 0x7B, + chest: 3, + }, + { + id: 'gt-map-chest', + area: 'gt', + room: 0x8B, + chest: 0, + }, + { + id: 'gt-firesnake', + area: 'gt', + room: 0x7D, + chest: 0, + }, + { + id: 'gt-rando-tl', + area: 'gt', + room: 0x7C, + chest: 0, + }, + { + id: 'gt-rando-tr', + area: 'gt', + room: 0x7C, + chest: 1, + }, + { + id: 'gt-rando-bl', + area: 'gt', + room: 0x7C, + chest: 2, + }, + { + id: 'gt-rando-br', + area: 'gt', + room: 0x7C, + chest: 3, + }, + { + id: 'gt-bobs-chest', + area: 'gt', + room: 0x8C, + chest: 3, + }, + { + id: 'gt-ice-left', + area: 'gt', + room: 0x1C, + chest: 1, + }, + { + id: 'gt-ice-mid', + area: 'gt', + room: 0x1C, + chest: 0, + }, + { + id: 'gt-ice-right', + area: 'gt', + room: 0x1C, + chest: 2, + }, + { + id: 'gt-big-chest', + area: 'gt', + room: 0x8C, + chest: 0, + }, + { + id: 'gt-helma-left', + area: 'gt', + room: 0x3D, + chest: 0, + }, + { + id: 'gt-helma-right', + area: 'gt', + room: 0x3D, + chest: 1, + }, + { + id: 'gt-pre-moldorm', + area: 'gt', + room: 0x3D, + chest: 2, + }, + { + id: 'gt-post-moldorm', + area: 'gt', + room: 0x4D, + chest: 0, + }, + { + id: 'hammer-pegs', + room: 0x127, + chest: 6, + }, + { + id: 'hc-boom', + area: 'hc', + room: 0x71, + chest: 0, + }, + { + id: 'hc-cell', + area: 'hc', + room: 0x80, + chest: 0, + }, + { + id: 'hc-map', + area: 'hc', + room: 0x72, + chest: 0, + }, + { + id: 'hookshot-cave-br', + room: 0x3C, + chest: 3, + }, + { + id: 'hookshot-cave-tr', + room: 0x3C, + chest: 0, + }, + { + id: 'hookshot-cave-tl', + room: 0x3C, + chest: 1, + }, + { + id: 'hookshot-cave-bl', + room: 0x3C, + chest: 2, + }, + { + id: 'hype-cave-top', + room: 0x11E, + chest: 0, + }, + { + id: 'hype-cave-left', + room: 0x11E, + chest: 1, + }, + { + id: 'hype-cave-right', + room: 0x11E, + chest: 2, + }, + { + id: 'hype-cave-bottom', + room: 0x11E, + chest: 4, + }, + { + id: 'hype-cave-npc', + room: 0x11E, + chest: 6, + }, + { + id: 'ice-rod-cave', + room: 0x120, + chest: 0, + }, + { + id: 'ip-compass-chest', + area: 'ip', + room: 0x2E, + chest: 0, + }, + { + id: 'ip-big-key-chest', + area: 'ip', + room: 0x1F, + chest: 0, + }, + { + id: 'ip-map-chest', + area: 'ip', + room: 0x3F, + chest: 0, + }, + { + id: 'ip-spike-chest', + area: 'ip', + room: 0x5F, + chest: 0, + }, + { + id: 'ip-freezor-chest', + area: 'ip', + room: 0x7E, + chest: 0, + }, + { + id: 'ip-big-chest', + area: 'ip', + room: 0x9E, + chest: 0, + }, + { + id: 'ip-ice-t', + area: 'ip', + room: 0xAE, + chest: 0, + }, + { + id: 'kak-well-top', + room: 0x2F, + chest: 0, + }, + { + id: 'kak-well-left', + room: 0x2F, + chest: 1, + }, + { + id: 'kak-well-mid', + room: 0x2F, + chest: 2, + }, + { + id: 'kak-well-right', + room: 0x2F, + chest: 3, + }, + { + id: 'kak-well-bottom', + room: 0x2F, + chest: 4, + }, + { + id: 'kings-tomb', + room: 0x113, + chest: 0, + }, + { + id: 'links-house', + room: 0x104, + chest: 0, + }, + { + id: 'lost-woods-hideout', + room: 0xE1, + chest: 5, + }, + { + id: 'lumberjack', + room: 0xE2, + chest: 5, + }, + { + id: 'mimic-cave', + room: 0x10C, + chest: 0, + }, + { + id: 'mini-moldorm-far-left', + room: 0x123, + chest: 0, + }, + { + id: 'mini-moldorm-left', + room: 0x123, + chest: 1, + }, + { + id: 'mini-moldorm-right', + room: 0x123, + chest: 2, + }, + { + id: 'mini-moldorm-far-right', + room: 0x123, + chest: 3, + }, + { + id: 'mini-moldorm-npc', + room: 0x123, + chest: 6, + }, + { + id: 'mm-bridge-chest', + room: 0xA2, + chest: 0, + }, + { + id: 'mm-spike-chest', + room: 0xB3, + chest: 0, + }, + { + id: 'mm-lobby-chest', + room: 0xC2, + chest: 0, + }, + { + id: 'mm-compass-chest', + room: 0xC1, + chest: 0, + }, + { + id: 'mm-big-key-chest', + room: 0xD1, + chest: 0, + }, + { + id: 'mm-big-chest', + room: 0xC3, + chest: 0, + }, + { + id: 'mm-map-chest', + room: 0xC3, + chest: 1, + }, + { + id: 'mire-shed-left', + room: 0x10D, + chest: 0, + }, + { + id: 'mire-shed-right', + room: 0x10D, + chest: 1, + }, + { + id: 'paradox-lower-far-left', + room: 0xEF, + chest: 0, + }, + { + id: 'paradox-lower-left', + room: 0xEF, + chest: 1, + }, + { + id: 'paradox-lower-right', + room: 0xEF, + chest: 2, + }, + { + id: 'paradox-lower-far-right', + room: 0xEF, + chest: 4, + }, + { + id: 'paradox-lower-mid', + room: 0xEF, + chest: 5, + }, + { + id: 'paradox-upper-left', + room: 0xFF, + chest: 0, + }, + { + id: 'paradox-upper-right', + room: 0xFF, + chest: 1, + }, + { + id: 'pd-shooter-room', + room: 0x09, + chest: 0, + }, + { + id: 'pd-stalfos-basement', + room: 0x0A, + chest: 0, + }, + { + id: 'pd-big-key-chest', + room: 0x3A, + chest: 0, + }, + { + id: 'pd-arena-bridge', + room: 0x2A, + chest: 1, + }, + { + id: 'pd-arena-ledge', + room: 0x2A, + chest: 0, + }, + { + id: 'pd-map-chest', + room: 0x2B, + chest: 0, + }, + { + id: 'pd-big-chest', + room: 0x1A, + chest: 0, + }, + { + id: 'pd-compass-chest', + room: 0x1A, + chest: 1, + }, + { + id: 'pd-harmless-hellway', + room: 0x1A, + chest: 2, + }, + { + id: 'pd-maze-top', + room: 0x19, + chest: 0, + }, + { + id: 'pd-maze-bottom', + room: 0x19, + chest: 1, + }, + { + id: 'pd-basement-left', + room: 0x6A, + chest: 0, + }, + { + id: 'pd-basement-right', + room: 0x6A, + chest: 1, + }, + { + id: 'pyramid-fairy-left', + room: 0x116, + chest: 0, + }, + { + id: 'pyramid-fairy-right', + room: 0x116, + chest: 1, + }, + { + id: 'saha-left', + room: 0x105, + chest: 0, + }, + { + id: 'saha-mid', + room: 0x105, + chest: 1, + }, + { + id: 'saha-right', + room: 0x105, + chest: 2, + }, + { + id: 'sanc', + area: 'hc', + room: 0x12, + chest: 0, + }, + { + id: 'secret-passage', + room: 0x55, + chest: 0, + }, + { + id: 'sewers-left', + area: 'hc', + room: 0x11, + chest: 0, + }, + { + id: 'sewers-mid', + area: 'hc', + room: 0x11, + chest: 1, + }, + { + id: 'sewers-right', + area: 'hc', + room: 0x11, + chest: 2, + }, + { + id: 'sp-lobby', + area: 'sp', + room: 0x28, + chest: 0, + }, + { + id: 'sp-map-chest', + area: 'sp', + room: 0x37, + chest: 0, + }, + { + id: 'sp-big-chest', + area: 'sp', + room: 0x36, + chest: 0, + }, + { + id: 'sp-compass-chest', + area: 'sp', + room: 0x46, + chest: 0, + }, + { + id: 'sp-west-chest', + area: 'sp', + room: 0x34, + chest: 0, + }, + { + id: 'sp-big-key-chest', + area: 'sp', + room: 0x35, + chest: 0, + }, + { + id: 'sp-flooded-left', + area: 'sp', + room: 0x76, + chest: 0, + }, + { + id: 'sp-flooded-right', + area: 'sp', + room: 0x76, + chest: 1, + }, + { + id: 'sp-waterfall', + area: 'sp', + room: 0x66, + chest: 0, + }, + { + id: 'spec-rock-cave', + room: 0xEA, + chest: 6, + }, + { + id: 'spike-cave', + room: 0x117, + chest: 0, + }, + { + id: 'spiral-cave', + room: 0xFE, + chest: 0, + }, + { + id: 'super-bunny-top', + room: 0xF8, + chest: 0, + }, + { + id: 'super-bunny-bottom', + room: 0xF8, + chest: 0, + }, + { + id: 'sw-big-chest', + area: 'sw', + room: 0x58, + chest: 0, + }, + { + id: 'sw-map-chest', + area: 'sw', + room: 0x58, + chest: 1, + }, + { + id: 'sw-compass-chest', + area: 'sw', + room: 0x67, + chest: 0, + }, + { + id: 'sw-big-key-chest', + area: 'sw', + room: 0x57, + chest: 0, + }, + { + id: 'sw-pot-prison', + area: 'sw', + room: 0x57, + chest: 1, + }, + { + id: 'sw-pinball-room', + area: 'sw', + room: 0x68, + chest: 0, + }, + { + id: 'sw-bridge-chest', + area: 'sw', + room: 0x59, + chest: 0, + }, + { + id: 'tavern', + room: 0x103, + chest: 0, + }, + { + id: 'th-basement-cage', + area: 'th', + room: 0x87, + chest: 6, + }, + { + id: 'th-big-key-chest', + area: 'th', + room: 0x87, + chest: 0, + }, + { + id: 'th-map-chest', + area: 'th', + room: 0x77, + chest: 0, + }, + { + id: 'th-big-chest', + area: 'th', + room: 0x27, + chest: 0, + }, + { + id: 'th-compass-chest', + area: 'th', + room: 0x27, + chest: 1, + }, + { + id: 'tr-roller-left', + area: 'tr', + room: 0xB7, + chest: 0, + }, + { + id: 'tr-roller-right', + area: 'tr', + room: 0xB7, + chest: 1, + }, + { + id: 'tr-compass-chest', + area: 'tr', + room: 0xD6, + chest: 0, + }, + { + id: 'tr-chomps', + area: 'tr', + room: 0xB6, + chest: 0, + }, + { + id: 'tr-big-key-chest', + area: 'tr', + room: 0x14, + chest: 0, + }, + { + id: 'tr-big-chest', + area: 'tr', + room: 0x24, + chest: 0, + }, + { + id: 'tr-crysta-roller', + area: 'tr', + room: 0x04, + chest: 0, + }, + { + id: 'tr-laser-bridge-top', + area: 'tr', + room: 0xD5, + chest: 0, + }, + { + id: 'tr-laser-bridge-left', + area: 'tr', + room: 0xD5, + chest: 1, + }, + { + id: 'tr-laser-bridge-right', + area: 'tr', + room: 0xD5, + chest: 2, + }, + { + id: 'tr-laser-bridge-bottom', + area: 'tr', + room: 0xD5, + chest: 3, + }, + { + id: 'tt-map-chest', + area: 'tt', + room: 0xDB, + chest: 0, + }, + { + id: 'tt-big-key-chest', + area: 'tt', + room: 0xDB, + chest: 1, + }, + { + id: 'tt-ambush-chest', + area: 'tt', + room: 0xCB, + chest: 0, + }, + { + id: 'tt-compass-chest', + area: 'tt', + room: 0xDC, + chest: 0, + }, + { + id: 'tt-attic', + area: 'tt', + room: 0x65, + chest: 0, + }, + { + id: 'tt-cell', + area: 'tt', + room: 0x45, + chest: 0, + }, + { + id: 'tt-big-chest', + area: 'tt', + room: 0x44, + chest: 0, + }, + { + id: 'waterfall-fairy-left', + room: 0x114, + chest: 4, + }, + { + id: 'waterfall-fairy-right', + room: 0x114, + chest: 5, + }, +]; + +export const toggleBoolean = name => state => ({ + ...state, + [name]: !state[name], +}); + +export const increment = (name, max, skipZero) => state => { + let newValue = ((state[name] || 0) + 1) % (max + 1); + if (skipZero && !newValue) { + newValue = 1; + } + return { + ...state, + [name]: newValue, + }; +}; + +export const decrement = (name, max, skipZero) => state => { + let newValue = ((state[name] || 0) + max) % (max + 1); + if (skipZero && !newValue) { + newValue = max; + } + return { + ...state, + [name]: newValue, + }; +}; + +export const highestActive = (state, names) => { + for (let i = names.length; i >= 0; --i) { + if (state[names[i]]) { + return names[i]; + } + } + return null; +}; + +export const hasDungeonBoss = (state, dungeon) => !!state[`${dungeon.id}-boss-defeated`]; + +export const getDungeonBoss = (state, dungeon) => + state[`${dungeon.id}-boss`] || dungeon.boss || null; + +export const hasDungeonPrize = (state, dungeon) => !!state[`${dungeon.id}-prize-acquired`]; + +export const getDungeonPrize = (state, dungeon) => state[`${dungeon.id}-prize`] || null; + +export const makeEmptyState = () => { + const state = {}; + BOOLEAN_STATES.forEach(p => { + state[p] = INITIAL[p] || false; + }); + INTEGER_STATES.forEach(p => { + state[p] = INITIAL[p] || 0; + }); + DUNGEONS.forEach(dungeon => { + state[`${dungeon.id}-map`] = false; + state[`${dungeon.id}-compass`] = false; + state[`${dungeon.id}-small-key`] = 0; + state[`${dungeon.id}-big-key`] = false; + state[`${dungeon.id}-checks`] = 0; + if (dungeon.boss) { + state[`${dungeon.id}-boss`] = dungeon.boss; + state[`${dungeon.id}-boss-defeated`] = false; + } + if (dungeon.prize) { + state[`${dungeon.id}-prize`] = 'crystal'; + state[`${dungeon.id}-prize-acquired`] = false; + } + }); + return state; +}; + +const collectInventory = (state, data, prizeMap) => { + state.bow = !!(data[INV_ADDR.RANDO_BOW] & 0x80); + state.silvers = (data[INV_ADDR.RANDO_BOW] & 0xC0) == 0xC0; + state['bowless-silvers'] = (data[INV_ADDR.RANDO_BOW] & 0xC0) == 0x40; + state['blue-boomerang'] = !!(data[INV_ADDR.RANDO_BOOM] & 0x40); + state['red-boomerang'] = !!(data[INV_ADDR.RANDO_BOOM] & 0x80); + state.hookshot = !!data[INV_ADDR.HOOK]; + state.bomb = data[INV_ADDR.BOMB]; + state.mushroom = !!(data[INV_ADDR.RANDO_POWDER] & 0x20); + state.powder = !!(data[INV_ADDR.RANDO_POWDER] & 0x10); + state['fire-rod'] = !!data[INV_ADDR.FROD]; + state['ice-rod'] = !!data[INV_ADDR.IROD]; + state.bombos = !!data[INV_ADDR.BOMBOS]; + state.ether = !!data[INV_ADDR.ETHER]; + state.quake = !!data[INV_ADDR.QUAKE]; + state.lamp = !!data[INV_ADDR.LAMP]; + state.hammer = !!data[INV_ADDR.HAMMER]; + state.shovel = !!(data[INV_ADDR.RANDO_FLUTE] & 0x04); + state.flute = !!(data[INV_ADDR.RANDO_FLUTE] & 0x03); + state.duck = !!(data[INV_ADDR.RANDO_FLUTE] & 0x01); + state.bugnet = !!data[INV_ADDR.BUGNET]; + state.book = !!data[INV_ADDR.BOOK]; + state.bottle = 0; + if (data[INV_ADDR.BOTTLE_1]) { + ++state.bottle; + } + if (data[INV_ADDR.BOTTLE_2]) { + ++state.bottle; + } + if (data[INV_ADDR.BOTTLE_3]) { + ++state.bottle; + } + if (data[INV_ADDR.BOTTLE_4]) { + ++state.bottle; + } + state.somaria = !!data[INV_ADDR.SOMARIA]; + state.byrna = !!data[INV_ADDR.BYRNA]; + state.cape = !!data[INV_ADDR.CAPE]; + state.mirror = !!data[INV_ADDR.MIRROR]; + state.lift = data[INV_ADDR.GLOVE]; + state.boots = !!data[INV_ADDR.BOOTS]; + state.flippers = !!data[INV_ADDR.FLIPPERS]; + state.moonpearl = !!data[INV_ADDR.MOONPEARL]; + state.sword = data[INV_ADDR.SWORD]; + state.shield = data[INV_ADDR.SHIELD]; + state.mail = data[INV_ADDR.ARMOR] + 1; + state['heart-piece'] = data[INV_ADDR.HEART_PIECE]; + state['half-magic'] = data[INV_ADDR.MAGIC_USE] > 0; + state['quarter-magic'] = data[INV_ADDR.MAGIC_USE] > 1; + const map = getShort(data, INV_ADDR.MAP); + const compass = getShort(data, INV_ADDR.COMPASS); + const bigKey = getShort(data, INV_ADDR.BIG_KEY); + DUNGEONS.forEach(dungeon => { + state[`${dungeon.id}-map`] = !!(map & dungeon.mask); + state[`${dungeon.id}-compass`] = !!(compass & dungeon.mask); + state[`${dungeon.id}-small-key`] = data[INV_ADDR.RANDO_KEY_START + dungeon.offset]; + state[`${dungeon.id}-big-key`] = !!(bigKey & dungeon.mask); + if (dungeon.prize) { + const isCrystal = prizeMap[dungeon.offset].isCrystal; + const prizeFlags = data[isCrystal ? INV_ADDR.CRYSTALS : INV_ADDR.PENDANTS]; + state[`${dungeon.id}-prize-acquired`] = !!(prizeFlags & prizeMap[dungeon.offset].mask); + } + }); +}; + +const collectOverworld = (state, data) => { + OVERWORLD_LOCATIONS.forEach(location => { + state[location.id] = !!(data[location.address] & location.mask); + }); +}; + +const collectUnderworld = (state, data) => { + UNDERWORLD_LOCATIONS.forEach(location => { + state[location.id] = isChestOpen(data, location.room, location.chest); + }); + DUNGEONS.forEach(dungeon => { + state[`${dungeon.id}-boss-defeated`] = isBossDefeated(data, dungeon.bossRoom); + }); +}; + +export const computeState = (data, prizeMap) => { + const state = {}; + collectInventory(state, data.slice(SRAM_ADDR.INV_START), prizeMap); + collectOverworld(state, data); + collectUnderworld(state, data.slice(SRAM_ADDR.ROOM_DATA_START)); + return state; +}; + +const getDungeonAmounts = (config, state) => { + const amounts = {}; + DUNGEONS.forEach(dungeon => { + let amount = 0; + let total = dungeon.checks.length; + dungeon.checks.forEach(check => { + if (state[check]) { + ++amount; + } + }); + if (!config.wildMap && state[`${dungeon.id}-map`]) { + --amount; + --total; + } + if (!config.wildCompass && state[`${dungeon.id}-compass`]) { + --amount; + --total; + } + if (!config.wildSmall) { + amount -= Math.min(state[`${dungeon.id}-small-key`], dungeon.sk); + total -= dungeon.sk; + } + if (!config.wildBig && !dungeon.dropBk && state[`${dungeon.id}-big-key`]) { + --amount; + --total; + } + amounts[dungeon.id] = Math.min(total, amount); + }); + return amounts; +}; + +export const mergeStates = (config, cur, inc) => { + const next = { ...cur, ...inc }; + const amounts = getDungeonAmounts(config, inc); + DUNGEONS.forEach(dungeon => { + next[`${dungeon.id}-checks`] = amounts[dungeon.id]; + }); + //console.log(next); + return next; +}; diff --git a/resources/js/hooks/tracker.js b/resources/js/hooks/tracker.js new file mode 100644 index 0000000..be5a52f --- /dev/null +++ b/resources/js/hooks/tracker.js @@ -0,0 +1,49 @@ +import PropTypes from 'prop-types'; +import React from 'react'; + +import { CONFIG, DUNGEONS, makeEmptyState } from '../helpers/tracker'; + +const context = React.createContext({}); + +export const useTracker = () => React.useContext(context); + +export const TrackerProvider = ({ children }) => { + const [config, setConfig] = React.useState(CONFIG); + const [state, setState] = React.useState(makeEmptyState()); + const [dungeons, setDungeons] = React.useState(DUNGEONS); + + React.useEffect(() => { + const newDungeons = DUNGEONS.map(dungeon => { + const newDungeon = JSON.parse(JSON.stringify(dungeon)); + if (config.wildMap && dungeon.map) { + ++newDungeon.items; + } + if (config.wildCompass && dungeon.compass) { + ++newDungeon.items; + } + if (config.wildSmall) { + newDungeon.items += dungeon.sk; + } + if (config.wildBig && dungeon.bk && !dungeon.dropBk) { + ++newDungeon.items; + } + if (!config.bossShuffle && dungeon.boss) { + newDungeon.bosses = [dungeon.boss]; + } + return newDungeon; + }); + setDungeons(newDungeons); + }, [config]); + + const value = React.useMemo(() => { + return { config, setConfig, dungeons, setState, state }; + }, [config, dungeons, state]); + + return + {children} + ; +}; + +TrackerProvider.propTypes = { + children: PropTypes.node, +}; diff --git a/resources/js/i18n/de.js b/resources/js/i18n/de.js index b8442dc..3b6240c 100644 --- a/resources/js/i18n/de.js +++ b/resources/js/i18n/de.js @@ -242,6 +242,7 @@ export default { 'bottle-bee': 'Bee in a Bottle', bottle: 'Bottle', bow: 'Bow', + 'bowless-silvers': 'Silvers ohne Bow', bugnet: 'Bugnet', byrna: 'Cane of Byrna', cape: 'Cape', @@ -270,9 +271,11 @@ export default { flippers: 'Flippers', flute: 'Flute', glove: 'Power Glove', + 'gold-sword': 'Gold Sword', 'green-mail': 'Green Mail', 'green-pendant': 'Pendant of Courage', 'green-potion': 'Green Potion', + 'half-magic': 'Half Magic', hammer: 'Hammer', 'heart-container': 'Heart Container', 'heart-piece': 'Heart Piece', @@ -280,6 +283,7 @@ export default { 'ice-rod': 'Ice Rod', lamp: 'Lamp', map: 'Map', + 'master-sword': 'Master Sword', mirror: 'Mirror', 'mirror-shield': 'Mirror Shield', mitts: 'Titan \'s Mitts', @@ -290,6 +294,7 @@ export default { 'not-moonpearl': 'Keine Moonpearl', powder: 'Powder', quake: 'Quake', + 'quarter-magic': 'Quarter Magic', 'red-bomb': 'Red Bomb', 'red-boomerang': 'Red Boomerang', 'red-mail': 'Red Mail', @@ -299,6 +304,7 @@ export default { silvers: 'Silvers', 'small-key': 'Small Key', somaria: 'Cane of Somaria', + 'tempered-sword': 'Tempered Sword', }, }, map: { diff --git a/resources/js/i18n/en.js b/resources/js/i18n/en.js index c5efdf4..b4acc0c 100644 --- a/resources/js/i18n/en.js +++ b/resources/js/i18n/en.js @@ -242,6 +242,7 @@ export default { 'bottle-bee': 'Bee in a Bottle', bottle: 'Bottle', bow: 'Bow', + 'bowless-silvers': 'Silvers w/o Bow', bugnet: 'Bugnet', byrna: 'Cane of Byrna', cape: 'Cape', @@ -270,9 +271,11 @@ export default { flippers: 'Flippers', flute: 'Flute', glove: 'Power Glove', + 'gold-sword': 'Gold Sword', 'green-mail': 'Green Mail', 'green-pendant': 'Pendant of Courage', 'green-potion': 'Green Potion', + 'half-magic': 'Half Magic', hammer: 'Hammer', 'heart-container': 'Heart Container', 'heart-piece': 'Heart Piece', @@ -280,6 +283,7 @@ export default { 'ice-rod': 'Ice Rod', lamp: 'Lamp', map: 'Map', + 'master-sword': 'Master Sword', mirror: 'Mirror', 'mirror-shield': 'Mirror Shield', mitts: 'Titan \'s Mitts', @@ -290,6 +294,7 @@ export default { 'not-moonpearl': 'No Moonpearl', powder: 'Powder', quake: 'Quake', + 'quarter-magic': 'Quarter Magic', 'red-bomb': 'Red Bomb', 'red-boomerang': 'Red Boomerang', 'red-mail': 'Red Mail', @@ -299,6 +304,7 @@ export default { silvers: 'Silvers', 'small-key': 'Small Key', somaria: 'Cane of Somaria', + 'tempered-sword': 'Tempered Sword', }, }, map: { diff --git a/resources/js/pages/Tracker.js b/resources/js/pages/Tracker.js new file mode 100644 index 0000000..eccd766 --- /dev/null +++ b/resources/js/pages/Tracker.js @@ -0,0 +1,17 @@ +import React from 'react'; +import { Helmet } from 'react-helmet'; + +import ErrorBoundary from '../components/common/ErrorBoundary'; +import Tracker from '../components/tracker'; +import { TrackerProvider } from '../hooks/tracker'; + +export const Component = () => { + return + + Tracker + + + + + ; +}; diff --git a/resources/sass/app.scss b/resources/sass/app.scss index 8413908..7554a9e 100644 --- a/resources/sass/app.scss +++ b/resources/sass/app.scss @@ -19,4 +19,5 @@ @import 'rounds'; @import 'techniques'; @import 'tournaments'; +@import 'tracker'; @import 'users'; diff --git a/resources/sass/common.scss b/resources/sass/common.scss index 0cb6655..8fe76bb 100644 --- a/resources/sass/common.scss +++ b/resources/sass/common.scss @@ -258,6 +258,7 @@ h1 { position: relative; display: inline-flex; align-items: center; + vertical-align: middle; width: 2em; height: 2em; @@ -266,6 +267,13 @@ h1 { max-width: 100%; max-height: 100%; } + .item-map-icon { + display: inline-block; + width: 100%; + height: 100%; + background: url(/items-v1.png); + background-size: 800% 1100%; + } .strike { position: absolute; top: 0; diff --git a/resources/sass/tracker.scss b/resources/sass/tracker.scss new file mode 100644 index 0000000..06f1577 --- /dev/null +++ b/resources/sass/tracker.scss @@ -0,0 +1,130 @@ +.tracker { + .count-display { + background: black; + font-weight: bold; + text-align: center; + } + .dungeon { + display: flex; + flex-direction: row; + align-items: stretch; + justify-content: flex-start; + gap: 1ex; + > * { + width: 2em; + height: 2em; + } + .dungeon-smalls .count-display, + .dungeon-tag { + background: black; + font-family: monospace; + font-size: 115%; + font-weight: bold; + text-align: center; + } + .dungeon-checks, + .dungeon-smalls { + position: relative; + .count-display { + pointer-events: none; + position: absolute; + top: .3ex; + left: .3ex; + bottom: .3ex; + right: .3ex; + &.is-zero { + display: none; + } + } + } + } + .dungeon-ep, + .dungeon-pd { + margin-top: 1ex; + } + .equipment { + display: grid; + grid-template-columns: 3em 3em 3em 3em 3em; + gap: 1ex; + padding: 1ex; + } + .items { + display: grid; + grid-template-columns: 3em 3em 3em 3em 3em; + gap: 1ex; + padding: 1ex; + } + .item { + position: relative; + width: 3em; + height: 3em; + + .bottom-left, + .bottom-right, + .top-left, + .top-right { + position: absolute; + width: 50%; + height: 50%; + .zelda-icon { + transform: scale(1.4); + } + } + .bottom-left { + bottom: 0; + left: 0; + } + .bottom-right { + bottom: 0; + right: 0; + } + .top-left { + top: 0; + left: 0; + } + .top-right { + top: 0; + right: 0; + } + + .left, + .right { + position: absolute; + width: 50%; + height: 100%; + overflow: hidden; + .zelda-icon { + width: 200%; + margin-left: -50%; + } + } + .left { + left: 0; + } + .right { + right: 0; + } + .count-display { + pointer-events: none; + &.is-zero { + display: none; + } + } + } + .toggle-icon { + &.inactive { + opacity: .5; + } + } + .tracker-toolbar { + .toggle-icon { + display: inline-block; + width: 2em; + height: 2em; + } + } + .zelda-icon { + width: 100%; + height: 100%; + } +} -- 2.39.2