m6o>kIOG=_Xzrc)N
zo*A#L5IBd02Sae?^2A?+PjwX1c&47Z!c+t3AO0=HpK9M{Ux((g@DF}%c=lapTA|3n
z`vM~i>6vM}IhMstbJ+R&TORdr=Gbn+H8F$CZ6DdS5&>T4@$;u(phkIZB0}yKI{t$Y
ze$0LWtPsFUfuPugxt?Pwe^f*p*?o+%!2gf;0u~?^fMO7v5r|g-F#|ILLmyCphmCg+Y*kQILU2kbzl{;r|f^
zd7xKW8NmSNEJh|~7N8v*oLt;M1zQCem>8LvnSizftp}>E1L?6mQqXwbzED#l4gO`Kd};u4Zls%q*Qnp!5NX66=_R?aT2ZtfnQUcn)u
zVc`*xQOPN(Y3Ui6S;Zx#W#tu>Rn0A}ZS5VMU6UqHnL2IyjG40*Enc#8+42=DS8dw7
zW$U)>J9h3mboj{8W5-XNJay^vm8;jT-?(|};iJb-o<4j2;^nK4pFV&2`tAFVpTGX!
zV&DTgm4OKqefA7LPVFoF5&OVn>!s550(bs1q`wgRSw68jtzZe0IKzaUibag7GXovd
z4*WQ^=x@J$dd0fjH~SPSPO(f!{vP!s~`PmV9A;8KB;on
zqjMHfYFo5!=C~X%(rODj5hBX7#?FmJ^!mSR^EYpu-nr#Ma@;cx-BxwB$JC8qUs=CvT7t=@}>fLHOJ3
zkM@o0biS+?Jgv9(;SD8$B?|mTsBP40*S}5Mq#3FF+b=5j;+hnX
zz(B8`853K%RtY*BD;LwQe!To`>bi=F)BQh)-!jRyT&!&~X@$|r9SQx3XY2ppq(Z9V
zVBi?3sVaNZH5*a+!#}rlewm*AQ&Q$m!ruixj6bJ--r~lboMu$@Tv`3G*69!b8G8OR
zr0u9rn`vWRnOyqq81q}PV*;g|df)yttatyt+wq*`0hy%zREZ5124F57nR(oO*LC%s
zeK%D$U2fRk;xs!qL}EHWz{6BN<&5!zj
b^A!~e8%74kks82R>w8vfQ74&>hT=^C^!7Q>
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow0.tga b/FishingBuddy/Icons/MiniMapArrow0.tga
new file mode 100644
index 0000000000000000000000000000000000000000..9046d30c158c6885baade472a0019201a187389a
GIT binary patch
literal 750
zcmZXS&q~8U5XQfxsf~KDc>`ZSLGlVl42XhS>D|(+M~||pe=m9yd;+1b;9W#=_taPD
zE3Dr)$(BGDzRAw+{AMP*3v3~bA%@sZ-{hKk2pd_&SuQWTmo>A&iPmnZIrY_k<>xaR
znCZ!-v|QsI-r*HKMocfZ)m+&zkm1NE#UE17lrj90i{bl%jcs-nrRZ!&hMH2Ln}y2J
z_qe769#hO>b6~-}(Dihijxx>h$bd0*K!pVQ3jU+o1P(Xw5k9#>Dhjy69ej#{%Rf{?
zY5qc$)F$;yv4FEmg7xoezBwcEc%nKfoVdt9CNfY3YcV=tjc~}z%4k)0BAjaX+FC{^
z*a?YOSc1C6NK_30EV*yjsbIUM{)$lb3A@zEe5=Y#x7zlkD63#kAYFq9D83tR>DL}s
nt=!!(OK1->>16%j+#0n6bZlInkBY1EqC7j@8y}S?#XkN4_+6AT
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow10.tga b/FishingBuddy/Icons/MiniMapArrow10.tga
new file mode 100644
index 0000000000000000000000000000000000000000..9f580d310fa484b03f223ceb357cf7376e08fe41
GIT binary patch
literal 1068
zcmcK3Pe{{o7{~EX>7bS594Le%qd#bfG8FZoh=*(~%xpRlK?rdviU^7fao{EciHe{g
zkiiZ?C}M{o1wlm+c8qS)p;IA5cnFP3PSx`E4%M5^ndI4ov$%>!
zcmcc57Hw0LfX|AFF7~%b>$Aq$*H}7lmgfdic!`GyX)4uhmSxzw6Z*wldrw{j*O3YPKHX^K9f!H=CCxgo;+xkS#v*SFS_?75L
zhy7kQuk9_Ni`-F&^Vk`NxnHMV({KB2LSnZLR3K>2GPS)NkB(n)Uzy
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow100.tga b/FishingBuddy/Icons/MiniMapArrow100.tga
new file mode 100644
index 0000000000000000000000000000000000000000..f55eb647954d27e8ccb86c3ca54e9c3e3c71cc56
GIT binary patch
literal 1068
zcma*lPe@cz6vy#jnUWLvC&5L3$c6YP%|MHybTDXyLCJrUB-edbI$DDlnsaxds;4yr>FH-@YJ%SgtPM^ig;9M{me`
ziSDgLuU>ndRV36x_LukZvt`l}{==gadX_C=BpG3F_e
zbGxdqDrMa@Se_f%2w)1cSkymuxIxZPB;V>*tYl{Gyb{ojW;{hAmM{U^Qx{y}x>#+U
zILE~_r}LXihr(y~kg*o_{SiEeA9>VcyQbC`PGoU0pay;Bbc57vd;jr_eRu)ee>Hn|
zX`Hpz579k!g!?iK>5`Utx*p!cI5}3oHgvG(EWKw?H89>Fr{8?@;5@VhQVslPHR1v9IQar_NjJt-OBrW|_CbQ=l!cmz?7O
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow110.tga b/FishingBuddy/Icons/MiniMapArrow110.tga
new file mode 100644
index 0000000000000000000000000000000000000000..156d4475cd32c5202d2559c892ab5c46145335c7
GIT binary patch
literal 1068
zcma*m%S)7D6vy$OmoA9mC|YA8wKro5Xjw84#w
zs0a~V7+U=Wi7ui|fg72fh#MmpX+kl6&rC1KAnJh+&pXeY^UiZQBSp&zmt0Ca>U`QU
zzT$ZbBe;iaNJcF7iX(h^9v!-=1yyNDF`DDE9}kg>)3CfKM20Ob3vV@~4fQIhF8$Lj
zttdm^nV&!-3XzH=M8;Vr2KoJEHBsM;K0M<+_4=iBedYUic!FZs{+x*6;Q~gLtyOhW
z_YtEQ#7lIeMr%65dQRyzxkFAd<6(B?#b-U$mdeP@!E^ZW2E%xdPx`AKEmG6JqdtS$
z4!M~xB|M?JqmUm
z`bpjxtRHOMP9*YBMu&`38{j0ixS=3pP}6t}TYHwiaZc6;)=QC*z(hG-V3xBC=mx!1
zKwS%byi?q2xQDC{cMI#QbMV2>4j1)++IH?NQ$Luq-m(7Mt%sQog`KCpKOa-<;Wy{F
ztOV{S+;{Pe2Z8bFPdb6vGJSFZNZ3E^>
Bo<9Hp
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow120.tga b/FishingBuddy/Icons/MiniMapArrow120.tga
new file mode 100644
index 0000000000000000000000000000000000000000..11f277d68a63e7d37f9caa379390c5afc3a485d9
GIT binary patch
literal 1068
zcmb7@Pe@d85XZl!hFOA;LU;&K6j6%&i=meeE3R&unNePr2-9%YgCK0A7P|gf&_G29
zF*>LR4G($=I^;pRb&v|r5{Wl00zr`NGpmb_hXxLO_`R7oGjDz~^P~%kNvcwnnH1Ap
z=OX$51fT&bAP3UGQY64>QiCz9O0Da$wv?|8^iN9C9Op2!fDcN+Er}R%by3rr(7py0
zp@N9IdG_l-ceSHy`pTDA@R`In=uUv14KG!qO?49c1cqVsm=I^X{$k(NGyOOv{xY_w
zutEHRmhgWA%PwCjqi{n-uhag
zc!ku=JBw|FFw{aRtb^Sp2$|8|+I*Z+sW{Ek;XNi5Q5RH$)shZlVEyQ%r#6?P*~a2+
zrnl(r0=?f?7Jm2O1^A!{><-q$7V;-+27lWNr(~f7<>CGT{PMu=Z@H}Q9_WQS{i4oS
z_}Wf6yJ8!
zZDalkTE%XAc=9`-I3%8Dn`HsmP6u^eU(`puUq9*5IJP1<>p$RCRATuH(fYaV0;lb+
mmRbHRxrv3rDS(?WH
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow130.tga b/FishingBuddy/Icons/MiniMapArrow130.tga
new file mode 100644
index 0000000000000000000000000000000000000000..6cb802bcc6592b8d719cd5ed98d4729643137042
GIT binary patch
literal 1068
zcmb``K}b|V9LMpWS!C*()X9tx2{M+vY~&$Gh*sS+S69wUD)d#IAljlD!0~@ueXf-9a9XKKFYpdaSiwBTP)vQnHQGK|TtFI{@IejweON<0a|@A)*O`gcMSDDw1cKG0e)nsdWpj}9E115$+tEM4|P}Thk3RJ
z`)&mK(1<$pkRPLE=GvVKjY~XSM}WFNsh@plVJ+p|@f=%?vHk=@B>7{{E-^jY=Vpg(~uoE6awCL;HUo7VmhH_#8eI~Dj}*nV2rxj6k;`c_{u
f&KoCx;q$)Xj6DDCYEO-~%ImAlzEkGC>B-R_dj6da
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow150.tga b/FishingBuddy/Icons/MiniMapArrow150.tga
new file mode 100644
index 0000000000000000000000000000000000000000..83cff321e162311010baacb19e3bb8f5a1e1ca8b
GIT binary patch
literal 1068
zcmd7QPe{{Y9LMoby3|Txpb2@9FcpU+{b3sDv5C`>nlq$}il_xH0#O;Q^58cAKtV+$
zfq2MJi4GmQM9{&yb&!g#g%I7;5Cl=|{oVG1F(|Ko;l+2q-|zc8d!Fy}NLg~iEw@hR
zIZvrvOtz9DRG=R17(z@1nkWA+n)nz%KjO;M3-UX8w5m@1(gSU3K;L*5MrO<^hYFY8
z=#)OIMZeXn9gS#P6WZ4!yhlLmI;zJE_QI7m$uj@CrjWK2r7ni4lo|3{ETM<*+5AUx
zolZMKs?ke5=lh*R&Ay(IU*jP@;sfFsMj`7$P>`59`%^Rq7M_{G+?nOrsVh@Zt$<
zew(9BKXgRnsd1#l9Oubl_V$JK@2QNso45r(E?^P&(60?0*BteBKIzfSyszld1}B(Y
zLlb!jClN*;Zflo8-(hF#g!Q7D-b8hsv#Ox38Dr=`Ijn!}h@gsfChvta-f~IeT^;?o
zL5=Of_Fsh%f}E$#Y3m5;C$$k9lor|iwmr@2vc77Pvu|ZD-K?jMXK{}_tlRFyMXm5W
zh|DPD#U+H5%b7|G^dw3iMjs;d_$hf5|B7RLD8o54pc=Nf6F7rPl;WUp?x%CloO;{m
Xp^D(uPTw_uhrjj8*{()^z*nQcM-!U}
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow160.tga b/FishingBuddy/Icons/MiniMapArrow160.tga
new file mode 100644
index 0000000000000000000000000000000000000000..ed709e5cf9084187e2c7af57521ba9591f43452c
GIT binary patch
literal 1068
zcmd7ROGwmF6vy$O5vdE`xDskK1Q8P)q{z`!eBh91j*kq2Fj_<@f|80MKGG~CUyB04
zg$gP@AP`-+5*LZ();4YeE!rjOqENK&866x%aO;5&_kZ7a&b=dDkuSm(E=Q2BcBYJ^
zo&*nC6r^cYYE9YtO#La&i)b1nkb+0(P=Mx?stq;jpXPO-2l`2SAMPL!{&AnmWArFS
zOG?w8YP73P9cd7Yc%gmzmrusoUcUIm$6GA3$EF(eS6z&Me=>KLatiHm(QkVkpOeBH
zQ_9c^zjR-1j4{2K#5h(l16%JEYhTv_vmV0oWYMi!efOTVhA|(|iZVpOiPz{smkyPs
zALQl@^DM`4$i=W6`l=lLVYMU0;|c1Kj}p8?HJ*F(@QpckKUWcj+h`(ptEyv1f6T=boV)Kov5PfMg^h6z4?bvF1l5j?=H+s)_^*O)u`~9Ei_y7H$|2Z(8QY1()XG&={
zYMkl3N!?WOkO4l>z+>n8wLlZ~w}|Z*Yp3$m@sb=rc*HNZ@rlXYaJ^MEDvxR>v9?M_
z{q~ggyrtK=vwEN&ezJl$Uhf~t`|~J}b}jbpr=Az=;yb6UIj76Itv>DJ8%drqj>G20
zIZM$?CD&C&OM~|RmVL?ly+e(P>k$)F{u?SRj(k))&R5(c_G-{9#reh>QS-0=%UJjNZ}}}-
TvZ>b0*38BY_1n{#=2Vj3H$&kSDEPub}Un
z?zfJku#;NwsP3V@S5-X`gK&&u6q{?lb@EvEsZ_^nd^S1V`MxT?*;}#jm%TlHvgV(9
zd6-?qgX*n!o$p&3YNy}3n62Zk!@|F{c)TJO9gp-@u;$^`vxdre6cYT6#M`Dhl%i@l
z*okDe)R{ft+8*%9qXJe`@vLvxS&zyC=|kF=c)!SbN0}bGA2s#109
zQhen-6M5#MTSZ#agm!gVtE|HaAOmMb8XrUQXU`pk*P`bd2YFW~5_uIYm=sL#u@v#j5E*uI1EYg7IDsbOjsF^Si(b(i*3pl$Ld
z5yDMa*jz12(>neB(kpVOunwDH0#@IHUgint3p2i>rU|!UcN0?$JzCy4?93b_;~oYO
zMjHm1ty4SHjGz@^<#R_-FUMxS59fET%kHi+VY8Iu3HrHT=`F_jA!ik#uOZ&IV;Vjz
z;{o0v5u>=yxhYI0&7c_;b98^Gr#eu*zSGAMckQYH5j3L&b^69x3*>j86zQ<&V^6!&
zIV>^nmLBT|{~=dNNJo%$zE=4D3|TlGc`W=WLy+HiSb5|=
z>jdvb3eRHp=+afDx}x{2ZPo!)z`p-0Y`;tt!D_6xZ1`}Vu>a@Zy`HE3zvVX82P;EP
PgY&4iu&K(asr2gv%ekVQL1T`1<*_h`a@BSp}G&s^^O&$;*9JO7bR=qREUE!U}|
z*?$^CSU2<^){da&94;dpX^4Zf-{aN|Cocy9Ov$BJ3egDanO{XRQgIR2;0#+oi(Q7~
z*Jrh9OZOC%S3kI{1%+vx=ffCNyapKu;0)`rUQy(FwWIUeR|IlV!Q7{HI{U8s+Mv5t
za$h)#?XIlvC#q(@0&0ACh+A-B0FCHEE9-^pDf#x3p1~D7(pfF>89dmxo4gW?Ar_Me
z!0I#fh5UBdnG5ku3Hr!BYwF?o1$fZ>d#q%fMj!5Illz>Z#tVzPs?oBVcy=9~cz_#-
zLOMDyh+brJuTnQISuxQdw-!0;F1_!o1%6n+6Zn8P=trxzm8dytY7hg96!c)8^R7|9
z$1Hfz>o7I1VQW1`xxSLu4|}(qkn-yJ{7sxBDH8U+
Zm;R}s(pyzj?eTdk%2WKsp0c7;{Q~a(oD~27
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow200.tga b/FishingBuddy/Icons/MiniMapArrow200.tga
new file mode 100644
index 0000000000000000000000000000000000000000..0906effc1f3cbbefe786ba67926c533505b66fd8
GIT binary patch
literal 1068
zcmciAU1-f=9KiAKsJ&dQ&5&A_qZBP$vDkzVhn>>K+00qE*lwm!!q#!JILqNe^KwHe
zDTJ^^yORs;VqS8~jT_~q-4QOfyv+B}IrUFm?8dJ?J^i2O_j}IodCmhfC`2Wd#7YZa
zk+GW%+$Y5gin;52zmi(2D*Y=;TxireYv1#L@9bid#k_WIgd(zzJGD%+6!N1H=5}k8
z4BvRj6jznjUcRuNH`MUR^-KA@2FGZGeb3OsTTWVYQ$sqh)5`IaUVhNbNApINQ=LMD
zb9FMG#~fwCU8We;Q{7P5E2UnAe){aMktf!4Yo@~84A8_^PPu+o$JL+;ZPyW<&^8@V
zC$Fs8uW;_9_cOvi&l!5Xt#&1JFh4GG%qeF7)jYT6iZ&^(epYzTS=TcP{m#)fHETfS
zN_z)2JTpJ7m71+AWnA{$lfUbG%o|ipd(@{kZBz&2=3mqr6{!$+{M~mP=Cdmw%>P8I
z`>nMm{O&>}{jOllf-cQ16z0c4=6P$_G5%vET=#K~Su@Tddp_p9rg%xIZwprG&v(1U
zxmwk0iPqU&mo9jYdw$QK@k0(rvp!s)*blp=DvIGopaB9(iz1gRjJBO
zj*pH#FKUkQ6GTvrQuvVu+aeLCMN}{nae%7V!+@7{g->qmB7S
zZIVCbS#ReGD??x1+^6Jy!7?T=jb2ot69e#To;B7NAFMayy00zwKWCV?HN{9r0j!oL
z6zY$%v_k$Ma$#pLRkGet*RGqlK;A9fLmM3AAf`Pf=^Ob`+{6Xgdb^_~_0TIj?<6wa
z{C(Z!*>^Oqq>s`Eczbt^aYT9C)d+c3<9qngif-7sub`3s`{$^tD
z>2mG5b=w|ku-YTIO@9x+sZ5^Uc&9SD{et?7w86wGy<1ZQ|L0KiDDMM|rB|??C*Wkn
z_%5b-*^g%QkTpiVZ+UNbWj!mwC7c%4lgqF>IS;GR&RK>V$UzGJ6-g&1<2|xF`mdw5
U=3$^N_#jvry8h@+&V@hBq$MQqd1E|Aslr|9UZ5!m2DE7#4;)$%|t?hk01yY
z#a4nQXw*Otq($pCE}}&dwQ!{fQUj8L!N2cGCk9b>9r*D7|L2~2@44rWbWn-NRHpJ%
z6JJTsE4(+O4qjBi12+nB3cE*{=2WB)I;r9DrSkhgD{Dld}(!H;ybc;3@*hMTGeotiE+GJpM%m{eG!V=G*=+a1M6n8r*@^
zaZPb%jG+Wpw?zuw9vH@G+|!`p!T1
z3-2+EQsEPfQQHLH_fd)y*ez!Hu@4bc!|v41X}vNz$iRM4#h|T!d^^c{l<0G!U)w`_
cJ`V3W@*f9+flJ2O-bRcK6KMNrk{DUOspGXI55oHhq
zA!@p4sWk&N5e?O%b(I%U{V`2r)`>N{+jWH_Nl;p8mF)_jw+{wKI*tW
zt3gFFzG_fE9XFD8Ru~k&3aGW7L6i@IFQOMU%GZu?D#RZSo%B82X)>l7<-V9KBkm
zU)Um=Cd9Z2
zc7~|lk#`Nd;6K0p-zM0n=+yO+n_{nFq&Rbgd!N%HId=AXSkL`&f<;A904|q6)R@AzQ)@T1+-Ji=2
gc9+0^)|7qOS|23NBqQyywphIN@Y&|r=}1U_0WvV1B>(^b
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow240.tga b/FishingBuddy/Icons/MiniMapArrow240.tga
new file mode 100644
index 0000000000000000000000000000000000000000..eac0c3d0af15af45d86b4c14a300d6f05f8346eb
GIT binary patch
literal 1068
zcmb8tPe@cz6vy%3H2pC(5XJ&si1-gRk~GXfml=)@{+$VNqamXOqXbehXnz(?T0wz|
zC_%W;C=nMf+C&MUa_}GdhicDh
zMlZFcPvpFZ)xO3%*mvz-P`lJDqZ?_i`clSE71FxK$oqiLm_P;2qX2!V(ki(F$ad9d
zF^;gdWet<_0$))HKO$&DF*^B%M=|m*!r4mOGuxw&@%}s`?-jDqk2*X^%$w+^G=~~E
zVfEEY(X4Lqk5<2ktGI*bu-@fil>VR5TkMT64vofLvZP1B*O~LA{CKH9YjqCCM
zkCK}Qci4FgD~o-Pk=KQXh-r^K-BbtvUBxqL8rN_Z?yz12SkV%F-qs+sA^qj7tgyNT
zPKx!+&ajtX%2J@X=2*!t#G7Vptx#^s4*XRngg
jx}Wtiv7V;8Zys}etlD5}sP?A6&EM2`sr`mOP+O+|Wr~|r
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow250.tga b/FishingBuddy/Icons/MiniMapArrow250.tga
new file mode 100644
index 0000000000000000000000000000000000000000..75b96cc400d343e054118fcf3759ae9b8ce570b7
GIT binary patch
literal 1068
zcmbW$OGs2v9LMpW8a@^}qvA@)u?Qkca0o?BOU$8R#Hri(0zrxv;sZf3hhiu*vlyDP
zMM2=g2}-OWh+4D~7mDRpH*Eqf+7;=-P_pkC=EBS*1peW}x%Zs^|IB&Zk@@0i;GH9i0g4
zpx*0@zNlN
zU)96!jgos0VcbPD{%+}~vh<9?(?~wIb}j3jcJzVVS-gT-_XXsl6c%UT&;qrWPy{=C
z%=S_vj6WjpHJ0Fp2SK!;0j>H@(InhAcv
z59VBArH^6Gy$U(;{M06&4)guZv(N3=S-SL*_aMw~nmbFrcRCWnjQenh{Vr-it2|Gk
t0`^()_}_R!#w;dq7KPYv9HMZq|JpzE1+13FR_{fxzxhPF$J^9croYD*oRRel{wP_`_?Cx*h>k;iIErG$sa@%M
z%k00&Thl$%(zfxW3y2k``4~W$85Y#2pXws-F1*OrGXEyw#}PzFs}eP?i~6c&{Z)vZ
z2U|vYhS)=?zK|3`KH_%`;MTmZX-Pf$w~_mToJS}@JY4YWmvS^sUL%h0${*4X&CzED
zZ}1MM;DN2>1`2RR->FiBTsN#{7Pr~aEVWwI0DYdr#!7+JpaKtJ>*z;{Cdes*vxoDv
zgVgAg`uIPH2+H8c6l{!i1lfc15_XPGq|&gv5>b`D=`sDDz~(xE1h`R6ZkayNuLD`w
z8Ft_5+1qd!jy~9@%&GFxFv;Kg_A%
zqxrUG?Ao*9$DaQrc-{gBwg-m=8L6PoJpW7fncA1Z_T6T`$-YK`zM&>fkD7hpTH9M}
zk3y7uYLB#*sK7b=TApjxJU*nh_N
zk{IJlj(;e5)O>UQ`uxVH9^#D6sv4%}XB?j=Juo6!IO
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow280.tga b/FishingBuddy/Icons/MiniMapArrow280.tga
new file mode 100644
index 0000000000000000000000000000000000000000..53df2b088f0276466048428fe48b51ac4f6089df
GIT binary patch
literal 1068
zcma*lPe@cz6vy$Oqe5e0Q=kw6m&Vdj2z5DLD@7{B-yeguAIF6hl5J^M5K}_kK
z$i#k8sx(k4j`GncyUS&C1nBb!tgH
zPjMMuxN($+07m6#P6LcL{WygToJUZrjGAU#KhDC9b38sS4#~5rMSK&o2ZnO4cYM4faMP+u!1IE46b6jlx@W5D%8()h=BEGrB42A+em_XYi*X1AXALy?g)9^WXbE?<*aU6K=WXIqdw3
z`Oae8fCspS|bUuPw&`15%Cvt4<@6nDboPY-vyx&a^UD0!}v-}@L`ao}%>CBe8
z$nC)kyoJ557Xhs*L1PqM#qN7x_tnm3M&(*ktN!R2HP*`z?xH}yc-{x=SG>q)((Yf6
zPHS2h>GgfiBTTJn(i+c3k&Sp^_uuZYolPw|+3S?@IG0xT9@0;pWLHuKoZd5x8+IQv
rVfUhq8#~1JJM`i@_7iq5Z9QIu_bRCJ-||-b0=|m!tYC@nhBsR~FqoX>
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow30.tga b/FishingBuddy/Icons/MiniMapArrow30.tga
new file mode 100644
index 0000000000000000000000000000000000000000..08926504d702ea1aa6772484e6d1e75d8f0ff009
GIT binary patch
literal 1068
zcmcK2Pe@cz6vy$OsbQrcs9-Ka3Plt}&51%cEk+uf{8vi45s|F$-$DpR%s<#@4WytU
zgcvQ-g+>e81TJ(T?p%aQYZ1j=7J?AS>wCr-9L3O02R`q;d*8YDo_Ft)E+`y{N>qAW
zxb>gzF`;>nmOboW$tBsy=yr;D0al%^CdKkZI5p_~43
z?g5;PXgZ4VUT&@FmGGJ=e8C$u@EvjbM854+6zoiTbxq5J?yA%6%NuqftfT0OjLgMIf4*qFCi!XjS7k5u+odV*vd9EvgO+N9n+
z^^@~5lxyE>YktEAwD3MgbBysK^1m$OzZmA-S8Co?xwcqgm-E_ZR~)^=0vh#`yfMbQ
z5dOb;3`QYWoA)`p(x=Os;CWu@oYh_C4Ct4dwN9T8r-jXDHQ9IB-q`-y8QD1xDnTE)
hpEvAWY(8@p+4yHXs;+U@dLDWz%5xu=dc5vD{RL0Kn-c&4
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow300.tga b/FishingBuddy/Icons/MiniMapArrow300.tga
new file mode 100644
index 0000000000000000000000000000000000000000..a876d681084ab07825e1ce329f43ec593213abed
GIT binary patch
literal 1068
zcma))O-NKx6vzLQ8rla4Dx`}LVz4F40lF&;$Kck9Krg%j|W7omm8VkOKRe
zo$n}BpVX!;JtF_IHkGC??9V8mL3|YKU0L9_Y&P1Jqjfza_ZBolT>n&~4Qg6fnO2CI
zfUA%Jo(1>_az~%4wWg=!b-^eUKpvcfD1`NuSbI}}myEZ!m+P3`sF}M4i5rI!aNsdm
zJ$BZB{-Tj-TkPiH68W|G1;zM3Ox$zGfi|du4#)@`btEf*hEzE-JhukIy$
z2yQ?eS|JDx=#Y}o()!``w2<#1Rq*dMG4t>l>Qr2nR&>2H`G*2@@N(RZSsfX%kwy3uwF
zHRp7SUfvM0A3~ZA1CoFr1=kE9RdfMVOZ&UhhI=3b>G(yR9|8p2b<~r
y%x1xKwRsGJ&8zj+X15shkP0DKIENzSz|OVT$mQX%>hwu>
zw5@V&@cEt6w7~or573WNoW$;NmIq;7QcMHnUqn#9HH7QhRF%Hznm!O?d!0uboMH8O
zF~|G2G)V4!+`}pOkcwVZYK^#2WW(u+U5QUAdZJtUrJKa{BOO6l-WAwhy__dQv&36Z
z+@p;6r}6x8;$Fhu+lDH1!;5xm@x*Jed^@*|R9K%QeE(CE#J$29)WhnrGaP}RK6vzy
zSi2AB{ML&a9aB^{^e0~XTVkK%1TG*Sw^6U}#7@KdlKsWEuf-xO#F)YTTZR0J;jz4`}9U!7e5
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow320.tga b/FishingBuddy/Icons/MiniMapArrow320.tga
new file mode 100644
index 0000000000000000000000000000000000000000..05bb867b2272eef4ec28ca6e0979072a392fc67f
GIT binary patch
literal 1068
zcma*lOGwmF6vy%3D50fIR;vI~t)B&G87C|srB1PqcbWj(f6GRYV
zYKxXWK}RA<7p>d0h!#cEqE#V838D)H{T`WHe?*}RAMgEN&zb+Z=l-QMxsjtB1v1@}
zXZ{!B+5FFC9&yKUBo*&tPWP-+%RQ$`cH`*A6$DX?vneN-v$5AW!{&3{&^MLqGwURV
z@eCvK>jiT!&cW*2J)$bqf_k*2TPV^WHR!i0^iwTbp`vxxA4wX)WgPPSfYns3!&+2_
zHgui*W^^F~A)G`TuIUr8oyhg%XRr?Ao$iqTfVgP{P!G$C;vmA*t$#Z-cY1>ORkR
z(a71N)K{l3Burz{CH|ey)0<-Mu|RLB><#-#WoeF1Pp}?B0``sD9qc!5@{cA|!}?r`
t5Uj`6CvVL>?mO(ev~SCX-LbpxosHdp>T4Uqjgh)Yw5H^0d88^F)Hdp)ojm{m
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow330.tga b/FishingBuddy/Icons/MiniMapArrow330.tga
new file mode 100644
index 0000000000000000000000000000000000000000..74d8087ec09a38077ea8828bf14f924a600b0662
GIT binary patch
literal 1068
zcmb`_Pe@cz6vy%3q?Kucpar^!P)GcO(jUw~ml=)@nmUTOQIRQw84037vOfz)`vVFV
zQUuaMMMGS;XcK~qa_2%++!}$n%R&f58NcW00~s9Lbl@|0-n-}B_s+RjIwd#Kl%~r`
z?$v)96JpkJUzZqj|G3Lb+{{A`QjmorRNxA-aSrj~u}*7*$zF8gp*)H(j_a%@7<+IN
z>4=Scx~}hfq<<>V8k0*Z(~8=(p*n5p758s(Eqz2ej@D`G^(vsBydkP;1hk_tV?MHw
zjV_dFk=zihHa9Z)6C!t+RidiL6mrpsC$KfWXytnnoSLjJM|)e(^_m`Nm&&8gcU)i$
zp$c!10Y9~PG)-W=Gmlt^Eh4UOgL4RSQ>CG%T+fM(!lJgd?5A`!f5N1B8Up)8a@L3zI2c^{ZjvoEi9C^d&gPn;E_OnKt
z%H;bJdB+(Il5b}rHhOedtIYnP&JE7e5((dwq%p<;1mQ;&;zz1JGuaP2E4H_G=De^z
l*}h-INl{3Goh_@)*gnOLKtoeyv#-%tS6ke2+vl$=(LQgRn|%NP
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow340.tga b/FishingBuddy/Icons/MiniMapArrow340.tga
new file mode 100644
index 0000000000000000000000000000000000000000..142b77959183f6cfc61e34e4c84317f890cf5bb1
GIT binary patch
literal 1068
zcmcK3Pe@cz6vy%3RH!Y~QE4TZlA(wRNfc>jVoF2epK&w;L5dckNuZ=d@z5-_7}RQ!
zAh=LL#Xk^4En0;OLv3rDHh~rHjB1f2>i5XJ7$m_K9r*C(-goYO=l&V#fZXuPtJD~`
z^&g*6%B7i&}Y@_yN>Cr{Q8D<6>CdzNJRy0FLQc!
z>aw-DkwHa6YUOx=tZ&CSkEH)!?=ip$flYHx}Z<$<{KgM
ztd?9PA%G6_p&1WxTOSzL3yVZtQHoycj(+W|e}ci}3mPWx8m9iaIquB%8dRHygcvT1r9*!g6`_UT{3
fYPA1@ow1$Mo)PfZl+^mFeHG;=>PmfOB{|v#&f}cO
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow350.tga b/FishingBuddy/Icons/MiniMapArrow350.tga
new file mode 100644
index 0000000000000000000000000000000000000000..e05593be447010b22899e4b2a00723dcb1668f24
GIT binary patch
literal 1068
zcmcK3OGs346vy%3l#e1w5ez~>GfW3kB&iTWf@a1Bw5KylBD643BBezoST@+mDCNdQ
zkpmWO63Im%QIM#J?Gkt9S_mXsgo-8j_@3bkyP=@jj
zZQuQ;Hi>bQ_c6BRXEnJ6t7}N7^n*2Q>OP+0BD{El0CMpbEqI7mS|V=%>8Qjo*VR~m%kRMn
zq`?EL<7>3ynKoz_V>w)iY&1}(&z#zy*t%`5X-p!Dm$3b`>z}H$z?blWoUkQ3;ik5a
zIK}U}M<46^32)GcUNmY=#hRsmKZ5W%xz^Y>RDph#GkzCq94F@m!l>3yr*4m(ewnnk
z_xP}9L8WR$wbaMf-pRQXYL4eoG{6m;YqzlfO99$A?mwCxN#Zu-uO7AD;yPNLXVL?6HH_qU^MydrByxEjjwG2K`j6e(~Fmp5m+)i0epAW}J^cUDIkZ
z?i6tW9K~G>paYNfkF&*z4W;B;jqE+gRKtFm#9cuTY)?NHFoZ7sCN2gCUb8w|y`s9w
znahZ?yc#?}Io@L!J=#{b=7_EIlHJ}>j%KNFLU#5>w4(th@Dk5(oBRyTkW=R7+1bzF
z20oLQNS-s7SUbl#yumDN{}%lqZX9-})~xRJ)a0WsYExCjjG_Cb
zu$GI6nzXEb=I_Jaxf6C*Be3=2m_}INh<^k>ycT5enz=8!%=%&d)gApwics%c+?kzc
zo_BB7IwlS-*X`c}Y{y_eO->T7po_iW!v
lE3RWN&Atck@1Dun{!?jNbK_N~CD;@U*I#I>4%RsV?E*Ltojm{m
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow50.tga b/FishingBuddy/Icons/MiniMapArrow50.tga
new file mode 100644
index 0000000000000000000000000000000000000000..e161fd474a84aabbc1f7f0cbf4b814a84fe9af46
GIT binary patch
literal 1068
zcma*mPe@cz6vy$OhG;pd<*Fo*Fd?03BxNc(L%N7kkbw{#
zZP8Lo!Hh_%MQb-Lq(u?BaFqm+Lg*sl^*z&j@Cb#u@R|GmoWr~KoI6scyiuS673X+&
zY0MeKuTjXuYV<2Z
z2_zNJJolf}rk@&}VQRx0iU0HyA;Q
zJ`&sJ=G(EhzQ+{SSKZ+KHQdJ?Sj`?Gf#+Ca|K(aH{<@oQ(+R}Yp*1}urjIptp-0;(
z_4KTYzF*Wjby?N9)S2?7r!MRHozyA5a9HoTUS^(A7CrsfZ#y$~?)tFbsNh8uRvW9Y
s^~m~cwYBqh66p*(%h_(A)yMlE?wQ-%*b-`uG)1BfXRd}LmqS7Q1v7x1B>(^b
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow60.tga b/FishingBuddy/Icons/MiniMapArrow60.tga
new file mode 100644
index 0000000000000000000000000000000000000000..a5398f264e25afd69841800e62b72edb2592d8f0
GIT binary patch
literal 1068
zcmaizU1-g57{@pzr=;V00aLh|hAz4Z;
z5RwZQZlqk`&c)iaTT*goq?G9RJSV5lPH~?4oZs*H|Gv-f<$0b1Gbmaebu6wedKJcb
zuD8fw1zq`a@winkoS~ijj*n!tTv+BO^qZtjx+Oy^Z@5LC{d{C5BYx|Wg;H+ye%K&s
z66C1jF*S^n;u|N8ALKjLJaxTCiuZF`u-X2umr>U7mfd_(HRUe9Ic4mC+n8R`XN#=0dyqel#1IpbP*O|96bHk{I6i_Pj22N!plDJIW#%J>)Law@
zE;6Vv1tE0dDq19FTidt^df?757Y>QH?->$?%QW%-|XRcf=7`h$-FDXPwhB_d}>fCjK?-zihn}eag~DJ(Qz>e)Ieumyw2O
zBaz9oic>qD>abQ+sZDi~e;*C{%6br|qa-IWS1OOj*qjgYX+vGwqjE=&|K|5_R9Y06?JY?v!fb3#})YT8jsMa
zU)1)NSYJf`A?{0bOtb9Ro|1_Rz~0e~47|hyY%kAfo%ldRzTFn!iCU<;l9*=np&A8P
z!5r)zx2eygH?Dj;vvz8>y$kU#j*`%byO_lcmaw2*wds>9-_E^E33@^P&v32N#Eu{c
ztGypL=z|7*SB2(X`Sy4c<2tS%I#29PbYPG@>EY~3!sl;2G={5ik9;Pk>98&Jl4t*Y
zo$r6o%i*pF~j+6hy&F%mf_VY)ItzZP*kLLiMwA`3=)&M+5;A+ryjd(QWL=e_rS=e}1uDQBcARcB5+
zvm;_U>n-pcW?&SmAO-$sT%u@7&-6__`l1BAVcraB$B1LuKL;IDzSmtHXhi#}(I?iP
z!eux-3X_PDOkS)Ly2V@0s*vY)q3?k{{Zf%O*&l#{2#u2_kd&bvR=$>1s~wG_dj*qV
z`Az)}y_3{NZI&Yp$6R8+Dz%{o{g9jbILLuVFaZytR-dU0Ky_H>1Q*Ga{Ae?%y8=t#
zgGva%6BvbjeWcd!2#MCSG9_s)^sHEF#=!0|2uZL8FX1r^DX3(vM(AV6-JC6;dd_{3
znpUtgd*Cd*gLzm1yVs<4BlMPLL#Hm#J0E9Ar^eo+93Fu6(e5|Qx4e!g+**&)+Zl>s
zTou~p8q_rP_rsXBn{QZ(590Nfy51Y(1(y=_0^J^N2@S2}=n&=1fO0?ftI(Aq;&6ofDXPd71Jk8!lZ{5|R8&%#Kk4t|5lY*M?
literal 0
HcmV?d00001
diff --git a/FishingBuddy/Icons/MiniMapArrow90.tga b/FishingBuddy/Icons/MiniMapArrow90.tga
new file mode 100644
index 0000000000000000000000000000000000000000..145dc6edda086472f9088dc336c4a5fe28f643ea
GIT binary patch
literal 1068
zcmbu8%}T>S6on6^3*FT>=nE)FU%`lhqTnChD{ftO=|Zr&=~D0sguFucBGSDpU%^+<
z^JOw*64bPK;bStBIp^M)+(F`%;}Thfe(490WH*d+uG>EdiegkEp310J`DXw@7z>KUA+_YGg3oQ
m_CEUVn$e{3-~SIUJg5VB{xeRG&$9FUBtJUbp6uu2Y)9Ya*PGD*
literal 0
HcmV?d00001
diff --git a/FishingBuddy/changes.txt b/FishingBuddy/changes.txt
new file mode 100644
index 0000000..4c2434d
--- /dev/null
+++ b/FishingBuddy/changes.txt
@@ -0,0 +1,267 @@
+Version 0.8.9
+- Send a fish caught message using the new SendAddonMessage API
+- Fix a bug where saving the outfit manager wasn't working (Thanks dwex!)
+- Style points are back (and in OutfitDisplayFrame tooltips -- thanks Shadrin!)
+- Update 'for' loops to be compatible with Lua 5.1
+- Updated German translation (thanks Chinkuwaila!)
+
+Version 0.8.8d
+- Update toc for patch 1.12
+- Small cleanup changes
+
+Version 0.8.8c
+- Handle "Oil Spills" as fishing pools
+- Fix an intermittent text alignment bug in the locations window
+- Make FishingBuddyFu for Fubar 2.0 work nicely (mostly expose some functions)
+
+Version 0.8.8b
+- Add tracking selection menu to locations window
+
+Version 0.8.8a
+- Fix a nil error in the tracking popup if you haven't caught one of the
+ default fish
+- '/fb updatedb' print out a message
+- Grab the names of fish we catch if we don't know it already (old data updating)
+
+Version 0.8.8
+- Improved cycle fish tracking -- right-click to choose fish to graph
+- Update the TastyFish count every time the window is shown during the
+ Exravaganza so that our count is always 'right'
+- Fix window always showing bug
+
+Version 0.8.7g
+- Fix a typo introduced in version f
+- Really, really check for Pat Nagle's Fish Terminator correctly (thanks Saur!)
+
+Version 0.8.7f
+- Put changes from d and e into the same release
+
+Version 0.8.7g
+- Fix a typo introduced in version f
+- Really, really check for Pat Nagle's Fish Terminator correctly
+
+Version 0.8.7f
+- Put changes from d and e into the same release
+
+Version 0.8.7e
+- Fix missing color 'YELLOW'
+- Fix translation errors that were causing string.format errors in German and Spanish
+- Fix problems with the Terminator
+
+Version 0.8.7d
+- Fix broken minimap enable logic for menus
+- Fix nil error in startup conversion of old versions
+
+Version 0.8.7c
+- Fix incompatibility with version 1.11 and highlight text
+
+Version 0.8.7b
+- Clean up event handling some more (only listen when we're fishing)
+- Fix 'doubled' fishing location display for new fishing areas
+
+Version 0.8.7a
+- Hopefully fix an intermittent bug that crashes the client during
+ the Extravaganza when leaving Booty Bay
+- Stop losing the OutfitDisplayFrame outfit when logging out
+- Should correctly reset the Watcher Window for all toons
+- Add in 'FBEnEspagnol' for Spanish-speaking fisherbuddies
+- Use the now-builtin Outfitter 'find by stat' function
+
+Version 0.8.7
+- Integration with Gatherer (depends on the tooltip when you cast)
+- Add a 'hide these icky fish' menu to the watcher window
+- Put the keybinding for 'Suit Up and Go Fishing!' back in
+- Add an option to only fish from pools during the Extravaganza
+- Better (and more) French translation support from krogh
+- Rework debugging output so that people don't get surprised by it anymore
+- Rework zone and subzone storage to reduce space
+- Don't save default values (smaller saved vars, faster loading)
+- Tune event handling for faster world transitions
+- Move a lot of information into tooltips in the display window
+- Removed 'Fast Cast' again since patch 1.10.1 breaks it
+- Fix translation loader to actually work (even in English!)
+- Rewrite Extravaganza code and hopefully fix the crashes
+- Add an offset menu to handle differences between game and machine time
+- Fix the display bug when switching between locations and fishes
+- If more than one outfit switcher is available, allow a choice
+- Don't allow a recast if the fishing loot window is up
+- Add 'updatedb' command to link info for fish with missing data (can disconnect!)
+
+Version 0.8.6h
+- Fast Cast is back!
+
+Version 0.8.6g
+- Fixed a nil reference bug in binding the keys that happens to some people (but
+ this makes easy cast not work, I still need to figure out what's happening)
+- Made the Fish Watcher window relative to UIParent and implement 'hover' dragging
+- Fixed the right-click menu in InfoBar support
+- Made click-to-move support a little more predictable. If you don't have a casting
+ modifer set, then click-to-move is turned off while you're fishing.
+
+Version 0.8.6f
+- Remove some debugging that broke when DevTools wasn't installed
+
+Version 0.8.6e
+- Easy Cast is back (Fast Cast is no more). Thanks to the Cosmos team who
+ figured out the appropriate place for hooking in the handling code -- it
+ was a snap to add in!
+- Removed the "Suit up and go fishing" stuff since we don't need it any more
+
+Version 0.8.6d
+- Fix a bunch of small errors that never showed up before
+- Add 'mouse fishing' option that binds the middle button (BUTTON3) to
+ 'cast now' (may not be necessary since 'Suit up and go fishing' works...)
+
+Version 0.8.6c
+- Mark OutfitDisplayFrame as version 1.10 compatible
+
+Version 0.8.6b
+- Update for patch 1.10 (11000)
+- Partial Spanish translation, thanks to fili
+- Some fixes that now don't make much difference because of 1.10
+
+Version 0.8.6a
+- Fixes for handling Eternium enchant correctly
+- Fix bug in 'Suit up and go fishing' handler
+
+Version 0.8.6
+- Rework easy cast to work with 1.10 -- no dice yet though :-(
+- Add "Suit up and go fishing" binding for an alternate 1.10 when "Easy Cast" no longer works
+- Outfitter support
+- Translation handling completely rewritten to eliminate missing strings
+ in translations
+- Fix for Eternium Line enchant (the tooltip string changed)
+
+Version 0.8.5g
+- Include OutfitDisplayFrame fix for nil error when fewer than five bags
+
+Version 0.8.5f
+- Auto-set sound volumes to make the bobber noise stand out (Good suggestion SBaL!)
+
+Version 0.8.5e
+- Don't count "Nat Pagle's Fish Terminator" as a fishing pole, even if it looks like one
+
+Version 0.8.5d
+- Fix a nil error in comparison after we've shrunk a table
+
+Version 0.8.5c
+- Fix nil error in cleanup command
+- Missing string in French translation for checking not to lure while clicking on the
+ bobber (it's still not the right translation though, hint hint!)
+
+Version 0.8.5b
+- Handle defaulting to 'English' correctly if we don't have a valid translation
+
+Version 0.8.5a
+- Fix French localization file
+
+Version 0.8.5
+- Add partial French translation, thanks to Corwin Whitehorn
+- Support for Titan v2.08
+- Support for InfoBar
+- Rewritten to drastically reduce global namespace pollution
+- Rewrote database displays to reduce memory usage
+- Use item ids instead of names in fish database to make things smaller
+- Rewritten graphing subsystem for future improvements
+- Use per-character variable saving to simplify data access and structures
+- Added 'cleanup' command to remove stale settings
+- Add modifier key support for easy cast
+- Show number of Tastyfish caught so far
+- Add partial French translation, thanks to Corwin Whitehorn
+- Try supporting ModWatcher
+- Fix for menu popup outside of minimap button
+- Don't do 'easy lures' if we're about to click on the bobber
+
+Version 0.8.4f
+- Change line endings to DOS again, seems to fix some LUA loading errors
+- Fix location scrollbar position for 1.9
+- Update to new numbering scheme for version
+- Fix a bug catching tracking fish in the last week of the year
+- Fix some small bugs that affect brand-new toons
+- Notice if we can't display fish tooltips instead of disconnecting
+- Fix bug where bringing up the outfit window would lose
+ what you were wearing before
+- Fishing Extravaganza countdown timer
+- Keep track of Tastyfish "schooling" locations
+
+Version 0.8.3
+- Update style and skill messages in outfit display to handle new 'dressing room' feature
+- Make sure that errors in switching outfits don't erase what we changed out of
+- Handle elapsed time even if OutfitDisplayFrame is disabled
+- Make sure we're not already switching outfits before we try again
+- Improved ButtonHole support
+
+Version 0.8.2
+- 'Cycle fish' graphs for the main cycle fish (additional fish coming soon)
+- New minimap button support
+- Display current zone in the fish watcher
+- Show elapsed time in the fish watcher (not perfect yet)
+- Fish watcher frame is moveable
+- Support for 'auto fishing lures'
+- Style points added for some of the Extravaganza rewards
+- Improved support for languages (removed static strings)
+- Support for 'ButtonHole' -- if that addon gets finished it'll be way cool
+- OutfitDisplayFrame support improved
+
+Version 0.8.1d
+- Better German help. Thanks blackrat!
+- '/fb import' import information from Impp's fishinfo, DataFish, or Fishinfo2 databases
+- '/fb current reset' to restart the current session fish counts
+- Some small internal code cleanup
+
+Version 0.8.1
+- Fixed an error in the German help system (I hope!)
+- '/fb watcher unlock/lock/reset' to move the fish watcher
+- Display percentage per zone when viewing 'by fish' so you can find those hot spots
+
+Version 0.8
+- Display your current skill in the watch frame
+- Track fish by zone and subzone (converts old data as you visit your old fishing haunts)
+- Track minimum skill for locations and for fish types
+- Full Titan panel support
+- Basic myAddOns support
+- Keeping up with the Jones' and added 'Easy Lure' just like Mugendai has :-)
+- A much better German translation (outfit switching should work now too) -- thanks blackrat!
+- Sort by number of fish caught
+- Should work with 'click to move' turned on
+- Track 'cycle fish' information (very preliminary)
+- OutfitDisplayFrame is now optional if you have an equipment manager you prefer
+
+Version 0.7.9c
+- Fix the I can't believe it worked! bug when looking for the Fishing skill
+
+Version 0.7.9b
+- It works even if you've never used Fishing Buddy before!
+
+Version 0.7.9
+- Really fix the per-server settings
+
+I aplogize for those people whose options got lost -- this time I got it right! I have
+no idea why the zip file didn't get uploaded last night, but the new one is good. Thank
+you for your patience!
+
+Version 0.7.8
+- a very preliminary German translation
+- myAddOns support
+- prefs are now stored by server for each toon
+
+The Titan panel support is still preliminary -- I want to make it default to 'on' and have a better icon. There are still things I'd like to have options for (like sorting the watch panel various ways and making it movable), but I'm going to concentrate on the outfit pieces so that they work for more situations.
+
+Thanks for all of your support!
+
+Version 0.7.7
+- Fix ugly display when switching between fish and locations
+- Added Titan panel support (ugly icon, need to polish up my image skills and make a nice gold one)
+- Sort the 'Fish Watcher' by name (for now)
+- Added key bindings for window toggle and outfit switching
+- Internal cleanups, prep for storing toon prefs by server
+
+Auto-loot (shift right click) works for me 'as is' -- I'll have to play with key mappings to see if there's one that stops this from working...
+
+Version 0.7.6
+- Add an option to leave off those pesky percentages
+- Add an option to only watch the fish while you're actually fishing
+- Update the version of OutfitDisplayFrame
+
+Version 0.7.5
+- fix a bad memory leak on the outfit display page
diff --git a/FishingBuddy/future.txt b/FishingBuddy/future.txt
new file mode 100644
index 0000000..1b60060
--- /dev/null
+++ b/FishingBuddy/future.txt
@@ -0,0 +1,41 @@
+Future features
+
+- Count tastyfish in your bag instead of as you catch them (lrdx)
+- Built-in notepad (Kiiingy)
+- "fish trash" feature (Jaim Sandar)
+* only fish in schools during Extravaganza (Lrdx)
+- multi-machine database merge (Alcasius)
+* mute everything but bobber sounds (SBaL)
+- current inventory fish count (islandercaleb)
+- more summary information while fishing (time now/session fish now/session) (Xantandor)
+- Grand totals in fish window
+- select specific frame to show when icons are clicked (Talyn)
+- remove quest items from the list of things caught (zino)
+- separate out pool fish from everything else for counting and percentages
+* save the show fish/locations choice (Dark Imakuni)
+* display both lifetime and current fish info in the watcher (LBlaze)
+* Save helm/cloak settings per outfit in ODF (Valzic)
+* remember tastyfish pool locations (KayJayDK)
+*/- Track cycle fish (Bruntlief)
+* Show current zone in watcher (Buio)
+* Force item slot empty in ODF (Dark Imakuni)
+* Minimap icon (Tarklash)
+- Skinning buddy (Devonkross)
+* elapsed fishing time (Anakar)
+* show current skill level in watcher (Valzic)
+* Titan Panel support (Dark Imakuni)
+* Only show counts -- no percentages (Dark Imakuni)
+* Gatherer integration (Vreejack)
+- Recipe list for fish (Paul2200)
+- display total fish caught all time and this session (truefreak)
+- fish caught database per toon (Filius)
+* Outfitter support (lots)
+* Fishing watcher movable (lots)
+* Save fishing level information (Yeoman, RamahP)
+- Lost fish count (RamahP)
+- HUD for fishing (lures, target fish?, counts, etc.)
+- Graphical fish watcher window, i.e. icons with counts
+- Font/size selection for watcher window (Fritos)
+- Auto-open support for fished items (chests, bloated fish, clams)
+- Expand fish pool tracking (i.e. display them like tastyfish schools)
+- Make the transparency of the watcher window settable (Tehryn)
\ No newline at end of file
diff --git a/FishingBuddy/localization.de.lua b/FishingBuddy/localization.de.lua
new file mode 100644
index 0000000..ef6c699
--- /dev/null
+++ b/FishingBuddy/localization.de.lua
@@ -0,0 +1,198 @@
+-- Deutsche
+-- lower upper
+-- a umlaut \195\164 \195\132
+-- o umlaut \195\192 \195\150
+-- u umlaut \195\188 \195\156
+
+FishingTranslations["deDE"] = {
+ NAME = "Fishing Buddy",
+ DESCRIPTION1 = "\195\156bersicht, wo welche Fische gefangen wurden",
+ DESCRIPTION2 = "und Handhabung deiner Fischereiausr\195\188stung.",
+
+ -- Tab labels and tooltips
+ LOCATIONS_INFO = "Anzeige von Fischen nach Fanggebieten",
+ LOCATIONS_TAB = "Fische",
+ OPTIONS_INFO = "Fishing Buddy-Einstellungen",
+ OPTIONS_TAB = "Einstellungen",
+
+ POINT = "Punkt",
+ POINTS = "Punkte",
+
+ RAW = "Roher",
+ FISH = "Fische",
+
+ BOBBER_NAME = "Blinker",
+ FISHINGSKILL = "Angeln",
+ HELP = "Hilfe",
+ SWITCH = "wechseln",
+ IMPORT = "importiere",
+
+ -- Thanks Maischter!
+ SCHOOL = "schwarm", -- e.g. '\195\150lige Schwarzmaul Schwarm'
+ FLOATING_WRECKAGE = "Schwimmende Wrackteile",
+ FLOATING_DEBRIS = "Schwimmende Tr\195\188mmer",
+ ELEM_WATER = "Elementarwasser",
+
+ ADD = "hinzuf\195\188gen",
+ REPLACE = "ersetze",
+ UPDATE = "update",
+ CURRENT = "Session",
+ RESET = "reset",
+ CLEANUP = "cleanup",
+ CHECK = "check",
+ NOW = "now",
+
+ NOREALM = "unbekannter Realm",
+
+ WATCHER = "Watcher",
+ WATCHER_LOCK = "fixieren",
+ WATCHER_UNLOCK = "freigeben",
+
+ UNKNOWN = "unbekannt",
+ WEEKLY = "w\195\182chentlich",
+ HOURLY = "st\195\188ndlich",
+
+ OFFSET_LABEL_TEXT = "Versatz:";
+
+ KEYS_LABEL_TEXT = "Umschalter:",
+ KEYS_NONE_TEXT = "Keiner",
+ KEYS_SHIFT_TEXT = "Shift",
+ KEYS_CTRL_TEXT = "Strg",
+ KEYS_ALT_TEXT = "Alt",
+
+ SHOWFISHIES = "Nach Fischnamen",
+ SHOWFISHIES_INFO = "Fisch-Log nach Fischart gruppiert anzeigen.",
+ SHOWLOCATIONS = "Nach Fanggebieten",
+ SHOWLOCATIONS_INFO = "Fisch-Log nach Fanggebiet gruppiert anzeigen.",
+ SWITCHOUTFIT = "Ausr\195\188stung wechseln",
+ SWITCHOUTFIT_INFO = "Zwischen der Angelausr\195\188stung und der vorherigen umschalten.",
+
+ -- Option names and tooltips
+ CONFIG_SHOWNEWFISHIES_ONOFF = "Zeige neue Fische",
+ CONFIG_SHOWNEWFISHIES_INFO = "Zeigt im Chat-Log an, wenn ein neuer Fisch an der gegenw\195\164rtigen Position gefangen wird.",
+ CONFIG_FISHWATCH_ONOFF = "Fisch-W\195\164chter",
+ CONFIG_FISHWATCH_INFO = "Zeigt in einer eigenen Chat-Anzeige die Fische an, die an der gegenw\195\164rtigen Position gefangen wurden.",
+ CONFIG_FISHWATCHSKILL_ONOFF = "Zeige Angelskill an",
+ CONFIG_FISHWATCHSKILL_INFO = "Zeigt deinen gegenw\195\164rtigen Angelskill in der \195\156bersicht an.",
+ CONFIG_FISHWATCHZONE_ONOFF = "Zone des Fanggebietes",
+ CONFIG_FISHWATCHZONE_INFO = "Zeigt die gegenw\195\164rtige Zone in der \195\156bersicht an.",
+ CONFIG_FISHWATCHONLY_ONOFF = "Nur beim Fischen",
+ CONFIG_FISHWATCHONLY_INFO = "Anzeige nur beim Fischen",
+ CONFIG_FISHWATCHPERCENT_ONOFF = "Prozent je Fischart",
+ CONFIG_FISHWATCHPERCENT_INFO = "Zeigt den Prozentsatz der gefangenen Fische je Fischart in der Anzeige.",
+ CONFIG_SUITUPFIRST_ONOFF = "Dress for success",
+ CONFIG_SUITUPFIRST_INFO = "Angelausrstung anlegen, wenn Du sie nicht tr\195\164gst, sobald die festgelegte Taste gedr\195\188ckt wird.",
+ CONFIG_EASYCAST_ONOFF = "\"Einfaches Werfen\"",
+ CONFIG_EASYCAST_INFO = "Wenn aktiviert, und eine Angel angelegt ist, wird bei einem Rechtsklick die Leine ausgeworfen.",
+ CONFIG_ONLYMINE_ONOFF = "Nur die Angel anlegen",
+ CONFIG_ONLYMINE_INFO = "Wenn aktiviert, wird \"Einfaches Werfen\" nur die Angel der aktuellen Fischereiausr\195\188stung checken (d.h. es sucht nicht nach weiteren/besseren Angeln).",
+ CONFIG_EASYLURES_ONOFF = "Automatischer K\195\182der",
+ CONFIG_EASYLURES_INFO = "Wenn aktiviert, wird (falls erforderlich) ein K\195\182der an der Angel angebracht, bevor man mit dem Angeln beginnt.",
+ CONFIG_MOUSEFISHING_ONOFF = "Maus-Angeln",
+ CONFIG_MOUSEFISHING_INFO = "Wenn aktiviert, wirft ein Linksklick die Leine aus und mit Rechtsklick wird der Fang eingeholt.",
+ CONFIG_SHOWLOCATIONZONES_ONOFF = "Zeige Zonen",
+ CONFIG_SHOWLOCATIONZONES_INFO = "Zeigt Zonen und Sub-Zonen an.",
+ CONFIG_SORTBYPERCENT_ONOFF = "Sortiere nach Anzahl gefangener Fische",
+ CONFIG_SORTBYPERCENT_INFO = "Anzeige sortiert nach Zahl der gefangenen Fische, anstelle von Fischnamen.",
+ CONFIG_STVTIMER_ONOFF = "Angelwettbewerb-Timer.",
+ CONFIG_STVTIMER_INFO = "Wenn aktiviert, wird je ein Countdown f\195\188r den Anfang und das Ende des Angelwettbewerbs angezeigt.",
+ CONFIG_STVPOOLSONLY_ONOFF = "Nur in Schw\195\164rme auswerfen",
+ CONFIG_STVPOOLSONLY_INFO = "Wenn aktiviert, wird \"Einfaches Werfen\" nur dann verwendet, wenn der Mauszeiger auf einen Schwarm zeigt.",
+ CONFIG_USEBUTTONHOLE_ONOFF = "ButtonHole verwenden",
+ CONFIG_USEBUTTONHOLE_INFO = "Wenn es erm\195\182glicht wird, steuert das ButtonHole-addon die minimaptaste. Nehmen bewirkt auf dem folgenden LOGON.",
+ CONFIG_USEGATHERER_ONOFF = "Gatherer verwenden",
+ CONFIG_USEGATHERER_INFO = "Wenn aktiviert, werden Schw\195\164rme von #NAME# im Gatherer eingetragen.",
+ CONFIG_SKILL_INFO = "Gesamtbonus durch Ausr\195\188stung.",
+ CONFIG_SKILL_TEXT = "Angeln ",
+ CONFIG_STYLISH_INFO = "Styling-Punkte, inspiriert durch die Draznars Fishing-FAQ in den (englischen) WoW-Foren.",
+ CONFIG_STYLISH_TEXT = "Styling: ",
+
+ TITAN_CLICKTOSWITCH_ONOFF = "Zum Wechseln der Ausr\195\188stung klicken.",
+ TITAN_CLICKTOSWITCH_INFO = "Wenn aktiviert, wechselt ein Linksklick die Ausr\195\188stung, ansonsten \195\182ffnet sich das #NAME#-Fenster.",
+
+ LEFTCLICKTODRAG = "Linksklick zum Ziehen",
+ RIGHTCLICKFORMENU = "Rechtsklick \195\182ffnet das Men\195\188.",
+ WATCHERCLICKHELP = "#LEFTCLICKTODRAG#\n#RIGHTCLICKFORMENU#",
+
+ MINIMAPBUTTONPLACEMENT = "Plazierung des Icons",
+ MINIMAPBUTTONPLACEMENTTOOLTIP = "Erlaubt Dir, das #NAME#-Icon um die Minimap zu verschieben.",
+ CONFIG_MINIMAPBUTTON_ONOFF = "Anzeigen des Minimap-Icons",
+ CONFIG_MINIMAPBUTTON_INFO = "Zeige das #NAME#-Icon an der Minimap an.",
+
+ CONFIG_ENHANCESOUNDS_ONOFF = "Angel-Ger\195\164usche verst\195\164rken",
+ CONFIG_ENHANCESOUNDS_INFO = "Maximiere Gesamtlautst\195\164rke und reduziere die Umgebungslautst\195\164rke, um das Pl\195\164tschern des K\195\182ders besser wahrnehmen zu k\195\182nnen.",
+
+ -- messages
+ COMPATIBLE_SWITCHER = "Kein kompatibles Ausr\195\188stungs-Wechsel-Addon gefunden.",
+ FAILEDINIT = "Nicht richtig initialisiert.",
+ IMPORTMSG = "'%s'-Datenbank importiert.",
+ NOIMPORTMSG = "Datenbanken Impp, DataFish oder FishInfo2 nicht gefunden.",
+ ADDFISHIEMSG = "F\195\188ge %s an Position %s hinzu.",
+ ADDSCHOOLMSG = "F\195\188ge '%s' an Position %s hinzu.",
+ NODATAMSG = "Keine Fischdaten vorhanden.",
+ TOOFASTMSG = "Kann Ausr\195\188stung nicht schnell wechseln.",
+ CLEANUP_NONEMSG = "Keine alten Einstellungen zur\195\188ckbehalten.",
+ CLEANUP_WILLMSG = "Alte Einstellungen verblieben f\195\188r |c#GREEN#%s|r: %s.",
+ CLEANUP_DONEMSG = "Alte Einstellungen entfernt f\195\188r |c#GREEN#%s|r: %s.",
+ CLEANUP_NOOLDMSG = "Es gibt keine alten Einstellungen f\195\188r Spieler |c#GREEN#%s|r.",
+ NONEAVAILABLE_MSG = "Keine verf\195\188gbar",
+ UPDATEDB_MSG = "%d Fischnamen aktualisiert.",
+
+ NOTLINKABLE = "",
+
+ TIMETOGO = "Angelwettbewerb beginnt in %d:%02d",
+ TIMELEFT = "Angelwettbewerb endet in %d:%02d",
+
+ STVZONENAME = "Schlingendorntal",
+
+ TOOLTIP_HINT = "Hinweis:";
+ TOOLTIP_HINTSWITCH = "wechselt ein Linksklick die Ausr\195\188stung",
+ TOOLTIP_HINTTOGGLE = "Linksklick \195\182ffnet das #NAME#-Fenster.",
+
+ -- Key binding support
+ BINDING_HEADER_FISHINGBUDDY_BINDINGS = "#NAME#",
+ BINDING_NAME_FISHINGBUDDY_TOGGLE = "#NAME# anzeigen",
+ BINDING_NAME_FISHINGBUDDY_SWITCH = "Ausr\195\188stung wechseln",
+
+ BINDING_NAME_TOGGLEFISHINGBUDDY_LOC = "Zonen-Fenster anzeigen",
+ BINDING_NAME_TOGGLEFISHINGBUDDY_OUT = "Outfit-Fenster anzeigen",
+ BINDING_NAME_TOGGLEFISHINGBUDDY_OPT = "Optionen-Fenster anzeigen",
+};
+
+FishingTranslations["deDE"].IMPORT_HELP = {
+ "|c#GREEN#/fb #IMPORT#|r",
+ " Importiere Impps Fishinfo- oder FishInfo2-Daten.",
+};
+
+FishingTranslations["deDE"].SWITCH_HELP = {
+ "|c#GREEN#/fb #SWITCH#|r",
+ " wechsle deine Angelausr\195\188stung und -kleidung.",
+};
+
+FishingTranslations["deDE"].WATCHER_HELP = {
+ "|c#GREEN#/fb #WATCHER#|r [|c#GREEN##WATCHER_LOCK#|r oder |c#GREEN##WATCHER_UNLOCK#|r oder |c#GREEN##RESET#|r]",
+ " fixieren .. Fixieren der \195\156bersicht,",
+ " freigeben .. Entriegeln zum Verschieben,",
+ " reset .. Zur\195\188cksetzen",
+};
+
+FishingTranslations["deDE"].CURRENT_HELP = {
+ "|c#GREEN#/fb #CURRENT# #RESET#|r",
+ " Zur\195\188cksetzen der w\195\164hrend der gegenw\195\164rtigen Session gefangenen Fische.",
+ };
+FishingTranslations["deDE"].CLEANUP_HELP = {
+ "|c#GREEN#/fb #CLEANUP#|r [|c#GREEN##CHECK#|r or |c#GREEN##NOW#|r]",
+ " Alte Einstellungen aufr\195\164umen. |c#GREEN##CHECK#|r verzeichnet",
+ " die alten Einstellungen, die von |c#GREEN##NOW#|r entfernt werden.",
+};
+
+FishingTranslations["deDE"].PRE_HELP = {
+ "Du kannst |c#GREEN#/fishingbuddy|r oder |c#GREEN#/fb|r f\195\188r alle Befehle benutzen",
+ "|c#GREEN#/fb|r: schaltet das Fenster ein/aus.",
+ "|c#GREEN#/fb #HELP#|r: zeigt diesen Hilfetext",
+};
+FishingTranslations["deDE"].POST_HELP = {
+ "Du kannst die Fensteraktivierung und den",
+ "Befehl zum Wechseln deiner Ausstattung in den",
+ "\"Tastaturbelegungen\" festlegen.",
+};
diff --git a/FishingBuddy/localization.es.lua b/FishingBuddy/localization.es.lua
new file mode 100644
index 0000000..e9e969e
--- /dev/null
+++ b/FishingBuddy/localization.es.lua
@@ -0,0 +1,121 @@
+FishingTranslations["esES"] = {
+ NAME = "Fishing Buddy",
+ DESCRIPTION1 = "Seguimiento de las capturas que has hecho",
+ DESCRIPTION2 = "y maneja tu ca\195\177a de pescar.",
+
+ -- Tab labels and tooltips
+ LOCATIONS_INFO = "Muestra info de zona de pesca",
+ LOCATIONS_TAB = "Zona",
+ OPTIONS_INFO = "Establece #NAME# opciones",
+ OPTIONS_TAB = "Opciones",
+
+ POINT = "punto",
+ POINTS = "puntos",
+
+ RAW = "Crudo",
+ FISH = "Pesca",
+
+ BOBBER_NAME = "Anzuelo",
+ FISHINGSKILL = "Pesca",
+ HELP = "ayuda",
+ SWITCH = "cambia",
+ IMPORT = "importa",
+
+ OIL_SPILL = "Perdita de Petro'leo",
+
+ ADD = "a\195\177de",
+ REPLACE = "reemplaza",
+ UPDATE = "actualiza",
+ CURRENT = "actual",
+ RESET = "resetea",
+ CLEANUP = "limpia",
+ CHECK = "chequea",
+ NOW = "ahora",
+
+ NOREALM = "reino desconocido",
+
+ WATCHER = "observador",
+ WATCHER_LOCK = "bloquea",
+ WATCHER_UNLOCK = "desbloquea",
+
+ UNKNOWN = "Desconocido",
+ WEEKLY = "Semanal",
+ HOURLY = "Por hora",
+
+ KEYS_LABEL_TEXT = "Modificadores:",
+ KEYS_NONE_TEXT = "Ninguno",
+ KEYS_SHIFT_TEXT = "Shift",
+ KEYS_CTRL_TEXT = "Control",
+ KEYS_ALT_TEXT = "Alt",
+
+ SHOWFISHIES = "Muestra Pez",
+ SHOWFISHIES_INFO = "Muestra historial de pesca por tipo de pez.",
+
+ SHOWLOCATIONS = "Ubicaciones",
+ SHOWLOCATIONS_INFO = "Muestra hostorial de pesca por zona de pesca.",
+
+ -- Option names and tooltips
+ CONFIG_SHOWNEWFISHIES_ONOFF = "Muestra nuevos peces",
+ CONFIG_SHOWNEWFISHIES_INFO = "Muestra un mensaje en el chat cuando la captura es nueva en el \195\161rea actual.",
+ CONFIG_FISHWATCH_ONOFF = "Observador",
+ CONFIG_FISHWATCH_INFO = "Muestra un texto con la captura en el \195\161rea actual.",
+ CONFIG_FISHWATCHSKILL_ONOFF = "Muestra habilidad actual",
+ CONFIG_FISHWATCHSKILL_INFO = "Muestra habilidad y mods en el \195\161rea de observaci\195\179n.",
+ CONFIG_FISHWATCHZONE_ONOFF = "Muestra zona actual",
+ CONFIG_FISHWATCHZONE_INFO = "Muestra zona actual en el \195\161rea de observaci\195\179n.",
+ CONFIG_FISHWATCHONLY_ONOFF = "Solo cuando pescas",
+ CONFIG_FISHWATCHONLY_INFO = "Solo muestra capturas en el observador si estas pescando actualmente",
+ CONFIG_FISHWATCHPERCENT_ONOFF = "Muestra porcentaje capturado",
+ CONFIG_FISHWATCHPERCENT_INFO = "Muestra el porcentaje de cada tipo de pez en el observador",
+ CONFIG_EASYLURES_ONOFF = "Se\195\177uelo facil",
+ CONFIG_EASYLURES_INFO = "Si activado, se aplicar\195\161 un se\195\177uelo a tu ca\195\177a antes de empezar a pescar siempre que lo necesites.",
+ CONFIG_ONLYMINE_ONOFF = "Equipa solo ca\195\177a",
+ CONFIG_ONLYMINE_INFO = "Si activado, captura facil solo cequear\195\161 si llevas la ca\195\177a (p.ej. no buscar\195\161 todas las posibilidades).",
+ CONFIG_SHOWLOCATIONZONES_ONOFF = "Muestra zonas",
+ CONFIG_SHOWLOCATIONZONES_INFO = "Muestra zonas y subzonas.",
+ CONFIG_SORTBYPERCENT_ONOFF = "Por n\195\186mero de capturas",
+ CONFIG_SORTBYPERCENT_INFO = "Ordena la pantalla con el n\195\186mero de peces capturadas y no por el nombre.",
+ CONFIG_STVTIMER_ONOFF = "Marcador de Fishing Extravaganza",
+ CONFIG_STVTIMER_INFO = "Si activado, muestra la cuenta atras para el comienzo de Fishing Extravaganza y muestra el tiempo restante.",
+ CONFIG_USEBUTTONHOLE_ONOFF = "Usa ButtonHole",
+ CONFIG_USEBUTTONHOLE_INFO = "Si activo, al addon ButtonHole controlar\195\161 el bot\195\179n del minimapa. Hace efecto al siguiente login.",
+
+ CONFIG_OUTFITTER_TEXT = "Bonus equipo habilidad: %s\r\nPuntuacion estilo Draznar's: %d ";
+
+ CLICKTOSWITCH_ONOFF = "Click para cambiar",
+ CLICKTOSWITCH_INFO = "Si activado, click-izq. Cambia equipos, sino saltar\195\161la ventana Fishing Buddy.",
+
+ LEFTCLICKTODRAG = "Click-izq para mover",
+
+ MINIMAPBUTTONPLACEMENT = "Posici\195\179n Bot\195\179n",
+ MINIMAPBUTTONPLACEMENTTOOLTIP = "Permite mover el #NAME# icono alrdedor del minimapa",
+ CONFIG_MINIMAPBUTTON_ONOFF = "Muestra icono minimapa",
+ CONFIG_MINIMAPBUTTON_INFO = "Muestra un #NAME# icono en el minimapa.",
+
+ CONFIG_ENHANCESOUNDS_ONOFF = "Activa sonidos de pesca",
+ CONFIG_ENHANCESOUNDS_INFO = "Maximiza el vol\195\186men y minimiza el vol\195\186men del ambiente para que se aprecie mejor el sonido cuando se pesca.",
+
+ -- messages
+ FAILEDINIT = "No inicializ\195\179 correctamente.",
+ IMPORTMSG = "BaseDatos '%s' importada.",
+ NOIMPORTMSG = "No Impp, DataFish, o FishInfo2 BasesDatos encontradas.",
+ ADDFISHIEMSG = "A\195\177diendo %s a zona %s.",
+ NODATAMSG = "No datos pesca disponibles.",
+ CLEANUP_NONEMSG = "No quedan antig\195\186os ajustes.",
+ CLEANUP_WILLMSG = "Ajustes antig\195\186os quedan para |c#GREEN#%s|r: %s.",
+ CLEANUP_DONEMSG = "Borrados ajustes antig\195\186os para |c#GREEN#%s|r: %s.",
+ CLEANUP_NOOLDMSG = "No hay ajustes antig\195\186os para jugador |c#GREEN#%s|r.",
+
+ NOTLINKABLE = "",
+
+ TIMETOGO = "Extravaganza comienza en %d:%02d",
+ TIMELEFT = "Extravaganza acaba en %d:%02d",
+
+ STVZONENAME = "Stranglethorn Vale",
+
+ TOOLTIP_HINT = "Consejo:",
+ TOOLTIP_HINTSWITCH = "click para cambiar equipos",
+ TOOLTIP_HINTTOGGLE = "click para mostar #NAME# ventana.",
+};
+
+
diff --git a/FishingBuddy/localization.fr.lua b/FishingBuddy/localization.fr.lua
new file mode 100644
index 0000000..c691adf
--- /dev/null
+++ b/FishingBuddy/localization.fr.lua
@@ -0,0 +1,128 @@
+FishingTranslations["frFR"] = {
+ NAME = "Fishing Buddy";
+ DESCRIPTION1 = "Se souvient des poissons pris et";
+ DESCRIPTION2 = "organise votre \195\169quipement.";
+
+ -- Tab labels and tooltips
+ LOCATIONS_INFO = "Affiche les informations de p\195\170che locales";
+ LOCATIONS = "Localisations";
+ OPTIONS_INFO = "R\195\168gle les options";
+ OPTIONS = "Options";
+
+ POINT = "point";
+ POINTS = "points";
+
+ RAW = "Raw";
+
+ BOBBER_NAME = "Fishing Bobber";
+ FISHINGSKILL = "P\195\170che";
+ HELP = "Aide";
+ SWITCH = "switch";
+ IMPORT = "import";
+
+ ADD = "add";
+ REPLACE = "replace";
+ UPDATE = "update";
+ CURRENT = "current";
+ RESET = "reset";
+ CLEANUP = "cleanup";
+ CHECK = "check";
+ NOW = "NOW";
+
+ WATCHER = "watcher";
+ WATCHER_LOCK = "lock";
+ WATCHER_UNLOCK = "unlock";
+
+ UNKNOWN = "Inconnu";
+ WEEKLY = "Hebdomadaire";
+ HOURLY = "toutes les heures";
+
+ KEYS_LABEL_TEXT = "Touches:",
+ KEYS_NONE_TEXT = "Aucune",
+ KEYS_SHIFT_TEXT = "Shift",
+ KEYS_CTRL_TEXT = "CTRL",
+ KEYS_ALT_TEXT = "Alt",
+
+ SHOWFISHIES = "Poissons";
+ SHOWFISHIES_INFO = "Affiche vos prises class\195\169es par type de poisson.";
+
+ SHOWLOCATIONS = "Montrer les zones";
+ SHOWLOCATIONS_INFO = "Affiche vos prises class\195\169es par r\195\169gions.";
+
+ -- Option names and tooltips
+ CONFIG_SHOWNEWFISHIES_ONOFF = "Montrer les nouveaux poissons",
+ CONFIG_SHOWNEWFISHIES_INFO = "Affiche un message dans la zone de texte quand un nouveau poisson est p\195\169ch\195\169.",
+ CONFIG_FISHWATCH_ONOFF = "Archives des poissons",
+ CONFIG_FISHWATCH_INFO = "Affiche une zone de texte avec les poissons d\195\169j\195\160 p\195\169ch\195\169s dans la zone courante.",
+ CONFIG_FISHWATCHONLY_ONOFF = "Seulement en p\195\169chant",
+ CONFIG_FISHWATCHONLY_INFO = "Montrer seulement les poissons lorsque vous \195\170tes en train de p\195\169cher.",
+ CONFIG_FISHWATCHSKILL_ONOFF = "Niveau actuel",
+ CONFIG_FISHWATCHSKILL_INFO = "Affiche votre niveau courant en p\195\170che ainsi que les am\195\169liorations dans la zone de texte.",
+ CONFIG_FISHWATCHZONE_ONOFF = "Zone courante",
+ CONFIG_FISHWATCHZONE_INFO = "Affiche la zone courante dans la zone de texte.",
+ CONFIG_FISHWATCHPERCENT_ONOFF = "Montrer les pourcentages",
+ CONFIG_FISHWATCHPERCENT_INFO = "Affiche les pourcentages pour chaque type de poissons dans la zone de texte.",
+ CONFIG_EASYCAST_ONOFF = "Lancer la ligne facilement",
+ CONFIG_EASYCAST_INFO = "Si activ\195\169, lorsque votre canne \195\160 p\195\170che est \195\169quip\195\169e, un clic droit lance la ligne.",
+ CONFIG_SORTBYPERCENT_ONOFF = "Trier par quantit\195\169 de poissons",
+ CONFIG_SORTBYPERCENT_INFO = "Trie l'affichage par quantit\195\169 de poissons p\195\169ch\195\169s au lieu du nom.",
+ CONFIG_STVTIMER_ONOFF = "Timer du concours de p\195\170che",
+ CONFIG_STVTIMER_INFO = "Si activ\195\169, un compteur sera affich\195\169 indiquant le temps restant avant le debut et la fin du concours.",
+ CONFIG_USEGATHERER_ONOFF = "Utiliser Gatherer",
+ CONFIG_USEGATHERER_INFO = "Si activ\195\169, un compteur sera affich\195\169 indiquant le temps restant avant le debut et la fin du concours.",
+
+ CLICKTOSWITCH_ONOFF = "Clique pour changer";
+ CLICKTOSWITCH_INFO = "Si activ\195\169, un clic gauche change l'\195\169quipement, si d\195\169sactiv\195\169, affiche la fen\195\170tre.";
+
+ LEFTCLICKTODRAG = "Clique gauche pour bouger";
+
+ MINIMAPBUTTONPLACEMENT = "Position du bouton";
+ MINIMAPBUTTONPLACEMENTTOOLTIP = "Permet de bouger le bouton de #NAME# autour de la minimap";
+ CONFIG_MINIMAPBUTTON_ONOFF = "Affiche le bouton de la minimap.";
+ CONFIG_MINIMAPBUTTON_INFO = "Affiche le bouton de #NAME# pr\195\168s de la minimap.";
+
+ CONFIG_ENHANCESOUNDS_ONOFF = "Augmentez les bruits de p\195\170che";
+ CONFIG_ENHANCESOUNDS_INFO = "Maximisez le volume sain et r\195\169duisez au minimum le volume ambiant pour faire le bobber \195\169bruiter plus apparent tout en p\195\170chant.";
+
+ TIMETOGO = "Le concours de p\195\170che commence dans %d:%02d";
+ TIMELEFT = "Le concours de p\195\170che se termine dans %d:%02d";
+
+ STVZONENAME = "Vall\195\169e de Strangleronce";
+
+ BINDING_HEADER_FISHINGBUDDY_BINDINGS = "#NAME#";
+ BINDING_NAME_FISHINGBUDDY_TOGGLE = "Toggle:#NAME#(Fen\195\170tre)";
+ BINDING_NAME_FISHINGBUDDY_SWITCH = "Changer l'\195\169quipement";
+
+ BINDING_NAME_TOGGLEFISHINGBUDDY_LOC = "Toggle: #NAME# (Panneau de r\195\169gion)";
+ BINDING_NAME_TOGGLEFISHINGBUDDY_OPT = "Toggle: #NAME# (Panneau d'options)";
+
+ ABBREV_APRIL = "Avr",
+};
+
+FishingTranslations["frFR"].IMPORT_HELP = {
+ "|c#GREEN#/fb #IMPORT#|r",
+ " Importe les donn\195\169es d'Impp's fishinfo ou de FishInfo2.",
+};
+FishingTranslations["frFR"].SWITCH_HELP = {
+ "|c#GREEN#/fb #SWITCH#|r",
+ " Change l'\195\169quipement (si OutfitDisplayFrame ou Outfitter est charg\195\169)",
+};
+FishingTranslations["frFR"].WATCHER_HELP = {
+ "|c#GREEN#/fb #WATCHER#|r [|c#GREEN##WATCHER_LOCK#|r or |c#GREEN##WATCHER_UNLOCK#|r or |c#GREEN##RESET#|r]",
+ " D\195\169v\195\169rouille pour bouger la fen\195\170tre,",
+ " lock pour arr\195\170ter, reset pour mettre a z\195\169ro",
+};
+FishingTranslations["frFR"].CURRENT_HELP = {
+ "|c#GREEN#/fb #CURRENT# #RESET#|r",
+ " Met a z\195\169ro des poissons pris durant cette session.",
+};
+
+FishingTranslations["frFR"].PRE_HELP = {
+ "Vous pouvez utiliser |c#GREEN#/fishingbuddy|r ou |c#GREEN#/fb|r pour toutes les commandes",
+ "|c#GREEN#/fb|r: seul, affiche/cache la fen\195\170tre de FishingBuddy",
+ "|c#GREEN#/fb #HELP#|r: affiche ce message",
+};
+FishingTranslations["frFR"].POST_HELP = {
+ "Vous pouvez assigner une touche pour afficher/cacher la fen\195\170tre et/ou",
+ "changer d'\195\169quipement dans la fen\195\170tre \"Raccourcis\".",
+};
diff --git a/FishingBuddy/localization.lua b/FishingBuddy/localization.lua
new file mode 100644
index 0000000..3276c19
--- /dev/null
+++ b/FishingBuddy/localization.lua
@@ -0,0 +1,232 @@
+-- default to American English
+
+FishingTranslations = {};
+FishingTranslations["enUS"] = {
+ NAME = "Fishing Buddy",
+ DESCRIPTION1 = "Keep track of the fish you've caught",
+ DESCRIPTION2 = "and manage your fishing gear.",
+ DESCRIPTION = "#DESCRIPTION1# #DESCRIPTION2#",
+
+ ID = "FishingBuddy",
+ MSGID = "FBAM", -- Fishing Buddy Addon Message
+
+ WINDOW_TITLE = "#NAME# v#VERSION#",
+ FISHINGTEXTURE = "Interface\\Icons\\Trade_Fishing",
+
+ -- Tab labels and tooltips
+ LOCATIONS_INFO = "Show fishing location information",
+ LOCATIONS_TAB = "Locations",
+ OPTIONS_INFO = "Set #NAME# options",
+ OPTIONS_TAB = "Options",
+
+ POINT = "point",
+ POINTS = "points",
+
+ RAW = "Raw",
+ FISH = "Fish",
+
+ BOBBER_NAME = "Fishing Bobber",
+ FISHINGSKILL = "Fishing",
+ HELP = "help",
+ SWITCH = "switch",
+ IMPORT = "import",
+ UPDATEDB = "updatedb",
+ FORCE = "force",
+
+ OUTFITS = "Outfits",
+
+ SCHOOL = "School", -- e.g. 'Oily Blackmouth School'
+ FLOATING_WRECKAGE = "Floating Wreckage",
+ FLOATING_DEBRIS = "Floating Debris",
+ ELEM_WATER = "Elemental Water",
+ OIL_SPILL = "Oil Spill",
+
+ ADD = "add",
+ REPLACE = "replace",
+ UPDATE = "update",
+ CURRENT = "current",
+ RESET = "reset",
+ CLEANUP = "cleanup",
+ CHECK = "check",
+ NOW = "now",
+
+ NOREALM = "unknown realm",
+
+ WATCHER = "watcher",
+ WATCHER_LOCK = "lock",
+ WATCHER_UNLOCK = "unlock",
+
+ UNKNOWN = "Unknown",
+ WEEKLY = "weekly",
+ HOURLY = "hourly",
+
+ BROADCAST_LABEL_TEXT = "Broadcast:";
+ BROADCAST_DUMP_TEXT = "Blocked";
+ BROADCAST_RECV_TEXT = "Accept";
+
+ OFFSET_LABEL_TEXT = "Offset:";
+
+ KEYS_LABEL_TEXT = "Modifiers:",
+ KEYS_NONE_TEXT = "None",
+ KEYS_SHIFT_TEXT = "Shift",
+ KEYS_CTRL_TEXT = "Control",
+ KEYS_ALT_TEXT = "Alt",
+
+ SHOWFISHIES = "Show fish",
+ SHOWFISHIES_INFO = "Display fishing history grouped by fish type.",
+
+ SHOWLOCATIONS = "Locations",
+ SHOWLOCATIONS_INFO = "Display fishing history grouped by where caught.",
+
+ -- Option names and tooltips
+ CONFIG_SHOWNEWFISHIES_ONOFF = "Show new fish",
+ CONFIG_SHOWNEWFISHIES_INFO = "Display a message in the chat area when a new fish for the current location is caught.",
+ CONFIG_FISHWATCH_ONOFF = "Fish watcher",
+ CONFIG_FISHWATCH_INFO = "Display a text overlay with the fish caught in the current location.",
+ CONFIG_FISHWATCHONLY_ONOFF = "Only while fishing",
+ CONFIG_FISHWATCHONLY_INFO = "Only watch the fish caught when we're actually fishing",
+ CONFIG_FISHWATCHSKILL_ONOFF = "Current skill",
+ CONFIG_FISHWATCHSKILL_INFO = "Display your current fishing skill and mods in the fish watch area.",
+ CONFIG_FISHWATCHZONE_ONOFF = "Current zone",
+ CONFIG_FISHWATCHZONE_INFO = "Display the current zone in the fish watch area.",
+ CONFIG_FISHWATCHPERCENT_ONOFF = "Show percentages",
+ CONFIG_FISHWATCHPERCENT_INFO = "Display the percentage of each kind of fish on the watch display",
+ CONFIG_SUITUPFIRST_ONOFF = "Dress for success",
+ CONFIG_SUITUPFIRST_INFO = "Put on your fishing outfit if you're not wearing it when the binding key is pressed",
+ CONFIG_EASYCAST_ONOFF = "Easy Cast",
+ CONFIG_EASYCAST_INFO = "If enabled, then when a fishing pole is equipped and you right click, you will cast the line.",
+ CONFIG_EASYLURES_ONOFF = "Easy Lures",
+ CONFIG_EASYLURES_INFO = "If enabled, a lure will applied to your fishing pole before you start fishing, whenever you need one.",
+ CONFIG_ONLYMINE_ONOFF = "Outfit Pole Only",
+ CONFIG_ONLYMINE_INFO = "If enabled, easy cast will only check for your outfit's fishing pole (i.e. it won't search all possible poles for a match).",
+ CONFIG_MOUSEFISHING_ONOFF = "Mouse fishing",
+ CONFIG_MOUSEFISHING_INFO = "If enabled, left-click throws your line and right-click loots the bobber",
+ CONFIG_SHOWLOCATIONZONES_ONOFF = "Show Zones",
+ CONFIG_SHOWLOCATIONZONES_INFO = "Display both zones and subzones.",
+ CONFIG_SORTBYPERCENT_ONOFF = "Sort by number caught",
+ CONFIG_SORTBYPERCENT_INFO = "Order displays by the number of fish caught instead of by name.",
+ CONFIG_STVTIMER_ONOFF = "Fishing Extravaganza timer",
+ CONFIG_STVTIMER_INFO = "If enabled, display a countdown timer for the start of the Fishing Extravaganza and a countdown of the timer left.",
+ CONFIG_STVPOOLSONLY_ONOFF = "Only cast in pools",
+ CONFIG_STVPOOLSONLY_INFO = "If enabled, easy cast will only be enabled if the cursor is over a fishing hole.",
+ CONFIG_USEBUTTONHOLE_ONOFF = "Use ButtonHole",
+ CONFIG_USEBUTTONHOLE_INFO = "If enabled, the ButtonHole addon will control the minimap button. Takes effect on the next login.",
+ CONFIG_USEGATHERER_ONOFF = "Use Gatherer",
+ CONFIG_USEGATHERER_INFO = "If enabled, #NAME# will inform Gatherer about fishing holes.",
+
+ CONFIG_OUTFITTER_TEXT = "Outfit skill bonus: %s\r\nDraznar's style score: %d ",
+
+ CLICKTOSWITCH_ONOFF = "Click to switch",
+ CLICKTOSWITCH_INFO = "If enabled, a left click switches outfits, otherwise it brings up the Fishing Buddy window.",
+
+ LEFTCLICKTODRAG = "Left-click to drag",
+ RIGHTCLICKFORMENU = "Right-click for menu",
+ WATCHERCLICKHELP = "#LEFTCLICKTODRAG#\n#RIGHTCLICKFORMENU#",
+
+ MINIMAPBUTTONPLACEMENT = "Button Placement",
+ MINIMAPBUTTONPLACEMENTTOOLTIP = "Allows you to move the #NAME# icon around the minimap",
+ CONFIG_MINIMAPBUTTON_ONOFF = "Display minimap icon",
+ CONFIG_MINIMAPBUTTON_INFO = "Display a #NAME# icon on the minimap.",
+
+ CONFIG_ENHANCESOUNDS_ONOFF = "Enhance fishing sounds",
+ CONFIG_ENHANCESOUNDS_INFO = "Maximize sound volume and minimize ambient volume to make the bobber noise more noticeable while fishing.",
+
+ HIDEINWATCHER = "Display this fish in the watcher",
+
+ -- messages
+ COMPATIBLE_SWITCHER = "No compatible outfit switcher found.",
+ TOOMANYFISHERMEN = "You have more than one easy cast mod installed.",
+ FAILEDINIT = "Did not initialize correctly.",
+ IMPORTMSG = "Imported '%s' database.",
+ NOIMPORTMSG = "No Impp, DataFish, or FishInfo2 databases found.",
+ ADDFISHIEMSG = "Adding %s to location %s.",
+ ADDSCHOOLMSG = "Adding '%s' to location %s.",
+ NODATAMSG = "No fishing data available.",
+ CLEANUP_NONEMSG = "No old settings remain.",
+ CLEANUP_WILLMSG = "Old settings remaining for |c#RED#%s|r: %s.",
+ CLEANUP_DONEMSG = "Old settings removed for |c#RED#%s|r: %s.",
+ CLEANUP_NOOLDMSG = "There are no old settings for player |c#GREEN#%s|r.",
+ NONEAVAILABLE_MSG = "None available",
+ UPDATEDB_MSG = "Updated %d fish names.",
+
+ MINIMUMSKILL = "Minimum skill: %d",
+ NOTLINKABLE = "- ",
+ CAUGHTTHISMANY = "Caught %d",
+ CAUGHTTHISTOTAL = "Total %d",
+ FISHTYPES = "Fish types: %d",
+
+ DASH = " -- ",
+ FISHCAUGHT = "%d %s",
+ TIMETOGO = "Extravaganza starts in %d:%02d",
+ TIMELEFT = "Extravaganza ends in %d:%02d",
+ FATLADYSINGS = "|c#RED#Extravaganza is over|r (%d:%02d left)",
+ RIGGLE_BASSBAIT = "^Riggle Bassbait .*: .*! (.*) .*!$",
+
+ STVZONENAME = "Stranglethorn Vale",
+
+ TOOLTIP_HINT = "Hint:",
+ TOOLTIP_HINTSWITCH = "click to switch outfits",
+ TOOLTIP_HINTTOGGLE = "click to show the #NAME# window.",
+
+ -- Key binding support
+ BINDING_HEADER_FISHINGBUDDY_BINDINGS = "#NAME#",
+ BINDING_NAME_FISHINGBUDDY_TOGGLE = "Toggle #NAME# Window",
+ BINDING_NAME_FISHINGBUDDY_SWITCH = "Switch Fishing Outfit",
+ BINDING_NAME_FISHINGBUDDY_GOFISHING = "Suit up and go fishing",
+
+ BINDING_NAME_TOGGLEFISHINGBUDDY_LOC = "Toggle #NAME# Locations Pane",
+ BINDING_NAME_TOGGLEFISHINGBUDDY_OPT = "Toggle #NAME# Options Pane",
+};
+
+FishingTranslations["enUS"].IMPORT_HELP = {
+ "|c#GREEN#/fb #IMPORT#|r",
+ " Import Impp's fishinfo or FishInfo2 data.",
+};
+FishingTranslations["enUS"].SWITCH_HELP = {
+ "|c#GREEN#/fb #SWITCH#|r",
+ " swap outfits (if OutfitDisplayFrame or Outfitter is available)",
+};
+FishingTranslations["enUS"].WATCHER_HELP = {
+ "|c#GREEN#/fb #WATCHER#|r [|c#GREEN##WATCHER_LOCK#|r or |c#GREEN##WATCHER_UNLOCK#|r or |c#GREEN##RESET#|r]",
+ " Unlock the watcher to move the window,",
+ " lock to stop, reset to reset",
+};
+FishingTranslations["enUS"].CURRENT_HELP = {
+ "|c#GREEN#/fb #CURRENT# #RESET#|r",
+ " Reset the fish caught during the current session.",
+};
+FishingTranslations["enUS"].UPDATEDB_HELP = {
+ "|c#GREEN#/fb #UPDATEDB# [#FORCE#]|r",
+ " Try and find the names of all the fish we don't know already.",
+ " An attempt is made to skip 'rare' fish that may disconnect you",
+ " from the server -- use the '#FORCE#' option to override the check.",
+};
+FishingTranslations["enUS"].CLEANUP_HELP = {
+ "|c#GREEN#/fb #CLEANUP#|r [|c#GREEN#f#CHECK#|r or |c#GREEN##NOW#|r]",
+ " Clean up old settings. |c#GREEN##CHECK#|r lists which",
+ " settings will be removed by |c#GREEN##NOW#|r.",
+};
+
+FishingTranslations["enUS"].PRE_HELP = {
+ "You can use |c#GREEN#/fishingbuddy|r or |c#GREEN#/fb|r for all commands",
+ "|c#GREEN#/fb|r: by itself, toggle the Fishing Buddy window",
+ "|c#GREEN#/fb #HELP#|r: display this message",
+};
+FishingTranslations["enUS"].POST_HELP = {
+ "You can bind both the window toggle and the outfit",
+ " switch command to keys in the \"Key Bindings\" window.",
+};
+
+FishingTranslations["enUS"].HELPMSG = {
+ "@PRE_HELP",
+ "@SWITCH_HELP",
+ "@WATCHER_HELP",
+ "@CURRENT_HELP",
+ "@CLEANUP_HELP",
+ "@IMPORT_HELP",
+ "@TRACKING_HELP",
+ "@UPDATEDB_HELP",
+ " ",
+ "@POST_HELP",
+};
+
diff --git a/FishingBuddy/readme.txt b/FishingBuddy/readme.txt
new file mode 100644
index 0000000..8158a4e
--- /dev/null
+++ b/FishingBuddy/readme.txt
@@ -0,0 +1,64 @@
+Fishing Buddy
+-------------
+
+ Yet another fishing support add-on. It's a combination of TackleBox,
+ Impp's Fishing Info and a fishing outfit manager all rolled into one. I
+ wrote it both to provide some functionality that was missing from all
+ of the other fishing add-ons I was using and to learn to do add-ons.
+
+ Features:
+ - 'Easy Cast' lets you right-click to cast your line. Use the same mouse
+ button for looting and casting. A double-click will force another cast early
+ - 'Fish Watcher' lets you see the fish you've caught here before (or
+ the fish that you've caught in the current session)
+ - Display your current skill level and the time since you started fishing
+ - Choose your fishing outfit and change into it easily
+ - Support for automatically adding a lure to your fishing pole
+ - Full Titan Panel support
+ - myAddOns support
+ - Preliminary support for tracking 'cycle fish' such as the Nightfin
+ Snapper so you know when to go looking for them
+
+ Example commands:
+ /fishingbuddy or /fb
+ toggle the display of the Fishing Buddy window
+ /fb help
+ print the list of Fishing Buddy commands
+ /fb switch
+ wear your chosen fishing outfit, or change back
+
+ There are two actual add-ons -- the second one, OutfitDisplayFrame,
+ handles the pretty pane to set up your fishing outfit (it's next on
+ the list to be made into something more general that anyone can use).
+ The OutfitDisplayFrame addon can be safely left out if you have a
+ preferred equipment manager.
+
+ alt-clicking on an item in your outfit display will clear it
+
+ Silly stuff:
+ In addition to displaying the fishing bonus for your fishing outfit,
+ it also displays your 'style points' as inferred from Draznar's
+ Fishing FAQ (http://wow.toshimo.com/viewtopic.php?t=272).
+
+ Thanks to the authors of:
+
+ TackleBox -- still adding cool features to keep up with!
+ Impp's Fishing DB
+ QuickWeaponSwap
+ GuildMap
+
+ and many, many others!
+
+ Feel free to send comments to Sutorix=AT=hotmail.com.
+
+Installation
+------------
+
+1. Unzip the 'FishingBuddyVERSION.zip' file
+2. If your unzip program allows you to specify a location, then
+ unzip it into the "Interface/AddOns" folder contained in your
+ WoW folder (the location that WoW was installed)
+3. If your unzip program doesn't let you specify the destination,
+ then find your WoW folder (where it was installed) and drag
+ the 'FishingBuddy' and 'OutfitDisplayFrame' folder into the
+ 'Interface/AddOns' folder.
diff --git a/OutfitDisplayFrame/OutfitDisplayFrame.lua b/OutfitDisplayFrame/OutfitDisplayFrame.lua
new file mode 100644
index 0000000..d2c5441
--- /dev/null
+++ b/OutfitDisplayFrame/OutfitDisplayFrame.lua
@@ -0,0 +1,1286 @@
+OUTFITDISPLAYFRAME_VERSION = GetAddOnMetadata("OutfitDisplayFrame", "Version");
+
+OUTFITDISPLAYFRAME_NAME = "Outfit Display Frame";
+OUTFITDISPLAYFRAME_TITLE = OUTFITDISPLAYFRAME_NAME.." v"..OUTFITDISPLAYFRAME_VERSION;
+OUTFITDISPLAYFRAME_BANKDELAY = 0.5;
+
+local PlayerSlotNames = {
+ [1] = { name = "HeadSlot", tooltip = HEADSLOT };
+ [2] = { name = "NeckSlot", tooltip = NECKSLOT },
+ [3] = { name = "ShoulderSlot", tooltip = SHOULDERSLOT },
+ [4] = { name = "BackSlot", tooltip = BACKSLOT },
+ [5] = { name = "ChestSlot", tooltip = CHESTSLOT },
+ [6] = { name = "ShirtSlot", tooltip = SHIRTSLOT },
+ [7] = { name = "TabardSlot", tooltip = TABARDSLOT },
+ [8] = { name = "WristSlot", tooltip = WRISTSLOT },
+ [9] = { name = "HandsSlot", tooltip = HANDSSLOT },
+ [10] = { name = "WaistSlot", tooltip = WAISTSLOT },
+ [11] = { name = "LegsSlot", tooltip = LEGSSLOT },
+ [12] = { name = "FeetSlot", tooltip = FEETSLOT },
+ [13] = { name = "Finger0Slot", tooltip = FINGER0SLOT },
+ [14] = { name = "Finger1Slot", tooltip = FINGER1SLOT },
+ [15] = { name = "Trinket0Slot", tooltip = TRINKET0SLOT },
+ [16] = { name = "Trinket1Slot", tooltip = TRINKET1SLOT },
+ [17] = { name = "MainHandSlot", tooltip = MAINHANDSLOT },
+ [18] = { name = "SecondaryHandSlot", tooltip = SECONDARYHANDSLOT },
+ [19] = { name = "RangedSlot", tooltip = RANGEDSLOT },
+}
+
+local SavedPickupContainerItem = nil;
+local SavedPickupInventoryItem = nil;
+
+local LastOffSource = nil;
+local PerformSlowerSwap = false;
+local BankIsOpen = false;
+
+local function tonil(val)
+ if ( not val ) then
+ return "nil";
+ else
+ return val;
+ end
+end
+
+local function Print(msg, r, g, b)
+ if ( DEFAULT_CHAT_FRAME ) then
+ if ( not r ) then
+ DEFAULT_CHAT_FRAME:AddMessage(msg);
+ else
+ DEFAULT_CHAT_FRAME:AddMessage(msg, r, g, b);
+ end
+ end
+end
+
+-- Based on code in QuickMountEquip
+local function SafeHookFunction(func, newfunc)
+ local oldValue = getglobal(func);
+ if ( oldValue ~= getglobal(newfunc) ) then
+ setglobal(func, getglobal(newfunc));
+ return true;
+ end
+ return false;
+end
+
+-- this really ought to be in a library somewhere
+local function SplitLink(link)
+ local _,_, color, item, name = string.find(link, "|c(%x+)|Hitem:(%d+:%d+:%d+:%d+)|h%[(.-)%]|h|r");
+ return color, item, name;
+end
+
+function OutfitDisplayFrame_OnLoad()
+ local temp = PickupContainerItem;
+ if ( SafeHookFunction("PickupContainerItem", "OutfitDisplayFrame_PickupContainerItem") ) then
+ SavedPickupContainerItem = temp;
+ end
+
+ temp = PickupInventoryItem;
+ if ( SafeHookFunction("PickupInventoryItem", "OutfitDisplayFrame_PickupInventoryItem") ) then
+ SavedPickupInventoryItem = temp;
+ end
+
+ local parent = this:GetName();
+ for i=1,19,1 do
+ local slotName = PlayerSlotNames[i].name;
+ local button = getglobal(parent..slotName);
+ button.tooltip = PlayerSlotNames[i].tooltip;
+ OutfitDisplayItemButton_Draw(button);
+ PlayerSlotNames[i].id = GetInventorySlotInfo(slotName);
+ end
+
+ -- ITEM_LOCK_CHANGED gets invoked a lot -- let's optimize it
+ this:RegisterEvent("PLAYER_ENTERING_WORLD");
+ this:RegisterEvent("PLAYER_LEAVING_WORLD");
+
+ -- ideas borrowed from "WeaponQuickSwap - by CapnBry"
+ this:RegisterEvent("BANKFRAME_OPENED");
+ this:RegisterEvent("BANKFRAME_CLOSED");
+
+ Print(OUTFITDISPLAYFRAME_TITLE.." loaded.");
+end
+
+local function DressUpItem(model, thing)
+ if ( not model or not thing or thing == "" ) then
+ return;
+ end
+ local item = gsub(thing, "(%d+).*", "%1", 1);
+ model:TryOn(item);
+end
+
+local BankFrameClosedTime = 0;
+
+function OutfitDisplayFrame_OnEvent(...)
+ if (arg[1] == "ITEM_LOCK_CHANGED") and not arg[2] then
+ OutfitDisplayFrame_ExecuteSwapIteration();
+ elseif ( arg[1] == "BANKFRAME_OPENED" or arg[1] == "BANKFRAME_CLOSED" ) then
+ BankFrameIsOpen = ( arg[1] == "BANKFRAME_OPENED" );
+ local frame = getglobal(this:GetName().."MessageUpdateFrame");
+ if ( frame ) then
+ BankFrameClosedTime = OUTFITDISPLAYFRAME_BANKDELAY;
+ frame:Show();
+ end
+ elseif ( arg[1] == "PLAYER_ENTERING_WORLD" ) then
+ this:RegisterEvent("ITEM_LOCK_CHANGED");
+ elseif ( arg[1] == "PLAYER_LEAVING_WORLD" ) then
+ this:UnregisterEvent("ITEM_LOCK_CHANGED");
+ end
+end
+
+function OutfitDisplayFrame_MessageUpdate(elapsed)
+ BankFrameClosedTime = BankFrameClosedTime - elapsed;
+ if ( BankFrameClosedTime <= 0 ) then
+ this:Hide();
+ OutfitDisplayFrame_UpdateMessage(this:GetParent());
+ BankFrameClosedTime = 0;
+ end
+end
+
+local function GetSlotButton(button, slotName)
+ local parent = button:GetParent():GetName();
+ return getglobal(parent..slotName);
+end
+
+local WOW = nil;
+local function _GetItemInfo(link)
+ if ( not WOW ) then
+ WOW = {};
+ local v, b, d = GetBuildInfo();
+ WOW.build = b;
+ WOW.date = d;
+ local s,e,maj,min,dot = string.find(v, "(%d+).(%d+).(%d+)");
+ FishingBuddy.Debug("Version "..v);
+ WOW.major = tonumber(maj);
+ WOW.minor = tonumber(min);
+ WOW.dot = tonumber(dot);
+ end
+-- name, link, rarity, itemlevel, minlevel, itemtype
+-- subtype, stackcount, equiploc, texture
+ local nm,li,ra,il,ml,it,st,sc,el,tx;
+ if ( WOW.major > 1 ) then
+ nm,li,ra,il,ml,it,st,sc,el,tx = GetItemInfo(link);
+ else
+ nm,li,ra,ml,it,st,sc,el,tx = GetItemInfo(link);
+ end
+ return nm,li,ra,ml,it,st,sc,el,tx,il;
+end
+
+local function IsItemOneHanded(item)
+ if ( item ) then
+ local _,_,_,_,_,_,_,bodyslot = _GetItemInfo("item:"..item);
+ if ( bodyslot == "INVTYPE_2HWEAPON" or bodyslot == INVTYPE_2HWEAPON ) then
+ return false;
+ end
+ end
+ return true;
+end
+
+function OutfitDisplayFrame_CursorCanGoInSlot(button)
+ if ( button.forced ) then
+ return false;
+ end
+ local secondary = GetSlotButton(button, "SecondaryHandSlot");
+ local mainbutton = GetSlotButton(button, "MainHandSlot");
+ if ( button == secondary and mainbutton and mainbutton.item ) then
+ return IsItemOneHanded(mainbutton.item);
+ end
+ return CursorCanGoInSlot(button:GetID())
+end
+
+-- much hackery to know what actually is in the cursor when somebody drops it on us
+local OD_Track_Bag = nil;
+local OD_Track_Slot = nil;
+
+-- whatever we think the user picked up, apply it to our stuff
+local function AcceptCursorItem(button)
+ local parent = button:GetParent();
+ local pname = parent:GetName();
+ if ( not OutfitDisplayFrame_CursorCanGoInSlot(button) ) then
+ button = nil;
+ for i=1,19,1 do
+ local temp = getglobal(pname..PlayerSlotNames[i].name);
+ if ( temp and OutfitDisplayFrame_CursorCanGoInSlot(temp) ) then
+ button = temp;
+ end
+ end
+ end
+
+ if ( button ) then
+ local link, texture;
+ if ( OD_Track_Bag ) then
+ link = GetContainerItemLink(OD_Track_Bag, OD_Track_Slot);
+ texture = GetContainerItemInfo(OD_Track_Bag, OD_Track_Slot);
+ else
+ link = GetInventoryItemLink("player", OD_Track_Slot);
+ texture = GetInventoryItemTexture("player", OD_Track_Slot);
+ end
+ button.color, button.item, button.name = SplitLink(link);
+ button.texture = texture;
+ button.used = true;
+ button.empty = nil;
+ button.missing = false;
+ if ( OD_Track_Bag and (OD_Track_Bag == BANK_CONTAINER or
+ OD_Track_Bag > NUM_BAG_SLOTS) ) then
+ button.banked = true;
+ end
+ OutfitDisplayItemButton_Change(button);
+ end
+
+ -- clear the cursor item
+ if ( OD_Track_Bag ) then
+ SavedPickupContainerItem(OD_Track_Bag, OD_Track_Slot);
+ elseif ( OD_Track_Slot ) then
+ SavedPickupInventoryItem(OD_Track_Slot);
+ end
+ OD_Track_Bag = nil;
+ OD_Track_Slot = nil;
+end
+
+-- figure out what the user picked up, so that if they drop it on us we can deal with it
+function OutfitDisplayFrame_TrackItemPickup(bag, slot)
+ OD_Track_Bag = bag;
+ OD_Track_Slot = slot;
+end
+
+function OutfitDisplayFrame_PickupContainerItem(bag, slot)
+ if ( SavedPickupContainerItem ) then
+ SavedPickupContainerItem(bag, slot);
+ end
+ OutfitDisplayFrame_TrackItemPickup(bag, slot);
+end
+
+function OutfitDisplayFrame_PickupInventoryItem(slot)
+ if ( SavedPickupInventoryItem ) then
+ SavedPickupInventoryItem(slot);
+ end
+ OutfitDisplayFrame_TrackItemPickup(nil, slot);
+end
+
+-- handle making the items in the outfit pane do nice things
+function OutfitDisplayItemButton_OnEnter()
+ if ( GameTooltip.finished ) then
+ return;
+ end
+ GameTooltip.finished = 1;
+ GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
+ if (this.item) then
+ local link = "item:"..this.item;
+ if ( GetItemInfo(link) ) then
+ GameTooltip:SetHyperlink(link);
+ elseif ( this.name ) then
+ GameTooltip:SetText(this.name);
+ elseif ( this.tooltip ) then
+ GameTooltip:SetText(this.tooltip);
+ else
+ GameTooltip:SetText("", 1, 0, 0);
+ end
+ elseif ( this.tooltip ) then
+ GameTooltip:AddLine(this.tooltip);
+ else
+ local parentlen = string.len(this:GetParent():GetName())+1;
+ local slotName = strsub(this:GetName(), parentlen);
+ slotName = strsub(slotName, 1, string.len(slotName) - 4);
+ this.tooltip = slotName;
+ GameTooltip:AddLine(this.tooltip);
+ end
+ local parent = this:GetParent();
+ if ( parent.CustomTooltip ) then
+ parent.CustomTooltip(this);
+ end
+ GameTooltip:AddLine(OUTFITDISPLAYFRAME_ALTCLICK,.8,.8,.8,1);
+ GameTooltip:Show();
+end
+
+function OutfitDisplayItemButton_OnEvent(event)
+ if ( event == "CURSOR_UPDATE" ) then
+ if ( not this.forced ) then
+ if ((this.CursorCanGoInSlot and this.CursorCanGoInSlot(this)) or
+ OutfitDisplayFrame_CursorCanGoInSlot(this)) then
+ this:LockHighlight();
+ else
+ this:UnlockHighlight();
+ end
+ end
+ end
+end
+
+function OutfitDisplayItemButton_OnClick(clicked, ignoreModifiers)
+ if ( clicked == "LeftButton" ) then
+ if( not ignoreModifiers or ignoreModifiers == 0 ) then
+ if ( IsShiftKeyDown() ) then
+ if ( this.item and ChatFrameEditBox:IsVisible() ) then
+ local color = this.color;
+ if ( not color ) then
+ color = "ffffffff";
+ end
+ local link = "|c"..color.."|Hitem"..this.item.."|h["..this.name.."]|h|r";
+ ChatFrameEditBox:Insert(link);
+ return;
+ end
+ elseif ( IsAltKeyDown() ) then
+ OutfitDisplayItemButton_Clear(this, false, false);
+ OutfitDisplayItemButton_Change(this);
+ return;
+ end
+ end
+ -- fall through for drags and non-modified clicks
+ if ( CursorHasItem() ) then
+ AcceptCursorItem(this);
+ end
+ end
+end
+
+function OutfitDisplayItemButton_OnLoad()
+ local parentlen = string.len(this:GetParent():GetName())+1;
+ local slotName = strsub(this:GetName(), parentlen);
+ local id;
+ local textureName;
+ id, textureName = GetInventorySlotInfo(slotName);
+ this:SetID(id);
+ this.backgroundTextureName = textureName;
+ SetItemButtonTexture(this, this.backgroundTextureName);
+ this:RegisterForDrag("LeftButton");
+ this:RegisterForClicks("LeftButtonUp", "RightButtonUp");
+ this:RegisterEvent("CURSOR_UPDATE");
+end
+
+function OutfitDisplayItemButton_Draw(button)
+ if ( button.texture ) then
+ SetItemButtonTexture(button, button.texture);
+ else
+ SetItemButtonTexture(button, button.backgroundTextureName);
+ end
+ if ( button.missing ) then
+ SetItemButtonTextureVertexColor(button, 1.0, 0.1, 0.1);
+ elseif ( button.banked ) then
+ SetItemButtonTextureVertexColor(button, 0.1, 0.1, 1.0);
+ else
+ SetItemButtonTextureVertexColor(button, 1.0, 1.0, 1.0);
+ end
+ local checkbox = getglobal(button:GetName().."CheckBox");
+ if (checkbox) then
+ local pname = button:GetParent():GetName();
+ local showhelm = getglobal(pname.."ShowHelm");
+ local showcloak = getglobal(pname.."ShowCloak");
+ if ( button.forced ) then
+ checkbox:SetChecked(true);
+ checkbox:Disable();
+ checkbox:Show();
+ elseif ( button.empty or not button.used ) then
+ if ( checkbox.slotName == "HeadSlot" ) then
+ showhelm:Hide();
+ showhelm:SetChecked(false);
+ elseif ( checkbox.slotName == "BackSlot" ) then
+ showcloak:Hide();
+ showcloak:SetChecked(false);
+ end
+ checkbox:Enable();
+ checkbox:SetChecked(button.empty);
+ checkbox:Show();
+ elseif ( button.used ) then
+ checkbox:Hide();
+ if ( checkbox.slotName == "HeadSlot" ) then
+ showhelm:Show();
+ elseif ( checkbox.slotName == "BackSlot" ) then
+ showcloak:Show();
+ end
+ end
+ end
+end
+
+function OutfitDisplayItemButton_Change(button)
+ OutfitDisplayItemButton_Draw(button);
+ -- handle two handed weapons
+ local parent = button:GetParent();
+ local pname = parent:GetName();
+ local parentlen = string.len(pname)+1;
+ local slotName = strsub(button:GetName(), parentlen);
+ if ( slotName == "MainHandSlot" ) then
+ local secondary = getglobal(pname.."SecondaryHandSlot");
+ if ( not button.used and secondary.forced ) then
+ OutfitDisplayItemButton_Clear(secondary, false, false);
+ elseif ( button.used and not IsItemOneHanded(button.item) ) then
+ OutfitDisplayItemButton_Clear(secondary, true);
+ secondary.forced = true;
+ end
+ OutfitDisplayItemButton_Draw(secondary);
+ end
+ OutfitDisplayFrame_UpdateMessage(parent);
+ OutfitDisplayFrame_UpdateModel(parent, button);
+ if( parent.OutfitChanged ) then
+ parent.OutfitChanged( button );
+ end
+end
+
+function OutfitDisplayItemButton_Clear(button, empty, used)
+ button.name = nil;
+ button.item = nil;
+ button.texture = nil;
+ button.color = nil;
+ button.missing = nil;
+ button.banked = nil;
+ button.forced = nil;
+ button.empty = empty;
+ button.used = used or empty;
+end
+
+-- override ShowHelm and ShowCloak
+function OutfitDisplayOverrideBox_OnLoad()
+ local parentlen = string.len(this:GetParent():GetName())+1;
+ this.slotName = strsub(this:GetName(), parentlen);
+end
+
+function OutfitDisplayOverrideBox_OnEnter()
+ GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
+ local text;
+ if ( this.slotName == "ShowHelm" ) then
+ text = OUTFITDISPLAYFRAME_OVERRIDEHELM;
+ else
+ text = OUTFITDISPLAYFRAME_OVERRIDECLOAK;
+ end
+ GameTooltip:SetText(text, nil, nil, nil, nil, 1);
+ GameTooltip:Show();
+end
+
+-- check box handling
+function OutfitDisplayCheckBox_OnEnter()
+ GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
+ GameTooltip:SetText(OUTFITDISPLAYFRAME_USECHECKBOX, nil, nil, nil, nil, 1);
+ GameTooltip:Show();
+end
+
+function OutfitDisplayCheckBox_OnLoad()
+ local parentlen = string.len(this:GetParent():GetName())+1;
+ local name = strsub(this:GetName(), parentlen);
+ this.slotName = strsub(name, 1, -9);
+end
+
+function OutfitDisplayCheckBox_OnClick()
+ local pname = this:GetParent():GetName();
+ local button = getglobal(pname..this.slotName);
+ OutfitDisplayItemButton_Clear(button, this:GetChecked());
+ OutfitDisplayItemButton_Change(button);
+end
+
+local function UpdateModel_ThisSlot(pname, model, idx)
+ local slotName = PlayerSlotNames[idx].name;
+ local what = getglobal(pname..slotName);
+ local item = nil;
+ if ( what and what.used ) then
+ if ( not what.empty ) then
+ item = what.item;
+ end
+ else
+ local slot = PlayerSlotNames[idx].id;
+ local link = GetInventoryItemLink("player", slot);
+ if ( link ) then
+ _, item, _ = SplitLink(link);
+ end
+ end
+ if ( item ) then
+ DressUpItem(model, item);
+ end
+end
+
+function OutfitDisplayFrame_UpdateModel(frame, button)
+ local pname = frame:GetName();
+ local model = getglobal(pname.."Model");
+ local empty = false;
+ if ( not model ) then
+ return;
+ end
+ if ( button and button.used ) then
+ if ( button.empty and not button.forced ) then
+ empty = true;
+ end
+ else
+ for i=1,19,1 do
+ local what = getglobal(pname..PlayerSlotNames[i].name);
+ if ( what and what.empty ) then
+ empty = true;
+ end
+ end
+ end
+ if ( empty ) then
+ model:Undress();
+ end
+ for i=19,1,-1 do
+ UpdateModel_ThisSlot(pname, model, i);
+ end
+end
+
+function OutfitDisplayFrame_SetOutfit(frame, outfit)
+ if not outfit then
+ return;
+ end
+ local pname = frame:GetName();
+ for i=1,19,1 do
+ local slotName = PlayerSlotNames[i].name;
+ local button = getglobal(pname..slotName);
+ if ( button and outfit[slotName] and outfit[slotName].used ) then
+ OutfitDisplayItemButton_Clear(button);
+ if ( outfit[slotName].used ) then
+ button.name = outfit[slotName].name;
+ button.item = outfit[slotName].item;
+ button.texture = outfit[slotName].texture;
+ button.color = outfit[slotName].color;
+ button.missing = outfit[slotName].missing;
+ button.banked = outfit[slotName].banked;
+ button.forced = outfit[slotName].forced;
+ button.empty = outfit[slotName].empty;
+ button.used = true;
+ else
+ OutfitDisplayItemButton_Clear(button, true, true);
+ end
+ OutfitDisplayItemButton_Draw(button);
+ end
+ end
+ if ( outfit["Options"] ) then
+ local showhelm = getglobal(pname.."ShowHelm");
+ local showcloak = getglobal(pname.."ShowCloak");
+ showhelm:SetChecked(outfit["Options"].helm);
+ showcloak:SetChecked(outfit["Options"].cloak);
+ end
+ OutfitDisplayFrame_UpdateModel(frame);
+ OutfitDisplayFrame_UpdateMessage(frame, outfit);
+end
+
+function OutfitDisplayFrame_GetOutfit(frame, puthere)
+ local pname = frame:GetName();
+ local outfit = puthere or nil;
+ local showhelm = getglobal(pname.."ShowHelm");
+ local showcloak = getglobal(pname.."ShowCloak");
+ local setOptions = false;
+ if not outfit then
+ outfit = {};
+ end
+ outfit["Options"] = {};
+ for i=1,19,1 do
+ local slotName = PlayerSlotNames[i].name;
+ local button = getglobal(pname..slotName);
+
+ if ( button and button.used ) then
+ outfit[slotName] = {};
+ if ( not button.empty ) then
+ outfit[slotName].name = button.name;
+ outfit[slotName].item = button.item;
+ outfit[slotName].texture = button.texture;
+ outfit[slotName].color = button.color;
+ outfit[slotName].missing = button.missing;
+ outfit[slotName].banked = button.banked;
+ outfit[slotName].forced = button.forced;
+ end
+ outfit[slotName].empty = button.empty;
+ outfit[slotName].used = true;
+ if ( not button.empty ) then
+ if ( slotName == "HeadSlot" ) then
+ if ( showhelm ) then
+ if ( showhelm:GetChecked() ) then
+ outfit["Options"].helm = 1;
+ end
+ setOptions = true;
+ end
+ elseif ( slotName == "BackSlot" ) then
+ if ( showcloak ) then
+ if ( showcloak:GetChecked() ) then
+ outfit["Options"].cloak = 1;
+ end
+ setOptions = true;
+ end
+ end
+ end
+ elseif ( outfit and outfit.used ) then
+ outfit[slotName] = nil;
+ end
+ end
+ if ( not setOptions ) then
+ outfit["Options"] = nil;
+ end
+ if ( outfit ) then
+ -- check for two-handed weapon
+ local mainhand = outfit["MainHandSlot"];
+ if ( mainhand and not IsItemOneHanded(mainhand.item) ) then
+ outfit["SecondaryHandSlot"] = {};
+ outfit["SecondaryHandSlot"].forced = true;
+ outfit["SecondaryHandSlot"].empty = true;
+ outfit["SecondaryHandSlot"].used = true;
+ end
+ end
+ return outfit;
+end
+
+function OutfitDisplayFrame_GetItemInfo(bag, slot)
+ local link;
+ local c, i, n;
+ if ( bag ) then
+ link = GetContainerItemLink (bag,slot);
+ else
+ link = GetInventoryItemLink("player", slot);
+ end
+ if (link) then
+ c, i, n = SplitLink(link);
+ end
+ return c, i, n;
+end
+
+-- get a snapshot of the current state of the player
+function OutfitDisplayFrame_GetBagInfo()
+ local contents = {};
+ local empties = {};
+
+ local numSlots = 0;
+ -- check each of the bags on the player
+ for bag=0, NUM_BAG_FRAMES do
+ -- get the number of slots in the bag (0 if no bag)
+ numSlots = GetContainerNumSlots(bag);
+ if (numSlots > 0) then
+ -- check each slot in the bag
+ for slot=1, numSlots do
+ local c, i, n = OutfitDisplayFrame_GetItemInfo(bag, slot);
+ if ( i ) then
+ contents[i] = {};
+ contents[i].bag = bag;
+ contents[i].slot = slot;
+ contents[i].color = c;
+ contents[i].name = n;
+ else
+ local what = {};
+ what.bag = bag;
+ what.slot = slot;
+ tinsert(empties, what);
+ end
+ end
+ end
+ end
+
+ for idx=1,19,1 do
+ local slot = PlayerSlotNames[idx].id;
+ local c, i, n = OutfitDisplayFrame_GetItemInfo(nil, slot);
+ if ( i ) then
+ contents[i] = {};
+ contents[i].slot = slot;
+ contents[i].color = c;
+ contents[i].name = n;
+ end
+ end
+
+ return contents, empties;
+end
+
+-- look in a particular bag
+local function CheckThisBag(bag, id, skipcount)
+ -- get the number of slots in the bag (0 if no bag)
+ local numSlots = GetContainerNumSlots(bag);
+ if (numSlots > 0) then
+ -- check each slot in the bag
+ for slot=1, numSlots do
+ local c, i, n = OutfitDisplayFrame_GetItemInfo(bag, slot);
+ if ( i and id == i ) then
+ if ( skipcount == 0 ) then
+ return slot, skipcount;
+ end
+ skipcount = skipcount - 1;
+ end
+ end
+ end
+ return nil, skipcount;
+end
+
+-- look for the outfit anywhere we can find it
+local function FindThisItem(id, skipcount)
+ if ( not id ) then
+ return nil,nil,nil;
+ end
+ local skipcount = skipcount or 0;
+ -- check each of the bags on the player
+ for bag=0, NUM_BAG_FRAMES do
+ local slot;
+ slot, skipcount = CheckThisBag(bag, id, skipcount);
+ if ( slot ) then
+ return bag, slot, false;
+ end
+ end
+
+ for idx=1,19,1 do
+ local slot = PlayerSlotNames[idx].id;
+ local c, i, n = OutfitDisplayFrame_GetItemInfo(nil, slot);
+ if ( (id and i and id == i) or (name and n and name == n) ) then
+ if ( skipcount == 0 ) then
+ return nil, slot, false;
+ end
+ skipcount = skipcount - 1;
+ end
+ end
+
+ -- look in the bank
+ -- Geez, this is ugly
+ local bankbags = { BANK_CONTAINER, 5, 6, 7, 8, 9, 10 };
+ for b=1,7 do
+ local slot;
+ slot, skipcount = CheckThisBag(bankbags[b], id, skipcount);
+ if ( slot ) then
+ return bankbags[b], slot, true;
+ end
+ end
+ -- return nil, nil, nil;
+end
+
+-- look for the outfit anywhere we can find it
+-- we should look in the bank someday
+function OutfitDisplayFrame_FindOutfit(outfit)
+ -- look for every item, if we find everything return a table of locations
+ -- otherwise don't return anything
+ if ( not outfit ) then
+ return nil;
+ end
+ local spots = { };
+ for slotName in pairs(outfit) do
+ if ( outfit[slotName].use and not outfit[slotName].empty ) then
+ local bag, slot = FindThisItem( outfit[slotName].item );
+ if ( not bag and not slot ) then
+ spots = nil;
+ return nil;
+ else
+ spots[slotName] = { };
+ spots[slotName].bag = bag;
+ spots[slotName].slot = slot;
+ end
+ end
+ end
+ return spots;
+end
+
+function OutfitDisplayFrame_CanFindOutfit(outfit)
+ if ( not outfit ) then
+ return false;
+ end
+ for slotName in pairs(outfit) do
+ if ( outfit[slotName].used and not outfit[slotName].empty ) then
+ local bag, slot = FindThisItem( outfit[slotName].item );
+ if ( not bag and not slot ) then
+ return false;
+ end
+ end
+ end
+ return true;
+end
+
+local function CheckSwitchWillFail(frame, outfit)
+ local contents, empties = OutfitDisplayFrame_GetBagInfo();
+ local numfree = table.getn(empties);
+ local needfree = 0;
+ local missing = false;
+ local banked = false;
+ for i=1,19,1 do
+ local slotName = PlayerSlotNames[i].name;
+ local check;
+ if ( outfit ) then
+ check = outfit[slotName];
+ else
+ check = getglobal(frame:GetName()..slotName);
+ end
+ if ( check and check.used ) then
+ if ( not check.empty ) then
+ local bag, slot, inbank = FindThisItem( check.item );
+ if ( not bag and not slot ) then
+ -- pretend it's still in the bank and we just can't get it
+ if ( check.banked ) then
+ check.banked = true;
+ banked = true;
+ else
+ missing = true;
+ end
+ check.missing = not check.banked;
+ else
+ check.missing = nil;
+ check.banked = inbank;
+ end
+ else
+ local slot = PlayerSlotNames[i].id;
+ if ( OutfitDisplayFrame_GetItemInfo(nil, slot) ) then
+ needfree = needfree + 1;
+ end
+ end
+ end
+ end
+ if ( missing ) then
+ return OUTFITDISPLAYFRAME_ITEMSNOTFOUND;
+ end
+ if ( banked and not BankIsOpen ) then
+ return OUTFITDISPLAYFRAME_ITEMSINBANK;
+ end
+ if ( needfree > numfree ) then
+ return OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE;
+ end
+ return nil;
+end
+
+function OutfitDisplayFrame_SwitchWillFail(frame, outfit)
+ if ( not outfit ) then
+ return OUTFITDISPLAYFRAME_INVALIDOUTFIT;
+ end
+ if ( not next(outfit) ) then
+ return OUTFITDISPLAYFRAME_EMPTYOUTFIT;
+ end
+ -- if we're swapping, fail early
+ if ( OutfitDisplayFrame_IsSwapping() ) then
+ return OUTFITDISPLAYFRAME_TOOFASTMSG;
+ end
+ return CheckSwitchWillFail(frame, outfit);
+end
+
+function OutfitDisplayFrame_IsWearing(outfit)
+ if ( not outfit ) then
+ return false;
+ end
+ for slotName in pairs(outfit) do
+ if ( outfit[slotName].used and not outfit[slotName].empty ) then
+ local slot = GetInventorySlotInfo(slotName);
+ local link = GetInventoryItemLink("player", slot);
+ local foundit = false;
+ if ( link ) then
+ local color, item, name = SplitLink(link);
+ if ( item == outfit[slotName].item ) then
+ foundit = true;
+ end
+ end
+ if ( not foundit ) then
+ return false;
+ end
+ end
+ end
+ return true;
+end
+
+function OutfitDisplayFrame_UpdateMessage(frame, outfit)
+ if ( frame ) then
+ local msg;
+ if ( outfit ) then
+ msg = CheckSwitchWillFail(frame, outfit);
+ end
+ local messages = getglobal(frame:GetName().."Message");
+ if ( msg ) then
+ messages:SetText(msg);
+ messages:SetTextColor(1, 1, 1);
+ messages:Show();
+ else
+ messages:SetText("");
+ messages:Hide();
+ end
+ end
+end
+
+function OutfitDisplayFrame_GetSlotContents(slotName, returnEmpty)
+ if ( slotName ~= "Options" ) then
+ local slot = GetInventorySlotInfo(slotName);
+ local link = GetInventoryItemLink("player", slot);
+ if ( link ) then
+ local contents = {};
+ local color, item, name = SplitLink(link);
+ contents.item = item;
+ contents.name = name;
+ contents.color = color;
+ contents.texture = texture;
+ contents.used = true;
+ local bag, slot = FindThisItem( item );
+ contents.bag = bag;
+ contents.slot = slot;
+ return contents;
+ end
+ end
+ -- return nil;
+end
+
+function OutfitDisplayFrame_GetWearing(check)
+ local wearing = {};
+ if ( check ) then
+ for slotName in pairs(check) do
+ wearing[slotName] = OutfitDisplayFrame_GetSlotContents(slotName);
+ end
+ -- make sure we pick up the off hand if we're going to put something
+ -- two-handed in the main hand slot
+ local mainhand = check["MainHandSlot"];
+ local offhand = wearing["SecondaryHandSlot"];
+ if ( not offhand and mainhand and not IsItemOneHanded(mainhand.item) ) then
+ wearing["SecondaryHandSlot"] = OutfitDisplayFrame_GetSlotContents("SecondaryHandSlot");
+ end
+ else
+ for i=1,19,1 do
+ local slotName = PlayerSlotNames[i].name;
+ wearing[slotName] = OutfitDisplayFrame_GetSlotContents(slotName);
+ end
+ end
+ wearing["Options"] = {}
+ if ( ShowingCloak() ) then
+ wearing["Options"].cloak = 1;
+ else
+ wearing["Options"].cloak = 0;
+ end
+ if ( ShowingHelm() ) then
+ wearing["Options"].helm = 1;
+ else
+ wearing["Options"].helm = 0;
+ end
+ return wearing;
+end
+
+function OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount, bag_affinity, slot_affinity)
+ skipcount = skipcount or 0;
+
+ -- try to put the item in the requested affinity, if possible
+ if bag_affinity and slot_affinity and
+ not GetContainerItemInfo(bag_affinity, slot_affinity) then
+ return bag_affinity, slot_affinity;
+ end
+
+ -- if we couldn't get the bag and slot we wanted, just try the same bag
+ if bag_affinity then
+ for j=GetContainerNumSlots(bag_affinity),1,-1 do
+ if not GetContainerItemInfo(bag_affinity,j) then
+ if skipcount == 0 then return bag_affinity,j; end
+ skipcount = skipcount - 1;
+ end
+ end
+ end
+
+ -- no affinity, check all bags
+ for i=NUM_BAG_FRAMES,0,-1 do
+ -- but skip any bag we already have affinity for (because it might have
+ -- already modified skipcount)
+ if bag_affinity ~= i then
+ -- Make sure this isn't a quiver, those won't hold shit
+ local bagName = GetBagName(i);
+ if ( bagName ) then
+ local texture = GetInventoryItemTexture("player",
+ ContainerIDToInventoryID(i));
+
+ if ( string.find(texture, "INV_Misc_Bag_%d") and not string.find(bagName, AMMOSLOT) ) then
+ for j=GetContainerNumSlots(i),1,-1 do
+ if not GetContainerItemInfo(i,j) then
+ if skipcount == 0 then return i,j; end
+ skipcount = skipcount - 1;
+ end -- if empty
+ end -- for slots
+ end -- if normal bag
+ end -- if there is a bag
+ end -- if not affinity bag
+ end -- for bags
+
+ -- not found return nil,nil implicitly
+end
+
+-- okay, let's switch to the specified outfit
+-- code liberally borrowed from "WeaponQuickSwap - by CapnBry"
+
+-- list functions
+local function swapentry_print(entry)
+ if ( DEFAULT_CHAT_FRAME ) then
+ local msg = "Entry "..tonil(entry.sb)..","..tonil(entry.si)..","..tonil(entry.db)..","..tonil(entry.di);
+ DEFAULT_CHAT_FRAME:AddMessage(msg, 1.0,0,0);
+ end
+end
+
+local function swaplist_print(list)
+ while ( list ) do
+ swapentry_print(list);
+ list = list.next;
+ end
+end
+
+local function swaplist_push(list, sb, si, db, di, helm, cloak)
+ list = { next = list, sb = sb, si = si, db = db, di = di,
+ helm = helm, cloak = cloak };
+ return list;
+end
+
+local function swaplist_popfirst(list)
+ if not list then return; end
+ list = list.next;
+ return list;
+end
+
+-- Unit variable to hold the stack of swaps
+local outfitswap = nil;
+
+function OutfitDisplayFrame_IsSwapping()
+ if ( outfitswap or OutfitDisplayFrame_AnyItemLocked() ) then
+ return true;
+ else
+ return false;
+ end
+end
+
+-- First we do everything except the main hand and secondary hand
+-- Then we do the hard stuff
+
+function OutfitDisplayFrame_ItemIsLocked(bag, slot)
+ if not bag and not slot then
+ return false;
+ end
+
+ if not bag then
+ return IsInventoryItemLocked(slot);
+ else
+ local _,_,locked = GetContainerItemInfo(bag,slot);
+ return locked;
+ end
+end
+
+function OutfitDisplayFrame_AnyItemLocked()
+-- Checks all the bags and the equipped slots to see if any are still locked
+ for i=0,NUM_BAG_FRAMES do
+ for j=1,GetContainerNumSlots(i) do
+ local _,_,locked = GetContainerItemInfo(i,j);
+ if ( locked ) then
+ return true;
+ end
+ end
+ end
+ for i=1,19,1 do
+ if ( IsInventoryItemLocked(PlayerSlotNames[i].id) ) then
+ return true;
+ end
+ end
+ return false;
+end
+
+local function ShowCheck(dohelm, flag)
+ if ( flag ) then
+ if ( dohelm ) then
+ ShowHelm(flag);
+ else
+ ShowCloak(flag);
+ end
+ end
+end
+
+function OutfitDisplayFrame_ExecuteSwapIteration()
+ if not outfitswap then
+ PerformSlowerSwap = false;
+ return;
+ end
+
+ if OutfitDisplayFrame_ItemIsLocked(outfitswap.sb, outfitswap.si) or
+ OutfitDisplayFrame_ItemIsLocked(outfitswap.db, outfitswap.di) then
+ return;
+ end
+
+ local beslow = PerformSlowerSwap;
+
+ if ( outfitswap.helm ~= nil or outfitswap.cloak ~= nil ) then
+
+ ShowCheck ( true, outfitswap.helm);
+ ShowCheck ( false, outfitswap.cloak);
+
+ beslow = false;
+
+ else
+
+ if not outfitswap.sb then
+ SavedPickupInventoryItem(outfitswap.si);
+ else
+ SavedPickupContainerItem(outfitswap.sb, outfitswap.si);
+ end
+
+ if not outfitswap.db then
+ if not outfitswap.di then
+ PutItemInBackpack();
+ else
+ SavedPickupInventoryItem(outfitswap.di);
+ end
+ else
+ SavedPickupContainerItem(outfitswap.db, outfitswap.di);
+ end
+
+ end
+
+ outfitswap = swaplist_popfirst(outfitswap);
+ if ( outfitswap and not beslow ) then
+ return OutfitDisplayFrame_ExecuteSwapIteration();
+ end
+end
+
+function OutfitDisplayFrame_SwitchOne(outfit, index, skipcount)
+ local slotName = PlayerSlotNames[index].name;
+ if ( outfit and outfit[slotName] ) then
+ local invslot = GetInventorySlotInfo(slotName);
+ if ( outfit[slotName].empty ) then
+ local bag, slot = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount);
+ outfitswap = swaplist_push(outfitswap, nil, invslot, bag, slot);
+ skipcount = skipcount + 1;
+ else
+ local bag, slot = FindThisItem( outfit[slotName].item );
+ -- either we couldn't find it, or it's where it should be
+ if ( bag ~= nil or slot ~= invslot ) then
+ outfitswap = swaplist_push(outfitswap, bag, slot, nil, invslot);
+ end
+ end
+ end
+ return skipcount;
+end
+
+local function OnSwapError(error)
+ outfitswap = nil;
+ if ( UIErrorsFrame ) then
+ UIErrorsFrame:AddMessage(error, 1.0, 0.1, 0.1, 1.0, UIERRORS_HOLD_TIME);
+ end
+ return;
+end
+
+function OutfitDisplayFrame_SwitchOutfit(outfit)
+ if ( CursorHasItem() or OutfitDisplayFrame_IsSwapping() ) then
+ return OnSwapError(OUTFITDISPLAYFRAME_TOOFASTMSG);
+ end
+ if ( not outfit ) then
+ return OnSwapError(OUTFITDISPLAYFRAME_INVALIDOUTFIT);
+ end
+
+ -- might not need to swap slowly
+ PerformSlowerSwap = false;
+
+ -- need to check to see that we have enough room
+ local old = OutfitDisplayFrame_GetWearing(outfit);
+
+ if ( outfit["Options"] ) then
+ -- do cloak and helm setting last
+ outfitswap = swaplist_push(outfitswap, nil, nil, nil, nil,
+ outfit["Options"].helm,
+ outfit["Options"].cloak);
+ end
+
+ -- do everything except weapon slots
+ local skipcount = 0;
+ for i=1,16,1 do
+ skipcount = OutfitDisplayFrame_SwitchOne(outfit, i, skipcount);
+ end
+ OutfitDisplayFrame_SwitchOne(outfit, 19, skipcount);
+
+ if ( not outfit["MainHandSlot"] and not outfit["SecondaryHandSlot"] ) then
+ OutfitDisplayFrame_ExecuteSwapIteration();
+ return old;
+ end
+
+ local mainhandslot = GetInventorySlotInfo("MainHandSlot");
+ local secondaryslot = GetInventorySlotInfo("SecondaryHandSlot");
+ local mainhand = outfit["MainHandSlot"];
+ local offhand = outfit["SecondaryHandSlot"];
+ -- now do hands
+ local m_sb;
+ local m_si;
+ local o_sb;
+ local o_si;
+ local m_ok = not mainhand or not mainhand.item;
+ local o_ok = not offhand or not offhand.item;
+
+ if ( mainhand and mainhand.item ) then
+ m_sb, m_si = FindThisItem(mainhand.item);
+ m_ok = ( not m_sb and m_si == mainhandslot );
+ end
+ if ( offhand and offhand.item ) then
+ local multiples = 0;
+ if ( mainhand and mainhand.item == offhand.item ) then
+ multiples = 1;
+ end
+ o_sb, o_si = FindThisItem( offhand.item, multiples);
+ o_ok = ( not o_sb and o_si == secondaryslot );
+ end
+
+ if ( not m_ok ) then
+ -- do we need two of these?
+ if ( o_ok and not m_sb and m_si == secondaryslot ) then
+ m_sb, m_si = FindThisItem( mainhand.item, 1);
+ end
+ end
+
+ -- moving from bags
+ if ( m_sb and o_sb ) then
+ -- insert them backwards, since they get popped off
+ -- main hand has to get done first in case it's currently
+ -- a two hander
+ outfitswap = swaplist_push(outfitswap, o_sb, o_si, nil, secondaryslot);
+ outfitswap = swaplist_push(outfitswap, m_sb, m_si, nil, mainhandslot);
+ elseif ( not m_sb and m_si == secondaryslot and not o_sb and o_si == mainhandslot ) then
+ outfitswap = swaplist_push(outfitswap, nil, mainhandslot, nil, secondaryslot);
+ else
+ -- Install main hand
+ if not m_ok then
+ -- if nothing going to the main hand
+ if ( not m_sb and not m_si ) then
+ -- and the main is not going to the off: put it in a bag
+ if not ( not o_sb and o_si == mainhandslot) then
+ local bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount);
+ if not (bb and bi) then
+ return OnSwapError(OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE);
+ end
+ skipcount = skipcount + 1;
+ outfitswap = swaplist_push(outfitswap, nil, mainhandslot, bb, bi);
+ -- when moving A,"" -> "",B where A is a 2h, the offhand
+ -- doesn't lock properly, so work around it by swapping
+ -- slowly (only one swap per lock notify)
+ PerformSlowerSwap = not IsItemOneHanded(mainhand.item);
+ end
+ else
+ outfitswap = swaplist_push(outfitswap, m_sb, m_si, nil, mainhandslot);
+ end
+ end
+
+ -- Load offhand if not already there
+ if not o_ok then
+ if ( not o_sb and not o_si ) then
+ if not (not m_sb and m_si == secondaryslot) then
+ local bb, bi;
+ if LastOffSource then
+ bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount,
+ LastOffSource.bag, LastOffSource.slot);
+ else
+ bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount);
+ end
+
+ if not (bb and bi) then
+ return OnSwapError(OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE);
+ end
+ skipcount = skipcount + 1;
+ outfitswap = swaplist_push(outfitswap, nil, secondaryslot, bb, bi);
+ end
+ else
+ -- if the main hand weapon is coming from the offhand slot
+ -- we need to fix up its source to be where the offhand is
+ -- GOING to be after the bag->off swap
+ if outfitswap and ( not m_sb and m_si == secondaryslot) then
+ outfitswap.sb = o_sb;
+ outfitswap.si = o_si;
+ -- don't set o_sb, o_si they're tested later
+ end
+
+ outfitswap = swaplist_push(outfitswap, o_sb, o_si, nil, secondaryslot);
+ end
+ end
+
+-- Special Case: Moving off to main, and not main to off
+-- This is because maybe the main hand weapon is main only
+ if (not m_sb and m_si == secondaryslot) and not ( not o_sb and o_si == mainhandslot) then
+ local bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount);
+ if not (bb and bi) then
+ return OnSwapError(OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE);
+ end
+ skipcount = skipcount + 1;
+ outfitswap = swaplist_push(outfitswap, nil, mainhandslot, bb, bi);
+ end
+
+ -- Same thing for off hand
+ if (not o_sb and o_si == mainhandslot) and not (not m_sb and m_si == secondaryslot) then
+ local bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount);
+ if not (bb and bi) then
+ return OnSwapError(OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE);
+ end
+ skipcount = skipcount + 1;
+ outfitswap = swaplist_push(outfitswap, nil, mainhandslot, bb, bi);
+ end
+
+ if o_sb then
+ LastOffSource = { bag = o_sb, slot = o_si };
+ end
+ end
+
+ -- Start moving
+ OutfitDisplayFrame_ExecuteSwapIteration();
+ return old;
+end
diff --git a/OutfitDisplayFrame/OutfitDisplayFrame.toc b/OutfitDisplayFrame/OutfitDisplayFrame.toc
new file mode 100644
index 0000000..1b7f438
--- /dev/null
+++ b/OutfitDisplayFrame/OutfitDisplayFrame.toc
@@ -0,0 +1,8 @@
+## Interface: 11200
+## Title: OutfitDisplayFrame
+## Version: 0.5.9
+## Notes: A utility frame to display a set of equipable items.
+## Notes-deDE: Ein Fenster, dass die Ausr\195\188stung anzeigt
+## Notes-frFR: Un cadre d'utilit\195\169 pour afficher une s\195\169rie d'articles de equipable
+## Author: Sutorix=AT=hotmail.com
+OutfitDisplayFrame.xml
diff --git a/OutfitDisplayFrame/OutfitDisplayFrame.xml b/OutfitDisplayFrame/OutfitDisplayFrame.xml
new file mode 100644
index 0000000..a07bfe1
--- /dev/null
+++ b/OutfitDisplayFrame/OutfitDisplayFrame.xml
@@ -0,0 +1,541 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ OutfitDisplayCheckBox_OnLoad();
+
+
+ OutfitDisplayCheckBox_OnClick();
+
+
+ OutfitDisplayCheckBox_OnEnter();
+
+
+ GameTooltip.finished = nil;
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+ OutfitDisplayOverrideBox_OnLoad();
+
+
+ OutfitDisplayOverrideBox_OnEnter();
+
+
+ GameTooltip.finished = nil;
+ GameTooltip:Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Model_OnLoad();
+ this:RegisterEvent("DISPLAY_SIZE_CHANGED");
+ this:RegisterEvent("UNIT_MODEL_CHANGED");
+ this:RegisterEvent("PLAYER_ENTERING_WORLD");
+
+
+ if ( event == "PLAYER_ENTERING_WORLD" ) then
+ this:SetUnit("player");
+ return;
+ end
+ if ( this:IsVisible() ) then
+ OutfitDisplayFrame_UpdateModel(this);
+ end
+
+
+ OutfitDisplayFrame_UpdateModel(this);
+
+
+ Model_OnUpdate(arg1, this);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this:SetFrameLevel(this:GetFrameLevel()+1);
+
+
+
+
+
+
+ OutfitDisplayFrame_MessageUpdate(arg1);
+
+
+
+
+
+
+ OutfitDisplayFrame_OnLoad();
+
+
+ OutfitDisplayFrame_OnEvent(event, arg1);
+
+
+ return;
+
+
+
+
+
diff --git a/OutfitDisplayFrame/changes.txt b/OutfitDisplayFrame/changes.txt
new file mode 100644
index 0000000..f96fa69
--- /dev/null
+++ b/OutfitDisplayFrame/changes.txt
@@ -0,0 +1,55 @@
+Version 0.5.9
+- Add a way for clients to add their own tooltip information
+- Update 'for' loops to be compatible with Lua 5.1
+
+Version 0.5.8
+- Update toc for patch 1.12
+
+Version 0.5.7
+- Optimize event handling (lots if ITEM_LOCK_CHANGED events during
+ world transitions)
+- Empty outfits have a message
+
+Version 0.5.6
+- Fix nil error when you have fewer than five bags
+
+Version 0.5.5
+- Fix "no space" error when swapping empty space for empty space
+
+Version 0.5.4
+- Attempt to fix soul bag issues (as well as ammo pouches and quivers)
+
+Version 0.5.3
+- Better French translation, thanks to Corwin Whitehorn
+
+Version 0.5.2
+- Add the information about alt-clicking to clear the outfit item
+ to all tooltips
+
+Version 0.5.1
+- Fix a bug where dual-wield of the same item would fail to switch
+ correctly
+
+Version 0.5
+- Add an option to override the values of "Show Helm" and "Show Cloak"
+ when switching outfits
+- Make forced entries disabled
+
+Version 0.4
+- Add outfit preview using the new 'dressing room' stuff
+- Fix two hand weapon to only off hand bug (missed from WeaponQuickSwap)
+- Count locked items as still swapping outfits
+- Use GetItemInfo to find Two-hand items, instead of parsing tooltips.
+ This should mean that OutfitDisplayFrame will now switch for all
+ languages, even those without explicit translations.
+
+Version 0.3.1
+- Fix a typo in the item clearing code
+
+Version 0.3
+- Handle outfits with banked items
+- Code cleanup
+
+Version 0.2
+- Allow 'empty' items in outfits
+- More robust switching code
diff --git a/OutfitDisplayFrame/localization.lua b/OutfitDisplayFrame/localization.lua
new file mode 100644
index 0000000..d773b8d
--- /dev/null
+++ b/OutfitDisplayFrame/localization.lua
@@ -0,0 +1,40 @@
+-- Magic strings
+
+-- English
+OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE = "Not enough free space in bags.";
+OUTFITDISPLAYFRAME_ITEMSNOTFOUND = "Outfit contains missing items.";
+OUTFITDISPLAYFRAME_INVALIDOUTFIT = "Invalid outfit format.";
+OUTFITDISPLAYFRAME_EMPTYOUTFIT = "Empty outfit.";
+OUTFITDISPLAYFRAME_ITEMSINBANK = "Outfit contains banked items.";
+OUTFITDISPLAYFRAME_TOOFASTMSG = "Can't switch outfits that quickly.";
+OUTFITDISPLAYFRAME_ALTCLICK = "Alt-click will reset to an empty slot.";
+
+OUTFITDISPLAYFRAME_USECHECKBOX = "When checked, this slot is forced empty on switch.";
+OUTFITDISPLAYFRAME_OVERRIDEHELM = "When checked, override the value of \"Show Helm\" when this outfit is worn.";
+OUTFITDISPLAYFRAME_OVERRIDECLOAK = "When checked, override the value of \"Show Cloak\" when this outfit is worn.";
+
+-- German
+if ( GetLocale() == "deDE" ) then
+ OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE = "Nicht genug Platz in den Taschen";
+ OUTFITDISPLAYFRAME_ITEMSNOTFOUND = "Ausr\195\188stung enth\195\164lt fehlende Gegenst\195\164nde";
+ OUTFITDISPLAYFRAME_INVALIDOUTFIT = "Ung\195\188ltiges Ausr\195\188stungsformat";
+ OUTFITDISPLAYFRAME_ITEMSINBANK = "Ausstattung enth\195\164lt Gegenst\195\164nde, die auf der Bank sind.";
+ OUTFITDISPLAYFRAME_TOOFASTMSG = "Sie k\195\182nnen nicht Ausstattungen schalten, die schnell.";
+
+ OUTFITDISPLAYFRAME_USECHECKBOX = "Wenn H\195\164ckchen gesetzt, wird der Taschenplatz wird bim Ausr\195\188stungswechsel geleert.";
+end
+
+if ( GetLocale() == "frFR" ) then
+ -- OUTFITDISPLAYFRAME_TWOHANDED = "Deux-mains";
+ OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE = "Pas assez d'espace libre dans les sacs";
+ OUTFITDISPLAYFRAME_ITEMSNOTFOUND = "Articles manquants pour l'\195\169quipement choisi.";
+ OUTFITDISPLAYFRAME_INVALIDOUTFIT = "Format d'\195\169quipement incorrect.";
+ OUTFITDISPLAYFRAME_ITEMSINBANK = "L'\195\169quipement contient les articles en banque.";
+ OUTFITDISPLAYFRAME_TOOFASTMSG = "On ne peut pas commuter les \195\169quipements aussi rapidement.";
+
+ OUTFITDISPLAYFRAME_ALTCLICK = "Alt-click annulera l'equipement";
+
+ OUTFITDISPLAYFRAME_USECHECKBOX = "Si coch\195\169, ce slot est vid\195\169 lors de la commutation.";
+ OUTFITDISPLAYFRAME_OVERRIDEHELM = "Si coch\195\169, force le \"Afficher le casque\" quand cette tenue est port\195\169e.";
+ OUTFITDISPLAYFRAME_OVERRIDECLOAK = "Si coch\195\169, force le \"Afficher la cape\" quand cette tenue est port\195\169e.";
+end
diff --git a/OutfitDisplayFrame/readme.txt b/OutfitDisplayFrame/readme.txt
new file mode 100644
index 0000000..44e2610
--- /dev/null
+++ b/OutfitDisplayFrame/readme.txt
@@ -0,0 +1,14 @@
+OutfitDisplayFrame
+------------------
+
+This is a utility frame for handling 'outfits' -- collections of wearable
+items that you can swap with what you are currently wearing.
+
+It's in its early stages, so don't expect perfection -- but it does a pretty
+good job of hanlding the basics. Plus, it handles having part of your outfits
+in the bank!
+
+This would not have been possible without the incredible example of
+WeaponQuickSwap by CapnBry.
+
+Feel free to send comments to Sutorix on the Windrunner server.
\ No newline at end of file