From cc5b1721cc57a884fd8512750eccda828144189b Mon Sep 17 00:00:00 2001 From: Beats Date: Mon, 3 Apr 2023 23:55:28 -0400 Subject: [PATCH 01/45] Show indicators for pickupable and moveable items --- icons/house_exit.png | Bin 0 -> 253 bytes icons/house_exit.xpm | 41 ++++++++ icons/mini_borderize.png | Bin 0 -> 1523 bytes icons/mini_borderize.xpm | 21 +++++ icons/mini_change.png | Bin 0 -> 602 bytes icons/mini_change.xpm | 116 +++++++++++++++++++++++ icons/mini_copy.png | Bin 0 -> 2066 bytes icons/mini_copy.xpm | 126 +++++++++++++++++++++++++ icons/mini_cut.png | Bin 0 -> 648 bytes icons/mini_cut.xpm | 93 ++++++++++++++++++ icons/mini_delete.png | Bin 0 -> 678 bytes icons/mini_delete.xpm | 151 +++++++++++++++++++++++++++++ icons/mini_draw.png | Bin 0 -> 548 bytes icons/mini_draw.xpm | 78 +++++++++++++++ icons/mini_erase.png | Bin 0 -> 680 bytes icons/mini_erase.xpm | 81 ++++++++++++++++ icons/mini_fill.png | Bin 0 -> 707 bytes icons/mini_fill.xpm | 122 ++++++++++++++++++++++++ icons/mini_move.png | Bin 0 -> 2381 bytes icons/mini_move.xpm | 70 ++++++++++++++ icons/mini_paste.png | Bin 0 -> 531 bytes icons/mini_paste.xpm | 93 ++++++++++++++++++ icons/mini_randomize.png | Bin 0 -> 1620 bytes icons/mini_randomize.xpm | 26 +++++ icons/mini_remote.png | Bin 0 -> 5972 bytes icons/mini_remote.xpm | 117 +++++++++++++++++++++++ icons/mini_replace.png | Bin 0 -> 719 bytes icons/mini_replace.xpm | 137 +++++++++++++++++++++++++++ icons/mini_rotate.png | Bin 0 -> 602 bytes icons/mini_rotate.xpm | 116 +++++++++++++++++++++++ icons/mini_select.png | Bin 0 -> 2140 bytes icons/mini_select.xpm | 33 +++++++ icons/mini_switch.png | Bin 0 -> 877 bytes icons/mini_switch.xpm | 124 ++++++++++++++++++++++++ icons/mini_unselect.png | Bin 0 -> 2142 bytes icons/mini_unselect.xpm | 33 +++++++ icons/moveable.png | Bin 0 -> 377 bytes icons/moveable.xpm | 43 +++++++++ icons/pickupable.png | Bin 0 -> 474 bytes icons/pickupable.xpm | 44 +++++++++ icons/pickupable_moveable.png | Bin 0 -> 561 bytes icons/pickupable_moveable.xpm | 44 +++++++++ icons/spawns.png | Bin 0 -> 778 bytes icons/spawns.xpm | 92 ++++++++++++++++++ icons/toolbar_hooks.png | Bin 0 -> 197 bytes icons/toolbar_hooks.xpm | 25 +++++ icons/toolbar_moveables.png | Bin 0 -> 213 bytes icons/toolbar_moveables.xpm | 25 +++++ icons/toolbar_pickupables.png | Bin 0 -> 240 bytes icons/toolbar_pickupables.xpm | 31 ++++++ remeres.exe.manifest | 15 +++ source/application.cpp | 5 + source/application.h | 1 + source/artprovider.cpp | 26 +++++ source/artprovider.h | 10 ++ source/graphics.cpp | 114 ++++++++++++++++++++-- source/graphics.h | 23 ++++- source/gui.cpp | 2 + source/gui_ids.h | 8 +- source/main_menubar.cpp | 39 +++++++- source/main_menubar.h | 4 + source/main_toolbar.cpp | 63 +++++++++++++ source/main_toolbar.h | 4 + source/map_display.cpp | 2 + source/map_drawer.cpp | 172 +++++++++++++++++++++++++--------- source/map_drawer.h | 6 +- source/settings.cpp | 3 + source/settings.h | 4 + source/sprites.h | 7 ++ 69 files changed, 2330 insertions(+), 60 deletions(-) create mode 100644 icons/house_exit.png create mode 100644 icons/house_exit.xpm create mode 100644 icons/mini_borderize.png create mode 100644 icons/mini_borderize.xpm create mode 100644 icons/mini_change.png create mode 100644 icons/mini_change.xpm create mode 100644 icons/mini_copy.png create mode 100644 icons/mini_copy.xpm create mode 100644 icons/mini_cut.png create mode 100644 icons/mini_cut.xpm create mode 100644 icons/mini_delete.png create mode 100644 icons/mini_delete.xpm create mode 100644 icons/mini_draw.png create mode 100644 icons/mini_draw.xpm create mode 100644 icons/mini_erase.png create mode 100644 icons/mini_erase.xpm create mode 100644 icons/mini_fill.png create mode 100644 icons/mini_fill.xpm create mode 100644 icons/mini_move.png create mode 100644 icons/mini_move.xpm create mode 100644 icons/mini_paste.png create mode 100644 icons/mini_paste.xpm create mode 100644 icons/mini_randomize.png create mode 100644 icons/mini_randomize.xpm create mode 100644 icons/mini_remote.png create mode 100644 icons/mini_remote.xpm create mode 100644 icons/mini_replace.png create mode 100644 icons/mini_replace.xpm create mode 100644 icons/mini_rotate.png create mode 100644 icons/mini_rotate.xpm create mode 100644 icons/mini_select.png create mode 100644 icons/mini_select.xpm create mode 100644 icons/mini_switch.png create mode 100644 icons/mini_switch.xpm create mode 100644 icons/mini_unselect.png create mode 100644 icons/mini_unselect.xpm create mode 100644 icons/moveable.png create mode 100644 icons/moveable.xpm create mode 100644 icons/pickupable.png create mode 100644 icons/pickupable.xpm create mode 100644 icons/pickupable_moveable.png create mode 100644 icons/pickupable_moveable.xpm create mode 100644 icons/spawns.png create mode 100644 icons/spawns.xpm create mode 100644 icons/toolbar_hooks.png create mode 100644 icons/toolbar_hooks.xpm create mode 100644 icons/toolbar_moveables.png create mode 100644 icons/toolbar_moveables.xpm create mode 100644 icons/toolbar_pickupables.png create mode 100644 icons/toolbar_pickupables.xpm create mode 100644 remeres.exe.manifest diff --git a/icons/house_exit.png b/icons/house_exit.png new file mode 100644 index 0000000000000000000000000000000000000000..134d6c9f10c4c75d1956519d5c2ce05af815cf18 GIT binary patch literal 253 zcmV{U^IkF5n3SJxc^yYD@s6B zDJVIh^N~nh177Jc6`==&xeKfiE^TOmaGL`v2mm+$vIkclWXSvF00000NkvXXu0mjf DwU}fx literal 0 HcmV?d00001 diff --git a/icons/house_exit.xpm b/icons/house_exit.xpm new file mode 100644 index 00000000..0ba5fccd --- /dev/null +++ b/icons/house_exit.xpm @@ -0,0 +1,41 @@ +/* XPM */ +static const char *house_exit_xpm[] = { +/* columns rows colors chars-per-pixel */ +"32 32 3 1 ", +" c black", +". c magenta", +"X c white", +/* pixels */ +"................................", +"................................", +"..... ....", +"..... XXX X X X XXX ....", +"..... X X X X X ....", +"..... XX X X X ....", +"..... X X X X X ....", +"..... XXX X X X X ....", +"..... ....", +"................................", +"................................", +"........... ...........", +"........... XXXXXX ..........", +"........... XXXXX ..........", +"........... XXXX ..........", +"........... XXX ..........", +"........... XX ..........", +"........... XX ..........", +"........... XX ..........", +"........... XX ..........", +"........... XX ..........", +"........... XX ..........", +"........... XX ..........", +"........... XX ..........", +"............ XX ..........", +"............. ...........", +".............. .............", +"............... .............", +"................ .............", +"................. .............", +".................. .............", +"................................" +}; diff --git a/icons/mini_borderize.png b/icons/mini_borderize.png new file mode 100644 index 0000000000000000000000000000000000000000..ee7d830d90a30b2d81592ee5a869817cd5c389b8 GIT binary patch literal 1523 zcmbVMO=uid9G^fdH6aodN~q9|(}NM5&)rNqkB%|fNwSMhjGKj~o_v}2c6ZpBdE?AW zcamBZMMXpqD-^^YRy?VAQYtOd3i0UCi(n7+T4{@*$M!$_F{HIx?7*A%^?Sen_y7I1 z)s@NdL*s%VOxCJS9pv8EeQJ$`i%{~;l7AG z7AlyqO{!#J3}`_(KA*+d>rgIk(v~0D(v3@(CDA9gbYj-k+_*y9esw3I>pQCrZ>Qr~ zM4Eq2Jf0yS2r0*676ws@GF$5NB3S3gswDOyykkoXxj=ElT@x!Tp`xj1vZrZ=IAgq|x*c(x$x(WA#Ng1>OZ=GoEE01@yveq>ErF&36T-Nljnbi;z+q~JV^vqQ z+@wB`cm*!rN`k&{;;A&CA&qznSiQi;ZN^#JX8%H6T;C-CTmhJ}cfFP#E2 zh7P$eI&EynRISsLZ6zLEIt6MT&8>-1C83zJq`_D)3e?(2Wzop&O`dAPApULYg*!x{UbE?SDc6VWP5i7Zg&4V2&RMCLU_CB*b8_ zAL15OElN3# zJX&*X37n(&J^`yRHa&e-Hq1F9n?~7_H{nD!2-QfrNvsmaqxTN;w(=Ahy(j`h(lO@Ddoht(vgesS~rGt#$L+CA%ObV#@o zU78rnzJ6!s%qzdY@gy04`Pa_%zk;dHcO$>_acOz>kL7b$Cw70Cab9?D|IU$XwhNCnbKaI~ORLT| Ii?6`6pHR5;7E zlj%-cQ51!F4&J~xM61?D4NeiKN{NVy6X-Qqxk8=MfEX_jL}^8BK|~N7FhJC_i5-lo zIHJodz)CX1Y{)@S~!d8q1l+bMV!}{YL?7wC( z%edaW=F&F+ z($9?`K8YY%uR)_%0MQCxd3ndPa;Y~P?U+0ni$XZM7r6Hug|3%ZMP*Zkl*~_HJgCLk zA%$#B#@zrWY4GPt5fc}9icOq|ZdVP>t`f>G-FQBfO2-8VoE7L?C-B-QL8&<(Elc$< z9F9VNpaHd~Mzw{9XMM@!tpI_e9I`cn>D7RVpdQ8}3WkFbsCW7qu?h_iA<}x2LUHGS zH_L_8E5^i;Hs-n?bM4!dqv}ItRGh3xVBa~)+_!mXcGsfbDMZdlCbCp%NFPW!OYKP{ oAG`}3ZPvA c #58A34F", +", c #6DBF62", +"' c #8CCA82", +") c #ABD8A1", +"! c #A2D499", +"~ c #A6D59C", +"{ c #A4D49B", +"] c #9BD092", +"^ c #9ED196", +"/ c #79B871", +"( c #509947", +"_ c #85C77B", +": c #A9D7A0", +"< c #A0D197", +"[ c #81C077", +"} c #7EBC75", +"| c #97CC8E", +"1 c #9BCF93", +"2 c #98CE90", +"3 c #69AB61", +"4 c #6ABA5F", +"5 c #9DD194", +"6 c #A6D59D", +"7 c #5DAA53", +"8 c #59A650", +"9 c #56A14D", +"0 c #529C4A", +"a c #90C989", +"b c #8CC885", +"c c #84C07D", +"d c #43893C", +"e c #66B65C", +"f c #63B259", +"g c #60AE56", +"h c #5CA953", +"i c #4E9746", +"j c #6FAF67", +"k c #8FC988", +"l c #3E8438", +"m c #55A04C", +"n c #499142", +"o c #6AAB63", +"p c #8AC783", +"q c #88C582", +"r c #3A7E34", +"s c #549F4B", +"t c #509A48", +"u c #499141", +"v c #458C3E", +"w c #84C17C", +"x c #7EC177", +"y c #77B771", +"z c #367930", +"A c #539E4B", +"B c #6CAE63", +"C c #68AA60", +"D c #489040", +"E c #61A35A", +"F c #87C581", +"G c #85C47E", +"H c #82C27C", +"I c #54964E", +"J c #539D4A", +"K c #6AAD63", +"L c #8FC987", +"M c #8BC785", +"N c #89C682", +"O c #87C47F", +"P c #7CBF75", +"Q c #82C27B", +"R c #5B9D55", +"S c #31732C", +"T c #4E9846", +"U c #66A95F", +"V c #8BC683", +"W c #85C37E", +"X c #74B56D", +"Y c #52954D", +"Z c #468D3F", +"` c #5EA157", +" . c #5A9E55", +".. c #3B7F35", +"+. c #377B31", +"@. c #33762E", +"#. c #3E8337", +" ", +" ", +" . + @ # ", +" $ % & * = - ; > ", +" , ' ) ! ~ { ] ^ / ( ", +" _ : = < [ } | 1 2 3 ", +" 4 5 6 1 7 8 9 0 a b c d ", +" e f g h i j k b l ", +" m n o p q r ", +" s t u v w x y z ", +" A B C D E F G H I ", +" J K L M N O P Q R S ", +" T U V F W H X Y S ", +" Z ` ...+.@. ", +" #.r ", +" z "}; diff --git a/icons/mini_copy.png b/icons/mini_copy.png new file mode 100644 index 0000000000000000000000000000000000000000..e4b3158ba4ddcfffab50a57a63c59fcb817de8c0 GIT binary patch literal 2066 zcmbVN4Qvxt9Pij1FjhcelMli3wnP-J_tEcTm2K_Vs&t!MlT8S)*Spv5TzgmUu4{)e zI2MG(nM_8+z(7Mpl3~V&#>gPT1cwAdCbEfwz$5_?6wIQTh|G6e*8qYLF1fpR@BQBI z|NDQu|238t7wXfdrRj7!y}QU&hTapkdrT^NKHWbE&}(eC=oLk$8#hV2lXM$er|5K# zT@bvLYNclZ%Sj;v;3Xe4#6n?&*6DKQ#lnEAfhy*M0YP-&*Y@tmF@bmB6=o0R2|Ho6 zP_$fz<;#n`-0~XE&g1i5z;a?NA_zehV6jk8RM?mUAL3=vSeqtsYzU&(IPg5pAXe!q z#hj81F^hpBIErF0tKC3bOePC82V*FPA}KRTGX!m6DHBUuvG|1}YclU=%Utv0w$PUY zuU6GCOOnxO)DSfqBsoCRcDtRV7?NQKgdmhUQ3WwVRI)}GTu|X;A*>3Lh-r+#Cq+~T zj+73&5DF(~MI|046fiOd!X#~=G?#{eJeRJ3pKKgi8Yz;fTEJ&feIc7<~i0c$svFo7D6BZ$*>r}u|ybIrxcWAWEiP4-ahYk zI!k5AF9gwoQdXFcxeJ^Y+HSEBjDa4K>+!H|QBi@&LAT3+qu>|>foCZjG@2-c^BE~C zVTC3@*zIONVYdOJ$!s?A6k{9N?~=HPRstjYd9>eZ^8uPM1Hy(%p78li=wb8w2*{X? zG;c$s0F3M}kp*-FLGY1zw1cVD4qGHBD64hxqf-u-#YaH_8!8tTaN03&;GC9!$m8*8 z;T{oqI1h$tqty_R{!d*D!xYJ{Mu80T0w`J!tUL04;uTQ)|I!~WdH0ikSDikJ^mtgg zY9Iz6>Zv5IIYVmQXE-V3-T4|?yRB1=z)}0thKat5J`$Z9iilc9eYx@Ug%+JIsmJZg z^V;5ythKM1oHu3F{slgPoXB2#=jE|1r7U;M#^V?5GTY`U{Tc3S-QOS+7Enl>|XV18-lyv;{A{(pt>E`=^wX;|Y(>*P}|4GxL z>wVAe`+L+MX|0RjcxxLF&)wY0Bp2uMA6)$CmLof3;N&W&-qtbt-Lvac4b^sYEA`jO8;&-&*KU4w*Rr0mJ9C2#Tj=JwKbM^EbPs$pp{sq| ziKki{4oiJsZS2ZWKxjux?`5f}1$J-VO=q4+|6xVnvHYq}h&Kyg>c8}HMP+Sf+sih0 z3UkHRGp4Q9xN-X7s>1Z%i_JHDxkk(J+^Z|EAI{vjr2e;wZR1<}yWR7pF literal 0 HcmV?d00001 diff --git a/icons/mini_copy.xpm b/icons/mini_copy.xpm new file mode 100644 index 00000000..474c3fad --- /dev/null +++ b/icons/mini_copy.xpm @@ -0,0 +1,126 @@ +/* XPM */ +static const char *mini_copy_xpm[] = { +"16 16 107 2", +" c None", +". c #0F6DFF", +"+ c #227DFF", +"@ c #2480FF", +"# c #2280FF", +"$ c #2380FF", +"% c #237EFF", +"& c #1B7AFF", +"* c #0770FF", +"= c #0056EE", +"- c #1F7CFF", +"; c #FFFFFF", +"> c #E7F3FF", +", c #E8F3FF", +"' c #E5F2FF", +") c #DEEFFF", +"! c #E2F3FF", +"~ c #73BCFF", +"{ c #257AFF", +"] c #0058F1", +"^ c #ECF5FF", +"/ c #C2DEFF", +"( c #C3E0FF", +"_ c #BCDCFF", +": c #AAD3FF", +"< c #F2F9FF", +"[ c #BFE2FF", +"} c #80C1FF", +"| c #0C74FF", +"1 c #217DFF", +"2 c #EFF6FF", +"3 c #CAE2FF", +"4 c #CAE3FF", +"5 c #C3DEFF", +"6 c #B4D9FF", +"7 c #D3E9FF", +"8 c #E6F3FF", +"9 c #EFF9FF", +"0 c #3391FF", +"a c #F0F7FF", +"b c #CFE5FF", +"c c #CEE4FF", +"d c #C8E2FF", +"e c #BEDCFF", +"f c #88C3FF", +"g c #7DC0FF", +"h c #77BBFF", +"i c #3EA1FF", +"j c #3E9DFF", +"k c #2C96FF", +"l c #207DFF", +"m c #F2F7FF", +"n c #D4E7FF", +"o c #C5E0FF", +"p c #7CBEFF", +"q c #FEFFFF", +"r c #D5E7FF", +"s c #D2E6FF", +"t c #CDE4FF", +"u c #78BAFF", +"v c #1D7BFF", +"w c #F1F7FF", +"x c #D9E9FF", +"y c #DBEAFF", +"z c #D7E7FF", +"A c #1E79FF", +"B c #1F78FF", +"C c #EAF5FF", +"D c #B2D6FF", +"E c #A3D1FF", +"F c #DFEFFF", +"G c #257DFF", +"H c #2376FF", +"I c #D9FFF7", +"J c #76BBFF", +"K c #BEDEFF", +"L c #247EFF", +"M c #176EFF", +"N c #E9F3FF", +"O c #E3F1FF", +"P c #E2F0FF", +"Q c #E5F0FF", +"R c #E6F2FF", +"S c #76B9FF", +"T c #C7E3FF", +"U c #BDDBFF", +"V c #237CFF", +"W c #126BFF", +"X c #146AFF", +"Y c #0E66FF", +"Z c #0D66FF", +"` c #D2E5FF", +" . c #CBE2FF", +".. c #217BFF", +"+. c #EBF7FF", +"@. c #2277FF", +"#. c #DBFFF4", +"$. c #2572FF", +"%. c #116BFF", +"&. c #E7F1FF", +"*. c #ECF4FF", +"=. c #1F72FF", +"-. c #0864FF", +";. c #0C66FF", +">. c #0F65FF", +",. c #0A65FF", +"'. c #1E71FF", +". + @ # $ % & * = ", +"- ; > , ' ) ! ~ { ] ", +"+ ^ / ( _ : < [ } | ", +"1 2 3 4 5 6 7 8 9 0 ", +"1 a b c d e f g h h i j k * = ", +"l m n n b o p q > , ' ) ! ~ { ] ", +"- a r n s t u ^ / ( _ : < [ } | ", +"v w x y x z h 2 3 4 5 6 7 8 9 A ", +"B C x y x z h a b c d e D E F G ", +"H I x y x z J m n n b o K 6 ' L ", +"M N O P Q R S a r n s t T U > V ", +"W X Y Z Y Z v w x y x z ` .w ..", +" B C x y x z ` .+.@.", +" H I x y x z ` .#.$.", +" %.N O P Q R R &.*.=.", +" -.;.Y Z Y Z Z >.,.'."}; diff --git a/icons/mini_cut.png b/icons/mini_cut.png new file mode 100644 index 0000000000000000000000000000000000000000..f215d6f6b7c81ab344a3e53e0e5e756c58c82d90 GIT binary patch literal 648 zcmV;30(bq1P)Sxb0Y6MkDSd{nPwTp^L>b`TxVmKBiF^NLQ>My+_!0?|)hBPe_#}P$?rlUF;M20U z`oNWE|K(DrsR+gN%g)?+`OfqmmmiA8O_U(YfPnV(E$8mN{jZQVJ-L7LxzmTQJ^!PS zHqDyoKn&^H)Oq>Q$Nzns&wsn~^6P)|vPC&W#R9Kw95|FC`?q!91!~-K_R;^uDLWSs zj7A}sG%2IZxvQP(HeS-nn71T-`ku2F9(?#8KXKbp!Qe&~yaot4r%3=c-cDF`=YPn& z3!hUrzxqFO*Ny)VU;p?Y-nniMuVuI+UIUD>=B$ZZdhM^2Z-JeJcbDl-H)3?9>AG_?ve_7A86r2Wlb?y7)ShoTkzeah}rl)Oq{=a0=sekDkpZ?d4n{v>% zcgJPxg7sgx4Lmup8sO5j^?B5iYcCv|)*VgT_U6A?-trsfIcr`APCfD&B(EM;R_0K# z{lAb!kTg~UrQ ilDgypkCC?sx*7n c #CEDEED", +", c #8FB3CE", +"' c #C3D6E7", +") c #548AB2", +"! c #D3E2F1", +"~ c #8EB3CF", +"{ c #DCE9F5", +"] c #598FB6", +"^ c #DDE9F5", +"/ c #B4CDE2", +"( c #6194B9", +"_ c #32699D", +": c #427EB1", +"< c #2C689E", +"[ c #6797BC", +"} c #D0E0F0", +"| c #5F91B6", +"1 c #60AADC", +"2 c #549ED0", +"3 c #65B3EA", +"4 c #99BAD8", +"5 c #E1EBF8", +"6 c #5789AE", +"7 c #326A9C", +"8 c #5EA5D6", +"9 c #60ADE4", +"0 c #9BBDDC", +"a c #A5CDEF", +"b c #67B7EF", +"c c #5DA6D8", +"d c #4A8ABE", +"e c #417EA8", +"f c #326E96", +"g c #66B0E7", +"h c #74A2CA", +"i c #67B1E5", +"j c #2D5E94", +"k c #4D8DB8", +"l c #3B70AF", +"m c #4482B5", +"n c #5AA4D6", +"o c #4182AE", +"p c #66B6EC", +"q c #366EA7", +"r c #376CAC", +"s c #5195C4", +"t c #4078B7", +"u c #5197C7", +"v c #5AA6D8", +"w c #366CA6", +"x c #3568A8", +"y c #57A0D1", +"z c #366A8E", +"A c #3F75B4", +"B c #2F5E9F", +"C c #63B2E7", +"D c #4F92BF", +"E c #62ABDD", +"F c #3262A2", +"G c #3161A0", +"H c #3F76B6", +"I c #3465A4", +" . ", +" + ", +" @ # ", +" $ %& ", +" * =- ", +" ;> ,' ", +" )!~{ ", +" ]^/( ", +" _:<[}| ", +" :123456 ", +" 78 90abc ", +" de fghijkl ", +" mnopqrs t ", +" uvw xy zA ", +" BCDEF ", +" GHI "}; diff --git a/icons/mini_delete.png b/icons/mini_delete.png new file mode 100644 index 0000000000000000000000000000000000000000..cdf2054a654ea77f5e5b8f2833eaf841812e1187 GIT binary patch literal 678 zcmV;X0$KfuP)-DICBP8Y$h(zuoqC{YG z8%kK&_5ef%AvY8XVRdB{%~lgL@fjrIvm{@|;^G6uVlikv4g32QXdP`*f=_IGWIIRH z@9V_jPS&M|OQg((ZI5tLt-9_Ex~}8%#V0RdXXiEDuN(x0K&-FoeDC$f6_&Jp}peDX7mC6Ux{=Wnm0HOW}`$@DhqW}N^ M07*qoM6N<$g3f9&M*si- literal 0 HcmV?d00001 diff --git a/icons/mini_delete.xpm b/icons/mini_delete.xpm new file mode 100644 index 00000000..b0203c08 --- /dev/null +++ b/icons/mini_delete.xpm @@ -0,0 +1,151 @@ +/* XPM */ +static const char *mini_delete_xpm[] = { +"16 16 132 2", +" c None", +". c #BAB9BA", +"+ c #B9BABA", +"@ c #BCBBBB", +"# c #6A6A6A", +"$ c #696A6A", +"% c #686969", +"& c #676768", +"* c #B9B9B9", +"= c #B8B8B8", +"- c #B7B7B7", +"; c #ADACAD", +"> c #CACACA", +", c #E3E3E3", +"' c #ECEBEC", +") c #A0A0A0", +"! c #F9F9FA", +"~ c #FCFCFC", +"{ c #9FA09F", +"] c #F1F1F1", +"^ c #E8E9E9", +"/ c #C9C9C9", +"( c #A9A9A9", +"_ c #A1A2A1", +": c #C1C1C0", +"< c #D5D5D4", +"[ c #DDDCDD", +"} c #EDEDED", +"| c #F5F4F5", +"1 c #F5F5F4", +"2 c #F6F5F5", +"3 c #EFEFEF", +"4 c #D1D1D1", +"5 c #999999", +"6 c #929392", +"7 c #B3B4B4", +"8 c #969596", +"9 c #969696", +"0 c #9A9A9A", +"a c #9A999A", +"b c #A3A3A2", +"c c #B7B8B8", +"d c #C5C5C5", +"e c #C8C8C8", +"f c #E0DFE0", +"g c #898989", +"h c #7B7C7B", +"i c #8B8C8B", +"j c #9F9F9F", +"k c #B6B6B6", +"l c #CACACB", +"m c #E0E0DF", +"n c #E5E5E5", +"o c #E8E8E9", +"p c #DADAD9", +"q c #979696", +"r c #757675", +"s c #939392", +"t c #808080", +"u c #737374", +"v c #737373", +"w c #686868", +"x c #676666", +"y c #797978", +"z c #848484", +"A c #8F8E8F", +"B c #8C8D8C", +"C c #9A9A99", +"D c #B2B1B2", +"E c #9D9D9D", +"F c #ACADAC", +"G c #BEBDBD", +"H c #D2D2D1", +"I c #FFFFFF", +"J c #F3F4F3", +"K c #959696", +"L c #909090", +"M c #B1B1B1", +"N c #9C9B9B", +"O c #BABABA", +"P c #CFCFCF", +"Q c #A7A8A8", +"R c #F3F4F4", +"S c #8C8D8D", +"T c #878787", +"U c #B1B0B1", +"V c #9A9B9B", +"W c #D1D1D0", +"X c #D0D0D0", +"Y c #A9A8A9", +"Z c #858585", +"` c #7E7F7F", +" . c #9B9B9B", +".. c #D1D0D1", +"+. c #CFD0D0", +"@. c #F4F4F3", +"#. c #7D7C7C", +"$. c #777777", +"%. c #B2B1B1", +"&. c #9B9A9B", +"*. c #D0D1D0", +"=. c #BABAB9", +"-. c #F3F3F4", +";. c #757575", +">. c #707070", +",. c #B2B2B2", +"'. c #BABABB", +"). c #A8A8A8", +"!. c #6E6E6E", +"~. c #6B6A6A", +"{. c #9D9D9C", +"]. c #AAABAA", +"^. c #BBBABB", +"/. c #CECFCF", +"(. c #F0F0F0", +"_. c #696868", +":. c #646465", +"<. c #818181", +"[. c #989898", +"}. c #A3A2A2", +"|. c #BFBFBF", +"1. c #D2D2D3", +"2. c #D9D9D8", +"3. c #E2E2E2", +"4. c #939393", +"5. c #636364", +"6. c #626162", +"7. c #616161", +"8. c #606060", +"9. c #605F60", +"0. c #5F5F5F", +"a. c #5F6060", +" ", +" . + @ # $ % & * = - ", +" ; > , ' ) ! ~ { ] ^ / ( ", +" _ : < [ , } | 1 2 3 4 5 ", +" 6 7 8 9 0 a b c d e f g ", +" h i j ( k l m n o p q r ", +" s t u v w x y z A B ", +" C D E F G H ] I J K ", +" L M N 4 O P Q I R S ", +" T U V W O X Y I R Z ", +" ` M ...O +.Y I @.#. ", +" $.%.&.*.=.X ( I -.;. ", +" >.,. .W '.P ).I J !. ", +" ~.,.{.].^./.(.I -._. ", +" :.<.[.}.|.1.2.3.4.5. ", +" 6.7.8.9.0.a. "}; diff --git a/icons/mini_draw.png b/icons/mini_draw.png new file mode 100644 index 0000000000000000000000000000000000000000..a3ecf87784e7715238421dbbe773a54f602c7fb9 GIT binary patch literal 548 zcmV+<0^9wGP)_f5P$T1}wR3qlt(jG_Y0Zr52WH59esgOQSo5P}VIa-lfSOgY zCZygaE0|WSnkNR-ymix>c|SI-nf-6e(wcueyQTi$-RJ-R;B=$^K+VoLQ)2g$Ws=Pc zm#>>RZ{`29@OSkoJqNN@e;Py`Af1JrY`wEZP%6mtqXSk zPwm?BzjD%=|3xj6wl2t5m&ThH>ZdPV+c10m|F)IK{&%jw_P=uO$^X$kSO5DKE_-is$J8N5P(ZnF4bK|DPP6 c #F3E8BE", +", c #F8E87E", +"' c #D1AC3E", +") c #D2AE40", +"! c #AE7B1A", +"~ c #DAC073", +"{ c #F3E9BE", +"] c #D5B344", +"^ c #F4E9BF", +"/ c #DABB4B", +"( c #B2AC98", +"_ c #C0981E", +": c #ECDA92", +"< c #E2C656", +"[ c #B2AC9A", +"} c #B2AC9E", +"| c #B2AC9B", +"1 c #B4A57C", +"2 c #B98B1A", +"3 c #DDBE4F", +"4 c #C19732", +"5 c #83A1A7", +"6 c #919EA9", +"7 c #CFD2CD", +"8 c #FCF2D3", +"9 c #F2E5C0", +"0 c #B39F6E", +"a c #8095A4", +"b c #96BAD4", +"c c #85A0B9", +"d c #658AB4", +"e c #7992AC", +"f c #728492", +"g c #7F97A5", +"h c #809BAF", +"i c #86A9C6", +"j c #89AFD6", +"k c #799DC9", +"l c #5B8CD5", +"m c #4D71A6", +"n c #6C859C", +"o c #627C97", +"p c #597493", +"q c #516C90", +"r c #4B668C", +"s c #506D9A", +"t c #B2A16E", +" ", +" .+", +" @#$", +" @%&*", +" =-;* ", +" =>,' ", +" =>,)! ", +" ~{,]! ", +" ~^,/! ", +" (_:,dQ5?sAZxk0j_~+0? zFfhzpcnPKsDJx^>${up*Qnxw?K_GaLC0vqV@!}zZU1kX)sOVJe&emQkPf>eW@KzrD za}4~G2X)k$dHvqYk;%0me0h)e-skuC5wKV=7z9a@ARG?E<-!37ct%hH5Rn2%0F>bR zNdx$<0|gCbXJ8-@fLJUBp->1M4hJmRH3O)$@$uCYLI^0SyQbf7?9!geWO(EiAhYWR zKq9TYEcLrxOhtgrlh>v9sXI2F7{FJ-@At!hjKMcI4qudd2vds58wT`xJ-Bu9W=97| zjmbl76n8R$} zZ8rbzDQ}`pScX+q74!MLJe^KK*L85+mKIJrbJ*kYz|n*4r+9iSSmE(_EEWm{88hIp zskO{H{Ax7Nhrwax;iG3b#v{z5Dp(^Ii$xjNe_*C2MmDzM96rwN>|yPPh<)K>G$WVG zWqC9jooi^j-Nxw&;C8!V>+OE_9-&P_$!GK4&LUST6?r%uo`YMh)&fqa(^*Z^PH_%3 z_KSXk3U#W2-2_>xR%2DD)e-zae{+}_NhXsKbRsH>A`b=we%QcxF_xt_Dr6`IV#%+yFV3o0Qe5eafr}Gj< zy*QiAcscXWQfCRFW~k|WWztyHD1$k0qFksoHqp5Zi*(DXFWu2U0t^5U(Njaf literal 0 HcmV?d00001 diff --git a/icons/mini_erase.xpm b/icons/mini_erase.xpm new file mode 100644 index 00000000..59f92737 --- /dev/null +++ b/icons/mini_erase.xpm @@ -0,0 +1,81 @@ +/* XPM */ +static const char *mini_erase_xpm[] = { +"16 16 62 1", +" c None", +". c #FDB8C9", +"+ c #FEB9CA", +"@ c #FCB5C6", +"# c #ECA5B6", +"$ c #ECA7B8", +"% c #AD0224", +"& c #B00225", +"* c #FBB3C4", +"= c #EAA2B3", +"- c #EBA4B5", +"; c #A90224", +"> c #F9B0C1", +", c #E99FB0", +"' c #E9A1B2", +") c #DC8798", +"! c #EE99AA", +"~ c #A50223", +"{ c #F8F8F8", +"] c #F5F5F5", +"^ c #E89DAE", +"/ c #D98495", +"( c #DB8697", +"_ c #ED98A9", +": c #A10222", +"< c #F6F6F6", +"[ c #F2F2F2", +"} c #D68192", +"| c #D88394", +"1 c #EA95A6", +"2 c #9F0222", +"3 c #F4F4F4", +"4 c #EFEFEF", +"5 c #D27D8E", +"6 c #D47F90", +"7 c #E792A3", +"8 c #9D0221", +"9 c #F3F3F3", +"0 c #ECECEC", +"a c #CECECE", +"b c #D0D0D0", +"c c #E38E9F", +"d c #9B0221", +"e c #F1F1F1", +"f c #E9E9E9", +"g c #CACACA", +"h c #CCCCCC", +"i c #DCDCDC", +"j c #F0F0F0", +"k c #E6E6E6", +"l c #C6C6C6", +"m c #C8C8C8", +"n c #D8D8D8", +"o c #E3E3E3", +"p c #C2C2C2", +"q c #C4C4C4", +"r c #D4D4D4", +"s c #E1E1E1", +"t c #BFBFBF", +"u c #C0C0C0", +"v c #D1D1D1", +"w c #DFDFDF", +" ", +" .+ ", +" @#$+% ", +" &*=-#$+; ", +" >,'=-#)!~", +" {]^,'=/(_:", +" <[[[^,}|12 ", +" 3444445678 ", +" 900000abcd ", +" efffffghi ", +" jkkkkklmn ", +" joooopqr ", +" jsstuv ", +" waaa ", +" ", +" "}; diff --git a/icons/mini_fill.png b/icons/mini_fill.png new file mode 100644 index 0000000000000000000000000000000000000000..f82a8865a7bc0326fd56f27a869326be4a7d688b GIT binary patch literal 707 zcmV;!0zCbRP)d6{}iR@dma4U zGwNI63={10?wsg6GrMIz9=9gZKjA|+f3>GAK+D|GJH82pDTdw`PIL|}-E9ldO1tCE zh!Y}h7`H{Mc=~qbQ(FLcAgsD6T*IKskM2jy_-qNlZnsM>1c*c;%G7om9HAYZ4@|gr ze-YdHGL{@3SlraFMS}W1yBeCDwgj)70ffV0WjdWkyAqr__<>5Lf>Nmjzuyn#`-SF| zCD@#CrZM!vJ3OHFTxO9ZIYyfsjRp#Z0 zMwk*D4u?7#jpFF&2#1GEG`Byu|C}hU^-i!wvCE+^rj9RT$?eTa}EEYkR zMK{!HwbGGEfk1HjC$2x=82slTsZ=WU`uaN4eVfe&i9|y3`F!?;Cy|z1E>{~228hLC plE>q<_Zv^tYSsXk%l)sJ)*onV;!t9*YM1~3002ovPDHLkV1n&hO1S_4 literal 0 HcmV?d00001 diff --git a/icons/mini_fill.xpm b/icons/mini_fill.xpm new file mode 100644 index 00000000..31414792 --- /dev/null +++ b/icons/mini_fill.xpm @@ -0,0 +1,122 @@ +/* XPM */ +static const char *mini_fill_xpm[] = { +"16 16 103 2", +" c None", +". c #4884C2", +"+ c #427DBD", +"@ c #80ABD2", +"# c #4C81BD", +"$ c #4680BE", +"% c #7BA5CF", +"& c #4679B7", +"* c #3F77B7", +"= c #6E96C7", +"- c #3C6EAF", +"; c #738BAE", +"> c #B9C0C7", +", c #376DB0", +"' c #5F87BF", +") c #3463A9", +"! c #9CAAC0", +"~ c #C8C8C8", +"{ c #D4D5D7", +"] c #3B6DAD", +"^ c #2C5DA5", +"/ c #2757A1", +"( c #D5DBE4", +"_ c #A8B2BA", +": c #AAB9C6", +"< c #A1B6C6", +"[ c #93AFC3", +"} c #C7C7C7", +"| c #D7D7D7", +"1 c #ECECEC", +"2 c #7D97BD", +"3 c #BFC6D0", +"4 c #7690B8", +"5 c #E4E4E4", +"6 c #EDEDED", +"7 c #98A5B0", +"8 c #ACC6D9", +"9 c #A6C4DB", +"0 c #83A6C2", +"a c #C6C6C6", +"b c #DADADA", +"c c #A5B3C8", +"d c #7F97BB", +"e c #A9B6CC", +"f c #E5E5E5", +"g c #E3E3E3", +"h c #BFBFBF", +"i c #82919D", +"j c #89AAC2", +"k c #8EB7D7", +"l c #C5C5C5", +"m c #F1F1F1", +"n c #DCDCDC", +"o c #D9D9D9", +"p c #EBEBEB", +"q c #B9B9B9", +"r c #B7B7B7", +"s c #72828F", +"t c #7EACCE", +"u c #6898BD", +"v c #D3D3D3", +"w c #E9E9E9", +"x c #DEDEDE", +"y c #DDDDDD", +"z c #D4D4D4", +"A c #D1D1D1", +"B c #B6B6B6", +"C c #909090", +"D c #727272", +"E c #6999BE", +"F c #6CA6D1", +"G c #B2B2B2", +"H c #CBCBCB", +"I c #F0F0F0", +"J c #EEEEEE", +"K c #EAEAEA", +"L c #D8D8D8", +"M c #D2D2D2", +"N c #D0D0D0", +"O c #C0C0C0", +"P c #949494", +"Q c #717171", +"R c #5E93BC", +"S c #568FBA", +"T c #A4A4A4", +"U c #C3C3C3", +"V c #E7E7E7", +"W c #DBDBDB", +"X c #CFCFCF", +"Y c #9A9A9A", +"Z c #548EBA", +"` c #3B82B6", +" . c #969696", +".. c #BABABA", +"+. c #E0E0E0", +"@. c #ABABAB", +"#. c #878787", +"$. c #B1B1B1", +"%. c #ACACAC", +"&. c #707070", +"*. c #7A7A7A", +"=. c #9F9F9F", +"-. c #6F6F6F", +" . + ", +" . @ # ", +" $ % & ", +" * = - ; ", +" > , ' ) ! ", +" ~ { ] ^ / ( _ : < [ ", +" } | 1 2 3 4 5 6 7 8 9 0 ", +" a | 1 b c d e f g h i j k ", +"l | m n o n p g n | q r s t u ", +"h v w x y 1 p o z A B C D E F ", +" G H I J K L M N O P Q R S ", +" T U V W A X N Y D Z ` ", +" ...+.v b @.Q ", +" #.$.f %.&. ", +" *.=.-. ", +" "}; diff --git a/icons/mini_move.png b/icons/mini_move.png new file mode 100644 index 0000000000000000000000000000000000000000..27f5e060ae02a744491d32bef7c67abe4b63b221 GIT binary patch literal 2381 zcmb_eeQXnD7{57nFu)ASG8|(&Zj&(B^}gD!cdlU94%$ga*{Y00r*H4B?Xk93?ryA` z@)19l00F|lsC)$H2mWCg-}nJYm<}QeM8ZdK1_%&{#IPV6Fj4TmuC1U92(iue-h1EQ z^Lu{J^FGhLUFfNrGAuJU6G4z+E~ld!-m~;;(39}D;OcDvZ-b-GnJR(|8KGZk$f`9X z5hUYz$y=+{x~Foy95w(!_KAjAI114SQZ^|T1$@1zp*}GnMXXr&&OI0^307=|$xXVW zb}=Y9n-#I9xys8o*Ym7^O`3?7#W+Y17Bzsz!l8)D#jIGImxE({n!wOFM60)AHr*jw z>-L~_SrJjQfy8-|q|s8=K$(q3Gg*StBux^eiJ)klGIOMnqe{`l2ZP=e!OvAYCMSHs zCo2}zv?xaqjg5_lM#dm30fJ&#mLO?@rg4bC)uxCBVt7O?Ofon`l~<&wCdm<0X9PaE zL9=2|X@3aeXo@zXCej2GM#MmrpbVrQQXDAoDO|Kc3B{cYJRyd}uo%%)h^124Xi(N< zH7E~2om#%j0Zgsio$_%{E#Yv=g{oD|fng*Pa!<7CZHkISwW!Js3NKd7fiesAXri25 z5rHNvURe$$H_DTgjM9{WM#s&NB7)qg7T;kYI)ElxF}Q0CPEt5+_R1D_v$83DJL{XA|Fj3(SinN2up z6#a~e5m}SpoV1^&NU#M#=#hC~tNfFSB#RA3q{2N`6OB|30*O&bny82QurkXCy=$Nm z+CS{`Er2Q+tP~hdOeB)mYA0Au_F(c(SF*-pa@Ct zQ>XnfRrYI*KoM;LxO)%m17aZYDwuPB=|)h>Qxt8&DZo;=g@whyntcM!S_FY%%oa;2 zfWdAQCPIGDR$0{>qy@gnW7Fyi0E7hk*M z7)Vw!JX`c(>QI9Zsbf)$z&t7N(7Sk`>k@*bZFM?!*sbA4=Fe)ZS0+CJ;dl@@xfy%#oQ*q5ChgI+kY;#$^YX<^&XZ*{IK-#aps?GbJV zUBip=TPtTx?>cjN?9H-mGk@QFc~QFhe$%()Re!#-zCArTrQAkrYj65u)=JUFXMljh!*G;B;N_Nu_tQ!#BGwySFHJRf~OE`cU@@XUU<@j}(XJN1M(* zJLcB08~gLmTwi=*`|Ia|SC-!_IJ%2!J-hvju~vC%-AVG~NEbV+V|vl4<&UpE;p%pF pyy&@HIjVVHdu}-I<)c+;eYe&u%enO3Wc?41tD?%$UjEvfe*@#oEV}>z literal 0 HcmV?d00001 diff --git a/icons/mini_move.xpm b/icons/mini_move.xpm new file mode 100644 index 00000000..cbc7154d --- /dev/null +++ b/icons/mini_move.xpm @@ -0,0 +1,70 @@ +/* XPM */ +static const char *mini_move_xpm[] = { +"16 16 51 1", +" c None", +". c #409EE9", +"+ c #3D9BE6", +"@ c #90DCFF", +"# c #3996E1", +"$ c #8DD9FE", +"% c #83CFFD", +"& c #1574BF", +"* c #8AD6FC", +"= c #308AD5", +"- c #85D1FB", +"; c #2C84CF", +"> c #80CCF8", +", c #277EC9", +"' c #7DC9F7", +") c #1D78C3", +"! c #6CBAE9", +"~ c #72BFE9", +"{ c #2277C1", +"] c #79C5F5", +"^ c #67B3EF", +"/ c #78C4F4", +"( c #71C0F1", +"_ c #5EB4E7", +": c #57AFE3", +"< c #48A1DB", +"[ c #54ACE1", +"} c #53ABE0", +"| c #52AAE0", +"1 c #50A9DF", +"2 c #3A95D4", +"3 c #61B7E6", +"4 c #1C6FBA", +"5 c #77C3F4", +"6 c #49AEE6", +"7 c #42A9E3", +"8 c #1769B4", +"9 c #3BB1EC", +"0 c #1363AE", +"a c #1262AD", +"b c #2CB3F3", +"c c #0D5BA6", +"d c #0D5CA7", +"e c #1EB6FA", +"f c #0956A1", +"g c #13B8FE", +"h c #02B2FE", +"i c #10B7FE", +"j c #05519C", +"k c #0CB6FF", +"l c #024D98", +" . ", +" +@+ ", +" #$%$# ", +" &&&*&&& ", +" = &-& = ", +" ;; &>& ;; ", +" ,',,,)!),,,~, ", +"{]^/(_:<[}|123{ ", +" 4544446444474 ", +" 88 898 88 ", +" 0 aba 0 ", +" cddeddc ", +" fghif ", +" jkj ", +" l ", +" "}; diff --git a/icons/mini_paste.png b/icons/mini_paste.png new file mode 100644 index 0000000000000000000000000000000000000000..337c5654f34c69add22a0b1add40af56cabfb488 GIT binary patch literal 531 zcmV+u0_^>XP)#NM+rnz9`GKNq18HF*!jU=pp8Z&tzNH786c~GkPHxUfG`YcbX_-Z z7+R@RqHC6Aq4yOsjp_cUArA(Lu0Sk(-bV7kPIMffdM2*;vkOW zoSiQ{#)7d5Fp>RLgwP6b zIB>!?c4{0TcpY;95yJX}qioz>nVNXkLFJf6RaO7Ii3pIy>&&dtXcVvYUuOIWFaX`m VMy2B^-jM(R002ovPDHLkV1f((?XLg; literal 0 HcmV?d00001 diff --git a/icons/mini_paste.xpm b/icons/mini_paste.xpm new file mode 100644 index 00000000..cdb9d24d --- /dev/null +++ b/icons/mini_paste.xpm @@ -0,0 +1,93 @@ +/* XPM */ +static const char *mini_paste_xpm[] = { +"16 16 74 1", +" c None", +". c #A1A1A1", +"+ c #A87838", +"@ c #9D8A6F", +"# c #969696", +"$ c #FBFBFB", +"% c #A67536", +"& c #F7E8D0", +"* c #878787", +"= c #F4F4F4", +"- c #E9E9E9", +"; c #A37234", +"> c #EBCB94", +", c #E3B567", +"' c #A39170", +") c #777777", +"! c #9F6E32", +"~ c #E9C792", +"{ c #DFB064", +"] c #DFAF63", +"^ c #9B692F", +"/ c #E5C48F", +"( c #DAAB60", +"_ c #DAAA5F", +": c #B8A586", +"< c #96642B", +"[ c #E2BF8D", +"} c #D5A55C", +"| c #D5A45B", +"1 c #9C9C9C", +"2 c #FDFDFD", +"3 c #C2C2C2", +"4 c #915F28", +"5 c #DEBB89", +"6 c #D09F57", +"7 c #D09E56", +"8 c #959595", +"9 c #EBEBEB", +"0 c #EAEAEA", +"a c #8D5925", +"b c #DAB686", +"c c #CA9852", +"d c #CA9751", +"e c #8D8D8D", +"f c #EDEDED", +"g c #885321", +"h c #D6B283", +"i c #C4924E", +"j c #C4914D", +"k c #858585", +"l c #EEEEEE", +"m c #834E1E", +"n c #D2AE7F", +"o c #BF8C49", +"p c #BE8B48", +"q c #7B7B7B", +"r c #7E491A", +"s c #CEAA7C", +"t c #BA8645", +"u c #B98544", +"v c #727272", +"w c #EFEFEF", +"x c #7A4417", +"y c #CBA67A", +"z c #B58141", +"A c #686868", +"B c #F0F0F0", +"C c #764015", +"D c #C8A378", +"E c #606060", +"F c #F1F1F1", +"G c #733D13", +"H c #585858", +"I c #515151", +" .... ", +"+++@#$$#@+++ ", +"%&&*=--=*&&% ", +";>,'))))',>; ", +"!~{]]]]]]{~! ", +"^/(___:....... ", +"<[}|||122222213 ", +"4567778290--2888", +"abcddde2f90-222e", +"ghijjjk2lf90--2k", +"mnopppq2llf90-2q", +"rstuuuv2wllf902v", +"xyzzzzA2Bwllf92A", +"CDDDDDE2FBwllf2E", +"GGGGGGH22222222H", +" IIIIIIIIII"}; diff --git a/icons/mini_randomize.png b/icons/mini_randomize.png new file mode 100644 index 0000000000000000000000000000000000000000..720bf5a167485063926038072c0f557947555a1d GIT binary patch literal 1620 zcmbVMTWs4@7@B(S;YniHJn3S)vySfqJ~GR7F0{frE{pDn-S*H`^yZiYY}E5pa8{+qN1Ldv(flm zDx=Po)Ud{k?4pOOG9fUK3+bv+HXXSdVH&(LS$oGkLpLC9DZ-3;0_m)hrlZ(KbdUqA z3V=w5!kiHF`-9*SS_C5CL4X%TRtU<#FAE{M^)W=6t>xvh*kdhOWEWwIu4~CWU#V2M zio{{NzzgAUm-l{KC1ZH5?fR9m-P9h zp)Q8e5#hM;gT#!MLpDS^nVN<8G34M`TSf7MM9uAmHyObWwyMQIl98uwp19NV4FUC9;)d0Gdz*YkI!65mW@S6u1gXQbvO= zye3#v*WPuV&tL0GsNyL!w%1mCiVtX|2jS-AET1s$LmH7}bkE z(wNq-q%JW{qHtpd5X=3AUU2(VJq+@u? zPOBoDPP0QM>2Nk_W!cG}mPi|1OU6bsLkkN>&iUrSmiYdAr=FkqVCtqfx=;5{`wqvm zFMjdd-1&$5e0K~!_~XEDpIFnCD_{0bR+ZQI%NKVZm=b&5T{_hTmZ?vV_pSEyb;VWG zTT9Icj|Sor_4%{6UASK=ZU%>+$SrSuYh>x|-{IaBJUH3E_RC+l|9Ru0ab&eVHNEXy zow1JZS~=PM=7E(#=PTdW&rB}XsWT;Q$H_;(-+M#in|Jn~UAyn0g!0lo^}$WY7A{|W z`sivXJ^mhi`J+4U{_wL~&;0QCzS4K8g>z?L`T4{!WS#n<)w|9wzVOG&rSiU+`h|g0 Vc;@5RX`k2klkrsS^zP~TzX2R*5rzN& literal 0 HcmV?d00001 diff --git a/icons/mini_randomize.xpm b/icons/mini_randomize.xpm new file mode 100644 index 00000000..d3c679a6 --- /dev/null +++ b/icons/mini_randomize.xpm @@ -0,0 +1,26 @@ +/* XPM */ +static const char *mini_randomize_xpm[] = { +"16 16 7 1", +" c None", +". c #000000", +"+ c #E1EBFF", +"@ c #001540", +"# c #C1D5FF", +"$ c #A1BFFF", +"% c #81AAFF", +" .. ", +" .++++. ", +" .++++++++. ", +" .++++++.+++++. ", +".+++++++@+++++#.", +".###++++++++#$$.", +".#####++++#$%@$.", +".######+#$%%%@$.", +".#####@#$@%%%%$.", +".###@#@#$@%@%%$.", +".#@#@###$%%@%@$.", +".#@#####$%%%%@$.", +" .######$@%%%%. ", +" .####$@%%. ", +" .##$%. ", +" .. "}; diff --git a/icons/mini_remote.png b/icons/mini_remote.png new file mode 100644 index 0000000000000000000000000000000000000000..93ec4af694b4785e69f14d5591ea65bb417f2fd2 GIT binary patch literal 5972 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 c #307EB8", +", c #A0D5EE", +"' c #7DC1E7", +") c #78BEE6", +"! c #7EC1E7", +"~ c #A4D7EE", +"{ c #155B9A", +"] c #135895", +"^ c #4083B5", +"/ c #ADD8EB", +"( c #D1EBF6", +"_ c #D7EEF9", +": c #89C9EC", +"< c #75BFE6", +"[ c #73BEE6", +"} c #77C0E7", +"| c #95D3EE", +"1 c #135894", +"2 c #4C90BD", +"3 c #CFECF8", +"4 c #98D2EE", +"5 c #7AC3E8", +"6 c #72BFE6", +"7 c #75C1E7", +"8 c #6EBDE6", +"9 c #6FBEE6", +"0 c #86CAEB", +"a c #D3EDF8", +"b c #BDE2F1", +"c c #6CACCE", +"d c #12538D", +"e c #104C83", +"f c #B2DFF0", +"g c #77C1E9", +"h c #69B8E6", +"i c #6FBCE8", +"j c #88C9EC", +"k c #BCE4F6", +"l c #7CB7D6", +"m c #0E487D", +"n c #99D7EE", +"o c #5AADDE", +"p c #4EA5DB", +"q c #47A1D9", +"r c #409ED8", +"s c #3B9BD7", +"t c #3D9CD7", +"u c #439FD9", +"v c #4AA3DA", +"w c #59ADDE", +"x c #ACDFF1", +"y c #0E477C", +"z c #0D4273", +"A c #49BEDE", +"B c #3595CD", +"C c #318CC9", +"D c #3392CC", +"E c #4FC2E2", +"F c #0D4375", +"G c #0A3965", +"H c #2B84BD", +"I c #33A5D2", +"J c #2A89C2", +"K c #277FBC", +"L c #267CBB", +"M c #267BBA", +"N c #277DBB", +"O c #2883BE", +"P c #2F99CB", +"Q c #309BCF", +"R c #0B3B69", +"S c #1765A6", +"T c #238DCA", +"U c #2590CA", +"V c #2795CB", +"W c #2693CA", +"X c #2796CC", +"Y c #248EC9", +"Z c #1D7DC2", +"` c #0E3F6D", +" . c #072D50", +".. c #09345C", +"+. c #09355F", +"@. c #093661", +"#. c #09345E", +"$. c #083259", +" ", +" ", +" ", +" . . . ", +" + @ # @ + $ ", +" % & * = * - % ", +" ; ; > , ' ) ! ~ { ", +" ] ^ / ( _ : < [ } | 1 ] ", +" 2 3 4 5 6 7 8 8 9 0 a b c d ", +"e f g h h h h h h h h i j k l e ", +"m n o p q r s s s s t u v w x y ", +"z A B C C C C C C C C C C D E F ", +"G H I J K L M M M M M N O P Q R ", +" G S T U V W W W W W X Y Z ` ", +" ...+.@.@.@.@.@.@.@.#.$. ", +" "}; diff --git a/icons/mini_replace.png b/icons/mini_replace.png new file mode 100644 index 0000000000000000000000000000000000000000..21bb0c959bfc83aa6c6caa6acd0e4203efdf018a GIT binary patch literal 719 zcmV;=0x?{Eh?fm;@OLO@X~{Udhld11{$=7*hVP@JxKn5 zQtUQunjbqmGrrl4(WX84;4wS1^L_7oZ@)GAQyKgTgVLn@Mrk$nijoUyZ#W`KtG73r zx0QFV8LB1q6)6=oxb*NWwhPvJpnN{6Rr6q4BQ81a`^`3ShO4$(tfzY7og(cZOm}rN1C-nZ^Q@ zF_e5;=W?*-3RE0HYzpzHi>uuZT&m6KoDq0MgB|V?9mB2jN8t#ej!22BD+gys6PUe` zK;h3+@-v=Je!}7}iLTwdkba-XhkFAti+XRPVI4mh#jyiXm?lAu zHjjV>IuK|K^$=w=@o0KJ-gg4|Y!2D`$=JS$OhK&M*;=r(uk11?uB$Sf3+3@F_!1Q^ z;qZz-L>=|=YA(>e^JHecKbA~o3I!6lG?wtl*Ix9_M@B9HuHiSJtcGX*@xjcKp%H!g zOzLBSD--J~0QPvUXm^icrD`I=L)iE+r9UbqYkH(fKuU`G&?RtLhOxB&E~+XBo1SY* zd8TEN9^br%(KJ_!6B+6xFGFBk?toSzl(w6zt%va59{&&V2#l=+Is{2{2*{QG(*Bt3 zD$jj?l|Ci711UHek5-pM$T|%CUwFgZ?!|8b1^~E?A%^kQ+;;!~002ovPDHLkV1k!Q BNcI2# literal 0 HcmV?d00001 diff --git a/icons/mini_replace.xpm b/icons/mini_replace.xpm new file mode 100644 index 00000000..b94ef8a9 --- /dev/null +++ b/icons/mini_replace.xpm @@ -0,0 +1,137 @@ +/* XPM */ +static const char *mini_replace_xpm[] = { +"16 16 118 2", +" c None", +". c #1984B9", +"+ c #0E7EB6", +"@ c #097BB4", +"# c #087BB4", +"$ c #097BB5", +"% c #FFFFFF", +"& c #CDEFFF", +"* c #CEEFFF", +"= c #D2F3FF", +"- c #7E939E", +"; c #CFF0FF", +"> c #D0F0FF", +", c #D4F5FF", +"' c #8296A1", +") c #D4F4FF", +"! c #4585BA", +"~ c #4284B9", +"{ c #0C7DB5", +"] c #E2FAFF", +"^ c #E0FAFF", +"/ c #E0FDFF", +"( c #899DA5", +"_ c #DDFBFF", +": c #4082B8", +"< c #B7D7EC", +"[ c #3E80B6", +"} c #1985B9", +"| c #1280B7", +"1 c #0A7CB4", +"2 c #0076B1", +"3 c #0075B0", +"4 c #3785AC", +"5 c #95A0A6", +"6 c #91A0A8", +"7 c #8C9CA5", +"8 c #3A7DB4", +"9 c #B7D8EE", +"0 c #AFD3EC", +"a c #4181B6", +"b c #1081B7", +"c c #D7EBFA", +"d c #CFE6F7", +"e c #CDE6F6", +"f c #D1E8F8", +"g c #0076B2", +"h c #F6FFFF", +"i c #93A0A5", +"j c #E7FEFF", +"k c #BBDEF4", +"l c #B5DAF1", +"m c #92C5E7", +"n c #52A2D8", +"o c #9ACBED", +"p c #4683B8", +"q c #0C7FB6", +"r c #77B7E2", +"s c #CEE6F7", +"t c #FAFFFF", +"u c #939FA5", +"v c #E9FEFF", +"w c #3F7AAB", +"x c #4182B8", +"y c #3D7EB4", +"z c #65B2E5", +"A c #67B4E7", +"B c #4382B6", +"C c #D7EBFB", +"D c #B0D7F2", +"E c #AFD6F2", +"F c #D1E9FB", +"G c #0077B8", +"H c #FEFFFF", +"I c #95A4B1", +"J c #EEFFFF", +"K c #4383B8", +"L c #7AC5F5", +"M c #1579AA", +"N c #0D80BB", +"O c #017CBD", +"P c #0077BD", +"Q c #0076BF", +"R c #4E7E88", +"S c #D88522", +"T c #CE8020", +"U c #C87B16", +"V c #407BAB", +"W c #4585B9", +"X c #F2993C", +"Y c #FFFB92", +"Z c #FFF793", +"` c #FFF797", +" . c #FFF69B", +".. c #FFF69E", +"+. c #E09647", +"@. c #FFF69A", +"#. c #F4CD46", +"$. c #F3CD49", +"%. c #F2CD4B", +"&. c #F1CD4B", +"*. c #D8954C", +"=. c #FFF69C", +"-. c #F6DA68", +";. c #F6DA6A", +">. c #F6DB6B", +",. c #D8974D", +"'. c #FFFA9F", +"). c #FFEE8A", +"!. c #FFEE8B", +"~. c #FFEF8C", +"{. c #FFEF8D", +"]. c #C78E48", +"^. c #D59548", +"/. c #D29042", +"(. c #D08D3D", +"_. c #CE8B37", +":. c #CC8732", +"<. c #C9852B", +" . + @ # @ $ @ ", +" + % % % % % % ", +" @ % & * = - = ", +" @ % ; > , ' ) ", +" ! ~ { % ] ^ / ( _ ", +" : < [ } | 1 2 3 4 5 6 7 ", +"! : 8 9 0 a b c d e f g h i j ", +"~ k l m n o p q f r r s g t u v ", +"w x y z A B b C D E F G H I J ", +" K L B M N O P Q R S T U ", +" V W X Y Z ` .....", +" +.@.#.$.%.&.&.", +" *.=.-.;.>.>.>.", +" ,.'.).!.~.{.{.", +" ].^./.(._.:.<.", +" "}; diff --git a/icons/mini_rotate.png b/icons/mini_rotate.png new file mode 100644 index 0000000000000000000000000000000000000000..aa65210eb07ee0e87f511a28e83a637def538a0f GIT binary patch literal 602 zcmV-g0;T`6pHR5;7E zlj%-cQ51!F4&J~xM61?D4NeiKN{NVy6X-Qqxk8=MfEX_jL}^8BK|~N7FhJC_i5-lo zIHJodz)CX1Y{)@S~!d8q1l+bMV!}{YL?7wC( z%edaW=F&F+ z($9?`K8YY%uR)_%0MQCxd3ndPa;Y~P?U+0ni$XZM7r6Hug|3%ZMP*Zkl*~_HJgCLk zA%$#B#@zrWY4GPt5fc}9icOq|ZdVP>t`f>G-FQBfO2-8VoE7L?C-B-QL8&<(Elc$< z9F9VNpaHd~Mzw{9XMM@!tpI_e9I`cn>D7RVpdQ8}3WkFbsCW7qu?h_iA<}x2LUHGS zH_L_8E5^i;Hs-n?bM4!dqv}ItRGh3xVBa~)+_!mXcGsfbDMZdlCbCp%NFPW!OYKP{ oAG`}3ZPvA c #58A34F", +", c #6DBF62", +"' c #8CCA82", +") c #ABD8A1", +"! c #A2D499", +"~ c #A6D59C", +"{ c #A4D49B", +"] c #9BD092", +"^ c #9ED196", +"/ c #79B871", +"( c #509947", +"_ c #85C77B", +": c #A9D7A0", +"< c #A0D197", +"[ c #81C077", +"} c #7EBC75", +"| c #97CC8E", +"1 c #9BCF93", +"2 c #98CE90", +"3 c #69AB61", +"4 c #6ABA5F", +"5 c #9DD194", +"6 c #A6D59D", +"7 c #5DAA53", +"8 c #59A650", +"9 c #56A14D", +"0 c #529C4A", +"a c #90C989", +"b c #8CC885", +"c c #84C07D", +"d c #43893C", +"e c #66B65C", +"f c #63B259", +"g c #60AE56", +"h c #5CA953", +"i c #4E9746", +"j c #6FAF67", +"k c #8FC988", +"l c #3E8438", +"m c #55A04C", +"n c #499142", +"o c #6AAB63", +"p c #8AC783", +"q c #88C582", +"r c #3A7E34", +"s c #549F4B", +"t c #509A48", +"u c #499141", +"v c #458C3E", +"w c #84C17C", +"x c #7EC177", +"y c #77B771", +"z c #367930", +"A c #539E4B", +"B c #6CAE63", +"C c #68AA60", +"D c #489040", +"E c #61A35A", +"F c #87C581", +"G c #85C47E", +"H c #82C27C", +"I c #54964E", +"J c #539D4A", +"K c #6AAD63", +"L c #8FC987", +"M c #8BC785", +"N c #89C682", +"O c #87C47F", +"P c #7CBF75", +"Q c #82C27B", +"R c #5B9D55", +"S c #31732C", +"T c #4E9846", +"U c #66A95F", +"V c #8BC683", +"W c #85C37E", +"X c #74B56D", +"Y c #52954D", +"Z c #468D3F", +"` c #5EA157", +" . c #5A9E55", +".. c #3B7F35", +"+. c #377B31", +"@. c #33762E", +"#. c #3E8337", +" ", +" ", +" . + @ # ", +" $ % & * = - ; > ", +" , ' ) ! ~ { ] ^ / ( ", +" _ : = < [ } | 1 2 3 ", +" 4 5 6 1 7 8 9 0 a b c d ", +" e f g h i j k b l ", +" m n o p q r ", +" s t u v w x y z ", +" A B C D E F G H I ", +" J K L M N O P Q R S ", +" T U V F W H X Y S ", +" Z ` ...+.@. ", +" #.r ", +" z "}; diff --git a/icons/mini_select.png b/icons/mini_select.png new file mode 100644 index 0000000000000000000000000000000000000000..96bc076b413e0b2a73ee02cf466977929c4e3d13 GIT binary patch literal 2140 zcmb_dTWB0r7@i2GF&e2T7!`DwP%+w>IWs#uyEA4Rlik=XbkikWng~LB_RN{xAv+gm zCfQ9y5JkmWpY%bBK1jg}M6LQ*(9lvb4=NEKR4gg@q}JNHFA75ZXK$u$l7`^2GjlHA z`Ty^~o&V+h#QwhCdwUs%>C291CgHm~dV0Fy{Xl&U!{-)n{E2{JZoM;lx|kDh_A|_` z$E?D1IGsD76W127;TEY-vpqmF%+PSn!(@hrY>}2MC&m47`g4x8j1)H&&!L=`re$k< z!Ka57CJJO>hG+&iypJ8K=^((SA!ciK#R>FUifhQ#VH_=s9NU0|GbwH)Qpir{@@(4m zDXR*ICkV-GLK7raQB<^-m641@6c;6#msA}ox|CpBKMu6{hN(|x9&hP_S&A!%p{I*t zwOSRbF~RjqqNHh>h-6Wgc|h>Nyc6OY?*s#F2^ks?-||Asb=XKEF1oW}iUX!i6Kt;| z)(Ki}0*8q;?1_?qB9j_GgLH7-tY2v;H;70p)TT}t09NW?y|Np+LD}6zbZ7f21>o9T zuA^f^F1FoK5rkuNU`ER!8=`~4yhp`J8o0AQp<{DEb0D(D)6+i1q3ai1x6%$&zD=2x zB|&B%nz9_jtp>|*QJv*~o+cTKAT8^PrMQ8qi4 zRwYeUd0CJebaOd9>jWWo2+d|v95_d?EJIHwshprR&YMYU@>Ek49vdd%Q9O|(T8tDG zS#F=txMVg;f%bU=&L`q3K{18$$V?XbBvw=&B*tN6XmN~+M4~{n5pn&XZ$Sy-%8ung zsr=`Pwv-XDD1aCTtwI{brPioo?TgIZF3lk^sv0=NHb+fC;?^3QmW^8xgZY-;L-eT* z1GbUAIwnzBrZ^JiBQ?0zvb8}(w&&5N*lL-A&@J+`2@6~^tYV*zlpuOHtOIc~@&TUP zn!2hHQ-$!u{ik7Gi75tORO6VJig8842y2EBZ<~HSbyIaN?(d{wIG}Dxcchqn>k6|IJ61 zj>h`#c!iQ~?DhH5ud|Q-^7?A^>(cn(a_qsS@U1WFdrqzne)?mI`RvkHFD}0~6~Aq8 z&+``^KJVmy`?DC7?)h%D>!qLTAKm}^;pN@TYkz0&dt`w5R#~|{|IQn|XRjQNrk@;G z>!Qcrzp(JMy?C5CwRmjqS@~SyvYCjc-o>8b<6W1}{`Kzpk53+aVW@tS^v}%j5oYyL P)c><%6PXW3k3RP=F#5Lp literal 0 HcmV?d00001 diff --git a/icons/mini_select.xpm b/icons/mini_select.xpm new file mode 100644 index 00000000..1721af19 --- /dev/null +++ b/icons/mini_select.xpm @@ -0,0 +1,33 @@ +/* XPM */ +static const char *mini_select_xpm[] = { +"16 16 14 1", +" c None", +". c #8AA4F1", +"+ c #6587ED", +"@ c #C2CFF8", +"# c #5D7FE4", +"$ c #4567CC", +"% c #395BBE", +"& c #2648AC", +"* c #2244AB", +"= c #2749B8", +"- c #2D4FC5", +"; c #3C5EDF", +"> c #5C70C0", +", c #4163E9", +" ", +" .+@++@++@++@+. ", +" #@@@@@@@@@@@@# ", +" @@@@@@@@@@@@@@ ", +" $@@@@@@@@@@@@$ ", +" %@@@@@@@@@@@@% ", +" @@@@@@@@@@@@@@ ", +" &@@@@@@@@@@@@& ", +" *@@@@@@@@@@@@* ", +" @@@@@@@@@@@@@@ ", +" =@@@@@@@@@@@@= ", +" -@@@@@@@@@@@@- ", +" @@@@@@@@@@@@@@ ", +" ;@@@@@@@@@@@@; ", +" >,@,,@,,@,,@,> ", +" "}; diff --git a/icons/mini_switch.png b/icons/mini_switch.png new file mode 100644 index 0000000000000000000000000000000000000000..ab3dd3021d249143db2c59fdb8b84b72b1a4cbb7 GIT binary patch literal 877 zcmV-z1CsoSP)hadrQ+My~I{) zyrdVbwANN5QY&huDhgU?!Qz7tKJ`H?6#6Fw9~142f&~A$Obj4|1knr@T_OJA3C@7y)Zv~+L=evrb460nahyKfw>q|6 z!|-OkUF(83pL`j@m_iZ>uhVe+Ky7_mx6SW~T>Z?vwgY(&kq{6CcB;AFTeI5dE_W%S zO8`MkBq$u|SQ8w7IzNO75)yw4DnJ|)RG(W>_q0}eAH4W7>~V{My*vDCObW719WcQ` z4IH4AGoLS9Q9>cYHzuM|z+YBYTUF|d%x6|vIit06XP`{iY*CbeeU2r*MPfgb zdX}0!-Oa%p_ddQxK`)51d{<~Y`+@7Q5#M@fRi$gYwwyWE(o|ciDym{L%X#}LHoKI} zJ`xBS!3tgGr}AJ~RYQ`ZfRsrlE%b%aJDN^d<9>fdNt_8vCZ$0(wvdU(wJ?#SK@7H$ zcMj2jhlOY^2OK1wOe%=&S}Ju>DG?j=x;oD!RY5l>T}bI!uh07xg9b33SE>V1jS2Qs z!vKAG8AN$Y-zBf7WU#tvLtDDNJrH3oQbkNV@$!RiY}!062G&U~!LFiOHfR|+wy%G8 zV|X&mlTgN3R46@h_0^Hn{lVL51xze$wQZPm;?WO+Kh?trmKFtq|Y*VI^UuJyYuPnnV<5@DFk zU;wmOMnUWu8Nutcqa8=QM}@DGRQR>(E&=duYDDpNp`X9M96{C(oNSDZhUSnrj^aKR zgr=i7L4SJQnZ5nj49G3Lzis56FK`kw<81oYV|#ImH(>!XA2@`o2(`F#zqpcsbPgYc zTxyoR8RPSkK^Q9uNRcT015(7wVtg c #83D0F9", +", c #84D0FA", +"' c #75C1F6", +") c #81CDF8", +"! c #338ED9", +"~ c #92DEFE", +"{ c #82CEFB", +"] c #7DC9F9", +"^ c #80CDF8", +"/ c #3C96DC", +"( c #4097DB", +"_ c #7ECBF7", +": c #79C5F7", +"< c #78C4F6", +"[ c #7ECAF8", +"} c #7FCBF8", +"| c #6FBBF2", +"1 c #7AC6F6", +"2 c #2E87D2", +"3 c #4099DE", +"4 c #60B4EA", +"5 c #79C6F5", +"6 c #5CAAE8", +"7 c #388ED3", +"8 c #76C4F3", +"9 c #73BFF4", +"0 c #76C3F4", +"a c #54A6E0", +"b c #3389D0", +"c c #287FCA", +"d c #76C2F4", +"e c #4298DA", +"f c #3689CD", +"g c #61B0E6", +"h c #68B6ED", +"i c #65B4E9", +"j c #3589CC", +"k c #2277C2", +"l c #2073BE", +"m c #3B8ECE", +"n c #4CAEE7", +"o c #3FA5E1", +"p c #3588CA", +"q c #1666B1", +"r c #267CC1", +"s c #30AFEF", +"t c #1BA8EE", +"u c #349CDB", +"v c #1E77BF", +"w c #2E86CC", +"x c #0F5EA9", +"y c #1F6EB5", +"z c #2F91D1", +"A c #1CB6F9", +"B c #05B0FC", +"C c #22AEF0", +"D c #176FB8", +"E c #1199E3", +"F c #22AFF3", +"G c #2A94D7", +"H c #1F78C1", +"I c #1C6EB9", +"J c #5EC8F8", +"K c #0B58A3", +"L c #54C2F9", +"M c #08B4FF", +"N c #03B3FF", +"O c #18B0F6", +"P c #126BB4", +"Q c #1469B2", +"R c #1BB1F6", +"S c #05B2FE", +"T c #07B3FE", +"U c #14B8FE", +"V c #22BCFE", +"W c #02B1FE", +"X c #33C1FE", +"Y c #06529D", +"Z c #2CBBFA", +"` c #1AA9ED", +" . c #1888CD", +".. c #0959A4", +"+. c #1166B0", +"@. c #188DD4", +"#. c #13A7EF", +"$. c #10B4FB", +"%. c #1ABAFF", +"&. c #00B2FF", +"*. c #2ABFFF", +"=. c #105FAA", +"-. c #034E99", +";. c #024D98", +">. c #28BEFF", +" . ", +" + + ", +" . . @ @ @ @ # @ ", +"+ $ % & * = - ; > , ' ) ! ", +"@ ~ { ] ^ / ( _ : < [ } | 1 2 ", +" 3 4 5 6 7 8 9 0 a b c d c ", +" e f g h i j k k k ", +" l m n o p l ", +" q r s t u v w k k ", +"x y z A B C D E F G H I J I ", +"K L M N O P Q R S T U V W X q ", +"Y Z ` ... +.@.#.$.%.&.*.=. ", +"-.;.;.;. K K >.K ", +" Y Y ", +" ", +" "}; diff --git a/icons/mini_unselect.png b/icons/mini_unselect.png new file mode 100644 index 0000000000000000000000000000000000000000..ee87370b1efb75afe9847d0f78685b0ba8edf6d7 GIT binary patch literal 2142 zcmb_eU1%It6rLD}HElt#(5TdolUA%aGk1P>XUrts?5^E~ZW_~tMi832Gk14~?9Plc zlk8?uY6?vi@kK;R(LPo1sSkOrV5|iV`qn;)pi=Nj)KXE=*!9f*nYL*ff){4z&b{9~ z=R1G*>|2u)M|KZBF-TF=?rbJC1@A|rXU72i?!VQ<@Os3{yc|%}&c~vsk2?Rs5Jf$F z*v?Of)48L%=~g*xxdp=2s~(^!YGkbLVRM#*bb*v?$6$WB{3%1*mcg7*awz8|N!iXc zd~&=okvAK&re-l?qx48!2LV+QV!B?fIDuX_n3h}}=Fu|G&@D(fYcPpOAw8X&q?4{s zXq7{(iI7OgG)_=uSw+v&A`%gg6kZTnLDiA03o*Jg7|`ZhMSUvuVn-Kz8B940J)P%k zwHjBGIM*-nf~ILa5_wT%0l@|fPKfKQ6AX7Hq)1@;winv2Lq`&E!JP{Y2AH-@sCqrI zPS9}^IE=4jj~6%;nbZPWW)J7h`IVM(%j8LgREZM?fE9XJuk40yPex6%#NWS256 z3YUUs141zmR(%93mVG{qOOR# zq}&08l(BG#9|*Qgz3BQ?3Y@(CC2HNe*$(xNTg@_d zN(AnBp4q-JTdRx><8bdK@c$XpO44?Q@pmU*Yj0f}=w>qXmT1~*YVgr(i^Ksx`Ox%~ z+p8Z!!@QbJCGzoi%(Z57tpDH}XBHP1f4H{vbMw@N?~32gze)aV%n1E366)I*pX)z) z_|Wi;X0!SDh2OvUXYb9-!POsQFBGNBUheeJuebif%WI!qvcLNB>dMNBM-tNNdE7WR z1Y`8|+vCf9$hdy<%KJ-u-c>&T4G9RLwdNmZt^S$D$2ZRO@4NU>pJg1~1>=)fDhHmV zt|j;JBPU-dhOfEV|)I7`tn0pcD_eZTDo%T>m3Ka QiT(j((-Wyn<1?rK1=TXLFaQ7m literal 0 HcmV?d00001 diff --git a/icons/mini_unselect.xpm b/icons/mini_unselect.xpm new file mode 100644 index 00000000..0193895a --- /dev/null +++ b/icons/mini_unselect.xpm @@ -0,0 +1,33 @@ +/* XPM */ +static const char *mini_unselect_xpm[] = { +"16 16 14 1", +" c None", +". c #F1AF8A", +"+ c #ED9665", +"@ c #F8D6C2", +"# c #E48E5D", +"$ c #CC7645", +"% c #BE6939", +"& c #AC5626", +"* c #AB5422", +"= c #B85E27", +"- c #C5682D", +"; c #DF7E3C", +"> c #C0855C", +", c #E98641", +" ", +" .+@++@++@++@+. ", +" #@@@@@@@@@@@@# ", +" @@@@@@@@@@@@@@ ", +" $@@@@@@@@@@@@$ ", +" %@@@@@@@@@@@@% ", +" @@@@@@@@@@@@@@ ", +" &@@@@@@@@@@@@& ", +" *@@@@@@@@@@@@* ", +" @@@@@@@@@@@@@@ ", +" =@@@@@@@@@@@@= ", +" -@@@@@@@@@@@@- ", +" @@@@@@@@@@@@@@ ", +" ;@@@@@@@@@@@@; ", +" >,@,,@,,@,,@,> ", +" "}; diff --git a/icons/moveable.png b/icons/moveable.png new file mode 100644 index 0000000000000000000000000000000000000000..9310e716c9c0010697740be9a6b0241c9f69185f GIT binary patch literal 377 zcmV-<0fzpGP)-~G$W z;z;Izv#yY(luFb3H*@GS#*`LfSSJ9pl>kJfoKAlsDgk5%4YL1-ZQJTNj$pO`3<%A8 ze`vq8Ryp@6QwV+g0gfx6MU3%q4zwAA5DwT5P&=W%bpJXdjp%q!>C4jb3++5Jv)X z*acUK5Jf?9z$y`P2aNf8-XZ`qrDr?7&p6RthPCE<#_e68?c-cN!~)uyb1)*})H?{) z)|}S8?YqQ*N~FzKy{YBx_foKCPcQf=c@Zxf{PaFR=fq6rh@sPPrshioti-ebj+Ihx X1KGi3u1z9u00000NkvXXu0mjfY$KqZ literal 0 HcmV?d00001 diff --git a/icons/moveable.xpm b/icons/moveable.xpm new file mode 100644 index 00000000..49cd9a83 --- /dev/null +++ b/icons/moveable.xpm @@ -0,0 +1,43 @@ +/* XPM */ +static const char *moveable_xpm[] = { +/* columns rows colors chars-per-pixel */ +"32 32 5 1 ", +" c #010101", +". c gray2", +"X c magenta", +"o c #FBFBFB", +"O c white", +/* pixels */ +"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", +"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", +"XXXXXXXXXXXXXXXX XXXXXXXXXXXXXX", +"XXXXXXXXXXXXXX OO .XXXXXXXXXXX", +"XXXXXXXXXXX OOOOOO XXXXXXXXX", +"XXXXXXXXXX OOOOOOOOOOOO XXXXXXXX", +"XXXXXXXXXX OOOOOOOO XXXXXXXX", +"XXXXXXXXXX OO OOOO Oo XXXXXXXX", +"XXXXXXXXXX OOOO OOOO XXXXXXXX", +"XXXXXXXXXX OOOOOO OOOOO XXXXXXXX", +"XXXXXXXXXX OOOOOO OOOOO XXXXXXXX", +"XXXXXXXXXX OOOOOO OOOOO XXXXXXXX", +"XXXXXXXXXX OOOOOO OOOOO XXXXXXXX", +"XXXXXXXXXXX OOOO OOO XXXXXXXXX", +"XXXXXXXXXXXXX OO O XXXXXXXXXXX", +"XXXXXXXXXXXXXXX XXXXXXXXXXXXX", +"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", +"XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX", +"XXXXXXXXXXXX O XXXXXXXXXXXXXXXXX", +"XXXXXXXXXXX OOO XXXXXXXXXXXXXXXX", +"XXXXXXXXXXX O XXXXXXXXXXXXXXXX", +"XXXXXXXXX XX O XX XXXXXXXXXXXXXX", +"XXXXXXXX O OOO O XXXXXXXXXXXXX", +"XXXXXXX OOOOOOOOOOO XXXXXXXXXXXX", +"XXXXXXXX O OOO O XXXXXXXXXXXXX", +"XXXXXXXXX XX O XX XXXXXXXXXXXXXX", +"XXXXXXXXXXXX O XXXXXXXXXXXXXXXXX", +"XXXXXXXXXXX OOO XXXXXXXXXXXXXXXX", +"XXXXXXXXXXXX O XXXXXXXXXXXXXXXXX", +"XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX", +"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", +"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +}; diff --git a/icons/pickupable.png b/icons/pickupable.png new file mode 100644 index 0000000000000000000000000000000000000000..98b9ec8f9fd5086db7cc8155e2b3d2be5adf1cf0 GIT binary patch literal 474 zcmV<00VV#4P)xk?)4jRL7j~vg&aip40}W+PhhR5w`PH>e44;xf))UTT%yr!5oK(P)oNXjIgM45TSzcFO zLwy^r-T-Yy61MKU^}eORTLkh8krPRUN<~b0a9l5KdM;l>`co|wyM$va1eWEDJ^(o^ z{L58P0%uaacAS*xgr#t*nvexNOyHBo#3Z5NR)@_{gS(q|eqh&mzwD4~)f})kqn>k> z!?O>*TD;^bTg9pyf_J(d9f>#3bE^GvzrF<~0V&bDg$7DNF-=M*WRU|hR=jE3HWLJE za7w=4JaFYkz|*``z>=F|t{q;n8u&?pTC4$#dEMDYL(>9J@1+8Bn2Qev2IEf1vh(*} z&syLG0Xmcb34Fmwdp@7^cs%~fY{&7aRc`^Lx4s2?l3q2l5&}SfRBRi> z>0!-Y05EQ`cYr6qBi%45aRWGPs2kn|PDJzru9jPYwJn0D00000NkvXXu0mjf$DRHx literal 0 HcmV?d00001 diff --git a/icons/pickupable_moveable.xpm b/icons/pickupable_moveable.xpm new file mode 100644 index 00000000..0df86bcc --- /dev/null +++ b/icons/pickupable_moveable.xpm @@ -0,0 +1,44 @@ +/* XPM */ +static const char *pickupable_moveable_xpm[] = { +/* columns rows colors chars-per-pixel */ +"32 32 6 1 ", +" c #010101", +". c gray1", +"X c #040404", +"o c magenta", +"O c #FBFBFB", +"+ c white", +/* pixels */ +"oooooooooooooooooooooooooooooooo", +"oooooooooooooooooooooooooooooooo", +"oooooooooooooooooooooo oooooooo", +"oooooooo ooooooooooo ++ Xooooo", +"ooooooo + ooooooo ++++++ Xooo", +"oooooo +++ ooooo ++++++++++++ oo", +"oooooo + ooooo +++++++O oo", +"oooo oo + oo ooo ++ ++++ +O oo", +"ooo + +++ + oo ++++ ++++ oo", +"oo +++++++++++ o ++++++ +++++ oo", +"ooo + +++ + oo ++++++ +++++ oo", +"oooo oo + oo ooo ++++++ +++++ oo", +"ooooooo + oooooo ++++++ +++++ oo", +"oooooo +++ oooooo ++++ +++ ooo", +"ooooooo + ooooooooo ++ + ooooo", +"oooooooo oooooooooooo ooooooo", +"ooooooooooooooooooooooooooo ooo", +"oooooooooo ooooooooooo ++ oo", +"ooooooooo +O+++ ooo +++ oo", +"oooooooo +++++++++++++ X +++ ooo", +"ooooo ++++++++++++++ ++++ oooo", +"oooo ++ O++++++ ++++ ooooo", +"ooo ++++ +++++++++++++++ oooooo", +"oo ++++++ +++++++++++++ ooooooo", +"ooo ++++++ + oooooooo", +"oooo O++++O oooooooooooooooooo", +"ooooo ++++++ ooooooooooooooooooo", +"oooooo +++++Xooooooooooooooooooo", +"ooooooo +++ oooooooooooooooooooo", +"oooooooo + ooooooooooooooooooooo", +"ooooooooo oooooooooooooooooooooo", +"oooooooooooooooooooooooooooooooo" +}; diff --git a/icons/spawns.png b/icons/spawns.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f19a34edb7f8348c38019a9c4c751608521126 GIT binary patch literal 778 zcmV+l1NHogP)*BNEZ>6J|HVy)U<{mC@TKr?SyPB81D*_?VN|v`J$*B*4jIy z)CVNF-dZkFjrTWW^0^?J3bI5n8wsBAt#%E|ZEJ7kQUpxzm0HjL>sMm(1nM1?1$Hsn1|`<7#=N;W@{0D^GU1JYO=fzxaeu5*P}G1R-pq-k36HtpjFQW4DFVLy z>)mRK`SM^)DFZ<<0(z|Sy%GtR_hucm`W$N`pYJ7zoMJ5g4e5*^Cnw`6U!7k2P@4iX zWD=k5CImgz&RC?yHk3_BreQQ0GGdp6AuqU5E5b}cqX135el4bVW*Lzjwf)kl=mXL4 zkRiX80{$>32x{uUCsLazFk*sO;)#I7idA9?t&INT~2MBhFAgk3qMK=GFgN8ga7~l07*qo IM6N<$f-#0^cK`qY literal 0 HcmV?d00001 diff --git a/icons/spawns.xpm b/icons/spawns.xpm new file mode 100644 index 00000000..5eb324fa --- /dev/null +++ b/icons/spawns.xpm @@ -0,0 +1,92 @@ +/* XPM */ +static const char *spawns_xpm[] = { +/* columns rows colors chars-per-pixel */ +"32 32 54 1 ", +" c black", +". c #4B0078", +"X c #4E007C", +"o c DimGray", +"O c #520083", +"+ c #550088", +"@ c #58008C", +"# c #5B0091", +"$ c #5E0097", +"% c #5F0098", +"& c #60009A", +"* c #63009E", +"= c #6500A1", +"- c #6700A5", +"; c #6E00B0", +": c #7300B8", +"> c #7700BF", +", c #7A00C3", +"< c #7A00C4", +"1 c #7C00C7", +"2 c #7E00C9", +"3 c #8300D2", +"4 c #8400D3", +"5 c #8400D4", +"6 c #8700D8", +"7 c #8800DA", +"8 c #8D00E1", +"9 c #9100E8", +"0 c #9702F0", +"q c #9805F0", +"w c #9B0CF1", +"e c #9D10F1", +"r c #9E14F1", +"t c #A421F2", +"y c #A627F2", +"u c #A72AF2", +"i c #A82CF3", +"p c #A92FF3", +"a c #AA31F3", +"s c #AB34F3", +"d c #AE3BF3", +"f c #B03EF4", +"g c magenta", +"h c #B040F4", +"j c #B244F4", +"k c #B346F4", +"l c #B54BF4", +"z c #B64DF5", +"x c #B751F5", +"c c #BA57F5", +"v c #BB5AF5", +"b c #BD5EF6", +"n c #BE61F6", +"m c white", +/* pixels */ +"gggggggggggggggggggggggggggggggg", +"ggggggggggggggg ggggggggggggggg", +"ggggggggggg oo ggggggggggg", +"ggggggggg ommmmmmmmo ggggggggg", +"ggggggg omm mmmmmm mmo ggggggg", +"gggggg ommmm mmmmmm mmmmo gggggg", +"ggggg ommmmm m m mmmmmo ggggg", +"gggg ommmmmm js mmmmmmo gggg", +"gggg mmmmmmm zhie mmmmmmm gggg", +"ggg ommmm mm lldt05 mm mmmmo ggg", +"ggg mm mm mm hhar8< mm mm mm ggg", +"gg omm mm mm duw6 mm mm mmo gg", +"gg mmm mm m m mm mmm gg", +"gg mmmm mmm jy mmm mmmm gg", +"gg mmmm m bvlie9 m mmmm gg", +"g ommmmmm nnvlae97 mmmmmmo g", +"g ommmmmmm bbbclaw972 mmmmmmmo g", +"gg mmmmmm vvcxjyq82: mmmmmm gg", +"gg mmmmm jlljfie81;*$ mmmmm gg", +"gg mmmm iiutrq4;&+X. mmmm gg", +"gg ommm m req96>=O.... m mmmo gg", +"ggg mm mmm 84,;%..... mmm mm ggg", +"ggg om mm 3:-#...... mm mo ggg", +"gggg mmm m =@...... m mmm gggg", +"gggg omm mmm .... mmm mmo gggg", +"ggggg om mmmm mmmm mo ggggg", +"gggggg ommmmmmmmmmmmmmmmo gggggg", +"ggggggg ommmmmmmmmmmmo ggggggg", +"ggggggggg ommmmmmmmo ggggggggg", +"ggggggggggg oo ggggggggggg", +"ggggggggggggggg ggggggggggggggg", +"gggggggggggggggggggggggggggggggg" +}; diff --git a/icons/toolbar_hooks.png b/icons/toolbar_hooks.png new file mode 100644 index 0000000000000000000000000000000000000000..4eb911dea1ce24cf6484d80924bf9aa8a2977fdb GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`J)SO(Ar`&8LD75-1{{lz{f^(s zwt42#J#Xgs*f}I{tMD@9GI%n`pUulHU&!TWbFweHXpVqT&K$qkRYnKZN}u>JO#Qsd z`PXHZ3$8!6=hyoL9DQ3?=&`}YsVkIU>8j#eE7O_p9$Cq~=zTQh+}%Ef!sD02+Ra_P vSGfIXej{ernDu*Vv4o@9+_QpH&%R;&$nCBe_8?yt=q?6NS3j3^P6bkPz>R)w*x7C-nw0^jED41PqQ`YX;m%s2yP1NOKFu!Cl@&8i33XpRd NJYD@<);T3K0RU>zSk?dl literal 0 HcmV?d00001 diff --git a/icons/toolbar_moveables.xpm b/icons/toolbar_moveables.xpm new file mode 100644 index 00000000..16d852e5 --- /dev/null +++ b/icons/toolbar_moveables.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static const char *toolbar_moveable_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 16 3 1 ", +" c None", +". c black", +"X c white", +/* pixels */ +" . ", +" .X. ", +" .XXX. ", +" .XXXXX. ", +" .X.XXX.X. ", +" .XX.X.XX. ", +" .X.XX.XX. ", +" .XXX.X.X. ", +" . .X. .X. ", +" .X..X..X. ", +" .XXXXXXXXX. ", +" .X..X..X. ", +" . .X. . ", +" .XXX. ", +" .X. ", +" . " +}; diff --git a/icons/toolbar_pickupables.png b/icons/toolbar_pickupables.png new file mode 100644 index 0000000000000000000000000000000000000000..7d246bf6a8cae5754f17e3262e324af50d79cc49 GIT binary patch literal 240 zcmVa?2V`Zk8||^NdWxRiGUsGBo4N3J}S^=ZQ2}xE!H^&-B?KlVn%-=0;#*aI}@dp z#$?=4`ztwT@v5~-j8V*S!SWQ?HoB`JP${LoPf83sD$vrYy2i$1A%~(1xSV qC$d4}qAcS7kzdX?62BzZBBCEYleOlY!j|3u0000 + + + + + + + + + + + + + + diff --git a/source/application.cpp b/source/application.cpp index 1926f39f..51310e02 100644 --- a/source/application.cpp +++ b/source/application.cpp @@ -606,6 +606,11 @@ void MainFrame::UpdateFloorMenu() menu_bar->UpdateFloorMenu(); } +void MainFrame::UpdateIndicatorsMenu() +{ + menu_bar->UpdateIndicatorsMenu(); +} + bool MainFrame::LoadMap(FileName name) { return g_gui.LoadMap(name); diff --git a/source/application.h b/source/application.h index eb43031b..5d62d3dc 100644 --- a/source/application.h +++ b/source/application.h @@ -85,6 +85,7 @@ class MainFrame : public wxFrame void OnUpdateMenus(wxCommandEvent& event); void UpdateFloorMenu(); + void UpdateIndicatorsMenu(); void OnIdle(wxIdleEvent& event); void OnExit(wxCloseEvent& event); diff --git a/source/artprovider.cpp b/source/artprovider.cpp index 830819ae..df715faa 100644 --- a/source/artprovider.cpp +++ b/source/artprovider.cpp @@ -37,6 +37,15 @@ #include "../icons/rectangular_5.xpm" #include "../icons/rectangular_6.xpm" #include "../icons/rectangular_7.xpm" +#include "../icons/toolbar_hooks.xpm" +#include "../icons/toolbar_pickupables.xpm" +#include "../icons/toolbar_moveables.xpm" + +#include "../icons/spawns.xpm" +#include "../icons/house_exit.xpm" +#include "../icons/pickupable.xpm" +#include "../icons/moveable.xpm" +#include "../icons/pickupable_moveable.xpm" wxBitmap ArtProvider::CreateBitmap(const wxArtID& id, const wxArtClient& client, const wxSize& WXUNUSED(size)) @@ -84,6 +93,23 @@ wxBitmap ArtProvider::CreateBitmap(const wxArtID& id, const wxArtClient& client, return wxBitmap(rectangular_6_xpm); else if (id == ART_RECTANGULAR_7) return wxBitmap(rectangular_7_xpm); + else if (id == ART_HOOKS_TOOLBAR) + return wxBitmap(toolbar_hooks_xpm); + else if (id == ART_PICKUPABLE_TOOLBAR) + return wxBitmap(toolbar_pickupables_xpm); + else if (id == ART_MOVEABLE_TOOLBAR) + return wxBitmap(toolbar_moveable_xpm); + } else if (client == wxART_OTHER) { + if (id == ART_SPAWNS) + return wxBitmap(spawns_xpm); + else if (id == ART_HOUSE_EXIT) + return wxBitmap(house_exit_xpm); + else if (id == ART_PICKUPABLE) + return wxBitmap(pickupable_xpm); + else if (id == ART_MOVEABLE) + return wxBitmap(moveable_xpm); + else if (id == ART_PICKUPABLE_MOVEABLE) + return wxBitmap(pickupable_moveable_xpm); } return wxNullBitmap; diff --git a/source/artprovider.h b/source/artprovider.h index 551c27ca..0113c2a4 100644 --- a/source/artprovider.h +++ b/source/artprovider.h @@ -42,6 +42,16 @@ #define ART_RECTANGULAR_6 wxART_MAKE_ART_ID(ART_RECTANGULAR_6) #define ART_RECTANGULAR_7 wxART_MAKE_ART_ID(ART_RECTANGULAR_7) +#define ART_HOOKS_TOOLBAR wxART_MAKE_ART_ID(ART_HOOKS_TOOLBAR) +#define ART_PICKUPABLE_TOOLBAR wxART_MAKE_ART_ID(ART_PICKUPABLE_TOOLBAR) +#define ART_MOVEABLE_TOOLBAR wxART_MAKE_ART_ID(ART_MOVEABLE_TOOLBAR) + +#define ART_SPAWNS wxART_MAKE_ART_ID(ART_SPAWNS) +#define ART_HOUSE_EXIT wxART_MAKE_ART_ID(ART_HOUSE_EXIT) +#define ART_PICKUPABLE wxART_MAKE_ART_ID(ART_PICKUPABLE) +#define ART_MOVEABLE wxART_MAKE_ART_ID(ART_MOVEABLE) +#define ART_PICKUPABLE_MOVEABLE wxART_MAKE_ART_ID(ART_PICKUPABLE_MOVEABLE) + class ArtProvider : public wxArtProvider { protected: diff --git a/source/graphics.cpp b/source/graphics.cpp index 02f5754f..2e299ed6 100644 --- a/source/graphics.cpp +++ b/source/graphics.cpp @@ -20,6 +20,7 @@ #include "sprites.h" #include "graphics.h" +#include "artprovider.h" #include "filehandle.h" #include "settings.h" #include "gui.h" @@ -28,6 +29,7 @@ #include #include #include +#include #include "pngfiles.h" // All 133 template colors @@ -161,6 +163,19 @@ GameSprite* GraphicManager::getCreatureSprite(int id) return nullptr; } +GameSprite* GraphicManager::getEditorSprite(int id) +{ + if(id >= 0) { + return nullptr; + } + + SpriteMap::iterator it = sprite_space.find(id); + if(it != sprite_space.end()) { + return dynamic_cast(it->second); + } + return nullptr; +} + uint16_t GraphicManager::getItemSpriteMaxID() const { return item_count; @@ -332,6 +347,12 @@ bool GraphicManager::loadEditorSprites() nullptr ); + sprite_space[EDITOR_SPRITE_SPAWNS] = GameSprite::createFromBitmap(ART_SPAWNS); + sprite_space[EDITOR_SPRITE_HOUSE_EXIT] = GameSprite::createFromBitmap(ART_HOUSE_EXIT); + sprite_space[EDITOR_SPRITE_PICKUPABLE_ITEM] = GameSprite::createFromBitmap(ART_PICKUPABLE); + sprite_space[EDITOR_SPRITE_MOVEABLE_ITEM] = GameSprite::createFromBitmap(ART_MOVEABLE); + sprite_space[EDITOR_SPRITE_PICKUPABLE_MOVEABLE_ITEM] = GameSprite::createFromBitmap(ART_PICKUPABLE_MOVEABLE); + return true; } @@ -997,7 +1018,7 @@ GameSprite::Image::~Image() unloadGLTexture(0); } -void GameSprite::Image::createGLTexture(GLuint whatid) +void GameSprite::Image::createGLTexture(GLuint textureId) { ASSERT(!isGLLoaded); @@ -1009,7 +1030,7 @@ void GameSprite::Image::createGLTexture(GLuint whatid) isGLLoaded = true; g_gui.gfx.loaded_textures += 1; - glBindTexture(GL_TEXTURE_2D, whatid); + glBindTexture(GL_TEXTURE_2D, textureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Linear Filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 0x812F); // GL_CLAMP_TO_EDGE @@ -1017,14 +1038,13 @@ void GameSprite::Image::createGLTexture(GLuint whatid) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SPRITE_PIXELS, SPRITE_PIXELS, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba); delete[] rgba; - #undef SPRITE_SIZE } -void GameSprite::Image::unloadGLTexture(GLuint whatid) +void GameSprite::Image::unloadGLTexture(GLuint textureId) { isGLLoaded = false; g_gui.gfx.loaded_textures -= 1; - glDeleteTextures(1, &whatid); + glDeleteTextures(1, &textureId); } void GameSprite::Image::visit() @@ -1177,12 +1197,75 @@ GLuint GameSprite::NormalImage::getHardwareID() return id; } -void GameSprite::NormalImage::createGLTexture(GLuint ignored) +void GameSprite::NormalImage::createGLTexture(GLuint textureId) { Image::createGLTexture(id); } -void GameSprite::NormalImage::unloadGLTexture(GLuint ignored) +void GameSprite::NormalImage::unloadGLTexture(GLuint textureId) +{ + Image::unloadGLTexture(id); +} + +GameSprite::EditorImage::EditorImage(const wxArtID& bitmapId) : + NormalImage(), + bitmapId(bitmapId) +{ } + +void GameSprite::EditorImage::createGLTexture(GLuint textureId) +{ + ASSERT(!isGLLoaded); + + wxSize size(SPRITE_PIXELS, SPRITE_PIXELS); + wxBitmap bitmap = wxArtProvider::GetBitmap(bitmapId, wxART_OTHER, size); + + wxNativePixelData data(bitmap); + if (!data) return; + + const int imageSize = SPRITE_PIXELS_SIZE * 4; + GLubyte *imageData = new GLubyte[imageSize]; + int write = 0; + + wxNativePixelData::Iterator it(data); + it.Offset(data, 0, 0); + + for (size_t y = 0; y < SPRITE_PIXELS; ++y) + { + wxNativePixelData::Iterator row_start = it; + + for(size_t x = 0; x < SPRITE_PIXELS; ++x, it++) + { + uint8_t red = it.Red(); + uint8_t green = it.Green(); + uint8_t blue = it.Blue(); + bool transparent = red == 0xFF && green == 0x00 && blue == 0xFF; + + imageData[write + 0] = red; + imageData[write + 1] = green; + imageData[write + 2] = blue; + imageData[write + 3] = transparent ? 0x00 : 0xFF; + write += 4; + } + + it = row_start; + it.OffsetY(data, 1); + } + + isGLLoaded = true; + id = g_gui.gfx.getFreeTextureID(); + g_gui.gfx.loaded_textures += 1; + + glBindTexture(GL_TEXTURE_2D, id); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Linear Filtering + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 0x812F); // GL_CLAMP_TO_EDGE + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 0x812F); // GL_CLAMP_TO_EDGE + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SPRITE_PIXELS, SPRITE_PIXELS, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData); + + delete[] imageData; +} + +void GameSprite::EditorImage::unloadGLTexture(GLuint textureId) { Image::unloadGLTexture(id); } @@ -1343,6 +1426,23 @@ void GameSprite::TemplateImage::unloadGLTexture(GLuint unused) Image::unloadGLTexture(gl_tid); } +GameSprite* GameSprite::createFromBitmap(const wxArtID& bitmapId) +{ + GameSprite::EditorImage* image = new GameSprite::EditorImage(bitmapId); + + GameSprite* sprite = new GameSprite(); + sprite->width = 1; + sprite->height = 1; + sprite->layers = 1; + sprite->pattern_x = 1; + sprite->pattern_y = 1; + sprite->pattern_z = 1; + sprite->frames = 1; + sprite->numsprites = 1; + sprite->spriteList.push_back(image); + return sprite; +} + // ============================================================================ // Animator diff --git a/source/graphics.h b/source/graphics.h index 4fce360a..a8654eca 100644 --- a/source/graphics.h +++ b/source/graphics.h @@ -23,6 +23,7 @@ #include #include "client_version.h" +#include enum SpriteSize { SPRITE_SIZE_16x16, @@ -87,6 +88,8 @@ class GameSprite : public Sprite{ std::pair getDrawOffset() const; uint8_t getMiniMapColor() const; + static GameSprite* createFromBitmap(const wxArtID& bitmapId); + protected: class Image; class NormalImage; @@ -110,8 +113,8 @@ class GameSprite : public Sprite{ virtual uint8_t* getRGBData() = 0; virtual uint8_t* getRGBAData() = 0; protected: - virtual void createGLTexture(GLuint whatid); - virtual void unloadGLTexture(GLuint whatid); + virtual void createGLTexture(GLuint textureId); + virtual void unloadGLTexture(GLuint textureId); }; class NormalImage : public Image { @@ -132,8 +135,18 @@ class GameSprite : public Sprite{ virtual uint8_t* getRGBData(); virtual uint8_t* getRGBAData(); protected: - virtual void createGLTexture(GLuint ignored = 0); - virtual void unloadGLTexture(GLuint ignored = 0); + virtual void createGLTexture(GLuint textureId = 0); + virtual void unloadGLTexture(GLuint textureId = 0); + }; + + class EditorImage : public NormalImage { + public: + EditorImage(const wxArtID& bitmapId); + protected: + void createGLTexture(GLuint textureId) override; + void unloadGLTexture(GLuint textureId) override; + private: + wxArtID bitmapId; }; class TemplateImage : public Image { @@ -258,6 +271,7 @@ class GraphicManager Sprite* getSprite(int id); GameSprite* getCreatureSprite(int id); + GameSprite* getEditorSprite(int id); long getElapsedTime() const { return (animation_timer->TimeInMicro() / 1000).ToLong(); } @@ -318,6 +332,7 @@ class GraphicManager friend class GameSprite::Image; friend class GameSprite::NormalImage; + friend class GameSprite::EditorImage; friend class GameSprite::TemplateImage; }; diff --git a/source/gui.cpp b/source/gui.cpp index 0e3df86f..c0f35bce 100644 --- a/source/gui.cpp +++ b/source/gui.cpp @@ -1117,6 +1117,8 @@ void GUI::RefreshView() for(EditorTab* editorTab : editorTabs) { editorTab->GetWindow()->Refresh(); } + + root->GetAuiToolBar()->UpdateIndicators(); } void GUI::CreateLoadBar(wxString message, bool canCancel /* = false */ ) diff --git a/source/gui_ids.h b/source/gui_ids.h index 2fae8609..578ea753 100644 --- a/source/gui_ids.h +++ b/source/gui_ids.h @@ -183,14 +183,18 @@ enum EditorActionID TOOLBAR_SIZES_4, TOOLBAR_SIZES_5, TOOLBAR_SIZES_6, - TOOLBAR_SIZES_7 + TOOLBAR_SIZES_7, + TOOLBAR_HOOKS, + TOOLBAR_PICKUPABLES, + TOOLBAR_MOVEABLES }; enum ToolBarID { TOOLBAR_STANDARD, TOOLBAR_BRUSHES, TOOLBAR_POSITION, - TOOLBAR_SIZES + TOOLBAR_SIZES, + TOOLBAR_INDICATORS, }; #endif diff --git a/source/main_menubar.cpp b/source/main_menubar.cpp index a8d5163e..982a2155 100644 --- a/source/main_menubar.cpp +++ b/source/main_menubar.cpp @@ -120,6 +120,7 @@ MainMenuBar::MainMenuBar(MainFrame *frame) : frame(frame) MAKE_ACTION(VIEW_TOOLBARS_BRUSHES, wxITEM_CHECK, OnToolbars); MAKE_ACTION(VIEW_TOOLBARS_POSITION, wxITEM_CHECK, OnToolbars); MAKE_ACTION(VIEW_TOOLBARS_SIZES, wxITEM_CHECK, OnToolbars); + MAKE_ACTION(VIEW_TOOLBARS_INDICATORS, wxITEM_CHECK, OnToolbars); MAKE_ACTION(VIEW_TOOLBARS_STANDARD, wxITEM_CHECK, OnToolbars); MAKE_ACTION(NEW_VIEW, wxITEM_NORMAL, OnNewView); MAKE_ACTION(TOGGLE_FULLSCREEN, wxITEM_NORMAL, OnToggleFullscreen); @@ -149,6 +150,8 @@ MainMenuBar::MainMenuBar(MainFrame *frame) : frame(frame) MAKE_ACTION(SHOW_TOOLTIPS, wxITEM_CHECK, OnChangeViewSettings); MAKE_ACTION(SHOW_PREVIEW, wxITEM_CHECK, OnChangeViewSettings); MAKE_ACTION(SHOW_WALL_HOOKS, wxITEM_CHECK, OnChangeViewSettings); + MAKE_ACTION(SHOW_PICKUPABLES, wxITEM_CHECK, OnChangeViewSettings); + MAKE_ACTION(SHOW_MOVEABLES, wxITEM_CHECK, OnChangeViewSettings); MAKE_ACTION(WIN_MINIMAP, wxITEM_NORMAL, OnMinimapWindow); MAKE_ACTION(NEW_PALETTE, wxITEM_NORMAL, OnNewPalette); @@ -395,6 +398,7 @@ void MainMenuBar::Update() EnableItem(DEBUG_VIEW_DAT, loaded); UpdateFloorMenu(); + UpdateIndicatorsMenu(); } void MainMenuBar::LoadValues() @@ -404,6 +408,7 @@ void MainMenuBar::LoadValues() CheckItem(VIEW_TOOLBARS_BRUSHES, g_settings.getBoolean(Config::SHOW_TOOLBAR_BRUSHES)); CheckItem(VIEW_TOOLBARS_POSITION, g_settings.getBoolean(Config::SHOW_TOOLBAR_POSITION)); CheckItem(VIEW_TOOLBARS_SIZES, g_settings.getBoolean(Config::SHOW_TOOLBAR_SIZES)); + CheckItem(VIEW_TOOLBARS_INDICATORS, g_settings.getBoolean(Config::SHOW_TOOLBAR_INDICATORS)); CheckItem(VIEW_TOOLBARS_STANDARD, g_settings.getBoolean(Config::SHOW_TOOLBAR_STANDARD)); CheckItem(SELECT_MODE_COMPENSATE, g_settings.getBoolean(Config::COMPENSATED_SELECT)); @@ -451,6 +456,8 @@ void MainMenuBar::LoadValues() CheckItem(SHOW_TOOLTIPS, g_settings.getBoolean(Config::SHOW_TOOLTIPS)); CheckItem(SHOW_PREVIEW, g_settings.getBoolean(Config::SHOW_PREVIEW)); CheckItem(SHOW_WALL_HOOKS, g_settings.getBoolean(Config::SHOW_WALL_HOOKS)); + CheckItem(SHOW_PICKUPABLES, g_settings.getBoolean(Config::SHOW_PICKUPABLES)); + CheckItem(SHOW_MOVEABLES, g_settings.getBoolean(Config::SHOW_MOVEABLES)); } void MainMenuBar::LoadRecentFiles() @@ -479,11 +486,29 @@ std::vector MainMenuBar::GetRecentFiles() void MainMenuBar::UpdateFloorMenu() { - if(g_gui.IsEditorOpen()) { - for(int i = 0; i < MAP_LAYERS; ++i) - CheckItem(MenuBar::ActionID(MenuBar::FLOOR_0 + i), false); - CheckItem(MenuBar::ActionID(MenuBar::FLOOR_0 + g_gui.GetCurrentFloor()), true); + using namespace MenuBar; + + if(!g_gui.IsEditorOpen()) { + return; } + + for (int i = 0; i < MAP_LAYERS; ++i) + CheckItem(static_cast(MenuBar::FLOOR_0 + i), false); + + CheckItem(static_cast(MenuBar::FLOOR_0 + g_gui.GetCurrentFloor()), true); +} + +void MainMenuBar::UpdateIndicatorsMenu() +{ + using namespace MenuBar; + + if(!g_gui.IsEditorOpen()) { + return; + } + + CheckItem(SHOW_WALL_HOOKS, g_settings.getBoolean(Config::SHOW_WALL_HOOKS)); + CheckItem(SHOW_PICKUPABLES, g_settings.getBoolean(Config::SHOW_PICKUPABLES)); + CheckItem(SHOW_MOVEABLES, g_settings.getBoolean(Config::SHOW_MOVEABLES)); } bool MainMenuBar::Load(const FileName& path, wxArrayString& warnings, wxString& error) @@ -1751,6 +1776,10 @@ void MainMenuBar::OnToolbars(wxCommandEvent& event) g_gui.ShowToolbar(TOOLBAR_SIZES, event.IsChecked()); g_settings.setInteger(Config::SHOW_TOOLBAR_SIZES, event.IsChecked()); break; + case VIEW_TOOLBARS_INDICATORS: + g_gui.ShowToolbar(TOOLBAR_INDICATORS, event.IsChecked()); + g_settings.setInteger(Config::SHOW_TOOLBAR_INDICATORS, event.IsChecked()); + break; case VIEW_TOOLBARS_STANDARD: g_gui.ShowToolbar(TOOLBAR_STANDARD, event.IsChecked()); g_settings.setInteger(Config::SHOW_TOOLBAR_STANDARD, event.IsChecked()); @@ -1835,6 +1864,8 @@ void MainMenuBar::OnChangeViewSettings(wxCommandEvent& event) g_settings.setInteger(Config::SHOW_TOOLTIPS, IsItemChecked(MenuBar::SHOW_TOOLTIPS)); g_settings.setInteger(Config::SHOW_PREVIEW, IsItemChecked(MenuBar::SHOW_PREVIEW)); g_settings.setInteger(Config::SHOW_WALL_HOOKS, IsItemChecked(MenuBar::SHOW_WALL_HOOKS)); + g_settings.setInteger(Config::SHOW_PICKUPABLES, IsItemChecked(MenuBar::SHOW_PICKUPABLES)); + g_settings.setInteger(Config::SHOW_MOVEABLES, IsItemChecked(MenuBar::SHOW_MOVEABLES)); g_gui.RefreshView(); } diff --git a/source/main_menubar.h b/source/main_menubar.h index 9c0a9ec2..d83e0fb8 100644 --- a/source/main_menubar.h +++ b/source/main_menubar.h @@ -89,6 +89,7 @@ namespace MenuBar VIEW_TOOLBARS_BRUSHES, VIEW_TOOLBARS_POSITION, VIEW_TOOLBARS_SIZES, + VIEW_TOOLBARS_INDICATORS, VIEW_TOOLBARS_STANDARD, NEW_VIEW, TOGGLE_FULLSCREEN, @@ -116,6 +117,8 @@ namespace MenuBar SHOW_TOOLTIPS, SHOW_PREVIEW, SHOW_WALL_HOOKS, + SHOW_PICKUPABLES, + SHOW_MOVEABLES, WIN_MINIMAP, NEW_PALETTE, TAKE_SCREENSHOT, @@ -167,6 +170,7 @@ class MainMenuBar : public wxEvtHandler // Turn on/off all buttons according to current editor state void Update(); void UpdateFloorMenu(); // Only concerns the floor menu + void UpdateIndicatorsMenu(); void AddRecentFile(FileName file); void LoadRecentFiles(); diff --git a/source/main_toolbar.cpp b/source/main_toolbar.cpp index 3781d9a7..10bb572b 100644 --- a/source/main_toolbar.cpp +++ b/source/main_toolbar.cpp @@ -31,6 +31,7 @@ const wxString MainToolBar::STANDARD_BAR_NAME = "standard_toolbar"; const wxString MainToolBar::BRUSHES_BAR_NAME = "brushes_toolbar"; const wxString MainToolBar::POSITION_BAR_NAME = "position_toolbar"; const wxString MainToolBar::SIZES_BAR_NAME = "sizes_toolbar"; +const wxString MainToolBar::INDICATORS_BAR_NAME = "indicators_toolbar"; #define loadPNGFile(name) _wxGetBitmapFromMemory(name, sizeof(name)) inline wxBitmap* _wxGetBitmapFromMemory(const unsigned char* data, int length) @@ -145,10 +146,25 @@ MainToolBar::MainToolBar(wxWindow* parent, wxAuiManager* manager) sizes_toolbar->ToggleTool(TOOLBAR_SIZES_RECTANGULAR, true); sizes_toolbar->ToggleTool(TOOLBAR_SIZES_1, true); + wxBitmap hooks_bitmap = wxArtProvider::GetBitmap(ART_HOOKS_TOOLBAR, wxART_TOOLBAR, icon_size); + wxBitmap pickupables_bitmap = wxArtProvider::GetBitmap(ART_PICKUPABLE_TOOLBAR, wxART_TOOLBAR, icon_size); + wxBitmap moveables_bitmap = wxArtProvider::GetBitmap(ART_MOVEABLE_TOOLBAR, wxART_TOOLBAR, icon_size); + + indicators_toolbar = newd wxAuiToolBar(parent, TOOLBAR_INDICATORS, wxDefaultPosition, wxDefaultSize, wxAUI_TB_DEFAULT_STYLE); + indicators_toolbar->SetToolBitmapSize(icon_size); + indicators_toolbar->AddTool(TOOLBAR_HOOKS, wxEmptyString, hooks_bitmap, wxNullBitmap, wxITEM_CHECK, "Wall Hooks", wxEmptyString, NULL); + indicators_toolbar->AddTool(TOOLBAR_PICKUPABLES, wxEmptyString, pickupables_bitmap, wxNullBitmap, wxITEM_CHECK, "Pickupables", wxEmptyString, NULL); + indicators_toolbar->AddTool(TOOLBAR_MOVEABLES, wxEmptyString, moveables_bitmap, wxNullBitmap, wxITEM_CHECK, "Moveables", wxEmptyString, NULL); + indicators_toolbar->Realize(); + indicators_toolbar->ToggleTool(TOOLBAR_HOOKS, g_settings.getBoolean(Config::SHOW_WALL_HOOKS)); + indicators_toolbar->ToggleTool(TOOLBAR_PICKUPABLES, g_settings.getBoolean(Config::SHOW_PICKUPABLES)); + indicators_toolbar->ToggleTool(TOOLBAR_MOVEABLES, g_settings.getBoolean(Config::SHOW_MOVEABLES)); + manager->AddPane(standard_toolbar, wxAuiPaneInfo().Name(STANDARD_BAR_NAME).ToolbarPane().Top().Row(1).Position(1).Floatable(false)); manager->AddPane(brushes_toolbar, wxAuiPaneInfo().Name(BRUSHES_BAR_NAME).ToolbarPane().Top().Row(1).Position(2).Floatable(false)); manager->AddPane(position_toolbar, wxAuiPaneInfo().Name(POSITION_BAR_NAME).ToolbarPane().Top().Row(1).Position(4).Floatable(false)); manager->AddPane(sizes_toolbar, wxAuiPaneInfo().Name(SIZES_BAR_NAME).ToolbarPane().Top().Row(1).Position(3).Floatable(false)); + manager->AddPane(indicators_toolbar, wxAuiPaneInfo().Name(INDICATORS_BAR_NAME).ToolbarPane().Top().Row(1).Position(5).Floatable(false)); standard_toolbar->Bind(wxEVT_COMMAND_MENU_SELECTED, &MainToolBar::OnStandardButtonClick, this); brushes_toolbar->Bind(wxEVT_COMMAND_MENU_SELECTED, &MainToolBar::OnBrushesButtonClick, this); @@ -160,6 +176,7 @@ MainToolBar::MainToolBar(wxWindow* parent, wxAuiManager* manager) z_control->Bind(wxEVT_KEY_UP, &MainToolBar::OnPositionKeyUp, this); go_button->Bind(wxEVT_BUTTON, &MainToolBar::OnPositionButtonClick, this); sizes_toolbar->Bind(wxEVT_COMMAND_MENU_SELECTED, &MainToolBar::OnSizesButtonClick, this); + indicators_toolbar->Bind(wxEVT_COMMAND_MENU_SELECTED, &MainToolBar::OnIndicatorsButtonClick, this); HideAll(); } @@ -176,6 +193,7 @@ MainToolBar::~MainToolBar() z_control->Unbind(wxEVT_KEY_UP, &MainToolBar::OnPositionKeyUp, this); go_button->Unbind(wxEVT_BUTTON, &MainToolBar::OnPositionButtonClick, this); sizes_toolbar->Unbind(wxEVT_COMMAND_MENU_SELECTED, &MainToolBar::OnSizesButtonClick, this); + indicators_toolbar->Unbind(wxEVT_COMMAND_MENU_SELECTED, &MainToolBar::OnIndicatorsButtonClick, this); } void MainToolBar::UpdateButtons() @@ -266,6 +284,15 @@ void MainToolBar::UpdateBrushButtons() g_gui.GetAuiManager()->Update(); } +void MainToolBar::UpdateIndicators() +{ + indicators_toolbar->ToggleTool(TOOLBAR_HOOKS, g_settings.getBoolean(Config::SHOW_WALL_HOOKS)); + indicators_toolbar->ToggleTool(TOOLBAR_PICKUPABLES, g_settings.getBoolean(Config::SHOW_PICKUPABLES)); + indicators_toolbar->ToggleTool(TOOLBAR_MOVEABLES, g_settings.getBoolean(Config::SHOW_MOVEABLES)); + + g_gui.GetAuiManager()->Update(); +} + void MainToolBar::UpdateBrushSize(BrushShape shape, int size) { if (shape == BRUSHSHAPE_CIRCLE) { @@ -371,6 +398,14 @@ void MainToolBar::LoadPerspective() } else GetPane(TOOLBAR_SIZES).Hide(); + if (g_settings.getBoolean(Config::SHOW_TOOLBAR_INDICATORS)) { + std::string info = g_settings.getString(Config::TOOLBAR_INDICATORS_LAYOUT); + if (!info.empty()) + manager->LoadPaneInfo(wxString(info), GetPane(TOOLBAR_INDICATORS)); + GetPane(TOOLBAR_INDICATORS).Show(); + } else + GetPane(TOOLBAR_INDICATORS).Hide(); + manager->Update(); } @@ -399,6 +434,11 @@ void MainToolBar::SavePerspective() wxString info = manager->SavePaneInfo(GetPane(TOOLBAR_SIZES)); g_settings.setString(Config::TOOLBAR_SIZES_LAYOUT, info.ToStdString()); } + + if (g_settings.getBoolean(Config::SHOW_TOOLBAR_INDICATORS)) { + wxString info = manager->SavePaneInfo(GetPane(TOOLBAR_INDICATORS)); + g_settings.setString(Config::SHOW_TOOLBAR_INDICATORS, info.ToStdString()); + } } void MainToolBar::OnStandardButtonClick(wxCommandEvent& event) @@ -564,6 +604,27 @@ void MainToolBar::OnSizesButtonClick(wxCommandEvent& event) } } +void MainToolBar::OnIndicatorsButtonClick(wxCommandEvent& event) +{ + bool toggled = indicators_toolbar->GetToolToggled(event.GetId()); + switch (event.GetId()) { + case TOOLBAR_HOOKS: + g_settings.setInteger(Config::SHOW_WALL_HOOKS, toggled); + g_gui.root->UpdateIndicatorsMenu(); + break; + case TOOLBAR_PICKUPABLES: + g_settings.setInteger(Config::SHOW_PICKUPABLES, toggled); + g_gui.root->UpdateIndicatorsMenu(); + break; + case TOOLBAR_MOVEABLES: + g_settings.setInteger(Config::SHOW_MOVEABLES, toggled); + g_gui.root->UpdateIndicatorsMenu(); + break; + default: + break; + } +} + wxAuiPaneInfo& MainToolBar::GetPane(ToolBarID id) { wxAuiManager* manager = g_gui.GetAuiManager(); @@ -579,6 +640,8 @@ wxAuiPaneInfo& MainToolBar::GetPane(ToolBarID id) return manager->GetPane(POSITION_BAR_NAME); case TOOLBAR_SIZES: return manager->GetPane(SIZES_BAR_NAME); + case TOOLBAR_INDICATORS: + return manager->GetPane(INDICATORS_BAR_NAME); default: return wxAuiNullPaneInfo; } diff --git a/source/main_toolbar.h b/source/main_toolbar.h index 49e5fdc2..238acc88 100644 --- a/source/main_toolbar.h +++ b/source/main_toolbar.h @@ -35,6 +35,7 @@ class MainToolBar : public wxEvtHandler void UpdateButtons(); void UpdateBrushButtons(); void UpdateBrushSize(BrushShape shape, int size); + void UpdateIndicators(); void Show(ToolBarID id, bool show); void HideAll(bool update = true); void LoadPerspective(); @@ -46,12 +47,14 @@ class MainToolBar : public wxEvtHandler void OnPositionKeyUp(wxKeyEvent& event); void OnPastePositionText(wxClipboardTextEvent& event); void OnSizesButtonClick(wxCommandEvent& event); + void OnIndicatorsButtonClick(wxCommandEvent& event); private: static const wxString STANDARD_BAR_NAME; static const wxString BRUSHES_BAR_NAME; static const wxString POSITION_BAR_NAME; static const wxString SIZES_BAR_NAME; + static const wxString INDICATORS_BAR_NAME; wxAuiToolBar* standard_toolbar; wxAuiToolBar* brushes_toolbar; @@ -61,6 +64,7 @@ class MainToolBar : public wxEvtHandler NumberTextCtrl* z_control; wxButton* go_button; wxAuiToolBar* sizes_toolbar; + wxAuiToolBar* indicators_toolbar; }; #endif // RME_MAINTOOLBAR_H_ diff --git a/source/map_display.cpp b/source/map_display.cpp index 3737ecea..0bb86357 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -222,6 +222,8 @@ void MapCanvas::OnPaint(wxPaintEvent& event) options.show_only_modified = g_settings.getBoolean(Config::SHOW_ONLY_MODIFIED_TILES); options.show_preview = g_settings.getBoolean(Config::SHOW_PREVIEW); options.show_hooks = g_settings.getBoolean(Config::SHOW_WALL_HOOKS); + options.show_pickupables = g_settings.getBoolean(Config::SHOW_PICKUPABLES); + options.show_moveables = g_settings.getBoolean(Config::SHOW_MOVEABLES); options.hide_items_when_zoomed = g_settings.getBoolean(Config::HIDE_ITEMS_WHEN_ZOOMED); } diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index 4e8b2249..b27ecfd3 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -76,6 +76,8 @@ void DrawingOptions::SetDefault() show_only_modified = false; show_preview = false; show_hooks = false; + show_pickupables = false; + show_moveables = false; hide_items_when_zoomed = true; } @@ -106,6 +108,8 @@ void DrawingOptions::SetIngame() show_only_modified = false; show_preview = false; show_hooks = false; + show_pickupables = false; + show_moveables = false; hide_items_when_zoomed = false; } @@ -293,6 +297,18 @@ void MapDrawer::DrawMap() DrawTile(nd->getTile(map_x, map_y, map_z)); } } + if (!options.show_as_minimap && !options.show_only_colors && + (options.show_pickupables + || options.show_moveables + || options.show_houses + || options.show_spawns_monster + || options.show_spawns_npc)) { + for(int map_x = 0; map_x < 4; ++map_x) { + for(int map_y = 0; map_y < 4; ++map_y) { + DrawTileIndicators(nd->getTile(map_x, map_y, map_z)); + } + } + } } else { if(!nd->isRequested(map_z > GROUND_LAYER)) { // Request the node @@ -575,7 +591,7 @@ void MapDrawer::DrawDraggingShadow() BlitCreature(draw_x, draw_y, tile->monster); if(tile->spawnMonster && tile->spawnMonster->isSelected()) - BlitSpriteType(draw_x, draw_y, SPRITE_SPAWN, 160, 160, 160, 160); + DrawIndicator(draw_x, draw_y, EDITOR_SPRITE_SPAWNS, 160, 160, 160, 160); if(tile->npc && tile->npc->isSelected() && options.show_npcs) BlitCreature(draw_x, draw_y, tile->npc); @@ -1059,7 +1075,8 @@ void MapDrawer::DrawBrush() } } -void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Tile* tile, const Item* item, bool ephemeral, int red, int green, int blue, int alpha) { +void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Tile* tile, const Item* item, bool ephemeral, int red, int green, int blue, int alpha) +{ ItemType& it = g_items[item->getID()]; if(!options.ingame && !ephemeral && item->isSelected()) { @@ -1169,7 +1186,8 @@ void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Tile* tile, const Item* DrawHookIndicator(draw_x, draw_y, it); } -void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Position& pos, const Item* item, bool ephemeral, int red, int green, int blue, int alpha) { +void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Position& pos, const Item* item, bool ephemeral, int red, int green, int blue, int alpha) +{ ItemType& it = g_items[item->getID()]; if(!options.ingame && !ephemeral && item->isSelected()) { @@ -1558,35 +1576,6 @@ void MapDrawer::DrawTile(TileLocation* location) BlitCreature(draw_x, draw_y, tile->npc); } } - //if(location->getWaypointCount() > 0 && options.show_houses) { - //BlitSpriteType(draw_x, draw_y, SPRITE_FLAME_BLUE, 64, 64, 255); - //} - - if(tile->isHouseExit() && options.show_houses) { - if(tile->hasHouseExit(current_house_id)) { - BlitSpriteType(draw_x, draw_y, SPRITE_FLAG_GREY, 64, 255, 255); - } else { - BlitSpriteType(draw_x, draw_y, SPRITE_FLAG_GREY, 64, 64, 255); - } - } - //if(tile->isTownExit()) { - // BlitSpriteType(draw_x, draw_y, SPRITE_FLAG_GREY, 255, 255, 64); - //} - if(tile->spawnMonster && options.show_spawns_monster) { - if(tile->spawnMonster->isSelected()) { - BlitSpriteType(draw_x, draw_y, SPRITE_SPAWN, 128, 128, 128); - } else { - BlitSpriteType(draw_x, draw_y, SPRITE_SPAWN, 255, 255, 255); - } - } - - if(tile->spawnNpc && options.show_spawns_npc) { - if(tile->spawnNpc->isSelected()) { - BlitSpriteType(draw_x, draw_y, SPRITE_SPAWN_NPC, 128, 128, 128); - } else { - BlitSpriteType(draw_x, draw_y, SPRITE_SPAWN_NPC, 255, 255, 255); - } - } } if(options.show_tooltips) { @@ -1672,6 +1661,83 @@ void MapDrawer::DrawHookIndicator(int x, int y, const ItemType& type) glEnable(GL_TEXTURE_2D); } +void MapDrawer::DrawTileIndicators(TileLocation* location) +{ + if(!location) + return; + + Tile* tile = location->get(); + if(!tile) + return; + + int map_x = location->getX(); + int map_y = location->getY(); + int map_z = location->getZ(); + + int offset; + if (map_z <= GROUND_LAYER) + offset = (GROUND_LAYER - map_z) * TILE_SIZE; + else + offset = TILE_SIZE * (floor - map_z); + + int x = ((map_x * TILE_SIZE) - view_scroll_x) - offset; + int y = ((map_y * TILE_SIZE) - view_scroll_y) - offset; + + if(zoom < 10.0 && (options.show_pickupables || options.show_moveables)) { + uint8_t red = 0xFF, green = 0xFF, blue = 0xFF; + if (tile->isHouseTile()) { + green = 0x00; + blue = 0x00; + } + for (ItemVector::iterator it = tile->items.begin(); it != tile->items.end(); it++) { + const uint16_t itemId = (*it)->getID(); + const ItemType& type = g_items[itemId]; + if ((type.pickupable && options.show_pickupables) || (type.moveable && options.show_moveables)) { + if (type.pickupable && options.show_pickupables && type.moveable && options.show_moveables) + DrawIndicator(x, y, EDITOR_SPRITE_PICKUPABLE_MOVEABLE_ITEM, red, green, blue); + else if (type.pickupable && options.show_pickupables) + DrawIndicator(x, y, EDITOR_SPRITE_PICKUPABLE_ITEM, red, green, blue); + else if (type.moveable && options.show_moveables) + DrawIndicator(x, y, EDITOR_SPRITE_MOVEABLE_ITEM, red, green, blue); + } + } + } + + if(options.show_houses && tile->isHouseExit()) { + if(tile->hasHouseExit(current_house_id)) { + DrawIndicator(x, y, EDITOR_SPRITE_HOUSE_EXIT); + } else { + DrawIndicator(x, y, EDITOR_SPRITE_HOUSE_EXIT, 64, 64, 255, 128); + } + } + + if(options.show_spawns_monster && tile->spawnMonster) { + if(tile->spawnMonster->isSelected()) { + DrawIndicator(x, y, EDITOR_SPRITE_SPAWNS, 128, 128, 128); + } else { + DrawIndicator(x, y, EDITOR_SPRITE_SPAWNS); + } + } + + if(tile->spawnNpc && options.show_spawns_npc) { + if(tile->spawnNpc->isSelected()) { + DrawIndicator(x, y, SPRITE_SPAWN_NPC, 128, 128, 128); + } else { + DrawIndicator(x, y, SPRITE_SPAWN_NPC, 255, 255, 255); + } + } +} + +void MapDrawer::DrawIndicator(int x, int y, int indicator, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + GameSprite* sprite = g_gui.gfx.getEditorSprite(indicator); + if(sprite == nullptr) + return; + + int textureId = sprite->getHardwareID(0,0,0,-1,0,0,0,0); + glBlitTexture(x, y, textureId, r, g, b, a, true); +} + void MapDrawer::DrawTooltips() { for(std::vector::const_iterator it = tooltips.begin(); it != tooltips.end(); ++it) { @@ -1809,18 +1875,40 @@ void MapDrawer::TakeScreenshot(uint8_t* screenshot_buffer) glReadPixels(0, screensize_y - i, screensize_x, 1, GL_RGB, GL_UNSIGNED_BYTE, (GLubyte*)(screenshot_buffer) + 3*screensize_x*i); } -void MapDrawer::glBlitTexture(int sx, int sy, int texture_number, int red, int green, int blue, int alpha) +void MapDrawer::glBlitTexture(int x, int y, int textureId, int red, int green, int blue, int alpha, bool adjustZoom) { - if(texture_number != 0) { - glBindTexture(GL_TEXTURE_2D, texture_number); - glColor4ub(uint8_t(red), uint8_t(green), uint8_t(blue), uint8_t(alpha)); - glBegin(GL_QUADS); - glTexCoord2f(0.f, 0.f); glVertex2f(sx, sy); - glTexCoord2f(1.f, 0.f); glVertex2f(sx + TILE_SIZE, sy); - glTexCoord2f(1.f, 1.f); glVertex2f(sx + TILE_SIZE, sy + TILE_SIZE); - glTexCoord2f(0.f, 1.f); glVertex2f(sx, sy + TILE_SIZE); - glEnd(); + if (textureId <= 0) + return; + + glBindTexture(GL_TEXTURE_2D, textureId); + glColor4ub(uint8_t(red), uint8_t(green), uint8_t(blue), uint8_t(alpha)); + glBegin(GL_QUADS); + + if(adjustZoom) { + float size = TILE_SIZE; + if (zoom < 1.0f) { + float offset = 10 / (10 * zoom); + size = std::max(16, TILE_SIZE * zoom); + x += offset; + y += offset; + } else if (zoom > 1.f) { + float offset = (10 * zoom); + size = TILE_SIZE + offset; + x -= offset; + y -= offset; + } + glTexCoord2f(0.f, 0.f); glVertex2f(x, y); + glTexCoord2f(1.f, 0.f); glVertex2f(x + size, y); + glTexCoord2f(1.f, 1.f); glVertex2f(x + size, y + size); + glTexCoord2f(0.f, 1.f); glVertex2f(x, y + size); + } else { + glTexCoord2f(0.f, 0.f); glVertex2f(x, y); + glTexCoord2f(1.f, 0.f); glVertex2f(x + TILE_SIZE, y); + glTexCoord2f(1.f, 1.f); glVertex2f(x + TILE_SIZE, y + TILE_SIZE); + glTexCoord2f(0.f, 1.f); glVertex2f(x, y + TILE_SIZE); } + + glEnd(); } void MapDrawer::glBlitSquare(int sx, int sy, int red, int green, int blue, int alpha) diff --git a/source/map_drawer.h b/source/map_drawer.h index 4851aaf8..46096a27 100644 --- a/source/map_drawer.h +++ b/source/map_drawer.h @@ -75,6 +75,8 @@ struct DrawingOptions { bool show_only_modified; bool show_preview; bool show_hooks; + bool show_pickupables; + bool show_moveables; bool hide_items_when_zoomed; }; @@ -140,6 +142,8 @@ class MapDrawer void DrawTile(TileLocation* tile); void DrawBrushIndicator(int x, int y, Brush* brush, uint8_t r, uint8_t g, uint8_t b); void DrawHookIndicator(int x, int y, const ItemType& type); + void DrawTileIndicators(TileLocation* location); + void DrawIndicator(int x, int y, int indicator, uint8_t r = 255, uint8_t g = 255, uint8_t b = 255, uint8_t a = 255); void WriteTooltip(Item* item, std::ostringstream& stream); void WriteTooltip(Waypoint* item, std::ostringstream& stream); void MakeTooltip(int screenx, int screeny, const std::string& text, uint8_t r = 255, uint8_t g = 255, uint8_t b = 255); @@ -157,7 +161,7 @@ class MapDrawer }; void getColor(Brush* brush, const Position& position, uint8_t &r, uint8_t &g, uint8_t &b); - void glBlitTexture(int sx, int sy, int texture_number, int red, int green, int blue, int alpha); + void glBlitTexture(int x, int y, int textureId, int red, int green, int blue, int alpha, bool adjustZoom = false); void glBlitSquare(int sx, int sy, int red, int green, int blue, int alpha); void glColor(wxColor color); void glColor(BrushColor color); diff --git a/source/settings.cpp b/source/settings.cpp index 90ecf292..8f686284 100644 --- a/source/settings.cpp +++ b/source/settings.cpp @@ -213,6 +213,8 @@ void Settings::IO(IOMode mode) Int(SHOW_ONLY_MODIFIED_TILES, 0); Int(SHOW_PREVIEW, 1); Int(SHOW_WALL_HOOKS, 0); + Int(SHOW_PICKUPABLES, 0); + Int(SHOW_MOVEABLES, 0); section("Version"); Int(VERSION_ID, 0); @@ -323,6 +325,7 @@ void Settings::IO(IOMode mode) Int(SHOW_TOOLBAR_BRUSHES, 0); Int(SHOW_TOOLBAR_POSITION, 0); Int(SHOW_TOOLBAR_SIZES, 0); + Int(SHOW_TOOLBAR_INDICATORS, 0); String(TOOLBAR_STANDARD_LAYOUT, ""); String(TOOLBAR_BRUSHES_LAYOUT, ""); String(TOOLBAR_POSITION_LAYOUT, ""); diff --git a/source/settings.h b/source/settings.h index 54786029..e1c68d33 100644 --- a/source/settings.h +++ b/source/settings.h @@ -58,6 +58,8 @@ namespace Config { SHOW_TOOLTIPS, SHOW_PREVIEW, SHOW_WALL_HOOKS, + SHOW_PICKUPABLES, + SHOW_MOVEABLES, SHOW_AS_MINIMAP, SHOW_ONLY_TILEFLAGS, SHOW_ONLY_MODIFIED_TILES, @@ -166,10 +168,12 @@ namespace Config { SHOW_TOOLBAR_BRUSHES, SHOW_TOOLBAR_POSITION, SHOW_TOOLBAR_SIZES, + SHOW_TOOLBAR_INDICATORS, TOOLBAR_STANDARD_LAYOUT, TOOLBAR_BRUSHES_LAYOUT, TOOLBAR_POSITION_LAYOUT, TOOLBAR_SIZES_LAYOUT, + TOOLBAR_INDICATORS_LAYOUT, LAST, }; diff --git a/source/sprites.h b/source/sprites.h index e0592026..cb54f8ef 100644 --- a/source/sprites.h +++ b/source/sprites.h @@ -56,6 +56,13 @@ enum { EDITOR_SPRITE_WINDOW_HATCH, EDITOR_SPRITE_SELECTION_GEM, EDITOR_SPRITE_DRAWING_GEM, + + EDITOR_SPRITE_SPAWNS, + EDITOR_SPRITE_HOUSE_EXIT, + EDITOR_SPRITE_PICKUPABLE_ITEM, + EDITOR_SPRITE_MOVEABLE_ITEM, + EDITOR_SPRITE_PICKUPABLE_MOVEABLE_ITEM, + EDITOR_SPRITE_LAST }; From eb95ea96417afdfcc4abdd44e711a53f65b4234b Mon Sep 17 00:00:00 2001 From: Beats Date: Mon, 3 Apr 2023 23:56:54 -0400 Subject: [PATCH 02/45] Fix: drawing always refreshing ui --- source/gui.cpp | 2 -- source/main_menubar.cpp | 1 + source/main_toolbar.cpp | 3 +++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/source/gui.cpp b/source/gui.cpp index c0f35bce..0e3df86f 100644 --- a/source/gui.cpp +++ b/source/gui.cpp @@ -1117,8 +1117,6 @@ void GUI::RefreshView() for(EditorTab* editorTab : editorTabs) { editorTab->GetWindow()->Refresh(); } - - root->GetAuiToolBar()->UpdateIndicators(); } void GUI::CreateLoadBar(wxString message, bool canCancel /* = false */ ) diff --git a/source/main_menubar.cpp b/source/main_menubar.cpp index 982a2155..b8c10cbf 100644 --- a/source/main_menubar.cpp +++ b/source/main_menubar.cpp @@ -1868,6 +1868,7 @@ void MainMenuBar::OnChangeViewSettings(wxCommandEvent& event) g_settings.setInteger(Config::SHOW_MOVEABLES, IsItemChecked(MenuBar::SHOW_MOVEABLES)); g_gui.RefreshView(); + g_gui.root->GetAuiToolBar()->UpdateIndicators(); } void MainMenuBar::OnChangeFloor(wxCommandEvent& event) diff --git a/source/main_toolbar.cpp b/source/main_toolbar.cpp index 10bb572b..d1631ff3 100644 --- a/source/main_toolbar.cpp +++ b/source/main_toolbar.cpp @@ -611,14 +611,17 @@ void MainToolBar::OnIndicatorsButtonClick(wxCommandEvent& event) case TOOLBAR_HOOKS: g_settings.setInteger(Config::SHOW_WALL_HOOKS, toggled); g_gui.root->UpdateIndicatorsMenu(); + g_gui.RefreshView(); break; case TOOLBAR_PICKUPABLES: g_settings.setInteger(Config::SHOW_PICKUPABLES, toggled); g_gui.root->UpdateIndicatorsMenu(); + g_gui.RefreshView(); break; case TOOLBAR_MOVEABLES: g_settings.setInteger(Config::SHOW_MOVEABLES, toggled); g_gui.root->UpdateIndicatorsMenu(); + g_gui.RefreshView(); break; default: break; From c0a6a4dcfb84a77964d53a66ed3cb2803f798450 Mon Sep 17 00:00:00 2001 From: Beats Date: Mon, 3 Apr 2023 23:57:41 -0400 Subject: [PATCH 03/45] Fix crash on invalid friend for wallbrush --- source/wall_brush.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/wall_brush.cpp b/source/wall_brush.cpp index e169291e..2f9770d5 100644 --- a/source/wall_brush.cpp +++ b/source/wall_brush.cpp @@ -229,6 +229,7 @@ bool WallBrush::load(pugi::xml_node node, wxArrayString& warnings) friends.push_back(brush->getID()); } else { warnings.push_back("Brush '" + wxstr(name) + "' is not defined."); + continue; } if(childNode.attribute("redirect").as_bool()) { From 0309b2a0b0d61231eac6c8a7844ebb57f5ab666a Mon Sep 17 00:00:00 2001 From: Beats Date: Tue, 4 Apr 2023 00:12:40 -0400 Subject: [PATCH 04/45] Option to remove empty spawns --- data/menubar.xml | 4 +- source/main_menubar.cpp | 152 +++++++++++++++++++++++++++++++++++++ source/main_menubar.h | 4 + source/map_display.cpp | 2 +- source/palette_monster.cpp | 2 +- 5 files changed, 161 insertions(+), 3 deletions(-) diff --git a/data/menubar.xml b/data/menubar.xml index 7064d206..ab509839 100644 --- a/data/menubar.xml +++ b/data/menubar.xml @@ -48,10 +48,12 @@ - + + + diff --git a/source/main_menubar.cpp b/source/main_menubar.cpp index b8c10cbf..18148e39 100644 --- a/source/main_menubar.cpp +++ b/source/main_menubar.cpp @@ -112,6 +112,8 @@ MainMenuBar::MainMenuBar(MainFrame *frame) : frame(frame) MAKE_ACTION(MAP_REMOVE_ITEMS, wxITEM_NORMAL, OnMapRemoveItems); MAKE_ACTION(MAP_REMOVE_CORPSES, wxITEM_NORMAL, OnMapRemoveCorpses); MAKE_ACTION(MAP_REMOVE_UNREACHABLE_TILES, wxITEM_NORMAL, OnMapRemoveUnreachable); + MAKE_ACTION(MAP_REMOVE_EMPTY_MONSTERS_SPAWNS, wxITEM_NORMAL, OnMapRemoveEmptyMonsterSpawns); + MAKE_ACTION(MAP_REMOVE_EMPTY_NPCS_SPAWNS, wxITEM_NORMAL, OnMapRemoveEmptyNpcSpawns); MAKE_ACTION(MAP_CLEANUP, wxITEM_NORMAL, OnMapCleanup); MAKE_ACTION(MAP_CLEAN_HOUSE_ITEMS, wxITEM_NORMAL, OnMapCleanHouseItems); MAKE_ACTION(MAP_PROPERTIES, wxITEM_NORMAL, OnMapProperties); @@ -360,6 +362,8 @@ void MainMenuBar::Update() EnableItem(MAP_REMOVE_ITEMS, is_host); EnableItem(MAP_REMOVE_CORPSES, is_local); EnableItem(MAP_REMOVE_UNREACHABLE_TILES, is_local); + EnableItem(MAP_REMOVE_EMPTY_MONSTERS_SPAWNS, is_local); + EnableItem(MAP_REMOVE_EMPTY_NPCS_SPAWNS, is_local); EnableItem(CLEAR_INVALID_HOUSES, is_local); EnableItem(CLEAR_MODIFIED_STATE, is_local); @@ -1423,6 +1427,154 @@ void MainMenuBar::OnMapRemoveUnreachable(wxCommandEvent& WXUNUSED(event)) } } +void MainMenuBar::OnMapRemoveEmptyMonsterSpawns(wxCommandEvent& WXUNUSED(event)) +{ + if (!g_gui.IsEditorOpen()) { + return; + } + + int ok = g_gui.PopupDialog("Remove Empty Monsters Spawns", "Do you want to remove all empty monsters spawns from the map?", wxYES | wxNO); + if (ok == wxID_YES) { + Editor* editor = g_gui.GetCurrentEditor(); + editor->selection.clear(); + + g_gui.CreateLoadBar("Searching map for empty monsters spawns to remove..."); + + Map& map = g_gui.GetCurrentMap(); + MonsterVector monster; + TileVector toDeleteSpawns; + for (const auto& spawnPosition : map.spawnsMonster) { + Tile* tile = map.getTile(spawnPosition); + if (!tile || !tile->spawnMonster) { + continue; + } + + const int32_t radius = tile->spawnMonster->getSize(); + + bool empty = true; + for (int32_t y = -radius; y <= radius; ++y) { + for (int32_t x = -radius; x <= radius; ++x) { + Tile* creature_tile = map.getTile(spawnPosition + Position(x, y, 0)); + if (creature_tile && creature_tile->monster && !creature_tile->monster->isSaved()) { + creature_tile->monster->save(); + monster.push_back(creature_tile->monster); + empty = false; + } + } + } + + if (empty) { + toDeleteSpawns.push_back(tile); + } + } + + for (Monster* monster : monster) { + monster->reset(); + } + + BatchAction* batch = editor->actionQueue->createBatch(ACTION_DELETE_TILES); + Action* action = editor->actionQueue->createAction(batch); + + const size_t count = toDeleteSpawns.size(); + size_t removed = 0; + for (const auto& tile : toDeleteSpawns) { + Tile* newtile = tile->deepCopy(map); + map.removeSpawnMonster(newtile); + delete newtile->spawnMonster; + newtile->spawnMonster = nullptr; + if (++removed % 5 == 0) { + // update progress bar for each 5 spawns removed + g_gui.SetLoadDone(100 * removed / count); + } + action->addChange(newd Change(newtile)); + } + + batch->addAndCommitAction(action); + editor->addBatch(batch); + + g_gui.DestroyLoadBar(); + + wxString msg; + msg << removed << " empty monsters spawns removed."; + g_gui.PopupDialog("Search completed", msg, wxOK); + g_gui.GetCurrentMap().doChange(); + } +} + +void MainMenuBar::OnMapRemoveEmptyNpcSpawns(wxCommandEvent& WXUNUSED(event)) +{ + if (!g_gui.IsEditorOpen()) { + return; + } + + int ok = g_gui.PopupDialog("Remove Empty Npcs Spawns", "Do you want to remove all empty npcs spawns from the map?", wxYES | wxNO); + if (ok == wxID_YES) { + Editor* editor = g_gui.GetCurrentEditor(); + editor->selection.clear(); + + g_gui.CreateLoadBar("Searching map for empty npcs spawns to remove..."); + + Map& map = g_gui.GetCurrentMap(); + NpcVector npc; + TileVector toDeleteSpawns; + for (const auto& spawnPosition : map.spawnsNpc) { + Tile* tile = map.getTile(spawnPosition); + if (!tile || !tile->spawnNpc) { + continue; + } + + const int32_t radius = tile->spawnNpc->getSize(); + + bool empty = true; + for (int32_t y = -radius; y <= radius; ++y) { + for (int32_t x = -radius; x <= radius; ++x) { + Tile* creature_tile = map.getTile(spawnPosition + Position(x, y, 0)); + if (creature_tile && creature_tile->npc && !creature_tile->npc->isSaved()) { + creature_tile->npc->save(); + npc.push_back(creature_tile->npc); + empty = false; + } + } + } + + if (empty) { + toDeleteSpawns.push_back(tile); + } + } + + for (Npc* npc : npc) { + npc->reset(); + } + + BatchAction* batch = editor->actionQueue->createBatch(ACTION_DELETE_TILES); + Action* action = editor->actionQueue->createAction(batch); + + const size_t count = toDeleteSpawns.size(); + size_t removed = 0; + for (const auto& tile : toDeleteSpawns) { + Tile* newtile = tile->deepCopy(map); + map.removeSpawnNpc(newtile); + delete newtile->spawnNpc; + newtile->spawnNpc = nullptr; + if (++removed % 5 == 0) { + // update progress bar for each 5 spawns removed + g_gui.SetLoadDone(100 * removed / count); + } + action->addChange(newd Change(newtile)); + } + + batch->addAndCommitAction(action); + editor->addBatch(batch); + + g_gui.DestroyLoadBar(); + + wxString msg; + msg << removed << " empty npcs spawns removed."; + g_gui.PopupDialog("Search completed", msg, wxOK); + g_gui.GetCurrentMap().doChange(); + } +} + void MainMenuBar::OnClearHouseTiles(wxCommandEvent& WXUNUSED(event)) { Editor* editor = g_gui.GetCurrentEditor(); diff --git a/source/main_menubar.h b/source/main_menubar.h index d83e0fb8..4779d257 100644 --- a/source/main_menubar.h +++ b/source/main_menubar.h @@ -83,6 +83,8 @@ namespace MenuBar MAP_REMOVE_ITEMS, MAP_REMOVE_CORPSES, MAP_REMOVE_UNREACHABLE_TILES, + MAP_REMOVE_EMPTY_MONSTERS_SPAWNS, + MAP_REMOVE_EMPTY_NPCS_SPAWNS, MAP_CLEAN_HOUSE_ITEMS, MAP_PROPERTIES, MAP_STATISTICS, @@ -217,6 +219,8 @@ class MainMenuBar : public wxEvtHandler void OnMapRemoveItems(wxCommandEvent& event); void OnMapRemoveCorpses(wxCommandEvent& event); void OnMapRemoveUnreachable(wxCommandEvent& event); + void OnMapRemoveEmptyMonsterSpawns(wxCommandEvent& event); + void OnMapRemoveEmptyNpcSpawns(wxCommandEvent& event); void OnClearHouseTiles(wxCommandEvent& event); void OnClearModifiedState(wxCommandEvent& event); void OnToggleAutomagic(wxCommandEvent& event); diff --git a/source/map_display.cpp b/source/map_display.cpp index 0bb86357..48b56370 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -2483,7 +2483,7 @@ void MapPopupMenu::Update() Append( MAP_POPUP_MENU_SELECT_MONSTER_BRUSH, "Select Monster", "Uses the current monster as a monster brush"); if(topSpawnMonster) - Append( MAP_POPUP_MENU_SELECT_SPAWN_BRUSH, "Select Npc", "Select the npc brush"); + Append( MAP_POPUP_MENU_SELECT_SPAWN_BRUSH, "Select Monster", "Select the npc brush"); if(topNpc) Append( MAP_POPUP_MENU_SELECT_NPC_BRUSH, "Select Npc", "Uses the current npc as a npc brush"); diff --git a/source/palette_monster.cpp b/source/palette_monster.cpp index 26ceb8c1..0de25b0a 100644 --- a/source/palette_monster.cpp +++ b/source/palette_monster.cpp @@ -70,7 +70,7 @@ MonsterPalettePanel::MonsterPalettePanel(wxWindow* parent, wxWindowID id) : grid->Add(monster_brush_button, 0, wxEXPAND); grid->Add(newd wxStaticText(this, wxID_ANY, "Spawn size")); - spawn_monster_size_spin = newd wxSpinCtrl(this, PALETTE_MONSTER_SPAWN_SIZE, i2ws(5), wxDefaultPosition, wxSize(50, 20), wxSP_ARROW_KEYS, 1, g_settings.getInteger(Config::MAX_SPAWN_MONSTER_RADIUS), g_settings.getInteger(Config::CURRENT_SPAWN_MONSTER_RADIUS)); + spawn_monster_size_spin = newd wxSpinCtrl(this, PALETTE_MONSTER_SPAWN_SIZE, i2ws(1), wxDefaultPosition, wxSize(50, 20), wxSP_ARROW_KEYS, 1, g_settings.getInteger(Config::MAX_SPAWN_MONSTER_RADIUS), g_settings.getInteger(Config::CURRENT_SPAWN_MONSTER_RADIUS)); grid->Add(spawn_monster_size_spin, 0, wxEXPAND); spawn_monster_brush_button = newd wxToggleButton(this, PALETTE_SPAWN_MONSTER_BRUSH_BUTTON, "Place Spawn"); grid->Add(spawn_monster_brush_button, 0, wxEXPAND); From 7634d6dc4b71e83afa16357e57207f3b5abf4f10 Mon Sep 17 00:00:00 2001 From: Beats Date: Tue, 4 Apr 2023 00:37:03 -0400 Subject: [PATCH 05/45] Draws position indicator, some code cleanup --- source/gui.cpp | 4 +- source/gui.h | 2 +- source/map_display.cpp | 6 +++ source/map_display.h | 1 + source/map_drawer.cpp | 99 ++++++++++++++++++++++++++++++------------ source/map_drawer.h | 11 ++++- source/map_region.h | 9 ++-- source/map_window.cpp | 7 ++- source/map_window.h | 2 +- source/position.h | 2 +- 10 files changed, 102 insertions(+), 41 deletions(-) diff --git a/source/gui.cpp b/source/gui.cpp index 0e3df86f..b05aab96 100644 --- a/source/gui.cpp +++ b/source/gui.cpp @@ -1245,11 +1245,11 @@ void GUI::UpdateMenubar() root->UpdateMenubar(); } -void GUI::SetScreenCenterPosition(Position position) +void GUI::SetScreenCenterPosition(const Position& position, bool showIndicator) { MapTab* mapTab = GetCurrentMapTab(); if(mapTab) - mapTab->SetScreenCenterPosition(position); + mapTab->SetScreenCenterPosition(position, showIndicator); } void GUI::DoCut() diff --git a/source/gui.h b/source/gui.h index fb1d0a33..b2eff147 100644 --- a/source/gui.h +++ b/source/gui.h @@ -274,7 +274,7 @@ class GUI bool IsVersionLoaded() const {return loaded_version != CLIENT_VERSION_NONE;} // Centers current view on position - void SetScreenCenterPosition(Position pos); + void SetScreenCenterPosition(const Position& position, bool showIndicator = true); // Refresh the view canvas void RefreshView(); // Fit all/specified current map view to map dimensions diff --git a/source/map_display.cpp b/source/map_display.cpp index 48b56370..6b0a7946 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -254,6 +254,12 @@ void MapCanvas::OnPaint(wxPaintEvent& event) editor.SendNodeRequests(); } +void MapCanvas::ShowPositionIndicator(const Position& position) +{ + if (drawer) + drawer->ShowPositionIndicator(position); +} + void MapCanvas::TakeScreenshot(wxFileName path, wxString format) { int screensize_x, screensize_y; diff --git a/source/map_display.h b/source/map_display.h index 9a2d57aa..5a7f97af 100644 --- a/source/map_display.h +++ b/source/map_display.h @@ -116,6 +116,7 @@ class MapCanvas : public wxGLCanvas { Position GetCursorPosition() const; + void ShowPositionIndicator(const Position& position); void TakeScreenshot(wxFileName path, wxString format); protected: diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index b27ecfd3..10334953 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -328,6 +328,8 @@ void MapDrawer::DrawMap() } } } + + DrawPositionIndicator(map_z); } if(only_colors) @@ -1436,19 +1438,14 @@ void MapDrawer::DrawTile(TileLocation* location) { if(!location) return; - Tile* tile = location->get(); + Tile* tile = location->get(); if(!tile) return; if(options.show_only_modified && !tile->isModified()) return; - int map_x = location->getX(); - int map_y = location->getY(); - int map_z = location->getZ(); - - if(options.show_tooltips && location->getWaypointCount() > 0) { Waypoint* waypoint = canvas->editor.map.waypoints.getWaypoint(location); if(waypoint) @@ -1458,14 +1455,9 @@ void MapDrawer::DrawTile(TileLocation* location) bool as_minimap = options.show_as_minimap; bool only_colors = as_minimap || options.show_only_colors; - int offset; - if (map_z <= GROUND_LAYER) - offset = (GROUND_LAYER - map_z) * TILE_SIZE; - else - offset = TILE_SIZE * (floor - map_z); - - int draw_x = ((map_x * TILE_SIZE) - view_scroll_x) - offset; - int draw_y = ((map_y * TILE_SIZE) - view_scroll_y) - offset; + const Position& position = location->getPosition(); + int draw_x, draw_y; + getDrawPosition(position, draw_x, draw_y); uint8_t r = 255,g = 255,b = 255; if(tile->ground || only_colors) { @@ -1550,14 +1542,14 @@ void MapDrawer::DrawTile(TileLocation* location) BlitItem(draw_x, draw_y, tile, tile->ground, false, r, g, b); } - if(options.show_tooltips && map_z == floor) + if(options.show_tooltips && position.z == floor) WriteTooltip(tile->ground, tooltip); } if(!only_colors) { if(zoom < 10.0 || !options.hide_items_when_zoomed) { for(ItemVector::iterator it = tile->items.begin(); it != tile->items.end(); it++) { - if(options.show_tooltips && map_z == floor) + if(options.show_tooltips && position.z == floor) WriteTooltip(*it, tooltip); if(options.show_preview && zoom <= 2.0) @@ -1670,18 +1662,8 @@ void MapDrawer::DrawTileIndicators(TileLocation* location) if(!tile) return; - int map_x = location->getX(); - int map_y = location->getY(); - int map_z = location->getZ(); - - int offset; - if (map_z <= GROUND_LAYER) - offset = (GROUND_LAYER - map_z) * TILE_SIZE; - else - offset = TILE_SIZE * (floor - map_z); - - int x = ((map_x * TILE_SIZE) - view_scroll_x) - offset; - int y = ((map_y * TILE_SIZE) - view_scroll_y) - offset; + int x, y; + getDrawPosition(location->getPosition(), x, y); if(zoom < 10.0 && (options.show_pickupables || options.show_moveables)) { uint8_t red = 0xFF, green = 0xFF, blue = 0xFF; @@ -1738,6 +1720,36 @@ void MapDrawer::DrawIndicator(int x, int y, int indicator, uint8_t r, uint8_t g, glBlitTexture(x, y, textureId, r, g, b, a, true); } +void MapDrawer::DrawPositionIndicator(int z) +{ + if (z != pos_indicator.z + || pos_indicator.x < start_x + || pos_indicator.x > end_x + || pos_indicator.y < start_y + || pos_indicator.y > end_y) { + return; + } + + constexpr int duration = 5000; + const long time = pos_indicator_timer.Time(); + if (time >= duration) + return; + + int x, y; + getDrawPosition(pos_indicator, x, y); + + int size = static_cast(TILE_SIZE * (0.3f + std::abs(500 - time % 1000) / 1000.f)); + int offset = (TILE_SIZE - size) / 2; + + glDisable(GL_TEXTURE_2D); + drawRect(x + offset + 2, y + offset + 2, size - 4, size - 4, *wxWHITE, 2); + drawRect(x + offset + 1, y + offset + 1, size - 2, size - 2, *wxBLACK, 2); + glEnable(GL_TEXTURE_2D); + + if (time >= duration) + pos_indicator_timer.Pause(); +} + void MapDrawer::DrawTooltips() { for(std::vector::const_iterator it = tooltips.begin(); it != tooltips.end(); ++it) { @@ -1875,6 +1887,12 @@ void MapDrawer::TakeScreenshot(uint8_t* screenshot_buffer) glReadPixels(0, screensize_y - i, screensize_x, 1, GL_RGB, GL_UNSIGNED_BYTE, (GLubyte*)(screenshot_buffer) + 3*screensize_x*i); } +void MapDrawer::ShowPositionIndicator(const Position& position) +{ + pos_indicator = position; + pos_indicator_timer.Start(); +} + void MapDrawer::glBlitTexture(int x, int y, int textureId, int red, int green, int blue, int alpha, bool adjustZoom) { if (textureId <= 0) @@ -1982,3 +2000,28 @@ void MapDrawer::glColorCheck(Brush* brush, const Position& pos) else glColor(COLOR_INVALID); } + +void MapDrawer::drawRect(int x, int y, int w, int h, const wxColour& color, int width) +{ + glLineWidth(width); + glColor4ub(color.Red(), color.Green(), color.Blue(), color.Alpha()); + glBegin(GL_LINE_LOOP); + glVertex2f(x, y); + glVertex2f(x + w, y); + glVertex2f(x + w, y + h); + glVertex2f(x, y + h); + glVertex2f(x, y); + glEnd(); +} + +void MapDrawer::getDrawPosition(const Position& position, int& x, int& y) +{ + int offset; + if (position.z <= GROUND_LAYER) + offset = (GROUND_LAYER - position.z) * TILE_SIZE; + else + offset = TILE_SIZE * (floor - position.z); + + x = ((position.x * TILE_SIZE) - view_scroll_x) - offset; + y = ((position.y * TILE_SIZE) - view_scroll_y) - offset; +} diff --git a/source/map_drawer.h b/source/map_drawer.h index 46096a27..8368e8a6 100644 --- a/source/map_drawer.h +++ b/source/map_drawer.h @@ -104,6 +104,9 @@ class MapDrawer std::vector tooltips; std::ostringstream tooltip; + wxStopWatch pos_indicator_timer; + Position pos_indicator; + public: MapDrawer(MapCanvas* canvas); ~MapDrawer(); @@ -129,6 +132,8 @@ class MapDrawer void TakeScreenshot(uint8_t* screenshot_buffer); + void ShowPositionIndicator(const Position& position); + DrawingOptions& getOptions() { return options; } protected: @@ -144,6 +149,7 @@ class MapDrawer void DrawHookIndicator(int x, int y, const ItemType& type); void DrawTileIndicators(TileLocation* location); void DrawIndicator(int x, int y, int indicator, uint8_t r = 255, uint8_t g = 255, uint8_t b = 255, uint8_t a = 255); + void DrawPositionIndicator(int z); void WriteTooltip(Item* item, std::ostringstream& stream); void WriteTooltip(Waypoint* item, std::ostringstream& stream); void MakeTooltip(int screenx, int screeny, const std::string& text, uint8_t r = 255, uint8_t g = 255, uint8_t b = 255); @@ -166,8 +172,11 @@ class MapDrawer void glColor(wxColor color); void glColor(BrushColor color); void glColorCheck(Brush* brush, const Position& pos); -}; + void drawRect(int x, int y, int w, int h, const wxColour& color, int width = 1); +private: + void getDrawPosition(const Position& position, int &x, int &y); +}; #endif diff --git a/source/map_region.h b/source/map_region.h index 454e6d7e..27767e47 100644 --- a/source/map_region.h +++ b/source/map_region.h @@ -51,11 +51,10 @@ class TileLocation int size() const; bool empty() const; - Position getPosition() const { return position; } - - int getX() const {return position.x;} - int getY() const {return position.y;} - int getZ() const {return position.z;} + const Position& getPosition() const noexcept { return position; } + int getX() const noexcept { return position.x; } + int getY() const noexcept { return position.y; } + int getZ() const noexcept { return position.z; } size_t getSpawnMonsterCount() const {return spawn_monster_count;} void increaseSpawnCount() {spawn_monster_count++;} diff --git a/source/map_window.cpp b/source/map_window.cpp index 2a795765..41c8be73 100644 --- a/source/map_window.cpp +++ b/source/map_window.cpp @@ -134,7 +134,7 @@ Position MapWindow::GetScreenCenterPosition() return Position(x, y, canvas->GetFloor()); } -void MapWindow::SetScreenCenterPosition(const Position& position) +void MapWindow::SetScreenCenterPosition(const Position& position, bool showIndicator) { if(position == Position()) return; @@ -156,11 +156,14 @@ void MapWindow::SetScreenCenterPosition(const Position& position) Scroll(x, y, true); canvas->ChangeFloor(position.z); + + if (showIndicator) + canvas->ShowPositionIndicator(position); } void MapWindow::GoToPreviousCenterPosition() { - SetScreenCenterPosition(previous_position); + SetScreenCenterPosition(previous_position, true); } void MapWindow::Scroll(int x, int y, bool center) diff --git a/source/map_window.h b/source/map_window.h index c5243ca4..2a11231c 100644 --- a/source/map_window.h +++ b/source/map_window.h @@ -67,7 +67,7 @@ class MapWindow : public wxPanel // Screen position. Position GetScreenCenterPosition(); - void SetScreenCenterPosition(const Position& position); + void SetScreenCenterPosition(const Position& position, bool showIndicator = false); void GoToPreviousCenterPosition(); // Return the containing canvas diff --git a/source/position.h b/source/position.h index c9ce5d48..aec67736 100644 --- a/source/position.h +++ b/source/position.h @@ -80,7 +80,7 @@ class Position { return *this; } - bool operator==(const Position& p) const { + bool operator==(const Position& p) const noexcept { return p.x == x && p.y == y && p.z == z; } From ab65bc55555369ed053954e0ba9f4ec88f5c0cec Mon Sep 17 00:00:00 2001 From: Beats Date: Tue, 4 Apr 2023 00:50:01 -0400 Subject: [PATCH 06/45] Teleport copy/paste improvements --- source/common.cpp | 57 +++++++++++++++++++++++++++ source/common.h | 2 + source/complexitem.h | 9 ++--- source/gui_ids.h | 1 + source/map_display.cpp | 66 +++++++++++++------------------- source/map_display.h | 1 + source/map_drawer.cpp | 3 -- source/old_properties_window.cpp | 45 +++++++++------------- source/old_properties_window.h | 6 +-- 9 files changed, 110 insertions(+), 80 deletions(-) diff --git a/source/common.cpp b/source/common.cpp index 8047ae44..000c2848 100644 --- a/source/common.cpp +++ b/source/common.cpp @@ -248,6 +248,63 @@ bool posFromClipboard(int& x, int& y, int& z) return done; } +bool posToClipboard(int x, int y, int z, int format) +{ + if (!wxTheClipboard->Open()) + return false; + + wxTextDataObject* data = new wxTextDataObject(); + + switch (format) { + case 0: + data->SetText(wxString::Format("{x = %d, y = %d, z = %d}", x, y, z)); + break; + case 1: + data->SetText(wxString::Format("{\"x\":%d, \"y\":%d, \"z\":%d}", x, y, z)); + break; + case 2: + data->SetText(wxString::Format("%d, %d, %d", x, y, z)); + break; + case 3: + data->SetText(wxString::Format("(%d, %d, %d)", x, y, z)); + break; + case 4: + data->SetText(wxString::Format("Position(%d, %d, %d)", x, y, z)); + break; + default: + wxTheClipboard->Close(); + return false; + } + + wxTheClipboard->SetData(data); + wxTheClipboard->Close(); + return true; +} + +bool posToClipboard(int fromx, int fromy, int fromz, int tox, int toy, int toz) +{ + if (!wxTheClipboard->Open()) + return false; + + std::ostringstream clip; + clip << "{"; + clip << "fromx = " << fromx << ", "; + clip << "tox = " << tox << ", "; + clip << "fromy = " << fromy << ", "; + clip << "toy = " << toy << ", "; + if (fromz != toz) { + clip << "fromz = " << fromz << ", "; + clip << "toz = " << toz; + } + else + clip << "z = " << fromz; + clip << "}"; + + wxTheClipboard->SetData(new wxTextDataObject(clip.str())); + wxTheClipboard->Close(); + return true; +} + wxString b2yn(bool value) { return value ? "Yes" : "No"; diff --git a/source/common.h b/source/common.h index 0e91594d..652f1d24 100644 --- a/source/common.h +++ b/source/common.h @@ -72,6 +72,8 @@ std::string wstring2string(const std::wstring& widestring); // Gets position values from ClipBoard bool posFromClipboard(int& x, int& y, int& z); +bool posToClipboard(int x, int y, int z, int format); +bool posToClipboard(int fromx, int fromy, int fromz, int tox, int toy, int toz); // Returns 'yes' if the defined value is true or 'no' if it is false. wxString b2yn(bool v); diff --git a/source/complexitem.h b/source/complexitem.h index e7dafb69..ebd17e2f 100644 --- a/source/complexitem.h +++ b/source/complexitem.h @@ -68,11 +68,10 @@ class Teleport : public Item //virtual void serializeItemAttributes_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; //virtual bool readItemAttribute_OTMM(const IOMap& maphandle, OTMM_ItemAttribute attr, BinaryNode* node); - int32_t getX() const { return destination.x; } - int32_t getY() const { return destination.y; } - int32_t getZ() const { return destination.z; } - - Position getDestination() const { return destination; } + const Position& getDestination() const noexcept { return destination; } + int getX() const noexcept { return destination.x; } + int getY() const noexcept { return destination.y; } + int getZ() const noexcept { return destination.z; } void setDestination(const Position& position) { destination = position; } bool hasDestination() const { return destination != Position(); } diff --git a/source/gui_ids.h b/source/gui_ids.h index 578ea753..64566514 100644 --- a/source/gui_ids.h +++ b/source/gui_ids.h @@ -59,6 +59,7 @@ enum EditorActionID MAP_POPUP_MENU_SWITCH_DOOR, MAP_POPUP_MENU_ROTATE, MAP_POPUP_MENU_GOTO, + MAP_POPUP_MENU_COPY_DESTINATION, MAP_POPUP_MENU_SELECT_RAW_BRUSH, MAP_POPUP_MENU_SELECT_MONSTER_BRUSH, MAP_POPUP_MENU_SELECT_SPAWN_BRUSH, diff --git a/source/map_display.cpp b/source/map_display.cpp index 6b0a7946..59b97242 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -84,6 +84,7 @@ BEGIN_EVENT_TABLE(MapCanvas, wxGLCanvas) // ---- EVT_MENU(MAP_POPUP_MENU_ROTATE, MapCanvas::OnRotateItem) EVT_MENU(MAP_POPUP_MENU_GOTO, MapCanvas::OnGotoDestination) + EVT_MENU(MAP_POPUP_MENU_COPY_DESTINATION, MapCanvas::OnCopyDestination) EVT_MENU(MAP_POPUP_MENU_SWITCH_DOOR, MapCanvas::OnSwitchDoor) // ---- EVT_MENU(MAP_POPUP_MENU_SELECT_RAW_BRUSH, MapCanvas::OnSelectRAWBrush) @@ -1952,46 +1953,11 @@ void MapCanvas::OnCopyPosition(wxCommandEvent& WXUNUSED(event)) Position minPos = editor.selection.minPosition(); Position maxPos = editor.selection.maxPosition(); - std::ostringstream clip; if(minPos != maxPos) { - clip << "{"; - clip << "fromx = " << minPos.x << ", "; - clip << "tox = " << maxPos.x << ", "; - clip << "fromy = " << minPos.y << ", "; - clip << "toy = " << maxPos.y << ", "; - if(minPos.z != maxPos.z) { - clip << "fromz = " << minPos.z << ", "; - clip << "toz = " << maxPos.z; - } - else - clip << "z = " << minPos.z; - clip << "}"; + posToClipboard(minPos.x, minPos.y, minPos.z, maxPos.x, maxPos.y, maxPos.z); } else { - switch (g_settings.getInteger(Config::COPY_POSITION_FORMAT)) { - case 0: - clip << "{x = " << minPos.x << ", y = " << minPos.y << ", z = " << minPos.z << "}"; - break; - case 1: - clip << "{\"x\":" << minPos.x << ",\"y\":" << minPos.y << ",\"z\":" << minPos.z << "}"; - break; - case 2: - clip << minPos.x << ", " << minPos.y << ", " << minPos.z; - break; - case 3: - clip << "(" << minPos.x << ", " << minPos.y << ", " << minPos.z << ")"; - break; - case 4: - clip << "Position(" << minPos.x << ", " << minPos.y << ", " << minPos.z << ")"; - break; - } - } - - if(wxTheClipboard->Open()) { - wxTextDataObject* obj = new wxTextDataObject(); - obj->SetText(wxstr(clip.str())); - wxTheClipboard->SetData(obj); - - wxTheClipboard->Close(); + int format = g_settings.getInteger(Config::COPY_POSITION_FORMAT); + posToClipboard(minPos.x, minPos.y, minPos.z, format); } } @@ -2108,6 +2074,20 @@ void MapCanvas::OnGotoDestination(wxCommandEvent& WXUNUSED(event)) } } +void MapCanvas::OnCopyDestination(wxCommandEvent& WXUNUSED(event)) +{ + Tile* tile = editor.selection.getSelectedTile(); + ItemVector selected_items = tile->getSelectedItems(); + ASSERT(selected_items.size() > 0); + + Teleport* teleport = dynamic_cast(selected_items.front()); + if (teleport) { + const Position& destination = teleport->getDestination(); + int format = g_settings.getInteger(Config::COPY_POSITION_FORMAT); + posToClipboard(destination.x, destination.y, destination.z, format); + } +} + void MapCanvas::OnSwitchDoor(wxCommandEvent& WXUNUSED(event)) { Tile* tile = editor.selection.getSelectedTile(); @@ -2471,8 +2451,14 @@ void MapPopupMenu::Update() if(topSelectedItem->isRoteable()) Append(MAP_POPUP_MENU_ROTATE, "&Rotate item", "Rotate this item"); - if(teleport && teleport->hasDestination()) - Append(MAP_POPUP_MENU_GOTO, "&Go To Destination", "Go to the destination of this teleport"); + if(teleport) { + bool enabled = teleport->hasDestination(); + wxMenuItem* goto_menu = Append(MAP_POPUP_MENU_GOTO, "&Go To Destination", "Go to the destination of this teleport"); + goto_menu->Enable(enabled); + wxMenuItem* dest_menu = Append(MAP_POPUP_MENU_COPY_DESTINATION, "Copy &Destination", "Copy the destination of this teleport"); + dest_menu->Enable(enabled); + AppendSeparator(); + } if(topSelectedItem->isDoor()) { diff --git a/source/map_display.h b/source/map_display.h index 5a7f97af..6a6aa857 100644 --- a/source/map_display.h +++ b/source/map_display.h @@ -76,6 +76,7 @@ class MapCanvas : public wxGLCanvas { void OnDelete(wxCommandEvent& event); // ---- void OnGotoDestination(wxCommandEvent& event); + void OnCopyDestination(wxCommandEvent& event); void OnRotateItem(wxCommandEvent& event); void OnSwitchDoor(wxCommandEvent& event); // ---- diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index 10334953..43688a1e 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -1745,9 +1745,6 @@ void MapDrawer::DrawPositionIndicator(int z) drawRect(x + offset + 2, y + offset + 2, size - 4, size - 4, *wxWHITE, 2); drawRect(x + offset + 1, y + offset + 1, size - 2, size - 2, *wxBLACK, 2); glEnable(GL_TEXTURE_2D); - - if (time >= duration) - pos_indicator_timer.Pause(); } void MapDrawer::DrawTooltips() diff --git a/source/old_properties_window.cpp b/source/old_properties_window.cpp index 3b7783c6..3dbf3d73 100644 --- a/source/old_properties_window.cpp +++ b/source/old_properties_window.cpp @@ -53,7 +53,8 @@ OldPropertiesWindow::OldPropertiesWindow(wxWindow* win_parent, const Map* map, c depot_id_field(nullptr), splash_type_field(nullptr), text_field(nullptr), - description_field(nullptr) + description_field(nullptr), + destination_field(nullptr) { ASSERT(edit_item); @@ -304,22 +305,13 @@ OldPropertiesWindow::OldPropertiesWindow(wxWindow* win_parent, const Map* map, c subsizer->Add(door_id_field, wxSizerFlags(1).Expand()); } - if(teleport) { - subsizer->Add(newd wxStaticText(this, wxID_ANY, "Destination")); - - wxSizer* possizer = newd wxBoxSizer(wxHORIZONTAL); - x_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(teleport->getX()), wxDefaultPosition, wxSize(-1, 20), wxSP_ARROW_KEYS, 0, map->getWidth(), teleport->getX()); - possizer->Add(x_field, wxSizerFlags(3).Expand()); - y_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(teleport->getY()), wxDefaultPosition, wxSize(-1, 20), wxSP_ARROW_KEYS, 0, map->getHeight(), teleport->getY()); - possizer->Add(y_field, wxSizerFlags(3).Expand()); - z_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(teleport->getZ()), wxDefaultPosition, wxSize(-1, 20), wxSP_ARROW_KEYS, 0, MAP_MAX_LAYER, teleport->getZ()); - possizer->Add(z_field, wxSizerFlags(2).Expand()); - - subsizer->Add(possizer, wxSizerFlags(1).Expand()); - } - boxsizer->Add(subsizer, wxSizerFlags(1).Expand()); topsizer->Add(boxsizer, wxSizerFlags(0).Expand().Border(wxLEFT | wxRIGHT, 20)); + + if(teleport) { + destination_field = new PositionCtrl(this, "Destination", teleport->getX(), teleport->getY(), teleport->getZ(), map->getWidth(), map->getHeight()); + topsizer->Add(destination_field, wxSizerFlags(0).Expand().Border(wxLEFT | wxRIGHT, 20)); + } } // Others attributes @@ -363,7 +355,8 @@ OldPropertiesWindow::OldPropertiesWindow(wxWindow* win_parent, const Map* map, c depot_id_field(nullptr), splash_type_field(nullptr), text_field(nullptr), - description_field(nullptr) + description_field(nullptr), + destination_field(nullptr) { ASSERT(edit_monster); @@ -415,7 +408,8 @@ OldPropertiesWindow::OldPropertiesWindow(wxWindow* win_parent, const Map* map, c depot_id_field(nullptr), splash_type_field(nullptr), text_field(nullptr), - description_field(nullptr) + description_field(nullptr), + destination_field(nullptr) { ASSERT(edit_spawn_monster); @@ -455,7 +449,8 @@ OldPropertiesWindow::OldPropertiesWindow(wxWindow* win_parent, const Map* map, c depot_id_field(nullptr), splash_type_field(nullptr), text_field(nullptr), - description_field(nullptr) + description_field(nullptr), + destination_field(nullptr) { ASSERT(edit_npc); @@ -507,7 +502,8 @@ OldPropertiesWindow::OldPropertiesWindow(wxWindow* win_parent, const Map* map, c depot_id_field(nullptr), splash_type_field(nullptr), text_field(nullptr), - description_field(nullptr) + description_field(nullptr), + destination_field(nullptr) { ASSERT(edit_spawn_npc); @@ -663,10 +659,6 @@ void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) if(edit_item->canHoldDescription() && description_field) { description_field->GetValue(); } - Position new_dest; - if(teleport) { - new_dest = Position(x_field->GetValue(), y_field->GetValue(), z_field->GetValue()); - } uint8_t new_door_id = 0; if(door) { new_door_id = door_id_field->GetValue(); @@ -712,12 +704,14 @@ void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) } if(teleport) { - if(edit_map->getTile(new_dest) == nullptr || edit_map->getTile(new_dest)->isBlocking()) { + Position destination = destination_field->GetPosition(); + if(!edit_map->getTile(destination) || edit_map->getTile(destination)->isBlocking()) { int ret = g_gui.PopupDialog(this, "Warning", "This teleport leads nowhere, or to an invalid location. Do you want to change the destination?", wxYES | wxNO); if(ret == wxID_YES) { return; } } + teleport->setDestination(destination); } // Done validating, set the values. @@ -730,9 +724,6 @@ void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) if(door) { door->setDoorID(new_door_id); } - if(teleport) { - teleport->setDestination(new_dest); - } edit_item->setUniqueID(new_uid); edit_item->setActionID(new_aid); diff --git a/source/old_properties_window.h b/source/old_properties_window.h index aebd7d85..00b3a392 100644 --- a/source/old_properties_window.h +++ b/source/old_properties_window.h @@ -42,8 +42,6 @@ class OldPropertiesWindow : public ObjectPropertiesWindowBase void Update(); -protected: - protected: wxSpinCtrl* count_field; wxChoice* direction_field; @@ -51,9 +49,7 @@ class OldPropertiesWindow : public ObjectPropertiesWindowBase wxSpinCtrl* unique_id_field; wxSpinCtrl* door_id_field; wxChoice* depot_id_field; - wxSpinCtrl* x_field; - wxSpinCtrl* y_field; - wxSpinCtrl* z_field; + PositionCtrl* destination_field; wxChoice* splash_type_field; wxTextCtrl* text_field; wxTextCtrl* description_field; From d371035fe85db055d9129876ee425ffa6643199d Mon Sep 17 00:00:00 2001 From: Beats Date: Tue, 4 Apr 2023 00:52:40 -0400 Subject: [PATCH 07/45] Fix flood fill --- source/map_display.cpp | 8 +------- source/map_display.h | 5 ++--- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/source/map_display.cpp b/source/map_display.cpp index 59b97242..9b3d40a1 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -2613,13 +2613,7 @@ void MapCanvas::getTilesToDraw(int mouse_map_x, int mouse_map_y, int floor, Posi bool MapCanvas::floodFill(Map *map, const Position& center, int x, int y, GroundBrush* brush, PositionVector* positions) { - countMaxFills++; - if (countMaxFills > (BLOCK_SIZE * 4 * 4)) { - countMaxFills = 0; - return true; - } - - if(x <= 0 || y <= 0 || x >= BLOCK_SIZE || y >= BLOCK_SIZE) { + if(x < 0 || y < 0 || x > BLOCK_SIZE || y > BLOCK_SIZE) { return false; } diff --git a/source/map_display.h b/source/map_display.h index 6a6aa857..28bddd94 100644 --- a/source/map_display.h +++ b/source/map_display.h @@ -126,17 +126,16 @@ class MapCanvas : public wxGLCanvas { private: enum { - BLOCK_SIZE = 100 + BLOCK_SIZE = 64 }; - inline int getFillIndex(int x, int y) const { return x + BLOCK_SIZE * y; } + inline int getFillIndex(int x, int y) const noexcept { return ((y % BLOCK_SIZE) * BLOCK_SIZE) + (x % BLOCK_SIZE); } static bool processed[BLOCK_SIZE*BLOCK_SIZE]; Editor& editor; MapDrawer *drawer; int keyCode; - int countMaxFills = 0; // View related int floor; From 5fb26bced274b0efefe2d3a57f06cab1bd219eef Mon Sep 17 00:00:00 2001 From: Beats Date: Tue, 4 Apr 2023 00:56:59 -0400 Subject: [PATCH 08/45] Add function to get minimap/8bit color --- source/common.cpp | 10 ++++++ source/common.h | 2 ++ source/graphics.h | 67 --------------------------------------- source/map.cpp | 6 +++- source/map_drawer.cpp | 24 +++++++++----- source/map_drawer.h | 5 +-- source/minimap_window.cpp | 2 +- 7 files changed, 37 insertions(+), 79 deletions(-) diff --git a/source/common.cpp b/source/common.cpp index 000c2848..5abf298f 100644 --- a/source/common.cpp +++ b/source/common.cpp @@ -309,3 +309,13 @@ wxString b2yn(bool value) { return value ? "Yes" : "No"; } + +wxColor colorFromEightBit(int color) +{ + if(color <= 0 || color >= 216) + return wxColor(0, 0, 0); + const uint8_t red = (uint8_t)(int(color / 36) % 6 * 51); + const uint8_t green = (uint8_t)(int(color / 6) % 6 * 51); + const uint8_t blue = (uint8_t)(color % 6 * 51); + return wxColor(red, green, blue); +} diff --git a/source/common.h b/source/common.h index 652f1d24..b388c96c 100644 --- a/source/common.h +++ b/source/common.h @@ -78,4 +78,6 @@ bool posToClipboard(int fromx, int fromy, int fromz, int tox, int toy, int toz); // Returns 'yes' if the defined value is true or 'no' if it is false. wxString b2yn(bool v); +wxColor colorFromEightBit(int color); + #endif diff --git a/source/graphics.h b/source/graphics.h index a8654eca..ccfcd1c0 100644 --- a/source/graphics.h +++ b/source/graphics.h @@ -354,71 +354,4 @@ struct RGBQuad { } }; -static RGBQuad minimap_color[256] = { - RGBQuad(0, 0, 0), RGBQuad(0, 0, 51), RGBQuad(0, 0, 102), RGBQuad(0, 0, 153), // 0 - RGBQuad(0, 0, 204), RGBQuad(0, 0, 255), RGBQuad(0, 51, 0), RGBQuad(0, 51, 51), // 4 - RGBQuad(0, 51, 102), RGBQuad(0, 51, 153), RGBQuad(0, 51, 204), RGBQuad(0, 51, 255), // 8 - RGBQuad(0, 102, 0), RGBQuad(0, 102, 51), RGBQuad(0, 102, 102), RGBQuad(0, 102, 153), // 12 - RGBQuad(0, 102, 204), RGBQuad(0, 102, 255), RGBQuad(0, 153, 0), RGBQuad(0, 153, 51), // 16 - RGBQuad(0, 153, 102), RGBQuad(0, 153, 153), RGBQuad(0, 153, 204), RGBQuad(0, 153, 255), // 20 - RGBQuad(0, 204, 0), RGBQuad(0, 204, 51), RGBQuad(0, 204, 102), RGBQuad(0, 204, 153), // 24 - RGBQuad(0, 204, 204), RGBQuad(0, 204, 255), RGBQuad(0, 255, 0), RGBQuad(0, 255, 51), // 28 - RGBQuad(0, 255, 102), RGBQuad(0, 255, 153), RGBQuad(0, 255, 204), RGBQuad(0, 255, 255), // 32 - RGBQuad(51, 0, 0), RGBQuad(51, 0, 51), RGBQuad(51, 0, 102), RGBQuad(51, 0, 153), // 36 - RGBQuad(51, 0, 204), RGBQuad(51, 0, 255), RGBQuad(51, 51, 0), RGBQuad(51, 51, 51), // 40 - RGBQuad(51, 51, 102), RGBQuad(51, 51, 153), RGBQuad(51, 51, 204), RGBQuad(51, 51, 255), // 44 - RGBQuad(51, 102, 0), RGBQuad(51, 102, 51), RGBQuad(51, 102, 102), RGBQuad(51, 102, 153), // 48 - RGBQuad(51, 102, 204), RGBQuad(51, 102, 255), RGBQuad(51, 153, 0), RGBQuad(51, 153, 51), // 52 - RGBQuad(51, 153, 102), RGBQuad(51, 153, 153), RGBQuad(51, 153, 204), RGBQuad(51, 153, 255), // 56 - RGBQuad(51, 204, 0), RGBQuad(51, 204, 51), RGBQuad(51, 204, 102), RGBQuad(51, 204, 153), // 60 - RGBQuad(51, 204, 204), RGBQuad(51, 204, 255), RGBQuad(51, 255, 0), RGBQuad(51, 255, 51), // 64 - RGBQuad(51, 255, 102), RGBQuad(51, 255, 153), RGBQuad(51, 255, 204), RGBQuad(51, 255, 255), // 68 - RGBQuad(102, 0, 0), RGBQuad(102, 0, 51), RGBQuad(102, 0, 102), RGBQuad(102, 0, 153), // 72 - RGBQuad(102, 0, 204), RGBQuad(102, 0, 255), RGBQuad(102, 51, 0), RGBQuad(102, 51, 51), // 76 - RGBQuad(102, 51, 102), RGBQuad(102, 51, 153), RGBQuad(102, 51, 204), RGBQuad(102, 51, 255), // 80 - RGBQuad(102, 102, 0), RGBQuad(102, 102, 51), RGBQuad(102, 102, 102), RGBQuad(102, 102, 153), // 84 - RGBQuad(102, 102, 204), RGBQuad(102, 102, 255), RGBQuad(102, 153, 0), RGBQuad(102, 153, 51), // 88 - RGBQuad(102, 153, 102), RGBQuad(102, 153, 153), RGBQuad(102, 153, 204), RGBQuad(102, 153, 255), // 92 - RGBQuad(102, 204, 0), RGBQuad(102, 204, 51), RGBQuad(102, 204, 102), RGBQuad(102, 204, 153), // 96 - RGBQuad(102, 204, 204), RGBQuad(102, 204, 255), RGBQuad(102, 255, 0), RGBQuad(102, 255, 51), // 100 - RGBQuad(102, 255, 102), RGBQuad(102, 255, 153), RGBQuad(102, 255, 204), RGBQuad(102, 255, 255), // 104 - RGBQuad(153, 0, 0), RGBQuad(153, 0, 51), RGBQuad(153, 0, 102), RGBQuad(153, 0, 153), // 108 - RGBQuad(153, 0, 204), RGBQuad(153, 0, 255), RGBQuad(153, 51, 0), RGBQuad(153, 51, 51), // 112 - RGBQuad(153, 51, 102), RGBQuad(153, 51, 153), RGBQuad(153, 51, 204), RGBQuad(153, 51, 255), // 116 - RGBQuad(153, 102, 0), RGBQuad(153, 102, 51), RGBQuad(153, 102, 102), RGBQuad(153, 102, 153), // 120 - RGBQuad(153, 102, 204), RGBQuad(153, 102, 255), RGBQuad(153, 153, 0), RGBQuad(153, 153, 51), // 124 - RGBQuad(153, 153, 102), RGBQuad(153, 153, 153), RGBQuad(153, 153, 204), RGBQuad(153, 153, 255), // 128 - RGBQuad(153, 204, 0), RGBQuad(153, 204, 51), RGBQuad(153, 204, 102), RGBQuad(153, 204, 153), // 132 - RGBQuad(153, 204, 204), RGBQuad(153, 204, 255), RGBQuad(153, 255, 0), RGBQuad(153, 255, 51), // 136 - RGBQuad(153, 255, 102), RGBQuad(153, 255, 153), RGBQuad(153, 255, 204), RGBQuad(153, 255, 255), // 140 - RGBQuad(204, 0, 0), RGBQuad(204, 0, 51), RGBQuad(204, 0, 102), RGBQuad(204, 0, 153), // 144 - RGBQuad(204, 0, 204), RGBQuad(204, 0, 255), RGBQuad(204, 51, 0), RGBQuad(204, 51, 51), // 148 - RGBQuad(204, 51, 102), RGBQuad(204, 51, 153), RGBQuad(204, 51, 204), RGBQuad(204, 51, 255), // 152 - RGBQuad(204, 102, 0), RGBQuad(204, 102, 51), RGBQuad(204, 102, 102), RGBQuad(204, 102, 153), // 156 - RGBQuad(204, 102, 204), RGBQuad(204, 102, 255), RGBQuad(204, 153, 0), RGBQuad(204, 153, 51), // 160 - RGBQuad(204, 153, 102), RGBQuad(204, 153, 153), RGBQuad(204, 153, 204), RGBQuad(204, 153, 255), // 164 - RGBQuad(204, 204, 0), RGBQuad(204, 204, 51), RGBQuad(204, 204, 102), RGBQuad(204, 204, 153), // 168 - RGBQuad(204, 204, 204), RGBQuad(204, 204, 255), RGBQuad(204, 255, 0), RGBQuad(204, 255, 51), // 172 - RGBQuad(204, 255, 102), RGBQuad(204, 255, 153), RGBQuad(204, 255, 204), RGBQuad(204, 255, 255), // 176 - RGBQuad(255, 0, 0), RGBQuad(255, 0, 51), RGBQuad(255, 0, 102), RGBQuad(255, 0, 153), // 180 - RGBQuad(255, 0, 204), RGBQuad(255, 0, 255), RGBQuad(255, 51, 0), RGBQuad(255, 51, 51), // 184 - RGBQuad(255, 51, 102), RGBQuad(255, 51, 153), RGBQuad(255, 51, 204), RGBQuad(255, 51, 255), // 188 - RGBQuad(255, 102, 0), RGBQuad(255, 102, 51), RGBQuad(255, 102, 102), RGBQuad(255, 102, 153), // 192 - RGBQuad(255, 102, 204), RGBQuad(255, 102, 255), RGBQuad(255, 153, 0), RGBQuad(255, 153, 51), // 196 - RGBQuad(255, 153, 102), RGBQuad(255, 153, 153), RGBQuad(255, 153, 204), RGBQuad(255, 153, 255), // 200 - RGBQuad(255, 204, 0), RGBQuad(255, 204, 51), RGBQuad(255, 204, 102), RGBQuad(255, 204, 153), // 204 - RGBQuad(255, 204, 204), RGBQuad(255, 204, 255), RGBQuad(255, 255, 0), RGBQuad(255, 255, 51), // 208 - RGBQuad(255, 255, 102), RGBQuad(255, 255, 153), RGBQuad(255, 255, 204), RGBQuad(255, 255, 255), // 212 - RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 216 - RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 220 - RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 224 - RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 228 - RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 232 - RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 236 - RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 240 - RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 244 - RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 248 - RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0) // 252 -}; - #endif diff --git a/source/map.cpp b/source/map.cpp index cb4c0d9c..82fc01e2 100644 --- a/source/map.cpp +++ b/source/map.cpp @@ -586,6 +586,10 @@ bool Map::exportMinimap(FileName filename, int floor /*= GROUND_LAYER*/, bool di if(size() == 0) return true; + uint32_t minimap_colors[256]; + for(int i = 0; i < 256; ++i) + minimap_colors[i] = colorFromEightBit(i).GetRGB(); + for(MapIterator mit = begin(); mit != end(); ++mit) { if((*mit)->get() == nullptr || (*mit)->empty()) continue; @@ -695,7 +699,7 @@ bool Map::exportMinimap(FileName filename, int floor /*= GROUND_LAYER*/, bool di // Write the color palette for(int i = 0; i < 256; ++i) - fh.addU32(uint32_t(minimap_color[i])); + fh.addU32(minimap_colors[i]); // Bitmap width must be divisible by four, calculate how much padding we need int padding = ((minimap_width & 3) != 0? 4-(minimap_width & 3) : 0); diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index 43688a1e..203c0860 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -1526,11 +1526,8 @@ void MapDrawer::DrawTile(TileLocation* location) if(only_colors) { if(as_minimap) { - uint8_t color = tile->getMiniMapColor(); - r = (uint8_t)(int(color / 36) % 6 * 51); - g = (uint8_t)(int(color / 6) % 6 * 51); - b = (uint8_t)(color % 6 * 51); - glBlitSquare(draw_x, draw_y, r, g, b, 255); + wxColor color = colorFromEightBit(tile->getMiniMapColor()); + glBlitSquare(draw_x, draw_y, color); } else if(r != 255 || g != 255 || b != 255) { glBlitSquare(draw_x, draw_y, r, g, b, 128); @@ -1937,7 +1934,18 @@ void MapDrawer::glBlitSquare(int sx, int sy, int red, int green, int blue, int a glEnd(); } -void MapDrawer::glColor(wxColor color) +void MapDrawer::glBlitSquare(int x, int y, const wxColor& color) +{ + glColor4ub(color.Red(), color.Green(), color.Blue(), color.Alpha()); + glBegin(GL_QUADS); + glVertex2f(x, y); + glVertex2f(x + TILE_SIZE, y); + glVertex2f(x + TILE_SIZE, y + TILE_SIZE); + glVertex2f(x, y + TILE_SIZE); + glEnd(); +} + +void MapDrawer::glColor(const wxColor& color) { glColor4ub(color.Red(), color.Green(), color.Blue(), color.Alpha()); } @@ -1998,11 +2006,11 @@ void MapDrawer::glColorCheck(Brush* brush, const Position& pos) glColor(COLOR_INVALID); } -void MapDrawer::drawRect(int x, int y, int w, int h, const wxColour& color, int width) +void MapDrawer::drawRect(int x, int y, int w, int h, const wxColor& color, int width) { glLineWidth(width); glColor4ub(color.Red(), color.Green(), color.Blue(), color.Alpha()); - glBegin(GL_LINE_LOOP); + glBegin(GL_LINE_STRIP); glVertex2f(x, y); glVertex2f(x + w, y); glVertex2f(x + w, y + h); diff --git a/source/map_drawer.h b/source/map_drawer.h index 8368e8a6..5e5176a2 100644 --- a/source/map_drawer.h +++ b/source/map_drawer.h @@ -169,10 +169,11 @@ class MapDrawer void getColor(Brush* brush, const Position& position, uint8_t &r, uint8_t &g, uint8_t &b); void glBlitTexture(int x, int y, int textureId, int red, int green, int blue, int alpha, bool adjustZoom = false); void glBlitSquare(int sx, int sy, int red, int green, int blue, int alpha); - void glColor(wxColor color); + void glBlitSquare(int x, int y, const wxColor& color); + void glColor(const wxColor& color); void glColor(BrushColor color); void glColorCheck(Brush* brush, const Position& pos); - void drawRect(int x, int y, int w, int h, const wxColour& color, int width = 1); + void drawRect(int x, int y, int w, int h, const wxColor& color, int width = 1); private: void getDrawPosition(const Position& position, int &x, int &y); diff --git a/source/minimap_window.cpp b/source/minimap_window.cpp index cd70f6d4..ad3b7cd6 100644 --- a/source/minimap_window.cpp +++ b/source/minimap_window.cpp @@ -40,7 +40,7 @@ MinimapWindow::MinimapWindow(wxWindow* parent) : update_timer(this) { for(int i = 0; i < 256; ++i) { - pens[i] = newd wxPen(wxColor(minimap_color[i].red, minimap_color[i].green, minimap_color[i].blue)); + pens[i] = new wxPen(colorFromEightBit(i)); } } From c620771c3f8e8e333f297a7854d4090defbf6822 Mon Sep 17 00:00:00 2001 From: Beats Date: Tue, 4 Apr 2023 01:02:07 -0400 Subject: [PATCH 09/45] Small code cleanup --- source/map_drawer.cpp | 29 ++++++++++++++++++----------- source/map_drawer.h | 3 +++ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index 203c0860..9b622339 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -113,6 +113,18 @@ void DrawingOptions::SetIngame() hide_items_when_zoomed = false; } +bool DrawingOptions::isOnlyColors() const noexcept +{ + return show_as_minimap || show_only_colors; +} + +bool DrawingOptions::isTileIndicators() const noexcept +{ + if(isOnlyColors()) + return false; + return show_pickupables || show_moveables || show_houses || show_spawns_monster || show_spawns_npc; +} + MapDrawer::MapDrawer(MapCanvas* canvas) : canvas(canvas), editor(canvas->editor) { //// @@ -249,7 +261,8 @@ void MapDrawer::DrawMap() current_house_id = brush->asHouseExit()->getHouseID(); } - bool only_colors = options.show_as_minimap || options.show_only_colors; + bool only_colors = options.isOnlyColors(); + bool tile_indicators = options.isTileIndicators(); // Enable texture mode if(!only_colors) @@ -297,12 +310,7 @@ void MapDrawer::DrawMap() DrawTile(nd->getTile(map_x, map_y, map_z)); } } - if (!options.show_as_minimap && !options.show_only_colors && - (options.show_pickupables - || options.show_moveables - || options.show_houses - || options.show_spawns_monster - || options.show_spawns_npc)) { + if (tile_indicators) { for(int map_x = 0; map_x < 4; ++map_x) { for(int map_y = 0; map_y < 4; ++map_y) { DrawTileIndicators(nd->getTile(map_x, map_y, map_z)); @@ -1452,8 +1460,7 @@ void MapDrawer::DrawTile(TileLocation* location) WriteTooltip(waypoint, tooltip); } - bool as_minimap = options.show_as_minimap; - bool only_colors = as_minimap || options.show_only_colors; + bool only_colors = options.isOnlyColors(); const Position& position = location->getPosition(); int draw_x, draw_y; @@ -1462,7 +1469,7 @@ void MapDrawer::DrawTile(TileLocation* location) uint8_t r = 255,g = 255,b = 255; if(tile->ground || only_colors) { - if(!as_minimap) { + if(!options.show_as_minimap) { bool showspecial = options.show_only_colors || options.show_special_tiles; if(options.show_blocking && tile->isBlocking() && tile->size() > 0) { @@ -1525,7 +1532,7 @@ void MapDrawer::DrawTile(TileLocation* location) } if(only_colors) { - if(as_minimap) { + if(options.show_as_minimap) { wxColor color = colorFromEightBit(tile->getMiniMapColor()); glBlitSquare(draw_x, draw_y, color); } diff --git a/source/map_drawer.h b/source/map_drawer.h index 5e5176a2..891e2557 100644 --- a/source/map_drawer.h +++ b/source/map_drawer.h @@ -50,6 +50,9 @@ struct DrawingOptions { void SetIngame(); void SetDefault(); + bool isOnlyColors() const noexcept; + bool isTileIndicators() const noexcept; + bool transparent_floors; bool transparent_items; bool show_ingame_box; From 877385e3ab8a75bf3e9703c54a8521505db6144e Mon Sep 17 00:00:00 2001 From: Beats Date: Tue, 4 Apr 2023 01:17:25 -0400 Subject: [PATCH 10/45] Cleanup Position --- source/action.cpp | 10 +++--- source/complexitem.h | 2 +- source/house.cpp | 4 +-- source/map_window.cpp | 2 +- source/old_properties_window.cpp | 4 +-- source/palette_waypoints.cpp | 2 +- source/position.h | 58 +++++++++++++------------------- source/waypoints.cpp | 2 +- 8 files changed, 35 insertions(+), 49 deletions(-) diff --git a/source/action.cpp b/source/action.cpp index f426ffc2..7384b859 100644 --- a/source/action.cpp +++ b/source/action.cpp @@ -281,9 +281,8 @@ void Action::commit(DirtyList* dirty_list) TileLocation* newtile = editor.map.getTileL(p->second); // Only need to remove from old if it actually exists - if(p->second != Position()) - if(oldtile && oldtile->getWaypointCount() > 0) - oldtile->decreaseWaypointCount(); + if(p->second.isValid() && oldtile && oldtile->getWaypointCount() > 0) + oldtile->decreaseWaypointCount(); newtile->increaseWaypointCount(); @@ -418,9 +417,8 @@ void Action::undo(DirtyList* dirty_list) TileLocation* newtile = editor.map.getTileL(p->second); // Only need to remove from old if it actually exists - if(p->second != Position()) - if(oldtile && oldtile->getWaypointCount() > 0) - oldtile->decreaseWaypointCount(); + if(p->second.isValid() && oldtile && oldtile->getWaypointCount() > 0) + oldtile->decreaseWaypointCount(); newtile->increaseWaypointCount(); diff --git a/source/complexitem.h b/source/complexitem.h index ebd17e2f..3b6f57d4 100644 --- a/source/complexitem.h +++ b/source/complexitem.h @@ -74,7 +74,7 @@ class Teleport : public Item int getZ() const noexcept { return destination.z; } void setDestination(const Position& position) { destination = position; } - bool hasDestination() const { return destination != Position(); } + bool hasDestination() const { return destination.isValid(); } protected: // We could've made this public and skip the functions, but that would diff --git a/source/house.cpp b/source/house.cpp index fa753528..dc345771 100644 --- a/source/house.cpp +++ b/source/house.cpp @@ -187,10 +187,10 @@ std::string House::getDescription() void House::setExit(Map* targetmap, const Position& pos) { // This might fail when the user decides to put an exit at 0,0,0, let's just hope noone does (Noone SHOULD, so there is no problem? Hm?) - if(pos == exit || pos == Position()) + if(pos == exit || !pos.isValid()) return; - if(exit != Position()) { + if(exit.isValid()) { Tile* oldexit = targetmap->getTile(exit); if(oldexit) oldexit->removeHouseExit(this); diff --git a/source/map_window.cpp b/source/map_window.cpp index 41c8be73..b4f99baf 100644 --- a/source/map_window.cpp +++ b/source/map_window.cpp @@ -136,7 +136,7 @@ Position MapWindow::GetScreenCenterPosition() void MapWindow::SetScreenCenterPosition(const Position& position, bool showIndicator) { - if(position == Position()) + if(!position.isValid()) return; int x = position.x * TILE_SIZE; diff --git a/source/old_properties_window.cpp b/source/old_properties_window.cpp index 3dbf3d73..bb7ca352 100644 --- a/source/old_properties_window.cpp +++ b/source/old_properties_window.cpp @@ -691,9 +691,7 @@ void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) const House* house = edit_map->houses.getHouse(edit_tile->getHouseID()); if(house) { Position pos = house->getDoorPositionByID(new_door_id); - if(pos == Position()) { - // Do nothing - } else if(pos != edit_tile->getPosition()) { + if(pos.isValid() && pos != edit_tile->getPosition()) { int ret = g_gui.PopupDialog(this, "Warning", "This doorid conflicts with another one in this house, are you sure you want to continue?", wxYES | wxNO); if(ret == wxID_NO) { return; diff --git a/source/palette_waypoints.cpp b/source/palette_waypoints.cpp index a9f1e9c1..add1e2e0 100644 --- a/source/palette_waypoints.cpp +++ b/source/palette_waypoints.cpp @@ -117,7 +117,7 @@ void WaypointPalettePanel::OnUpdate() { if(wxTextCtrl* tc = waypoint_list->GetEditControl()) { Waypoint* wp = map->waypoints.getWaypoint(nstr(tc->GetValue())); - if(wp && wp->pos == Position()) { + if(wp && !wp->pos.isValid()) { if(map->getTile(wp->pos)) map->getTileL(wp->pos)->decreaseWaypointCount(); map->waypoints.removeWaypoint(wp->name); diff --git a/source/position.h b/source/position.h index aec67736..62dccebf 100644 --- a/source/position.h +++ b/source/position.h @@ -23,8 +23,6 @@ #include #include -class SmallPosition; - class Position { public: // We use int since it's the native machine type and can be several times faster than @@ -33,20 +31,20 @@ class Position { int x, y, z; Position() : x(0), y(0), z(0) {} - Position(int _x, int _y, int _z) : x(_x), y(_y), z(_z) {} + Position(int x, int y, int z) : x(x), y(y), z(z) {} - bool operator<(const Position& p) const { - if(z < p.z) + bool operator<(const Position& other) const noexcept { + if(z < other.z) return true; - if(z > p.z) + if(z > other.z) return false; - if(y < p.y) + if(y < other.y) return true; - if(y > p.y) + if(y > other.y) return false; - if(x < p.x) + if(x < other.x) return true; //if(x > p.x) // return false; @@ -55,40 +53,36 @@ class Position { return false; } - bool operator>(const Position& p) const { - return !(*this < p); + bool operator>(const Position& other) const noexcept { + return !(*this < other); } - Position operator-(const Position& p) const { - Position newpos; - newpos.x = x - p.x; - newpos.y = y - p.y; - newpos.z = z - p.z; - return newpos; + Position operator-(const Position& other) const noexcept { + return Position(x - other.x, y - other.y, z - other.z); } - Position operator+(const Position& p) const { - Position newpos; - newpos.x = x + p.x; - newpos.y = y + p.y; - newpos.z = z + p.z; - return newpos; + Position operator+(const Position& other) const noexcept { + return Position(x + other.x, y + other.y, z + other.z); } - Position& operator+=(const Position& p) { - *this = *this + p; + Position& operator+=(const Position& other) { + *this = *this + other; return *this; } - bool operator==(const Position& p) const noexcept { - return p.x == x && p.y == y && p.z == z; + bool operator==(const Position& other) const noexcept { + return other.z == z && other.x == x && other.y == y; } - bool operator!=(const Position& p) const { - return ! (*this == p); + bool operator!=(const Position& other) const noexcept { + return !(*this == other); } - bool isValid() const; + bool isValid() const noexcept { + if(x == 0 && y == 0 && z == 0) + return false; + return z >= 0 && z <= MAP_MAX_LAYER && x >= 0 && x <= MAP_MAX_WIDTH && y >= 0 && y <= MAP_MAX_HEIGHT; + } }; inline std::ostream& operator<<(std::ostream& os, const Position& pos) { @@ -117,10 +111,6 @@ inline std::istream& operator>>(std::istream& is, Position& pos) { return is; } -inline bool Position::isValid() const { - return x >= 0 && x <= MAP_MAX_WIDTH && y >= 0 && y <= MAP_MAX_HEIGHT && z >= 0 && z <= MAP_MAX_LAYER; -} - inline Position abs(const Position& position) { return Position( std::abs(position.x), diff --git a/source/waypoints.cpp b/source/waypoints.cpp index a5c70a82..918e36cc 100644 --- a/source/waypoints.cpp +++ b/source/waypoints.cpp @@ -23,7 +23,7 @@ void Waypoints::addWaypoint(Waypoint* wp) { removeWaypoint(wp->name); - if(wp->pos != Position()) { + if(wp->pos.isValid()) { Tile* t = map.getTile(wp->pos); if(!t) map.setTile(wp->pos, t = map.allocator(map.createTileL(wp->pos))); From 2fc26fa9e17d272251fcc343eda82afa01915036 Mon Sep 17 00:00:00 2001 From: Beats Date: Tue, 4 Apr 2023 19:35:33 -0400 Subject: [PATCH 11/45] Code cleanup and small optimizations --- source/graphics.cpp | 22 +- source/graphics.h | 8 +- source/item.cpp | 4 +- source/item.h | 3 +- source/map_drawer.cpp | 699 +++++++++++++++++++++--------------------- source/map_drawer.h | 9 +- 6 files changed, 372 insertions(+), 373 deletions(-) diff --git a/source/graphics.cpp b/source/graphics.cpp index 2e299ed6..2d7882c0 100644 --- a/source/graphics.cpp +++ b/source/graphics.cpp @@ -604,8 +604,9 @@ bool GraphicManager::loadSpriteMetadataFlags(FileReadHandle& file, GameSprite* s file.getU16(offset_x); file.getU16(offset_y); - sType->drawoffset_x = offset_x; - sType->drawoffset_y = offset_y; + sType->draw_offset = wxPoint(offset_x, offset_y); + } else { + sType->draw_offset = wxPoint(8, 8); } break; } @@ -831,8 +832,6 @@ GameSprite::GameSprite() : numsprites(0), animator(nullptr), draw_height(0), - drawoffset_x(0), - drawoffset_y(0), minimap_color(0) { dc[SPRITE_SIZE_16x16] = nullptr; @@ -866,21 +865,6 @@ void GameSprite::unloadDC() dc[SPRITE_SIZE_32x32] = nullptr; } -int GameSprite::getDrawHeight() const -{ - return draw_height; -} - -std::pair GameSprite::getDrawOffset() const -{ - return std::make_pair(drawoffset_x, drawoffset_y); -} - -uint8_t GameSprite::getMiniMapColor() const -{ - return minimap_color; -} - int GameSprite::getIndex(int width, int height, int layer, int pattern_x, int pattern_y, int pattern_z, int frame) const { return ((((((frame % this->frames) * diff --git a/source/graphics.h b/source/graphics.h index ccfcd1c0..f06bc3d5 100644 --- a/source/graphics.h +++ b/source/graphics.h @@ -84,9 +84,9 @@ class GameSprite : public Sprite{ void clean(int time); - int getDrawHeight() const; - std::pair getDrawOffset() const; - uint8_t getMiniMapColor() const; + uint16_t getDrawHeight() const noexcept { return draw_height; } + const wxPoint& getDrawOffset() const noexcept { return draw_offset; } + uint8_t getMiniMapColor() const noexcept { return minimap_color; } static GameSprite* createFromBitmap(const wxArtID& bitmapId); @@ -190,7 +190,7 @@ class GameSprite : public Sprite{ uint16_t draw_height; uint16_t drawoffset_x; - uint16_t drawoffset_y; + wxPoint draw_offset; uint16_t minimap_color; diff --git a/source/item.cpp b/source/item.cpp index 028c6025..97fbcdb1 100644 --- a/source/item.cpp +++ b/source/item.cpp @@ -227,13 +227,13 @@ bool Item::hasProperty(enum ITEMPROPERTY prop) const return false; } -std::pair Item::getDrawOffset() const +wxPoint Item::getDrawOffset() const { ItemType& it = g_items[id]; if(it.sprite != nullptr) { return it.sprite->getDrawOffset(); } - return std::make_pair(0,0); + return wxPoint(0, 0); } double Item::getWeight() const diff --git a/source/item.h b/source/item.h index ecbde259..8e1bc0e7 100644 --- a/source/item.h +++ b/source/item.h @@ -175,8 +175,7 @@ class Item : public ItemAttributes // Drawing related uint8_t getMiniMapColor() const; - int getHeight() const; - std::pair getDrawOffset() const; + wxPoint getDrawOffset() const; // Item types bool hasProperty(enum ITEMPROPERTY prop) const; diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index 9b622339..b8df8025 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -143,7 +143,7 @@ void MapDrawer::SetupVars() dragging = canvas->dragging; dragging_draw = canvas->dragging_draw; - zoom = (float)canvas->GetZoom(); + zoom = static_cast(canvas->GetZoom()); tile_size = int(TILE_SIZE / zoom); // after zoom floor = canvas->GetFloor(); @@ -193,7 +193,7 @@ void MapDrawer::SetupGL() void MapDrawer::Release() { - for(std::vector::const_iterator it = tooltips.begin(); it != tooltips.end(); ++it) { + for(auto it = tooltips.begin(); it != tooltips.end(); ++it) { delete *it; } tooltips.clear(); @@ -246,6 +246,28 @@ inline int getFloorAdjustment(int floor) return TILE_SIZE * (GROUND_LAYER - floor); } +void MapDrawer::DrawShade(int map_z) +{ + bool only_colors = options.isOnlyColors(); + if(map_z == end_z && start_z != end_z) { + if(!only_colors) + glDisable(GL_TEXTURE_2D); + + float x = screensize_x * zoom; + float y = screensize_y * zoom; + glColor4ub(0, 0, 0, 128); + glBegin(GL_QUADS); + glVertex2f(0, y); + glVertex2f(x, y); + glVertex2f(x,0); + glVertex2f(0,0); + glEnd(); + + if(!only_colors) + glEnable(GL_TEXTURE_2D); + } +} + void MapDrawer::DrawMap() { bool live_client = editor.IsLiveClient(); @@ -269,21 +291,8 @@ void MapDrawer::DrawMap() glEnable(GL_TEXTURE_2D); for(int map_z = start_z; map_z >= superend_z; map_z--) { - if(map_z == end_z && start_z != end_z && options.show_shade) { - // Draw shade - if(!only_colors) - glDisable(GL_TEXTURE_2D); - - glColor4ub(0, 0, 0, 128); - glBegin(GL_QUADS); - glVertex2f(0,int(screensize_y*zoom)); - glVertex2f(int(screensize_x*zoom),int(screensize_y*zoom)); - glVertex2f(int(screensize_x*zoom),0); - glVertex2f(0,0); - glEnd(); - - if(!only_colors) - glEnable(GL_TEXTURE_2D); + if(options.show_shade) { + DrawShade(map_z); } if(map_z >= end_z) { @@ -296,12 +305,10 @@ void MapDrawer::DrawMap() for(int nd_map_y = nd_start_y; nd_map_y <= nd_end_y; nd_map_y += 4) { QTreeNode* nd = editor.map.getLeaf(nd_map_x, nd_map_y); if(!nd) { - if(live_client) { - nd = editor.map.createLeaf(nd_map_x, nd_map_y); - nd->setVisible(false, false); - } - else + if(!live_client) continue; + nd = editor.map.createLeaf(nd_map_x, nd_map_y); + nd->setVisible(false, false); } if(!live_client || nd->isVisible(map_z > GROUND_LAYER)) { @@ -344,98 +351,106 @@ void MapDrawer::DrawMap() glEnable(GL_TEXTURE_2D); // Draws the doodad preview or the paste preview (or import preview) - if(g_gui.secondary_map != nullptr && !options.ingame) { - Position normalPos; - Position to(mouse_map_x, mouse_map_y, floor); - - if(canvas->isPasting()) { - normalPos = editor.copybuffer.getPosition(); - } else if(brush && brush->isDoodad()) { - normalPos = Position(0x8000, 0x8000, 0x8); + DrawSecondaryMap(map_z); + + --start_x; + --start_y; + ++end_x; + ++end_y; + } + + if(!only_colors) + glEnable(GL_TEXTURE_2D); +} + +void MapDrawer::DrawSecondaryMap(int map_z) +{ + if(options.ingame) + return; + + BaseMap* secondary_map = g_gui.secondary_map; + if(!secondary_map) return; + + Position normal_pos; + Position to_pos(mouse_map_x, mouse_map_y, floor); + + if(canvas->isPasting()) { + normal_pos = editor.copybuffer.getPosition(); + } else { + Brush* brush = g_gui.GetCurrentBrush(); + if(brush && brush->isDoodad()) { + normal_pos = Position(0x8000, 0x8000, 0x8); + } + } + + for(int map_x = start_x; map_x <= end_x; map_x++) { + for(int map_y = start_y; map_y <= end_y; map_y++) { + Position final_pos(map_x, map_y, map_z); + Position pos = normal_pos + final_pos - to_pos; + if(pos.z < 0 || pos.z >= MAP_LAYERS) { + continue; } - for(int map_x = start_x; map_x <= end_x; map_x++) { - for(int map_y = start_y; map_y <= end_y; map_y++) { - Position final(map_x, map_y, map_z); - Position pos = normalPos + final - to; - //Position pos = topos + copypos - Position(map_x, map_y, map_z); - if(pos.z >= MAP_LAYERS || pos.z < 0) { - continue; + Tile* tile = secondary_map->getTile(pos); + if(!tile) continue; + + int draw_x, draw_y; + getDrawPosition(final_pos, draw_x, draw_y); + + // Draw ground + uint8_t r = 160, g = 160, b = 160; + if(tile->ground) { + if(options.show_blocking && tile->isBlocking()) { + g = g/3*2; + b = b/3*2; + } + if(options.show_houses && tile->isHouseTile()) { + if(tile->getHouseID() == current_house_id) { + r /= 2; + } else { + r /= 2; + g /= 2; } + } else if(options.show_special_tiles && tile->isPZ()) { + r /= 2; + b /= 2; + } + if(options.show_special_tiles && tile->getMapFlags() & TILESTATE_PVPZONE) { + r = r/3*2; + b = r/3*2; + } + if(options.show_special_tiles && tile->getMapFlags() & TILESTATE_NOLOGOUT) { + b /= 2; + } + if(options.show_special_tiles && tile->getMapFlags() & TILESTATE_NOPVP) { + g /= 2; + } + BlitItem(draw_x, draw_y, tile, tile->ground, true, r, g, b, 160); + } - Tile* tile = g_gui.secondary_map->getTile(pos); - if(tile) { - // Compensate for underground/overground - int offset; - if(map_z <= GROUND_LAYER) - offset = (GROUND_LAYER - map_z) * TILE_SIZE; - else - offset = TILE_SIZE * (floor - map_z); - - int draw_x = ((map_x * TILE_SIZE) - view_scroll_x) - offset; - int draw_y = ((map_y * TILE_SIZE) - view_scroll_y) - offset; - - // Draw ground - uint8_t r = 160, g = 160, b = 160; - if(tile->ground) { - if(tile->isBlocking() && options.show_blocking) { - g = g/3*2; - b = b/3*2; - } - if(tile->isHouseTile() && options.show_houses) { - if((int)tile->getHouseID() == current_house_id) { - r /= 2; - } else { - r /= 2; - g /= 2; - } - } else if(options.show_special_tiles && tile->isPZ()) { - r /= 2; - b /= 2; - } - if(options.show_special_tiles && tile->getMapFlags() & TILESTATE_PVPZONE) { - r = r/3*2; - b = r/3*2; - } - if(options.show_special_tiles && tile->getMapFlags() & TILESTATE_NOLOGOUT) { - b /= 2; - } - if(options.show_special_tiles && tile->getMapFlags() & TILESTATE_NOPVP) { - g /= 2; - } - BlitItem(draw_x, draw_y, tile, tile->ground, true, r, g, b, 160); - } + bool hidden = options.hide_items_when_zoomed && zoom > 10.f; - // Draw items on the tile - if(zoom <= 10.0 || !options.hide_items_when_zoomed) { - ItemVector::iterator it; - for(it = tile->items.begin(); it != tile->items.end(); it++) { - if((*it)->isBorder()) { - BlitItem(draw_x, draw_y, tile, *it, true, 160, r, g, b); - } else { - BlitItem(draw_x, draw_y, tile, *it, true, 160, 160, 160, 160); - } - } - // Monsters - if(tile->monster && options.show_monsters) - BlitCreature(draw_x, draw_y, tile->monster); - // Npcs - if(tile->npc && options.show_npcs) - BlitCreature(draw_x, draw_y, tile->npc); - } + // Draw items + if(!hidden && !tile->items.empty()) { + for(const Item* item : tile->items) { + if(item->isBorder()) { + BlitItem(draw_x, draw_y, tile, item, true, 160, r, g, b); + } else { + BlitItem(draw_x, draw_y, tile, item, true, 160, 160, 160, 160); } } } - } - --start_x; - --start_y; - ++end_x; - ++end_y; + // Monsters + if(!hidden && options.show_monsters && tile->monster) { + BlitCreature(draw_x, draw_y, tile->monster); + } + // NPCS + if(!hidden && options.show_npcs && tile->npc) { + BlitCreature(draw_x, draw_y, tile->npc); + } + } } - - if(!only_colors) - glEnable(GL_TEXTURE_2D); } void MapDrawer::DrawIngameBox() @@ -519,8 +534,8 @@ void MapDrawer::DrawIngameBox() glVertex2f(box_start_x, box_start_y); glEnd(); - box_start_x += 7 * TILE_SIZE; - box_start_y += 5 * TILE_SIZE; + box_start_x += ((CLIENT_MAP_WIDTH/2)-2) * TILE_SIZE; + box_start_y += ((CLIENT_MAP_HEIGHT/2)-2) * TILE_SIZE; box_end_x = box_start_x + TILE_SIZE; box_end_y = box_start_y + TILE_SIZE; @@ -556,58 +571,57 @@ void MapDrawer::DrawGrid() void MapDrawer::DrawDraggingShadow() { + if(!dragging || options.ingame || editor.selection.isBusy()) + return; + glEnable(GL_TEXTURE_2D); // Draw dragging shadow - if(!editor.selection.isBusy() && dragging && !options.ingame) { - for(TileSet::iterator tit = editor.selection.begin(); tit != editor.selection.end(); tit++) { - Tile* tile = *tit; - Position pos = tile->getPosition(); + for(Tile* tile : editor.selection) { + int move_z = canvas->drag_start_z - floor; + int move_x = canvas->drag_start_x - mouse_map_x; + int move_y = canvas->drag_start_y - mouse_map_y; - int move_x, move_y, move_z; - move_x = canvas->drag_start_x - mouse_map_x; - move_y = canvas->drag_start_y - mouse_map_y; - move_z = canvas->drag_start_z - floor; + if(move_x == 0 && move_y == 0 && move_z == 0) + continue; - pos.x -= move_x; - pos.y -= move_y; - pos.z -= move_z; + const Position& position = tile->getPosition(); + int pos_z = position.z - move_z; + if(pos_z < 0 || pos_z >= MAP_LAYERS) { + continue; + } - if(pos.z < 0 || pos.z >= MAP_LAYERS) { - continue; - } + int pos_x = position.x - move_x; + int pos_y = position.y - move_y; - // On screen and dragging? - if(pos.x+2 > start_x && pos.x < end_x && pos.y+2 > start_y && pos.y < end_y && (move_x != 0 || move_y != 0 || move_z != 0)) { - int offset; - if(pos.z <= GROUND_LAYER) - offset = (GROUND_LAYER - pos.z) * TILE_SIZE; - else - offset = TILE_SIZE * (floor - pos.z); - - int draw_x = ((pos.x * TILE_SIZE) - view_scroll_x) - offset; - int draw_y = ((pos.y * TILE_SIZE) - view_scroll_y) - offset; - - ItemVector toRender = tile->getSelectedItems(); - Tile* desttile = editor.map.getTile(pos); - for(ItemVector::const_iterator iit = toRender.begin(); iit != toRender.end(); iit++) { - if(desttile) - BlitItem(draw_x, draw_y, desttile, *iit, true, 160,160,160,160); - else - BlitItem(draw_x, draw_y, pos, *iit, true, 160,160,160,160); - } + // On screen and dragging? + if(pos_x+2 > start_x && pos_x < end_x && pos_y+2 > start_y && pos_y < end_y) { + Position pos(pos_x, pos_y, pos_z); + int draw_x, draw_y; + getDrawPosition(pos, draw_x, draw_y); - if(tile->monster && tile->monster->isSelected() && options.show_monsters) - BlitCreature(draw_x, draw_y, tile->monster); + ItemVector items = tile->getSelectedItems(); + Tile* dest_tile = editor.map.getTile(pos); - if(tile->spawnMonster && tile->spawnMonster->isSelected()) - DrawIndicator(draw_x, draw_y, EDITOR_SPRITE_SPAWNS, 160, 160, 160, 160); + for(Item* item : items) { + if(dest_tile) + BlitItem(draw_x, draw_y, dest_tile, item, true, 160,160,160,160); + else + BlitItem(draw_x, draw_y, pos, item, true, 160,160,160,160); + } - if(tile->npc && tile->npc->isSelected() && options.show_npcs) - BlitCreature(draw_x, draw_y, tile->npc); + if(options.show_monsters && tile->monster && tile->monster->isSelected()) { + BlitCreature(draw_x, draw_y, tile->monster); + } + if(tile->spawnMonster && tile->spawnMonster->isSelected()) { + DrawIndicator(draw_x, draw_y, EDITOR_SPRITE_SPAWNS, 160, 160, 160, 160); + } - if(tile->spawnNpc && tile->spawnNpc->isSelected()) - BlitSpriteType(draw_x, draw_y, SPRITE_SPAWN_NPC, 160, 160, 160, 160); + if(options.show_npcs && tile->npc && tile->npc->isSelected()) { + BlitCreature(draw_x, draw_y, tile->npc); + } + if(tile->spawnNpc && tile->spawnNpc->isSelected()) { + DrawIndicator(draw_x, draw_y, EDITOR_SPRITE_SPAWNS, 160, 160, 160, 160); } } } @@ -617,40 +631,33 @@ void MapDrawer::DrawDraggingShadow() void MapDrawer::DrawHigherFloors() { + if(!options.transparent_floors || floor == 0 || floor == 8) + return; + glEnable(GL_TEXTURE_2D); - // Draw "transparent higher floor" - if(floor != 8 && floor != 0 && options.transparent_floors) { - int map_z = floor - 1; - for(int map_x = start_x; map_x <= end_x; map_x++) { - for(int map_y = start_y; map_y <= end_y; map_y++) { - Tile* tile = editor.map.getTile(map_x, map_y, map_z); - if(tile) { - int offset; - if (map_z <= GROUND_LAYER) - offset = (GROUND_LAYER - map_z) * TILE_SIZE; - else - offset = TILE_SIZE*(floor - map_z); - - int draw_x = ((map_x * TILE_SIZE) - view_scroll_x) - offset; - int draw_y = ((map_y * TILE_SIZE) - view_scroll_y) - offset; - - //Position pos = tile->getPosition(); - - if(tile->ground) { - if(tile->isPZ()) { - BlitItem(draw_x, draw_y, tile, tile->ground, false, 128,255,128, 96); - } else { - BlitItem(draw_x, draw_y, tile, tile->ground, false, 255,255,255, 96); - } - } - if(zoom <= 10.0 || !options.hide_items_when_zoomed) { - ItemVector::iterator it; - for(it = tile->items.begin(); it != tile->items.end(); it++) - BlitItem(draw_x, draw_y, tile, *it, false, 255,255,255, 96); - } + int map_z = floor - 1; + for(int map_x = start_x; map_x <= end_x; map_x++) { + for(int map_y = start_y; map_y <= end_y; map_y++) { + Tile* tile = editor.map.getTile(map_x, map_y, map_z); + if(!tile) continue; + + int draw_x, draw_y; + getDrawPosition(tile->getPosition(), draw_x, draw_y); + + if(tile->ground) { + if(tile->isPZ()) { + BlitItem(draw_x, draw_y, tile, tile->ground, false, 128,255,128, 96); + } else { + BlitItem(draw_x, draw_y, tile, tile->ground, false, 255,255,255, 96); } } + + bool hidden = options.hide_items_when_zoomed && zoom > 10.f; + if(!hidden && !tile->items.empty()) { + for(const Item* item : tile->items) + BlitItem(draw_x, draw_y, tile, item, false, 255,255,255, 96); + } } } @@ -772,19 +779,21 @@ void MapDrawer::DrawBrush() else if(brush->isEraser()) brushColor = COLOR_ERASER; + int adjustment = getFloorAdjustment(floor); + if(dragging_draw) { ASSERT(brush->canDrag()); if(brush->isWall()) { int last_click_start_map_x = std::min(canvas->last_click_map_x, mouse_map_x); int last_click_start_map_y = std::min(canvas->last_click_map_y, mouse_map_y); - int last_click_end_map_x = std::max(canvas->last_click_map_x, mouse_map_x)+1; - int last_click_end_map_y = std::max(canvas->last_click_map_y, mouse_map_y)+1; + int last_click_end_map_x = std::max(canvas->last_click_map_x, mouse_map_x)+1; + int last_click_end_map_y = std::max(canvas->last_click_map_y, mouse_map_y)+1; - int last_click_start_sx = last_click_start_map_x * TILE_SIZE - view_scroll_x - getFloorAdjustment(floor); - int last_click_start_sy = last_click_start_map_y * TILE_SIZE - view_scroll_y - getFloorAdjustment(floor); - int last_click_end_sx = last_click_end_map_x * TILE_SIZE - view_scroll_x - getFloorAdjustment(floor); - int last_click_end_sy = last_click_end_map_y * TILE_SIZE - view_scroll_y - getFloorAdjustment(floor); + int last_click_start_sx = last_click_start_map_x * TILE_SIZE - view_scroll_x - adjustment; + int last_click_start_sy = last_click_start_map_y * TILE_SIZE - view_scroll_y - adjustment; + int last_click_end_sx = last_click_end_map_x * TILE_SIZE - view_scroll_x - adjustment; + int last_click_end_sy = last_click_end_map_y * TILE_SIZE - view_scroll_y - adjustment; int delta_x = last_click_end_sx - last_click_start_sx; int delta_y = last_click_end_sy - last_click_start_sy; @@ -848,9 +857,9 @@ void MapDrawer::DrawBrush() raw_brush = brush->asRaw(); for(int y = start_y; y <= end_y; y++) { - int cy = y * TILE_SIZE - view_scroll_y - getFloorAdjustment(floor); + int cy = y * TILE_SIZE - view_scroll_y - adjustment; for(int x = start_x; x <= end_x; x++) { - int cx = x * TILE_SIZE - view_scroll_x - getFloorAdjustment(floor); + int cx = x * TILE_SIZE - view_scroll_x - adjustment; if(brush->isOptionalBorder()) glColorCheck(brush, Position(x, y, floor)); else @@ -863,10 +872,10 @@ void MapDrawer::DrawBrush() int last_click_end_map_x = std::max(canvas->last_click_map_x, mouse_map_x)+1; int last_click_end_map_y = std::max(canvas->last_click_map_y, mouse_map_y)+1; - int last_click_start_sx = last_click_start_map_x * TILE_SIZE - view_scroll_x - getFloorAdjustment(floor); - int last_click_start_sy = last_click_start_map_y * TILE_SIZE - view_scroll_y - getFloorAdjustment(floor); - int last_click_end_sx = last_click_end_map_x * TILE_SIZE - view_scroll_x - getFloorAdjustment(floor); - int last_click_end_sy = last_click_end_map_y * TILE_SIZE - view_scroll_y - getFloorAdjustment(floor); + int last_click_start_sx = last_click_start_map_x * TILE_SIZE - view_scroll_x - adjustment; + int last_click_start_sy = last_click_start_map_y * TILE_SIZE - view_scroll_y - adjustment; + int last_click_end_sx = last_click_end_map_x * TILE_SIZE - view_scroll_x - adjustment; + int last_click_end_sy = last_click_end_map_y * TILE_SIZE - view_scroll_y - adjustment; glColor(brushColor); glBegin(GL_QUADS); @@ -910,10 +919,10 @@ void MapDrawer::DrawBrush() raw_brush = brush->asRaw(); for(int y = start_y-1; y <= end_y+1; y++) { - int cy = y * TILE_SIZE - view_scroll_y - getFloorAdjustment(floor); + int cy = y * TILE_SIZE - view_scroll_y - adjustment; float dy = center_y - y; for(int x = start_x-1; x <= end_x+1; x++) { - int cx = x * TILE_SIZE - view_scroll_x - getFloorAdjustment(floor); + int cx = x * TILE_SIZE - view_scroll_x - adjustment; float dx = center_x - x; //printf("%f;%f\n", dx, dy); @@ -945,10 +954,10 @@ void MapDrawer::DrawBrush() int end_map_x = mouse_map_x + g_gui.GetBrushSize() + 1; int end_map_y = mouse_map_y + g_gui.GetBrushSize() + 1; - int start_sx = start_map_x * TILE_SIZE - view_scroll_x - getFloorAdjustment(floor); - int start_sy = start_map_y * TILE_SIZE - view_scroll_y - getFloorAdjustment(floor); - int end_sx = end_map_x * TILE_SIZE - view_scroll_x - getFloorAdjustment(floor); - int end_sy = end_map_y * TILE_SIZE - view_scroll_y - getFloorAdjustment(floor); + int start_sx = start_map_x * TILE_SIZE - view_scroll_x - adjustment; + int start_sy = start_map_y * TILE_SIZE - view_scroll_y - adjustment; + int end_sx = end_map_x * TILE_SIZE - view_scroll_x - adjustment; + int end_sy = end_map_y * TILE_SIZE - view_scroll_y - adjustment; int delta_x = end_sx - start_sx; int delta_y = end_sy - start_sy; @@ -984,8 +993,8 @@ void MapDrawer::DrawBrush() } glEnd(); } else if(brush->isDoor()) { - int cx = (mouse_map_x) * TILE_SIZE - view_scroll_x - getFloorAdjustment(floor); - int cy = (mouse_map_y) * TILE_SIZE - view_scroll_y - getFloorAdjustment(floor); + int cx = (mouse_map_x) * TILE_SIZE - view_scroll_x - adjustment; + int cy = (mouse_map_y) * TILE_SIZE - view_scroll_y - adjustment; glColorCheck(brush, Position(mouse_map_x, mouse_map_y, floor)); glBegin(GL_QUADS); @@ -996,8 +1005,8 @@ void MapDrawer::DrawBrush() glEnd(); } else if(brush->isMonster()) { glEnable(GL_TEXTURE_2D); - int cy = (mouse_map_y) * TILE_SIZE - view_scroll_y - getFloorAdjustment(floor); - int cx = (mouse_map_x) * TILE_SIZE - view_scroll_x - getFloorAdjustment(floor); + int cy = (mouse_map_y) * TILE_SIZE - view_scroll_y - adjustment; + int cx = (mouse_map_x) * TILE_SIZE - view_scroll_x - adjustment; MonsterBrush* monster_brush = brush->asMonster(); if(monster_brush->canDraw(&editor.map, Position(mouse_map_x, mouse_map_y, floor))) BlitCreature(cx, cy, monster_brush->getType()->outfit, SOUTH, 255, 255, 255, 160); @@ -1022,9 +1031,9 @@ void MapDrawer::DrawBrush() } for(int y = -g_gui.GetBrushSize()-1; y <= g_gui.GetBrushSize()+1; y++) { - int cy = (mouse_map_y + y) * TILE_SIZE - view_scroll_y - getFloorAdjustment(floor); + int cy = (mouse_map_y + y) * TILE_SIZE - view_scroll_y - adjustment; for(int x = -g_gui.GetBrushSize()-1; x <= g_gui.GetBrushSize()+1; x++) { - int cx = (mouse_map_x + x) * TILE_SIZE - view_scroll_x - getFloorAdjustment(floor); + int cx = (mouse_map_x + x) * TILE_SIZE - view_scroll_x - adjustment; if(g_gui.GetBrushShape() == BRUSHSHAPE_SQUARE) { if(x >= -g_gui.GetBrushSize() && x <= g_gui.GetBrushSize() && y >= -g_gui.GetBrushSize() && y <= g_gui.GetBrushSize()) { if(brush->isRaw()) { @@ -1087,7 +1096,13 @@ void MapDrawer::DrawBrush() void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Tile* tile, const Item* item, bool ephemeral, int red, int green, int blue, int alpha) { - ItemType& it = g_items[item->getID()]; + const ItemType& type = g_items.getItemType(item->getID()); + if(type.id == 0) { + glDisable(GL_TEXTURE_2D); + glBlitSquare(draw_x, draw_y, *wxRED); + glEnable(GL_TEXTURE_2D); + return; + } if(!options.ingame && !ephemeral && item->isSelected()) { red /= 2; @@ -1096,51 +1111,44 @@ void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Tile* tile, const Item* } // Ugly hacks. :) - if(it.id == 0) { - glDisable(GL_TEXTURE_2D); - glBlitSquare(draw_x, draw_y, 255, 0, 0, alpha); - glEnable(GL_TEXTURE_2D); - return; - } else if(it.id == ITEM_STAIRS && !options.ingame) { + if(type.id == ITEM_STAIRS && !options.ingame) { glDisable(GL_TEXTURE_2D); glBlitSquare(draw_x, draw_y, red, green, 0, alpha/3*2); glEnable(GL_TEXTURE_2D); return; - } else if(it.id == ITEM_NOTHING_SPECIAL && !options.ingame) { + } else if(type.id == ITEM_NOTHING_SPECIAL && !options.ingame) { glDisable(GL_TEXTURE_2D); glBlitSquare(draw_x, draw_y, red, 0, 0, alpha/3*2); glEnable(GL_TEXTURE_2D); return; } - - GameSprite* spr = it.sprite; - - if(it.isMetaItem()) + if(type.isMetaItem()) return; - if(spr == nullptr) + if(!ephemeral && type.pickupable && !options.show_items) return; - if(!ephemeral && it.pickupable && !options.show_items) + GameSprite* sprite = type.sprite; + if(!sprite) return; - int screenx = draw_x - spr->getDrawOffset().first; - int screeny = draw_y - spr->getDrawOffset().second; + int screenx = draw_x - sprite->getDrawOffset().x; + int screeny = draw_y - sprite->getDrawOffset().y; const Position& pos = tile->getPosition(); // Set the newd drawing height accordingly - draw_x -= spr->getDrawHeight(); - draw_y -= spr->getDrawHeight(); + draw_x -= sprite->getDrawHeight(); + draw_y -= sprite->getDrawHeight(); int subtype = -1; - int pattern_x = pos.x % spr->pattern_x; - int pattern_y = pos.y % spr->pattern_y; - int pattern_z = pos.z % spr->pattern_z; + int pattern_x = pos.x % sprite->pattern_x; + int pattern_y = pos.y % sprite->pattern_y; + int pattern_z = pos.z % sprite->pattern_z; - if(it.isSplash() || it.isFluidContainer()) { + if(type.isSplash() || type.isFluidContainer()) { subtype = item->getSubtype(); - } else if(it.isHangable) { + } else if(type.isHangable) { if(tile->hasProperty(HOOK_SOUTH)) { pattern_x = 1; } else if(tile->hasProperty(HOOK_EAST)) { @@ -1148,7 +1156,7 @@ void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Tile* tile, const Item* } else { pattern_x = 0; } - } else if(it.stackable) { + } else if(type.stackable) { if(item->getSubtype() <= 1) subtype = 0; else if(item->getSubtype() <= 2) @@ -1168,19 +1176,19 @@ void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Tile* tile, const Item* } if(!ephemeral && options.transparent_items && - (!it.isGroundTile() || spr->width > 1 || spr->height > 1) && - !it.isSplash() && - (!it.isBorder || spr->width > 1 || spr->height > 1) + (!type.isGroundTile() || sprite->width > 1 || sprite->height > 1) && + !type.isSplash() && + (!type.isBorder || sprite->width > 1 || sprite->height > 1) ) { alpha /= 2; } int frame = item->getFrame(); - for(int cx = 0; cx != spr->width; cx++) { - for(int cy = 0; cy != spr->height; cy++) { - for(int cf = 0; cf != spr->layers; cf++) { - int texnum = spr->getHardwareID(cx,cy,cf, + for(int cx = 0; cx != sprite->width; cx++) { + for(int cy = 0; cy != sprite->height; cy++) { + for(int cf = 0; cf != sprite->layers; cf++) { + int texnum = sprite->getHardwareID(cx,cy,cf, subtype, pattern_x, pattern_y, @@ -1192,13 +1200,15 @@ void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Tile* tile, const Item* } } - if(options.show_hooks && (it.hookSouth || it.hookEast)) - DrawHookIndicator(draw_x, draw_y, it); + if(options.show_hooks && (type.hookSouth || type.hookEast)) + DrawHookIndicator(draw_x, draw_y, type); } void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Position& pos, const Item* item, bool ephemeral, int red, int green, int blue, int alpha) { - ItemType& it = g_items[item->getID()]; + const ItemType& type = g_items.getItemType(item->getID()); + if(type.id == 0) + return; if(!options.ingame && !ephemeral && item->isSelected()) { red /= 2; @@ -1206,43 +1216,42 @@ void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Position& pos, const It green /= 2; } - if(it.id == ITEM_STAIRS && !options.ingame) { // Ugly hack yes? + if(type.id == ITEM_STAIRS && !options.ingame) { // Ugly hack yes? glDisable(GL_TEXTURE_2D); glBlitSquare(draw_x, draw_y, red, green, 0, alpha/3*2); glEnable(GL_TEXTURE_2D); return; - } else if(it.id == ITEM_NOTHING_SPECIAL && !options.ingame) { // Ugly hack yes? + } else if(type.id == ITEM_NOTHING_SPECIAL && !options.ingame) { // Ugly hack yes? glDisable(GL_TEXTURE_2D); glBlitSquare(draw_x, draw_y, red, 0, 0, alpha/3*2); glEnable(GL_TEXTURE_2D); return; } - GameSprite* spr = it.sprite; - - if(it.isMetaItem()) + if(type.isMetaItem()) return; - if(spr == nullptr) + if(!ephemeral && type.pickupable && options.show_items) return; - if(!ephemeral && it.pickupable && options.show_items) + GameSprite* sprite = type.sprite; + if(!sprite) return; - int screenx = draw_x - spr->getDrawOffset().first; - int screeny = draw_y - spr->getDrawOffset().second; + int screenx = draw_x - sprite->getDrawOffset().x; + int screeny = draw_y - sprite->getDrawOffset().y; // Set the newd drawing height accordingly - draw_x -= spr->getDrawHeight(); - draw_y -= spr->getDrawHeight(); + draw_x -= sprite->getDrawHeight(); + draw_y -= sprite->getDrawHeight(); int subtype = -1; - int pattern_x = pos.x % spr->pattern_x; - int pattern_y = pos.y % spr->pattern_y; - int pattern_z = pos.z % spr->pattern_z; + int pattern_x = pos.x % sprite->pattern_x; + int pattern_y = pos.y % sprite->pattern_y; + int pattern_z = pos.z % sprite->pattern_z; - if(it.isSplash() || it.isFluidContainer()) { + if(type.isSplash() || type.isFluidContainer()) { subtype = item->getSubtype(); - } else if(it.isHangable) { + } else if(type.isHangable) { pattern_x = 0; /* if(tile->hasProperty(HOOK_SOUTH)) { @@ -1253,7 +1262,7 @@ void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Position& pos, const It pattern_x = -0; } */ - } else if(it.stackable) { + } else if(type.stackable) { if(item->getSubtype() <= 1) subtype = 0; else if(item->getSubtype() <= 2) @@ -1273,19 +1282,19 @@ void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Position& pos, const It } if(!ephemeral && options.transparent_items && - (!it.isGroundTile() || spr->width > 1 || spr->height > 1) && - !it.isSplash() && - (!it.isBorder || spr->width > 1 || spr->height > 1) + (!type.isGroundTile() || sprite->width > 1 || sprite->height > 1) && + !type.isSplash() && + (!type.isBorder || sprite->width > 1 || sprite->height > 1) ) { alpha /= 2; } int frame = item->getFrame(); - for(int cx = 0; cx != spr->width; ++cx) { - for(int cy = 0; cy != spr->height; ++cy) { - for(int cf = 0; cf != spr->layers; ++cf) { - int texnum = spr->getHardwareID(cx,cy,cf, + for(int cx = 0; cx != sprite->width; ++cx) { + for(int cy = 0; cy != sprite->height; ++cy) { + for(int cf = 0; cf != sprite->layers; ++cf) { + int texnum = sprite->getHardwareID(cx,cy,cf, subtype, pattern_x, pattern_y, @@ -1297,41 +1306,46 @@ void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Position& pos, const It } } - if(options.show_hooks && (it.hookSouth || it.hookEast) && zoom <= 3.0) - DrawHookIndicator(draw_x, draw_y, it); + if(options.show_hooks && (type.hookSouth || type.hookEast) && zoom <= 3.0) + DrawHookIndicator(draw_x, draw_y, type); } void MapDrawer::BlitSpriteType(int screenx, int screeny, uint32_t spriteid, int red, int green, int blue, int alpha) { - GameSprite* spr = g_items[spriteid].sprite; - if(spr == nullptr) return; - screenx -= spr->getDrawOffset().first; - screeny -= spr->getDrawOffset().second; - - int tme = 0; //GetTime() % itype->FPA; - for(int cx = 0; cx != spr->width; ++cx) { - for(int cy = 0; cy != spr->height; ++cy) { - for(int cf = 0; cf != spr->layers; ++cf) { - int texnum = spr->getHardwareID(cx,cy,cf,-1,0,0,0,tme); - //printf("CF: %d\tTexturenum: %d\n", cf, texnum); + const ItemType& type = g_items.getItemType(spriteid); + if(type.id == 0) + return; + + GameSprite* sprite = type.sprite; + if(!sprite) + return; + + screenx -= sprite->getDrawOffset().x; + screeny -= sprite->getDrawOffset().y; + + int frame = 0; + for(int cx = 0; cx != sprite->width; ++cx) { + for(int cy = 0; cy != sprite->height; ++cy) { + for(int cf = 0; cf != sprite->layers; ++cf) { + int texnum = sprite->getHardwareID(cx,cy,cf,-1,0,0,0, frame); glBlitTexture(screenx - cx * TILE_SIZE, screeny - cy * TILE_SIZE, texnum, red, green, blue, alpha); } } } } -void MapDrawer::BlitSpriteType(int screenx, int screeny, GameSprite* spr, int red, int green, int blue, int alpha) +void MapDrawer::BlitSpriteType(int screenx, int screeny, GameSprite* sprite, int red, int green, int blue, int alpha) { - if(spr == nullptr) return; - screenx -= spr->getDrawOffset().first; - screeny -= spr->getDrawOffset().second; - - int tme = 0; //GetTime() % itype->FPA; - for(int cx = 0; cx != spr->width; ++cx) { - for(int cy = 0; cy != spr->height; ++cy) { - for(int cf = 0; cf != spr->layers; ++cf) { - int texnum = spr->getHardwareID(cx,cy,cf,-1,0,0,0,tme); - //printf("CF: %d\tTexturenum: %d\n", cf, texnum); + if(!sprite) return; + + screenx -= sprite->getDrawOffset().x; + screeny -= sprite->getDrawOffset().y; + + int frame = 0; + for(int cx = 0; cx != sprite->width; ++cx) { + for(int cy = 0; cy != sprite->height; ++cy) { + for(int cf = 0; cf != sprite->layers; ++cf) { + int texnum = sprite->getHardwareID(cx,cy,cf,-1,0,0,0, frame); glBlitTexture(screenx - cx * TILE_SIZE, screeny - cy * TILE_SIZE, texnum, red, green, blue, alpha); } } @@ -1341,17 +1355,12 @@ void MapDrawer::BlitSpriteType(int screenx, int screeny, GameSprite* spr, int re void MapDrawer::BlitCreature(int screenx, int screeny, const Outfit& outfit, Direction dir, int red, int green, int blue, int alpha) { if(outfit.lookItem != 0) { - ItemType& it = g_items[outfit.lookItem]; - BlitSpriteType(screenx, screeny, it.sprite, red, green, blue, alpha); + const ItemType& type = g_items.getItemType(outfit.lookItem); + BlitSpriteType(screenx, screeny, type.sprite, red, green, blue, alpha); } else { - GameSprite* spr = g_gui.gfx.getCreatureSprite(outfit.lookType); - if(!spr || outfit.lookType == 0) { + GameSprite* sprite = g_gui.gfx.getCreatureSprite(outfit.lookType); + if(!sprite || outfit.lookType == 0) { return; - /* - spr = g_gui.gfx.getCreatureSprite(138); - if(!spr) - return; - */ } // mount and addon drawing thanks to otc code @@ -1364,22 +1373,22 @@ void MapDrawer::BlitCreature(int screenx, int screeny, const Outfit& outfit, Dir glBlitTexture(screenx - cx * TILE_SIZE, screeny - cy * TILE_SIZE, texnum, red, green, blue, alpha); } } - pattern_z = std::min(1, spr->pattern_z - 1); + pattern_z = std::min(1, sprite->pattern_z - 1); } } - int tme = 0; //GetTime() % itype->FPA; + int frame = 0; // pattern_y => creature addon - for (int pattern_y = 0; pattern_y < spr->pattern_y; pattern_y++) { + for(int pattern_y = 0; pattern_y < sprite->pattern_y; pattern_y++) { // continue if we dont have this addon if (pattern_y > 0 && !(outfit.lookAddon & (1 << (pattern_y - 1)))) continue; - for (int cx = 0; cx != spr->width; ++cx) { - for (int cy = 0; cy != spr->height; ++cy) { - int texnum = spr->getHardwareID(cx, cy, (int)dir, pattern_y, pattern_z, outfit, tme); + for(int cx = 0; cx != sprite->width; ++cx) { + for(int cy = 0; cy != sprite->height; ++cy) { + int texnum = sprite->getHardwareID(cx, cy, (int)dir, pattern_y, pattern_z, outfit, frame); glBlitTexture(screenx - cx * TILE_SIZE, screeny - cy * TILE_SIZE, texnum, red, green, blue, alpha); } } @@ -1387,14 +1396,14 @@ void MapDrawer::BlitCreature(int screenx, int screeny, const Outfit& outfit, Dir } } -void MapDrawer::BlitCreature(int screenx, int screeny, const Monster* c, int red, int green, int blue, int alpha) +void MapDrawer::BlitCreature(int screenx, int screeny, const Monster* creature, int red, int green, int blue, int alpha) { - if(!options.ingame && c->isSelected()) { + if(!options.ingame && creature->isSelected()) { red /= 2; green /= 2; blue /= 2; } - BlitCreature(screenx, screeny, c->getLookType(), c->getDirection(), red, green, blue, alpha); + BlitCreature(screenx, screeny, creature->getLookType(), creature->getDirection(), red, green, blue, alpha); } // Npcs void MapDrawer::BlitCreature(int screenx, int screeny, const Npc* npc, int red, int green, int blue, int alpha) @@ -1407,10 +1416,9 @@ void MapDrawer::BlitCreature(int screenx, int screeny, const Npc* npc, int red, BlitCreature(screenx, screeny, npc->getLookType(), npc->getDirection(), red, green, blue, alpha); } -void MapDrawer::WriteTooltip(Item* item, std::ostringstream& stream) +void MapDrawer::WriteTooltip(const Item* item, std::ostringstream& stream) { - if(item == nullptr) - return; + if(!item) return; const uint16_t id = item->getID(); if(id < 100) @@ -1435,7 +1443,7 @@ void MapDrawer::WriteTooltip(Item* item, std::ostringstream& stream) stream << "text: " << text << "\n"; } -void MapDrawer::WriteTooltip(Waypoint* waypoint, std::ostringstream& stream) +void MapDrawer::WriteTooltip(const Waypoint* waypoint, std::ostringstream& stream) { if (stream.tellp() > 0) stream << "\n"; @@ -1444,16 +1452,16 @@ void MapDrawer::WriteTooltip(Waypoint* waypoint, std::ostringstream& stream) void MapDrawer::DrawTile(TileLocation* location) { - if(!location) - return; + if(!location) return; Tile* tile = location->get(); - if(!tile) - return; + if(!tile) return; if(options.show_only_modified && !tile->isModified()) return; + const Position& position = location->getPosition(); + if(options.show_tooltips && location->getWaypointCount() > 0) { Waypoint* waypoint = canvas->editor.map.waypoints.getWaypoint(location); if(waypoint) @@ -1462,12 +1470,11 @@ void MapDrawer::DrawTile(TileLocation* location) bool only_colors = options.isOnlyColors(); - const Position& position = location->getPosition(); int draw_x, draw_y; getDrawPosition(position, draw_x, draw_y); uint8_t r = 255,g = 255,b = 255; - if(tile->ground || only_colors) { + if(only_colors || tile->hasGround()) { if(!options.show_as_minimap) { bool showspecial = options.show_only_colors || options.show_special_tiles; @@ -1506,8 +1513,7 @@ void MapDrawer::DrawTile(TileLocation* location) if(options.show_houses && tile->isHouseTile()) { if((int)tile->getHouseID() == current_house_id) { r /= 2; - } - else { + } else { r /= 2; g /= 2; } @@ -1550,37 +1556,39 @@ void MapDrawer::DrawTile(TileLocation* location) WriteTooltip(tile->ground, tooltip); } - if(!only_colors) { - if(zoom < 10.0 || !options.hide_items_when_zoomed) { - for(ItemVector::iterator it = tile->items.begin(); it != tile->items.end(); it++) { - if(options.show_tooltips && position.z == floor) - WriteTooltip(*it, tooltip); + bool hidden = only_colors || (options.hide_items_when_zoomed && zoom > 10.f); - if(options.show_preview && zoom <= 2.0) - (*it)->animate(); + if(!hidden && !tile->items.empty()) { + for(Item* item : tile->items) { + if(options.show_tooltips && position.z == floor) + WriteTooltip(item, tooltip); - if((*it)->isBorder()) { - BlitItem(draw_x, draw_y, tile, *it, false, r, g, b); - } else { - BlitItem(draw_x, draw_y, tile, *it); - } - } - if(tile->monster && options.show_monsters) { - BlitCreature(draw_x, draw_y, tile->monster); - } - if(tile->npc && options.show_npcs) { - BlitCreature(draw_x, draw_y, tile->npc); + if(options.show_preview && zoom <= 2.0) + item->animate(); + + if(item->isBorder()) { + BlitItem(draw_x, draw_y, tile, item, false, r, g, b); + } else { + BlitItem(draw_x, draw_y, tile, item); } } } + if(!hidden && options.show_monsters && tile->monster) { + BlitCreature(draw_x, draw_y, tile->monster); + } + + if(!hidden && options.show_npcs && tile->npc) { + BlitCreature(draw_x, draw_y, tile->npc); + } + if(options.show_tooltips) { if(location->getWaypointCount() > 0) MakeTooltip(draw_x, draw_y, tooltip.str(), 0, 255, 0); else MakeTooltip(draw_x, draw_y, tooltip.str()); + tooltip.str(""); } - tooltip.str(""); } void MapDrawer::DrawBrushIndicator(int x, int y, Brush* brush, uint8_t r, uint8_t g, uint8_t b) @@ -1675,9 +1683,8 @@ void MapDrawer::DrawTileIndicators(TileLocation* location) green = 0x00; blue = 0x00; } - for (ItemVector::iterator it = tile->items.begin(); it != tile->items.end(); it++) { - const uint16_t itemId = (*it)->getID(); - const ItemType& type = g_items[itemId]; + for(const Item* item : tile->items) { + const ItemType& type = g_items.getItemType(item->getID()); if ((type.pickupable && options.show_pickupables) || (type.moveable && options.show_moveables)) { if (type.pickupable && options.show_pickupables && type.moveable && options.show_moveables) DrawIndicator(x, y, EDITOR_SPRITE_PICKUPABLE_MOVEABLE_ITEM, red, green, blue); @@ -1753,8 +1760,12 @@ void MapDrawer::DrawPositionIndicator(int z) void MapDrawer::DrawTooltips() { - for(std::vector::const_iterator it = tooltips.begin(); it != tooltips.end(); ++it) { - MapTooltip* tooltip = (*it); + if(!options.show_tooltips || tooltips.empty()) + return; + + glDisable(GL_TEXTURE_2D); + + for(MapTooltip* tooltip : tooltips) { const char* text = tooltip->text.c_str(); float line_width = 0.0f; float width = 2.0f; @@ -1853,6 +1864,8 @@ void MapDrawer::DrawTooltips() } } } + + glEnable(GL_TEXTURE_2D); } void MapDrawer::MakeTooltip(int screenx, int screeny, const std::string& text, uint8_t r, uint8_t g, uint8_t b) @@ -1860,7 +1873,7 @@ void MapDrawer::MakeTooltip(int screenx, int screeny, const std::string& text, u if(text.empty()) return; - MapTooltip *tooltip = newd MapTooltip(screenx, screeny, text, r, g, b); + MapTooltip *tooltip = new MapTooltip(screenx, screeny, text, r, g, b); tooltip->checkLineEnding(); tooltips.push_back(tooltip); } @@ -1930,14 +1943,14 @@ void MapDrawer::glBlitTexture(int x, int y, int textureId, int red, int green, i glEnd(); } -void MapDrawer::glBlitSquare(int sx, int sy, int red, int green, int blue, int alpha) +void MapDrawer::glBlitSquare(int x, int y, int red, int green, int blue, int alpha) { glColor4ub(uint8_t(red), uint8_t(green), uint8_t(blue), uint8_t(alpha)); glBegin(GL_QUADS); - glVertex2f(sx, sy); - glVertex2f(sx + TILE_SIZE, sy); - glVertex2f(sx + TILE_SIZE, sy + TILE_SIZE); - glVertex2f(sx, sy + TILE_SIZE); + glVertex2f(x, y); + glVertex2f(x + TILE_SIZE, y); + glVertex2f(x + TILE_SIZE, y + TILE_SIZE); + glVertex2f(x, y + TILE_SIZE); glEnd(); } diff --git a/source/map_drawer.h b/source/map_drawer.h index 891e2557..aaa3dee6 100644 --- a/source/map_drawer.h +++ b/source/map_drawer.h @@ -45,6 +45,7 @@ struct MapTooltip // Storage during drawing, for option caching struct DrawingOptions { +public: DrawingOptions(); void SetIngame(); @@ -123,7 +124,9 @@ class MapDrawer void Draw(); void DrawBackground(); + void DrawShade(int mapz); void DrawMap(); + void DrawSecondaryMap(int mapz); void DrawDraggingShadow(); void DrawHigherFloors(); void DrawSelectionBox(); @@ -153,8 +156,8 @@ class MapDrawer void DrawTileIndicators(TileLocation* location); void DrawIndicator(int x, int y, int indicator, uint8_t r = 255, uint8_t g = 255, uint8_t b = 255, uint8_t a = 255); void DrawPositionIndicator(int z); - void WriteTooltip(Item* item, std::ostringstream& stream); - void WriteTooltip(Waypoint* item, std::ostringstream& stream); + void WriteTooltip(const Item* item, std::ostringstream& stream); + void WriteTooltip(const Waypoint* item, std::ostringstream& stream); void MakeTooltip(int screenx, int screeny, const std::string& text, uint8_t r = 255, uint8_t g = 255, uint8_t b = 255); enum BrushColor { @@ -171,7 +174,7 @@ class MapDrawer void getColor(Brush* brush, const Position& position, uint8_t &r, uint8_t &g, uint8_t &b); void glBlitTexture(int x, int y, int textureId, int red, int green, int blue, int alpha, bool adjustZoom = false); - void glBlitSquare(int sx, int sy, int red, int green, int blue, int alpha); + void glBlitSquare(int x, int y, int red, int green, int blue, int alpha); void glBlitSquare(int x, int y, const wxColor& color); void glColor(const wxColor& color); void glColor(BrushColor color); From a220678900b1f4b7fbc15912a974bf57742f09a9 Mon Sep 17 00:00:00 2001 From: Beats Date: Tue, 4 Apr 2023 20:12:55 -0400 Subject: [PATCH 12/45] Code cleanup --- source/tile.cpp | 310 +++++++++++++++++++----------------------------- source/tile.h | 85 ++++++------- 2 files changed, 158 insertions(+), 237 deletions(-) diff --git a/source/tile.cpp b/source/tile.cpp index 653a562a..e94a247c 100644 --- a/source/tile.cpp +++ b/source/tile.cpp @@ -87,12 +87,8 @@ Tile* Tile::deepCopy(BaseMap& map) // Spawncount & exits are not transferred on copy! if(ground) copy->ground = ground->deepCopy(); - ItemVector::iterator it; - - it = items.begin(); - while(it != items.end()) { - copy->items.push_back((*it)->deepCopy()); - ++it; + for(const Item* item : items) { + copy->items.push_back(item->deepCopy()); } return copy; @@ -103,12 +99,8 @@ uint32_t Tile::memsize() const uint32_t mem = sizeof(*this); if(ground) mem += ground->memsize(); - ItemVector::const_iterator it; - - it = items.begin(); - while(it != items.end()) { - mem += (*it)->memsize(); - ++it; + for(const Item* item : items) { + mem += item->memsize(); } mem += sizeof(Item*) * items.capacity(); @@ -135,6 +127,9 @@ int Tile::size() const } void Tile::merge(Tile* other) { + + if(!other) return; + if(other->isPZ()) setPZ(true); if(other->house_id) { house_id = other->house_id; @@ -182,12 +177,8 @@ void Tile::merge(Tile* other) { other->npc = nullptr; } - ItemVector::iterator it; - - it = other->items.begin(); - while(it != other->items.end()) { - addItem(*it); - ++it; + for(Item* item : other->items) { + addItem(item); } other->items.clear(); } @@ -201,9 +192,8 @@ bool Tile::hasProperty(enum ITEMPROPERTY prop) const return true; } - ItemVector::const_iterator iit; - for(iit = items.begin(); iit != items.end(); ++iit){ - if((*iit)->hasProperty(prop)) + for(const Item* item : items) { + if(item->hasProperty(prop)) return true; } @@ -251,8 +241,8 @@ Item* Tile::getItemAt(int index) const return ground; index--; } - if(index >= 0 && index < static_cast(items.size())) { - return items[index]; + if(!items.empty() && index >= 0 && index < items.size()) { + return items.at(index); } return nullptr; } @@ -311,12 +301,8 @@ void Tile::select() if(monster) monster->select(); if(npc) npc->select(); - ItemVector::iterator it; - - it = items.begin(); - while(it != items.end()) { - (*it)->select(); - ++it; + for(Item* item : items) { + item->select(); } statflags |= TILESTATE_SELECTED; @@ -331,12 +317,8 @@ void Tile::deselect() if(monster) monster->deselect(); if(npc) npc->deselect(); - ItemVector::iterator it; - - it = items.begin(); - while(it != items.end()) { - (*it)->deselect(); - ++it; + for(Item* item : items) { + item->deselect(); } statflags &= ~TILESTATE_SELECTED; @@ -344,9 +326,9 @@ void Tile::deselect() Item* Tile::getTopSelectedItem() { - for(ItemVector::reverse_iterator iter = items.rbegin(); iter != items.rend(); ++iter) { - if((*iter)->isSelected() && !(*iter)->isMetaItem()) { - return *iter; + for(auto it = items.rbegin(); it != items.rend(); ++it) { + if((*it)->isSelected() && !(*it)->isMetaItem()) { + return *it; } } if(ground && ground->isSelected() && !ground->isMetaItem()) { @@ -366,12 +348,10 @@ ItemVector Tile::popSelectedItems(bool ignoreTileSelected) ground = nullptr; } - ItemVector::iterator it; - - it = items.begin(); - while(it != items.end()) { - if((*it)->isSelected()) { - pop_items.push_back(*it); + for(auto it = items.begin(); it != items.end();) { + Item* item = (*it); + if(item->isSelected()) { + pop_items.push_back(item); it = items.erase(it); } else { ++it; @@ -392,13 +372,10 @@ ItemVector Tile::getSelectedItems() selected_items.push_back(ground); } - ItemVector::iterator it; - - it = items.begin(); - while(it != items.end()) { - if((*it)->isSelected()) { - selected_items.push_back(*it); - } it++; + for(Item* item : items) { + if(item->isSelected()) { + selected_items.push_back(item); + } } return selected_items; @@ -409,10 +386,10 @@ uint8_t Tile::getMiniMapColor() const if(minimapColor != INVALID_MINIMAP_COLOR) return minimapColor; - for(ItemVector::const_reverse_iterator item_iter = items.rbegin(); item_iter != items.rend(); ++item_iter) { - if((*item_iter)->getMiniMapColor()) { - return (*item_iter)->getMiniMapColor(); - break; + for(auto it = items.rbegin(); it != items.rend(); ++it) { + uint8_t color = (*it)->getMiniMapColor(); + if(color != 0) { + return color; } } @@ -424,32 +401,6 @@ uint8_t Tile::getMiniMapColor() const return 0; } -bool tilePositionLessThan(const Tile* a, const Tile* b) -{ - return a->getPosition() < b->getPosition(); -} - -bool tilePositionVisualLessThan(const Tile* a, const Tile* b) -{ - Position pa = a->getPosition(); - Position pb = b->getPosition(); - - if(pa.z > pb.z) - return true; - if(pa.z < pb.z) - return false; - - if(pa.y < pb.y) - return true; - if(pa.y > pb.y) - return false; - - if(pa.x < pb.x) - return true; - - return false; -} - void Tile::update() { statflags &= TILESTATE_MODIFIED; @@ -482,37 +433,35 @@ void Tile::update() } } - ItemVector::const_iterator iter = items.begin(); - while(iter != items.end()) { - Item* i = *iter; - if(i->isSelected()) { + for(const Item* item : items) { + if(item->isSelected()) { statflags |= TILESTATE_SELECTED; } - if(i->getUniqueID() != 0) { + if(item->getUniqueID() != 0) { statflags |= TILESTATE_UNIQUE; } - if(i->getMiniMapColor() != 0) { - minimapColor = i->getMiniMapColor(); + if(item->getMiniMapColor() != 0) { + minimapColor = item->getMiniMapColor(); } - ItemType& it = g_items[i->getID()]; - if(it.unpassable) { + const ItemType& type = g_items.getItemType(item->getID()); + + if(type.unpassable) { statflags |= TILESTATE_BLOCKING; } - if(it.isOptionalBorder) { + if(type.isOptionalBorder) { statflags |= TILESTATE_OP_BORDER; } - if(it.isTable) { + if(type.isTable) { statflags |= TILESTATE_HAS_TABLE; } - if(it.isCarpet) { + if(type.isCarpet) { statflags |= TILESTATE_HAS_CARPET; } - ++iter; } if((statflags & TILESTATE_BLOCKING) == 0) { - if(ground == nullptr && items.size() == 0) { + if(!ground && items.empty()) { statflags |= TILESTATE_BLOCKING; } } @@ -532,27 +481,23 @@ void Tile::addBorderItem(Item* item) GroundBrush* Tile::getGroundBrush() const { - if(ground) { - if(ground->getGroundBrush()) { - return ground->getGroundBrush(); - } + if(ground && ground->getGroundBrush()) { + return ground->getGroundBrush(); } return nullptr; } void Tile::cleanBorders() { - ItemVector::iterator it; + if(items.empty()) return; - it = items.begin(); - while(it != items.end()) { - if((*it)->isBorder()) { - delete *it; - it = items.erase(it); - } else { - // Borders should only be on the bottom, we can ignore the rest of the items - return; - } + for(auto it = items.begin(); it != items.end();) { + Item* item = (*it); + // Borders should only be on the bottom, we can ignore the rest of the items + if(!item->isBorder()) break; + + delete item; + it = items.erase(it); } } @@ -563,39 +508,30 @@ void Tile::wallize(BaseMap* parent) Item* Tile::getWall() const { - ItemVector::const_iterator it; - - it = items.begin(); - while(it != items.end()) { - if((*it)->isWall()) { - return *it; - } ++it; + for(Item* item : items) { + if(item->isWall()) { + return item; + } } return nullptr; } Item* Tile::getCarpet() const { - ItemVector::const_iterator it; - - it = items.begin(); - while(it != items.end()) { - if((*it)->isCarpet()) { - return *it; - } ++it; + for(Item* item : items) { + if(item->isCarpet()) { + return item; + } } return nullptr; } Item* Tile::getTable() const { - ItemVector::const_iterator it; - - it = items.begin(); - while(it != items.end()) { - if((*it)->isTable()) { - return *it; - } ++it; + for(Item* item : items) { + if(item->isTable()) { + return item; + } } return nullptr; } @@ -612,44 +548,50 @@ void Tile::addWallItem(Item* item) void Tile::cleanWalls(bool dontdelete) { - ItemVector::iterator it; + if(items.empty()) return; - it = items.begin(); - while(it != items.end()) { - if((*it)->isWall()) { + for(auto it = items.begin(); it != items.end();) { + Item* item = (*it); + if(item && item->isWall()) { if(!dontdelete) { - delete *it; + delete item; } it = items.erase(it); - } else ++it; + } else { + ++it; + } } } -void Tile::cleanWalls(WallBrush* wb) +void Tile::cleanWalls(WallBrush* brush) { ItemVector::iterator it; - it = items.begin(); - while(it != items.end()) { - if((*it)->isWall() && wb->hasWall(*it)) { - delete *it; + for(auto it = items.begin(); it != items.end();) { + Item* item = (*it); + if(item && item->isWall() && brush->hasWall(item)) { + delete item; it = items.erase(it); - } else ++it; + } else { + ++it; + } } } void Tile::cleanTables(bool dontdelete) { - ItemVector::iterator it; + if(items.empty()) return; - it = items.begin(); - while(it != items.end()) { - if((*it)->isTable()) { + for(auto it = items.begin(); it != items.end();) { + Item* item = (*it); + if(item && item->isTable()) { if(!dontdelete) { - delete *it; + delete item; } it = items.erase(it); - } else ++it; + } else { + ++it; + } } } @@ -665,24 +607,21 @@ void Tile::carpetize(BaseMap* parent) void Tile::selectGround() { - bool selected_ = false; + bool selected = false; if(ground) { ground->select(); - selected_ = true; + selected = true; } ItemVector::iterator it; - it = items.begin(); - while(it != items.end()) { - if((*it)->isBorder()) { - (*it)->select(); - selected_ = true; - } else { + for(Item* item : items) { + if(!item->isBorder()) break; - } - ++it; + item->select(); + selected = true; } - if(selected_) statflags |= TILESTATE_SELECTED; + + if(selected) statflags |= TILESTATE_SELECTED; } @@ -691,44 +630,45 @@ void Tile::deselectGround() if(ground) { ground->deselect(); } - ItemVector::iterator it = items.begin(); - while(it != items.end()) { - if((*it)->isBorder()) { - (*it)->deselect(); - } else { + for(Item* item : items) { + if(!item->isBorder()) break; - } - ++it; + + item->deselect(); } } -void Tile::setHouse(House* _house) +void Tile::setHouse(House* house) { - house_id = (_house? _house->id : 0); + house_id = (house ? house->id : 0); } -void Tile::addHouseExit(House* h) +void Tile::addHouseExit(House* house) { - if(!h) - return; - HouseExitList* house_exits = location->createHouseExits(); - house_exits->push_back(h->id); + if(!house) return; + + HouseExitList* exits = location->createHouseExits(); + exits->push_back(house->id); } -void Tile::removeHouseExit(House* h) +void Tile::removeHouseExit(House* house) { - if(!h) - return; + if(!house) return; - HouseExitList* house_exits = location->getHouseExits(); - if(!house_exits) - return; + HouseExitList* exits = location->getHouseExits(); + if(!exits || exits->empty()) return; - for(std::vector::iterator it = house_exits->begin(); it != house_exits->end(); ++it) { - if(*it == h->id) { - house_exits->erase(it); - return; - } - } + auto it = std::find(exits->begin(), exits->end(), house->id); + if(it != exits->end()) + exits->erase(it); } +bool Tile::hasHouseExit(uint32_t houseId) const +{ + const HouseExitList* exits = getHouseExits(); + if(!exits || exits->empty()) + return false; + + auto it = std::find(exits->begin(), exits->end(), houseId); + return it != exits->end(); +} diff --git a/source/tile.h b/source/tile.h index e893455e..24450fa0 100644 --- a/source/tile.h +++ b/source/tile.h @@ -77,11 +77,10 @@ class Tile const TileLocation* getLocation() const {return location;} // Position of the tile - Position getPosition() {return location->getPosition();} - const Position getPosition() const {return location->getPosition();} - int getX() const {return location->getPosition().x;} - int getY() const {return location->getPosition().y;} - int getZ() const {return location->getPosition().z;} + const Position& getPosition() const noexcept { return location->getPosition(); } + int getX() const noexcept { return location->getX(); } + int getY() const noexcept { return location->getY(); } + int getZ() const noexcept { return location->getZ(); } public: //Functions // Absorb the other tile into this tile @@ -136,10 +135,10 @@ class Tile uint8_t getMiniMapColor() const; - // Does this tile have ground? - bool hasGround() const { return ground != nullptr; } + bool hasItems() const noexcept { return ground || !items.empty(); } + bool hasGround() const noexcept { return ground != nullptr; } bool hasBorders() const { - return items.size() && items[0]->isBorder(); + return !items.empty() && items.front()->isBorder(); } // Get the border brush of this tile @@ -173,7 +172,7 @@ class Tile Item* getWall() const; bool hasWall() const; // Remove all walls from the tile (for autowall) (only of those belonging to the specified brush - void cleanWalls(WallBrush* wb); + void cleanWalls(WallBrush* brush); // Remove all walls from the tile void cleanWalls(bool dontdelete = false); // Add a wall item (same as just addItem, but an additional check to verify that it is a wall) @@ -188,25 +187,25 @@ class Tile void carpetize(BaseMap* parent); // Has to do with houses - bool isHouseTile() const; - uint32_t getHouseID() const; - void addHouseExit(House* h); - void removeHouseExit(House* h); + bool isHouseTile() const noexcept; + uint32_t getHouseID() const noexcept; + void addHouseExit(House* house); + void removeHouseExit(House* house); bool isHouseExit() const; const HouseExitList* getHouseExits() const; HouseExitList* getHouseExits(); - bool hasHouseExit(uint32_t exit) const; + bool hasHouseExit(uint32_t houseId) const; void setHouse(House* house); // Mapflags (PZ, PVPZONE etc.) - void setMapFlags(uint16_t _flags); - void unsetMapFlags(uint16_t _flags); - uint16_t getMapFlags() const; + void setMapFlags(uint16_t flags); + void unsetMapFlags(uint16_t flags); + uint16_t getMapFlags() const noexcept; // Statflags (You really ought not to touch this) - void setStatFlags(uint16_t _flags); - void unsetStatFlags(uint16_t _flags); - uint16_t getStatFlags() const; + void setStatFlags(uint16_t flags); + void unsetStatFlags(uint16_t flags); + uint16_t getStatFlags() const noexcept; protected: union { @@ -225,10 +224,6 @@ class Tile Tile& operator==(const Tile& i);// Can't compare }; -bool tilePositionLessThan(const Tile* a, const Tile* b); -// This sorts them by draw order -bool tilePositionVisualLessThan(const Tile* a, const Tile* b); - typedef std::vector TileVector; typedef std::unordered_set TileSet; typedef std::list TileList; @@ -237,11 +232,11 @@ inline bool Tile::hasWall() const { return getWall() != nullptr; } -inline bool Tile::isHouseTile() const { +inline bool Tile::isHouseTile() const noexcept { return house_id != 0; } -inline uint32_t Tile::getHouseID() const { +inline uint32_t Tile::getHouseID() const noexcept { return house_id; } @@ -254,45 +249,31 @@ inline const HouseExitList* Tile::getHouseExits() const { } inline bool Tile::isHouseExit() const { - const HouseExitList* house_exits = getHouseExits(); - if(house_exits) - return !house_exits->empty(); - return false; -} - -inline bool Tile::hasHouseExit(uint32_t exit) const { - const HouseExitList* house_exits = getHouseExits(); - if(house_exits) { - for(HouseExitList::const_iterator iter = house_exits->begin(); iter != house_exits->end(); ++iter) { - if(*iter == exit) { - return true; - } - } - } - return false; + const HouseExitList* exits = location->getHouseExits(); + return exits && !exits->empty(); } -inline void Tile::setMapFlags(uint16_t _flags) { - mapflags = _flags | mapflags; +inline void Tile::setMapFlags(uint16_t flags) { + mapflags = flags | mapflags; } -inline void Tile::unsetMapFlags(uint16_t _flags) { - mapflags &= ~_flags; +inline void Tile::unsetMapFlags(uint16_t flags) { + mapflags &= ~flags; } -inline uint16_t Tile::getMapFlags() const { +inline uint16_t Tile::getMapFlags() const noexcept { return mapflags; } -inline void Tile::setStatFlags(uint16_t _flags) { - statflags = _flags | statflags; +inline void Tile::setStatFlags(uint16_t flags) { + statflags = flags | statflags; } -inline void Tile::unsetStatFlags(uint16_t _flags) { - statflags &= ~_flags; +inline void Tile::unsetStatFlags(uint16_t flags) { + statflags &= ~flags; } -inline uint16_t Tile::getStatFlags() const { +inline uint16_t Tile::getStatFlags() const noexcept { return statflags; } From 3e32dc275888fde8f132fd69b1211a038073326f Mon Sep 17 00:00:00 2001 From: Beats Date: Wed, 5 Apr 2023 18:33:37 -0400 Subject: [PATCH 13/45] Code cleanup and small optimizations (#406) --- data/items/items.xml | 4 + source/action.cpp | 4 +- source/action.h | 2 +- source/basemap.h | 4 +- source/brush.cpp | 24 +- source/carpet_brush.cpp | 23 +- source/common_windows.cpp | 12 +- source/complexitem.cpp | 2 +- source/complexitem.h | 4 +- source/doodad_brush.cpp | 19 +- source/editor.cpp | 25 +- source/filehandle.h | 6 +- source/find_item_window.cpp | 30 +-- source/graphics.cpp | 14 +- source/graphics.h | 25 +- source/ground_brush.cpp | 66 ++--- source/house.h | 2 +- source/iomap_otbm.cpp | 27 +- source/item.cpp | 169 ++++++------- source/item.h | 110 ++++---- source/items.cpp | 489 +++++++++++++++++++----------------- source/items.h | 99 ++++---- source/main_menubar.cpp | 9 +- source/map.cpp | 2 +- source/map.h | 6 +- source/map_display.cpp | 81 +++--- source/map_display.h | 6 +- source/map_drawer.cpp | 2 +- source/materials.cpp | 37 ++- source/raw_brush.cpp | 6 +- source/selection.cpp | 46 ++-- source/table_brush.cpp | 12 +- source/tileset.cpp | 22 +- source/wall_brush.cpp | 68 ++--- source/waypoints.cpp | 6 +- source/waypoints.h | 2 +- 36 files changed, 748 insertions(+), 717 deletions(-) diff --git a/data/items/items.xml b/data/items/items.xml index 6bdfca15..f54b66c8 100644 --- a/data/items/items.xml +++ b/data/items/items.xml @@ -2,6 +2,8 @@ + + @@ -20,6 +22,8 @@ + + diff --git a/source/action.cpp b/source/action.cpp index 7384b859..72d6990b 100644 --- a/source/action.cpp +++ b/source/action.cpp @@ -160,7 +160,7 @@ void Action::commit(DirtyList* dirty_list) void** data = &c->data; Tile* newtile = reinterpret_cast(*data); ASSERT(newtile); - Position pos = newtile->getPosition(); + const Position& pos = newtile->getPosition(); if(editor.IsLiveClient()) { QTreeNode* nd = editor.map.getLeaf(pos.x, pos.y); @@ -318,7 +318,7 @@ void Action::undo(DirtyList* dirty_list) void** data = &c->data; Tile* oldtile = reinterpret_cast(*data); ASSERT(oldtile); - Position pos = oldtile->getPosition(); + const Position& pos = oldtile->getPosition(); if(editor.IsLiveClient()) { QTreeNode* nd = editor.map.getLeaf(pos.x, pos.y); diff --git a/source/action.h b/source/action.h index 755df9d7..ad6f2eef 100644 --- a/source/action.h +++ b/source/action.h @@ -151,7 +151,7 @@ class BatchAction { public: virtual ~BatchAction(); - void resetTimer() {timestamp = 0;} + void resetTimer() { timestamp = 0; } // Get memory footprint size_t memsize(bool resize = false) const; diff --git a/source/basemap.h b/source/basemap.h index 083669ce..b5235822 100644 --- a/source/basemap.h +++ b/source/basemap.h @@ -104,8 +104,8 @@ class BaseMap // Assigns a tile, it might seem pointless to provide position, but it is not, as the passed tile may be nullptr void setTile(int _x, int _y, int _z, Tile* newtile, bool remove = false); - void setTile(const Position& pos, Tile* newtile, bool remove = false) {setTile(pos.x, pos.y, pos.z, newtile, remove);} - void setTile(Tile* newtile, bool remove = false) {setTile(newtile->getX(), newtile->getY(), newtile->getZ(), newtile, remove);} + void setTile(const Position& pos, Tile* newtile, bool remove = false) { setTile(pos.x, pos.y, pos.z, newtile, remove); } + void setTile(Tile* newtile, bool remove = false) { setTile(newtile->getX(), newtile->getY(), newtile->getZ(), newtile, remove); } // Replaces a tile and returns the old one Tile* swapTile(int _x, int _y, int _z, Tile* newtile); Tile* swapTile(const Position& pos, Tile* newtile) {return swapTile(pos.x, pos.y, pos.z, newtile);} diff --git a/source/brush.cpp b/source/brush.cpp index 27c77a80..b5a26e7b 100644 --- a/source/brush.cpp +++ b/source/brush.cpp @@ -367,10 +367,10 @@ void DoorBrush::switchDoor(Item* item) WallBrush::DoorType& dt = *iter; if(dt.type == doortype) { ASSERT(dt.id); - ItemType& it = g_items[dt.id]; - ASSERT(it.id != 0); + const ItemType& type = g_items.getItemType(dt.id); + ASSERT(type.id != 0); - if(it.isOpen == new_open) { + if(type.isOpen == new_open) { item->setID(dt.id); return; } @@ -413,10 +413,10 @@ bool DoorBrush::canDraw(BaseMap* map, const Position& position) const WallBrush::DoorType& dt = *iter; if(dt.type == doortype) { ASSERT(dt.id); - ItemType& it = g_items[dt.id]; - ASSERT(it.id != 0); + const ItemType& type = g_items.getItemType(dt.id); + ASSERT(type.id != 0); - if(it.isOpen == open) { + if(type.isOpen == open) { return true; } else if(!close_match) { discarded_id = dt.id; @@ -489,10 +489,10 @@ void DoorBrush::draw(BaseMap* map, Tile* tile, void* parameter) WallBrush::DoorType& dt = *iter; if(dt.type == doortype) { ASSERT(dt.id); - ItemType& it = g_items[dt.id]; - ASSERT(it.id != 0); + const ItemType& type = g_items.getItemType(dt.id); + ASSERT(type.id != 0); - if(it.isOpen == open) { + if(type.isOpen == open) { item = transformItem(item, dt.id, tile); perfect_match = true; break; @@ -557,10 +557,10 @@ void DoorBrush::draw(BaseMap* map, Tile* tile, void* parameter) WallBrush::DoorType& dt = (*it); if(dt.type == doortype) { ASSERT(dt.id); - ItemType& it = g_items[dt.id]; - ASSERT(it.id != 0); + const ItemType& type = g_items.getItemType(dt.id); + ASSERT(type.id != 0); - if(it.isOpen == open) { + if(type.isOpen == open) { item = transformItem(item, dt.id, tile); perfect_match = true; break; diff --git a/source/carpet_brush.cpp b/source/carpet_brush.cpp index 45101822..1db32693 100644 --- a/source/carpet_brush.cpp +++ b/source/carpet_brush.cpp @@ -46,7 +46,7 @@ bool CarpetBrush::load(pugi::xml_node node, wxArrayString& warnings) } if((attribute = node.attribute("server_lookid"))) { - look_id = g_items[attribute.as_ushort()].clientID; + look_id = g_items.getItemType(attribute.as_ushort()).clientID; } for(pugi::xml_node childNode = node.first_child(); childNode; childNode = childNode.next_sibling()) { @@ -91,17 +91,17 @@ bool CarpetBrush::load(pugi::xml_node node, wxArrayString& warnings) int32_t chance = attribute.as_int(); - ItemType& it = g_items[id]; - if(it.id == 0) { + ItemType* type = g_items.getRawItemType(id); + if(!type) { warnings.push_back("There is no itemtype with id " + std::to_string(id)); continue; - } else if(it.brush && it.brush != this) { + } else if(type->brush && type->brush != this) { warnings.push_back("Itemtype id " + std::to_string(id) + " already has a brush"); continue; } - it.isCarpet = true; - it.brush = this; + type->isCarpet = true; + type->brush = this; auto& alignItem = carpet_items[alignment]; alignItem.total_chance += chance; @@ -120,18 +120,17 @@ bool CarpetBrush::load(pugi::xml_node node, wxArrayString& warnings) } uint16_t id = attribute.as_ushort(); - - ItemType& it = g_items[id]; - if(it.id == 0) { + ItemType* type = g_items.getRawItemType(id); + if(!type) { warnings.push_back("There is no itemtype with id " + std::to_string(id)); return false; - } else if(it.brush && it.brush != this) { + } else if(type->brush && type->brush != this) { warnings.push_back("Itemtype id " + std::to_string(id) + " already has a brush"); return false; } - it.isCarpet = true; - it.brush = this; + type->isCarpet = true; + type->brush = this; auto& alignItem = carpet_items[alignment]; alignItem.total_chance = 1; diff --git a/source/common_windows.cpp b/source/common_windows.cpp index 39423b9c..b0b7ca19 100644 --- a/source/common_windows.cpp +++ b/source/common_windows.cpp @@ -892,11 +892,11 @@ void FindBrushDialog::OnClickOKInternal() if(!result_brush) { // Then let's search the RAWs for(int id = 0; id <= g_items.getMaxID(); ++id) { - ItemType& it = g_items[id]; - if(it.id == 0) + const ItemType& type = g_items.getItemType(id); + if(type.id == 0) continue; - RAWBrush* raw_brush = it.raw_brush; + RAWBrush* raw_brush = type.raw_brush; if(!raw_brush) continue; @@ -947,11 +947,11 @@ void FindBrushDialog::RefreshContentsInternal() } for(int id = 0; id <= g_items.getMaxID(); ++id) { - ItemType& it = g_items[id]; - if(it.id == 0) + const ItemType& type = g_items.getItemType(id); + if(type.id == 0) continue; - RAWBrush* raw_brush = it.raw_brush; + RAWBrush* raw_brush = type.raw_brush; if(!raw_brush) continue; diff --git a/source/complexitem.cpp b/source/complexitem.cpp index f2abbb61..86aedbba 100644 --- a/source/complexitem.cpp +++ b/source/complexitem.cpp @@ -56,7 +56,7 @@ Item* Container::getItem(size_t index) const double Container::getWeight() { - return g_items[id].weight; + return getItemType().weight; } // Teleport diff --git a/source/complexitem.h b/source/complexitem.h index 3b6f57d4..c56e343f 100644 --- a/source/complexitem.h +++ b/source/complexitem.h @@ -41,8 +41,8 @@ class Container : public Item Item* deepCopy() const; Item* getItem(size_t index) const; - size_t getItemCount() const { return contents.size(); } - size_t getVolume() const { return g_items[id].volume; } + size_t getItemCount() const noexcept { return contents.size(); } + size_t getVolume() const noexcept { return getItemType().volume; } ItemVector& getVector() { return contents; } double getWeight(); diff --git a/source/doodad_brush.cpp b/source/doodad_brush.cpp index de9bc660..7707a9ff 100644 --- a/source/doodad_brush.cpp +++ b/source/doodad_brush.cpp @@ -93,15 +93,12 @@ bool DoodadBrush::loadAlternative(pugi::xml_node node, wxArrayString& warnings, continue; } - ItemType& it = g_items[item->getID()]; - if(it.id != 0) { - it.doodad_brush = this; + ItemType* type = g_items.getRawItemType(item->getID()); + if(!type) { + type->doodad_brush = this; } - SingleBlock sb; - sb.item = item; - sb.chance = attribute.as_int(); - + SingleBlock sb{ attribute.as_int(), item }; alternativeBlock->single_items.push_back(sb); alternativeBlock->single_chance += sb.chance; } else if(childName == "composite") { @@ -154,9 +151,9 @@ bool DoodadBrush::loadAlternative(pugi::xml_node node, wxArrayString& warnings, if(item) { items.push_back(item); - ItemType& it = g_items[item->getID()]; - if(it.id != 0) { - it.doodad_brush = this; + ItemType* type = g_items.getRawItemType(item->getID()); + if(!type) { + type->doodad_brush = this; } } } @@ -183,7 +180,7 @@ bool DoodadBrush::load(pugi::xml_node node, wxArrayString& warnings) } if((attribute = node.attribute("server_lookid"))) { - look_id = g_items[attribute.as_ushort()].clientID; + look_id = g_items.getItemType(attribute.as_ushort()).clientID; } if((attribute = node.attribute("on_blocking"))) { diff --git a/source/editor.cpp b/source/editor.cpp index 81071a5d..eca10ac5 100644 --- a/source/editor.cpp +++ b/source/editor.cpp @@ -399,7 +399,7 @@ bool Editor::exportSelectionAsMiniMap(FileName directory, wxString fileName) if(tile->empty()) continue; - Position pos = tile->getPosition(); + const Position& pos = tile->getPosition(); if(pos.x < min_x) min_x = pos.x; @@ -1126,7 +1126,7 @@ void Editor::moveSelection(Position offset) TileList borderize_tiles; // Go through all modified (selected) tiles (might be slow) for(TileSet::iterator it = tmp_storage.begin(); it != tmp_storage.end(); ++it) { - Position pos = (*it)->getPosition(); + const Position& pos = (*it)->getPosition(); // Go through all neighbours Tile* t; t = map.getTile(pos.x , pos.y , pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t);} @@ -1205,7 +1205,7 @@ void Editor::moveSelection(Position offset) // Go through all modified (selected) tiles (might be slow) for(TileSet::iterator it = selection.begin(); it != selection.end(); it++) { bool add_me = false; // If this tile is touched - Position pos = (*it)->getPosition(); + const Position& pos = (*it)->getPosition(); // Go through all neighbours Tile* t; t = map.getTile(pos.x-1, pos.y-1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;} @@ -1299,10 +1299,8 @@ void Editor::destroySelection() if(g_settings.getInteger(Config::USE_AUTOMAGIC)) { for(int y = -1; y <= 1; y++) { for(int x = -1; x <= 1; x++) { - tilestoborder.push_back( - Position(tile->getPosition().x + x, - tile->getPosition().y + y, - tile->getPosition().z)); + const Position& position = tile->getPosition(); + tilestoborder.push_back(Position(position.x + x, position.y + y, position.z)); } } } @@ -1353,18 +1351,19 @@ void Editor::destroySelection() void doSurroundingBorders(DoodadBrush* doodad_brush, PositionList& tilestoborder, Tile* buffer_tile, Tile* new_tile) { if(doodad_brush->doNewBorders() && g_settings.getInteger(Config::USE_AUTOMAGIC)) { - tilestoborder.push_back(Position(new_tile->getPosition().x, new_tile->getPosition().y, new_tile->getPosition().z)); + const Position& position = new_tile->getPosition(); + tilestoborder.push_back(Position(position)); if(buffer_tile->hasGround()) { for(int y = -1; y <= 1; y++) { for(int x = -1; x <= 1; x++) { - tilestoborder.push_back(Position(new_tile->getPosition().x + x, new_tile->getPosition().y + y, new_tile->getPosition().z)); + tilestoborder.push_back(Position(position.x + x, position.y + y, position.z)); } } } else if(buffer_tile->hasWall()) { - tilestoborder.push_back(Position(new_tile->getPosition().x, new_tile->getPosition().y-1, new_tile->getPosition().z)); - tilestoborder.push_back(Position(new_tile->getPosition().x-1, new_tile->getPosition().y, new_tile->getPosition().z)); - tilestoborder.push_back(Position(new_tile->getPosition().x+1, new_tile->getPosition().y, new_tile->getPosition().z)); - tilestoborder.push_back(Position(new_tile->getPosition().x, new_tile->getPosition().y+1, new_tile->getPosition().z)); + tilestoborder.push_back(Position(position.x, position.y-1, position.z)); + tilestoborder.push_back(Position(position.x-1, position.y, position.z)); + tilestoborder.push_back(Position(position.x+1, position.y, position.z)); + tilestoborder.push_back(Position(position.x, position.y+1, position.z)); } } } diff --git a/source/filehandle.h b/source/filehandle.h index c5907568..f2f9b136 100644 --- a/source/filehandle.h +++ b/source/filehandle.h @@ -54,11 +54,7 @@ class FileHandle { public: FileHandle() : error_code(FILE_NO_ERROR), file(nullptr) {} - virtual ~FileHandle() {close();} - - // Ensures we don't accidentally copy it. - FileHandle(const FileHandle &) = delete; - FileHandle &operator=(const FileHandle &) = delete; + virtual ~FileHandle() { close(); } virtual void close(); virtual bool isOpen() {return file != nullptr;} diff --git a/source/find_item_window.cpp b/source/find_item_window.cpp index 50b83a7b..ad356f60 100644 --- a/source/find_item_window.cpp +++ b/source/find_item_window.cpp @@ -54,12 +54,12 @@ FindItemDialog::FindItemDialog(wxWindow* parent, const wxString& title, bool onl options_box_sizer->Add(options_radio_box, 0, wxALL | wxEXPAND, 5); wxStaticBoxSizer* server_id_box_sizer = newd wxStaticBoxSizer(newd wxStaticBox(this, wxID_ANY, "Server ID"), wxVERTICAL); - server_id_spin = newd wxSpinCtrl(server_id_box_sizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 100, g_items.getMaxID(), 100); + server_id_spin = newd wxSpinCtrl(server_id_box_sizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, g_items.getMinID(), g_items.getMaxID(), g_items.getMinID()); server_id_box_sizer->Add(server_id_spin, 0, wxALL | wxEXPAND, 5); options_box_sizer->Add(server_id_box_sizer, 1, wxALL | wxEXPAND, 5); wxStaticBoxSizer* client_id_box_sizer = newd wxStaticBoxSizer(newd wxStaticBox(this, wxID_ANY, "Client ID"), wxVERTICAL); - client_id_spin = newd wxSpinCtrl(client_id_box_sizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 100, g_gui.gfx.getItemSpriteMaxID(), 100); + client_id_spin = newd wxSpinCtrl(client_id_box_sizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, g_gui.gfx.getItemSpriteMinID(), g_gui.gfx.getItemSpriteMaxID(), g_gui.gfx.getItemSpriteMinID()); client_id_spin->Enable(false); client_id_box_sizer->Add(client_id_spin, 0, wxALL | wxEXPAND, 5); options_box_sizer->Add(client_id_box_sizer, 1, wxALL | wxEXPAND, 5); @@ -285,8 +285,8 @@ void FindItemDialog::RefreshContentsInternal() if(selection == SearchMode::ServerIDs) { uint16_t serverID = (uint16_t)server_id_spin->GetValue(); - for(int id = 100; id <= g_items.getMaxID(); ++id) { - ItemType& item = g_items.getItemType(id); + for(int id = g_items.getMinID(); id <= g_items.getMaxID(); ++id) { + const ItemType& item = g_items.getItemType(id); if(item.id != serverID) continue; @@ -302,10 +302,10 @@ void FindItemDialog::RefreshContentsInternal() } } else if(selection == SearchMode::ClientIDs) { - uint16_t clientID = (uint16_t)client_id_spin->GetValue(); - for (int id = 100; id <= g_items.getMaxID(); ++id) { - ItemType& item = g_items.getItemType(id); - if (item.id == 0 || item.clientID != clientID) + uint16_t clientID = static_cast(client_id_spin->GetValue()); + for(int id = g_items.getMinID(); id <= g_items.getMaxID(); ++id) { + const ItemType& item = g_items.getItemType(id); + if(item.id == 0 || item.clientID != clientID) continue; RAWBrush* raw_brush = item.raw_brush; @@ -322,8 +322,8 @@ void FindItemDialog::RefreshContentsInternal() else if(selection == SearchMode::Names) { std::string search_string = as_lower_str(nstr(name_text_input->GetValue())); if(search_string.size() >= 2) { - for(int id = 100; id <= g_items.getMaxID(); ++id) { - ItemType& item = g_items.getItemType(id); + for(int id = g_items.getMinID(); id <= g_items.getMaxID(); ++id) { + const ItemType& item = g_items.getItemType(id); if(item.id == 0) continue; @@ -343,9 +343,9 @@ void FindItemDialog::RefreshContentsInternal() } } else if(selection == SearchMode::Types) { - for(int id = 100; id <= g_items.getMaxID(); ++id) { - ItemType& item = g_items.getItemType(id); - if (item.id == 0) + for(int id = g_items.getMinID(); id <= g_items.getMaxID(); ++id) { + const ItemType& item = g_items.getItemType(id); + if(item.id == 0) continue; RAWBrush* raw_brush = item.raw_brush; @@ -390,8 +390,8 @@ void FindItemDialog::RefreshContentsInternal() floor_change->GetValue()); if(has_selected) { - for(int id = 100; id <= g_items.getMaxID(); ++id) { - ItemType& item = g_items.getItemType(id); + for(int id = g_items.getMinID(); id <= g_items.getMaxID(); ++id) { + const ItemType& item = g_items.getItemType(id); if(item.id == 0) continue; diff --git a/source/graphics.cpp b/source/graphics.cpp index 2d7882c0..620ee4ea 100644 --- a/source/graphics.cpp +++ b/source/graphics.cpp @@ -15,7 +15,6 @@ // along with this program. If not, see . ////////////////////////////////////////////////////////////////////// - #include "main.h" #include "sprites.h" @@ -176,16 +175,6 @@ GameSprite* GraphicManager::getEditorSprite(int id) return nullptr; } -uint16_t GraphicManager::getItemSpriteMaxID() const -{ - return item_count; -} - -uint16_t GraphicManager::getCreatureSpriteMaxID() const -{ - return creature_count; -} - #define loadPNGFile(name) _wxGetBitmapFromMemory(name, sizeof(name)) inline wxBitmap* _wxGetBitmapFromMemory(const unsigned char* data, int length) { @@ -1271,7 +1260,8 @@ GameSprite::TemplateImage::~TemplateImage() //// } -void GameSprite::TemplateImage::colorizePixel(uint8_t color, uint8_t& red, uint8_t& green, uint8_t& blue) { +void GameSprite::TemplateImage::colorizePixel(uint8_t color, uint8_t& red, uint8_t& green, uint8_t& blue) +{ // Thanks! Khaos, or was it mips? Hmmm... =) uint8_t ro = (TemplateOutfitLookupTable[color] & 0xFF0000) >> 16; // rgb outfit uint8_t go = (TemplateOutfitLookupTable[color] & 0xFF00) >> 8; diff --git a/source/graphics.h b/source/graphics.h index f06bc3d5..827dbc50 100644 --- a/source/graphics.h +++ b/source/graphics.h @@ -53,6 +53,7 @@ class Sprite { virtual void DrawTo(wxDC* dc, SpriteSize sz, int start_x, int start_y, int width = -1, int height = -1) = 0; virtual void unloadDC() = 0; + private: Sprite(const Sprite&); Sprite& operator=(const Sprite&); @@ -189,7 +190,6 @@ class GameSprite : public Sprite{ Animator* animator; uint16_t draw_height; - uint16_t drawoffset_x; wxPoint draw_offset; uint16_t minimap_color; @@ -275,8 +275,9 @@ class GraphicManager long getElapsedTime() const { return (animation_timer->TimeInMicro() / 1000).ToLong(); } - uint16_t getItemSpriteMaxID() const; - uint16_t getCreatureSpriteMaxID() const; + uint16_t getItemSpriteMinID() const noexcept { return 100; } + uint16_t getItemSpriteMaxID() const noexcept { return item_count; } + uint16_t getCreatureSpriteMaxID() const noexcept { return creature_count; } // Get an unused texture id (this is acquired by simply increasing a value starting from 0x10000000) GLuint getFreeTextureID(); @@ -336,22 +337,4 @@ class GraphicManager friend class GameSprite::TemplateImage; }; -struct RGBQuad { - uint8_t red; - uint8_t green; - uint8_t blue; - uint8_t reserved; - - RGBQuad(uint8_t r, uint8_t g, uint8_t b) : red(r), green (g), blue(b), reserved(0) {} - - operator uint32_t() { - return (blue << 0) | (green << 8) | (red << 16); - } - - operator bool() { - //std::cout << "RGBQuad operator bool " << int(red) << " || " << int(blue) << " || " << int(green) << std::endl; - return blue != 0 || red != 0 || green != 0; - } -}; - #endif diff --git a/source/ground_brush.cpp b/source/ground_brush.cpp index 1949a4ce..56ec869b 100644 --- a/source/ground_brush.cpp +++ b/source/ground_brush.cpp @@ -82,33 +82,33 @@ bool AutoBorder::load(pugi::xml_node node, wxArrayString& warnings, GroundBrush* const std::string& orientation = attribute.as_string(); - ItemType& it = g_items[itemid]; - if(it.id == 0) { + ItemType* type = g_items.getRawItemType(itemid); + if(!type) { warnings.push_back("Invalid item ID " + std::to_string(itemid) + " for border " + std::to_string(id)); continue; } if(ground) { // We are a ground border - it.group = ITEM_GROUP_NONE; - it.ground_equivalent = ground_equivalent; - it.brush = owner; + type->group = ITEM_GROUP_NONE; + type->ground_equivalent = ground_equivalent; + type->brush = owner; - ItemType& it2 = g_items[ground_equivalent]; - it2.has_equivalent = it2.id != 0; + ItemType* type2 = g_items.getRawItemType(ground_equivalent); + type2->has_equivalent = type2->id != 0; } - it.alwaysOnBottom = true; // Never-ever place other items under this, will confuse the user something awful. - it.isBorder = true; - it.isOptionalBorder = it.isOptionalBorder ? true : optionalBorder; - if(group && !it.border_group) { - it.border_group = group; + type->alwaysOnBottom = true; // Never-ever place other items under this, will confuse the user something awful. + type->isBorder = true; + type->isOptionalBorder = type->isOptionalBorder ? true : optionalBorder; + if(group && !type->border_group) { + type->border_group = group; } int32_t edge_id = edgeNameToID(orientation); if(edge_id != BORDER_NONE) { tiles[edge_id] = itemid; - if(it.border_alignment == BORDER_NONE) { - it.border_alignment = ::BorderType(edge_id); + if(type->border_alignment == BORDER_NONE) { + type->border_alignment = ::BorderType(edge_id); } } } @@ -153,6 +153,10 @@ bool GroundBrush::load(pugi::xml_node node, wxArrayString& warnings) look_id = attribute.as_ushort(); } + if((attribute = node.attribute("server_lookid"))) { + look_id = g_items.getItemType(attribute.as_ushort()).clientID; + } + if((attribute = node.attribute("z-order"))) { z_order = attribute.as_int(); } @@ -171,23 +175,23 @@ bool GroundBrush::load(pugi::xml_node node, wxArrayString& warnings) uint16_t itemId = childNode.attribute("id").as_ushort(); int32_t chance = childNode.attribute("chance").as_int(); - ItemType& it = g_items[itemId]; - if(it.id == 0) { + ItemType* type = g_items.getRawItemType(itemId); + if(!type) { warnings.push_back("\nInvalid item id " + std::to_string(itemId)); return false; } - if(!it.isGroundTile()) { + if(!type->isGroundTile()) { warnings.push_back("\nItem " + std::to_string(itemId) + " is not ground item."); return false; } - if(it.brush && it.brush != this) { + if(type->brush && type->brush != this) { warnings.push_back("\nItem " + std::to_string(itemId) + " can not be member of two brushes"); return false; } - it.brush = this; + type->brush = this; total_chance += chance; ItemChanceBlock ci; @@ -205,14 +209,14 @@ bool GroundBrush::load(pugi::xml_node node, wxArrayString& warnings) uint16_t ground_equivalent = attribute.as_ushort(); // Load from inline definition - ItemType& it = g_items[ground_equivalent]; - if(it.id == 0) { + const ItemType& type = g_items.getItemType(ground_equivalent); + if(type.id == 0) { warnings.push_back("Invalid id of ground dependency equivalent item.\n"); continue; - } else if(!it.isGroundTile()) { - warnings.push_back("Ground id " + std::to_string(ground_equivalent) + " dependency equivalent is not a ground item.\n"); + } else if(!type.isGroundTile()) { + warnings.push_back("Ground dependency equivalent is not a ground item.\n"); continue; - } else if(it.brush && it.brush != this) { + } else if(type.brush && type.brush != this) { warnings.push_back("Ground dependency equivalent does not use the same brush as ground border.\n"); continue; } @@ -244,7 +248,7 @@ bool GroundBrush::load(pugi::xml_node node, wxArrayString& warnings) } uint16_t ground_equivalent = attribute.as_ushort(); - ItemType& it = g_items[ground_equivalent]; + const ItemType& it = g_items.getItemType(ground_equivalent); if(it.id == 0) { warnings.push_back("Invalid id of ground dependency equivalent item.\n"); } @@ -420,12 +424,12 @@ bool GroundBrush::load(pugi::xml_node node, wxArrayString& warnings) AutoBorder* autoBorder = itt->second; ASSERT(autoBorder != nullptr); - ItemType& it = g_items[with_id]; - if(it.id == 0) { + ItemType* type = g_items.getRawItemType(with_id); + if(!type) { return false; } - it.isBorder = true; + type->isBorder = true; if(!specificCaseBlock) { specificCaseBlock = newd SpecificCaseBlock(); } @@ -443,12 +447,12 @@ bool GroundBrush::load(pugi::xml_node node, wxArrayString& warnings) } int32_t with_id = attribute.as_int(); - ItemType& it = g_items[with_id]; - if(it.id == 0) { + ItemType* type = g_items.getRawItemType(with_id); + if(!type) { return false; } - it.isBorder = true; + type->isBorder = true; if(!specificCaseBlock) { specificCaseBlock = newd SpecificCaseBlock(); } diff --git a/source/house.h b/source/house.h index 0c31fb48..af70a928 100644 --- a/source/house.h +++ b/source/house.h @@ -73,7 +73,7 @@ class Houses { #ifdef __VISUALC__ // C++0x compliance to some degree :) HouseMap::iterator erase(HouseMap::iterator iter) {return houses.erase(iter);} #else - void erase(HouseMap::iterator iter) {houses.erase(iter);} + void erase(HouseMap::iterator iter) { houses.erase(iter); } #endif HouseMap::iterator find(uint32_t val) {return houses.find(val);} diff --git a/source/iomap_otbm.cpp b/source/iomap_otbm.cpp index c76630e3..129ce778 100644 --- a/source/iomap_otbm.cpp +++ b/source/iomap_otbm.cpp @@ -67,20 +67,19 @@ void reform(Map* map, Tile* tile, Item* item) Item* Item::Create_OTBM(const IOMap& maphandle, BinaryNode* stream) { - uint16_t _id; - if(!stream->getU16(_id)) { + uint16_t id; + if(!stream->getU16(id)) { return nullptr; } - uint8_t _count = 0; - - const ItemType& iType = g_items[_id]; + const ItemType& type = g_items.getItemType(id); + uint8_t count = 0; if(maphandle.version.otbm == MAP_OTBM_1) { - if(iType.stackable || iType.isSplash() || iType.isFluidContainer()) { - stream->getU8(_count); + if(type.stackable || type.isSplash() || type.isFluidContainer()) { + stream->getU8(count); } } - return Item::Create(_id, _count); + return Item::Create(id, count); } bool Item::readItemAttribute_OTBM(const IOMap& maphandle, OTBM_ItemAttribute attr, BinaryNode* stream) @@ -177,8 +176,8 @@ bool Item::unserializeItemNode_OTBM(const IOMap& maphandle, BinaryNode* node) void Item::serializeItemAttributes_OTBM(const IOMap& maphandle, NodeFileWriteHandle& stream) const { if(maphandle.version.otbm >= MAP_OTBM_2) { - const ItemType& iType = g_items[id]; - if(iType.stackable || iType.isSplash() || iType.isFluidContainer()) { + const ItemType& type = g_items.getItemType(id); + if(type.stackable || type.isSplash() || type.isFluidContainer()) { stream.addU8(OTBM_ATTR_COUNT); stream.addU8(getSubtype()); } @@ -239,8 +238,8 @@ bool Item::serializeItemNode_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f file.addNode(OTBM_ITEM); file.addU16(id); if(maphandle.version.otbm == MAP_OTBM_1) { - const ItemType& iType = g_items[id]; - if(iType.stackable || iType.isSplash() || iType.isFluidContainer()) { + const ItemType& type = g_items.getItemType(id); + if(type.stackable || type.isSplash() || type.isFluidContainer()) { file.addU8(getSubtype()); } } @@ -372,8 +371,8 @@ bool Container::serializeItemNode_OTBM(const IOMap& maphandle, NodeFileWriteHand file.addU16(id); if(maphandle.version.otbm == MAP_OTBM_1) { // In the ludicrous event that an item is a container AND stackable, we have to do this. :p - const ItemType& iType = g_items[id]; - if(iType.stackable || iType.isSplash() || iType.isFluidContainer()) { + const ItemType& type = g_items.getItemType(id); + if(type.stackable || type.isSplash() || type.isFluidContainer()) { file.addU8(getSubtype()); } } diff --git a/source/item.cpp b/source/item.cpp index 97fbcdb1..5afdcc58 100644 --- a/source/item.cpp +++ b/source/item.cpp @@ -30,40 +30,35 @@ #include "table_brush.h" #include "wall_brush.h" -Item* Item::Create(uint16_t _type, uint16_t _subtype /*= 0xFFFF*/) -{ - if(_type == 0) return nullptr; - Item* newItem = nullptr; - - const ItemType& it = g_items[_type]; - - if(it.id != 0){ - if(it.isDepot()) { - newItem = newd Depot(_type); - } else if(it.isContainer()) { - newItem = newd Container(_type); - } else if(it.isTeleport()) { - newItem = newd Teleport(_type); - } else if(it.isDoor()) { - newItem = newd Door(_type); - } else if(_subtype == 0xFFFF) { - if(it.isFluidContainer()) { - newItem = newd Item(_type, LIQUID_NONE); - } else if(it.isSplash()) { - newItem = newd Item(_type, LIQUID_WATER); - } else if(it.charges > 0) { - newItem = newd Item(_type, it.charges); - } else { - newItem = newd Item(_type, 1); - } +Item* Item::Create(uint16_t id, uint16_t subtype /*= 0xFFFF*/) +{ + if(id == 0) return nullptr; + + const ItemType& type = g_items.getItemType(id); + if(type.id == 0) { + return newd Item(id, subtype); + } + + if(type.isDepot()) { + return new Depot(id); + } else if(type.isContainer()) { + return new Container(id); + } else if(type.isTeleport()) { + return new Teleport(id); + } else if(type.isDoor()) { + return new Door(id); + } else if(subtype == 0xFFFF) { + if(type.isFluidContainer()) { + return new Item(id, LIQUID_NONE); + } else if(type.isSplash()) { + return new Item(id, LIQUID_WATER); + } else if(type.charges > 0) { + return new Item(id, type.charges); } else { - newItem = newd Item(_type, _subtype); + return new Item(id, 1); } - } else { - newItem = newd Item(_type, _subtype); } - - return newItem; + return new Item(id, subtype); } Item::Item(unsigned short _type, unsigned short _count) : @@ -153,41 +148,42 @@ uint32_t Item::memsize() const return mem; } -void Item::setID(uint16_t newid) +void Item::setID(uint16_t new_id) { - id = newid; + id = new_id; } -void Item::setSubtype(uint16_t n) +void Item::setSubtype(uint16_t _subtype) { - subtype = n; + subtype = _subtype; } bool Item::hasSubtype() const { - const ItemType& it = g_items[id]; - return (it.isFluidContainer() || it.isSplash() || isCharged() || it.stackable || it.charges != 0); + const ItemType& type = g_items.getItemType(id); + return (type.isFluidContainer() + || type.stackable + || type.charges != 0 + || type.isSplash() + || isCharged()); } uint16_t Item::getSubtype() const { - if(hasSubtype()) { - return subtype; - } - return 0; + return hasSubtype() ? subtype : 0; } bool Item::hasProperty(enum ITEMPROPERTY prop) const { - const ItemType& it = g_items[id]; - switch(prop){ + const ItemType& type = g_items.getItemType(id); + switch(prop) { case BLOCKSOLID: - if(it.unpassable) + if(type.unpassable) return true; break; case MOVEABLE: - if(it.moveable && getUniqueID() == 0) + if(type.moveable && getUniqueID() == 0) return true; break; /* @@ -197,27 +193,27 @@ bool Item::hasProperty(enum ITEMPROPERTY prop) const break; */ case BLOCKPROJECTILE: - if(it.blockMissiles) + if(type.blockMissiles) return true; break; case BLOCKPATHFIND: - if(it.blockPathfinder) + if(type.blockPathfinder) return true; break; case HOOK_SOUTH: - if(it.hookSouth) + if(type.hookSouth) return true; break; case HOOK_EAST: - if(it.hookEast) + if(type.hookEast) return true; break; case BLOCKINGANDNOTMOVEABLE: - if(it.unpassable && (!it.moveable || getUniqueID() != 0)) + if(type.unpassable && (!type.moveable || getUniqueID() != 0)) return true; break; @@ -229,21 +225,20 @@ bool Item::hasProperty(enum ITEMPROPERTY prop) const wxPoint Item::getDrawOffset() const { - ItemType& it = g_items[id]; - if(it.sprite != nullptr) { - return it.sprite->getDrawOffset(); + const ItemType& type = g_items.getItemType(id); + if(type.sprite) { + return type.sprite->getDrawOffset(); } return wxPoint(0, 0); } double Item::getWeight() const { - ItemType& it = g_items[id]; - if(it.stackable) { - return it.weight * std::max(1, (int)subtype); + const ItemType& type = g_items.getItemType(id); + if(type.stackable) { + return type.weight * std::max(1, (int)subtype); } - - return it.weight; + return type.weight; } void Item::setUniqueID(unsigned short n) @@ -268,11 +263,11 @@ void Item::setDescription(const std::string& str) double Item::getWeight() { - ItemType& it = g_items[id]; - if(it.isStackable()) { - return it.weight * subtype; + const ItemType& type = g_items.getItemType(id); + if(type.isStackable()) { + return type.weight * subtype; } - return it.weight; + return type.weight; } bool Item::canHoldText() const @@ -282,53 +277,53 @@ bool Item::canHoldText() const bool Item::canHoldDescription() const { - return g_items[id].allowDistRead; + return g_items.getItemType(id).allowDistRead; } uint8_t Item::getMiniMapColor() const { - GameSprite* spr = g_items[id].sprite; - if(spr) { - return spr->getMiniMapColor(); + GameSprite* sprite = g_items.getItemType(id).sprite; + if(sprite) { + return sprite->getMiniMapColor(); } return 0; } GroundBrush* Item::getGroundBrush() const { - ItemType& item_type = g_items.getItemType(id); - if(item_type.isGroundTile() && item_type.brush && item_type.brush->isGround()) { - return item_type.brush->asGround(); + const ItemType& type = g_items.getItemType(id); + if(type.isGroundTile() && type.brush && type.brush->isGround()) { + return type.brush->asGround(); } return nullptr; } TableBrush* Item::getTableBrush() const { - ItemType& item_type = g_items.getItemType(id); - if(item_type.isTable && item_type.brush && item_type.brush->isTable()) { - return item_type.brush->asTable(); + const ItemType& type = g_items.getItemType(id); + if(type.isTable && type.brush && type.brush->isTable()) { + return type.brush->asTable(); } return nullptr; } CarpetBrush* Item::getCarpetBrush() const { - ItemType& item_type = g_items.getItemType(id); - if(item_type.isCarpet && item_type.brush && item_type.brush->isCarpet()) { - return item_type.brush->asCarpet(); + const ItemType& type = g_items.getItemType(id); + if(type.isCarpet && type.brush && type.brush->isCarpet()) { + return type.brush->asCarpet(); } return nullptr; } DoorBrush* Item::getDoorBrush() const { - ItemType& item_type = g_items.getItemType(id); - if(!item_type.isWall || !item_type.isBrushDoor || !item_type.brush || !item_type.brush->isWall()) { + const ItemType& type = g_items.getItemType(id); + if(!type.isWall || !type.isBrushDoor || !type.brush || !type.brush->isWall()) { return nullptr; } - DoorType door_type = item_type.brush->asWall()->getDoorTypeFromID(id); + DoorType door_type = type.brush->asWall()->getDoorTypeFromID(id); DoorBrush* door_brush = nullptr; // Quite a horrible dependency on a global here, meh. switch(door_type) { @@ -365,30 +360,30 @@ DoorBrush* Item::getDoorBrush() const WallBrush* Item::getWallBrush() const { - ItemType& item_type = g_items.getItemType(id); - if(item_type.isWall && item_type.brush && item_type.brush->isWall()) - return item_type.brush->asWall(); + const ItemType& type = g_items.getItemType(id); + if(type.isWall && type.brush && type.brush->isWall()) + return type.brush->asWall(); return nullptr; } BorderType Item::getWallAlignment() const { - ItemType& it = g_items[id]; - if(!it.isWall) { + const ItemType& type = g_items.getItemType(id); + if(!type.isWall) { return BORDER_NONE; } - return it.border_alignment; + return type.border_alignment; } BorderType Item::getBorderAlignment() const { - ItemType& it = g_items[id]; - return it.border_alignment; + const ItemType& type = g_items.getItemType(id); + return type.border_alignment; } void Item::animate() { - ItemType& type = g_items[id]; + const ItemType& type = g_items.getItemType(id); GameSprite* sprite = type.sprite; if(!sprite || !sprite->animator) return; diff --git a/source/item.h b/source/item.h index 8e1bc0e7..5bc92dfb 100644 --- a/source/item.h +++ b/source/item.h @@ -76,7 +76,7 @@ class Item : public ItemAttributes { public: //Factory member to create item of right type based on type - static Item* Create(uint16_t _type, uint16_t _subtype = 0xFFFF); + static Item* Create(uint16_t id, uint16_t subtype = 0xFFFF); static Item* Create(pugi::xml_node); static Item* Create_OTBM(const IOMap& maphandle, BinaryNode* stream); //static Item* Create_OTMM(const IOMap& maphandle, BinaryNode* stream); @@ -84,6 +84,7 @@ class Item : public ItemAttributes protected: // Constructor for items Item(unsigned short _type, unsigned short _count); + public: virtual ~Item(); @@ -139,39 +140,42 @@ class Item : public ItemAttributes static std::string LiquidID2Name(uint16_t id); static uint16_t LiquidName2ID(std::string id); + const ItemType& getItemType() const noexcept { return g_items.getItemType(id); } + // IDs - uint16_t getID() const {return id;} - uint16_t getClientID() const {return g_items[id].clientID;} + uint16_t getID() const { return id; } + uint16_t getClientID() const { return g_items.getItemType(id).clientID; } + // NOTE: This is very volatile, do NOT use this unless you know exactly what you're doing // which you probably don't so avoid it like the plague! - void setID(uint16_t id); + void setID(uint16_t new_id); - bool typeExists() const {return g_items.typeExists(id);} + bool isValidID() const { return g_items.isValidID(id); } // Usual attributes virtual double getWeight() const; - int getAttack() const {return g_items[id].attack;} - int getArmor() const {return g_items[id].armor;} - int getDefense() const {return g_items[id].defense;} - //int getSlotPosition() const {return g_items[id].slot_position;} + int getAttack() const { return getItemType().attack; } + int getArmor() const { return getItemType().armor; } + int getDefense() const { return getItemType().defense; } + //int getSlotPosition() const { return g_items.getItemType(id).slot_position; } // Item g_settings bool canHoldText() const; bool canHoldDescription() const; - bool isReadable() const {return g_items[id].canReadText;} - bool canWriteText() const {return g_items[id].canWriteText;} - uint32_t getMaxWriteLength() const {return g_items[id].maxTextLen;} - Brush* getBrush() const {return g_items[id].brush;} + bool isReadable() const { return getItemType().canReadText; } + bool canWriteText() const { return getItemType().canWriteText; } + uint32_t getMaxWriteLength() const { return getItemType().maxTextLen; } + Brush* getBrush() const { return getItemType().brush; } GroundBrush* getGroundBrush() const; WallBrush* getWallBrush() const; DoorBrush* getDoorBrush() const; TableBrush* getTableBrush() const; CarpetBrush* getCarpetBrush() const; - Brush* getDoodadBrush() const {return g_items[id].doodad_brush;} // This is not necessarily a doodad brush - RAWBrush* getRAWBrush() const {return g_items[id].raw_brush;} - uint16_t getGroundEquivalent() const {return g_items[id].ground_equivalent;} - uint16_t hasBorderEquivalent() const {return g_items[id].has_equivalent;} - uint32_t getBorderGroup() const {return g_items[id].border_group;} + Brush* getDoodadBrush() const { return getItemType().doodad_brush; } // This is not necessarily a doodad brush + RAWBrush* getRAWBrush() const { return getItemType().raw_brush; } + uint16_t getGroundEquivalent() const { return getItemType().ground_equivalent; } + uint16_t hasBorderEquivalent() const { return getItemType().has_equivalent; } + uint32_t getBorderGroup() const { return getItemType().border_group; } // Drawing related uint8_t getMiniMapColor() const; @@ -179,35 +183,34 @@ class Item : public ItemAttributes // Item types bool hasProperty(enum ITEMPROPERTY prop) const; - bool isBlocking() const {return g_items[id].unpassable;} - bool isStackable() const {return g_items[id].stackable;} - bool isClientCharged() const {return g_items[id].isClientCharged();} - bool isExtraCharged() const {return g_items[id].isExtraCharged();} - bool isCharged() const {return isClientCharged() || isExtraCharged();} - bool isFluidContainer() const {return (g_items[id].isFluidContainer());} - bool isAlwaysOnBottom() const {return g_items[id].alwaysOnBottom;} - int getTopOrder() const {return g_items[id].alwaysOnTopOrder;} - bool isGroundTile() const {return g_items[id].isGroundTile();} - bool isSplash() const {return g_items[id].isSplash();} - bool isMagicField() const {return g_items[id].isMagicField();} - bool isNotMoveable() const {return !g_items[id].moveable;} - bool isMoveable() const {return g_items[id].moveable;} - bool isPickupable() const {return g_items[id].pickupable;} - //bool isWeapon() const {return (g_items[id].weaponType != WEAPON_NONE && g_items[id].weaponType != WEAPON_AMMO);} - //bool isUseable() const {return g_items[id].useable;} - bool isHangable() const {return g_items[id].isHangable;} - bool isRoteable() const {const ItemType& it = g_items[id]; return it.rotable && it.rotateTo;} - void doRotate() {if(isRoteable()) id = g_items[id].rotateTo;} - bool hasCharges() const {return g_items[id].charges != 0;} - bool isBorder() const {return g_items[id].isBorder;} - bool isOptionalBorder() const {return g_items[id].isOptionalBorder;} - bool isWall() const {return g_items[id].isWall;} - bool isDoor() const {return g_items[id].isDoor();} - bool isOpen() const {return g_items[id].isOpen;} - bool isBrushDoor() const {return g_items[id].isBrushDoor;} - bool isTable() const {return g_items[id].isTable;} - bool isCarpet() const {return g_items[id].isCarpet;} - bool isMetaItem() const {return g_items[id].isMetaItem();} + bool isBlocking() const { return getItemType().unpassable; } + bool isStackable() const { return getItemType().stackable; } + bool isClientCharged() const { return getItemType().isClientCharged(); } + bool isExtraCharged() const { return getItemType().isExtraCharged(); } + bool isCharged() const { return isClientCharged() || isExtraCharged(); } + bool isFluidContainer() const { return (getItemType().isFluidContainer()); } + bool isAlwaysOnBottom() const { return getItemType().alwaysOnBottom; } + int getTopOrder() const { return getItemType().alwaysOnTopOrder; } + bool isGroundTile() const { return getItemType().isGroundTile(); } + bool isSplash() const { return getItemType().isSplash(); } + bool isMagicField() const { return getItemType().isMagicField(); } + bool isNotMoveable() const { return !getItemType().moveable; } + bool isMoveable() const { return getItemType().moveable; } + bool isPickupable() const { return getItemType().pickupable; } + //bool isWeapon() const { return (getItemType().weaponType != WEAPON_NONE && g_items[id].weaponType != WEAPON_AMMO); } + //bool isUseable() const { return getItemType().useable; } + bool isHangable() const { return getItemType().isHangable; } + bool isRoteable() const { return getItemType().rotable && getItemType().rotateTo; } + bool hasCharges() const { return getItemType().charges != 0; } + bool isBorder() const { return getItemType().isBorder; } + bool isOptionalBorder() const { return getItemType().isOptionalBorder; } + bool isWall() const { return getItemType().isWall; } + bool isDoor() const { return getItemType().isDoor(); } + bool isOpen() const { return getItemType().isOpen; } + bool isBrushDoor() const { return getItemType().isBrushDoor; } + bool isTable() const { return getItemType().isTable; } + bool isCarpet() const { return getItemType().isCarpet; } + bool isMetaItem() const { return getItemType().isMetaItem(); } // Wall alignment (vertical, horizontal, pole, corner) BorderType getWallAlignment() const; @@ -215,8 +218,8 @@ class Item : public ItemAttributes BorderType getBorderAlignment() const; // Get the name! - const std::string getName() const {return g_items[id].name;} - const std::string getFullName() const {return g_items[id].name + g_items[id].editorsuffix;} + const std::string getName() const { return getItemType().name; } + const std::string getFullName() const { return getItemType().name + getItemType().editorsuffix; } // Selection bool isSelected() const {return selected;} @@ -234,7 +237,7 @@ class Item : public ItemAttributes // Subtype (count, fluid, charges) int getCount() const; uint16_t getSubtype() const; - void setSubtype(uint16_t n); + void setSubtype(uint16_t subtype); bool hasSubtype() const; void setUniqueID(uint16_t n); @@ -252,6 +255,12 @@ class Item : public ItemAttributes void animate(); int getFrame() const {return frame;} + void doRotate() { + if(isRoteable()) { + setID(getItemType().rotateTo); + } + } + protected: uint16_t id; // the same id as in ItemType // Subtype is either fluid type, count, subtype or charges @@ -270,7 +279,6 @@ typedef std::list ItemList; Item* transformItem(Item* old_item, uint16_t new_id, Tile* parent = nullptr); - inline int Item::getCount() const { if(isStackable() || isExtraCharged() || isClientCharged()) { return subtype; diff --git a/source/items.cpp b/source/items.cpp index dfc717f6..9c372555 100644 --- a/source/items.cpp +++ b/source/items.cpp @@ -96,14 +96,14 @@ ItemType::ItemType() : //// } -ItemType::~ItemType() +bool ItemType::isFloorChange() const noexcept { - //// -} - -bool ItemType::isFloorChange() const -{ - return floorChange || floorChangeDown || floorChangeNorth || floorChangeSouth || floorChangeEast || floorChangeWest; + return floorChange + || floorChangeDown + || floorChangeNorth + || floorChangeSouth + || floorChangeEast + || floorChangeWest; } ItemDatabase::ItemDatabase() : @@ -118,10 +118,10 @@ ItemDatabase::ItemDatabase() : monster_count(0), distance_count(0), - minclientID(0), - maxclientID(0), + minClientID(0), + maxClientID(0), - max_item_id(0) + maxItemId(0) { //// } @@ -133,7 +133,7 @@ ItemDatabase::~ItemDatabase() void ItemDatabase::clear() { - for(uint32_t i = 0; i < items.size(); i++) { + for(size_t i = 0; i < items.size(); i++) { delete items[i]; items.set(i, nullptr); } @@ -141,22 +141,21 @@ void ItemDatabase::clear() bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArrayString& warnings) { - uint8_t u8; - - for( ; itemNode != nullptr; itemNode = itemNode->advance()) { - if(!itemNode->getU8(u8)) { + for(; itemNode != nullptr; itemNode = itemNode->advance()) { + uint8_t group; + if(!itemNode->getU8(group)) { // Invalid! warnings.push_back("Invalid item type encountered..."); continue; } - if(u8 == ITEM_GROUP_DEPRECATED) + if(group == ITEM_GROUP_DEPRECATED) continue; - ItemType* t = newd ItemType(); - t->group = ItemGroup_t(u8); + ItemType* item = new ItemType(); + item->group = static_cast(group); - switch(t->group) { + switch(item->group) { case ITEM_GROUP_NONE: case ITEM_GROUP_GROUND: case ITEM_GROUP_SPLASH: @@ -167,39 +166,50 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra case ITEM_GROUP_WRITEABLE: case ITEM_GROUP_KEY: break; - case ITEM_GROUP_DOOR: t->type = ITEM_TYPE_DOOR; break; - case ITEM_GROUP_CONTAINER: t->type = ITEM_TYPE_CONTAINER; break; - case ITEM_GROUP_RUNE: t->client_chargeable = true; break; - case ITEM_GROUP_TELEPORT: t->type = ITEM_TYPE_TELEPORT; break; - case ITEM_GROUP_MAGICFIELD: t->type = ITEM_TYPE_MAGICFIELD; break; + case ITEM_GROUP_DOOR: + item->type = ITEM_TYPE_DOOR; + break; + case ITEM_GROUP_CONTAINER: + item->type = ITEM_TYPE_CONTAINER; + break; + case ITEM_GROUP_RUNE: + item->client_chargeable = true; + break; + case ITEM_GROUP_TELEPORT: + item->type = ITEM_TYPE_TELEPORT; + break; + case ITEM_GROUP_MAGICFIELD: + item->type = ITEM_TYPE_MAGICFIELD; + break; default: warnings.push_back("Unknown item group declaration"); + break; } uint32_t flags; if(itemNode->getU32(flags)) { - t->unpassable = ((flags & FLAG_UNPASSABLE) == FLAG_UNPASSABLE); - t->blockMissiles = ((flags & FLAG_BLOCK_MISSILES) == FLAG_BLOCK_MISSILES); - t->blockPathfinder = ((flags & FLAG_BLOCK_PATHFINDER) == FLAG_BLOCK_PATHFINDER); - t->hasElevation = ((flags & FLAG_HAS_ELEVATION) == FLAG_HAS_ELEVATION); + item->unpassable = ((flags & FLAG_UNPASSABLE) == FLAG_UNPASSABLE); + item->blockMissiles = ((flags & FLAG_BLOCK_MISSILES) == FLAG_BLOCK_MISSILES); + item->blockPathfinder = ((flags & FLAG_BLOCK_PATHFINDER) == FLAG_BLOCK_PATHFINDER); + item->hasElevation = ((flags & FLAG_HAS_ELEVATION) == FLAG_HAS_ELEVATION); //t->useable = ((flags & FLAG_USEABLE) == FLAG_USEABLE); - t->pickupable = ((flags & FLAG_PICKUPABLE) == FLAG_PICKUPABLE); - t->moveable = ((flags & FLAG_MOVEABLE) == FLAG_MOVEABLE); - t->stackable = ((flags & FLAG_STACKABLE) == FLAG_STACKABLE); - t->floorChangeDown = ((flags & FLAG_FLOORCHANGEDOWN) == FLAG_FLOORCHANGEDOWN); - t->floorChangeNorth = ((flags & FLAG_FLOORCHANGENORTH) == FLAG_FLOORCHANGENORTH); - t->floorChangeEast = ((flags & FLAG_FLOORCHANGEEAST) == FLAG_FLOORCHANGEEAST); - t->floorChangeSouth = ((flags & FLAG_FLOORCHANGESOUTH) == FLAG_FLOORCHANGESOUTH); - t->floorChangeWest = ((flags & FLAG_FLOORCHANGEWEST) == FLAG_FLOORCHANGEWEST); - t->floorChange = t->floorChangeDown || t->floorChangeNorth || t->floorChangeEast || t->floorChangeSouth || t->floorChangeWest; + item->pickupable = ((flags & FLAG_PICKUPABLE) == FLAG_PICKUPABLE); + item->moveable = ((flags & FLAG_MOVEABLE) == FLAG_MOVEABLE); + item->stackable = ((flags & FLAG_STACKABLE) == FLAG_STACKABLE); + item->floorChangeDown = ((flags & FLAG_FLOORCHANGEDOWN) == FLAG_FLOORCHANGEDOWN); + item->floorChangeNorth = ((flags & FLAG_FLOORCHANGENORTH) == FLAG_FLOORCHANGENORTH); + item->floorChangeEast = ((flags & FLAG_FLOORCHANGEEAST) == FLAG_FLOORCHANGEEAST); + item->floorChangeSouth = ((flags & FLAG_FLOORCHANGESOUTH) == FLAG_FLOORCHANGESOUTH); + item->floorChangeWest = ((flags & FLAG_FLOORCHANGEWEST) == FLAG_FLOORCHANGEWEST); + item->floorChange = item->floorChangeDown || item->floorChangeNorth || item->floorChangeEast || item->floorChangeSouth || item->floorChangeWest; // Now this is confusing, just accept that the ALWAYSONTOP flag means it's always on bottom, got it?! - t->alwaysOnBottom = ((flags & FLAG_ALWAYSONTOP) == FLAG_ALWAYSONTOP); - t->isHangable = ((flags & FLAG_HANGABLE) == FLAG_HANGABLE); - t->hookEast = ((flags & FLAG_HOOK_EAST) == FLAG_HOOK_EAST); - t->hookSouth = ((flags & FLAG_HOOK_SOUTH) == FLAG_HOOK_SOUTH); - t->allowDistRead = ((flags & FLAG_ALLOWDISTREAD) == FLAG_ALLOWDISTREAD); - t->rotable = ((flags & FLAG_ROTABLE) == FLAG_ROTABLE); - t->canReadText = ((flags & FLAG_READABLE) == FLAG_READABLE); + item->alwaysOnBottom = ((flags & FLAG_ALWAYSONTOP) == FLAG_ALWAYSONTOP); + item->isHangable = ((flags & FLAG_HANGABLE) == FLAG_HANGABLE); + item->hookEast = ((flags & FLAG_HOOK_EAST) == FLAG_HOOK_EAST); + item->hookSouth = ((flags & FLAG_HOOK_SOUTH) == FLAG_HOOK_SOUTH); + item->allowDistRead = ((flags & FLAG_ALLOWDISTREAD) == FLAG_ALLOWDISTREAD); + item->rotable = ((flags & FLAG_ROTABLE) == FLAG_ROTABLE); + item->canReadText = ((flags & FLAG_READABLE) == FLAG_READABLE); } uint8_t attribute; @@ -216,11 +226,11 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra error = "items.otb: Unexpected data length of server id block (Should be 2 bytes)"; return false; } - if(!itemNode->getU16(t->id)) + if(!itemNode->getU16(item->id)) warnings.push_back("Invalid item type property (2)"); - if(max_item_id < t->id) - max_item_id = t->id; + if(maxItemId < item->id) + maxItemId = item->id; break; } @@ -230,10 +240,10 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra return false; } - if(!itemNode->getU16(t->clientID)) + if(!itemNode->getU16(item->clientID)) warnings.push_back("Invalid item type property (2)"); - t->sprite = static_cast(g_gui.gfx.getSprite(t->clientID)); + item->sprite = static_cast(g_gui.gfx.getSprite(item->clientID)); break; } @@ -269,11 +279,11 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra break; } - uint8_t u8 = 0; - if(!itemNode->getU8(u8)) + uint8_t value = 0; + if(!itemNode->getU8(value)) warnings.push_back("Invalid item type property (5)"); - t->alwaysOnTopOrder = u8; + item->alwaysOnTopOrder = value; break; } @@ -290,7 +300,7 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra warnings.push_back("Invalid item type property (6)"); break; } - t->name = (char*)name; + item->name = (char*)name; break; } @@ -308,7 +318,7 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra break; } - t->description = (char*)description; + item->description = (char*)description; break; } @@ -318,7 +328,7 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra break; } - if(!itemNode->getU16(t->volume)) + if(!itemNode->getU16(item->volume)) warnings.push_back("Invalid item type property (8)"); break; } @@ -328,14 +338,14 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra warnings.push_back("items.otb: Unexpected data length of item weight block (Should be 8 bytes)"); break; } - uint8_t w[sizeof(double)]; - if(!itemNode->getRAW(w, sizeof(double))) { + + uint8_t weight[sizeof(double)]; + if(!itemNode->getRAW(weight, sizeof(double))) { warnings.push_back("Invalid item type property (7)"); break; } - double wi = *reinterpret_cast(&w); - t->weight = wi; + item->weight = *reinterpret_cast(&weight); break; } @@ -351,7 +361,7 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra break; } - t->rotateTo = rotate; + item->rotateTo = rotate; break; } @@ -375,7 +385,7 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra } //t->readOnlyId = wb3->readOnlyId; - t->maxTextLen = maxTextLen; + item->maxTextLen = maxTextLen; break; } @@ -388,71 +398,80 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra } } - if(t) { - if(items[t->id]) { - warnings.push_back("items.otb: Duplicate items"); - delete items[t->id]; - } - items.set(t->id, t); + if(items[item->id]) { + warnings.push_back("items.otb: Duplicate items"); + delete items[item->id]; } + items.set(item->id, item); } return true; } bool ItemDatabase::loadFromOtbVer2(BinaryNode* itemNode, wxString& error, wxArrayString& warnings) { - uint8_t u8; - for( ; itemNode != nullptr; itemNode = itemNode->advance()) { - if(!itemNode->getU8(u8)) { + uint8_t group; + for(; itemNode != nullptr; itemNode = itemNode->advance()) { + if(!itemNode->getU8(group)) { // Invalid! warnings.push_back("Invalid item type encountered..."); continue; } - if(ItemGroup_t(u8) == ITEM_GROUP_DEPRECATED) + if(group == ITEM_GROUP_DEPRECATED) continue; - ItemType* t = newd ItemType(); - t->group = ItemGroup_t(u8); + ItemType* item = newd ItemType(); + item->group = static_cast(group); - switch(t->group) { + switch(item->group) { case ITEM_GROUP_NONE: case ITEM_GROUP_GROUND: case ITEM_GROUP_SPLASH: case ITEM_GROUP_FLUID: break; - case ITEM_GROUP_DOOR: t->type = ITEM_TYPE_DOOR; break; - case ITEM_GROUP_CONTAINER: t->type = ITEM_TYPE_CONTAINER; break; - case ITEM_GROUP_RUNE: t->client_chargeable = true; break; - case ITEM_GROUP_TELEPORT: t->type = ITEM_TYPE_TELEPORT; break; - case ITEM_GROUP_MAGICFIELD: t->type = ITEM_TYPE_MAGICFIELD; break; + case ITEM_GROUP_DOOR: + item->type = ITEM_TYPE_DOOR; + break; + case ITEM_GROUP_CONTAINER: + item->type = ITEM_TYPE_CONTAINER; + break; + case ITEM_GROUP_RUNE: + item->client_chargeable = true; + break; + case ITEM_GROUP_TELEPORT: + item->type = ITEM_TYPE_TELEPORT; + break; + case ITEM_GROUP_MAGICFIELD: + item->type = ITEM_TYPE_MAGICFIELD; + break; default: warnings.push_back("Unknown item group declaration"); + break; } uint32_t flags; if(itemNode->getU32(flags)) { - t->unpassable = ((flags & FLAG_UNPASSABLE) == FLAG_UNPASSABLE); - t->blockMissiles = ((flags & FLAG_BLOCK_MISSILES) == FLAG_BLOCK_MISSILES); - t->blockPathfinder = ((flags & FLAG_BLOCK_PATHFINDER) == FLAG_BLOCK_PATHFINDER); - t->hasElevation = ((flags & FLAG_HAS_ELEVATION) == FLAG_HAS_ELEVATION); - t->pickupable = ((flags & FLAG_PICKUPABLE) == FLAG_PICKUPABLE); - t->moveable = ((flags & FLAG_MOVEABLE) == FLAG_MOVEABLE); - t->stackable = ((flags & FLAG_STACKABLE) == FLAG_STACKABLE); - t->floorChangeDown = ((flags & FLAG_FLOORCHANGEDOWN) == FLAG_FLOORCHANGEDOWN); - t->floorChangeNorth = ((flags & FLAG_FLOORCHANGENORTH) == FLAG_FLOORCHANGENORTH); - t->floorChangeEast = ((flags & FLAG_FLOORCHANGEEAST) == FLAG_FLOORCHANGEEAST); - t->floorChangeSouth = ((flags & FLAG_FLOORCHANGESOUTH) == FLAG_FLOORCHANGESOUTH); - t->floorChangeWest = ((flags & FLAG_FLOORCHANGEWEST) == FLAG_FLOORCHANGEWEST); - t->floorChange = t->floorChangeDown || t->floorChangeNorth || t->floorChangeEast || t->floorChangeSouth || t->floorChangeWest; + item->unpassable = ((flags & FLAG_UNPASSABLE) == FLAG_UNPASSABLE); + item->blockMissiles = ((flags & FLAG_BLOCK_MISSILES) == FLAG_BLOCK_MISSILES); + item->blockPathfinder = ((flags & FLAG_BLOCK_PATHFINDER) == FLAG_BLOCK_PATHFINDER); + item->hasElevation = ((flags & FLAG_HAS_ELEVATION) == FLAG_HAS_ELEVATION); + item->pickupable = ((flags & FLAG_PICKUPABLE) == FLAG_PICKUPABLE); + item->moveable = ((flags & FLAG_MOVEABLE) == FLAG_MOVEABLE); + item->stackable = ((flags & FLAG_STACKABLE) == FLAG_STACKABLE); + item->floorChangeDown = ((flags & FLAG_FLOORCHANGEDOWN) == FLAG_FLOORCHANGEDOWN); + item->floorChangeNorth = ((flags & FLAG_FLOORCHANGENORTH) == FLAG_FLOORCHANGENORTH); + item->floorChangeEast = ((flags & FLAG_FLOORCHANGEEAST) == FLAG_FLOORCHANGEEAST); + item->floorChangeSouth = ((flags & FLAG_FLOORCHANGESOUTH) == FLAG_FLOORCHANGESOUTH); + item->floorChangeWest = ((flags & FLAG_FLOORCHANGEWEST) == FLAG_FLOORCHANGEWEST); + item->floorChange = item->floorChangeDown || item->floorChangeNorth || item->floorChangeEast || item->floorChangeSouth || item->floorChangeWest; // Now this is confusing, just accept that the ALWAYSONTOP flag means it's always on bottom, got it?! - t->alwaysOnBottom = ((flags & FLAG_ALWAYSONTOP) == FLAG_ALWAYSONTOP); - t->isHangable = ((flags & FLAG_HANGABLE) == FLAG_HANGABLE); - t->hookEast = ((flags & FLAG_HOOK_EAST) == FLAG_HOOK_EAST); - t->hookSouth = ((flags & FLAG_HOOK_SOUTH) == FLAG_HOOK_SOUTH); - t->allowDistRead = ((flags & FLAG_ALLOWDISTREAD) == FLAG_ALLOWDISTREAD); - t->rotable = ((flags & FLAG_ROTABLE) == FLAG_ROTABLE); - t->canReadText = ((flags & FLAG_READABLE) == FLAG_READABLE); + item->alwaysOnBottom = ((flags & FLAG_ALWAYSONTOP) == FLAG_ALWAYSONTOP); + item->isHangable = ((flags & FLAG_HANGABLE) == FLAG_HANGABLE); + item->hookEast = ((flags & FLAG_HOOK_EAST) == FLAG_HOOK_EAST); + item->hookSouth = ((flags & FLAG_HOOK_SOUTH) == FLAG_HOOK_SOUTH); + item->allowDistRead = ((flags & FLAG_ALLOWDISTREAD) == FLAG_ALLOWDISTREAD); + item->rotable = ((flags & FLAG_ROTABLE) == FLAG_ROTABLE); + item->canReadText = ((flags & FLAG_READABLE) == FLAG_READABLE); } uint8_t attribute; @@ -470,11 +489,11 @@ bool ItemDatabase::loadFromOtbVer2(BinaryNode* itemNode, wxString& error, wxArra return false; } - if(!itemNode->getU16(t->id)) + if(!itemNode->getU16(item->id)) warnings.push_back("Invalid item type property (2)"); - if(max_item_id < t->id) - max_item_id = t->id; + if(maxItemId < item->id) + maxItemId = item->id; break; } @@ -484,10 +503,10 @@ bool ItemDatabase::loadFromOtbVer2(BinaryNode* itemNode, wxString& error, wxArra return false; } - if(!itemNode->getU16(t->clientID)) + if(!itemNode->getU16(item->clientID)) warnings.push_back("Invalid item type property (2)"); - t->sprite = static_cast(g_gui.gfx.getSprite(t->clientID)); + item->sprite = static_cast(g_gui.gfx.getSprite(item->clientID)); break; } @@ -523,11 +542,11 @@ bool ItemDatabase::loadFromOtbVer2(BinaryNode* itemNode, wxString& error, wxArra break; } - uint8_t u8 = 0; - if(!itemNode->getU8(u8)) { + uint8_t value = 0; + if(!itemNode->getU8(value)) { warnings.push_back("Invalid item type property (5)"); } - t->alwaysOnTopOrder = u8; + item->alwaysOnTopOrder = value; break; } @@ -540,69 +559,70 @@ bool ItemDatabase::loadFromOtbVer2(BinaryNode* itemNode, wxString& error, wxArra } } - if(t) { - if(items[t->id]) { - warnings.push_back("items.otb: Duplicate items"); - delete items[t->id]; - } - items.set(t->id, t); + if(items[item->id]) { + warnings.push_back("items.otb: Duplicate items"); + delete items[item->id]; } + items.set(item->id, item); } return true; } -bool ItemDatabase::loadFromOtbVer3(BinaryNode* itemNode, wxString& error, wxArrayString& warnings) { - uint8_t u8; - for( ; itemNode != nullptr; itemNode = itemNode->advance()) { - if(!itemNode->getU8(u8)) { +bool ItemDatabase::loadFromOtbVer3(BinaryNode* itemNode, wxString& error, wxArrayString& warnings) +{ + uint8_t group; + for(; itemNode != nullptr; itemNode = itemNode->advance()) { + if(!itemNode->getU8(group)) { // Invalid! warnings.push_back("Invalid item type encountered..."); continue; } - if(ItemGroup_t(u8) == ITEM_GROUP_DEPRECATED) + if(group == ITEM_GROUP_DEPRECATED) continue; - ItemType* t = newd ItemType(); - t->group = ItemGroup_t(u8); + ItemType* item = newd ItemType(); + item->group = static_cast(group); - switch(t->group) { - case ITEM_GROUP_NONE: + switch(item->group) { + case ITEM_GROUP_NONE: case ITEM_GROUP_GROUND: case ITEM_GROUP_SPLASH: case ITEM_GROUP_FLUID: break; - case ITEM_GROUP_CONTAINER: t->type = ITEM_TYPE_CONTAINER; break; + case ITEM_GROUP_CONTAINER: + item->type = ITEM_TYPE_CONTAINER; break; default: warnings.push_back("Unknown item group declaration"); + break; } uint32_t flags; if(itemNode->getU32(flags)) { - t->unpassable = ((flags & FLAG_UNPASSABLE) == FLAG_UNPASSABLE); - t->blockMissiles = ((flags & FLAG_BLOCK_MISSILES) == FLAG_BLOCK_MISSILES); - t->blockPathfinder = ((flags & FLAG_BLOCK_PATHFINDER) == FLAG_BLOCK_PATHFINDER); - t->hasElevation = ((flags & FLAG_HAS_ELEVATION) == FLAG_HAS_ELEVATION); - t->pickupable = ((flags & FLAG_PICKUPABLE) == FLAG_PICKUPABLE); - t->moveable = ((flags & FLAG_MOVEABLE) == FLAG_MOVEABLE); - t->stackable = ((flags & FLAG_STACKABLE) == FLAG_STACKABLE); - t->floorChangeDown = ((flags & FLAG_FLOORCHANGEDOWN) == FLAG_FLOORCHANGEDOWN); - t->floorChangeNorth = ((flags & FLAG_FLOORCHANGENORTH) == FLAG_FLOORCHANGENORTH); - t->floorChangeEast = ((flags & FLAG_FLOORCHANGEEAST) == FLAG_FLOORCHANGEEAST); - t->floorChangeSouth = ((flags & FLAG_FLOORCHANGESOUTH) == FLAG_FLOORCHANGESOUTH); - t->floorChangeWest = ((flags & FLAG_FLOORCHANGEWEST) == FLAG_FLOORCHANGEWEST); - t->floorChange = t->floorChangeDown || t->floorChangeNorth || t->floorChangeEast || t->floorChangeSouth || t->floorChangeWest; + item->unpassable = ((flags & FLAG_UNPASSABLE) == FLAG_UNPASSABLE); + item->blockMissiles = ((flags & FLAG_BLOCK_MISSILES) == FLAG_BLOCK_MISSILES); + item->blockPathfinder = ((flags & FLAG_BLOCK_PATHFINDER) == FLAG_BLOCK_PATHFINDER); + item->hasElevation = ((flags & FLAG_HAS_ELEVATION) == FLAG_HAS_ELEVATION); + item->pickupable = ((flags & FLAG_PICKUPABLE) == FLAG_PICKUPABLE); + item->moveable = ((flags & FLAG_MOVEABLE) == FLAG_MOVEABLE); + item->stackable = ((flags & FLAG_STACKABLE) == FLAG_STACKABLE); + item->floorChangeDown = ((flags & FLAG_FLOORCHANGEDOWN) == FLAG_FLOORCHANGEDOWN); + item->floorChangeNorth = ((flags & FLAG_FLOORCHANGENORTH) == FLAG_FLOORCHANGENORTH); + item->floorChangeEast = ((flags & FLAG_FLOORCHANGEEAST) == FLAG_FLOORCHANGEEAST); + item->floorChangeSouth = ((flags & FLAG_FLOORCHANGESOUTH) == FLAG_FLOORCHANGESOUTH); + item->floorChangeWest = ((flags & FLAG_FLOORCHANGEWEST) == FLAG_FLOORCHANGEWEST); + item->floorChange = item->floorChangeDown || item->floorChangeNorth || item->floorChangeEast || item->floorChangeSouth || item->floorChangeWest; // Now this is confusing, just accept that the ALWAYSONTOP flag means it's always on bottom, got it?! - t->alwaysOnBottom = ((flags & FLAG_ALWAYSONTOP) == FLAG_ALWAYSONTOP); - t->isHangable = ((flags & FLAG_HANGABLE) == FLAG_HANGABLE); - t->hookEast = ((flags & FLAG_HOOK_EAST) == FLAG_HOOK_EAST); - t->hookSouth = ((flags & FLAG_HOOK_SOUTH) == FLAG_HOOK_SOUTH); - t->allowDistRead = ((flags & FLAG_ALLOWDISTREAD) == FLAG_ALLOWDISTREAD); - t->rotable = ((flags & FLAG_ROTABLE) == FLAG_ROTABLE); - t->canReadText = ((flags & FLAG_READABLE) == FLAG_READABLE); - t->client_chargeable = ((flags & FLAG_CLIENTCHARGES) == FLAG_CLIENTCHARGES); - t->ignoreLook = ((flags & FLAG_IGNORE_LOOK) == FLAG_IGNORE_LOOK); + item->alwaysOnBottom = ((flags & FLAG_ALWAYSONTOP) == FLAG_ALWAYSONTOP); + item->isHangable = ((flags & FLAG_HANGABLE) == FLAG_HANGABLE); + item->hookEast = ((flags & FLAG_HOOK_EAST) == FLAG_HOOK_EAST); + item->hookSouth = ((flags & FLAG_HOOK_SOUTH) == FLAG_HOOK_SOUTH); + item->allowDistRead = ((flags & FLAG_ALLOWDISTREAD) == FLAG_ALLOWDISTREAD); + item->rotable = ((flags & FLAG_ROTABLE) == FLAG_ROTABLE); + item->canReadText = ((flags & FLAG_READABLE) == FLAG_READABLE); + item->client_chargeable = ((flags & FLAG_CLIENTCHARGES) == FLAG_CLIENTCHARGES); + item->ignoreLook = ((flags & FLAG_IGNORE_LOOK) == FLAG_IGNORE_LOOK); } uint8_t attribute; @@ -620,11 +640,11 @@ bool ItemDatabase::loadFromOtbVer3(BinaryNode* itemNode, wxString& error, wxArra return false; } - if(!itemNode->getU16(t->id)) + if(!itemNode->getU16(item->id)) warnings.push_back("Invalid item type property (2)"); - if(max_item_id < t->id) - max_item_id = t->id; + if(maxItemId < item->id) + maxItemId = item->id; break; } @@ -634,10 +654,10 @@ bool ItemDatabase::loadFromOtbVer3(BinaryNode* itemNode, wxString& error, wxArra return false; } - if(!itemNode->getU16(t->clientID)) + if(!itemNode->getU16(item->clientID)) warnings.push_back("Invalid item type property (2)"); - t->sprite = static_cast(g_gui.gfx.getSprite(t->clientID)); + item->sprite = static_cast(g_gui.gfx.getSprite(item->clientID)); break; } @@ -673,10 +693,11 @@ bool ItemDatabase::loadFromOtbVer3(BinaryNode* itemNode, wxString& error, wxArra break; } - if(!itemNode->getU8(u8)) + uint8_t value; + if(!itemNode->getU8(value)) warnings.push_back("Invalid item type property (5)"); - t->alwaysOnTopOrder = u8; + item->alwaysOnTopOrder = value; break; } @@ -689,13 +710,11 @@ bool ItemDatabase::loadFromOtbVer3(BinaryNode* itemNode, wxString& error, wxArra } } - if(t) { - if(items[t->id]) { - warnings.push_back("items.otb: Duplicate items"); - delete items[t->id]; - } - items.set(t->id, t); + if(items[item->id]) { + warnings.push_back("items.otb: Duplicate items"); + delete items[item->id]; } + items.set(item->id, item); } return true; } @@ -763,7 +782,7 @@ bool ItemDatabase::loadFromOtb(const FileName& datafile, wxString& error, wxArra return true; } -bool ItemDatabase::loadItemFromGameXml(pugi::xml_node itemNode, int id) +bool ItemDatabase::loadItemFromGameXml(pugi::xml_node itemNode, uint16_t id) { ClientVersionID clientVersion = g_gui.GetCurrentVersionID(); if(clientVersion < CLIENT_VERSION_980 && id > 20000 && id < 20100) { @@ -774,10 +793,12 @@ bool ItemDatabase::loadItemFromGameXml(pugi::xml_node itemNode, int id) return true; } - ItemType& it = getItemType(id); + if(!isValidID(id)) + return false; - it.name = itemNode.attribute("name").as_string(); - it.editorsuffix = itemNode.attribute("editorsuffix").as_string(); + ItemType& item = *items[id]; + item.name = itemNode.attribute("name").as_string(); + item.editorsuffix = itemNode.attribute("editorsuffix").as_string(); pugi::xml_attribute attribute; for(pugi::xml_node itemAttributesNode = itemNode.first_child(); itemAttributesNode; itemAttributesNode = itemAttributesNode.next_sibling()) { @@ -795,32 +816,32 @@ bool ItemDatabase::loadItemFromGameXml(pugi::xml_node itemNode, int id) std::string typeValue = attribute.as_string(); to_lower_str(key); if(typeValue == "depot") { - it.type = ITEM_TYPE_DEPOT; + item.type = ITEM_TYPE_DEPOT; } else if(typeValue == "mailbox") { - it.type = ITEM_TYPE_MAILBOX; + item.type = ITEM_TYPE_MAILBOX; } else if(typeValue == "trashholder") { - it.type = ITEM_TYPE_TRASHHOLDER; - } else if (typeValue == "container") { - it.type = ITEM_TYPE_CONTAINER; - } else if (typeValue == "door") { - it.type = ITEM_TYPE_DOOR; - } else if (typeValue == "magicfield") { - it.group = ITEM_GROUP_MAGICFIELD; - it.type = ITEM_TYPE_MAGICFIELD; - } else if (typeValue == "teleport") { - it.type = ITEM_TYPE_TELEPORT; - } else if (typeValue == "bed") { - it.type = ITEM_TYPE_BED; - } else if (typeValue == "key") { - it.type = ITEM_TYPE_KEY; + item.type = ITEM_TYPE_TRASHHOLDER; + } else if(typeValue == "container") { + item.type = ITEM_TYPE_CONTAINER; + } else if(typeValue == "door") { + item.type = ITEM_TYPE_DOOR; + } else if(typeValue == "magicfield") { + item.group = ITEM_GROUP_MAGICFIELD; + item.type = ITEM_TYPE_MAGICFIELD; + } else if(typeValue == "teleport") { + item.type = ITEM_TYPE_TELEPORT; + } else if(typeValue == "bed") { + item.type = ITEM_TYPE_BED; + } else if(typeValue == "key") { + item.type = ITEM_TYPE_KEY; } } else if(key == "name") { if((attribute = itemAttributesNode.attribute("value"))) { - it.name = attribute.as_string(); + item.name = attribute.as_string(); } } else if(key == "description") { if((attribute = itemAttributesNode.attribute("value"))) { - it.description = attribute.as_string(); + item.description = attribute.as_string(); } }else if(key == "runespellName") { /*if((attribute = itemAttributesNode.attribute("value"))) { @@ -828,38 +849,38 @@ bool ItemDatabase::loadItemFromGameXml(pugi::xml_node itemNode, int id) }*/ } else if(key == "weight") { if((attribute = itemAttributesNode.attribute("value"))) { - it.weight = attribute.as_int() / 100.f; + item.weight = attribute.as_int() / 100.f; } } else if(key == "armor") { if((attribute = itemAttributesNode.attribute("value"))) { - it.armor = attribute.as_int(); + item.armor = attribute.as_int(); } } else if(key == "defense") { if((attribute = itemAttributesNode.attribute("value"))) { - it.defense = attribute.as_int(); + item.defense = attribute.as_int(); } } else if(key == "rotateto") { if((attribute = itemAttributesNode.attribute("value"))) { - it.rotateTo = attribute.as_ushort(); + item.rotateTo = attribute.as_ushort(); } } else if(key == "containersize") { if((attribute = itemAttributesNode.attribute("value"))) { - it.volume = attribute.as_ushort(); + item.volume = attribute.as_ushort(); } } else if(key == "readable") { if((attribute = itemAttributesNode.attribute("value"))) { - it.canReadText = attribute.as_bool(); + item.canReadText = attribute.as_bool(); } } else if(key == "writeable") { if((attribute = itemAttributesNode.attribute("value"))) { - it.canWriteText = it.canReadText = attribute.as_bool(); + item.canWriteText = item.canReadText = attribute.as_bool(); } } else if(key == "decayto") { - it.decays = true; + item.decays = true; } else if(key == "maxtextlen" || key == "maxtextlength") { if((attribute = itemAttributesNode.attribute("value"))) { - it.maxTextLen = attribute.as_ushort(); - it.canReadText = it.maxTextLen > 0; + item.maxTextLen = attribute.as_ushort(); + item.canReadText = item.maxTextLen > 0; } } else if(key == "writeonceitemid") { /*if((attribute = itemAttributesNode.attribute("value"))) { @@ -867,43 +888,43 @@ bool ItemDatabase::loadItemFromGameXml(pugi::xml_node itemNode, int id) }*/ } else if(key == "allowdistread") { if((attribute = itemAttributesNode.attribute("value"))) { - it.allowDistRead = attribute.as_bool(); + item.allowDistRead = attribute.as_bool(); } } else if(key == "charges") { if((attribute = itemAttributesNode.attribute("value"))) { - it.charges = attribute.as_uint(); - it.extra_chargeable = true; + item.charges = attribute.as_uint(); + item.extra_chargeable = true; } } else if(key == "floorchange") { if ((attribute = itemAttributesNode.attribute("value"))) { std::string value = attribute.as_string(); if(value == "down") { - it.floorChangeDown = true; - it.floorChange = true; - } else if (value == "north") { - it.floorChangeNorth = true; - it.floorChange = true; - } else if (value == "south") { - it.floorChangeSouth = true; - it.floorChange = true; - } else if (value == "west") { - it.floorChangeWest = true; - it.floorChange = true; - } else if (value == "east") { - it.floorChangeEast = true; - it.floorChange = true; + item.floorChangeDown = true; + item.floorChange = true; + } else if(value == "north") { + item.floorChangeNorth = true; + item.floorChange = true; + } else if(value == "south") { + item.floorChangeSouth = true; + item.floorChange = true; + } else if(value == "west") { + item.floorChangeWest = true; + item.floorChange = true; + } else if(value == "east") { + item.floorChangeEast = true; + item.floorChange = true; } else if(value == "northex") - it.floorChange = true; + item.floorChange = true; else if(value == "southex") - it.floorChange = true; + item.floorChange = true; else if(value == "westex") - it.floorChange = true; + item.floorChange = true; else if(value == "eastex") - it.floorChange = true; - else if (value == "southalt") - it.floorChange = true; - else if (value == "eastalt") - it.floorChange = true; + item.floorChange = true; + else if(value == "southalt") + item.floorChange = true; + else if(value == "eastalt") + item.floorChange = true; } } } @@ -960,27 +981,37 @@ bool ItemDatabase::loadMetaItem(pugi::xml_node node) if(id == 0 || items[id]) { return false; } - items.set(id, newd ItemType()); - items[id]->is_metaitem = true; - items[id]->id = id; + + ItemType* item = new ItemType(); + item->is_metaitem = true; + item->id = id; + items.set(id, item); return true; } return false; } -ItemType& ItemDatabase::getItemType(int id) +const ItemType& ItemDatabase::getItemType(uint16_t id) const { - ItemType* it = items[id]; - if(it) - return *it; - else { - static ItemType dummyItemType; // use this for invalid ids - return dummyItemType; - } + if(id == 0 || id > maxItemId) + return dummy; + + const ItemType* type = items[id]; + if(type) return *type; + + return dummy; } -bool ItemDatabase::typeExists(int id) const +ItemType* ItemDatabase::getRawItemType(uint16_t id) { - ItemType* it = items[id]; - return it != nullptr; + if(id == 0 || id > maxItemId) + return nullptr; + return items[id]; +} + +bool ItemDatabase::isValidID(uint16_t id) const +{ + if(id == 0 || id > maxItemId) + return false; + return items[id] != nullptr; } diff --git a/source/items.h b/source/items.h index 92f74306..8eeff166 100644 --- a/source/items.h +++ b/source/items.h @@ -41,8 +41,6 @@ class GameSprite; class GameSprite; class ItemDatabase; -extern ItemDatabase g_items; - typedef uint8_t attribute_t; typedef uint32_t flags_t; typedef uint16_t datasize_t; @@ -237,39 +235,41 @@ struct writeableBlock3 { #pragma pack() -class ItemType { +class ItemType +{ private: ItemType(const ItemType&) {} public: ItemType(); - ~ItemType(); - bool isGroundTile() const { return (group == ITEM_GROUP_GROUND); } - bool isSplash() const { return (group == ITEM_GROUP_SPLASH); } - bool isFluidContainer() const { return (group == ITEM_GROUP_FLUID); } + bool isGroundTile() const noexcept { return group == ITEM_GROUP_GROUND; } + bool isSplash() const noexcept { return group == ITEM_GROUP_SPLASH; } + bool isFluidContainer() const noexcept { return group == ITEM_GROUP_FLUID; } bool isClientCharged() const { return client_chargeable; } bool isExtraCharged() const { return !client_chargeable && extra_chargeable; } - bool isDepot() const { return (type == ITEM_TYPE_DEPOT); } - bool isMailbox() const { return (type == ITEM_TYPE_MAILBOX); } - bool isTrashHolder() const { return (type == ITEM_TYPE_TRASHHOLDER); } - bool isContainer() const { return (type == ITEM_TYPE_CONTAINER); } - bool isDoor() const { return (type == ITEM_TYPE_DOOR); } - bool isMagicField() const { return (type == ITEM_TYPE_MAGICFIELD); } - bool isTeleport() const { return (type == ITEM_TYPE_TELEPORT); } - bool isBed() const { return (type == ITEM_TYPE_BED); } - bool isKey() const { return (type == ITEM_TYPE_KEY); } + bool isDepot() const noexcept { return type == ITEM_TYPE_DEPOT; } + bool isMailbox() const noexcept { return type == ITEM_TYPE_MAILBOX; } + bool isTrashHolder() const noexcept { return type == ITEM_TYPE_TRASHHOLDER; } + bool isContainer() const noexcept { return type == ITEM_TYPE_CONTAINER; } + bool isDoor() const noexcept { return type == ITEM_TYPE_DOOR; } + bool isMagicField() const noexcept { return type == ITEM_TYPE_MAGICFIELD; } + bool isTeleport() const noexcept { return type == ITEM_TYPE_TELEPORT; } + bool isBed() const noexcept { return type == ITEM_TYPE_BED; } + bool isKey() const noexcept { return type == ITEM_TYPE_KEY; } - bool isStackable() const { return stackable; } - bool isMetaItem() const { return is_metaitem; } + bool isStackable() const noexcept { return stackable; } + bool isMetaItem() const noexcept { return is_metaitem; } - bool isFloorChange() const; + bool isFloorChange() const noexcept; - GameSprite* sprite; - uint16_t id; - uint16_t clientID; + float getWeight() const noexcept { return weight; } + uint16_t getVolume() const noexcept { return volume; } + +// editor related +public: Brush* brush; Brush* doodad_brush; RAWBrush* raw_brush; @@ -280,16 +280,31 @@ class ItemType { bool has_raw; bool in_other_tileset; + uint16_t ground_equivalent; + uint32_t border_group; + bool has_equivalent; // True if any item has this as ground_equivalent + bool wall_hate_me; // (For wallbrushes, regard this as not part of the wall) + + bool isBorder; + bool isOptionalBorder; + bool isWall; + bool isBrushDoor; + bool isOpen; + bool isTable; + bool isCarpet; + +public: + GameSprite* sprite; + + uint16_t id; + uint16_t clientID; + ItemGroup_t group; ItemTypes_t type; uint16_t volume; uint16_t maxTextLen; //uint16_t writeOnceItemId; - uint16_t ground_equivalent; - uint32_t border_group; - bool has_equivalent; // True if any item has this as ground_equivalent - bool wall_hate_me; // (For wallbrushes, regard this as not part of the wall) std::string name; std::string editorsuffix; @@ -319,13 +334,6 @@ class ItemType { bool alwaysOnBottom; bool pickupable; bool rotable; - bool isBorder; - bool isOptionalBorder; - bool isWall; - bool isBrushDoor; - bool isOpen; - bool isTable; - bool isCarpet; bool floorChangeDown; bool floorChangeNorth; @@ -353,22 +361,21 @@ class ItemDatabase void clear(); - ItemType& operator[](size_t id) {return getItemType(id);} - uint16_t getMaxID() const {return max_item_id;} + uint16_t getMinID() const noexcept { return 100; } + uint16_t getMaxID() const noexcept { return maxItemId; } + const ItemType& getItemType(uint16_t id) const; + ItemType* getRawItemType(uint16_t id); - bool typeExists(int id) const; - ItemType& getItemType(int id); - ItemType& getItemIdByClientID(int spriteId); + bool isValidID(uint16_t id) const; bool loadFromOtb(const FileName& datafile, wxString& error, wxArrayString& warnings); bool loadFromGameXml(const FileName& datafile, wxString& error, wxArrayString& warnings); - bool loadItemFromGameXml(pugi::xml_node itemNode, int id); + bool loadItemFromGameXml(pugi::xml_node itemNode, uint16_t id); bool loadMetaItem(pugi::xml_node node); //typedef std::map ItemMap; typedef contigous_vector ItemMap; typedef std::map ItemNameMap; - ItemMap items; // Version information uint32_t MajorVersion; @@ -381,18 +388,24 @@ class ItemDatabase bool loadFromOtbVer3(BinaryNode* itemNode, wxString& error, wxArrayString& warnings); protected: + ItemMap items; + // Count of GameSprite types uint16_t item_count; uint16_t effect_count; uint16_t monster_count; uint16_t distance_count; - uint16_t minclientID; - uint16_t maxclientID; - uint16_t max_item_id; + uint16_t minClientID; + uint16_t maxClientID; + uint16_t maxItemId; + + ItemType dummy; friend class GameSprite; friend class Item; }; +extern ItemDatabase g_items; + #endif diff --git a/source/main_menubar.cpp b/source/main_menubar.cpp index 18148e39..746d0a90 100644 --- a/source/main_menubar.cpp +++ b/source/main_menubar.cpp @@ -32,6 +32,7 @@ #include +#include "items.h" #include "editor.h" #include "materials.h" #include "live_client.h" @@ -1371,7 +1372,7 @@ namespace OnMapRemoveUnreachable if(done % 0x1000 == 0) g_gui.SetLoadDone((unsigned int)(100 * done / total)); - Position pos = tile->getPosition(); + const Position& pos = tile->getPosition(); int sx = std::max(pos.x - 10, 0); int ex = std::min(pos.x + 10, 65535); int sy = std::max(pos.y - 8, 0); @@ -1713,7 +1714,7 @@ void MainMenuBar::OnMapStatistics(wxCommandEvent& WXUNUSED(event)) item_count += 1; \ if(!(_item)->isGroundTile() && !(_item)->isBorder()) { \ is_detailed = true; \ - ItemType& it = g_items[(_item)->getID()]; \ + const ItemType& it = g_items.getItemType((_item)->getID()); \ if(it.moveable) { \ loose_item_count += 1; \ } \ @@ -1733,13 +1734,11 @@ void MainMenuBar::OnMapStatistics(wxCommandEvent& WXUNUSED(event)) } \ } \ } - if(tile->ground) { ANALYZE_ITEM(tile->ground); } - for(ItemVector::const_iterator item_iter = tile->items.begin(); item_iter != tile->items.end(); ++item_iter) { - Item* item = *item_iter; + for(Item* item : tile->items) { ANALYZE_ITEM(item); } #undef ANALYZE_ITEM diff --git a/source/map.cpp b/source/map.cpp index 82fc01e2..1aaa6461 100644 --- a/source/map.cpp +++ b/source/map.cpp @@ -285,7 +285,7 @@ void Map::cleanInvalidTiles(bool showdialog) continue; for(ItemVector::iterator item_iter = tile->items.begin(); item_iter != tile->items.end();) { - if(g_items.typeExists((*item_iter)->getID())) + if(g_items.isValidID((*item_iter)->getID())) ++item_iter; else { delete *item_iter; diff --git a/source/map.h b/source/map.h index f30d10f6..5346ab11 100644 --- a/source/map.h +++ b/source/map.h @@ -83,9 +83,9 @@ class Map : public BaseMap // Returns true if the map has been saved // ie. it knows which file it should be saved to bool hasFile() const; - std::string getFilename() const {return filename;} - std::string getName() const {return name;} - void setName(const std::string& n) {name = n;} + std::string getFilename() const { return filename; } + std::string getName() const { return name; } + void setName(const std::string& n) { name = n; } // Get map data int getWidth() const {return width;} diff --git a/source/map_display.cpp b/source/map_display.cpp index 9b3d40a1..2fdcbc33 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -178,7 +178,7 @@ void MapCanvas::SetZoom(double value) GetScreenCenter(¢er_x, ¢er_y); zoom = value; - static_cast(GetParent())->SetScreenCenterPosition(Position(center_x, center_y, floor)); + GetMapWindow()->SetScreenCenterPosition(Position(center_x, center_y, floor)); UpdatePositionStatus(); UpdateZoomStatus(); @@ -188,8 +188,9 @@ void MapCanvas::SetZoom(double value) void MapCanvas::GetViewBox(int* view_scroll_x, int* view_scroll_y, int* screensize_x, int* screensize_y) const { - static_cast(GetParent())->GetViewSize(screensize_x, screensize_y); - static_cast(GetParent())->GetViewStart(view_scroll_x, view_scroll_y); + MapWindow* window = GetMapWindow(); + window->GetViewSize(screensize_x, screensize_y); + window->GetViewStart(view_scroll_x, view_scroll_y); } void MapCanvas::OnPaint(wxPaintEvent& event) @@ -279,7 +280,7 @@ void MapCanvas::TakeScreenshot(wxFileName path, wxString format) } else { // We got the shit int screensize_x, screensize_y; - static_cast(GetParent())->GetViewSize(&screensize_x, &screensize_y); + GetMapWindow()->GetViewSize(&screensize_x, &screensize_y); wxImage screenshot(screensize_x, screensize_y, screenshot_buffer); time_t t = time(nullptr); @@ -338,7 +339,7 @@ void MapCanvas::TakeScreenshot(wxFileName path, wxString format) void MapCanvas::ScreenToMap(int screen_x, int screen_y, int* map_x, int* map_y) { int start_x, start_y; - static_cast(GetParent())->GetViewStart(&start_x, &start_y); + GetMapWindow()->GetViewStart(&start_x, &start_y); screen_x *= GetContentScaleFactor(); screen_y *= GetContentScaleFactor(); @@ -364,10 +365,18 @@ void MapCanvas::ScreenToMap(int screen_x, int screen_y, int* map_x, int* map_y) }*/ } +MapWindow* MapCanvas::GetMapWindow() const +{ + wxWindow* window = GetParent(); + if(window) + return static_cast(window); + return nullptr; +} + void MapCanvas::GetScreenCenter(int* map_x, int* map_y) { int width, height; - static_cast(GetParent())->GetViewSize(&width, &height); + GetMapWindow()->GetViewSize(&width, &height); return ScreenToMap(width/2, height/2, map_x, map_y); } @@ -437,7 +446,7 @@ void MapCanvas::UpdateZoomStatus() void MapCanvas::OnMouseMove(wxMouseEvent& event) { if(screendragging) { - static_cast(GetParent())->ScrollRelative(int(g_settings.getFloat(Config::SCROLL_SPEED) * zoom*(event.GetX() - cursor_x)), int(g_settings.getFloat(Config::SCROLL_SPEED) * zoom*(event.GetY() - cursor_y))); + GetMapWindow()->ScrollRelative(int(g_settings.getFloat(Config::SCROLL_SPEED) * zoom*(event.GetX() - cursor_x)), int(g_settings.getFloat(Config::SCROLL_SPEED) * zoom*(event.GetY() - cursor_y))); Refresh(); } @@ -1002,7 +1011,7 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) last_click_y = int(event.GetY()*zoom); int start_x, start_y; - static_cast(GetParent())->GetViewStart(&start_x, &start_y); + GetMapWindow()->GetViewStart(&start_x, &start_y); last_click_abs_x = last_click_x + start_x; last_click_abs_y = last_click_y + start_y; @@ -1341,14 +1350,15 @@ void MapCanvas::OnMouseCameraClick(wxMouseEvent& event) last_mmb_click_x = event.GetX(); last_mmb_click_y = event.GetY(); + if(event.ControlDown()) { int screensize_x, screensize_y; - static_cast(GetParent())->GetViewSize(&screensize_x, &screensize_y); - - static_cast(GetParent())->ScrollRelative( + MapWindow* window = GetMapWindow(); + window->GetViewSize(&screensize_x, &screensize_y); + window->ScrollRelative( int(-screensize_x * (1.0 - zoom) * (std::max(cursor_x, 1) / double(screensize_x))), int(-screensize_y * (1.0 - zoom) * (std::max(cursor_y, 1) / double(screensize_y))) - ); + ); zoom = 1.0; Refresh(); } else { @@ -1366,11 +1376,12 @@ void MapCanvas::OnMouseCameraRelease(wxMouseEvent& event) } else if(last_mmb_click_x > event.GetX() - 3 && last_mmb_click_x < event.GetX() + 3 && last_mmb_click_y > event.GetY() - 3 && last_mmb_click_y < event.GetY() + 3) { int screensize_x, screensize_y; - static_cast(GetParent())->GetViewSize(&screensize_x, &screensize_y); - static_cast(GetParent())->ScrollRelative( + MapWindow* window = GetMapWindow(); + window->GetViewSize(&screensize_x, &screensize_y); + window->ScrollRelative( int(zoom * (2*cursor_x - screensize_x)), int(zoom * (2*cursor_y - screensize_y)) - ); + ); Refresh(); } } @@ -1432,7 +1443,7 @@ void MapCanvas::OnMousePropertiesClick(wxMouseEvent& event) last_click_y = int(event.GetY()*zoom); int start_x, start_y; - static_cast(GetParent())->GetViewStart(&start_x, &start_y); + GetMapWindow()->GetViewStart(&start_x, &start_y); last_click_abs_x = last_click_x + start_x; last_click_abs_y = last_click_y + start_y; @@ -1621,13 +1632,14 @@ void MapCanvas::OnWheel(wxMouseEvent& event) UpdateZoomStatus(); int screensize_x, screensize_y; - static_cast(GetParent())->GetViewSize(&screensize_x, &screensize_y); + MapWindow* window = GetMapWindow(); + window->GetViewSize(&screensize_x, &screensize_y); // This took a day to figure out! int scroll_x = int(screensize_x * diff * (std::max(cursor_x, 1) / double(screensize_x))) * GetContentScaleFactor(); int scroll_y = int(screensize_y * diff * (std::max(cursor_y, 1) / double(screensize_y))) * GetContentScaleFactor(); - static_cast(GetParent())->ScrollRelative(-scroll_x, -scroll_y); + window->ScrollRelative(-scroll_x, -scroll_y); } Refresh(); @@ -1654,6 +1666,8 @@ void MapCanvas::OnGainMouse(wxMouseEvent& event) void MapCanvas::OnKeyDown(wxKeyEvent& event) { + MapWindow* window = GetMapWindow(); + //char keycode = event.GetKeyCode(); // std::cout << "Keycode " << keycode << std::endl; switch(event.GetKeyCode()) { @@ -1678,13 +1692,13 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) } int screensize_x, screensize_y; - static_cast(GetParent())->GetViewSize(&screensize_x, &screensize_y); + window->GetViewSize(&screensize_x, &screensize_y); // This took a day to figure out! int scroll_x = int(screensize_x * diff * (std::max(cursor_x, 1) / double(screensize_x))); int scroll_y = int(screensize_y * diff * (std::max(cursor_y, 1) / double(screensize_y))); - static_cast(GetParent())->ScrollRelative(-scroll_x, -scroll_y); + window->ScrollRelative(-scroll_x, -scroll_y); UpdatePositionStatus(); UpdateZoomStatus(); @@ -1701,13 +1715,12 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) } int screensize_x, screensize_y; - static_cast(GetParent())->GetViewSize(&screensize_x, &screensize_y); + window->GetViewSize(&screensize_x, &screensize_y); // This took a day to figure out! int scroll_x = int(screensize_x * diff * (std::max(cursor_x, 1) / double(screensize_x))); int scroll_y = int(screensize_y * diff * (std::max(cursor_y, 1) / double(screensize_y))); - - static_cast(GetParent())->ScrollRelative(-scroll_x, -scroll_y); + window->ScrollRelative(-scroll_x, -scroll_y); UpdatePositionStatus(); UpdateZoomStatus(); @@ -1730,7 +1743,7 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) case WXK_NUMPAD_UP: case WXK_UP: { int start_x, start_y; - static_cast(GetParent())->GetViewStart(&start_x, &start_y); + window->GetViewStart(&start_x, &start_y); int tiles = 3; if(event.ControlDown()) @@ -1738,7 +1751,7 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) else if(zoom == 1.0) tiles = 1; - static_cast(GetParent())->Scroll(start_x, int(start_y - TILE_SIZE * tiles * zoom)); + window->Scroll(start_x, int(start_y - TILE_SIZE * tiles * zoom)); UpdatePositionStatus(); Refresh(); break; @@ -1746,7 +1759,7 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) case WXK_NUMPAD_DOWN: case WXK_DOWN: { int start_x, start_y; - static_cast(GetParent())->GetViewStart(&start_x, &start_y); + window->GetViewStart(&start_x, &start_y); int tiles = 3; if(event.ControlDown()) @@ -1754,7 +1767,7 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) else if(zoom == 1.0) tiles = 1; - static_cast(GetParent())->Scroll(start_x, int(start_y + TILE_SIZE * tiles * zoom)); + window->Scroll(start_x, int(start_y + TILE_SIZE * tiles * zoom)); UpdatePositionStatus(); Refresh(); break; @@ -1762,7 +1775,7 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) case WXK_NUMPAD_LEFT: case WXK_LEFT: { int start_x, start_y; - static_cast(GetParent())->GetViewStart(&start_x, &start_y); + window->GetViewStart(&start_x, &start_y); int tiles = 3; if(event.ControlDown()) @@ -1770,7 +1783,7 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) else if(zoom == 1.0) tiles = 1; - static_cast(GetParent())->Scroll(int(start_x - TILE_SIZE * tiles * zoom), start_y); + window->Scroll(int(start_x - TILE_SIZE * tiles * zoom), start_y); UpdatePositionStatus(); Refresh(); break; @@ -1778,7 +1791,7 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) case WXK_NUMPAD_RIGHT: case WXK_RIGHT: { int start_x, start_y; - static_cast(GetParent())->GetViewStart(&start_x, &start_y); + window->GetViewStart(&start_x, &start_y); int tiles = 3; if(event.ControlDown()) @@ -1786,7 +1799,7 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) else if(zoom == 1.0) tiles = 1; - static_cast(GetParent())->Scroll(int(start_x + TILE_SIZE * tiles * zoom), start_y); + window->Scroll(int(start_x + TILE_SIZE * tiles * zoom), start_y); UpdatePositionStatus(); Refresh(); break; @@ -1848,11 +1861,11 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) Hotkey hk; if(g_gui.IsSelectionMode()) { int view_start_x, view_start_y; - static_cast(GetParent())->GetViewStart(&view_start_x, &view_start_y); + window->GetViewStart(&view_start_x, &view_start_y); int view_start_map_x = view_start_x / TILE_SIZE, view_start_map_y = view_start_y / TILE_SIZE; int view_screensize_x, view_screensize_y; - static_cast(GetParent())->GetViewSize(&view_screensize_x, &view_screensize_y); + window->GetViewSize(&view_screensize_x, &view_screensize_y); int map_x = int(view_start_map_x + (view_screensize_x * zoom) / TILE_SIZE / 2); int map_y = int(view_start_map_y + (view_screensize_y * zoom) / TILE_SIZE / 2); @@ -1875,7 +1888,7 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) int map_y = hk.GetPosition().y; int map_z = hk.GetPosition().z; - static_cast(GetParent())->Scroll(TILE_SIZE * map_x, TILE_SIZE * map_y, true); + window->Scroll(TILE_SIZE * map_x, TILE_SIZE * map_y, true); floor = map_z; g_gui.SetStatusText("Used hotkey " + i2ws(index)); diff --git a/source/map_display.h b/source/map_display.h index 28bddd94..1d59f9d3 100644 --- a/source/map_display.h +++ b/source/map_display.h @@ -31,7 +31,8 @@ class MapPopupMenu; class AnimationTimer; class MapDrawer; -class MapCanvas : public wxGLCanvas { +class MapCanvas : public wxGLCanvas +{ public: MapCanvas(MapWindow* parent, Editor& editor, int* attriblist); virtual ~MapCanvas(); @@ -98,7 +99,7 @@ class MapCanvas : public wxGLCanvas { void Refresh(); void ScreenToMap(int screen_x, int screen_y, int* map_x, int* map_y); - void MouseToMap(int* map_x, int* map_y) {ScreenToMap(cursor_x, cursor_y, map_x, map_y);} + void MouseToMap(int* map_x, int* map_y) { ScreenToMap(cursor_x, cursor_y, map_x, map_y); } void GetScreenCenter(int* map_x, int* map_y); void StartPasting(); @@ -115,6 +116,7 @@ class MapCanvas : public wxGLCanvas { void SetZoom(double value); void GetViewBox(int* view_scroll_x, int* view_scroll_y, int* screensize_x, int* screensize_y) const; + MapWindow* GetMapWindow() const; Position GetCursorPosition() const; void ShowPositionIndicator(const Position& position); diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index b8df8025..c2c8f102 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -1463,7 +1463,7 @@ void MapDrawer::DrawTile(TileLocation* location) const Position& position = location->getPosition(); if(options.show_tooltips && location->getWaypointCount() > 0) { - Waypoint* waypoint = canvas->editor.map.waypoints.getWaypoint(location); + Waypoint* waypoint = canvas->editor.map.waypoints.getWaypoint(position); if(waypoint) WriteTooltip(waypoint, tooltip); } diff --git a/source/materials.cpp b/source/materials.cpp index e2879356..d153fc2f 100644 --- a/source/materials.cpp +++ b/source/materials.cpp @@ -251,28 +251,28 @@ void Materials::createOtherTileset() // There should really be an iterator to do this for(int32_t id = 0; id <= g_items.getMaxID(); ++id) { - ItemType& it = g_items[id]; - if(it.id == 0) { + ItemType* type = g_items.getRawItemType(id); + if(!type) { continue; } - if(!it.isMetaItem()) { + if(!type->isMetaItem()) { Brush* brush; - if(it.in_other_tileset) { - others->getCategory(TILESET_RAW)->brushlist.push_back(it.raw_brush); + if(type->in_other_tileset) { + others->getCategory(TILESET_RAW)->brushlist.push_back(type->raw_brush); continue; - } else if(it.raw_brush == nullptr) { - brush = it.raw_brush = newd RAWBrush(it.id); - it.has_raw = true; - g_brushes.addBrush(it.raw_brush); - } else if(!it.has_raw) { - brush = it.raw_brush; + } else if(!type->raw_brush) { + brush = type->raw_brush = newd RAWBrush(type->id); + type->has_raw = true; + g_brushes.addBrush(type->raw_brush); + } else if(!type->has_raw) { + brush = type->raw_brush; } else continue; brush->flagAsVisible(); - others->getCategory(TILESET_RAW)->brushlist.push_back(it.raw_brush); - it.in_other_tileset = true; + others->getCategory(TILESET_RAW)->brushlist.push_back(type->raw_brush); + type->in_other_tileset = true; } } @@ -343,12 +343,11 @@ bool Materials::unserializeTileset(pugi::xml_node node, wxArrayString& warnings) bool Materials::isInTileset(Item* item, std::string tilesetName) const { - const ItemType& it = g_items[item->getID()]; - - return it.id != 0 && ( - isInTileset(it.brush, tilesetName) || - isInTileset(it.doodad_brush, tilesetName) || - isInTileset(it.raw_brush, tilesetName)); + const ItemType& type = g_items.getItemType(item->getID()); + return type.id != 0 && ( + isInTileset(type.brush, tilesetName) || + isInTileset(type.doodad_brush, tilesetName) || + isInTileset(type.raw_brush, tilesetName)); } bool Materials::isInTileset(Brush* brush, std::string tilesetName) const diff --git a/source/raw_brush.cpp b/source/raw_brush.cpp index 2971c918..932efadf 100644 --- a/source/raw_brush.cpp +++ b/source/raw_brush.cpp @@ -28,11 +28,7 @@ RAWBrush::RAWBrush(uint16_t itemid) : Brush() { - ItemType& it = g_items[itemid]; - if(it.id == 0) - itemtype = nullptr; - else - itemtype = ⁢ + itemtype = g_items.getRawItemType(itemid); } RAWBrush::~RAWBrush() diff --git a/source/selection.cpp b/source/selection.cpp index e395c7b2..6bf639ea 100644 --- a/source/selection.cpp +++ b/source/selection.cpp @@ -36,6 +36,8 @@ Selection::Selection(Editor& editor) : Selection::~Selection() { + tiles.clear(); + delete subsession; delete session; } @@ -43,8 +45,9 @@ Selection::~Selection() Position Selection::minPosition() const { Position minPos(0x10000, 0x10000, 0x10); - for(TileSet::const_iterator tile = tiles.begin(); tile != tiles.end(); ++tile) { - Position pos((*tile)->getPosition()); + for(const Tile* tile : tiles) { + if(!tile) continue; + const Position& pos = tile->getPosition(); if(minPos.x > pos.x) minPos.x = pos.x; if(minPos.y > pos.y) @@ -57,9 +60,10 @@ Position Selection::minPosition() const Position Selection::maxPosition() const { - Position maxPos(0, 0, 0); - for(TileSet::const_iterator tile = tiles.begin(); tile != tiles.end(); ++tile) { - Position pos((*tile)->getPosition()); + Position maxPos; + for(const Tile* tile : tiles) { + if(!tile) continue; + const Position& pos = tile->getPosition(); if(maxPos.x < pos.x) maxPos.x = pos.x; if(maxPos.y < pos.y) @@ -171,10 +175,10 @@ void Selection::remove(Tile* tile, Item* item) ASSERT(tile); ASSERT(item); - bool tmp = item->isSelected(); + bool selected = item->isSelected(); item->deselect(); Tile* new_tile = tile->deepCopy(editor.map); - if(tmp) item->select(); + if(selected) item->select(); if(item->isBorder() && g_settings.getInteger(Config::BORDER_IS_GROUND)) new_tile->deselectGround(); subsession->addChange(newd Change(new_tile)); @@ -186,10 +190,10 @@ void Selection::remove(Tile* tile, SpawnMonster* spawnMonster) ASSERT(tile); ASSERT(spawnMonster); - bool tmp = spawnMonster->isSelected(); + bool selected = spawnMonster->isSelected(); spawnMonster->deselect(); Tile* new_tile = tile->deepCopy(editor.map); - if(tmp) spawnMonster->select(); + if(selected) spawnMonster->select(); subsession->addChange(newd Change(new_tile)); } @@ -200,10 +204,10 @@ void Selection::remove(Tile* tile, SpawnNpc* spawnNpc) ASSERT(tile); ASSERT(spawnNpc); - bool tmp = spawnNpc->isSelected(); + bool selected = spawnNpc->isSelected(); spawnNpc->deselect(); Tile* new_tile = tile->deepCopy(editor.map); - if(tmp) spawnNpc->select(); + if(selected) spawnNpc->select(); subsession->addChange(newd Change(new_tile)); } @@ -214,10 +218,10 @@ void Selection::remove(Tile* tile, Monster* monster) ASSERT(tile); ASSERT(monster); - bool tmp = monster->isSelected(); + bool selected = monster->isSelected(); monster->deselect(); Tile* new_tile = tile->deepCopy(editor.map); - if(tmp) monster->select(); + if(selected) monster->select(); subsession->addChange(newd Change(new_tile)); } @@ -228,10 +232,10 @@ void Selection::remove(Tile* tile, Npc* npc) ASSERT(tile); ASSERT(npc); - bool tmp = npc->isSelected(); + bool selected = npc->isSelected(); npc->deselect(); Tile* new_tile = tile->deepCopy(editor.map); - if(tmp) npc->select(); + if(selected) npc->select(); subsession->addChange(newd Change(new_tile)); } @@ -293,15 +297,15 @@ void Selection::commit() if(session) { ASSERT(subsession); // We need to step out of the session before we do the action, else peril awaits us! - BatchAction* tmp = session; + BatchAction* batch = session; session = nullptr; // Do the action - tmp->addAndCommitAction(subsession); + batch->addAndCommitAction(subsession); // Create a newd action for subsequent selects subsession = editor.actionQueue->createAction(ACTION_SELECT); - session = tmp; + session = batch; } } @@ -315,11 +319,11 @@ void Selection::finish(SessionFlags flags) ASSERT(session); ASSERT(subsession); // We need to exit the session before we do the action, else peril awaits us! - BatchAction* tmp = session; + BatchAction* batch = session; session = nullptr; - tmp->addAndCommitAction(subsession); - editor.addBatch(tmp, 2); + batch->addAndCommitAction(subsession); + editor.addBatch(batch, 2); session = nullptr; subsession = nullptr; diff --git a/source/table_brush.cpp b/source/table_brush.cpp index dd7495db..7ce2d65b 100644 --- a/source/table_brush.cpp +++ b/source/table_brush.cpp @@ -41,7 +41,7 @@ TableBrush::~TableBrush() bool TableBrush::load(pugi::xml_node node, wxArrayString& warnings) { if(const pugi::xml_attribute attribute = node.attribute("server_lookid")) - look_id = g_items[attribute.as_ushort()].clientID; + look_id = g_items.getItemType(attribute.as_ushort()).clientID; if(look_id == 0) { look_id = node.attribute("lookid").as_ushort(); @@ -89,17 +89,17 @@ bool TableBrush::load(pugi::xml_node node, wxArrayString& warnings) break; } - ItemType& it = g_items[id]; - if(it.id == 0) { + ItemType* type = g_items.getRawItemType(id); + if(!type) { warnings.push_back("There is no itemtype with id " + std::to_string(id)); return false; - } else if(it.brush && it.brush != this) { + } else if(type->brush && type->brush != this) { warnings.push_back("Itemtype id " + std::to_string(id) + " already has a brush"); return false; } - it.isTable = true; - it.brush = this; + type->isTable = true; + type->brush = this; TableType tt; tt.item_id = id; diff --git a/source/tileset.cpp b/source/tileset.cpp index 30c9e66b..2338cd5f 100644 --- a/source/tileset.cpp +++ b/source/tileset.cpp @@ -208,9 +208,9 @@ void TilesetCategory::loadBrush(pugi::xml_node node, wxArrayString& warnings) std::string brushName = node.attribute("after").as_string(); if((attribute = node.attribute("afteritem"))) { - ItemType& it = g_items[attribute.as_ushort()]; - if(it.id != 0) { - brushName = it.raw_brush ? it.raw_brush->getName() : std::string(); + const ItemType& type = g_items.getItemType(attribute.as_ushort()); + if(type.id != 0) { + brushName = type.raw_brush ? type.raw_brush->getName() : std::string(); } } @@ -250,24 +250,24 @@ void TilesetCategory::loadBrush(pugi::xml_node node, wxArrayString& warnings) std::vector tempBrushVector; for(uint16_t id = fromId; id <= toId; ++id) { - ItemType& it = g_items[id]; - if(it.id == 0) { + ItemType* type = g_items.getRawItemType(id); + if(!type) { warnings.push_back(wxString::Format("Brush: %s, From: %d, To: %d", wxstr(brushName), fromId, toId)); warnings.push_back("Unknown item id #" + std::to_string(id) + "."); continue; } RAWBrush* brush; - if(it.raw_brush) { - brush = it.raw_brush; + if(type->raw_brush) { + brush = type->raw_brush; } else { - brush = it.raw_brush = newd RAWBrush(it.id); - it.has_raw = true; + brush = type->raw_brush = newd RAWBrush(type->id); + type->has_raw = true; tileset.brushes.addBrush(brush); // This will take care of cleaning up afterwards } - if(it.doodad_brush == nullptr && !isTrivial()) { - it.doodad_brush = brush; + if(type->doodad_brush == nullptr && !isTrivial()) { + type->doodad_brush = brush; } brush->flagAsVisible(); diff --git a/source/wall_brush.cpp b/source/wall_brush.cpp index 2f9770d5..71779011 100644 --- a/source/wall_brush.cpp +++ b/source/wall_brush.cpp @@ -43,7 +43,7 @@ bool WallBrush::load(pugi::xml_node node, wxArrayString& warnings) } if((attribute = node.attribute("server_lookid"))) { - look_id = g_items[attribute.as_ushort()].clientID; + look_id = g_items.getItemType(attribute.as_ushort()).clientID; } for(pugi::xml_node childNode = node.first_child(); childNode; childNode = childNode.next_sibling()) { @@ -106,18 +106,18 @@ bool WallBrush::load(pugi::xml_node node, wxArrayString& warnings) break; } - ItemType& it = g_items[id]; - if(it.id == 0) { + ItemType* type = g_items.getRawItemType(id); + if(!type) { warnings.push_back("There is no itemtype with id " + std::to_string(id)); return false; - } else if(it.brush && it.brush != this) { + } else if(type->brush && type->brush != this) { warnings.push_back("Itemtype id " + std::to_string(id) + " already has a brush"); return false; } - it.isWall = true; - it.brush = this; - it.border_alignment = ::BorderType(alignment); + type->isWall = true; + type->brush = this; + type->border_alignment = ::BorderType(alignment); WallType wt; wt.id = id; @@ -133,8 +133,8 @@ bool WallBrush::load(pugi::xml_node node, wxArrayString& warnings) break; } - const std::string& type = subChildNode.attribute("type").as_string(); - if(type.empty()) { + std::string nodetype = subChildNode.attribute("type").as_string(); + if(nodetype.empty()) { warnings.push_back("Could not read type tag of door node\n"); continue; } @@ -145,54 +145,54 @@ bool WallBrush::load(pugi::xml_node node, wxArrayString& warnings) isOpen = openAttribute.as_bool(); } else { isOpen = true; - if(type != "window" && type != "any window" && type != "hatch window") { + if(nodetype != "window" && nodetype != "any window" && nodetype != "hatch window") { warnings.push_back("Could not read open tag of door node\n"); break; } } - ItemType& it = g_items[id]; - if(it.id == 0) { + ItemType* type = g_items.getRawItemType(id); + if(!type) { warnings.push_back("There is no itemtype with id " + std::to_string(id)); return false; - } else if(it.brush && it.brush != this) { + } else if(type->brush && type->brush != this) { warnings.push_back("Itemtype id " + std::to_string(id) + " already has a brush"); return false; } - it.isWall = true; - it.brush = this; - it.isBrushDoor = true; - it.wall_hate_me = subChildNode.attribute("hate").as_bool(); - it.isOpen = isOpen; - it.border_alignment = ::BorderType(alignment); + type->isWall = true; + type->brush = this; + type->isBrushDoor = true; + type->wall_hate_me = subChildNode.attribute("hate").as_bool(); + type->isOpen = isOpen; + type->border_alignment = ::BorderType(alignment); DoorType dt; bool all_windows = false; bool all_doors = false; - if(type == "normal") { + if(nodetype == "normal") { dt.type = WALL_DOOR_NORMAL; - } else if(type == "locked") { + } else if(nodetype == "locked") { dt.type = WALL_DOOR_LOCKED; - } else if(type == "quest") { + } else if(nodetype == "quest") { dt.type = WALL_DOOR_QUEST; - } else if(type == "magic") { + } else if(nodetype == "magic") { dt.type = WALL_DOOR_MAGIC; - } else if(type == "archway") { + } else if(nodetype == "archway") { dt.type = WALL_ARCHWAY; - } else if(type == "window") { + } else if(nodetype == "window") { dt.type = WALL_WINDOW; - } else if(type == "hatch_window" || type == "hatch window") { + } else if(nodetype == "hatch_window" || nodetype == "hatch window") { dt.type = WALL_HATCH_WINDOW; - } else if(type == "any door") { + } else if(nodetype == "any door") { all_doors = true; - } else if(type == "any window") { + } else if(nodetype == "any window") { all_windows = true; - } else if(type == "any") { + } else if(nodetype == "any") { all_windows = true; all_doors = true; } else { - warnings.push_back("Unknown door type '" + wxstr(type) + "'\n"); + warnings.push_back("Unknown door type '" + wxstr(nodetype) + "'\n"); break; } @@ -350,9 +350,9 @@ bool hasMatchingWallBrushAtTile(BaseMap* map, WallBrush* wall_brush, uint32_t x, if(item->isWall()) { WallBrush* wb = item->getWallBrush(); if(wb == wall_brush) { - return !g_items[item->getID()].wall_hate_me; + return !g_items.getItemType(item->getID()).wall_hate_me; } else if(wall_brush->friendOf(wb) || wb->friendOf(wall_brush)) { - return !g_items[item->getID()].wall_hate_me; + return !g_items.getItemType(item->getID()).wall_hate_me; } } } @@ -692,10 +692,10 @@ void WallDecorationBrush::draw(BaseMap* map, Tile* tile, void* parameter) WallBrush::DoorType& dt = *door_iter; if(dt.type == doortype) { ASSERT(dt.id); - ItemType& it = g_items[dt.id]; + const ItemType& type = g_items.getItemType(dt.id); ASSERT(it.id != 0); - if(it.isOpen == open) { + if(type.isOpen == open) { id = dt.id; break; } else { diff --git a/source/waypoints.cpp b/source/waypoints.cpp index 918e36cc..3ce1be72 100644 --- a/source/waypoints.cpp +++ b/source/waypoints.cpp @@ -41,14 +41,14 @@ Waypoint* Waypoints::getWaypoint(std::string name) return iter->second; } -Waypoint* Waypoints::getWaypoint(TileLocation* location) +Waypoint* Waypoints::getWaypoint(const Position& position) { - if(!location) + if(!position.isValid()) return nullptr; // TODO find waypoint by position hash. for(WaypointMap::iterator it = waypoints.begin(); it != waypoints.end(); it++) { Waypoint* waypoint = it->second; - if(waypoint && waypoint->pos == location->position) + if(waypoint && waypoint->pos == position) return waypoint; } return nullptr; diff --git a/source/waypoints.h b/source/waypoints.h index 3afe5062..edfad897 100644 --- a/source/waypoints.h +++ b/source/waypoints.h @@ -39,7 +39,7 @@ class Waypoints { void addWaypoint(Waypoint* wp); Waypoint* getWaypoint(std::string name); - Waypoint* getWaypoint(TileLocation* location); + Waypoint* getWaypoint(const Position& position); void removeWaypoint(std::string name); WaypointMap waypoints; From ffad4a67d621ee1704abfbf338615223a7391a36 Mon Sep 17 00:00:00 2001 From: Beats Date: Wed, 5 Apr 2023 18:36:24 -0400 Subject: [PATCH 14/45] Cleanup and cast functions. --- source/complexitem.cpp | 34 ++++++------ source/complexitem.h | 120 ++++++++++++++++++++--------------------- source/item.h | 81 +++++++++++++--------------- 3 files changed, 114 insertions(+), 121 deletions(-) diff --git a/source/complexitem.cpp b/source/complexitem.cpp index 86aedbba..c9c2b47f 100644 --- a/source/complexitem.cpp +++ b/source/complexitem.cpp @@ -32,15 +32,15 @@ Container::~Container() for(Item* item : contents) { delete item; } + contents.clear(); } Item* Container::deepCopy() const { Item* copy = Item::deepCopy(); - Container* copyContainer = dynamic_cast(copy); - if(copyContainer) { - for(Item* item : contents) { - copyContainer->contents.push_back(item->deepCopy()); + if(Container* container = copy->getContainer()) { + for(const Item* item : contents) { + container->contents.push_back(item->deepCopy()); } } return copy; @@ -48,17 +48,12 @@ Item* Container::deepCopy() const Item* Container::getItem(size_t index) const { - if(index < contents.size()) { - return contents[index]; + if(index >= 0 && index < contents.size()) { + return contents.at(index); } return nullptr; } -double Container::getWeight() -{ - return getItemType().weight; -} - // Teleport Teleport::Teleport(const uint16_t type) : Item(type, 0), destination(0, 0, 0) @@ -68,8 +63,10 @@ Teleport::Teleport(const uint16_t type) : Item(type, 0), Item* Teleport::deepCopy() const { - Teleport* copy = static_cast(Item::deepCopy()); - copy->destination = destination; + Item* copy = Item::deepCopy(); + if(Teleport* teleport = copy->getTeleport()) { + teleport->setDestination(destination); + } return copy; } @@ -82,8 +79,10 @@ Door::Door(const uint16_t type) : Item(type, 0), Item* Door::deepCopy() const { - Door* copy = static_cast(Item::deepCopy()); - copy->doorId = doorId; + Item* copy = Item::deepCopy(); + if(Door* door = copy->getDoor()) { + door->doorId = doorId; + } return copy; } @@ -97,9 +96,8 @@ Depot::Depot(const uint16_t type) : Item(type, 0), Item* Depot::deepCopy() const { Item* copy = Item::deepCopy(); - Depot* copy_depot = dynamic_cast(copy); - if(copy_depot) { - copy_depot->depotId = depotId; + if(Depot* depot = copy->getDepot()) { + depot->depotId = depotId; } return copy; } diff --git a/source/complexitem.h b/source/complexitem.h index c56e343f..9f0d3e1d 100644 --- a/source/complexitem.h +++ b/source/complexitem.h @@ -34,91 +34,91 @@ struct OTBM_TeleportDestination class Container : public Item { - public: - Container(const uint16_t type); - ~Container(); +public: + Container(const uint16_t type); + ~Container(); - Item* deepCopy() const; - Item* getItem(size_t index) const; + Item* deepCopy() const override; + Container* getContainer() override { return this; } - size_t getItemCount() const noexcept { return contents.size(); } - size_t getVolume() const noexcept { return getItemType().volume; } + Item* getItem(size_t index) const; - ItemVector& getVector() { return contents; } - double getWeight(); + ItemVector& getVector() noexcept { return contents; } + size_t getItemCount() const noexcept { return contents.size(); } + size_t getVolume() const noexcept { return getItemType().volume; } + double getWeight() noexcept { return getItemType().weight; } - virtual bool unserializeItemNode_OTBM(const IOMap& maphandle, BinaryNode* node); - virtual bool serializeItemNode_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const; - //virtual bool unserializeItemNode_OTMM(const IOMap& maphandle, BinaryNode* node); - //virtual bool serializeItemNode_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; + virtual bool unserializeItemNode_OTBM(const IOMap& maphandle, BinaryNode* node); + virtual bool serializeItemNode_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const; + //virtual bool unserializeItemNode_OTMM(const IOMap& maphandle, BinaryNode* node); + //virtual bool serializeItemNode_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; - protected: - ItemVector contents; +protected: + ItemVector contents; }; class Teleport : public Item { - public: - Teleport(const uint16_t type); - - Item* deepCopy() const; - - virtual void serializeItemAttributes_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const; - virtual bool readItemAttribute_OTBM(const IOMap& maphandle, OTBM_ItemAttribute attr, BinaryNode* node); - //virtual void serializeItemAttributes_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; - //virtual bool readItemAttribute_OTMM(const IOMap& maphandle, OTMM_ItemAttribute attr, BinaryNode* node); - - const Position& getDestination() const noexcept { return destination; } - int getX() const noexcept { return destination.x; } - int getY() const noexcept { return destination.y; } - int getZ() const noexcept { return destination.z; } - void setDestination(const Position& position) { destination = position; } - - bool hasDestination() const { return destination.isValid(); } - - protected: - // We could've made this public and skip the functions, but that would - // make the handling of aid/uid/text different from handling teleports, - // which would be weird. - Position destination; +public: + Teleport(const uint16_t type); + + Item* deepCopy() const override; + Teleport* getTeleport() override { return this; } + + virtual void serializeItemAttributes_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const; + virtual bool readItemAttribute_OTBM(const IOMap& maphandle, OTBM_ItemAttribute attr, BinaryNode* node); + //virtual void serializeItemAttributes_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; + //virtual bool readItemAttribute_OTMM(const IOMap& maphandle, OTMM_ItemAttribute attr, BinaryNode* node); + + const Position& getDestination() const noexcept { return destination; } + int getX() const noexcept { return destination.x; } + int getY() const noexcept { return destination.y; } + int getZ() const noexcept { return destination.z; } + void setDestination(const Position& position) noexcept { destination = position; } + bool hasDestination() const noexcept { return destination.isValid(); } + +protected: + Position destination; }; class Door : public Item { - public: - Door(const uint16_t type); +public: + Door(const uint16_t type); - Item* deepCopy() const; + Item* deepCopy() const override; + Door* getDoor() override { return this; } - uint8_t getDoorID() const { return doorId; } - void setDoorID(uint8_t id) { doorId = id; } + uint8_t getDoorID() const { return doorId; } + void setDoorID(uint8_t id) { doorId = id; } - virtual void serializeItemAttributes_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const; - virtual bool readItemAttribute_OTBM(const IOMap& maphandle, OTBM_ItemAttribute attr, BinaryNode* node); - //virtual void serializeItemAttributes_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; - //virtual bool readItemAttribute_OTMM(const IOMap& maphandle, OTMM_ItemAttribute attr, BinaryNode* node); + virtual void serializeItemAttributes_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const; + virtual bool readItemAttribute_OTBM(const IOMap& maphandle, OTBM_ItemAttribute attr, BinaryNode* node); + //virtual void serializeItemAttributes_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; + //virtual bool readItemAttribute_OTMM(const IOMap& maphandle, OTMM_ItemAttribute attr, BinaryNode* node); - protected: - uint8_t doorId; +protected: + uint8_t doorId; }; class Depot : public Item { - public: - Depot(const uint16_t _type); +public: + Depot(const uint16_t _type); - Item* deepCopy() const; + Item* deepCopy() const override; + Depot* getDepot() override { return this; } - uint8_t getDepotID() const { return depotId; } - void setDepotID(uint8_t id) { depotId = id; } + uint8_t getDepotID() const { return depotId; } + void setDepotID(uint8_t id) { depotId = id; } - virtual void serializeItemAttributes_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const; - virtual bool readItemAttribute_OTBM(const IOMap& maphandle, OTBM_ItemAttribute attr, BinaryNode* node); - //virtual void serializeItemAttributes_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; - //virtual bool readItemAttribute_OTMM(const IOMap& maphandle, OTMM_ItemAttribute attr, BinaryNode* node); + virtual void serializeItemAttributes_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const; + virtual bool readItemAttribute_OTBM(const IOMap& maphandle, OTBM_ItemAttribute attr, BinaryNode* node); + //virtual void serializeItemAttributes_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; + //virtual bool readItemAttribute_OTMM(const IOMap& maphandle, OTMM_ItemAttribute attr, BinaryNode* node); - protected: - uint8_t depotId; +protected: + uint8_t depotId; }; #endif diff --git a/source/item.h b/source/item.h index 5bc92dfb..adc90d54 100644 --- a/source/item.h +++ b/source/item.h @@ -23,11 +23,6 @@ //#include "iomap_otmm.h" #include "item_attributes.h" -class Monster; -class Npc; -class Border; -class Tile; - enum ITEMPROPERTY { BLOCKSOLID, HASHEIGHT, @@ -72,6 +67,15 @@ enum SplashType IMPLEMENT_INCREMENT_OP(SplashType) +class Border; +class Tile; +class Container; +class Depot; +class Teleport; +class Door; +class Monster; +class Npc; + class Item : public ItemAttributes { public: @@ -93,48 +97,39 @@ class Item : public ItemAttributes // Get memory footprint size uint32_t memsize() const; - /* - virtual Container* getContainer() {return nullptr;} - virtual const Container* getContainer() const {return nullptr;} - virtual Teleport* getTeleport() {return nullptr;} - virtual const Teleport* getTeleport() const {return nullptr;} - virtual TrashHolder* getTrashHolder() {return nullptr;} - virtual const TrashHolder* getTrashHolder() const {return nullptr;} - virtual Mailbox* getMailbox() {return nullptr;} - virtual const Mailbox* getMailbox() const {return nullptr;} - virtual Door* getDoor() {return nullptr;} - virtual const Door* getDoor() const {return nullptr;} - virtual MagicField* getMagicField() {return nullptr;} - virtual const MagicField* getMagicField() const {return nullptr;} - */ + + virtual Container* getContainer() { return nullptr; } + virtual Depot* getDepot() { return nullptr; } + virtual Teleport* getTeleport() { return nullptr; } + virtual Door* getDoor() { return nullptr; } // OTBM map interface - // Serialize and unserialize (for save/load) - // Used internally - virtual bool readItemAttribute_OTBM(const IOMap& maphandle, OTBM_ItemAttribute attr, BinaryNode* stream); - virtual bool unserializeAttributes_OTBM(const IOMap& maphandle, BinaryNode* stream); - virtual bool unserializeItemNode_OTBM(const IOMap& maphandle, BinaryNode* node); - - // Will return a node containing this item - virtual bool serializeItemNode_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const; - // Will write this item to the stream supplied in the argument - virtual void serializeItemCompact_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const; - virtual void serializeItemAttributes_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const; + // Serialize and unserialize (for save/load) + // Used internally + virtual bool readItemAttribute_OTBM(const IOMap& maphandle, OTBM_ItemAttribute attr, BinaryNode* stream); + virtual bool unserializeAttributes_OTBM(const IOMap& maphandle, BinaryNode* stream); + virtual bool unserializeItemNode_OTBM(const IOMap& maphandle, BinaryNode* node); + + // Will return a node containing this item + virtual bool serializeItemNode_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const; + // Will write this item to the stream supplied in the argument + virtual void serializeItemCompact_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const; + virtual void serializeItemAttributes_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const; // OTMM map interface - /* - // Serialize and unserialize (for save/load) - // Used internally - virtual bool readItemAttribute_OTMM(const IOMap& maphandle, OTMM_ItemAttribute attr, BinaryNode* stream); - virtual bool unserializeAttributes_OTMM(const IOMap& maphandle, BinaryNode* stream); - virtual bool unserializeItemNode_OTMM(const IOMap& maphandle, BinaryNode* node); - - // Will return a node containing this item - virtual bool serializeItemNode_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; - // Will write this item to the stream supplied in the argument - virtual void serializeItemCompact_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; - virtual void serializeItemAttributes_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; - */ + /* + // Serialize and unserialize (for save/load) + // Used internally + virtual bool readItemAttribute_OTMM(const IOMap& maphandle, OTMM_ItemAttribute attr, BinaryNode* stream); + virtual bool unserializeAttributes_OTMM(const IOMap& maphandle, BinaryNode* stream); + virtual bool unserializeItemNode_OTMM(const IOMap& maphandle, BinaryNode* node); + + // Will return a node containing this item + virtual bool serializeItemNode_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; + // Will write this item to the stream supplied in the argument + virtual void serializeItemCompact_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; + virtual void serializeItemAttributes_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const; + */ // Static conversions static std::string LiquidID2Name(uint16_t id); From bca8e83fb6d80765e99905130ecc1cd3a84c3cab Mon Sep 17 00:00:00 2001 From: Beats Date: Wed, 5 Apr 2023 18:56:33 -0400 Subject: [PATCH 15/45] Avoid adding a new Unique ID if it already exists --- source/basemap.cpp | 52 +++++++++++++++++----- source/basemap.h | 16 ++++--- source/definitions.h | 5 +++ source/map.cpp | 60 +++++++++++++++++++++++++ source/map.h | 9 ++++ source/old_properties_window.cpp | 75 +++++++------------------------- 6 files changed, 139 insertions(+), 78 deletions(-) diff --git a/source/basemap.cpp b/source/basemap.cpp index 2fc3371d..e33f9d3b 100644 --- a/source/basemap.cpp +++ b/source/basemap.cpp @@ -108,27 +108,55 @@ TileLocation* BaseMap::createTileL(const Position& pos) return createTileL(pos.x, pos.y, pos.z); } -void BaseMap::setTile(int x, int y, int z, Tile* newtile, bool remove) +void BaseMap::setTile(int x, int y, int z, Tile* new_tile, bool remove) { - ASSERT(!newtile || newtile->getX() == int(x)); - ASSERT(!newtile || newtile->getY() == int(y)); - ASSERT(!newtile || newtile->getZ() == int(z)); + ASSERT(!new_tile || new_tile->getX() == x); + ASSERT(!new_tile || new_tile->getY() == y); + ASSERT(!new_tile || new_tile->getZ() == z); QTreeNode* leaf = root.getLeafForce(x, y); - Tile* old = leaf->setTile(x, y, z, newtile); - if(remove) - delete old; + Tile* old_tile = leaf->setTile(x, y, z, new_tile); + + if ((remove && old_tile) || new_tile) + updateUniqueIds(remove ? old_tile : nullptr, new_tile); + + if (remove) { + delete old_tile; + } +} + +void BaseMap::setTile(const Position& position, Tile* new_tile, bool remove) +{ + setTile(position.x, position.y, position.z, new_tile, remove); } -Tile* BaseMap::swapTile(int x, int y, int z, Tile* newtile) +void BaseMap::setTile(Tile* new_tile, bool remove) +{ + ASSERT(new_tile); + + const Position& position = new_tile->getPosition(); + setTile(position.x, position.y, position.z, new_tile, remove); +} + +Tile* BaseMap::swapTile(int x, int y, int z, Tile* new_tile) { ASSERT(z < MAP_LAYERS); - ASSERT(!newtile || newtile->getX() == int(x)); - ASSERT(!newtile || newtile->getY() == int(y)); - ASSERT(!newtile || newtile->getZ() == int(z)); + ASSERT(!new_tile || new_tile->getX() == x); + ASSERT(!new_tile || new_tile->getY() == y); + ASSERT(!new_tile || new_tile->getZ() == z); QTreeNode* leaf = root.getLeafForce(x, y); - return leaf->setTile(x, y, z, newtile); + Tile* old_tile = leaf->setTile(x, y, z, new_tile); + + if (old_tile || new_tile) + updateUniqueIds(old_tile, new_tile); + + return old_tile; +} + +Tile* BaseMap::swapTile(const Position& position, Tile* new_tile) +{ + return swapTile(position.x, position.y, position.z, new_tile); } // Iterators diff --git a/source/basemap.h b/source/basemap.h index b5235822..aeafb78e 100644 --- a/source/basemap.h +++ b/source/basemap.h @@ -83,7 +83,7 @@ class BaseMap void clear(bool del = true); MapIterator begin(); MapIterator end(); - uint64_t size() const {return tilecount;} + uint64_t size() const noexcept { return tilecount; } // these functions take a position and returns a tile on the map Tile* createTile(int x, int y, int z); @@ -103,22 +103,24 @@ class BaseMap QTreeNode* createLeaf(int x, int y) {return root.getLeafForce(x, y);} // Assigns a tile, it might seem pointless to provide position, but it is not, as the passed tile may be nullptr - void setTile(int _x, int _y, int _z, Tile* newtile, bool remove = false); - void setTile(const Position& pos, Tile* newtile, bool remove = false) { setTile(pos.x, pos.y, pos.z, newtile, remove); } - void setTile(Tile* newtile, bool remove = false) { setTile(newtile->getX(), newtile->getY(), newtile->getZ(), newtile, remove); } + void setTile(int x, int y, int z, Tile* new_tile, bool remove = false); + void setTile(const Position& position, Tile* new_tile, bool remove = false); + void setTile(Tile* new_tile, bool remove = false); // Replaces a tile and returns the old one - Tile* swapTile(int _x, int _y, int _z, Tile* newtile); - Tile* swapTile(const Position& pos, Tile* newtile) {return swapTile(pos.x, pos.y, pos.z, newtile);} + Tile* swapTile(int x, int y, int z, Tile* new_tile); + Tile* swapTile(const Position& position, Tile* new_tile); // Clears the visiblity according to the mask passed void clearVisible(uint32_t mask); - uint64_t getTileCount() const {return tilecount;} + uint64_t getTileCount() const noexcept { return tilecount; } public: MapAllocator allocator; protected: + virtual void updateUniqueIds(Tile* old_tile, Tile* new_tile) { } + uint64_t tilecount; QTreeNode root; // The Quad Tree root diff --git a/source/definitions.h b/source/definitions.h index 902b3226..524618a1 100644 --- a/source/definitions.h +++ b/source/definitions.h @@ -118,6 +118,11 @@ #define MAP_MAX_HEIGHT 65000 #define MAP_MAX_LAYER 15 +#define MIN_UNIQUE_ID 1000 +#define MAX_UNIQUE_ID 65535 +#define MIN_ACTION_ID 100 +#define MAX_ACTION_ID 65535 + // The size of the tile in pixels #define TILE_SIZE 32 diff --git a/source/map.cpp b/source/map.cpp index 1aaa6461..5d69af37 100644 --- a/source/map.cpp +++ b/source/map.cpp @@ -725,3 +725,63 @@ bool Map::exportMinimap(FileName filename, int floor /*= GROUND_LAYER*/, bool di return true; } + +void Map::updateUniqueIds(Tile* old_tile, Tile* new_tile) +{ + if(old_tile && old_tile->hasUniqueItem()) { + if(old_tile->ground) { + uint16_t uid = old_tile->ground->getUniqueID(); + if(uid != 0) + removeUniqueId(uid); + } + for(const Item* item : old_tile->items) { + if(item) { + uint16_t uid = item->getUniqueID(); + if(uid != 0) { + removeUniqueId(uid); + } + } + } + } + + if(new_tile && new_tile->hasUniqueItem()) { + if(new_tile->ground) { + uint16_t uid = new_tile->ground->getUniqueID(); + if(uid != 0) + addUniqueId(uid); + } + for(const Item* item : new_tile->items) { + if(item) { + uint16_t uid = item->getUniqueID(); + if(uid != 0) { + addUniqueId(uid); + } + } + } + } +} + +void Map::addUniqueId(uint16_t uid) +{ + auto it = std::find(uniqueIds.begin(), uniqueIds.end(), uid); + if (it == uniqueIds.end()) { + uniqueIds.push_back(uid); + } +} + +void Map::removeUniqueId(uint16_t uid) +{ + auto it = std::find(uniqueIds.begin(), uniqueIds.end(), uid); + if (it != uniqueIds.end()) { + uniqueIds.erase(it); + } +} + +bool Map::hasUniqueId(uint16_t uid) +{ + if (uid < MIN_UNIQUE_ID || uniqueIds.empty()) + return false; + + auto it = std::find(uniqueIds.begin(), uniqueIds.end(), uid); + return it != uniqueIds.end(); +} diff --git a/source/map.h b/source/map.h index 5346ab11..36ace2e1 100644 --- a/source/map.h +++ b/source/map.h @@ -105,6 +105,8 @@ class Map : public BaseMap void flagAsNamed() {unnamed = false;} + bool hasUniqueId(uint16_t uid); + protected: // Loads a map bool open(const std::string identifier); @@ -136,6 +138,10 @@ class Map : public BaseMap SpawnsNpc spawnsNpc; protected: + void updateUniqueIds(Tile* old_tile, Tile* new_tile) override; + void addUniqueId(uint16_t uid); + void removeUniqueId(uint16_t uid); + bool has_changed; // If the map has changed bool unnamed; // If the map has yet to receive a name @@ -145,6 +151,9 @@ class Map : public BaseMap public: Waypoints waypoints; + +private: + std::vector uniqueIds; }; template diff --git a/source/old_properties_window.cpp b/source/old_properties_window.cpp index bb7ca352..edbb13ee 100644 --- a/source/old_properties_window.cpp +++ b/source/old_properties_window.cpp @@ -565,44 +565,32 @@ void OldPropertiesWindow::OnFocusChange(wxFocusEvent& event) void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) { if(edit_item) { - if(dynamic_cast(edit_item)) { - // Container - int new_uid = unique_id_field->GetValue(); - int new_aid = action_id_field->GetValue(); - - if((new_uid < 1000 || new_uid > 0xFFFF) && new_uid != 0) { - g_gui.PopupDialog(this, "Error", "Unique ID must be between 1000 and 65535.", wxOK); + int new_uid = unique_id_field->GetValue(); + int new_aid = action_id_field->GetValue(); + if (!edit_item->getDepot()) { + if((new_uid < MIN_UNIQUE_ID || new_uid > MAX_UNIQUE_ID) && new_uid != 0) { + wxString message = "Unique ID must be between %d and %d."; + g_gui.PopupDialog(this, "Error", wxString::Format(message, MIN_UNIQUE_ID, MAX_UNIQUE_ID), wxOK); return; } - if(/* there is no item with the same UID */false) { + if(g_gui.GetCurrentMap().hasUniqueId(new_uid)) { g_gui.PopupDialog(this, "Error", "Unique ID must be unique, this UID is already taken.", wxOK); return; } - if((new_aid < 100 || new_aid > 0xFFFF) && new_aid != 0) { - g_gui.PopupDialog(this, "Error", "Action ID must be between 100 and 65535.", wxOK); + if((new_aid < MIN_ACTION_ID || new_aid > MAX_ACTION_ID) && new_aid != 0) { + wxString message = "Action ID must be between %d and %d."; + g_gui.PopupDialog(this, "Error", wxString::Format(message, MIN_ACTION_ID, MAX_ACTION_ID), wxOK); return; } + } + if(edit_item->getContainer()) { + // Container edit_item->setUniqueID(new_uid); edit_item->setActionID(new_aid); } else if(edit_item->canHoldText() || edit_item->canHoldDescription()) { // Book - int new_uid = unique_id_field->GetValue(); - int new_aid = action_id_field->GetValue(); std::string text = nstr(text_field->GetValue()); - - if((new_uid < 1000 || new_uid > 0xFFFF) && new_uid != 0) { - g_gui.PopupDialog(this, "Error", "Unique ID must be between 1000 and 65535.", wxOK); - return; - } - if(/* there is no item with the same UID */false) { - g_gui.PopupDialog(this, "Error", "Unique ID must be unique, this UID is already taken.", wxOK); - return; - } - if((new_aid < 100 || new_aid > 0xFFFF) && new_aid != 0) { - g_gui.PopupDialog(this, "Error", "Action ID must be between 100 and 65535.", wxOK); - return; - } if(text.length() >= 0xFFFF) { g_gui.PopupDialog(this, "Error", "Text is longer than 65535 characters, this is not supported by OpenTibia. Reduce the length of the text.", wxOK); return; @@ -619,22 +607,7 @@ void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) edit_item->setText(text); } else if(edit_item->isSplash() || edit_item->isFluidContainer()) { // Splash - int new_uid = unique_id_field->GetValue(); - int new_aid = action_id_field->GetValue(); int* new_type = reinterpret_cast(splash_type_field->GetClientData(splash_type_field->GetSelection())); - - if((new_uid < 1000 || new_uid > 0xFFFF) && new_uid != 0) { - g_gui.PopupDialog(this, "Error", "Unique ID must be between 1000 and 65535.", wxOK); - return; - } - if(/* there is no item with the same UID */false) { - g_gui.PopupDialog(this, "Error", "Unique ID must be unique, this UID is already taken.", wxOK); - return; - } - if((new_aid < 100 || new_aid > 0xFFFF) && new_aid != 0) { - g_gui.PopupDialog(this, "Error", "Action ID must be between 100 and 65535.", wxOK); - return; - } if(new_type) { edit_item->setSubtype(*new_type); } @@ -642,18 +615,15 @@ void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) edit_item->setActionID(new_aid); // Clean up client data - } else if(Depot* depot = dynamic_cast(edit_item)) { + } else if(Depot* depot = edit_item->getDepot()) { // Depot int* new_depotid = reinterpret_cast(depot_id_field->GetClientData(depot_id_field->GetSelection())); - depot->setDepotID(*new_depotid); } else { // Normal item - Door* door = dynamic_cast(edit_item); - Teleport* teleport = dynamic_cast(edit_item); + Door* door = edit_item->getDoor(); + Teleport* teleport = edit_item->getTeleport(); - int new_uid = unique_id_field->GetValue(); - int new_aid = action_id_field->GetValue(); int new_count = count_field? count_field->GetValue() : 1; std::string new_desc; if(edit_item->canHoldDescription() && description_field) { @@ -664,19 +634,6 @@ void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) new_door_id = door_id_field->GetValue(); } - if((new_uid < 1000 || new_uid > 0xFFFF) && new_uid != 0) { - g_gui.PopupDialog(this, "Error", "Unique ID must be between 1000 and 65535.", wxOK); - return; - } - if(/* there is no item with the same UID */false) { - g_gui.PopupDialog(this, "Error", "Unique ID must be unique, this UID is already taken.", wxOK); - return; - } - if((new_aid < 100 || new_aid > 0xFFFF) && new_aid != 0) { - g_gui.PopupDialog(this, "Error", "Action ID must be between 100 and 65535.", wxOK); - return; - } - /* if(edit_item->canHoldDescription()) { if(new_desc.length() > 127) { From a727aee8c98647b447917fdba0e3ed6852ce6f7b Mon Sep 17 00:00:00 2001 From: Beats Date: Wed, 5 Apr 2023 21:16:18 -0400 Subject: [PATCH 16/45] Code cleanup and small optimizations --- source/action.h | 39 +++---- source/brush.h | 4 +- source/copybuffer.h | 1 + source/editor.cpp | 5 +- source/editor.h | 14 +-- source/extension.h | 1 + source/graphics.cpp | 3 + source/graphics.h | 5 +- source/house.cpp | 8 +- source/house.h | 7 +- source/items.cpp | 1 + source/map.cpp | 220 +++++++++++++++++++++++---------------- source/map.h | 29 +++--- source/map_display.cpp | 5 - source/map_display.h | 6 +- source/map_drawer.h | 2 +- source/map_region.cpp | 7 ++ source/map_region.h | 26 ++--- source/map_window.h | 2 +- source/monster.cpp | 82 +++++++++------ source/monster.h | 60 +++-------- source/monsters.h | 4 +- source/npc.cpp | 79 +++++++++----- source/npc.h | 60 +++-------- source/npcs.h | 5 +- source/selection.cpp | 64 ++++++------ source/selection.h | 21 ++-- source/spawn_monster.cpp | 12 ++- source/spawn_monster.h | 30 +++--- source/spawn_npc.cpp | 12 ++- source/spawn_npc.h | 31 +++--- source/town.cpp | 4 +- source/town.h | 30 +++--- source/waypoints.cpp | 7 ++ source/waypoints.h | 23 ++-- 35 files changed, 472 insertions(+), 437 deletions(-) diff --git a/source/action.h b/source/action.h index ad6f2eef..5a67ce77 100644 --- a/source/action.h +++ b/source/action.h @@ -38,12 +38,14 @@ enum ChangeType { CHANGE_MOVE_WAYPOINT, }; -class Change { +class Change +{ private: ChangeType type; void* data; Change(); + public: Change(Tile* tile); static Change* Create(House* house, const Position& where); @@ -51,8 +53,8 @@ class Change { ~Change(); void clear(); - ChangeType getType() const {return type;} - void* getData() const {return data;} + ChangeType getType() const noexcept { return type; } + void* getData() const noexcept { return data; } // Get memory footprint uint32_t memsize() const; @@ -63,7 +65,8 @@ class Change { typedef std::vector ChangeList; // A dirty list represents a list of all tiles that was changed in an action -class DirtyList { +class DirtyList +{ public: DirtyList(); ~DirtyList(); @@ -96,8 +99,6 @@ class DirtyList { ChangeList ichanges; }; - - enum ActionIdentifier { ACTION_MOVE, ACTION_REMOTE, @@ -114,7 +115,8 @@ enum ActionIdentifier { ACTION_CHANGE_PROPERTIES, }; -class Action { +class Action +{ public: virtual ~Action(); @@ -125,11 +127,11 @@ class Action { // Get memory footprint size_t approx_memsize() const; size_t memsize() const; - size_t size() const {return changes.size();} - ActionIdentifier getType() const {return type;} + size_t size() const noexcept { return changes.size(); } + ActionIdentifier getType() const noexcept { return type; } void commit(DirtyList* dirty_list); - bool isCommited() const {return commited;} + bool isCommited() const noexcept { return commited; } void undo(DirtyList* dirty_list); void redo(DirtyList* dirty_list) {commit(dirty_list);} @@ -147,21 +149,21 @@ class Action { typedef std::vector ActionVector; -class BatchAction { +class BatchAction +{ public: virtual ~BatchAction(); - void resetTimer() { timestamp = 0; } + void resetTimer() noexcept { timestamp = 0; } // Get memory footprint size_t memsize(bool resize = false) const; - size_t size() const {return batch.size();} - ActionIdentifier getType() const {return type;} + size_t size() const noexcept { return batch.size(); } + ActionIdentifier getType() const noexcept { return type; } virtual void addAction(Action* action); virtual void addAndCommitAction(Action* action); - protected: BatchAction(Editor& editor, ActionIdentifier ident); @@ -180,7 +182,8 @@ class BatchAction { friend class ActionQueue; }; -class ActionQueue { +class ActionQueue +{ public: ActionQueue(Editor& editor); virtual ~ActionQueue(); @@ -200,8 +203,8 @@ class ActionQueue { void redo(); void clear(); - bool canUndo() {return current > 0;} - bool canRedo() {return current < actions.size();} + bool canUndo() noexcept { return current > 0; } + bool canRedo() noexcept { return current < actions.size(); } protected: size_t current; diff --git a/source/brush.h b/source/brush.h index a8dd0164..ad52397e 100644 --- a/source/brush.h +++ b/source/brush.h @@ -76,7 +76,7 @@ class Brushes bool unserializeBorder(pugi::xml_node node, wxArrayString& warnings); bool unserializeBrush(pugi::xml_node node, wxArrayString& warnings); - const BrushMap& getMap() const { return brushes; } + const BrushMap& getMap() const noexcept { return brushes; } protected: typedef std::map BorderMap; @@ -107,7 +107,7 @@ class Brush virtual bool canDraw(BaseMap* map, const Position& position) const = 0; // - uint32_t getID() const { return id; } + uint32_t getID() const noexcept { return id; } virtual std::string getName() const = 0; virtual void setName(const std::string& newName) { diff --git a/source/copybuffer.h b/source/copybuffer.h index cfffda79..8fb791a8 100644 --- a/source/copybuffer.h +++ b/source/copybuffer.h @@ -45,6 +45,7 @@ class CopyBuffer size_t GetTileCount(); BaseMap& getBufferMap(); + private: Position copyPos; BaseMap* tiles; diff --git a/source/editor.cpp b/source/editor.cpp index eca10ac5..3d4e468a 100644 --- a/source/editor.cpp +++ b/source/editor.cpp @@ -157,7 +157,8 @@ Editor::Editor(CopyBuffer& copybuffer, LiveClient* client) : ; } -Editor::~Editor() { +Editor::~Editor() +{ if(IsLive()) { CloseLiveServer(); } @@ -580,7 +581,7 @@ bool Editor::importMap(FileName filename, int import_x_offset, int import_y_offs House* current_house = map.houses.getHouse(imported_house->id); imported_house->townid = town_id_map[imported_house->townid]; - Position oldexit = imported_house->getExit(); + const Position& oldexit = imported_house->getExit(); imported_house->setExit(nullptr, Position()); // Reset it switch(house_import_type) { diff --git a/source/editor.h b/source/editor.h index ef492b5a..89f8f1c1 100644 --- a/source/editor.h +++ b/source/editor.h @@ -32,14 +32,15 @@ class LiveClient; class LiveServer; class LiveSocket; -class Editor { +class Editor +{ public: Editor(CopyBuffer& copybuffer, LiveClient* client); Editor(CopyBuffer& copybuffer, const FileName& fn); Editor(CopyBuffer& copybuffer); ~Editor(); -protected: +protected: // Live Server LiveServer* live_server; LiveClient* live_client; @@ -57,7 +58,7 @@ class Editor { LiveClient* GetLiveClient() const; LiveServer* GetLiveServer() const; LiveSocket& GetLive() const; - bool CanEdit() const {return true;} + bool CanEdit() const noexcept { return true; } bool IsLocal() const; bool IsLive() const; bool IsLiveServer() const; @@ -72,12 +73,11 @@ class Editor { void QueryNode(int ndx, int ndy, bool underground); void SendNodeRequests(); - // Map handling void saveMap(FileName filename, bool showdialog); // "" means default filename - uint16_t getMapWidth() const { return map.width; } - uint16_t getMapHeight() const { return map.height; } + uint16_t getMapWidth() const noexcept { return map.width; } + uint16_t getMapHeight() const noexcept { return map.height; } wxString getLoaderError() const {return map.getError();} bool importMap(FileName filename, int import_x_offset, int import_y_offset, int import_z_offset, ImportType house_import_type, ImportType spawn_import_type, ImportType spawn_npc_import_type); @@ -91,7 +91,7 @@ class Editor { void addAction(Action* action, int stacking_delay = 0); // Selection - bool hasSelection() const { return selection.size() != 0; } + bool hasSelection() const noexcept { return selection.size() != 0; } // Some simple actions that work on the map (these will work through the undo queue) // Moves the selected area by the offset void moveSelection(Position offset); diff --git a/source/extension.h b/source/extension.h index 8095177d..bb958e29 100644 --- a/source/extension.h +++ b/source/extension.h @@ -38,6 +38,7 @@ class MaterialsExtension std::string description; bool for_all_versions; ClientVersionList version_list; + private: MaterialsExtension(const MaterialsExtension&); MaterialsExtension& operator=(const MaterialsExtension&); diff --git a/source/graphics.cpp b/source/graphics.cpp index 620ee4ea..338aaa82 100644 --- a/source/graphics.cpp +++ b/source/graphics.cpp @@ -84,6 +84,9 @@ GraphicManager::~GraphicManager() delete iter->second; } + sprite_space.clear(); + image_space.clear(); + delete animation_timer; } diff --git a/source/graphics.h b/source/graphics.h index 827dbc50..f6de85f9 100644 --- a/source/graphics.h +++ b/source/graphics.h @@ -49,14 +49,12 @@ class Animator; class Sprite { public: Sprite() {} - virtual ~Sprite() {} virtual void DrawTo(wxDC* dc, SpriteSize sz, int start_x, int start_y, int width = -1, int height = -1) = 0; virtual void unloadDC() = 0; private: Sprite(const Sprite&); - Sprite& operator=(const Sprite&); }; class EditorSprite : public Sprite { @@ -66,6 +64,7 @@ class EditorSprite : public Sprite { virtual void DrawTo(wxDC* dc, SpriteSize sz, int start_x, int start_y, int width = -1, int height = -1); virtual void unloadDC(); + protected: wxBitmap* bm[SPRITE_SIZE_COUNT]; }; @@ -74,7 +73,7 @@ class EditorSprite : public Sprite { class GameSprite : public Sprite{ public: GameSprite(); - ~GameSprite(); + virtual ~GameSprite(); int getIndex(int width, int height, int layer, int pattern_x, int pattern_y, int pattern_z, int frame) const; GLuint getHardwareID(int _x, int _y, int _layer, int _subtype, int _pattern_x, int _pattern_y, int _pattern_z, int _frame); diff --git a/source/house.cpp b/source/house.cpp index dc345771..b25aef2a 100644 --- a/source/house.cpp +++ b/source/house.cpp @@ -31,8 +31,9 @@ Houses::Houses(Map& map) : Houses::~Houses() { - for(HouseMap::iterator it = houses.begin(); it != houses.end(); ++it) + for(auto it = houses.begin(); it != houses.end(); ++it) delete it->second; + houses.clear(); } uint32_t Houses::getEmptyID() @@ -90,11 +91,6 @@ House::House(Map& map) : //// } -House::~House() -{ - //// -} - void House::clean() { for(PositionList::const_iterator pos_iter = tiles.begin(); pos_iter != tiles.end(); ++pos_iter) { diff --git a/source/house.h b/source/house.h index af70a928..93d04608 100644 --- a/source/house.h +++ b/source/house.h @@ -26,10 +26,10 @@ class Door; class Houses; -class House { +class House +{ public: House(Map& map); - ~House(); void clean(); void addTile(Tile* tile); @@ -46,9 +46,10 @@ class House { void setExit(const Position& pos); void setExit(Map* map, const Position& pos); - Position getExit() const {return exit;} + const Position& getExit() const noexcept { return exit; } uint8_t getEmptyDoorID() const; Position getDoorPositionByID(uint8_t id) const; + protected: Map* map; PositionList tiles; diff --git a/source/items.cpp b/source/items.cpp index 9c372555..ccd6cd60 100644 --- a/source/items.cpp +++ b/source/items.cpp @@ -967,6 +967,7 @@ bool ItemDatabase::loadFromGameXml(const FileName& identifier, wxString& error, for(uint16_t id = fromId; id <= toId; ++id) { if(!loadItemFromGameXml(itemNode, id)) { + error = wxString::Format("Could not load item id %d. Item id not found.", id); return false; } } diff --git a/source/map.cpp b/source/map.cpp index 5d69af37..90226fb9 100644 --- a/source/map.cpp +++ b/source/map.cpp @@ -303,16 +303,6 @@ void Map::cleanInvalidTiles(bool showdialog) g_gui.DestroyLoadBar(); } -MapVersion Map::getVersion() const -{ - return mapVersion; -} - -bool Map::hasChanged() const -{ - return has_changed; -} - bool Map::doChange() { bool doupdate = !has_changed; @@ -327,11 +317,6 @@ bool Map::clearChanges() return doupdate; } -bool Map::hasFile() const -{ - return filename != ""; -} - void Map::setWidth(int new_width) { if(new_width > 65000) @@ -424,56 +409,88 @@ void Map::removeSpawnMonster(Tile* tile) } } -SpawnMonsterList Map::getSpawnMonsterList(Tile* where) +SpawnMonsterList Map::getSpawnMonsterList(const Tile* tile) const { SpawnMonsterList list; - TileLocation* tile_loc = where->getLocation(); - if(tile_loc) { - if(tile_loc->getSpawnMonsterCount() > 0) { - uint32_t found = 0; - if(where->spawnMonster) { + if(!tile) return list; + + const TileLocation* location = tile->getLocation(); + if(!location || location->getSpawnMonsterCount() == 0) + return list; + + uint32_t found = 0; + if(tile->spawnMonster) { + ++found; + list.push_back(tile->spawnMonster); + } + + // Scans the border tiles in an expanding square around the original spawn + const Position& position = tile->getPosition(); + int start_x = position.x - 1; + int end_x = position.x + 1; + int start_y = position.y - 1; + int end_y = position.y + 1; + + while(found != location->getSpawnMonsterCount()) { + for(int x = start_x; x <= end_x; ++x) { + const Tile* start_tile = getTile(x, start_y, position.z); + if(start_tile && start_tile->spawnMonster) { + list.push_back(start_tile->spawnMonster); ++found; - list.push_back(where->spawnMonster); } - // Scans the border tiles in an expanding square around the original monster spawn - int z = where->getZ(); - int start_x = where->getX() - 1, end_x = where->getX() + 1; - int start_y = where->getY() - 1, end_y = where->getY() + 1; - while(found != tile_loc->getSpawnMonsterCount()) { - for(int x = start_x; x <= end_x; ++x) { - Tile* tile = getTile(x, start_y, z); - if(tile && tile->spawnMonster) { - list.push_back(tile->spawnMonster); - ++found; - } - tile = getTile(x, end_y, z); - if(tile && tile->spawnMonster) { - list.push_back(tile->spawnMonster); - ++found; - } - } + const Tile* end_tile = getTile(x, end_y, position.z); + if(end_tile && end_tile->spawnMonster) { + list.push_back(end_tile->spawnMonster); + ++found; + } + } - for(int y = start_y + 1; y < end_y; ++y) { - Tile* tile = getTile(start_x, y, z); - if(tile && tile->spawnMonster) { - list.push_back(tile->spawnMonster); - ++found; - } - tile = getTile(end_x, y, z); - if(tile && tile->spawnMonster) { - list.push_back(tile->spawnMonster); - ++found; - } - } - --start_x, --start_y; - ++end_x, ++end_y; + for(int y = start_y + 1; y < end_y; ++y) { + const Tile* start_tile = getTile(start_x, y, position.z); + if(start_tile && start_tile->spawnMonster) { + list.push_back(start_tile->spawnMonster); + ++found; + } + const Tile* end_tile = getTile(end_x, y, position.z); + if(end_tile && end_tile->spawnMonster) { + list.push_back(end_tile->spawnMonster); + ++found; } } + + for(int y = start_y + 1; y < end_y; ++y) { + const Tile* start_tile = getTile(start_x, y, position.z); + if(start_tile && start_tile->spawnMonster) { + list.push_back(start_tile->spawnMonster); + ++found; + } + const Tile* end_tile = getTile(end_x, y, position.z); + if(end_tile && end_tile->spawnMonster) { + list.push_back(end_tile->spawnMonster); + ++found; + } + } + --start_x; + --start_y; + ++end_x; + ++end_y; } return list; } +SpawnMonsterList Map::getSpawnMonsterList(const Position& position) const +{ + const Tile* tile = getTile(position); + return getSpawnMonsterList(tile); +} + +SpawnMonsterList Map::getSpawnMonsterList(int x, int y, int z) const +{ + const Tile* tile = getTile(x, y, z); + return getSpawnMonsterList(tile); +} + bool Map::addSpawnNpc(Tile* tile) { SpawnNpc* spawnNpc = tile->spawnNpc; @@ -524,56 +541,75 @@ void Map::removeSpawnNpc(Tile* tile) } } -SpawnNpcList Map::getSpawnNpcList(Tile* where) +SpawnNpcList Map::getSpawnNpcList(const Tile* tile) const { SpawnNpcList listNpc; - TileLocation* tile_loc = where->getLocation(); - if(tile_loc) { - if(tile_loc->getSpawnNpcCount() > 0) { - uint32_t found = 0; - if(where->spawnNpc) { + if(!tile) return listNpc; + + const TileLocation* location = tile->getLocation(); + if(!location || location->getSpawnNpcCount() == 0) + return listNpc; + + uint32_t found = 0; + if(tile->spawnNpc) { + ++found; + listNpc.push_back(tile->spawnNpc); + } + + // Scans the border tiles in an expanding square around the original spawn + const Position& position = tile->getPosition(); + int start_x = position.x - 1; + int end_x = position.x + 1; + int start_y = position.y - 1; + int end_y = position.y + 1; + + while(found != location->getSpawnNpcCount()) { + for(int x = start_x; x <= end_x; ++x) { + const Tile* start_tile = getTile(x, start_y, position.z); + if(start_tile && start_tile->spawnNpc) { + listNpc.push_back(start_tile->spawnNpc); ++found; - listNpc.push_back(where->spawnNpc); } - // Scans the border tiles in an expanding square around the original spawnNpc - int z = where->getZ(); - int start_x = where->getX() - 1, end_x = where->getX() + 1; - int start_y = where->getY() - 1, end_y = where->getY() + 1; - while(found != tile_loc->getSpawnNpcCount()) { - for(int x = start_x; x <= end_x; ++x) { - Tile* tile = getTile(x, start_y, z); - if(tile && tile->spawnNpc) { - listNpc.push_back(tile->spawnNpc); - ++found; - } - tile = getTile(x, end_y, z); - if(tile && tile->spawnNpc) { - listNpc.push_back(tile->spawnNpc); - ++found; - } - } + const Tile* end_tile = getTile(x, end_y, position.z); + if(end_tile && end_tile->spawnNpc) { + listNpc.push_back(end_tile->spawnNpc); + ++found; + } + } - for(int y = start_y + 1; y < end_y; ++y) { - Tile* tile = getTile(start_x, y, z); - if(tile && tile->spawnNpc) { - listNpc.push_back(tile->spawnNpc); - ++found; - } - tile = getTile(end_x, y, z); - if(tile && tile->spawnNpc) { - listNpc.push_back(tile->spawnNpc); - ++found; - } - } - --start_x, --start_y; - ++end_x, ++end_y; + for(int y = start_y + 1; y < end_y; ++y) { + const Tile* start_tile = getTile(start_x, y, position.z); + if(start_tile && start_tile->spawnNpc) { + listNpc.push_back(start_tile->spawnNpc); + ++found; + } + const Tile* end_tile = getTile(end_x, y, position.z); + if(end_tile && end_tile->spawnNpc) { + listNpc.push_back(end_tile->spawnNpc); + ++found; } } + --start_x; + --start_y; + ++end_x; + ++end_y; } return listNpc; } +SpawnNpcList Map::getSpawnNpcList(const Position& position) const +{ + const Tile* tile = getTile(position); + return getSpawnNpcList(tile); +} + +SpawnNpcList Map::getSpawnNpcList(int x, int y, int z) const +{ + const Tile* tile = getTile(x, y, z); + return getSpawnNpcList(tile); +} + bool Map::exportMinimap(FileName filename, int floor /*= GROUND_LAYER*/, bool displaydialog) { uint8_t* pic = nullptr; @@ -777,7 +813,7 @@ void Map::removeUniqueId(uint16_t uid) } } -bool Map::hasUniqueId(uint16_t uid) +bool Map::hasUniqueId(uint16_t uid) const { if (uid < MIN_UNIQUE_ID || uniqueIds.empty()) return false; diff --git a/source/map.h b/source/map.h index 36ace2e1..b5526da5 100644 --- a/source/map.h +++ b/source/map.h @@ -43,12 +43,11 @@ class Map : public BaseMap bool convert(MapVersion to, bool showdialog = false); bool convert(const ConversionMap& cm, bool showdialog = false); - // Query information about the map - MapVersion getVersion() const; + MapVersion getVersion() const noexcept { return mapVersion; } // Returns true if any change has been done since last save - bool hasChanged() const; + bool hasChanged() const noexcept { return has_changed; } // Makes a change, doesn't matter what. Just so that it asks when saving (Also adds a * to the window title) bool doChange(); // Clears any changes @@ -66,9 +65,9 @@ class Map : public BaseMap void removeSpawnMonster(const Position& position) { removeSpawnMonster(getTile(position)); } // Returns all possible spawnsMonster on the target tile - SpawnMonsterList getSpawnMonsterList(Tile* t); - SpawnMonsterList getSpawnMonsterList(const Position& position) { return getSpawnMonsterList(getTile(position)); } - SpawnMonsterList getSpawnMonsterList(int32_t x, int32_t y, int32_t z) { return getSpawnMonsterList(getTile(x, y, z)); } + SpawnMonsterList getSpawnMonsterList(const Tile* tile) const; + SpawnMonsterList getSpawnMonsterList(const Position& position) const; + SpawnMonsterList getSpawnMonsterList(int x, int y, int z) const; // Mess with npc spawns bool addSpawnNpc(Tile* spawnMonster); @@ -76,16 +75,16 @@ class Map : public BaseMap void removeSpawnNpc(const Position& position) { removeSpawnNpc(getTile(position)); } // Returns all possible npc spawns on the target tile - SpawnNpcList getSpawnNpcList(Tile* t); - SpawnNpcList getSpawnNpcList(const Position& position) { return getSpawnNpcList(getTile(position)); } - SpawnNpcList getSpawnNpcList(int32_t x, int32_t y, int32_t z) { return getSpawnNpcList(getTile(x, y, z)); } + SpawnNpcList getSpawnNpcList(const Tile* tile) const; + SpawnNpcList getSpawnNpcList(const Position& position) const; + SpawnNpcList getSpawnNpcList(int x, int y, int z) const; // Returns true if the map has been saved // ie. it knows which file it should be saved to - bool hasFile() const; - std::string getFilename() const { return filename; } - std::string getName() const { return name; } - void setName(const std::string& n) { name = n; } + bool hasFile() const noexcept { return !filename.empty(); } + const std::string& getFilename() const noexcept { return filename; } + const std::string& getName() const noexcept { return name; } + void setName(const std::string& _name) noexcept { name = _name; } // Get map data int getWidth() const {return width;} @@ -103,9 +102,9 @@ class Map : public BaseMap void setSpawnMonsterFilename(const std::string& new_spawnmonsterfile); void setSpawnNpcFilename(const std::string& new_npcfile); - void flagAsNamed() {unnamed = false;} + void flagAsNamed() noexcept { unnamed = false; } - bool hasUniqueId(uint16_t uid); + bool hasUniqueId(uint16_t uid) const; protected: // Loads a map diff --git a/source/map_display.cpp b/source/map_display.cpp index 2fdcbc33..a34473d1 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -2682,11 +2682,6 @@ AnimationTimer::AnimationTimer(MapCanvas *canvas) : wxTimer(), //// }; -AnimationTimer::~AnimationTimer() -{ - //// -}; - void AnimationTimer::Notify() { if(map_canvas->GetZoom() <= 2.0) diff --git a/source/map_display.h b/source/map_display.h index 1d59f9d3..572bcb55 100644 --- a/source/map_display.h +++ b/source/map_display.h @@ -111,8 +111,8 @@ class MapCanvas : public wxGLCanvas void UpdateZoomStatus(); void ChangeFloor(int new_floor); - int GetFloor() const {return floor;} - double GetZoom() const { return zoom; } + int GetFloor() const noexcept { return floor; } + double GetZoom() const noexcept { return zoom; } void SetZoom(double value); void GetViewBox(int* view_scroll_x, int* view_scroll_y, int* screensize_x, int* screensize_y) const; @@ -195,6 +195,7 @@ class MapPopupMenu : public wxMenu { virtual ~MapPopupMenu(); void Update(); + protected: Editor& editor; }; @@ -203,7 +204,6 @@ class AnimationTimer : public wxTimer { public: AnimationTimer(MapCanvas *canvas); - ~AnimationTimer(); void Notify(); void Start(); diff --git a/source/map_drawer.h b/source/map_drawer.h index aaa3dee6..a66546aa 100644 --- a/source/map_drawer.h +++ b/source/map_drawer.h @@ -140,7 +140,7 @@ class MapDrawer void ShowPositionIndicator(const Position& position); - DrawingOptions& getOptions() { return options; } + DrawingOptions& getOptions() noexcept { return options; } protected: void BlitItem(int& screenx, int& screeny, const Tile* tile, const Item* item, bool ephemeral = false, int red = 255, int green = 255, int blue = 255, int alpha = 255); diff --git a/source/map_region.cpp b/source/map_region.cpp index e3671afa..6034687f 100644 --- a/source/map_region.cpp +++ b/source/map_region.cpp @@ -53,6 +53,13 @@ bool TileLocation::empty() const return size() == 0; } +HouseExitList* TileLocation::createHouseExits() +{ + if(!house_exits) + house_exits = new HouseExitList(); + return house_exits; +} + //**************** Floor ********************** Floor::Floor(int sx, int sy, int z) diff --git a/source/map_region.h b/source/map_region.h index 27767e47..0b7044b5 100644 --- a/source/map_region.h +++ b/source/map_region.h @@ -45,8 +45,8 @@ class TileLocation // Access tile // Can't set directly since that does not update tile count - Tile* get() {return tile;} - const Tile* get() const {return tile;} + Tile* get() noexcept { return tile; } + const Tile* get() const noexcept { return tile; } int size() const; bool empty() const; @@ -56,26 +56,27 @@ class TileLocation int getY() const noexcept { return position.y; } int getZ() const noexcept { return position.z; } - size_t getSpawnMonsterCount() const {return spawn_monster_count;} - void increaseSpawnCount() {spawn_monster_count++;} - void decreaseSpawnMonsterCount() {spawn_monster_count--;} + size_t getSpawnMonsterCount() const noexcept {return spawn_monster_count;} + void increaseSpawnCount() noexcept {spawn_monster_count++;} + void decreaseSpawnMonsterCount() noexcept {spawn_monster_count--;} - size_t getSpawnNpcCount() const {return spawn_npc_count;} - void increaseSpawnNpcCount() {spawn_npc_count++;} - void decreaseSpawnNpcCount() {spawn_npc_count--;} + size_t getSpawnNpcCount() const noexcept {return spawn_npc_count;} + void increaseSpawnNpcCount() noexcept {spawn_npc_count++;} + void decreaseSpawnNpcCount() noexcept {spawn_npc_count--;} - size_t getWaypointCount() const {return waypoint_count;} + size_t getWaypointCount() const noexcept {return waypoint_count;} void increaseWaypointCount() {waypoint_count++;} void decreaseWaypointCount() {waypoint_count--;} - HouseExitList* createHouseExits() {if(house_exits) return house_exits; return house_exits = newd HouseExitList;} - HouseExitList* getHouseExits() {return house_exits;} + HouseExitList* createHouseExits(); + HouseExitList* getHouseExits() noexcept { return house_exits; } friend class Floor; friend class QTreeNode; friend class Waypoints; }; -class Floor { +class Floor +{ public: Floor(int x, int y, int z); TileLocation locs[MAP_LAYERS]; @@ -117,6 +118,7 @@ class QTreeNode void setRequested(bool underground, bool r); bool isVisible(bool underground); bool isRequested(bool underground); + protected: BaseMap& map; uint32_t visible; diff --git a/source/map_window.h b/source/map_window.h index 2a11231c..27a57f26 100644 --- a/source/map_window.h +++ b/source/map_window.h @@ -71,7 +71,7 @@ class MapWindow : public wxPanel void GoToPreviousCenterPosition(); // Return the containing canvas - MapCanvas* GetCanvas() const { return canvas; } + MapCanvas* GetCanvas() const noexcept { return canvas; } void ShowReplaceItemsDialog(bool selectionOnly); void CloseReplaceItemsDialog(); diff --git a/source/monster.cpp b/source/monster.cpp index 7a637787..9ad9d199 100644 --- a/source/monster.cpp +++ b/source/monster.cpp @@ -19,42 +19,25 @@ #include "monster.h" -Monster::Monster(MonsterType* ctype) : direction(NORTH), spawntime(0), saved(false), selected(false) +Monster::Monster(MonsterType* type) : + direction(NORTH), + spawntime(0), + saved(false), + selected(false) { - if(ctype) - type_name = ctype->name; -} - -Monster::Monster(std::string ctype_name) : type_name(ctype_name), direction(NORTH), spawntime(0), saved(false), selected(false) -{ - //// + if(type) + type_name = type->name; } -Monster::~Monster() +Monster::Monster(const std::string& type_name) :type_name(type_name), + direction(NORTH), + spawntime(0), + saved(false), + selected(false) { //// } -std::string Monster::DirID2Name(uint16_t id) { - switch (id) { - case NORTH: return "North"; - case EAST: return "East"; - case SOUTH: return "South"; - case WEST: return "West"; - default: return "Unknown"; - } -} - -uint16_t Monster::DirName2ID(std::string dir) -{ - to_lower_str(dir); - if(dir == "north") return NORTH; - if(dir == "east") return EAST; - if(dir == "south") return SOUTH; - if(dir == "west") return WEST; - return SOUTH; -} - Monster* Monster::deepCopy() const { Monster* copy = newd Monster(type_name); @@ -67,9 +50,48 @@ Monster* Monster::deepCopy() const const Outfit& Monster::getLookType() const { - MonsterType* type = g_monsters[type_name]; + const MonsterType* type = g_monsters[type_name]; if(type) return type->outfit; static const Outfit otfi; // Empty outfit return otfi; } + +std::string Monster::getName() const +{ + const MonsterType* type = g_monsters[type_name]; + if(type) { + return type->name; + } + return ""; +} + +MonsterBrush* Monster::getBrush() const +{ + const MonsterType* type = g_monsters[type_name]; + if(type) { + return type->brush; + } + return nullptr; +} + +std::string Monster::DirID2Name(uint16_t id) +{ + switch (id) { + case NORTH: return "North"; + case EAST: return "East"; + case SOUTH: return "South"; + case WEST: return "West"; + default: return "Unknown"; + } +} + +uint16_t Monster::DirName2ID(std::string dir) +{ + to_lower_str(dir); + if(dir == "north") return NORTH; + if(dir == "east") return EAST; + if(dir == "south") return SOUTH; + if(dir == "west") return WEST; + return SOUTH; +} diff --git a/source/monster.h b/source/monster.h index 068e5ef3..45a4decb 100644 --- a/source/monster.h +++ b/source/monster.h @@ -23,34 +23,33 @@ class Monster { public: - Monster(MonsterType* ctype); - Monster(std::string type_name); - ~Monster(); - - // Static conversions - static std::string DirID2Name(uint16_t id); - static uint16_t DirName2ID(std::string id); + Monster(MonsterType* type); + Monster(const std::string& type_name); Monster* deepCopy() const; const Outfit& getLookType() const; - bool isSaved(); - void save(); - void reset(); + bool isSaved() const noexcept { return saved; } + void save() noexcept { saved = true; } + void reset() noexcept { saved = false; } - bool isSelected() const {return selected;} - void deselect() {selected = false;} - void select() {selected = true;} + bool isSelected() const noexcept { return selected; } + void deselect() noexcept { selected = false; } + void select() noexcept { selected = true; } std::string getName() const; MonsterBrush* getBrush() const; - int getSpawnMonsterTime() const {return spawntime;} - void setSpawnMonsterTime(int spawntime) {this->spawntime = spawntime;} + int getSpawnMonsterTime() const noexcept {return spawntime;} + void setSpawnMonsterTime(int time) noexcept { spawntime = time; } + + Direction getDirection() const noexcept { return direction; } + void setDirection(Direction _direction) noexcept { direction = _direction; } - Direction getDirection() const { return direction; } - void setDirection(Direction direction) { this->direction = direction; } + // Static conversions + static std::string DirID2Name(uint16_t id); + static uint16_t DirName2ID(std::string id); protected: std::string type_name; @@ -60,33 +59,6 @@ class Monster { bool selected; }; -inline void Monster::save() { - saved = true; -} - -inline void Monster::reset() { - saved = false; -} - -inline bool Monster::isSaved() { - return saved; -} - -inline std::string Monster::getName() const { - MonsterType* type = g_monsters[type_name]; - if(type) { - return type->name; - } - return ""; -} -inline MonsterBrush* Monster::getBrush() const { - MonsterType* type = g_monsters[type_name]; - if(type) { - return type->brush; - } - return nullptr; -} - typedef std::vector MonsterVector; typedef std::list MonsterList; diff --git a/source/monsters.h b/source/monsters.h index d485d305..ba4f12d5 100644 --- a/source/monsters.h +++ b/source/monsters.h @@ -47,8 +47,8 @@ class MonsterDatabase MonsterType* addMonsterType(const std::string& name, const Outfit& outfit); bool hasMissing() const; - iterator begin() {return monster_map.begin();} - iterator end() {return monster_map.end();} + iterator begin() noexcept { return monster_map.begin(); } + iterator end() noexcept { return monster_map.end(); } bool loadFromXML(const FileName& filename, bool standard, wxString& error, wxArrayString& warnings); bool importXMLFromOT(const FileName& filename, wxString& error, wxArrayString& warnings); diff --git a/source/npc.cpp b/source/npc.cpp index af1fe697..cd4eb8f3 100644 --- a/source/npc.cpp +++ b/source/npc.cpp @@ -25,39 +25,14 @@ Npc::Npc(NpcType* type) : direction(NORTH), spawnNpcTime(0), saved(false), selec type_name = type->name; } -Npc::Npc(std::string type_name) : type_name(type_name), direction(NORTH), spawnNpcTime(0), saved(false), selected(false) +Npc::Npc(const std::string& type_name) : type_name(type_name), direction(NORTH), spawnNpcTime(0), saved(false), selected(false) { //// } -Npc::~Npc() -{ - //// -} - -std::string Npc::DirID2Name(uint16_t id) { - switch (id) { - case NORTH: return "North"; - case EAST: return "East"; - case SOUTH: return "South"; - case WEST: return "West"; - default: return "Unknown"; - } -} - -uint16_t Npc::DirName2ID(std::string dir) -{ - to_lower_str(dir); - if(dir == "north") return NORTH; - if(dir == "east") return EAST; - if(dir == "south") return SOUTH; - if(dir == "west") return WEST; - return SOUTH; -} - Npc* Npc::deepCopy() const { - Npc* copy = newd Npc(type_name); + Npc* copy = new Npc(type_name); copy->spawnNpcTime = spawnNpcTime; copy->direction = direction; copy->selected = selected; @@ -67,9 +42,57 @@ Npc* Npc::deepCopy() const const Outfit& Npc::getLookType() const { - NpcType* type = g_npcs[type_name]; + const NpcType* type = g_npcs[type_name]; if(type) return type->outfit; static const Outfit otfi; // Empty outfit return otfi; } + +bool Npc::isNpc() const +{ + const NpcType* type = g_npcs[type_name]; + if(type) { + return type->isNpc; + } + return false; +} + +std::string Npc::getName() const +{ + const NpcType* type = g_npcs[type_name]; + if(type) { + return type->name; + } + return ""; +} + +NpcBrush* Npc::getBrush() const +{ + const NpcType* type = g_npcs[type_name]; + if(type) { + return type->brush; + } + return nullptr; +} + +std::string Npc::DirID2Name(uint16_t id) +{ + switch (id) { + case NORTH: return "North"; + case EAST: return "East"; + case SOUTH: return "South"; + case WEST: return "West"; + default: return "Unknown"; + } +} + +uint16_t Npc::DirName2ID(std::string dir) +{ + to_lower_str(dir); + if(dir == "north") return NORTH; + if(dir == "east") return EAST; + if(dir == "south") return SOUTH; + if(dir == "west") return WEST; + return SOUTH; +} diff --git a/source/npc.h b/source/npc.h index 9e52167a..67c58965 100644 --- a/source/npc.h +++ b/source/npc.h @@ -24,33 +24,34 @@ class Npc { public: Npc(NpcType* type); - Npc(std::string type_name); - ~Npc(); - - // Static conversions - static std::string DirID2Name(uint16_t id); - static uint16_t DirName2ID(std::string id); + Npc(const std::string& type_name); Npc* deepCopy() const; const Outfit& getLookType() const; - bool isSaved(); - void save(); - void reset(); + bool isSaved() const noexcept { return saved; } + void save() noexcept { saved = true; } + void reset() noexcept { saved = false; } - bool isSelected() const {return selected;} - void deselect() {selected = false;} - void select() {selected = true;} + bool isSelected() const noexcept { return selected; } + void deselect() noexcept { selected = false; } + void select() noexcept { selected = true; } + + bool isNpc() const; std::string getName() const; NpcBrush* getBrush() const; - int getSpawnNpcTime() const {return spawnNpcTime;} - void setSpawnNpcTime(int spawnNpcTime) {this->spawnNpcTime = spawnNpcTime;} + int getSpawnNpcTime() const noexcept {return spawnNpcTime;} + void setSpawnNpcTime(int time) noexcept { spawnNpcTime = time; } - Direction getDirection() const { return direction; } - void setDirection(Direction direction) { this->direction = direction; } + Direction getDirection() const noexcept { return direction; } + void setDirection(Direction _direction) noexcept { direction = _direction; } + + // Static conversions + static std::string DirID2Name(uint16_t id); + static uint16_t DirName2ID(std::string id); protected: std::string type_name; @@ -60,33 +61,6 @@ class Npc { bool selected; }; -inline void Npc::save() { - saved = true; -} - -inline void Npc::reset() { - saved = false; -} - -inline bool Npc::isSaved() { - return saved; -} - -inline std::string Npc::getName() const { - NpcType* npcType = g_npcs[type_name]; - if(npcType) { - return npcType->name; - } - return ""; -} -inline NpcBrush* Npc::getBrush() const { - NpcType* npcType = g_npcs[type_name]; - if(npcType) { - return npcType->brush; - } - return nullptr; -} - typedef std::vector NpcVector; typedef std::list NpcList; diff --git a/source/npcs.h b/source/npcs.h index 544bf3f4..408d5539 100644 --- a/source/npcs.h +++ b/source/npcs.h @@ -47,8 +47,8 @@ class NpcDatabase NpcType* addNpcType(const std::string& name, const Outfit& outfit); bool hasMissing() const; - iterator begin() {return npcMap.begin();} - iterator end() {return npcMap.end();} + iterator begin() noexcept {return npcMap.begin();} + iterator end() noexcept {return npcMap.end();} bool loadFromXML(const FileName& filename, bool standard, wxString& error, wxArrayString& warnings); bool importXMLFromOT(const FileName& filename, wxString& error, wxArrayString& warnings); @@ -63,6 +63,7 @@ class NpcType { NpcType& operator=(const NpcType& ct); ~NpcType(); + bool isNpc; bool missing; bool in_other_tileset; bool standard; diff --git a/source/selection.cpp b/source/selection.cpp index 6bf639ea..7d592ccf 100644 --- a/source/selection.cpp +++ b/source/selection.cpp @@ -26,10 +26,10 @@ #include "gui.h" Selection::Selection(Editor& editor) : - busy(false), editor(editor), session(nullptr), - subsession(nullptr) + subsession(nullptr), + busy(false) { //// } @@ -44,34 +44,34 @@ Selection::~Selection() Position Selection::minPosition() const { - Position minPos(0x10000, 0x10000, 0x10); + Position min_pos(0x10000, 0x10000, 0x10); for(const Tile* tile : tiles) { if(!tile) continue; - const Position& pos = tile->getPosition(); - if(minPos.x > pos.x) - minPos.x = pos.x; - if(minPos.y > pos.y) - minPos.y = pos.y; - if(minPos.z > pos.z) - minPos.z = pos.z; + const Position& tile_pos = tile->getPosition(); + if(min_pos.x > tile_pos.x) + min_pos.x = tile_pos.x; + if(min_pos.y > tile_pos.y) + min_pos.y = tile_pos.y; + if(min_pos.z > tile_pos.z) + min_pos.z = tile_pos.z; } - return minPos; + return min_pos; } Position Selection::maxPosition() const { - Position maxPos; + Position max_pos; for(const Tile* tile : tiles) { if(!tile) continue; - const Position& pos = tile->getPosition(); - if(maxPos.x < pos.x) - maxPos.x = pos.x; - if(maxPos.y < pos.y) - maxPos.y = pos.y; - if(maxPos.z < pos.z) - maxPos.z = pos.z; + const Position& tile_pos = tile->getPosition(); + if(max_pos.x < tile_pos.x) + max_pos.x = tile_pos.x; + if(max_pos.y < tile_pos.y) + max_pos.y = tile_pos.y; + if(max_pos.z < tile_pos.z) + max_pos.z = tile_pos.z; } - return maxPos; + return max_pos; } void Selection::add(Tile* tile, Item* item) @@ -87,9 +87,10 @@ void Selection::add(Tile* tile, Item* item) Tile* new_tile = tile->deepCopy(editor.map); item->deselect(); - if(g_settings.getInteger(Config::BORDER_IS_GROUND)) + if(g_settings.getInteger(Config::BORDER_IS_GROUND)) { if(item->isBorder()) new_tile->selectGround(); + } subsession->addChange(newd Change(new_tile)); } @@ -266,14 +267,14 @@ void Selection::removeInternal(Tile* tile) void Selection::clear() { if(session) { - for(TileSet::iterator it = tiles.begin(); it != tiles.end(); it++) { - Tile* new_tile = (*it)->deepCopy(editor.map); + for(Tile* tile : tiles) { + Tile* new_tile = tile->deepCopy(editor.map); new_tile->deselect(); subsession->addChange(newd Change(new_tile)); } } else { - for(TileSet::iterator it = tiles.begin(); it != tiles.end(); it++) { - (*it)->deselect(); + for(Tile* tile : tiles) { + tile->deselect(); } tiles.clear(); } @@ -282,9 +283,7 @@ void Selection::clear() void Selection::start(SessionFlags flags) { if(!(flags & INTERNAL)) { - if(flags & SUBTHREAD) { - ; - } else { + if(!(flags & SUBTHREAD)) { session = editor.actionQueue->createBatch(ACTION_SELECT); } subsession = editor.actionQueue->createAction(ACTION_SELECT); @@ -367,11 +366,6 @@ SelectionThread::SelectionThread(Editor& editor, Position start, Position end) : //// } -SelectionThread::~SelectionThread() -{ - //// -} - void SelectionThread::Execute() { Create(); @@ -381,6 +375,7 @@ void SelectionThread::Execute() wxThread::ExitCode SelectionThread::Entry() { selection.start(Selection::SUBTHREAD); + bool compesated = g_settings.getInteger(Config::COMPENSATED_SELECT); for(int z = start.z; z >= end.z; --z) { for(int x = start.x; x <= end.x; ++x) { for(int y = start.y; y <= end.y; ++y) { @@ -391,13 +386,12 @@ wxThread::ExitCode SelectionThread::Entry() selection.add(tile); } } - if(z <= GROUND_LAYER && g_settings.getInteger(Config::COMPENSATED_SELECT)) { + if(compesated && z <= GROUND_LAYER) { ++start.x; ++start.y; ++end.x; ++end.y; } } result = selection.subsession; selection.finish(Selection::SUBTHREAD); - return nullptr; } diff --git a/source/selection.h b/source/selection.h index 97c28802..70c599a0 100644 --- a/source/selection.h +++ b/source/selection.h @@ -56,7 +56,7 @@ class Selection void clear(); // Returns true when inside a session - bool isBusy() {return busy;} + bool isBusy() const noexcept { return busy; } // Position minPosition() const; @@ -81,31 +81,30 @@ class Selection // This deletes the thread void join(SelectionThread* thread); - size_t size() {return tiles.size();} - size_t size() const {return tiles.size();} + size_t size() const noexcept { return tiles.size(); } void updateSelectionCount(); - TileSet::iterator begin() {return tiles.begin();} - TileSet::iterator end() {return tiles.end();} - TileSet& getTiles() {return tiles; } - Tile* getSelectedTile() {ASSERT(size() == 1); return *tiles.begin();} + TileSet::iterator begin() noexcept { return tiles.begin(); } + TileSet::iterator end() noexcept { return tiles.end(); } + const TileSet& getTiles() const noexcept { return tiles; } + Tile* getSelectedTile() { ASSERT(size() == 1); return *tiles.begin(); } private: - bool busy; Editor& editor; BatchAction* session; Action* subsession; - TileSet tiles; + bool busy; friend class SelectionThread; }; -class SelectionThread : public wxThread { +class SelectionThread : public wxThread +{ public: SelectionThread(Editor& editor, Position start, Position end); - virtual ~SelectionThread(); void Execute(); // Calls "Create" and then "Run" + protected: virtual ExitCode Entry(); Editor& editor; diff --git a/source/spawn_monster.cpp b/source/spawn_monster.cpp index c4af71d1..922efa58 100644 --- a/source/spawn_monster.cpp +++ b/source/spawn_monster.cpp @@ -20,14 +20,18 @@ #include "tile.h" #include "spawn_monster.h" -SpawnsMonster::SpawnsMonster() +SpawnMonster::SpawnMonster(int size) : + size(0), + selected(false) { - //// + setSize(size); } -SpawnsMonster::~SpawnsMonster() +SpawnMonster* SpawnMonster::deepCopy() const { - //// + SpawnMonster* copy = new SpawnMonster(size); + copy->selected = selected; + return copy; } void SpawnsMonster::addSpawnMonster(Tile* tile) diff --git a/source/spawn_monster.h b/source/spawn_monster.h index 905539ac..2e5558b1 100644 --- a/source/spawn_monster.h +++ b/source/spawn_monster.h @@ -22,18 +22,15 @@ class Tile; class SpawnMonster { public: - SpawnMonster(int size = 3) : size(0), selected(false) {setSize(size);} - ~SpawnMonster() {} + SpawnMonster(int size = 3); - SpawnMonster* deepCopy() { - SpawnMonster* copy = newd SpawnMonster(size); - copy->selected = selected; - return copy; - } + SpawnMonster* deepCopy() const; + + bool isSelected() const noexcept { return selected; } + void select() noexcept { selected = true; } + void deselect() noexcept { selected = false; } - bool isSelected() const {return selected;} - void select() {selected = true;} - void deselect() {selected = false;} + int getSize() const noexcept { return size; } // Does not compare selection! bool operator==(const SpawnMonster& other) {return size == other.size;} @@ -43,7 +40,6 @@ class SpawnMonster { ASSERT(size < 100); size = newsize; } - int getSize() const {return size;} protected: int size; bool selected; @@ -54,17 +50,15 @@ typedef std::list SpawnMonsterList; class SpawnsMonster { public: - SpawnsMonster(); - ~SpawnsMonster(); void addSpawnMonster(Tile* tile); void removeSpawnMonster(Tile* tile); - SpawnMonsterPositionList::iterator begin() {return spawnsMonster.begin();} - SpawnMonsterPositionList::const_iterator begin() const {return spawnsMonster.begin();} - SpawnMonsterPositionList::iterator end() {return spawnsMonster.end();} - SpawnMonsterPositionList::const_iterator end() const {return spawnsMonster.end();} - void erase(SpawnMonsterPositionList::iterator iter) {spawnsMonster.erase(iter);} + SpawnMonsterPositionList::iterator begin() noexcept { return spawnsMonster.begin(); } + SpawnMonsterPositionList::const_iterator begin() const noexcept { return spawnsMonster.begin(); } + SpawnMonsterPositionList::iterator end() noexcept { return spawnsMonster.end(); } + SpawnMonsterPositionList::const_iterator end() const noexcept { return spawnsMonster.end(); } + void erase(SpawnMonsterPositionList::iterator iter) noexcept { spawnsMonster.erase(iter); } SpawnMonsterPositionList::iterator find(Position& pos) {return spawnsMonster.find(pos);} private: SpawnMonsterPositionList spawnsMonster; diff --git a/source/spawn_npc.cpp b/source/spawn_npc.cpp index 8b4b2b11..1fdf6cd5 100644 --- a/source/spawn_npc.cpp +++ b/source/spawn_npc.cpp @@ -20,14 +20,18 @@ #include "tile.h" #include "spawn_npc.h" -SpawnsNpc::SpawnsNpc() +SpawnNpc::SpawnNpc(int size) : + size(0), + selected(false) { - //// + setSize(size); } -SpawnsNpc::~SpawnsNpc() +SpawnNpc* SpawnNpc::deepCopy() const { - //// + SpawnNpc* copy = new SpawnNpc(size); + copy->selected = selected; + return copy; } void SpawnsNpc::addSpawnNpc(Tile* tile) diff --git a/source/spawn_npc.h b/source/spawn_npc.h index c2e61049..95a52f63 100644 --- a/source/spawn_npc.h +++ b/source/spawn_npc.h @@ -22,18 +22,15 @@ class Tile; class SpawnNpc { public: - SpawnNpc(int size = 3) : size(0), selected(false) {setSize(size);} - ~SpawnNpc() {} + SpawnNpc(int size = 3); - SpawnNpc* deepCopy() { - SpawnNpc* copy = newd SpawnNpc(size); - copy->selected = selected; - return copy; - } + SpawnNpc* deepCopy() const; + + bool isSelected() const noexcept { return selected; } + void select() noexcept { selected = true; } + void deselect() noexcept { selected = false; } - bool isSelected() const {return selected;} - void select() {selected = true;} - void deselect() {selected = false;} + int getSize() const noexcept { return size; } // Does not compare selection! bool operator==(const SpawnNpc& other) {return size == other.size;} @@ -43,7 +40,7 @@ class SpawnNpc { ASSERT(size < 100); size = newsize; } - int getSize() const {return size;} + protected: int size; bool selected; @@ -54,17 +51,15 @@ typedef std::list SpawnNpcList; class SpawnsNpc { public: - SpawnsNpc(); - ~SpawnsNpc(); void addSpawnNpc(Tile* tile); void removeSpawnNpc(Tile* tile); - SpawnNpcPositionList::iterator begin() {return spawnsNpc.begin();} - SpawnNpcPositionList::const_iterator begin() const {return spawnsNpc.begin();} - SpawnNpcPositionList::iterator end() {return spawnsNpc.end();} - SpawnNpcPositionList::const_iterator end() const {return spawnsNpc.end();} - void erase(SpawnNpcPositionList::iterator iter) {spawnsNpc.erase(iter);} + SpawnNpcPositionList::iterator begin() noexcept { return spawnsNpc.begin(); } + SpawnNpcPositionList::const_iterator begin() const noexcept { return spawnsNpc.begin(); } + SpawnNpcPositionList::iterator end() noexcept { return spawnsNpc.end(); } + SpawnNpcPositionList::const_iterator end() const noexcept { return spawnsNpc.end(); } + void erase(SpawnNpcPositionList::iterator iter) noexcept { spawnsNpc.erase(iter); } SpawnNpcPositionList::iterator find(Position& pos) {return spawnsNpc.find(pos);} private: SpawnNpcPositionList spawnsNpc; diff --git a/source/town.cpp b/source/town.cpp index 8cde35fc..59e4b027 100644 --- a/source/town.cpp +++ b/source/town.cpp @@ -82,7 +82,7 @@ Town* Towns::getTown(uint32_t id) return nullptr; } -void Town::setTemplePosition(const Position& pos) +void Town::setTemplePosition(const Position& position) { - templepos = pos; + templepos = position; } diff --git a/source/town.h b/source/town.h index 67ad486f..dac10b31 100644 --- a/source/town.h +++ b/source/town.h @@ -25,16 +25,16 @@ class Town public: Town(uint32_t _id) : id(_id), name("") {} Town(const Town& copy) : id(copy.id), name(copy.name), templepos(copy.templepos) {} - ~Town() {} - const std::string& getName() const { return name; } - void setName(const std::string& newName) { name = newName; } + const std::string& getName() const noexcept { return name; } + void setName(const std::string& _name) noexcept { name = _name; } - const Position& getTemplePosition() const {return templepos;} - void setTemplePosition(const Position& _pos); + const Position& getTemplePosition() const noexcept { return templepos; } + void setTemplePosition(const Position& position); + + uint32_t getID() const noexcept { return id; } + void setID(uint32_t _id) noexcept { id = _id; } - uint32_t getID() const {return id;} - void setID(uint32_t _id) {id = _id;} private: uint32_t id; std::string name; @@ -52,7 +52,7 @@ class Towns // Clears the townmap void clear(); - uint32_t count() const {return towns.size();} + uint32_t count() const noexcept { return towns.size(); } bool addTown(Town* town); uint32_t getEmptyID(); @@ -60,14 +60,14 @@ class Towns Town* getTown(std::string& townname); Town* getTown(uint32_t _townid); - TownMap::const_iterator begin() const{return towns.begin();} - TownMap::const_iterator end() const{return towns.end();} - TownMap::const_iterator find(uint32_t id) const {return towns.find(id);} - TownMap::iterator begin() {return towns.begin();} - TownMap::iterator end() {return towns.end();} - TownMap::iterator find(uint32_t id) {return towns.find(id);} + TownMap::const_iterator begin() const noexcept { return towns.begin(); } + TownMap::const_iterator end() const noexcept { return towns.end(); } + TownMap::const_iterator find(uint32_t id) const { return towns.find(id); } + TownMap::iterator begin() noexcept { return towns.begin(); } + TownMap::iterator end() noexcept { return towns.end(); } + TownMap::iterator find(uint32_t id) { return towns.find(id); } #ifdef __VISUALC__ // C++0x compliance to some degree :) - TownMap::iterator erase(TownMap::iterator iter) {return towns.erase(iter);} + TownMap::iterator erase(TownMap::iterator iter) noexcept { return towns.erase(iter); } #else void erase(TownMap::iterator iter) {towns.erase(iter);} #endif diff --git a/source/waypoints.cpp b/source/waypoints.cpp index 3ce1be72..6d67ac38 100644 --- a/source/waypoints.cpp +++ b/source/waypoints.cpp @@ -20,6 +20,13 @@ #include "waypoints.h" #include "map.h" +Waypoints::~Waypoints() +{ + for(auto it = waypoints.begin(); it != waypoints.end(); ++it) + delete it->second; + waypoints.clear(); +} + void Waypoints::addWaypoint(Waypoint* wp) { removeWaypoint(wp->name); diff --git a/source/waypoints.h b/source/waypoints.h index edfad897..62b556b7 100644 --- a/source/waypoints.h +++ b/source/waypoints.h @@ -20,7 +20,8 @@ #include "position.h" -class Waypoint { +class Waypoint +{ public: std::string name; Position pos; @@ -28,14 +29,11 @@ class Waypoint { typedef std::map WaypointMap; -class Waypoints { - Map& map; +class Waypoints +{ public: Waypoints(Map& map) : map(map) {} - ~Waypoints() { - for(WaypointMap::iterator iter = waypoints.begin(); iter != waypoints.end(); ++iter) - delete iter->second; - } + virtual ~Waypoints(); void addWaypoint(Waypoint* wp); Waypoint* getWaypoint(std::string name); @@ -44,10 +42,13 @@ class Waypoints { WaypointMap waypoints; - WaypointMap::iterator begin() {return waypoints.begin();} - WaypointMap::const_iterator begin() const {return waypoints.begin();} - WaypointMap::iterator end() {return waypoints.end();} - WaypointMap::const_iterator end() const {return waypoints.end();} + WaypointMap::iterator begin() { return waypoints.begin(); } + WaypointMap::const_iterator begin() const { return waypoints.begin(); } + WaypointMap::iterator end() { return waypoints.end(); } + WaypointMap::const_iterator end() const { return waypoints.end(); } + +private: + Map& map; }; #endif From d9cb0006a6aa36f48341310e0519b22aad84b912 Mon Sep 17 00:00:00 2001 From: Beats Date: Wed, 5 Apr 2023 21:39:23 -0400 Subject: [PATCH 17/45] More changes and cleanup --- source/action.cpp | 74 ++++++++++---------- source/application.cpp | 2 +- source/common_windows.cpp | 26 ++++--- source/copybuffer.cpp | 43 ++++++------ source/editor.h | 6 +- source/gui.cpp | 6 +- source/live_client.cpp | 4 +- source/live_peer.cpp | 4 +- source/live_server.cpp | 4 +- source/live_socket.cpp | 6 +- source/map_display.cpp | 119 +++++++++++++++++--------------- source/map_drawer.cpp | 18 ++--- source/map_tab.cpp | 5 +- source/map_window.cpp | 3 +- source/minimap_window.cpp | 19 ++--- source/replace_items_window.cpp | 4 +- source/selection.cpp | 28 ++++---- source/tile.cpp | 3 +- source/tile.h | 2 +- 19 files changed, 193 insertions(+), 183 deletions(-) diff --git a/source/action.cpp b/source/action.cpp index 72d6990b..589962de 100644 --- a/source/action.cpp +++ b/source/action.cpp @@ -163,7 +163,7 @@ void Action::commit(DirtyList* dirty_list) const Position& pos = newtile->getPosition(); if(editor.IsLiveClient()) { - QTreeNode* nd = editor.map.getLeaf(pos.x, pos.y); + QTreeNode* nd = editor.getMap().getLeaf(pos.x, pos.y); if(!nd || !nd->isVisible(pos.z > GROUND_LAYER)) { // Delete all changes that affect tiles outside our view c->clear(); @@ -172,7 +172,7 @@ void Action::commit(DirtyList* dirty_list) } } - Tile* oldtile = editor.map.swapTile(pos, newtile); + Tile* oldtile = editor.getMap().swapTile(pos, newtile); TileLocation* location = newtile->getLocation(); // Update other nodes in the network @@ -189,39 +189,39 @@ void Action::commit(DirtyList* dirty_list) if(oldtile) { if(newtile->getHouseID() != oldtile->getHouseID()) { // oooooomggzzz we need to add it to the appropriate house! - House* house = editor.map.houses.getHouse(oldtile->getHouseID()); + House* house = editor.getMap().houses.getHouse(oldtile->getHouseID()); if(house) house->removeTile(oldtile); - house = editor.map.houses.getHouse(newtile->getHouseID()); + house = editor.getMap().houses.getHouse(newtile->getHouseID()); if(house) house->addTile(newtile); } if(oldtile->spawnMonster) { if(newtile->spawnMonster) { if(*oldtile->spawnMonster != *newtile->spawnMonster) { - editor.map.removeSpawnMonster(oldtile); - editor.map.addSpawnMonster(newtile); + editor.getMap().removeSpawnMonster(oldtile); + editor.getMap().addSpawnMonster(newtile); } } else { // Monster spawn has been removed - editor.map.removeSpawnMonster(oldtile); + editor.getMap().removeSpawnMonster(oldtile); } } else if(newtile->spawnMonster) { - editor.map.addSpawnMonster(newtile); + editor.getMap().addSpawnMonster(newtile); } if(oldtile->spawnNpc) { if(newtile->spawnNpc) { if(*oldtile->spawnNpc != *newtile->spawnNpc) { - editor.map.removeSpawnNpc(oldtile); - editor.map.addSpawnNpc(newtile); + editor.getMap().removeSpawnNpc(oldtile); + editor.getMap().addSpawnNpc(newtile); } } else { // SpawnMonster has been removed - editor.map.removeSpawnNpc(oldtile); + editor.getMap().removeSpawnNpc(oldtile); } } else if(newtile->spawnNpc) { - editor.map.addSpawnNpc(newtile); + editor.getMap().addSpawnNpc(newtile); } //oldtile->update(); @@ -230,20 +230,20 @@ void Action::commit(DirtyList* dirty_list) *data = oldtile; } else { - *data = editor.map.allocator(location); + *data = editor.getMap().allocator(location); if(newtile->getHouseID() != 0) { // oooooomggzzz we need to add it to the appropriate house! - House* house = editor.map.houses.getHouse(newtile->getHouseID()); + House* house = editor.getMap().houses.getHouse(newtile->getHouseID()); if(house) { house->addTile(newtile); } } if(newtile->spawnMonster) - editor.map.addSpawnMonster(newtile); + editor.getMap().addSpawnMonster(newtile); if(newtile->spawnNpc) - editor.map.addSpawnNpc(newtile); + editor.getMap().addSpawnNpc(newtile); } // Mark the tile as modified @@ -260,7 +260,7 @@ void Action::commit(DirtyList* dirty_list) case CHANGE_MOVE_HOUSE_EXIT: { std::pair* p = reinterpret_cast* >(c->data); ASSERT(p); - House* whathouse = editor.map.houses.getHouse(p->first); + House* whathouse = editor.getMap().houses.getHouse(p->first); if(whathouse) { Position oldpos = whathouse->getExit(); @@ -273,12 +273,12 @@ void Action::commit(DirtyList* dirty_list) case CHANGE_MOVE_WAYPOINT: { std::pair* p = reinterpret_cast* >(c->data); ASSERT(p); - Waypoint* wp = editor.map.waypoints.getWaypoint(p->first); + Waypoint* wp = editor.getMap().waypoints.getWaypoint(p->first); if(wp) { // Change the tiles - TileLocation* oldtile = editor.map.getTileL(wp->pos); - TileLocation* newtile = editor.map.getTileL(p->second); + TileLocation* oldtile = editor.getMap().getTileL(wp->pos); + TileLocation* newtile = editor.getMap().getTileL(p->second); // Only need to remove from old if it actually exists if(p->second.isValid() && oldtile && oldtile->getWaypointCount() > 0) @@ -321,7 +321,7 @@ void Action::undo(DirtyList* dirty_list) const Position& pos = oldtile->getPosition(); if(editor.IsLiveClient()) { - QTreeNode* nd = editor.map.getLeaf(pos.x, pos.y); + QTreeNode* nd = editor.getMap().getLeaf(pos.x, pos.y); if(!nd || !nd->isVisible(pos.z > GROUND_LAYER)) { // Delete all changes that affect tiles outside our view c->clear(); @@ -330,7 +330,7 @@ void Action::undo(DirtyList* dirty_list) } } - Tile* newtile = editor.map.swapTile(pos, oldtile); + Tile* newtile = editor.getMap().swapTile(pos, oldtile); // Update server side change list (for broadcast) if(editor.IsLiveServer() && dirty_list) @@ -344,7 +344,7 @@ void Action::undo(DirtyList* dirty_list) if(newtile->getHouseID() != oldtile->getHouseID()) { // oooooomggzzz we need to remove it from the appropriate house! - House* house = editor.map.houses.getHouse(newtile->getHouseID()); + House* house = editor.getMap().houses.getHouse(newtile->getHouseID()); if(house) { house->removeTile(newtile); } else { @@ -352,7 +352,7 @@ void Action::undo(DirtyList* dirty_list) newtile->setHouse(nullptr); } - house = editor.map.houses.getHouse(oldtile->getHouseID()); + house = editor.getMap().houses.getHouse(oldtile->getHouseID()); if(house) { house->addTile(oldtile); } @@ -361,27 +361,27 @@ void Action::undo(DirtyList* dirty_list) if(oldtile->spawnMonster) { if(newtile->spawnMonster) { if(*oldtile->spawnMonster != *newtile->spawnMonster) { - editor.map.removeSpawnMonster(newtile); - editor.map.addSpawnMonster(oldtile); + editor.getMap().removeSpawnMonster(newtile); + editor.getMap().addSpawnMonster(oldtile); } } else { - editor.map.addSpawnMonster(oldtile); + editor.getMap().addSpawnMonster(oldtile); } } else if(newtile->spawnMonster) { - editor.map.removeSpawnMonster(newtile); + editor.getMap().removeSpawnMonster(newtile); } if(oldtile->spawnNpc) { if(newtile->spawnNpc) { if(*oldtile->spawnNpc != *newtile->spawnNpc) { - editor.map.removeSpawnNpc(newtile); - editor.map.addSpawnNpc(oldtile); + editor.getMap().removeSpawnNpc(newtile); + editor.getMap().addSpawnNpc(oldtile); } } else { - editor.map.addSpawnNpc(oldtile); + editor.getMap().addSpawnNpc(oldtile); } } else if(newtile->spawnNpc) { - editor.map.removeSpawnNpc(newtile); + editor.getMap().removeSpawnNpc(newtile); } *data = newtile; @@ -397,7 +397,7 @@ void Action::undo(DirtyList* dirty_list) case CHANGE_MOVE_HOUSE_EXIT: { std::pair* p = reinterpret_cast* >(c->data); ASSERT(p); - House* whathouse = editor.map.houses.getHouse(p->first); + House* whathouse = editor.getMap().houses.getHouse(p->first); if(whathouse) { Position oldpos = whathouse->getExit(); whathouse->setExit(p->second); @@ -409,12 +409,12 @@ void Action::undo(DirtyList* dirty_list) case CHANGE_MOVE_WAYPOINT: { std::pair* p = reinterpret_cast* >(c->data); ASSERT(p); - Waypoint* wp = editor.map.waypoints.getWaypoint(p->first); + Waypoint* wp = editor.getMap().waypoints.getWaypoint(p->first); if(wp) { // Change the tiles - TileLocation* oldtile = editor.map.getTileL(wp->pos); - TileLocation* newtile = editor.map.getTileL(p->second); + TileLocation* oldtile = editor.getMap().getTileL(wp->pos); + TileLocation* newtile = editor.getMap().getTileL(p->second); // Only need to remove from old if it actually exists if(p->second.isValid() && oldtile && oldtile->getWaypointCount() > 0) @@ -596,7 +596,7 @@ void ActionQueue::addBatch(BatchAction* batch, int stacking_delay) batch->commit(); // Update title - if(editor.map.doChange()) + if(editor.getMap().doChange()) g_gui.UpdateTitle(); if(batch->type == ACTION_REMOTE) { diff --git a/source/application.cpp b/source/application.cpp index 51310e02..2ab3a9c7 100644 --- a/source/application.cpp +++ b/source/application.cpp @@ -288,7 +288,7 @@ void Application::OnEventLoopEnter(wxEventLoopBase* loop) { g_gui.LoadMap(FileName(m_file_to_open)); } else if (!g_gui.IsWelcomeDialogShown() && g_gui.NewMap()) { //Open a new empty map // You generally don't want to save this map... - g_gui.GetCurrentEditor()->map.clearChanges(); + g_gui.GetCurrentEditor()->getMap().clearChanges(); } } diff --git a/source/common_windows.cpp b/source/common_windows.cpp index b0b7ca19..b0865cdf 100644 --- a/source/common_windows.cpp +++ b/source/common_windows.cpp @@ -52,7 +52,7 @@ MapPropertiesWindow::MapPropertiesWindow(wxWindow* parent, MapTab* view, Editor& editor(editor) { // Setup data variabels - Map& map = editor.map; + const Map& map = editor.getMap(); wxSizer* topsizer = newd wxBoxSizer(wxVERTICAL); @@ -238,8 +238,7 @@ struct MapConversionContext void MapPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) { - Map& map = editor.map; - + Map& map = editor.getMap(); MapVersion old_ver = map.getVersion(); MapVersion new_ver; @@ -544,7 +543,7 @@ ExportMiniMapWindow::ExportMiniMapWindow(wxWindow* parent, Editor& editor) : sizer->Add(tmpsizer, 0, wxALL | wxEXPAND, 5); // File name - wxString mapName(editor.map.getName().c_str(), wxConvUTF8); + wxString mapName(editor.getMap().getName().c_str(), wxConvUTF8); file_name_text_field = newd wxTextCtrl(this, wxID_ANY, mapName.BeforeLast('.'), wxDefaultPosition, wxDefaultSize); file_name_text_field->Bind(wxEVT_KEY_UP, &ExportMiniMapWindow::OnFileNameChanged, this); tmpsizer = newd wxStaticBoxSizer(wxHORIZONTAL, this, "File Name"); @@ -1226,7 +1225,7 @@ EditTownsDialog::EditTownsDialog(wxWindow* parent, Editor& editor) : wxDialog(parent, wxID_ANY, "Towns", wxDefaultPosition, wxSize(280,330)), editor(editor) { - Map& map = editor.map; + const Map& map = editor.getMap(); // Create topsizer wxSizer* sizer = newd wxBoxSizer(wxVERTICAL); @@ -1437,10 +1436,9 @@ void EditTownsDialog::OnClickRemove(wxCommandEvent& WXUNUSED(event)) } if(!town) return; - Map& map = editor.map; - for(HouseMap::iterator house_iter = map.houses.begin(); house_iter != map.houses.end(); ++house_iter) { - House* house = house_iter->second; - if(house->townid == town->getID()) { + const Map& map = editor.getMap(); + for(const auto& pair : map.houses) { + if(pair.second->townid == town->getID()) { g_gui.PopupDialog(this, "Error", "You cannot delete a town which still has houses associated with it.", wxOK); return; } @@ -1489,7 +1487,7 @@ void EditTownsDialog::OnClickOK(wxCommandEvent& WXUNUSED(event)) } } - Towns& towns = editor.map.towns; + Towns& towns = editor.getMap().towns; // Verify the newd information for(std::vector::iterator town_iter = town_list.begin(); town_iter != town_list.end(); ++town_iter) { @@ -1499,8 +1497,8 @@ void EditTownsDialog::OnClickOK(wxCommandEvent& WXUNUSED(event)) return; } if(!town->getTemplePosition().isValid() || - town->getTemplePosition().x > editor.map.getWidth() || - town->getTemplePosition().y > editor.map.getHeight()) { + town->getTemplePosition().x > editor.getMap().getWidth() || + town->getTemplePosition().y > editor.getMap().getHeight()) { wxString msg; msg << "The town " << wxstr(town->getName()) << " has an invalid temple position."; g_gui.PopupDialog(this, "Error", msg, wxOK); @@ -1516,7 +1514,7 @@ void EditTownsDialog::OnClickOK(wxCommandEvent& WXUNUSED(event)) towns.addTown(*town_iter); } town_list.clear(); - editor.map.doChange(); + editor.getMap().doChange(); EndModal(1); g_gui.RefreshPalettes(); @@ -1542,7 +1540,7 @@ GotoPositionDialog::GotoPositionDialog(wxWindow* parent, Editor& editor) : wxDialog(parent, wxID_ANY, "Go To Position", wxDefaultPosition, wxDefaultSize), editor(editor) { - Map& map = editor.map; + const Map& map = editor.getMap(); // create topsizer wxSizer* sizer = newd wxBoxSizer(wxVERTICAL); diff --git a/source/copybuffer.cpp b/source/copybuffer.cpp index 08dee1c3..039674cb 100644 --- a/source/copybuffer.cpp +++ b/source/copybuffer.cpp @@ -142,7 +142,7 @@ void CopyBuffer::cut(Editor& editor, int floor) tile_count++; Tile* tile = *it; - Tile* newtile = tile->deepCopy(editor.map); + Tile* newtile = tile->deepCopy(editor.getMap()); Tile* copied_tile = tiles->allocator(tile->getLocation()); if(tile->ground && tile->ground->isSelected()) { @@ -208,15 +208,15 @@ void CopyBuffer::cut(Editor& editor, int floor) if(g_settings.getInteger(Config::USE_AUTOMAGIC)) { action = editor.actionQueue->createAction(batch); for(PositionList::iterator it = tilestoborder.begin(); it != tilestoborder.end(); ++it) { - TileLocation* location = editor.map.createTileL(*it); + TileLocation* location = editor.getMap().createTileL(*it); if(location->get()) { - Tile* new_tile = location->get()->deepCopy(editor.map); - new_tile->borderize(&editor.map); - new_tile->wallize(&editor.map); + Tile* new_tile = location->get()->deepCopy(editor.getMap()); + new_tile->borderize(&editor.getMap()); + new_tile->wallize(&editor.getMap()); action->addChange(newd Change(new_tile)); } else { - Tile* new_tile = editor.map.allocator(location); - new_tile->borderize(&editor.map); + Tile* new_tile = editor.getMap().allocator(location); + new_tile->borderize(&editor.getMap()); if(new_tile->size()) { action->addChange(newd Change(new_tile)); } else { @@ -240,6 +240,8 @@ void CopyBuffer::paste(Editor& editor, const Position& toPosition) return; } + Map& map = editor.getMap(); + BatchAction* batchAction = editor.actionQueue->createBatch(ACTION_PASTE_TILES); Action* action = editor.actionQueue->createAction(batchAction); for(MapIterator it = tiles->begin(); it != tiles->end(); ++it) { @@ -249,17 +251,17 @@ void CopyBuffer::paste(Editor& editor, const Position& toPosition) if(!pos.isValid()) continue; - TileLocation* location = editor.map.createTileL(pos); - Tile* copy_tile = buffer_tile->deepCopy(editor.map); + TileLocation* location = map.createTileL(pos); + Tile* copy_tile = buffer_tile->deepCopy(map); Tile* old_dest_tile = location->get(); Tile* new_dest_tile = nullptr; copy_tile->setLocation(location); if(g_settings.getInteger(Config::MERGE_PASTE) || !copy_tile->ground) { if(old_dest_tile) - new_dest_tile = old_dest_tile->deepCopy(editor.map); + new_dest_tile = old_dest_tile->deepCopy(map); else - new_dest_tile = editor.map.allocator(location); + new_dest_tile = map.allocator(location); new_dest_tile->merge(copy_tile); delete copy_tile; } else { @@ -268,14 +270,14 @@ void CopyBuffer::paste(Editor& editor, const Position& toPosition) } // Add all surrounding tiles to the map, so they get borders - editor.map.createTile(pos.x-1, pos.y-1, pos.z); - editor.map.createTile(pos.x , pos.y-1, pos.z); - editor.map.createTile(pos.x+1, pos.y-1, pos.z); - editor.map.createTile(pos.x-1, pos.y , pos.z); - editor.map.createTile(pos.x+1, pos.y , pos.z); - editor.map.createTile(pos.x-1, pos.y+1, pos.z); - editor.map.createTile(pos.x , pos.y+1, pos.z); - editor.map.createTile(pos.x+1, pos.y+1, pos.z); + map.createTile(pos.x-1, pos.y-1, pos.z); + map.createTile(pos.x , pos.y-1, pos.z); + map.createTile(pos.x+1, pos.y-1, pos.z); + map.createTile(pos.x-1, pos.y , pos.z); + map.createTile(pos.x+1, pos.y , pos.z); + map.createTile(pos.x-1, pos.y+1, pos.z); + map.createTile(pos.x , pos.y+1, pos.z); + map.createTile(pos.x+1, pos.y+1, pos.z); action->addChange(newd Change(new_dest_tile)); } @@ -284,7 +286,6 @@ void CopyBuffer::paste(Editor& editor, const Position& toPosition) if(g_settings.getInteger(Config::USE_AUTOMAGIC) && g_settings.getInteger(Config::BORDERIZE_PASTE)) { action = editor.actionQueue->createAction(batchAction); TileList borderize_tiles; - Map& map = editor.map; // Go through all modified (selected) tiles (might be slow) for(MapIterator it = tiles->begin(); it != tiles->end(); ++it) { @@ -311,7 +312,7 @@ void CopyBuffer::paste(Editor& editor, const Position& toPosition) for(Tile* tile : borderize_tiles) { if(tile) { - Tile* newTile = tile->deepCopy(editor.map); + Tile* newTile = tile->deepCopy(map); newTile->borderize(&map); if(tile->ground && tile->ground->isSelected()) { diff --git a/source/editor.h b/source/editor.h index 89f8f1c1..2774cd9a 100644 --- a/source/editor.h +++ b/source/editor.h @@ -51,7 +51,6 @@ class Editor Selection selection; CopyBuffer& copybuffer; GroundBrush* replace_brush; - Map map; // The map that is being edited public: // Functions // Live Server handling @@ -76,6 +75,8 @@ class Editor // Map handling void saveMap(FileName filename, bool showdialog); // "" means default filename + Map& getMap() { return map; } + const Map& getMap() const noexcept { return map; } uint16_t getMapWidth() const noexcept { return map.width; } uint16_t getMapHeight() const noexcept { return map.height; } @@ -126,6 +127,9 @@ class Editor Editor(const Editor&); Editor& operator=(const Editor&); + +private: + Map map; }; inline void Editor::draw(const Position& offset, bool alt) { drawInternal(offset, alt, true); } diff --git a/source/gui.cpp b/source/gui.cpp index b05aab96..e605878e 100644 --- a/source/gui.cpp +++ b/source/gui.cpp @@ -482,7 +482,7 @@ void GUI::SaveCurrentMap(FileName filename, bool showdialog) if(editor) { editor->saveMap(filename, showdialog); - const std::string& filename = editor->map.getFilename(); + const std::string& filename = editor->getMap().getFilename(); const Position& position = mapTab->GetScreenCenterPosition(); std::ostringstream stream; stream << position; @@ -553,7 +553,7 @@ bool GUI::NewMap() auto *mapTab = newd MapTab(tabbook, editor); mapTab->OnSwitchEditorMode(mode); - editor->map.clearChanges(); + editor->getMap().clearChanges(); SetStatusText("Created new map"); UpdateTitle(); @@ -687,7 +687,7 @@ Map& GUI::GetCurrentMap() { Editor* editor = GetCurrentEditor(); ASSERT(editor); - return editor->map; + return editor->getMap(); } int GUI::GetOpenMapCount() diff --git a/source/live_client.cpp b/source/live_client.cpp index 659a8403..5dd4f343 100644 --- a/source/live_client.cpp +++ b/source/live_client.cpp @@ -309,7 +309,7 @@ void LiveClient::sendChanges(DirtyList& dirtyList) switch (change->getType()) { case CHANGE_TILE: { const Position& position = static_cast(change->getData())->getPosition(); - sendTile(mapWriter, editor->map.getTile(position), &position); + sendTile(mapWriter, editor->getMap().getTile(position), &position); break; } default: @@ -398,7 +398,7 @@ void LiveClient::parseHello(NetworkMessage& message) ASSERT(editor == nullptr); editor = newd Editor(g_gui.copybuffer, this); - Map& map = editor->map; + Map& map = editor->getMap(); map.setName("Live Map - " + message.read()); map.setWidth(message.read()); map.setHeight(message.read()); diff --git a/source/live_peer.cpp b/source/live_peer.cpp index 72b1df43..445e7572 100644 --- a/source/live_peer.cpp +++ b/source/live_peer.cpp @@ -254,7 +254,7 @@ void LivePeer::parseReady(NetworkMessage& message) NetworkMessage outMessage; outMessage.write(PACKET_HELLO_FROM_SERVER); - Map& map = server->getEditor()->map; + const Map& map = server->getEditor()->getMap(); outMessage.write(map.getName()); outMessage.write(map.getWidth()); outMessage.write(map.getHeight()); @@ -264,7 +264,7 @@ void LivePeer::parseReady(NetworkMessage& message) void LivePeer::parseNodeRequest(NetworkMessage& message) { - Map& map = server->getEditor()->map; + Map& map = server->getEditor()->getMap(); for(uint32_t nodes = message.read(); nodes != 0; --nodes) { uint32_t ind = message.read(); diff --git a/source/live_server.cpp b/source/live_server.cpp index cc44e155..fdf65204 100644 --- a/source/live_server.cpp +++ b/source/live_server.cpp @@ -125,7 +125,7 @@ void LiveServer::removeClient(uint32_t id) const uint32_t clientId = it->second->getClientId(); if(clientId != 0) { clientIds &= ~clientId; - editor->map.clearVisible(clientIds); + editor->getMap().clearVisible(clientIds); } clients.erase(it); @@ -197,7 +197,7 @@ void LiveServer::broadcastNodes(DirtyList& dirtyList) int32_t ndy = (ind.pos >> 4) & 0x3FFF; uint32_t floors = ind.floors; - QTreeNode* node = editor->map.getLeaf(ndx * 4, ndy * 4); + QTreeNode* node = editor->getMap().getLeaf(ndx * 4, ndy * 4); if(!node) { continue; } diff --git a/source/live_socket.cpp b/source/live_socket.cpp index 439437f2..53354efe 100644 --- a/source/live_socket.cpp +++ b/source/live_socket.cpp @@ -103,7 +103,7 @@ void LiveSocket::logMessage(const wxString& message) void LiveSocket::receiveNode(NetworkMessage& message, Editor& editor, Action* action, int32_t ndx, int32_t ndy, bool underground) { - QTreeNode* node = editor.map.getLeaf(ndx * 4, ndy * 4); + QTreeNode* node = editor.getMap().getLeaf(ndx * 4, ndy * 4); if(!node) { log->Message("Warning: Received update for unknown tile (" + std::to_string(ndx * 4) + "/" + std::to_string(ndy * 4) + "/" + (underground ? "true" : "false") + ")"); return; @@ -170,7 +170,7 @@ void LiveSocket::sendNode(uint32_t clientId, QTreeNode* node, int32_t ndx, int32 void LiveSocket::receiveFloor(NetworkMessage& message, Editor& editor, Action* action, int32_t ndx, int32_t ndy, int32_t z, QTreeNode* node, Floor* floor) { - Map& map = editor.map; + Map& map = editor.getMap(); uint16_t tileBits = message.read(); if(tileBits == 0) { @@ -292,7 +292,7 @@ Tile* LiveSocket::readTile(BinaryNode* node, Editor& editor, const Position* pos { ASSERT(node != nullptr); - Map& map = editor.map; + Map& map = editor.getMap(); uint8_t tileType; node->getByte(tileType); diff --git a/source/map_display.cpp b/source/map_display.cpp index a34473d1..e1990ce2 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -398,7 +398,7 @@ void MapCanvas::UpdatePositionStatus(int x, int y) g_gui.root->SetStatusText(ss,2); ss = ""; - Tile* tile = editor.map.getTile(map_x, map_y, floor); + Tile* tile = editor.getMap().getTile(map_x, map_y, floor); if(tile) { if(tile->spawnMonster && g_settings.getInteger(Config::SHOW_SPAWNS_MONSTER)) { ss << "Monster spawn radius: " << tile->spawnMonster->getSize(); @@ -506,7 +506,7 @@ void MapCanvas::OnMouseMove(wxMouseEvent& event) editor.draw(Position(mouse_map_x, mouse_map_y, floor), event.ShiftDown() || event.AltDown()); } } else if(brush->isDoor()) { - if(!brush->canDraw(&editor.map, Position(mouse_map_x, mouse_map_y, floor))) { + if(!brush->canDraw(&editor.getMap(), Position(mouse_map_x, mouse_map_y, floor))) { // We don't have to waste an action in this case... } else { PositionVector tilestodraw; @@ -591,45 +591,50 @@ void MapCanvas::OnMouseLeftClick(wxMouseEvent& event) void MapCanvas::OnMouseLeftDoubleClick(wxMouseEvent& event) { - if(g_settings.getInteger(Config::DOUBLECLICK_PROPERTIES)) { - int mouse_map_x, mouse_map_y; - ScreenToMap(event.GetX(), event.GetY(), &mouse_map_x, &mouse_map_y); - Tile* tile = editor.map.getTile(mouse_map_x, mouse_map_y, floor); + if(!g_settings.getInteger(Config::DOUBLECLICK_PROPERTIES)) { + return; + } - if(tile && tile->size() > 0) { - Tile* new_tile = tile->deepCopy(editor.map); - wxDialog* w = nullptr; + Map& map = editor.getMap(); + int mouse_map_x, mouse_map_y; + ScreenToMap(event.GetX(), event.GetY(), &mouse_map_x, &mouse_map_y); + const Tile* tile = map.getTile(mouse_map_x, mouse_map_y, floor); + + if(tile && tile->size() > 0) { + Tile* new_tile = tile->deepCopy(map); + wxDialog* dialog = nullptr; // Show monster spawn if(new_tile->spawnMonster && g_settings.getInteger(Config::SHOW_SPAWNS_MONSTER)) - w = newd OldPropertiesWindow(g_gui.root, &editor.map, new_tile, new_tile->spawnMonster); + dialog = newd OldPropertiesWindow(g_gui.root, &editor.getMap(), new_tile, new_tile->spawnMonster); // Show monster else if(new_tile->monster && g_settings.getInteger(Config::SHOW_MONSTERS)) - w = newd OldPropertiesWindow(g_gui.root, &editor.map, new_tile, new_tile->monster); + dialog = newd OldPropertiesWindow(g_gui.root, &editor.getMap(), new_tile, new_tile->monster); // Show npc else if(new_tile->npc && g_settings.getInteger(Config::SHOW_NPCS)) - w = newd OldPropertiesWindow(g_gui.root, &editor.map, new_tile, new_tile->npc); + dialog = newd OldPropertiesWindow(g_gui.root, &editor.getMap(), new_tile, new_tile->npc); // Show npc spawn else if(new_tile->spawnNpc && g_settings.getInteger(Config::SHOW_SPAWNS_NPC)) - w = newd OldPropertiesWindow(g_gui.root, &editor.map, new_tile, new_tile->spawnNpc); + dialog = newd OldPropertiesWindow(g_gui.root, &editor.getMap(), new_tile, new_tile->spawnNpc); else if(Item* item = new_tile->getTopItem()) { - if(editor.map.getVersion().otbm >= MAP_OTBM_4) - w = newd PropertiesWindow(g_gui.root, &editor.map, new_tile, item); + if(editor.getMap().getVersion().otbm >= MAP_OTBM_4) + dialog = newd PropertiesWindow(g_gui.root, &editor.getMap(), new_tile, item); else - w = newd OldPropertiesWindow(g_gui.root, &editor.map, new_tile, item); - } else - return; - - int ret = w->ShowModal(); - if(ret != 0) { - Action* action = editor.actionQueue->createAction(ACTION_CHANGE_PROPERTIES); - action->addChange(newd Change(new_tile)); - editor.addAction(action); + dialog = newd OldPropertiesWindow(g_gui.root, &editor.getMap(), new_tile, item); } else { - // Cancel! - delete new_tile; - } - w->Destroy(); + delete new_tile; + return; + } + + int ret = dialog->ShowModal(); + if(ret != 0) { + Action* action = editor.actionQueue->createAction(ACTION_CHANGE_PROPERTIES); + action->addChange(newd Change(new_tile)); + editor.addAction(action); + } else { + // Cancel! + delete new_tile; } + dialog->Destroy(); } } @@ -677,7 +682,7 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) ScreenToMap(event.GetX(), event.GetY(), &mouse_map_x, &mouse_map_y); if(event.ControlDown() && event.AltDown()) { - Tile* tile = editor.map.getTile(mouse_map_x, mouse_map_y, floor); + Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(tile && tile->size() > 0) { Item* item = tile->getTopItem(); if(item && item->getRAWBrush()) @@ -708,7 +713,7 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) editor.selection.updateSelectionCount(); } } else if(event.ControlDown()) { - Tile* tile = editor.map.getTile(mouse_map_x, mouse_map_y, floor); + Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(tile) { // Show monster spawn if(tile->spawnMonster && g_settings.getInteger(Config::SHOW_SPAWNS_MONSTER)) { @@ -778,7 +783,7 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) } } } else { - Tile* tile = editor.map.getTile(mouse_map_x, mouse_map_y, floor); + Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(!tile) { editor.selection.start(); // Start selection session editor.selection.clear(); // Clear out selection @@ -909,7 +914,7 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) bool will_show_spawn = false; if(brush->isSpawnMonster() || brush->isMonster()) { if(!g_settings.getBoolean(Config::SHOW_SPAWNS_MONSTER)) { - Tile* tile = editor.map.getTile(mouse_map_x, mouse_map_y, floor); + Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(!tile || !tile->spawnMonster) { will_show_spawn = true; } @@ -919,7 +924,7 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) editor.draw(Position(mouse_map_x, mouse_map_y, floor), event.ShiftDown() || event.AltDown()); if(will_show_spawn) { - Tile* tile = editor.map.getTile(mouse_map_x, mouse_map_y, floor); + Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(tile && tile->spawnMonster) { g_settings.setInteger(Config::SHOW_SPAWNS_MONSTER, true); g_gui.UpdateMenubar(); @@ -939,7 +944,7 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) bool will_show_spawn_npc = false; if(brush->isSpawnNpc() || brush->isNpc()) { if(!g_settings.getBoolean(Config::SHOW_SPAWNS_NPC)) { - Tile* tile = editor.map.getTile(mouse_map_x, mouse_map_y, floor); + Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(!tile || !tile->spawnNpc) { will_show_spawn_npc = true; } @@ -949,7 +954,7 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) editor.draw(Position(mouse_map_x, mouse_map_y, floor), event.ShiftDown() || event.AltDown()); if(will_show_spawn_npc) { - Tile* tile = editor.map.getTile(mouse_map_x, mouse_map_y, floor); + Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(tile && tile->spawnNpc) { g_settings.setInteger(Config::SHOW_SPAWNS_NPC, true); g_gui.UpdateMenubar(); @@ -959,7 +964,7 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) } else { if(brush->isGround() && event.AltDown()) { replace_dragging = true; - Tile* draw_tile = editor.map.getTile(mouse_map_x, mouse_map_y, floor); + Tile* draw_tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(draw_tile) { editor.replace_brush = draw_tile->getGroundBrush(); } else { @@ -1038,7 +1043,7 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) if(boundbox_selection) { if(mouse_map_x == last_click_map_x && mouse_map_y == last_click_map_y && event.ControlDown()) { // Mouse hasn't moved, do control+shift thingy! - Tile* tile = editor.map.getTile(mouse_map_x, mouse_map_y, floor); + Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(tile) { editor.selection.start(); // Start a selection session if(tile->isSelected()) { @@ -1164,7 +1169,7 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) //// } else { // User hasn't moved anything, meaning selection/deselection - Tile* tile = editor.map.getTile(mouse_map_x, mouse_map_y, floor); + Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(tile) { if(tile->spawnMonster && g_settings.getInteger(Config::SHOW_SPAWNS_MONSTER)) { if(!tile->spawnMonster->isSelected()) { @@ -1392,7 +1397,7 @@ void MapCanvas::OnMousePropertiesClick(wxMouseEvent& event) int mouse_map_x, mouse_map_y; ScreenToMap(event.GetX(), event.GetY(), &mouse_map_x, &mouse_map_y); - Tile* tile = editor.map.getTile(mouse_map_x, mouse_map_y, floor); + Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(g_gui.IsDrawingMode()) { g_gui.SetSelectionMode(); @@ -1464,7 +1469,7 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) if(boundbox_selection) { if(mouse_map_x == last_click_map_x && mouse_map_y == last_click_map_y && event.ControlDown()) { // Mouse hasn't move, do control+shift thingy! - Tile* tile = editor.map.getTile(mouse_map_x, mouse_map_y, floor); + Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(tile) { editor.selection.start(); // Start a selection session if(tile->isSelected()) { @@ -1489,7 +1494,7 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) case SELECT_CURRENT_FLOOR: { for(int x = last_click_map_x; x <= mouse_map_x; x++) { for(int y = last_click_map_y; y <= mouse_map_y; y ++) { - Tile* tile = editor.map.getTile(x, y, floor); + Tile* tile = editor.getMap().getTile(x, y, floor); if(!tile) continue; editor.selection.add(tile); } @@ -1518,7 +1523,7 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) for(int z = start_z; z >= end_z; z--) { for(int x = start_x; x <= end_x; x++) { for(int y = start_y; y <= end_y; y++) { - Tile* tile = editor.map.getTile(x, y, z); + Tile* tile = editor.getMap().getTile(x, y, z); if(!tile) continue; editor.selection.add(tile); } @@ -1556,7 +1561,7 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) for(int z = start_z; z >= end_z; z--) { for(int x = start_x; x <= end_x; x++) { for(int y = start_y; y <= end_y; y++) { - Tile* tile = editor.map.getTile(x, y, z); + Tile* tile = editor.getMap().getTile(x, y, z); if(!tile) continue; editor.selection.add(tile); } @@ -2039,7 +2044,7 @@ void MapCanvas::OnBrowseTile(wxCommandEvent& WXUNUSED(event)) Tile* tile = editor.selection.getSelectedTile(); if(!tile) return; ASSERT(tile->isSelected()); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); wxDialog* w = new BrowseTileWindow(g_gui.root, new_tile, wxPoint(cursor_x, cursor_y)); @@ -2062,7 +2067,7 @@ void MapCanvas::OnRotateItem(wxCommandEvent& WXUNUSED(event)) Action* action = editor.actionQueue->createAction(ACTION_ROTATE_ITEM); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); ItemVector selected_items = new_tile->getSelectedItems(); ASSERT(selected_items.size() > 0); @@ -2107,7 +2112,7 @@ void MapCanvas::OnSwitchDoor(wxCommandEvent& WXUNUSED(event)) Action* action = editor.actionQueue->createAction(ACTION_SWITCHDOOR); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); ItemVector selected_items = new_tile->getSelectedItems(); ASSERT(selected_items.size() > 0); @@ -2207,7 +2212,7 @@ void MapCanvas::OnSelectHouseBrush(wxCommandEvent& WXUNUSED(event)) return; if(tile->isHouseTile()) { - House* house = editor.map.houses.getHouse(tile->getHouseID()); + House* house = editor.getMap().houses.getHouse(tile->getHouseID()); if(house) { g_gui.house_brush->setHouse(house); g_gui.SelectBrush(g_gui.house_brush, TILESET_HOUSE); @@ -2253,18 +2258,18 @@ void MapCanvas::OnProperties(wxCommandEvent& WXUNUSED(event)) Tile* tile = editor.selection.getSelectedTile(); if(!tile) return; ASSERT(tile->isSelected()); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); wxDialog* w = nullptr; if(new_tile->spawnMonster && g_settings.getInteger(Config::SHOW_SPAWNS_MONSTER)) - w = newd OldPropertiesWindow(g_gui.root, &editor.map, new_tile, new_tile->spawnMonster); + w = newd OldPropertiesWindow(g_gui.root, &editor.getMap(), new_tile, new_tile->spawnMonster); else if(new_tile->monster && g_settings.getInteger(Config::SHOW_MONSTERS)) - w = newd OldPropertiesWindow(g_gui.root, &editor.map, new_tile, new_tile->monster); + w = newd OldPropertiesWindow(g_gui.root, &editor.getMap(), new_tile, new_tile->monster); else if(new_tile->npc && g_settings.getInteger(Config::SHOW_NPCS)) - w = newd OldPropertiesWindow(g_gui.root, &editor.map, new_tile, new_tile->npc); + w = newd OldPropertiesWindow(g_gui.root, &editor.getMap(), new_tile, new_tile->npc); else if(new_tile->spawnNpc && g_settings.getInteger(Config::SHOW_SPAWNS_NPC)) - w = newd OldPropertiesWindow(g_gui.root, &editor.map, new_tile, new_tile->spawnNpc); + w = newd OldPropertiesWindow(g_gui.root, &editor.getMap(), new_tile, new_tile->spawnNpc); else { ItemVector selected_items = new_tile->getSelectedItems(); @@ -2278,10 +2283,10 @@ void MapCanvas::OnProperties(wxCommandEvent& WXUNUSED(event)) } if(item) { - if(editor.map.getVersion().otbm >= MAP_OTBM_4) - w = newd PropertiesWindow(g_gui.root, &editor.map, new_tile, item); + if(editor.getMap().getVersion().otbm >= MAP_OTBM_4) + w = newd PropertiesWindow(g_gui.root, &editor.getMap(), new_tile, item); else - w = newd OldPropertiesWindow(g_gui.root, &editor.map, new_tile, item); + w = newd OldPropertiesWindow(g_gui.root, &editor.getMap(), new_tile, item); } else return; @@ -2572,7 +2577,7 @@ void MapCanvas::getTilesToDraw(int mouse_map_x, int mouse_map_y, int floor, Posi GroundBrush* newBrush = brush->asGround(); Position position(mouse_map_x, mouse_map_y, floor); - Tile* tile = editor.map.getTile(position); + Tile* tile = editor.getMap().getTile(position); GroundBrush* oldBrush = nullptr; if(tile) { oldBrush = tile->getGroundBrush(); @@ -2594,7 +2599,7 @@ void MapCanvas::getTilesToDraw(int mouse_map_x, int mouse_map_y, int floor, Posi } std::fill(std::begin(processed), std::end(processed), false); - floodFill(&editor.map, position, BLOCK_SIZE/2, BLOCK_SIZE/2, oldBrush, tilestodraw); + floodFill(&editor.getMap(), position, BLOCK_SIZE/2, BLOCK_SIZE/2, oldBrush, tilestodraw); } else { for(int y = -g_gui.GetBrushSize() - 1; y <= g_gui.GetBrushSize() + 1; y++) { diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index c2c8f102..d5f1b337 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -303,11 +303,11 @@ void MapDrawer::DrawMap() for(int nd_map_x = nd_start_x; nd_map_x <= nd_end_x; nd_map_x += 4) { for(int nd_map_y = nd_start_y; nd_map_y <= nd_end_y; nd_map_y += 4) { - QTreeNode* nd = editor.map.getLeaf(nd_map_x, nd_map_y); + QTreeNode* nd = editor.getMap().getLeaf(nd_map_x, nd_map_y); if(!nd) { if(!live_client) continue; - nd = editor.map.createLeaf(nd_map_x, nd_map_y); + nd = editor.getMap().createLeaf(nd_map_x, nd_map_y); nd->setVisible(false, false); } @@ -601,7 +601,7 @@ void MapDrawer::DrawDraggingShadow() getDrawPosition(pos, draw_x, draw_y); ItemVector items = tile->getSelectedItems(); - Tile* dest_tile = editor.map.getTile(pos); + Tile* dest_tile = editor.getMap().getTile(pos); for(Item* item : items) { if(dest_tile) @@ -639,7 +639,7 @@ void MapDrawer::DrawHigherFloors() int map_z = floor - 1; for(int map_x = start_x; map_x <= end_x; map_x++) { for(int map_y = start_y; map_y <= end_y; map_y++) { - Tile* tile = editor.map.getTile(map_x, map_y, map_z); + Tile* tile = editor.getMap().getTile(map_x, map_y, map_z); if(!tile) continue; int draw_x, draw_y; @@ -1008,7 +1008,7 @@ void MapDrawer::DrawBrush() int cy = (mouse_map_y) * TILE_SIZE - view_scroll_y - adjustment; int cx = (mouse_map_x) * TILE_SIZE - view_scroll_x - adjustment; MonsterBrush* monster_brush = brush->asMonster(); - if(monster_brush->canDraw(&editor.map, Position(mouse_map_x, mouse_map_y, floor))) + if(monster_brush->canDraw(&editor.getMap(), Position(mouse_map_x, mouse_map_y, floor))) BlitCreature(cx, cy, monster_brush->getType()->outfit, SOUTH, 255, 255, 255, 160); else BlitCreature(cx, cy, monster_brush->getType()->outfit, SOUTH, 255, 64, 64, 160); @@ -1018,7 +1018,7 @@ void MapDrawer::DrawBrush() int cy = (mouse_map_y) * TILE_SIZE - view_scroll_y - getFloorAdjustment(floor); int cx = (mouse_map_x) * TILE_SIZE - view_scroll_x - getFloorAdjustment(floor); NpcBrush* npcBrush = brush->asNpc(); - if(npcBrush->canDraw(&editor.map, Position(mouse_map_x, mouse_map_y, floor))) + if(npcBrush->canDraw(&editor.getMap(), Position(mouse_map_x, mouse_map_y, floor))) BlitCreature(cx, cy, npcBrush->getType()->outfit, SOUTH, 255, 255, 255, 160); else BlitCreature(cx, cy, npcBrush->getType()->outfit, SOUTH, 255, 64, 64, 160); @@ -1463,7 +1463,7 @@ void MapDrawer::DrawTile(TileLocation* location) const Position& position = location->getPosition(); if(options.show_tooltips && location->getWaypointCount() > 0) { - Waypoint* waypoint = canvas->editor.map.waypoints.getWaypoint(position); + Waypoint* waypoint = canvas->editor.getMap().waypoints.getWaypoint(position); if(waypoint) WriteTooltip(waypoint, tooltip); } @@ -1880,7 +1880,7 @@ void MapDrawer::MakeTooltip(int screenx, int screeny, const std::string& text, u void MapDrawer::getColor(Brush* brush, const Position& position, uint8_t &r, uint8_t &g, uint8_t &b) { - if(brush->canDraw(&editor.map, position)) { + if(brush->canDraw(&editor.getMap(), position)) { if(brush->isWaypoint()) { r = 0x00; g = 0xff, b = 0x00; } else { @@ -2020,7 +2020,7 @@ void MapDrawer::glColor(MapDrawer::BrushColor color) void MapDrawer::glColorCheck(Brush* brush, const Position& pos) { - if(brush->canDraw(&editor.map, pos)) + if(brush->canDraw(&editor.getMap(), pos)) glColor(COLOR_VALID); else glColor(COLOR_INVALID); diff --git a/source/map_tab.cpp b/source/map_tab.cpp index 7cf23755..d16b8a9d 100644 --- a/source/map_tab.cpp +++ b/source/map_tab.cpp @@ -84,7 +84,8 @@ MapWindow* MapTab::GetView() const wxString MapTab::GetTitle() const { wxString ss; - ss << wxstr(iref->editor->map.getName()) << (iref->editor->map.hasChanged()? "*": ""); + const Map& map = iref->editor->getMap(); + ss << wxstr(map.getName()) << (map.hasChanged() ? "*" : ""); return ss; } @@ -95,7 +96,7 @@ Editor* MapTab::GetEditor() const Map* MapTab::GetMap() const { - return &editor.map; + return &editor.getMap(); } void MapTab::VisibilityCheck() diff --git a/source/map_window.cpp b/source/map_window.cpp index b4f99baf..175d2a88 100644 --- a/source/map_window.cpp +++ b/source/map_window.cpp @@ -124,7 +124,8 @@ void MapWindow::GetViewSize(int* x, int* y) void MapWindow::FitToMap() { - SetSize(editor.map.getWidth() * TILE_SIZE, editor.map.getHeight() * TILE_SIZE, true); + const Map& map = editor.getMap(); + SetSize(map.getWidth() * TILE_SIZE, map.getHeight() * TILE_SIZE, true); } Position MapWindow::GetScreenCenterPosition() diff --git a/source/minimap_window.cpp b/source/minimap_window.cpp index ad3b7cd6..aacb1265 100644 --- a/source/minimap_window.cpp +++ b/source/minimap_window.cpp @@ -82,6 +82,7 @@ void MinimapWindow::OnPaint(wxPaintEvent& event) if(!g_gui.IsEditorOpen()) return; Editor& editor = *g_gui.GetCurrentEditor(); + const Map& map = editor.getMap(); int window_width = GetSize().GetWidth(); int window_height = GetSize().GetHeight(); @@ -102,22 +103,22 @@ void MinimapWindow::OnPaint(wxPaintEvent& event) if(start_x < 0) { start_x = 0; end_x = window_width; - } else if(end_x > editor.map.getWidth()) { - start_x = editor.map.getWidth() - window_width; - end_x = editor.map.getWidth(); + } else if(end_x > map.getWidth()) { + start_x = map.getWidth() - window_width; + end_x = map.getWidth(); } if(start_y < 0) { start_y = 0; end_y = window_height; - } else if(end_y > editor.map.getHeight()) { - start_y = editor.map.getHeight() - window_height; - end_y = editor.map.getHeight(); + } else if(end_y > map.getHeight()) { + start_y = map.getHeight() - window_height; + end_y = map.getHeight(); } start_x = std::max(start_x, 0); start_y = std::max(start_y, 0); - end_x = std::min(end_x, editor.map.getWidth()); - end_y = std::min(end_y, editor.map.getHeight()); + end_x = std::min(end_x, map.getWidth()); + end_y = std::min(end_y, map.getHeight()); last_start_x = start_x; last_start_y = start_y; @@ -129,7 +130,7 @@ void MinimapWindow::OnPaint(wxPaintEvent& event) if(g_gui.IsRenderingEnabled()) { for(int y = start_y, window_y = 0; y <= end_y; ++y, ++window_y) { for(int x = start_x, window_x = 0; x <= end_x; ++x, ++window_x) { - Tile* tile = editor.map.getTile(x, y, floor); + const Tile* tile = map.getTile(x, y, floor); if(tile) { uint8_t color = tile->getMiniMapColor(); if(color) { diff --git a/source/replace_items_window.cpp b/source/replace_items_window.cpp index 623250de..98618a83 100644 --- a/source/replace_items_window.cpp +++ b/source/replace_items_window.cpp @@ -343,7 +343,7 @@ void ReplaceItemsDialog::OnExecuteButtonClicked(wxCommandEvent& WXUNUSED(event)) ItemFinder finder(info.replaceId, (uint32_t)g_settings.getInteger(Config::REPLACE_SIZE)); // search on map - foreach_ItemOnMap(editor->map, finder, selectionOnly); + foreach_ItemOnMap(editor->getMap(), finder, selectionOnly); uint32_t total = 0; std::vector>& result = finder.result; @@ -351,7 +351,7 @@ void ReplaceItemsDialog::OnExecuteButtonClicked(wxCommandEvent& WXUNUSED(event)) if(!result.empty()) { Action* action = editor->actionQueue->createAction(ACTION_REPLACE_ITEMS); for(std::vector>::const_iterator rit = result.begin(); rit != result.end(); ++rit) { - Tile* new_tile = rit->first->deepCopy(editor->map); + Tile* new_tile = rit->first->deepCopy(editor->getMap()); int index = rit->first->getIndexOf(rit->second); ASSERT(index != wxNOT_FOUND); Item* item = new_tile->getItemAt(index); diff --git a/source/selection.cpp b/source/selection.cpp index 7d592ccf..2f3bb2a1 100644 --- a/source/selection.cpp +++ b/source/selection.cpp @@ -84,7 +84,7 @@ void Selection::add(Tile* tile, Item* item) // Make a copy of the tile with the item selected item->select(); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); item->deselect(); if(g_settings.getInteger(Config::BORDER_IS_GROUND)) { @@ -105,7 +105,7 @@ void Selection::add(Tile* tile, SpawnMonster* spawnMonster) // Make a copy of the tile with the item selected spawnMonster->select(); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); spawnMonster->deselect(); subsession->addChange(newd Change(new_tile)); @@ -121,7 +121,7 @@ void Selection::add(Tile* tile, SpawnNpc* spawnNpc) // Make a copy of the tile with the item selected spawnNpc->select(); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); spawnNpc->deselect(); subsession->addChange(newd Change(new_tile)); @@ -137,7 +137,7 @@ void Selection::add(Tile* tile, Monster* monster) // Make a copy of the tile with the item selected monster->select(); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); monster->deselect(); subsession->addChange(newd Change(new_tile)); @@ -153,7 +153,7 @@ void Selection::add(Tile* tile, Npc* npc) // Make a copy of the tile with the item selected npc->select(); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); npc->deselect(); subsession->addChange(newd Change(new_tile)); @@ -164,7 +164,7 @@ void Selection::add(Tile* tile) ASSERT(subsession); ASSERT(tile); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); new_tile->select(); subsession->addChange(newd Change(new_tile)); @@ -178,7 +178,7 @@ void Selection::remove(Tile* tile, Item* item) bool selected = item->isSelected(); item->deselect(); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); if(selected) item->select(); if(item->isBorder() && g_settings.getInteger(Config::BORDER_IS_GROUND)) new_tile->deselectGround(); @@ -193,7 +193,7 @@ void Selection::remove(Tile* tile, SpawnMonster* spawnMonster) bool selected = spawnMonster->isSelected(); spawnMonster->deselect(); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); if(selected) spawnMonster->select(); subsession->addChange(newd Change(new_tile)); @@ -207,7 +207,7 @@ void Selection::remove(Tile* tile, SpawnNpc* spawnNpc) bool selected = spawnNpc->isSelected(); spawnNpc->deselect(); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); if(selected) spawnNpc->select(); subsession->addChange(newd Change(new_tile)); @@ -221,7 +221,7 @@ void Selection::remove(Tile* tile, Monster* monster) bool selected = monster->isSelected(); monster->deselect(); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); if(selected) monster->select(); subsession->addChange(newd Change(new_tile)); @@ -235,7 +235,7 @@ void Selection::remove(Tile* tile, Npc* npc) bool selected = npc->isSelected(); npc->deselect(); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); if(selected) npc->select(); subsession->addChange(newd Change(new_tile)); @@ -245,7 +245,7 @@ void Selection::remove(Tile* tile) { ASSERT(subsession); - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); new_tile->deselect(); subsession->addChange(newd Change(new_tile)); @@ -268,7 +268,7 @@ void Selection::clear() { if(session) { for(Tile* tile : tiles) { - Tile* new_tile = tile->deepCopy(editor.map); + Tile* new_tile = tile->deepCopy(editor.getMap()); new_tile->deselect(); subsession->addChange(newd Change(new_tile)); } @@ -379,7 +379,7 @@ wxThread::ExitCode SelectionThread::Entry() for(int z = start.z; z >= end.z; --z) { for(int x = start.x; x <= end.x; ++x) { for(int y = start.y; y <= end.y; ++y) { - Tile* tile = editor.map.getTile(x, y, z); + Tile* tile = editor.getMap().getTile(x, y, z); if(!tile) continue; diff --git a/source/tile.cpp b/source/tile.cpp index e94a247c..2a08a6eb 100644 --- a/source/tile.cpp +++ b/source/tile.cpp @@ -75,7 +75,7 @@ Tile::~Tile() delete spawnNpc; } -Tile* Tile::deepCopy(BaseMap& map) +Tile* Tile::deepCopy(BaseMap& map) const { Tile* copy = map.allocator.allocateTile(location); copy->flags = flags; @@ -90,7 +90,6 @@ Tile* Tile::deepCopy(BaseMap& map) for(const Item* item : items) { copy->items.push_back(item->deepCopy()); } - return copy; } diff --git a/source/tile.h b/source/tile.h index 24450fa0..16d52af0 100644 --- a/source/tile.h +++ b/source/tile.h @@ -68,7 +68,7 @@ class Tile ~Tile(); // Argument is a the map to allocate the tile from - Tile* deepCopy(BaseMap& map); + Tile* deepCopy(BaseMap& map) const; // The location of the tile // Stores state that remains between the tile being moved (like house exits) From 6ddc115ee0dc8837eece50d409ce7853b510268c Mon Sep 17 00:00:00 2001 From: Beats Date: Wed, 5 Apr 2023 21:50:25 -0400 Subject: [PATCH 18/45] Changes and cleanup --- source/action.cpp | 18 ++- source/common_windows.cpp | 2 +- source/copybuffer.cpp | 25 ++-- source/editor.h | 4 +- source/gui.cpp | 18 ++- source/main_menubar.cpp | 10 +- source/map_display.cpp | 297 +++++++++++++++++++------------------- source/map_drawer.cpp | 5 +- 8 files changed, 194 insertions(+), 185 deletions(-) diff --git a/source/action.cpp b/source/action.cpp index 589962de..173bcd00 100644 --- a/source/action.cpp +++ b/source/action.cpp @@ -151,7 +151,8 @@ size_t Action::memsize() const void Action::commit(DirtyList* dirty_list) { - editor.selection.start(Selection::INTERNAL); + Selection& selection = editor.getSelection(); + selection.start(Selection::INTERNAL); ChangeList::const_iterator it = changes.begin(); while(it != changes.end()) { Change* c = *it; @@ -184,7 +185,7 @@ void Action::commit(DirtyList* dirty_list) //std::cout << "\tSwitched tile at " << pos.x << ";" << pos.y << ";" << pos.z << " from " << (void*)oldtile << " to " << *data << std::endl; if(newtile->isSelected()) - editor.selection.addInternal(newtile); + selection.addInternal(newtile); if(oldtile) { if(newtile->getHouseID() != oldtile->getHouseID()) { @@ -226,7 +227,7 @@ void Action::commit(DirtyList* dirty_list) //oldtile->update(); if(oldtile->isSelected()) - editor.selection.removeInternal(oldtile); + selection.removeInternal(oldtile); *data = oldtile; } else { @@ -299,7 +300,7 @@ void Action::commit(DirtyList* dirty_list) } ++it; } - editor.selection.finish(Selection::INTERNAL); + selection.finish(Selection::INTERNAL); commited = true; } @@ -308,7 +309,8 @@ void Action::undo(DirtyList* dirty_list) if(changes.empty()) return; - editor.selection.start(Selection::INTERNAL); + Selection& selection = editor.getSelection(); + selection.start(Selection::INTERNAL); ChangeList::reverse_iterator it = changes.rbegin(); while(it != changes.rend()) { @@ -338,9 +340,9 @@ void Action::undo(DirtyList* dirty_list) if(oldtile->isSelected()) - editor.selection.addInternal(oldtile); + selection.addInternal(oldtile); if(newtile->isSelected()) - editor.selection.removeInternal(newtile); + selection.removeInternal(newtile); if(newtile->getHouseID() != oldtile->getHouseID()) { // oooooomggzzz we need to remove it from the appropriate house! @@ -435,7 +437,7 @@ void Action::undo(DirtyList* dirty_list) } ++it; } - editor.selection.finish(Selection::INTERNAL); + selection.finish(Selection::INTERNAL); commited = false; } diff --git a/source/common_windows.cpp b/source/common_windows.cpp index b0865cdf..1d18d7af 100644 --- a/source/common_windows.cpp +++ b/source/common_windows.cpp @@ -265,7 +265,7 @@ void MapPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) wxArrayString warnings; // Switch version - g_gui.GetCurrentEditor()->selection.clear(); + g_gui.GetCurrentEditor()->getSelection().clear(); g_gui.GetCurrentEditor()->actionQueue->clear(); if(new_ver.client < old_ver.client) { diff --git a/source/copybuffer.cpp b/source/copybuffer.cpp index 039674cb..e0fa1487 100644 --- a/source/copybuffer.cpp +++ b/source/copybuffer.cpp @@ -59,7 +59,7 @@ void CopyBuffer::clear() void CopyBuffer::copy(Editor& editor, int floor) { - if(editor.selection.size() == 0) { + if(!editor.hasSelection()) { g_gui.SetStatusText("No tiles to copy."); return; } @@ -71,10 +71,9 @@ void CopyBuffer::copy(Editor& editor, int floor) int item_count = 0; copyPos = Position(0xFFFF, 0xFFFF, floor); - for(TileSet::iterator it = editor.selection.begin(); it != editor.selection.end(); ++it) { + for(Tile* tile : editor.getSelection()) { ++tile_count; - Tile* tile = *it; TileLocation* newlocation = tiles->createTileL(tile->getPosition()); Tile* copied_tile = tiles->allocator(newlocation); @@ -121,7 +120,7 @@ void CopyBuffer::copy(Editor& editor, int floor) void CopyBuffer::cut(Editor& editor, int floor) { - if(editor.selection.size() == 0) { + if(!editor.hasSelection()) { g_gui.SetStatusText("No tiles to cut."); return; } @@ -129,6 +128,7 @@ void CopyBuffer::cut(Editor& editor, int floor) clear(); tiles = newd BaseMap(); + Map& map = editor.getMap(); int tile_count = 0; int item_count = 0; copyPos = Position(0xFFFF, 0xFFFF, floor); @@ -138,11 +138,10 @@ void CopyBuffer::cut(Editor& editor, int floor) PositionList tilestoborder; - for(TileSet::iterator it = editor.selection.begin(); it != editor.selection.end(); ++it) { + for(Tile* tile : editor.getSelection()) { tile_count++; - Tile* tile = *it; - Tile* newtile = tile->deepCopy(editor.getMap()); + Tile* newtile = tile->deepCopy(map); Tile* copied_tile = tiles->allocator(tile->getLocation()); if(tile->ground && tile->ground->isSelected()) { @@ -208,15 +207,15 @@ void CopyBuffer::cut(Editor& editor, int floor) if(g_settings.getInteger(Config::USE_AUTOMAGIC)) { action = editor.actionQueue->createAction(batch); for(PositionList::iterator it = tilestoborder.begin(); it != tilestoborder.end(); ++it) { - TileLocation* location = editor.getMap().createTileL(*it); + TileLocation* location = map.createTileL(*it); if(location->get()) { - Tile* new_tile = location->get()->deepCopy(editor.getMap()); - new_tile->borderize(&editor.getMap()); - new_tile->wallize(&editor.getMap()); + Tile* new_tile = location->get()->deepCopy(map); + new_tile->borderize(&map); + new_tile->wallize(&map); action->addChange(newd Change(new_tile)); } else { - Tile* new_tile = editor.getMap().allocator(location); - new_tile->borderize(&editor.getMap()); + Tile* new_tile = map.allocator(location); + new_tile->borderize(&map); if(new_tile->size()) { action->addChange(newd Change(new_tile)); } else { diff --git a/source/editor.h b/source/editor.h index 2774cd9a..ee1a8032 100644 --- a/source/editor.h +++ b/source/editor.h @@ -48,7 +48,6 @@ class Editor public: // Public members ActionQueue* actionQueue; - Selection selection; CopyBuffer& copybuffer; GroundBrush* replace_brush; @@ -92,6 +91,8 @@ class Editor void addAction(Action* action, int stacking_delay = 0); // Selection + Selection& getSelection() { return selection; } + const Selection& getSelection() const { return selection; } bool hasSelection() const noexcept { return selection.size() != 0; } // Some simple actions that work on the map (these will work through the undo queue) // Moves the selected area by the offset @@ -130,6 +131,7 @@ class Editor private: Map map; + Selection selection; }; inline void Editor::draw(const Position& offset, bool alt) { drawInternal(offset, alt, true); } diff --git a/source/gui.cpp b/source/gui.cpp index e605878e..92a7aa1f 100644 --- a/source/gui.cpp +++ b/source/gui.cpp @@ -1292,9 +1292,10 @@ void GUI::PreparePaste() Editor* editor = GetCurrentEditor(); if (editor) { SetSelectionMode(); - editor->selection.start(); - editor->selection.clear(); - editor->selection.finish(); + Selection& selection = editor->getSelection(); + selection.start(); + selection.clear(); + selection.finish(); StartPasting(); RefreshView(); } @@ -1333,7 +1334,7 @@ bool GUI::DoUndo() Editor* editor = GetCurrentEditor(); if(editor && editor->actionQueue->canUndo()) { editor->actionQueue->undo(); - if(editor->selection.size() > 0) + if(editor->hasSelection()) SetSelectionMode(); SetStatusText("Undo action"); UpdateMinimap(); @@ -1349,7 +1350,7 @@ bool GUI::DoRedo() Editor* editor = GetCurrentEditor(); if(editor && editor->actionQueue->canRedo()) { editor->actionQueue->redo(); - if(editor->selection.size() > 0) + if(editor->hasSelection()) SetSelectionMode(); SetStatusText("Redo action"); UpdateMinimap(); @@ -1485,9 +1486,10 @@ void GUI::SetDrawingMode() continue; Editor* editor = mapTab->GetEditor(); - editor->selection.start(); - editor->selection.clear(); - editor->selection.finish(); + Selection& selection = editor->getSelection(); + selection.start(); + selection.clear(); + selection.finish(); al.insert(mapTab); } } diff --git a/source/main_menubar.cpp b/source/main_menubar.cpp index 746d0a90..18b5241e 100644 --- a/source/main_menubar.cpp +++ b/source/main_menubar.cpp @@ -1292,7 +1292,7 @@ void MainMenuBar::OnMapRemoveItems(wxCommandEvent& WXUNUSED(event)) if(dialog.ShowModal() == wxID_OK) { uint16_t itemid = dialog.getResultID(); - g_gui.GetCurrentEditor()->selection.clear(); + g_gui.GetCurrentEditor()->getSelection().clear(); g_gui.GetCurrentEditor()->actionQueue->clear(); OnMapRemoveItems::RemoveItemCondition condition(itemid); @@ -1335,7 +1335,7 @@ void MainMenuBar::OnMapRemoveCorpses(wxCommandEvent& WXUNUSED(event)) int ok = g_gui.PopupDialog("Remove Corpses", "Do you want to remove all corpses from the map?", wxYES | wxNO); if(ok == wxID_YES) { - g_gui.GetCurrentEditor()->selection.clear(); + g_gui.GetCurrentEditor()->getSelection().clear(); g_gui.GetCurrentEditor()->actionQueue->clear(); OnMapRemoveCorpses::condition func; @@ -1409,7 +1409,7 @@ void MainMenuBar::OnMapRemoveUnreachable(wxCommandEvent& WXUNUSED(event)) int ok = g_gui.PopupDialog("Remove Unreachable Tiles", "Do you want to remove all unreachable items from the map?", wxYES | wxNO); if(ok == wxID_YES) { - g_gui.GetCurrentEditor()->selection.clear(); + g_gui.GetCurrentEditor()->getSelection().clear(); g_gui.GetCurrentEditor()->actionQueue->clear(); OnMapRemoveUnreachable::condition func; @@ -1437,7 +1437,7 @@ void MainMenuBar::OnMapRemoveEmptyMonsterSpawns(wxCommandEvent& WXUNUSED(event)) int ok = g_gui.PopupDialog("Remove Empty Monsters Spawns", "Do you want to remove all empty monsters spawns from the map?", wxYES | wxNO); if (ok == wxID_YES) { Editor* editor = g_gui.GetCurrentEditor(); - editor->selection.clear(); + editor->getSelection().clear(); g_gui.CreateLoadBar("Searching map for empty monsters spawns to remove..."); @@ -1511,7 +1511,7 @@ void MainMenuBar::OnMapRemoveEmptyNpcSpawns(wxCommandEvent& WXUNUSED(event)) int ok = g_gui.PopupDialog("Remove Empty Npcs Spawns", "Do you want to remove all empty npcs spawns from the map?", wxYES | wxNO); if (ok == wxID_YES) { Editor* editor = g_gui.GetCurrentEditor(); - editor->selection.clear(); + editor->getSelection().clear(); g_gui.CreateLoadBar("Searching map for empty npcs spawns to remove..."); diff --git a/source/map_display.cpp b/source/map_display.cpp index e1990ce2..8aa44f44 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -681,6 +681,8 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) int mouse_map_x, mouse_map_y; ScreenToMap(event.GetX(), event.GetY(), &mouse_map_x, &mouse_map_y); + Selection& selection = editor.getSelection(); + if(event.ControlDown() && event.AltDown()) { Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(tile && tile->size() > 0) { @@ -707,121 +709,121 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) boundbox_selection = true; if(!event.ControlDown()) { - editor.selection.start(); // Start selection session - editor.selection.clear(); // Clear out selection - editor.selection.finish(); // End selection session - editor.selection.updateSelectionCount(); + selection.start(); // Start selection session + selection.clear(); // Clear out selection + selection.finish(); // End selection session + selection.updateSelectionCount(); } } else if(event.ControlDown()) { Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(tile) { // Show monster spawn if(tile->spawnMonster && g_settings.getInteger(Config::SHOW_SPAWNS_MONSTER)) { - editor.selection.start(); // Start selection session + selection.start(); // Start selection session if(tile->spawnMonster->isSelected()) { - editor.selection.remove(tile, tile->spawnMonster); + selection.remove(tile, tile->spawnMonster); } else { - editor.selection.add(tile, tile->spawnMonster); + selection.add(tile, tile->spawnMonster); } - editor.selection.finish(); // Finish selection session - editor.selection.updateSelectionCount(); + selection.finish(); // Finish selection session + selection.updateSelectionCount(); // Show monsters } else if(tile->monster && g_settings.getInteger(Config::SHOW_MONSTERS)) { - editor.selection.start(); // Start selection session + selection.start(); // Start selection session if(tile->monster->isSelected()) { - editor.selection.remove(tile, tile->monster); + selection.remove(tile, tile->monster); } else { - editor.selection.add(tile, tile->monster); + selection.add(tile, tile->monster); } - editor.selection.finish(); // Finish selection session - editor.selection.updateSelectionCount(); + selection.finish(); // Finish selection session + selection.updateSelectionCount(); } else { Item* item = tile->getTopItem(); if(item) { - editor.selection.start(); // Start selection session + selection.start(); // Start selection session if(item->isSelected()) { - editor.selection.remove(tile, item); + selection.remove(tile, item); } else { - editor.selection.add(tile, item); + selection.add(tile, item); } - editor.selection.finish(); // Finish selection session - editor.selection.updateSelectionCount(); + selection.finish(); // Finish selection session + selection.updateSelectionCount(); } } // Show npcs if(tile->spawnNpc && g_settings.getInteger(Config::SHOW_SPAWNS_NPC)) { - editor.selection.start(); // Start selection session + selection.start(); // Start selection session if(tile->spawnNpc->isSelected()) { - editor.selection.remove(tile, tile->spawnNpc); + selection.remove(tile, tile->spawnNpc); } else { - editor.selection.add(tile, tile->spawnNpc); + selection.add(tile, tile->spawnNpc); } - editor.selection.finish(); // Finish selection session - editor.selection.updateSelectionCount(); + selection.finish(); // Finish selection session + selection.updateSelectionCount(); } else if(tile->npc && g_settings.getInteger(Config::SHOW_NPCS)) { - editor.selection.start(); // Start selection session + selection.start(); // Start selection session if(tile->npc->isSelected()) { - editor.selection.remove(tile, tile->npc); + selection.remove(tile, tile->npc); } else { - editor.selection.add(tile, tile->npc); + selection.add(tile, tile->npc); } - editor.selection.finish(); // Finish selection session - editor.selection.updateSelectionCount(); + selection.finish(); // Finish selection session + selection.updateSelectionCount(); // Show npc spawn } else { Item* item = tile->getTopItem(); if(item) { - editor.selection.start(); // Start selection session + selection.start(); // Start selection session if(item->isSelected()) { - editor.selection.remove(tile, item); + selection.remove(tile, item); } else { - editor.selection.add(tile, item); + selection.add(tile, item); } - editor.selection.finish(); // Finish selection session - editor.selection.updateSelectionCount(); + selection.finish(); // Finish selection session + selection.updateSelectionCount(); } } } } else { Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(!tile) { - editor.selection.start(); // Start selection session - editor.selection.clear(); // Clear out selection - editor.selection.finish(); // End selection session - editor.selection.updateSelectionCount(); + selection.start(); // Start selection session + selection.clear(); // Clear out selection + selection.finish(); // End selection session + selection.updateSelectionCount(); } else if(tile->isSelected()) { dragging = true; drag_start_x = mouse_map_x; drag_start_y = mouse_map_y; drag_start_z = floor; } else { - editor.selection.start(); // Start a selection session - editor.selection.clear(); - editor.selection.commit(); + selection.start(); // Start a selection session + selection.clear(); + selection.commit(); // Show monster spawn if(tile->spawnMonster && g_settings.getInteger(Config::SHOW_SPAWNS_MONSTER)) { - editor.selection.add(tile, tile->spawnMonster); + selection.add(tile, tile->spawnMonster); dragging = true; drag_start_x = mouse_map_x; drag_start_y = mouse_map_y; drag_start_z = floor; // Show monsters } else if(tile->monster && g_settings.getInteger(Config::SHOW_MONSTERS)) { - editor.selection.add(tile, tile->monster); + selection.add(tile, tile->monster); dragging = true; drag_start_x = mouse_map_x; drag_start_y = mouse_map_y; drag_start_z = floor; // Show npc spawns } else if(tile->spawnNpc && g_settings.getInteger(Config::SHOW_SPAWNS_NPC)) { - editor.selection.add(tile, tile->spawnNpc); + selection.add(tile, tile->spawnNpc); dragging = true; drag_start_x = mouse_map_x; drag_start_y = mouse_map_y; drag_start_z = floor; // Show npcs } else if(tile->npc && g_settings.getInteger(Config::SHOW_NPCS)) { - editor.selection.add(tile, tile->npc); + selection.add(tile, tile->npc); dragging = true; drag_start_x = mouse_map_x; drag_start_y = mouse_map_y; @@ -829,15 +831,15 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) } else { Item* item = tile->getTopItem(); if(item) { - editor.selection.add(tile, item); + selection.add(tile, item); dragging = true; drag_start_x = mouse_map_x; drag_start_y = mouse_map_y; drag_start_z = floor; } } - editor.selection.finish(); // Finish the selection session - editor.selection.updateSelectionCount(); + selection.finish(); // Finish the selection session + selection.updateSelectionCount(); } } } while(false); @@ -1032,6 +1034,7 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) int mouse_map_x, mouse_map_y; ScreenToMap(event.GetX(), event.GetY(), &mouse_map_x, &mouse_map_y); + Selection& selection = editor.getSelection(); int move_x = last_click_map_x - mouse_map_x; int move_y = last_click_map_y - mouse_map_y; int move_z = last_click_map_z - floor; @@ -1045,14 +1048,14 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) // Mouse hasn't moved, do control+shift thingy! Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(tile) { - editor.selection.start(); // Start a selection session + selection.start(); // Start a selection session if(tile->isSelected()) { - editor.selection.remove(tile); + selection.remove(tile); } else { - editor.selection.add(tile); + selection.add(tile); } - editor.selection.finish(); // Finish the selection session - editor.selection.updateSelectionCount(); + selection.finish(); // Finish the selection session + selection.updateSelectionCount(); } } else { // The cursor has moved, do some boundboxing! @@ -1155,15 +1158,15 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) ASSERT(cleared == width); ASSERT(remainder == 0); - editor.selection.start(); // Start a selection session + selection.start(); // Start a selection session for(std::vector::iterator iter = threads.begin(); iter != threads.end(); ++iter) { (*iter)->Execute(); } for(std::vector::iterator iter = threads.begin(); iter != threads.end(); ++iter) { - editor.selection.join(*iter); + selection.join(*iter); } - editor.selection.finish(); // Finish the selection session - editor.selection.updateSelectionCount(); + selection.finish(); // Finish the selection session + selection.updateSelectionCount(); } } else if(event.ControlDown()) { //// @@ -1173,39 +1176,39 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) if(tile) { if(tile->spawnMonster && g_settings.getInteger(Config::SHOW_SPAWNS_MONSTER)) { if(!tile->spawnMonster->isSelected()) { - editor.selection.start(); // Start a selection session - editor.selection.add(tile, tile->spawnMonster); - editor.selection.finish(); // Finish the selection session - editor.selection.updateSelectionCount(); + selection.start(); // Start a selection session + selection.add(tile, tile->spawnMonster); + selection.finish(); // Finish the selection session + selection.updateSelectionCount(); } } else if(tile->monster && g_settings.getInteger(Config::SHOW_MONSTERS)) { if(!tile->monster->isSelected()) { - editor.selection.start(); // Start a selection session - editor.selection.add(tile, tile->monster); - editor.selection.finish(); // Finish the selection session - editor.selection.updateSelectionCount(); + selection.start(); // Start a selection session + selection.add(tile, tile->monster); + selection.finish(); // Finish the selection session + selection.updateSelectionCount(); } } else if(tile->spawnNpc && g_settings.getInteger(Config::SHOW_SPAWNS_NPC)) { if(!tile->spawnNpc->isSelected()) { - editor.selection.start(); // Start a selection session - editor.selection.add(tile, tile->spawnNpc); - editor.selection.finish(); // Finish the selection session - editor.selection.updateSelectionCount(); + selection.start(); // Start a selection session + selection.add(tile, tile->spawnNpc); + selection.finish(); // Finish the selection session + selection.updateSelectionCount(); } } else if(tile->npc && g_settings.getInteger(Config::SHOW_NPCS)) { if(!tile->npc->isSelected()) { - editor.selection.start(); // Start a selection session - editor.selection.add(tile, tile->monster); - editor.selection.finish(); // Finish the selection session - editor.selection.updateSelectionCount(); + selection.start(); // Start a selection session + selection.add(tile, tile->monster); + selection.finish(); // Finish the selection session + selection.updateSelectionCount(); } } else { Item* item = tile->getTopItem(); if(item && !item->isSelected()) { - editor.selection.start(); // Start a selection session - editor.selection.add(tile, item); - editor.selection.finish(); // Finish the selection session - editor.selection.updateSelectionCount(); + selection.start(); // Start a selection session + selection.add(tile, item); + selection.finish(); // Finish the selection session + selection.updateSelectionCount(); } } } @@ -1405,43 +1408,45 @@ void MapCanvas::OnMousePropertiesClick(wxMouseEvent& event) EndPasting(); + Selection& selection = editor.getSelection(); + boundbox_selection = false; if(event.ShiftDown()) { boundbox_selection = true; if(!event.ControlDown()) { - editor.selection.start(); // Start selection session - editor.selection.clear(); // Clear out selection - editor.selection.finish(); // End selection session - editor.selection.updateSelectionCount(); + selection.start(); // Start selection session + selection.clear(); // Clear out selection + selection.finish(); // End selection session + selection.updateSelectionCount(); } } else if(!tile) { - editor.selection.start(); // Start selection session - editor.selection.clear(); // Clear out selection - editor.selection.finish(); // End selection session - editor.selection.updateSelectionCount(); + selection.start(); // Start selection session + selection.clear(); // Clear out selection + selection.finish(); // End selection session + selection.updateSelectionCount(); } else if(tile->isSelected()) { // Do nothing! } else { - editor.selection.start(); // Start a selection session - editor.selection.clear(); - editor.selection.commit(); + selection.start(); // Start a selection session + selection.clear(); + selection.commit(); if(tile->spawnMonster && g_settings.getInteger(Config::SHOW_SPAWNS_MONSTER)) { - editor.selection.add(tile, tile->spawnMonster); + selection.add(tile, tile->spawnMonster); } else if(tile->monster && g_settings.getInteger(Config::SHOW_MONSTERS)) { - editor.selection.add(tile, tile->monster); + selection.add(tile, tile->monster); } else if(tile->npc && g_settings.getInteger(Config::SHOW_NPCS)) { - editor.selection.add(tile, tile->npc); + selection.add(tile, tile->npc); } else if(tile->spawnNpc && g_settings.getInteger(Config::SHOW_SPAWNS_NPC)) { - editor.selection.add(tile, tile->spawnNpc); + selection.add(tile, tile->spawnNpc); } else { Item* item = tile->getTopItem(); if(item) { - editor.selection.add(tile, item); + selection.add(tile, item); } } - editor.selection.finish(); // Finish the selection session - editor.selection.updateSelectionCount(); + selection.finish(); // Finish the selection session + selection.updateSelectionCount(); } last_click_x = int(event.GetX()*zoom); @@ -1467,18 +1472,19 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) } if(boundbox_selection) { + Selection& selection = editor.getSelection(); if(mouse_map_x == last_click_map_x && mouse_map_y == last_click_map_y && event.ControlDown()) { // Mouse hasn't move, do control+shift thingy! Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(tile) { - editor.selection.start(); // Start a selection session + selection.start(); // Start a selection session if(tile->isSelected()) { - editor.selection.remove(tile); + selection.remove(tile); } else { - editor.selection.add(tile); + selection.add(tile); } - editor.selection.finish(); // Finish the selection session - editor.selection.updateSelectionCount(); + selection.finish(); // Finish the selection session + selection.updateSelectionCount(); } } else { // The cursor has moved, do some boundboxing! @@ -1489,14 +1495,14 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) int tmp = mouse_map_y; mouse_map_y = last_click_map_y; last_click_map_y = tmp; } - editor.selection.start(); // Start a selection session + selection.start(); // Start a selection session switch(g_settings.getInteger(Config::SELECTION_TYPE)) { case SELECT_CURRENT_FLOOR: { for(int x = last_click_map_x; x <= mouse_map_x; x++) { for(int y = last_click_map_y; y <= mouse_map_y; y ++) { Tile* tile = editor.getMap().getTile(x, y, floor); if(!tile) continue; - editor.selection.add(tile); + selection.add(tile); } } break; @@ -1525,8 +1531,8 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) for(int y = start_y; y <= end_y; y++) { Tile* tile = editor.getMap().getTile(x, y, z); if(!tile) continue; - editor.selection.add(tile); - } + selection.add(tile); + } } if(z <= GROUND_LAYER && g_settings.getInteger(Config::COMPENSATED_SELECT)) { start_x++; start_y++; @@ -1563,7 +1569,7 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) for(int y = start_y; y <= end_y; y++) { Tile* tile = editor.getMap().getTile(x, y, z); if(!tile) continue; - editor.selection.add(tile); + selection.add(tile); } } if(z <= GROUND_LAYER && g_settings.getInteger(Config::COMPENSATED_SELECT)) { @@ -1574,8 +1580,8 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) break; } } - editor.selection.finish(); // Finish the selection session - editor.selection.updateSelectionCount(); + selection.finish(); // Finish the selection session + selection.updateSelectionCount(); } } else if(event.ControlDown()) { // Nothing @@ -1965,12 +1971,11 @@ void MapCanvas::OnDelete(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnCopyPosition(wxCommandEvent& WXUNUSED(event)) { - if(editor.selection.size() == 0) + if(editor.hasSelection()) return; - Position minPos = editor.selection.minPosition(); - Position maxPos = editor.selection.maxPosition(); - + Position minPos = editor.getSelection().minPosition(); + Position maxPos = editor.getSelection().maxPosition(); if(minPos != maxPos) { posToClipboard(minPos.x, minPos.y, minPos.z, maxPos.x, maxPos.y, maxPos.z); } else { @@ -1981,10 +1986,10 @@ void MapCanvas::OnCopyPosition(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnCopyServerId(wxCommandEvent& WXUNUSED(event)) { - ASSERT(editor.selection.size() == 1); + ASSERT(editor.getSelection().size() == 1); if(wxTheClipboard->Open()) { - Tile* tile = editor.selection.getSelectedTile(); + Tile* tile = editor.getSelection().getSelectedTile(); ItemVector selected_items = tile->getSelectedItems(); ASSERT(selected_items.size() == 1); @@ -2000,10 +2005,10 @@ void MapCanvas::OnCopyServerId(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnCopyClientId(wxCommandEvent& WXUNUSED(event)) { - ASSERT(editor.selection.size() == 1); + ASSERT(editor.getSelection().size() == 1); if(wxTheClipboard->Open()) { - Tile* tile = editor.selection.getSelectedTile(); + Tile* tile = editor.getSelection().getSelectedTile(); ItemVector selected_items = tile->getSelectedItems(); ASSERT(selected_items.size() == 1); @@ -2019,10 +2024,10 @@ void MapCanvas::OnCopyClientId(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnCopyName(wxCommandEvent& WXUNUSED(event)) { - ASSERT(editor.selection.size() == 1); + ASSERT(editor.getSelection().size() == 1); if(wxTheClipboard->Open()) { - Tile* tile = editor.selection.getSelectedTile(); + Tile* tile = editor.getSelection().getSelectedTile(); ItemVector selected_items = tile->getSelectedItems(); ASSERT(selected_items.size() == 1); @@ -2038,10 +2043,10 @@ void MapCanvas::OnCopyName(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnBrowseTile(wxCommandEvent& WXUNUSED(event)) { - if(editor.selection.size() != 1) + if(editor.getSelection().size() != 1) return; - Tile* tile = editor.selection.getSelectedTile(); + Tile* tile = editor.getSelection().getSelectedTile(); if(!tile) return; ASSERT(tile->isSelected()); Tile* new_tile = tile->deepCopy(editor.getMap()); @@ -2063,7 +2068,7 @@ void MapCanvas::OnBrowseTile(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnRotateItem(wxCommandEvent& WXUNUSED(event)) { - Tile* tile = editor.selection.getSelectedTile(); + Tile* tile = editor.getSelection().getSelectedTile(); Action* action = editor.actionQueue->createAction(ACTION_ROTATE_ITEM); @@ -2082,7 +2087,7 @@ void MapCanvas::OnRotateItem(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnGotoDestination(wxCommandEvent& WXUNUSED(event)) { - Tile* tile = editor.selection.getSelectedTile(); + Tile* tile = editor.getSelection().getSelectedTile(); ItemVector selected_items = tile->getSelectedItems(); ASSERT(selected_items.size() > 0); Teleport* teleport = dynamic_cast(selected_items.front()); @@ -2094,7 +2099,7 @@ void MapCanvas::OnGotoDestination(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnCopyDestination(wxCommandEvent& WXUNUSED(event)) { - Tile* tile = editor.selection.getSelectedTile(); + Tile* tile = editor.getSelection().getSelectedTile(); ItemVector selected_items = tile->getSelectedItems(); ASSERT(selected_items.size() > 0); @@ -2108,7 +2113,7 @@ void MapCanvas::OnCopyDestination(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnSwitchDoor(wxCommandEvent& WXUNUSED(event)) { - Tile* tile = editor.selection.getSelectedTile(); + Tile* tile = editor.getSelection().getSelectedTile(); Action* action = editor.actionQueue->createAction(ACTION_SWITCHDOOR); @@ -2127,8 +2132,8 @@ void MapCanvas::OnSwitchDoor(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnSelectRAWBrush(wxCommandEvent& WXUNUSED(event)) { - if(editor.selection.size() != 1) return; - Tile* tile = editor.selection.getSelectedTile(); + if(editor.getSelection().size() != 1) return; + Tile* tile = editor.getSelection().getSelectedTile(); if(!tile) return; Item* item = tile->getTopSelectedItem(); @@ -2138,8 +2143,8 @@ void MapCanvas::OnSelectRAWBrush(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnSelectGroundBrush(wxCommandEvent& WXUNUSED(event)) { - if(editor.selection.size() != 1) return; - Tile* tile = editor.selection.getSelectedTile(); + if(editor.getSelection().size() != 1) return; + Tile* tile = editor.getSelection().getSelectedTile(); if(!tile) return; GroundBrush* bb = tile->getGroundBrush(); @@ -2149,8 +2154,8 @@ void MapCanvas::OnSelectGroundBrush(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnSelectDoodadBrush(wxCommandEvent& WXUNUSED(event)) { - if(editor.selection.size() != 1) return; - Tile* tile = editor.selection.getSelectedTile(); + if(editor.getSelection().size() != 1) return; + Tile* tile = editor.getSelection().getSelectedTile(); if(!tile) return; Item* item = tile->getTopSelectedItem(); @@ -2160,8 +2165,8 @@ void MapCanvas::OnSelectDoodadBrush(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnSelectDoorBrush(wxCommandEvent& WXUNUSED(event)) { - if(editor.selection.size() != 1) return; - Tile* tile = editor.selection.getSelectedTile(); + if(editor.getSelection().size() != 1) return; + Tile* tile = editor.getSelection().getSelectedTile(); if(!tile) return; Item* item = tile->getTopSelectedItem(); @@ -2171,8 +2176,8 @@ void MapCanvas::OnSelectDoorBrush(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnSelectWallBrush(wxCommandEvent& WXUNUSED(event)) { - if(editor.selection.size() != 1) return; - Tile* tile = editor.selection.getSelectedTile(); + if(editor.getSelection().size() != 1) return; + Tile* tile = editor.getSelection().getSelectedTile(); if(!tile) return; Item* wall = tile->getWall(); WallBrush* wb = wall->getWallBrush(); @@ -2183,8 +2188,8 @@ void MapCanvas::OnSelectWallBrush(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnSelectCarpetBrush(wxCommandEvent& WXUNUSED(event)) { - if(editor.selection.size() != 1) return; - Tile* tile = editor.selection.getSelectedTile(); + if(editor.getSelection().size() != 1) return; + Tile* tile = editor.getSelection().getSelectedTile(); if(!tile) return; Item* wall = tile->getCarpet(); CarpetBrush* cb = wall->getCarpetBrush(); @@ -2195,8 +2200,8 @@ void MapCanvas::OnSelectCarpetBrush(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnSelectTableBrush(wxCommandEvent& WXUNUSED(event)) { - if(editor.selection.size() != 1) return; - Tile* tile = editor.selection.getSelectedTile(); + if(editor.getSelection().size() != 1) return; + Tile* tile = editor.getSelection().getSelectedTile(); if(!tile) return; Item* wall = tile->getTable(); TableBrush* tb = wall->getTableBrush(); @@ -2207,7 +2212,7 @@ void MapCanvas::OnSelectTableBrush(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnSelectHouseBrush(wxCommandEvent& WXUNUSED(event)) { - Tile* tile = editor.selection.getSelectedTile(); + Tile* tile = editor.getSelection().getSelectedTile(); if(!tile) return; @@ -2222,7 +2227,7 @@ void MapCanvas::OnSelectHouseBrush(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnSelectMonsterBrush(wxCommandEvent& WXUNUSED(event)) { - Tile* tile = editor.selection.getSelectedTile(); + Tile* tile = editor.getSelection().getSelectedTile(); if(!tile) return; @@ -2237,7 +2242,7 @@ void MapCanvas::OnSelectSpawnBrush(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnSelectNpcBrush(wxCommandEvent& WXUNUSED(event)) { - Tile* tile = editor.selection.getSelectedTile(); + Tile* tile = editor.getSelection().getSelectedTile(); if(!tile) return; @@ -2252,10 +2257,10 @@ void MapCanvas::OnSelectSpawnNpcBrush(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnProperties(wxCommandEvent& WXUNUSED(event)) { - if(editor.selection.size() != 1) + if(editor.getSelection().size() != 1) return; - Tile* tile = editor.selection.getSelectedTile(); + Tile* tile = editor.getSelection().getSelectedTile(); if(!tile) return; ASSERT(tile->isSelected()); Tile* new_tile = tile->deepCopy(editor.getMap()); @@ -2377,7 +2382,7 @@ void MapCanvas::Reset() last_mmb_click_x = -1; last_mmb_click_y = -1; - editor.selection.clear(); + editor.getSelection().clear(); editor.actionQueue->clear(); } @@ -2400,7 +2405,7 @@ void MapPopupMenu::Update() Delete(m_item); } - bool anything_selected = editor.selection.size() != 0; + bool anything_selected = editor.hasSelection(); wxMenuItem* cutItem = Append( MAP_POPUP_MENU_CUT, "&Cut\tCTRL+X", "Cut out all selected items"); cutItem->Enable(anything_selected); @@ -2418,8 +2423,8 @@ void MapPopupMenu::Update() deleteItem->Enable(anything_selected); if(anything_selected) { - if(editor.selection.size() == 1) { - Tile* tile = editor.selection.getSelectedTile(); + if(editor.getSelection().size() == 1) { + Tile* tile = editor.getSelection().getSelectedTile(); ItemVector selected_items = tile->getSelectedItems(); bool hasWall = false; diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index d5f1b337..ae9afc98 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -571,13 +571,12 @@ void MapDrawer::DrawGrid() void MapDrawer::DrawDraggingShadow() { - if(!dragging || options.ingame || editor.selection.isBusy()) + if(!dragging || options.ingame || editor.getSelection().isBusy()) return; glEnable(GL_TEXTURE_2D); - // Draw dragging shadow - for(Tile* tile : editor.selection) { + for(Tile* tile : editor.getSelection()) { int move_z = canvas->drag_start_z - floor; int move_x = canvas->drag_start_x - mouse_map_x; int move_y = canvas->drag_start_y - mouse_map_y; From ffeca4d3ee4a3f512a8f3caa3c892bb205ae25f3 Mon Sep 17 00:00:00 2001 From: Beats Date: Wed, 5 Apr 2023 21:58:36 -0400 Subject: [PATCH 19/45] Some changes --- source/common_windows.cpp | 2 +- source/copybuffer.cpp | 12 ++++++------ source/editor.h | 9 +++++---- source/gui.cpp | 14 +++++++------- source/live_client.cpp | 4 ++-- source/live_peer.cpp | 4 ++-- source/main_menubar.cpp | 20 ++++++++++---------- source/main_toolbar.cpp | 6 +++--- source/map_display.cpp | 22 +++++++++++----------- source/replace_items_window.cpp | 4 ++-- source/selection.cpp | 6 +++--- 11 files changed, 52 insertions(+), 51 deletions(-) diff --git a/source/common_windows.cpp b/source/common_windows.cpp index 1d18d7af..b6d5960a 100644 --- a/source/common_windows.cpp +++ b/source/common_windows.cpp @@ -266,7 +266,7 @@ void MapPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) // Switch version g_gui.GetCurrentEditor()->getSelection().clear(); - g_gui.GetCurrentEditor()->actionQueue->clear(); + g_gui.GetCurrentEditor()->getHistoryActions()->clear(); if(new_ver.client < old_ver.client) { int ret = g_gui.PopupDialog(this, "Notice", diff --git a/source/copybuffer.cpp b/source/copybuffer.cpp index e0fa1487..72e4d03a 100644 --- a/source/copybuffer.cpp +++ b/source/copybuffer.cpp @@ -133,8 +133,8 @@ void CopyBuffer::cut(Editor& editor, int floor) int item_count = 0; copyPos = Position(0xFFFF, 0xFFFF, floor); - BatchAction* batch = editor.actionQueue->createBatch(ACTION_CUT_TILES); - Action* action = editor.actionQueue->createAction(batch); + BatchAction* batch = editor.getHistoryActions()->createBatch(ACTION_CUT_TILES); + Action* action = editor.getHistoryActions()->createAction(batch); PositionList tilestoborder; @@ -205,7 +205,7 @@ void CopyBuffer::cut(Editor& editor, int floor) tilestoborder.unique(); if(g_settings.getInteger(Config::USE_AUTOMAGIC)) { - action = editor.actionQueue->createAction(batch); + action = editor.getHistoryActions()->createAction(batch); for(PositionList::iterator it = tilestoborder.begin(); it != tilestoborder.end(); ++it) { TileLocation* location = map.createTileL(*it); if(location->get()) { @@ -241,8 +241,8 @@ void CopyBuffer::paste(Editor& editor, const Position& toPosition) Map& map = editor.getMap(); - BatchAction* batchAction = editor.actionQueue->createBatch(ACTION_PASTE_TILES); - Action* action = editor.actionQueue->createAction(batchAction); + BatchAction* batchAction = editor.getHistoryActions()->createBatch(ACTION_PASTE_TILES); + Action* action = editor.getHistoryActions()->createAction(batchAction); for(MapIterator it = tiles->begin(); it != tiles->end(); ++it) { Tile* buffer_tile = (*it)->get(); Position pos = buffer_tile->getPosition() - copyPos + toPosition; @@ -283,7 +283,7 @@ void CopyBuffer::paste(Editor& editor, const Position& toPosition) batchAction->addAndCommitAction(action); if(g_settings.getInteger(Config::USE_AUTOMAGIC) && g_settings.getInteger(Config::BORDERIZE_PASTE)) { - action = editor.actionQueue->createAction(batchAction); + action = editor.getHistoryActions()->createAction(batchAction); TileList borderize_tiles; // Go through all modified (selected) tiles (might be slow) diff --git a/source/editor.h b/source/editor.h index ee1a8032..80cd58ef 100644 --- a/source/editor.h +++ b/source/editor.h @@ -47,7 +47,6 @@ class Editor public: // Public members - ActionQueue* actionQueue; CopyBuffer& copybuffer; GroundBrush* replace_brush; @@ -74,7 +73,7 @@ class Editor // Map handling void saveMap(FileName filename, bool showdialog); // "" means default filename - Map& getMap() { return map; } + Map& getMap() noexcept { return map; } const Map& getMap() const noexcept { return map; } uint16_t getMapWidth() const noexcept { return map.width; } uint16_t getMapHeight() const noexcept { return map.height; } @@ -85,14 +84,15 @@ class Editor bool exportMiniMap(FileName filename, int floor /*= GROUND_LAYER*/, bool displaydialog); bool exportSelectionAsMiniMap(FileName directory, wxString fileName); + ActionQueue* getHistoryActions() const noexcept { return actionQueue; } // Adds an action to the action queue (this allows the user to undo the action) // Invalidates the action pointer void addBatch(BatchAction* action, int stacking_delay = 0); void addAction(Action* action, int stacking_delay = 0); // Selection - Selection& getSelection() { return selection; } - const Selection& getSelection() const { return selection; } + Selection& getSelection() noexcept { return selection; } + const Selection& getSelection() const noexcept { return selection; } bool hasSelection() const noexcept { return selection.size() != 0; } // Some simple actions that work on the map (these will work through the undo queue) // Moves the selected area by the offset @@ -132,6 +132,7 @@ class Editor private: Map map; Selection selection; + ActionQueue* actionQueue; }; inline void Editor::draw(const Position& offset, bool alt) { drawInternal(offset, alt, true); } diff --git a/source/gui.cpp b/source/gui.cpp index 92a7aa1f..fd755e87 100644 --- a/source/gui.cpp +++ b/source/gui.cpp @@ -711,7 +711,7 @@ bool GUI::ShouldSave() if(map.getTileCount() == 0) { Editor* editor = GetCurrentEditor(); ASSERT(editor); - return editor->actionQueue->canUndo(); + return editor->getHistoryActions()->canUndo(); } return true; } @@ -1320,20 +1320,20 @@ void GUI::EndPasting() bool GUI::CanUndo() { Editor* editor = GetCurrentEditor(); - return (editor && editor->actionQueue->canUndo()); + return (editor && editor->getHistoryActions()->canUndo()); } bool GUI::CanRedo() { Editor* editor = GetCurrentEditor(); - return (editor && editor->actionQueue->canRedo()); + return (editor && editor->getHistoryActions()->canRedo()); } bool GUI::DoUndo() { Editor* editor = GetCurrentEditor(); - if(editor && editor->actionQueue->canUndo()) { - editor->actionQueue->undo(); + if(editor && editor->getHistoryActions()->canUndo()) { + editor->getHistoryActions()->undo(); if(editor->hasSelection()) SetSelectionMode(); SetStatusText("Undo action"); @@ -1348,8 +1348,8 @@ bool GUI::DoUndo() bool GUI::DoRedo() { Editor* editor = GetCurrentEditor(); - if(editor && editor->actionQueue->canRedo()) { - editor->actionQueue->redo(); + if(editor && editor->getHistoryActions()->canRedo()) { + editor->getHistoryActions()->redo(); if(editor->hasSelection()) SetSelectionMode(); SetStatusText("Redo action"); diff --git a/source/live_client.cpp b/source/live_client.cpp index 5dd4f343..07576f0e 100644 --- a/source/live_client.cpp +++ b/source/live_client.cpp @@ -453,9 +453,9 @@ void LiveClient::parseNode(NetworkMessage& message) int32_t ndy = (ind >> 4) & 0x3FFF; bool underground = ind & 1; - Action* action = editor->actionQueue->createAction(ACTION_REMOTE); + Action* action = editor->getHistoryActions()->createAction(ACTION_REMOTE); receiveNode(message, *editor, action, ndx, ndy, underground); - editor->actionQueue->addAction(action); + editor->getHistoryActions()->addAction(action); g_gui.RefreshView(); g_gui.UpdateMinimap(); diff --git a/source/live_peer.cpp b/source/live_peer.cpp index 445e7572..79b014ef 100644 --- a/source/live_peer.cpp +++ b/source/live_peer.cpp @@ -290,7 +290,7 @@ void LivePeer::parseReceiveChanges(NetworkMessage& message) BinaryNode* rootNode = mapReader.getRootNode(); BinaryNode* tileNode = rootNode->getChild(); - NetworkedAction* action = static_cast(editor.actionQueue->createAction(ACTION_REMOTE)); + NetworkedAction* action = static_cast(editor.getHistoryActions()->createAction(ACTION_REMOTE)); action->owner = clientId; if(tileNode) do { @@ -301,7 +301,7 @@ void LivePeer::parseReceiveChanges(NetworkMessage& message) } while(tileNode->advance()); mapReader.close(); - editor.actionQueue->addAction(action); + editor.getHistoryActions()->addAction(action); g_gui.RefreshView(); g_gui.UpdateMinimap(); diff --git a/source/main_menubar.cpp b/source/main_menubar.cpp index 18b5241e..ebef57dc 100644 --- a/source/main_menubar.cpp +++ b/source/main_menubar.cpp @@ -305,8 +305,8 @@ void MainMenuBar::Update() Editor* editor = g_gui.GetCurrentEditor(); if(editor) { - EnableItem(UNDO, editor->actionQueue->canUndo()); - EnableItem(REDO, editor->actionQueue->canRedo()); + EnableItem(UNDO, editor->getHistoryActions()->canUndo()); + EnableItem(REDO, editor->getHistoryActions()->canRedo()); EnableItem(PASTE, editor->copybuffer.canPaste()); } else { EnableItem(UNDO, false); @@ -1135,7 +1135,7 @@ void MainMenuBar::OnRemoveItemOnSelection(wxCommandEvent& WXUNUSED(event)) FindItemDialog dialog(frame, "Remove Item on Selection"); if(dialog.ShowModal() == wxID_OK) { - g_gui.GetCurrentEditor()->actionQueue->clear(); + g_gui.GetCurrentEditor()->getHistoryActions()->clear(); g_gui.CreateLoadBar("Searching item on selection to remove..."); OnMapRemoveItems::RemoveItemCondition condition(dialog.getResultID()); int64_t count = RemoveItemOnMap(g_gui.GetCurrentMap(), condition, true); @@ -1293,7 +1293,7 @@ void MainMenuBar::OnMapRemoveItems(wxCommandEvent& WXUNUSED(event)) uint16_t itemid = dialog.getResultID(); g_gui.GetCurrentEditor()->getSelection().clear(); - g_gui.GetCurrentEditor()->actionQueue->clear(); + g_gui.GetCurrentEditor()->getHistoryActions()->clear(); OnMapRemoveItems::RemoveItemCondition condition(itemid); g_gui.CreateLoadBar("Searching map for items to remove..."); @@ -1336,7 +1336,7 @@ void MainMenuBar::OnMapRemoveCorpses(wxCommandEvent& WXUNUSED(event)) if(ok == wxID_YES) { g_gui.GetCurrentEditor()->getSelection().clear(); - g_gui.GetCurrentEditor()->actionQueue->clear(); + g_gui.GetCurrentEditor()->getHistoryActions()->clear(); OnMapRemoveCorpses::condition func; g_gui.CreateLoadBar("Searching map for items to remove..."); @@ -1410,7 +1410,7 @@ void MainMenuBar::OnMapRemoveUnreachable(wxCommandEvent& WXUNUSED(event)) if(ok == wxID_YES) { g_gui.GetCurrentEditor()->getSelection().clear(); - g_gui.GetCurrentEditor()->actionQueue->clear(); + g_gui.GetCurrentEditor()->getHistoryActions()->clear(); OnMapRemoveUnreachable::condition func; g_gui.CreateLoadBar("Searching map for tiles to remove..."); @@ -1473,8 +1473,8 @@ void MainMenuBar::OnMapRemoveEmptyMonsterSpawns(wxCommandEvent& WXUNUSED(event)) monster->reset(); } - BatchAction* batch = editor->actionQueue->createBatch(ACTION_DELETE_TILES); - Action* action = editor->actionQueue->createAction(batch); + BatchAction* batch = editor->getHistoryActions()->createBatch(ACTION_DELETE_TILES); + Action* action = editor->getHistoryActions()->createAction(batch); const size_t count = toDeleteSpawns.size(); size_t removed = 0; @@ -1547,8 +1547,8 @@ void MainMenuBar::OnMapRemoveEmptyNpcSpawns(wxCommandEvent& WXUNUSED(event)) npc->reset(); } - BatchAction* batch = editor->actionQueue->createBatch(ACTION_DELETE_TILES); - Action* action = editor->actionQueue->createAction(batch); + BatchAction* batch = editor->getHistoryActions()->createBatch(ACTION_DELETE_TILES); + Action* action = editor->getHistoryActions()->createAction(batch); const size_t count = toDeleteSpawns.size(); size_t removed = 0; diff --git a/source/main_toolbar.cpp b/source/main_toolbar.cpp index d1631ff3..5f12a691 100644 --- a/source/main_toolbar.cpp +++ b/source/main_toolbar.cpp @@ -199,9 +199,9 @@ MainToolBar::~MainToolBar() void MainToolBar::UpdateButtons() { Editor* editor = g_gui.GetCurrentEditor(); - if (editor) { - standard_toolbar->EnableTool(wxID_UNDO, editor->actionQueue->canUndo()); - standard_toolbar->EnableTool(wxID_REDO, editor->actionQueue->canRedo()); + if(editor) { + standard_toolbar->EnableTool(wxID_UNDO, editor->getHistoryActions()->canUndo()); + standard_toolbar->EnableTool(wxID_REDO, editor->getHistoryActions()->canRedo()); standard_toolbar->EnableTool(wxID_PASTE, editor->copybuffer.canPaste()); } else { standard_toolbar->EnableTool(wxID_UNDO, false); diff --git a/source/map_display.cpp b/source/map_display.cpp index 8aa44f44..ee723a5e 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -627,7 +627,7 @@ void MapCanvas::OnMouseLeftDoubleClick(wxMouseEvent& event) int ret = dialog->ShowModal(); if(ret != 0) { - Action* action = editor.actionQueue->createAction(ACTION_CHANGE_PROPERTIES); + Action* action = editor.getHistoryActions()->createAction(ACTION_CHANGE_PROPERTIES); action->addChange(newd Change(new_tile)); editor.addAction(action); } else { @@ -1214,7 +1214,7 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) } } } - editor.actionQueue->resetTimer(); + editor.getHistoryActions()->resetTimer(); dragging = false; boundbox_selection = false; } else if(g_gui.GetCurrentBrush()){ // Drawing mode @@ -1342,7 +1342,7 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) } } } - editor.actionQueue->resetTimer(); + editor.getHistoryActions()->resetTimer(); drawing = false; dragging_draw = false; replace_dragging = false; @@ -1590,7 +1590,7 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) popup_menu->Update(); PopupMenu(popup_menu); - editor.actionQueue->resetTimer(); + editor.getHistoryActions()->resetTimer(); dragging = false; boundbox_selection = false; @@ -2055,7 +2055,7 @@ void MapCanvas::OnBrowseTile(wxCommandEvent& WXUNUSED(event)) int ret = w->ShowModal(); if(ret != 0) { - Action* action = editor.actionQueue->createAction(ACTION_DELETE_TILES); + Action* action = editor.getHistoryActions()->createAction(ACTION_DELETE_TILES); action->addChange(newd Change(new_tile)); editor.addAction(action); } else { @@ -2070,7 +2070,7 @@ void MapCanvas::OnRotateItem(wxCommandEvent& WXUNUSED(event)) { Tile* tile = editor.getSelection().getSelectedTile(); - Action* action = editor.actionQueue->createAction(ACTION_ROTATE_ITEM); + Action* action = editor.getHistoryActions()->createAction(ACTION_ROTATE_ITEM); Tile* new_tile = tile->deepCopy(editor.getMap()); @@ -2081,7 +2081,7 @@ void MapCanvas::OnRotateItem(wxCommandEvent& WXUNUSED(event)) action->addChange(newd Change(new_tile)); - editor.actionQueue->addAction(action); + editor.getHistoryActions()->addAction(action); g_gui.RefreshView(); } @@ -2115,7 +2115,7 @@ void MapCanvas::OnSwitchDoor(wxCommandEvent& WXUNUSED(event)) { Tile* tile = editor.getSelection().getSelectedTile(); - Action* action = editor.actionQueue->createAction(ACTION_SWITCHDOOR); + Action* action = editor.getHistoryActions()->createAction(ACTION_SWITCHDOOR); Tile* new_tile = tile->deepCopy(editor.getMap()); @@ -2126,7 +2126,7 @@ void MapCanvas::OnSwitchDoor(wxCommandEvent& WXUNUSED(event)) action->addChange(newd Change(new_tile)); - editor.actionQueue->addAction(action); + editor.getHistoryActions()->addAction(action); g_gui.RefreshView(); } @@ -2299,7 +2299,7 @@ void MapCanvas::OnProperties(wxCommandEvent& WXUNUSED(event)) int ret = w->ShowModal(); if(ret != 0) { - Action* action = editor.actionQueue->createAction(ACTION_CHANGE_PROPERTIES); + Action* action = editor.getHistoryActions()->createAction(ACTION_CHANGE_PROPERTIES); action->addChange(newd Change(new_tile)); editor.addAction(action); } else { @@ -2383,7 +2383,7 @@ void MapCanvas::Reset() last_mmb_click_y = -1; editor.getSelection().clear(); - editor.actionQueue->clear(); + editor.getHistoryActions()->clear(); } MapPopupMenu::MapPopupMenu(Editor& editor) : wxMenu(""), editor(editor) diff --git a/source/replace_items_window.cpp b/source/replace_items_window.cpp index 98618a83..1c622dbe 100644 --- a/source/replace_items_window.cpp +++ b/source/replace_items_window.cpp @@ -349,7 +349,7 @@ void ReplaceItemsDialog::OnExecuteButtonClicked(wxCommandEvent& WXUNUSED(event)) std::vector>& result = finder.result; if(!result.empty()) { - Action* action = editor->actionQueue->createAction(ACTION_REPLACE_ITEMS); + Action* action = editor->getHistoryActions()->createAction(ACTION_REPLACE_ITEMS); for(std::vector>::const_iterator rit = result.begin(); rit != result.end(); ++rit) { Tile* new_tile = rit->first->deepCopy(editor->getMap()); int index = rit->first->getIndexOf(rit->second); @@ -360,7 +360,7 @@ void ReplaceItemsDialog::OnExecuteButtonClicked(wxCommandEvent& WXUNUSED(event)) action->addChange(new Change(new_tile)); total++; } - editor->actionQueue->addAction(action); + editor->getHistoryActions()->addAction(action); } done++; diff --git a/source/selection.cpp b/source/selection.cpp index 2f3bb2a1..710b4043 100644 --- a/source/selection.cpp +++ b/source/selection.cpp @@ -284,9 +284,9 @@ void Selection::start(SessionFlags flags) { if(!(flags & INTERNAL)) { if(!(flags & SUBTHREAD)) { - session = editor.actionQueue->createBatch(ACTION_SELECT); + session = editor.getHistoryActions()->createBatch(ACTION_SELECT); } - subsession = editor.actionQueue->createAction(ACTION_SELECT); + subsession = editor.getHistoryActions()->createAction(ACTION_SELECT); } busy = true; } @@ -303,7 +303,7 @@ void Selection::commit() batch->addAndCommitAction(subsession); // Create a newd action for subsequent selects - subsession = editor.actionQueue->createAction(ACTION_SELECT); + subsession = editor.getHistoryActions()->createAction(ACTION_SELECT); session = batch; } } From 74446839cfc52e8612ce82f82ff07b3f0abdd030 Mon Sep 17 00:00:00 2001 From: Beats Date: Wed, 5 Apr 2023 21:59:30 -0400 Subject: [PATCH 20/45] Fix copy position. --- source/map_display.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/map_display.cpp b/source/map_display.cpp index ee723a5e..0592404e 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -1971,7 +1971,7 @@ void MapCanvas::OnDelete(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnCopyPosition(wxCommandEvent& WXUNUSED(event)) { - if(editor.hasSelection()) + if(!editor.hasSelection()) return; Position minPos = editor.getSelection().minPosition(); From 9d82e8c5229a2a8bf78cd6212e7ebe5920b8c09e Mon Sep 17 00:00:00 2001 From: Beats Date: Wed, 5 Apr 2023 22:01:06 -0400 Subject: [PATCH 21/45] Only show uid/aid alert if it really changed --- source/old_properties_window.cpp | 54 ++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/source/old_properties_window.cpp b/source/old_properties_window.cpp index edbb13ee..02c009d9 100644 --- a/source/old_properties_window.cpp +++ b/source/old_properties_window.cpp @@ -567,28 +567,35 @@ void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) if(edit_item) { int new_uid = unique_id_field->GetValue(); int new_aid = action_id_field->GetValue(); - if (!edit_item->getDepot()) { - if((new_uid < MIN_UNIQUE_ID || new_uid > MAX_UNIQUE_ID) && new_uid != 0) { - wxString message = "Unique ID must be between %d and %d."; - g_gui.PopupDialog(this, "Error", wxString::Format(message, MIN_UNIQUE_ID, MAX_UNIQUE_ID), wxOK); - return; - } - if(g_gui.GetCurrentMap().hasUniqueId(new_uid)) { - g_gui.PopupDialog(this, "Error", "Unique ID must be unique, this UID is already taken.", wxOK); - return; + bool uid_changed = false; + bool aid_changed = false; + + if(!edit_item->getDepot()) { + uid_changed = new_uid != edit_item->getUniqueID(); + aid_changed = new_aid != edit_item->getActionID(); + + if(uid_changed) { + if(new_uid != 0 && (new_uid < MIN_UNIQUE_ID || new_uid > MAX_UNIQUE_ID)) { + wxString message = "Unique ID must be between %d and %d."; + g_gui.PopupDialog(this, "Error", wxString::Format(message, MIN_UNIQUE_ID, MAX_UNIQUE_ID), wxOK); + return; + } + if(g_gui.GetCurrentMap().hasUniqueId(new_uid)) { + g_gui.PopupDialog(this, "Error", "Unique ID must be unique, this UID is already taken.", wxOK); + return; + } } - if((new_aid < MIN_ACTION_ID || new_aid > MAX_ACTION_ID) && new_aid != 0) { - wxString message = "Action ID must be between %d and %d."; - g_gui.PopupDialog(this, "Error", wxString::Format(message, MIN_ACTION_ID, MAX_ACTION_ID), wxOK); - return; + + if(aid_changed) { + if(new_aid != 0 && (new_aid < MIN_ACTION_ID || new_aid > MAX_ACTION_ID)) { + wxString message = "Action ID must be between %d and %d."; + g_gui.PopupDialog(this, "Error", wxString::Format(message, MIN_ACTION_ID, MAX_ACTION_ID), wxOK); + return; + } } } - if(edit_item->getContainer()) { - // Container - edit_item->setUniqueID(new_uid); - edit_item->setActionID(new_aid); - } else if(edit_item->canHoldText() || edit_item->canHoldDescription()) { + if(edit_item->canHoldText() || edit_item->canHoldDescription()) { // Book std::string text = nstr(text_field->GetValue()); if(text.length() >= 0xFFFF) { @@ -601,9 +608,6 @@ void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) return; } } - - edit_item->setUniqueID(new_uid); - edit_item->setActionID(new_aid); edit_item->setText(text); } else if(edit_item->isSplash() || edit_item->isFluidContainer()) { // Splash @@ -611,9 +615,6 @@ void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) if(new_type) { edit_item->setSubtype(*new_type); } - edit_item->setUniqueID(new_uid); - edit_item->setActionID(new_aid); - // Clean up client data } else if(Depot* depot = edit_item->getDepot()) { // Depot @@ -679,8 +680,13 @@ void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) if(door) { door->setDoorID(new_door_id); } + } + if(uid_changed) { edit_item->setUniqueID(new_uid); + } + + if(aid_changed) { edit_item->setActionID(new_aid); } } else if(edit_monster) { From e5a73e1a05d5ee01069e23ac5558f16d3e00121d Mon Sep 17 00:00:00 2001 From: Beats Date: Wed, 5 Apr 2023 23:21:52 -0400 Subject: [PATCH 22/45] Add actions history panel --- data/menubar.xml | 1 + icons/mini_fill.xpm | 2 +- source/CMakeLists.txt | 1 + source/action.cpp | 492 ++++++++++++++++-------------- source/action.h | 96 +++--- source/actions_history_window.cpp | 183 +++++++++++ source/actions_history_window.h | 67 ++++ source/application.cpp | 9 +- source/application.h | 1 + source/artprovider.cpp | 51 +++- source/artprovider.h | 16 + source/common.h | 2 +- source/common_windows.cpp | 2 +- source/copybuffer.cpp | 15 +- source/editor.cpp | 399 +++++++++++++++--------- source/editor.h | 17 +- source/editor_tabs.cpp | 44 +-- source/editor_tabs.h | 1 - source/gui.cpp | 113 +++++-- source/gui.h | 21 +- source/live_action.cpp | 12 +- source/live_action.h | 8 +- source/live_client.cpp | 4 +- source/live_peer.cpp | 4 +- source/main_menubar.cpp | 22 +- source/main_menubar.h | 2 + source/main_toolbar.cpp | 7 +- source/map_display.cpp | 98 +++--- source/palette_window.h | 4 +- source/replace_items_window.cpp | 17 +- source/selection.cpp | 21 +- source/selection.h | 16 +- source/settings.cpp | 2 + source/settings.h | 3 + source/tile.h | 6 +- vcproj/Project/RME.vcxproj | 2 + vcproj/rme - Copia.cfg | 142 +++++++++ 37 files changed, 1326 insertions(+), 577 deletions(-) create mode 100644 source/actions_history_window.cpp create mode 100644 source/actions_history_window.h create mode 100644 vcproj/rme - Copia.cfg diff --git a/data/menubar.xml b/data/menubar.xml index ab509839..4a2c3514 100644 --- a/data/menubar.xml +++ b/data/menubar.xml @@ -140,6 +140,7 @@ + diff --git a/icons/mini_fill.xpm b/icons/mini_fill.xpm index 31414792..c70596c3 100644 --- a/icons/mini_fill.xpm +++ b/icons/mini_fill.xpm @@ -1,5 +1,5 @@ /* XPM */ -static const char *mini_fill_xpm[] = { +static char * mini_fill_xpm[] = { "16 16 103 2", " c None", ". c #4884C2", diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 7f2964a0..cd0f74bd 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -34,6 +34,7 @@ target_sources(${PROJECT_NAME} PRIVATE about_window.cpp action.cpp + actions_history_window.cpp application.cpp artprovider.cpp basemap.cpp diff --git a/source/action.cpp b/source/action.cpp index 173bcd00..97349dc4 100644 --- a/source/action.cpp +++ b/source/action.cpp @@ -28,32 +28,26 @@ Change::Change() : type(CHANGE_NONE), data(nullptr) //// } -Change::Change(Tile* t) : type(CHANGE_TILE) +Change::Change(Tile* tile) : type(CHANGE_TILE) { - ASSERT(t); - data = t; + ASSERT(tile); + data = tile; } -Change* Change::Create(House* house, const Position& where) +Change* Change::Create(House* house, const Position& position) { - Change* c = newd Change(); - c->type = CHANGE_MOVE_HOUSE_EXIT; - std::pair* p = newd std::pair; - p->first = house->id; - p->second = where; - c->data = p; - return c; + Change* change = new Change(); + change->type = CHANGE_MOVE_HOUSE_EXIT; + change->data = new HouseData { house->id, position }; + return change; } -Change* Change::Create(Waypoint* wp, const Position& where) +Change* Change::Create(Waypoint* waypoint, const Position& position) { - Change* c = newd Change(); - c->type = CHANGE_MOVE_WAYPOINT; - std::pair* p = newd std::pair; - p->first = wp->name; - p->second = where; - c->data = p; - return c; + Change* change = new Change(); + change->type = CHANGE_MOVE_WAYPOINT; + change->data = new WaypointData { waypoint->name, position }; + return change; } Change::~Change() @@ -70,11 +64,11 @@ void Change::clear() break; case CHANGE_MOVE_HOUSE_EXIT: ASSERT(data); - delete reinterpret_cast* >(data); + delete reinterpret_cast(data); break; case CHANGE_MOVE_WAYPOINT: ASSERT(data); - delete reinterpret_cast* >(data); + delete reinterpret_cast(data); break; case CHANGE_NONE: break; @@ -85,6 +79,7 @@ void Change::clear() #endif break; } + type = CHANGE_NONE; data = nullptr; } @@ -92,13 +87,8 @@ void Change::clear() uint32_t Change::memsize() const { uint32_t mem = sizeof(*this); - switch(type) { - case CHANGE_TILE: - ASSERT(data); - mem += reinterpret_cast(data)->memsize(); - break; - default: - break; + if(type == CHANGE_TILE) { + mem += reinterpret_cast(data)->memsize(); } return mem; } @@ -112,11 +102,10 @@ Action::Action(Editor& editor, ActionIdentifier ident) : Action::~Action() { - ChangeList::const_reverse_iterator it = changes.rbegin(); - while(it != changes.rend()) { - delete *it; - ++it; + for(Change* change : changes) { + delete change; } + changes.clear(); } size_t Action::approx_memsize() const @@ -130,167 +119,151 @@ size_t Action::memsize() const { uint32_t mem = sizeof(*this); mem += sizeof(Change*) * 3 * changes.size(); - ChangeList::const_iterator it = changes.begin(); - while(it != changes.end()) { - Change* c = *it; - switch(c->type) { - case CHANGE_TILE: - { - ASSERT(c->data); - mem += reinterpret_cast(c->data)->memsize(); - break; - } - default: - break; + for(const Change* change : changes) { + if(change && change->getType() == CHANGE_TILE) { + mem += reinterpret_cast(change->getData())->memsize(); } - ++it; } + return mem; } void Action::commit(DirtyList* dirty_list) { + Map& map = editor.getMap(); Selection& selection = editor.getSelection(); selection.start(Selection::INTERNAL); - ChangeList::const_iterator it = changes.begin(); - while(it != changes.end()) { - Change* c = *it; - switch(c->type) { + + for (Change* change : changes) { + switch(change->getType()) { case CHANGE_TILE: { - void** data = &c->data; - Tile* newtile = reinterpret_cast(*data); - ASSERT(newtile); - const Position& pos = newtile->getPosition(); + void** data = &change->data; + Tile* new_tile = reinterpret_cast(*data); + ASSERT(new_tile); + + const Position& pos = new_tile->getPosition(); if(editor.IsLiveClient()) { - QTreeNode* nd = editor.getMap().getLeaf(pos.x, pos.y); - if(!nd || !nd->isVisible(pos.z > GROUND_LAYER)) { - // Delete all changes that affect tiles outside our view - c->clear(); - ++it; + QTreeNode* node = map.getLeaf(pos.x, pos.y); + if(!node || !node->isVisible(pos.z > GROUND_LAYER)) { + change->clear(); continue; } } - Tile* oldtile = editor.getMap().swapTile(pos, newtile); - TileLocation* location = newtile->getLocation(); + Tile* old_tile = map.swapTile(pos, new_tile); + TileLocation* location = new_tile->getLocation(); // Update other nodes in the network if(editor.IsLiveServer() && dirty_list) dirty_list->AddPosition(pos.x, pos.y, pos.z); - - newtile->update(); + new_tile->update(); //std::cout << "\tSwitched tile at " << pos.x << ";" << pos.y << ";" << pos.z << " from " << (void*)oldtile << " to " << *data << std::endl; - if(newtile->isSelected()) - selection.addInternal(newtile); + if(new_tile->isSelected()) + selection.addInternal(new_tile); - if(oldtile) { - if(newtile->getHouseID() != oldtile->getHouseID()) { + if(old_tile) { + if(new_tile->getHouseID() != old_tile->getHouseID()) { // oooooomggzzz we need to add it to the appropriate house! - House* house = editor.getMap().houses.getHouse(oldtile->getHouseID()); + House* house = map.houses.getHouse(old_tile->getHouseID()); if(house) - house->removeTile(oldtile); + house->removeTile(old_tile); - house = editor.getMap().houses.getHouse(newtile->getHouseID()); + house = map.houses.getHouse(new_tile->getHouseID()); if(house) - house->addTile(newtile); + house->addTile(new_tile); } - if(oldtile->spawnMonster) { - if(newtile->spawnMonster) { - if(*oldtile->spawnMonster != *newtile->spawnMonster) { - editor.getMap().removeSpawnMonster(oldtile); - editor.getMap().addSpawnMonster(newtile); + if(old_tile->spawnMonster) { + if(new_tile->spawnMonster) { + if(*old_tile->spawnMonster != *new_tile->spawnMonster) { + map.removeSpawnMonster(old_tile); + map.addSpawnMonster(new_tile); } } else { // Monster spawn has been removed - editor.getMap().removeSpawnMonster(oldtile); + editor.getMap().removeSpawnMonster(old_tile); } - } else if(newtile->spawnMonster) { - editor.getMap().addSpawnMonster(newtile); + } else if(new_tile->spawnMonster) { + editor.getMap().addSpawnMonster(new_tile); } - if(oldtile->spawnNpc) { - if(newtile->spawnNpc) { - if(*oldtile->spawnNpc != *newtile->spawnNpc) { - editor.getMap().removeSpawnNpc(oldtile); - editor.getMap().addSpawnNpc(newtile); + if(old_tile->spawnNpc) { + if(new_tile->spawnNpc) { + if(*old_tile->spawnNpc != *new_tile->spawnNpc) { + map.removeSpawnNpc(old_tile); + map.addSpawnNpc(new_tile); } } else { // SpawnMonster has been removed - editor.getMap().removeSpawnNpc(oldtile); + map.removeSpawnNpc(old_tile); } - } else if(newtile->spawnNpc) { - editor.getMap().addSpawnNpc(newtile); + } else if(new_tile->spawnNpc) { + map.addSpawnNpc(new_tile); } //oldtile->update(); - if(oldtile->isSelected()) - selection.removeInternal(oldtile); + if(old_tile->isSelected()) + selection.removeInternal(old_tile); - *data = oldtile; + *data = old_tile; } else { - *data = editor.getMap().allocator(location); - if(newtile->getHouseID() != 0) { + *data = map.allocator(location); + if(new_tile->getHouseID() != 0) { // oooooomggzzz we need to add it to the appropriate house! - House* house = editor.getMap().houses.getHouse(newtile->getHouseID()); + House* house = map.houses.getHouse(new_tile->getHouseID()); if(house) { - house->addTile(newtile); + house->addTile(new_tile); } } - if(newtile->spawnMonster) - editor.getMap().addSpawnMonster(newtile); + if(new_tile->spawnMonster) + map.addSpawnMonster(new_tile); - if(newtile->spawnNpc) - editor.getMap().addSpawnNpc(newtile); + if(new_tile->spawnNpc) + map.addSpawnNpc(new_tile); } - // Mark the tile as modified - newtile->modify(); + new_tile->modify(); // Update client dirty list if(editor.IsLiveClient() && dirty_list && type != ACTION_REMOTE) { - // Local action, assemble changes - dirty_list->AddChange(c); + dirty_list->AddChange(change); } break; } case CHANGE_MOVE_HOUSE_EXIT: { - std::pair* p = reinterpret_cast* >(c->data); - ASSERT(p); - House* whathouse = editor.getMap().houses.getHouse(p->first); - - if(whathouse) { - Position oldpos = whathouse->getExit(); - whathouse->setExit(p->second); - p->second = oldpos; + HouseData* data = reinterpret_cast(change->data); + ASSERT(data); + + House* house = map.houses.getHouse(data->id); + if(house) { + const Position& old_pos = house->getExit(); + house->setExit(data->position); + data->position = old_pos; } break; } case CHANGE_MOVE_WAYPOINT: { - std::pair* p = reinterpret_cast* >(c->data); - ASSERT(p); - Waypoint* wp = editor.getMap().waypoints.getWaypoint(p->first); + WaypointData* data = reinterpret_cast(change->data); + ASSERT(data); - if(wp) { - // Change the tiles - TileLocation* oldtile = editor.getMap().getTileL(wp->pos); - TileLocation* newtile = editor.getMap().getTileL(p->second); + Waypoint* waypoint = map.waypoints.getWaypoint(data->id); + if(waypoint) { + TileLocation* old_tile = map.getTileL(waypoint->pos); + TileLocation* new_tile = map.getTileL(data->position); - // Only need to remove from old if it actually exists - if(p->second.isValid() && oldtile && oldtile->getWaypointCount() > 0) - oldtile->decreaseWaypointCount(); + if(data->position.isValid() && old_tile && old_tile->getWaypointCount() > 0) + old_tile->decreaseWaypointCount(); - newtile->increaseWaypointCount(); + new_tile->increaseWaypointCount(); - // Update shit - Position oldpos = wp->pos; - wp->pos = p->second; - p->second = oldpos; + Position old_pos = waypoint->pos; + waypoint->pos = data->position; + data->position = old_pos; } break; } @@ -298,7 +271,6 @@ void Action::commit(DirtyList* dirty_list) default: break; } - ++it; } selection.finish(Selection::INTERNAL); commited = true; @@ -309,125 +281,118 @@ void Action::undo(DirtyList* dirty_list) if(changes.empty()) return; + Map& map = editor.getMap(); Selection& selection = editor.getSelection(); selection.start(Selection::INTERNAL); - ChangeList::reverse_iterator it = changes.rbegin(); - while(it != changes.rend()) { - Change* c = *it; - switch(c->type) { + for (Change* change : changes) { + switch(change->getType()) { case CHANGE_TILE: { - void** data = &c->data; - Tile* oldtile = reinterpret_cast(*data); - ASSERT(oldtile); - const Position& pos = oldtile->getPosition(); + void** data = &change->data; + Tile* old_tile = reinterpret_cast(*data); + ASSERT(old_tile); + const Position& pos = old_tile->getPosition(); if(editor.IsLiveClient()) { - QTreeNode* nd = editor.getMap().getLeaf(pos.x, pos.y); - if(!nd || !nd->isVisible(pos.z > GROUND_LAYER)) { + QTreeNode* node = map.getLeaf(pos.x, pos.y); + if(!node || !node->isVisible(pos.z > GROUND_LAYER)) { // Delete all changes that affect tiles outside our view - c->clear(); - ++it; + change->clear(); continue; } } - Tile* newtile = editor.getMap().swapTile(pos, oldtile); + Tile* new_tile = map.swapTile(pos, old_tile); // Update server side change list (for broadcast) if(editor.IsLiveServer() && dirty_list) dirty_list->AddPosition(pos.x, pos.y, pos.z); - if(oldtile->isSelected()) - selection.addInternal(oldtile); - if(newtile->isSelected()) - selection.removeInternal(newtile); + if(old_tile->isSelected()) + selection.addInternal(old_tile); + if(new_tile->isSelected()) + selection.removeInternal(new_tile); - if(newtile->getHouseID() != oldtile->getHouseID()) { + if(new_tile->getHouseID() != old_tile->getHouseID()) { // oooooomggzzz we need to remove it from the appropriate house! - House* house = editor.getMap().houses.getHouse(newtile->getHouseID()); + House* house = map.houses.getHouse(new_tile->getHouseID()); if(house) { - house->removeTile(newtile); + house->removeTile(new_tile); } else { - // Set tile house to 0, house has been removed - newtile->setHouse(nullptr); + new_tile->setHouse(nullptr); } - house = editor.getMap().houses.getHouse(oldtile->getHouseID()); + house = map.houses.getHouse(old_tile->getHouseID()); if(house) { - house->addTile(oldtile); + house->addTile(old_tile); } } - if(oldtile->spawnMonster) { - if(newtile->spawnMonster) { - if(*oldtile->spawnMonster != *newtile->spawnMonster) { - editor.getMap().removeSpawnMonster(newtile); - editor.getMap().addSpawnMonster(oldtile); + if(old_tile->spawnMonster) { + if(new_tile->spawnMonster) { + if(*old_tile->spawnMonster != *new_tile->spawnMonster) { + map.removeSpawnMonster(new_tile); + map.addSpawnMonster(old_tile); } } else { - editor.getMap().addSpawnMonster(oldtile); + map.addSpawnMonster(old_tile); } - } else if(newtile->spawnMonster) { - editor.getMap().removeSpawnMonster(newtile); + } else if(new_tile->spawnMonster) { + map.removeSpawnMonster(new_tile); } - if(oldtile->spawnNpc) { - if(newtile->spawnNpc) { - if(*oldtile->spawnNpc != *newtile->spawnNpc) { - editor.getMap().removeSpawnNpc(newtile); - editor.getMap().addSpawnNpc(oldtile); + if(old_tile->spawnNpc) { + if(new_tile->spawnNpc) { + if(*old_tile->spawnNpc != *new_tile->spawnNpc) { + map.removeSpawnNpc(new_tile); + map.addSpawnNpc(old_tile); } } else { - editor.getMap().addSpawnNpc(oldtile); + map.addSpawnNpc(old_tile); } - } else if(newtile->spawnNpc) { - editor.getMap().removeSpawnNpc(newtile); + } else if(new_tile->spawnNpc) { + map.removeSpawnNpc(new_tile); } - *data = newtile; - + *data = new_tile; // Update client dirty list if(editor.IsLiveClient() && dirty_list && type != ACTION_REMOTE) { - // Local action, assemble changes - dirty_list->AddChange(c); + dirty_list->AddChange(change); } break; } case CHANGE_MOVE_HOUSE_EXIT: { - std::pair* p = reinterpret_cast* >(c->data); - ASSERT(p); - House* whathouse = editor.getMap().houses.getHouse(p->first); - if(whathouse) { - Position oldpos = whathouse->getExit(); - whathouse->setExit(p->second); - p->second = oldpos; + HouseData* data = reinterpret_cast(change->data); + ASSERT(data); + + House* house = map.houses.getHouse(data->id); + if(house) { + const Position& oldpos = house->getExit(); + house->setExit(data->position); + data->position = oldpos; } break; } case CHANGE_MOVE_WAYPOINT: { - std::pair* p = reinterpret_cast* >(c->data); - ASSERT(p); - Waypoint* wp = editor.getMap().waypoints.getWaypoint(p->first); + WaypointData* data = reinterpret_cast(change->data); + ASSERT(data); - if(wp) { - // Change the tiles - TileLocation* oldtile = editor.getMap().getTileL(wp->pos); - TileLocation* newtile = editor.getMap().getTileL(p->second); + Waypoint* waypoint = map.waypoints.getWaypoint(data->id); + if(waypoint) { + TileLocation* old_tile = map.getTileL(waypoint->pos); + TileLocation* new_tile = map.getTileL(data->position); - // Only need to remove from old if it actually exists - if(p->second.isValid() && oldtile && oldtile->getWaypointCount() > 0) - oldtile->decreaseWaypointCount(); + if(data->position.isValid() && old_tile && old_tile->getWaypointCount() > 0) + old_tile->decreaseWaypointCount(); - newtile->increaseWaypointCount(); + new_tile->increaseWaypointCount(); - // Update shit - Position oldpos = wp->pos; - wp->pos = p->second; - p->second = oldpos; + Position old_pos = waypoint->pos; + waypoint->pos = data->position; + data->position = old_pos; } break; } @@ -435,8 +400,8 @@ void Action::undo(DirtyList* dirty_list) default: break; } - ++it; } + selection.finish(Selection::INTERNAL); commited = false; } @@ -469,7 +434,7 @@ size_t BatchAction::memsize(bool recalc) const uint32_t mem = sizeof(*this); mem += sizeof(Action*) * 3 * batch.size(); - for(Action* action : batch) { + for(const Action* action : batch) { #ifdef __USE_EXACT_MEMSIZE__ mem += action->memsize(); #else @@ -482,40 +447,39 @@ size_t BatchAction::memsize(bool recalc) const return mem; } +bool BatchAction::isNoSelection() const noexcept +{ + return type != ACTION_SELECT && type != ACTION_UNSELECT; +} + void BatchAction::addAction(Action* action) { - // If empty, do nothing. - if(action->size() == 0) { - delete action; + if(!action) { return; } - ASSERT(action->getType() == type); - - if(!editor.CanEdit()) { + if(action->empty() || !editor.CanEdit()) { delete action; return; } - // Add it! + ASSERT(action->getType() == type); + batch.push_back(action); timestamp = time(nullptr); } void BatchAction::addAndCommitAction(Action* action) { - // If empty, do nothing. - if(action->size() == 0) { - delete action; + if(!action) { return; } - if(!editor.CanEdit()) { + if(!editor.CanEdit() || action->empty()) { delete action; return; } - // Add it! action->commit(nullptr); batch.push_back(action); timestamp = time(nullptr); @@ -524,7 +488,7 @@ void BatchAction::addAndCommitAction(Action* action) void BatchAction::commit() { for(Action* action : batch) { - if(!action->isCommited()) { + if(action && !action->isCommited()) { action->commit(nullptr); } } @@ -558,24 +522,25 @@ ActionQueue::ActionQueue(Editor& editor) : ActionQueue::~ActionQueue() { - for(auto it = actions.begin(); it != actions.end(); it = actions.erase(it)) { - delete *it; + for(BatchAction* batch : actions) { + delete batch; } + actions.clear(); } -Action* ActionQueue::createAction(ActionIdentifier ident) +Action* ActionQueue::createAction(ActionIdentifier identifier) const { - return newd Action(editor, ident); + return new Action(editor, identifier); } -Action* ActionQueue::createAction(BatchAction* batch) +Action* ActionQueue::createAction(BatchAction* batch) const { - return newd Action(editor, batch->getType()); + return new Action(editor, batch->getType()); } -BatchAction* ActionQueue::createBatch(ActionIdentifier ident) +BatchAction* ActionQueue::createBatch(ActionIdentifier identifier) const { - return newd BatchAction(editor, ident); + return new BatchAction(editor, identifier); } void ActionQueue::resetTimer() @@ -589,7 +554,7 @@ void ActionQueue::addBatch(BatchAction* batch, int stacking_delay) ASSERT(batch); ASSERT(current <= actions.size()); - if(batch->size() == 0) { + if(batch->empty()) { delete batch; return; } @@ -598,10 +563,11 @@ void ActionQueue::addBatch(BatchAction* batch, int stacking_delay) batch->commit(); // Update title - if(editor.getMap().doChange()) + if(batch->isNoSelection() && editor.getMap().doChange()) { g_gui.UpdateTitle(); + } - if(batch->type == ACTION_REMOTE) { + if(batch->getType() == ACTION_REMOTE) { delete batch; return; } @@ -651,7 +617,7 @@ void ActionQueue::addAction(Action* action, int stacking_delay) { BatchAction* batch = createBatch(action->getType()); batch->addAndCommitAction(action); - if(batch->size() == 0) { + if(batch->empty()) { delete batch; return; } @@ -659,43 +625,97 @@ void ActionQueue::addAction(Action* action, int stacking_delay) addBatch(batch, stacking_delay); } -void ActionQueue::undo() +const BatchAction* ActionQueue::getAction(size_t index) const +{ + if(index >= 0 && index < actions.size()) { + return actions.at(index); + } + return nullptr; +} + +void ActionQueue::generateLabels() +{ + for(BatchAction* batch : actions) { + if(batch && batch->label.IsEmpty()) { + batch->label = createLabel(batch->getType()); + } + } +} + +bool ActionQueue::undo() { if(current > 0) { current--; - BatchAction* batch = actions[current]; - batch->undo(); + BatchAction* batch = actions.at(current); + if(batch) { + batch->undo(); + } + + // Update title + if(batch->isNoSelection() && editor.getMap().doChange()) { + g_gui.UpdateTitle(); + } + return true; } + return false; } -void ActionQueue::redo() +bool ActionQueue::redo() { if(current < actions.size()) { - BatchAction* batch = actions[current]; - batch->redo(); + BatchAction* batch = actions.at(current); + if(batch) { + batch->redo(); + } current++; + + // Update title + if(batch->isNoSelection() && editor.getMap().doChange()) { + g_gui.UpdateTitle(); + } + return true; } + return false; } -void ActionQueue::clear() +bool ActionQueue::hasChanges() const { - for(ActionList::iterator it = actions.begin(); it != actions.end();) { - delete *it; - it = actions.erase(it); + for(const BatchAction* batch : actions) { + if(batch && !batch->empty() && batch->isNoSelection()) { + return true; + } } - current = 0; + return false; } - -DirtyList::DirtyList() : - owner(0) +void ActionQueue::clear() { - ; + for(BatchAction* batch : actions) { + delete batch; + } + actions.clear(); + current = 0; } -DirtyList::~DirtyList() -{ - ; +wxString ActionQueue::createLabel(ActionIdentifier type) +{ + switch (type) { + case ACTION_MOVE: return "Move"; + case ACTION_SELECT: return "Select"; + case ACTION_UNSELECT: return "Unselect"; + case ACTION_DELETE_TILES: return "Delete"; + case ACTION_CUT_TILES: return "Cut"; + case ACTION_PASTE_TILES: return "Paste"; + case ACTION_RANDOMIZE: return "Randomize"; + case ACTION_BORDERIZE: return "Borderize"; + case ACTION_DRAW: return "Draw"; + case ACTION_ERASE: return "Erase"; + case ACTION_SWITCHDOOR: return "Switch Door"; + case ACTION_ROTATE_ITEM: return "Rotate Item"; + case ACTION_REPLACE_ITEMS: return "Replace"; + case ACTION_CHANGE_PROPERTIES: return "Change Properties"; + default: return wxEmptyString; + } } void DirtyList::AddPosition(int x, int y, int z) diff --git a/source/action.h b/source/action.h index 5a67ce77..0ea3eb47 100644 --- a/source/action.h +++ b/source/action.h @@ -31,6 +31,24 @@ class Action; class BatchAction; class ActionQueue; +enum ActionIdentifier { + ACTION_MOVE, + ACTION_REMOTE, + ACTION_SELECT, + ACTION_UNSELECT, + ACTION_DELETE_TILES, + ACTION_CUT_TILES, + ACTION_PASTE_TILES, + ACTION_RANDOMIZE, + ACTION_BORDERIZE, + ACTION_DRAW, + ACTION_ERASE, + ACTION_SWITCHDOOR, + ACTION_ROTATE_ITEM, + ACTION_REPLACE_ITEMS, + ACTION_CHANGE_PROPERTIES, +}; + enum ChangeType { CHANGE_NONE, CHANGE_TILE, @@ -38,27 +56,38 @@ enum ChangeType { CHANGE_MOVE_WAYPOINT, }; +struct HouseData { + uint32_t id; + Position position; +}; + +struct WaypointData { + std::string id; + Position position; +}; + class Change { -private: - ChangeType type; - void* data; - Change(); public: Change(Tile* tile); - static Change* Create(House* house, const Position& where); - static Change* Create(Waypoint* wp, const Position& where); ~Change(); + + static Change* Create(House* house, const Position& position); + static Change* Create(Waypoint* waypoint, const Position& position); + void clear(); ChangeType getType() const noexcept { return type; } void* getData() const noexcept { return data; } - // Get memory footprint uint32_t memsize() const; +private: + ChangeType type; + void* data; + friend class Action; }; @@ -68,15 +97,12 @@ typedef std::vector ChangeList; class DirtyList { public: - DirtyList(); - ~DirtyList(); - struct ValueType { uint32_t pos; uint32_t floors; }; - uint32_t owner; + uint32_t owner = 0; protected: struct Comparator { @@ -84,6 +110,7 @@ class DirtyList return a.pos < b.pos; } }; + public: typedef std::set SetType; @@ -99,22 +126,6 @@ class DirtyList ChangeList ichanges; }; -enum ActionIdentifier { - ACTION_MOVE, - ACTION_REMOTE, - ACTION_SELECT, - ACTION_DELETE_TILES, - ACTION_CUT_TILES, - ACTION_PASTE_TILES, - ACTION_RANDOMIZE, - ACTION_BORDERIZE, - ACTION_DRAW, - ACTION_SWITCHDOOR, - ACTION_ROTATE_ITEM, - ACTION_REPLACE_ITEMS, - ACTION_CHANGE_PROPERTIES, -}; - class Action { public: @@ -128,6 +139,7 @@ class Action size_t approx_memsize() const; size_t memsize() const; size_t size() const noexcept { return changes.size(); } + bool empty() const noexcept { return changes.empty(); } ActionIdentifier getType() const noexcept { return type; } void commit(DirtyList* dirty_list); @@ -135,7 +147,6 @@ class Action void undo(DirtyList* dirty_list); void redo(DirtyList* dirty_list) {commit(dirty_list);} - protected: Action(Editor& editor, ActionIdentifier ident); @@ -159,7 +170,10 @@ class BatchAction // Get memory footprint size_t memsize(bool resize = false) const; size_t size() const noexcept { return batch.size(); } + bool empty() const noexcept { return batch.empty(); } ActionIdentifier getType() const noexcept { return type; } + const wxString& getLabel() const noexcept { return label; } + bool isNoSelection() const noexcept; virtual void addAction(Action* action); virtual void addAndCommitAction(Action* action); @@ -178,6 +192,7 @@ class BatchAction uint32_t memory_size; ActionIdentifier type; ActionVector batch; + wxString label; friend class ActionQueue; }; @@ -192,21 +207,32 @@ class ActionQueue void resetTimer(); - virtual Action* createAction(ActionIdentifier ident); - virtual Action* createAction(BatchAction* parent); - virtual BatchAction* createBatch(ActionIdentifier ident); + virtual Action* createAction(ActionIdentifier identifier) const; + virtual Action* createAction(BatchAction* parent) const; + virtual BatchAction* createBatch(ActionIdentifier identifier) const; void addBatch(BatchAction* action, int stacking_delay = 0); void addAction(Action* action, int stacking_delay = 0); - void undo(); - void redo(); + bool undo(); + bool redo(); void clear(); - bool canUndo() noexcept { return current > 0; } - bool canRedo() noexcept { return current < actions.size(); } + const ActionList& getActions() const noexcept { return actions; } + const BatchAction* getAction(size_t index) const; + int getCurrentIndex() const noexcept { return current; } + bool canUndo() const noexcept { return current > 0; } + bool canRedo() const noexcept { return current < actions.size(); } + size_t size() const noexcept { return actions.size(); } + bool empty() const noexcept { return actions.empty(); } + + bool hasChanges() const; + + void generateLabels(); protected: + static wxString createLabel(ActionIdentifier type); + size_t current; size_t memory_size; Editor& editor; diff --git a/source/actions_history_window.cpp b/source/actions_history_window.cpp new file mode 100644 index 00000000..43a53de3 --- /dev/null +++ b/source/actions_history_window.cpp @@ -0,0 +1,183 @@ +////////////////////////////////////////////////////////////////////// +// This file is part of Remere's Map Editor +////////////////////////////////////////////////////////////////////// +// Remere's Map Editor is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Remere's Map Editor is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +////////////////////////////////////////////////////////////////////// + +#include "main.h" +#include "actions_history_window.h" +#include "artprovider.h" +#include "editor.h" +#include "gui.h" + +HistoryListBox::HistoryListBox(wxWindow* parent) : + wxVListBox(parent, wxID_ANY) +{ + wxSize icon_size = FROM_DIP(parent, wxSize(16, 16)); + open_bitmap = wxArtProvider::GetBitmap(wxART_FILE_OPEN, wxART_TOOLBAR, icon_size); + move_bitmap = wxArtProvider::GetBitmap(ART_MOVE, wxART_LIST, icon_size); + remote_bitmap = wxArtProvider::GetBitmap(ART_REMOTE, wxART_LIST, icon_size); + select_bitmap = wxArtProvider::GetBitmap(ART_SELECT, wxART_LIST, icon_size); + unselect_bitmap = wxArtProvider::GetBitmap(ART_UNSELECT, wxART_LIST, icon_size); + delete_bitmap = wxArtProvider::GetBitmap(ART_DELETE, wxART_LIST, icon_size); + cut_bitmap = wxArtProvider::GetBitmap(ART_CUT, wxART_LIST, icon_size); + paste_bitmap = wxArtProvider::GetBitmap(ART_PASTE, wxART_LIST, icon_size); + randomize_bitmap = wxArtProvider::GetBitmap(ART_RANDOMIZE, wxART_LIST, icon_size); + borderize_bitmap = wxArtProvider::GetBitmap(ART_BORDERIZE, wxART_LIST, icon_size); + draw_bitmap = wxArtProvider::GetBitmap(ART_DRAW, wxART_LIST, icon_size); + erase_bitmap = wxArtProvider::GetBitmap(ART_ERASE, wxART_LIST, icon_size); + switch_bitmap = wxArtProvider::GetBitmap(ART_SWITCH, wxART_LIST, icon_size); + rotate_bitmap = wxArtProvider::GetBitmap(ART_ROTATE, wxART_LIST, icon_size); + replace_bitmap = wxArtProvider::GetBitmap(ART_REPLACE, wxART_LIST, icon_size); + change_bitmap = wxArtProvider::GetBitmap(ART_CHANGE, wxART_LIST, icon_size); +} + +void HistoryListBox::OnDrawItem(wxDC& dc, const wxRect& rect, size_t index) const +{ + const Editor* editor = g_gui.GetCurrentEditor(); + if(!editor) { + return; + } + + const ActionQueue* actions = editor->getHistoryActions(); + if(!actions) { + return; + } + + if(IsSelected(index)) { + dc.SetTextForeground(*wxBLUE); + } else { + dc.SetTextForeground(*wxBLACK); + } + + const BatchAction* action = actions->getAction(index - 1); + if(action) { + const wxBitmap& bitmap = getIconBitmap(action->getType()); + dc.DrawBitmap(bitmap, rect.GetX() + 4, rect.GetY() + 4, true); + dc.DrawText(action->getLabel(), rect.GetX() + 28, rect.GetY() + 3); + } else { + dc.DrawBitmap(open_bitmap, rect.GetX() + 4, rect.GetY() + 4, true); + dc.DrawText("Open Map", rect.GetX() + 28, rect.GetY() + 3); + } +} + +wxCoord HistoryListBox::OnMeasureItem(size_t index) const +{ + return 24; +} + +const wxBitmap& HistoryListBox::getIconBitmap(ActionIdentifier identifier) const +{ + switch (identifier) + { + case ACTION_MOVE: + return move_bitmap; + case ACTION_REMOTE: + return remote_bitmap; + case ACTION_SELECT: + return select_bitmap; + case ACTION_UNSELECT: + return unselect_bitmap; + case ACTION_DELETE_TILES: + return delete_bitmap; + case ACTION_CUT_TILES: + return cut_bitmap; + case ACTION_PASTE_TILES: + return paste_bitmap; + case ACTION_RANDOMIZE: + return randomize_bitmap; + case ACTION_BORDERIZE: + return borderize_bitmap; + case ACTION_DRAW: + return draw_bitmap; + case ACTION_ERASE: + return erase_bitmap; + case ACTION_SWITCHDOOR: + return switch_bitmap; + case ACTION_ROTATE_ITEM: + return rotate_bitmap; + case ACTION_REPLACE_ITEMS: + return replace_bitmap; + case ACTION_CHANGE_PROPERTIES: + return change_bitmap; + default: + return wxNullBitmap; + } +} + +ActionsHistoryWindow::ActionsHistoryWindow(wxWindow* parent) : + wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(230, 250)) +{ + SetSizeHints(wxDefaultSize, wxDefaultSize); + + wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); + list = new HistoryListBox(this); + list->SetCanFocus(false); + sizer->Add(list, 1, wxEXPAND, 5); + + SetSizer(sizer); + Layout(); + + // Connect Events + list->Connect(wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(ActionsHistoryWindow::OnListSelected), NULL, this); +} + +ActionsHistoryWindow::~ActionsHistoryWindow() +{ + // Disconnect Events + list->Disconnect(wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(ActionsHistoryWindow::OnListSelected), NULL, this); +} + +void ActionsHistoryWindow::RefreshActions() +{ + if(!IsShownOnScreen()) + return; + + const Editor* editor = g_gui.GetCurrentEditor(); + if(!editor) { + list->SetItemCount(0); + list->Refresh(); + return; + } + + size_t count = 1; + int selection = 0; + + const ActionQueue* actions = editor->getHistoryActions(); + if(actions) { + count += actions->size(); + selection += actions->getCurrentIndex(); + } + + list->SetItemCount(count); + list->SetSelection(selection); + list->Refresh(); +} + +void ActionsHistoryWindow::OnListSelected(wxCommandEvent& event) +{ + int index = list->GetSelection(); + if(index == wxNOT_FOUND) + return; + + Editor* editor = g_gui.GetCurrentEditor(); + if(editor && editor->getHistoryActions()) { + int current = editor->getHistoryActions()->getCurrentIndex(); + if(index > current) { + editor->redo(index - current); + } else if (index < current) { + editor->undo(current - index); + } + } +} diff --git a/source/actions_history_window.h b/source/actions_history_window.h new file mode 100644 index 00000000..2007f6b8 --- /dev/null +++ b/source/actions_history_window.h @@ -0,0 +1,67 @@ +////////////////////////////////////////////////////////////////////// +// This file is part of Remere's Map Editor +////////////////////////////////////////////////////////////////////// +// Remere's Map Editor is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Remere's Map Editor is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +////////////////////////////////////////////////////////////////////// + +#ifndef RME_ACTIONS_HISTORY_WINDOW_H_ +#define RME_ACTIONS_HISTORY_WINDOW_H_ + +#include "main.h" +#include "action.h" + +class HistoryListBox : public wxVListBox +{ +public: + HistoryListBox(wxWindow *parent); + + void OnDrawItem(wxDC& dc, const wxRect& rect, size_t index) const override; + wxCoord OnMeasureItem(size_t index) const override; + +private: + const wxBitmap& getIconBitmap(ActionIdentifier identifier) const; + + wxBitmap open_bitmap; + wxBitmap move_bitmap; + wxBitmap remote_bitmap; + wxBitmap select_bitmap; + wxBitmap unselect_bitmap; + wxBitmap delete_bitmap; + wxBitmap cut_bitmap; + wxBitmap paste_bitmap; + wxBitmap randomize_bitmap; + wxBitmap borderize_bitmap; + wxBitmap draw_bitmap; + wxBitmap erase_bitmap; + wxBitmap switch_bitmap; + wxBitmap rotate_bitmap; + wxBitmap replace_bitmap; + wxBitmap change_bitmap; +}; + +class ActionsHistoryWindow : public wxPanel +{ +public: + ActionsHistoryWindow(wxWindow* parent); + virtual ~ActionsHistoryWindow(); + + void RefreshActions(); + + void OnListSelected(wxCommandEvent& event); + +protected: + HistoryListBox* list; +}; + +#endif diff --git a/source/application.cpp b/source/application.cpp index 2ab3a9c7..aa773482 100644 --- a/source/application.cpp +++ b/source/application.cpp @@ -52,6 +52,7 @@ BEGIN_EVENT_TABLE(MainFrame, wxFrame) EVT_ON_UPDATE_CHECK_FINISHED(wxID_ANY, MainFrame::OnUpdateReceived) #endif EVT_ON_UPDATE_MENUS(wxID_ANY, MainFrame::OnUpdateMenus) + EVT_ON_UPDATE_ACTIONS(wxID_ANY, MainFrame::OnUpdateActions) // Idle event handler EVT_IDLE(MainFrame::OnIdle) @@ -288,7 +289,7 @@ void Application::OnEventLoopEnter(wxEventLoopBase* loop) { g_gui.LoadMap(FileName(m_file_to_open)); } else if (!g_gui.IsWelcomeDialogShown() && g_gui.NewMap()) { //Open a new empty map // You generally don't want to save this map... - g_gui.GetCurrentEditor()->getMap().clearChanges(); + g_gui.GetCurrentEditor()->clearChanges(); } } @@ -444,6 +445,12 @@ void MainFrame::OnUpdateMenus(wxCommandEvent&) g_gui.UpdateTitle(); } +void MainFrame::OnUpdateActions(wxCommandEvent&) +{ + tool_bar->UpdateButtons(); + g_gui.RefreshActions(); +} + #ifdef __WINDOWS__ bool MainFrame::MSWTranslateMessage(WXMSG *msg) { diff --git a/source/application.h b/source/application.h index 5d62d3dc..e7cb2987 100644 --- a/source/application.h +++ b/source/application.h @@ -84,6 +84,7 @@ class MainFrame : public wxFrame MainToolBar* GetAuiToolBar() const { return tool_bar; } void OnUpdateMenus(wxCommandEvent& event); + void OnUpdateActions(wxCommandEvent& event); void UpdateFloorMenu(); void UpdateIndicatorsMenu(); void OnIdle(wxIdleEvent& event); diff --git a/source/artprovider.cpp b/source/artprovider.cpp index df715faa..f9def880 100644 --- a/source/artprovider.cpp +++ b/source/artprovider.cpp @@ -40,12 +40,26 @@ #include "../icons/toolbar_hooks.xpm" #include "../icons/toolbar_pickupables.xpm" #include "../icons/toolbar_moveables.xpm" - #include "../icons/spawns.xpm" #include "../icons/house_exit.xpm" #include "../icons/pickupable.xpm" #include "../icons/moveable.xpm" #include "../icons/pickupable_moveable.xpm" +#include "../icons/mini_move.xpm" +#include "../icons/mini_remote.xpm" +#include "../icons/mini_select.xpm" +#include "../icons/mini_unselect.xpm" +#include "../icons/mini_delete.xpm" +#include "../icons/mini_cut.xpm" +#include "../icons/mini_paste.xpm" +#include "../icons/mini_randomize.xpm" +#include "../icons/mini_borderize.xpm" +#include "../icons/mini_draw.xpm" +#include "../icons/mini_erase.xpm" +#include "../icons/mini_switch.xpm" +#include "../icons/mini_rotate.xpm" +#include "../icons/mini_replace.xpm" +#include "../icons/mini_change.xpm" wxBitmap ArtProvider::CreateBitmap(const wxArtID& id, const wxArtClient& client, const wxSize& WXUNUSED(size)) @@ -99,8 +113,39 @@ wxBitmap ArtProvider::CreateBitmap(const wxArtID& id, const wxArtClient& client, return wxBitmap(toolbar_pickupables_xpm); else if (id == ART_MOVEABLE_TOOLBAR) return wxBitmap(toolbar_moveable_xpm); - } else if (client == wxART_OTHER) { - if (id == ART_SPAWNS) + } else if(client == wxART_LIST) { + if(id == ART_MOVE) + return wxBitmap(mini_move_xpm); + else if(id == ART_REMOTE) + return wxBitmap(mini_remote_xpm); + else if(id == ART_SELECT) + return wxBitmap(mini_select_xpm); + else if(id == ART_UNSELECT) + return wxBitmap(mini_unselect_xpm); + else if(id == ART_DELETE) + return wxBitmap(mini_delete_xpm); + else if(id == ART_CUT) + return wxBitmap(mini_cut_xpm); + else if(id == ART_PASTE) + return wxBitmap(mini_paste_xpm); + else if(id == ART_RANDOMIZE) + return wxBitmap(mini_randomize_xpm); + else if(id == ART_BORDERIZE) + return wxBitmap(mini_borderize_xpm); + else if(id == ART_DRAW) + return wxBitmap(mini_draw_xpm); + else if(id == ART_ERASE) + return wxBitmap(mini_erase_xpm); + else if(id == ART_SWITCH) + return wxBitmap(mini_switch_xpm); + else if(id == ART_ROTATE) + return wxBitmap(mini_rotate_xpm); + else if(id == ART_REPLACE) + return wxBitmap(mini_replace_xpm); + else if(id == ART_CHANGE) + return wxBitmap(mini_change_xpm); + } else if(client == wxART_OTHER) { + if(id == ART_SPAWNS) return wxBitmap(spawns_xpm); else if (id == ART_HOUSE_EXIT) return wxBitmap(house_exit_xpm); diff --git a/source/artprovider.h b/source/artprovider.h index 0113c2a4..f0d53903 100644 --- a/source/artprovider.h +++ b/source/artprovider.h @@ -52,6 +52,22 @@ #define ART_MOVEABLE wxART_MAKE_ART_ID(ART_MOVEABLE) #define ART_PICKUPABLE_MOVEABLE wxART_MAKE_ART_ID(ART_PICKUPABLE_MOVEABLE) +#define ART_MOVE wxART_MAKE_ART_ID(ART_MOVE) +#define ART_REMOTE wxART_MAKE_ART_ID(ART_REMOTE) +#define ART_SELECT wxART_MAKE_ART_ID(ART_SELECT) +#define ART_UNSELECT wxART_MAKE_ART_ID(ART_UNSELECT) +#define ART_DELETE wxART_MAKE_ART_ID(ART_DELETE) +#define ART_CUT wxART_MAKE_ART_ID(ART_CUT) +#define ART_PASTE wxART_MAKE_ART_ID(ART_PASTE) +#define ART_RANDOMIZE wxART_MAKE_ART_ID(ART_RANDOMIZE) +#define ART_BORDERIZE wxART_MAKE_ART_ID(ART_BORDERIZE) +#define ART_DRAW wxART_MAKE_ART_ID(ART_DRAW) +#define ART_ERASE wxART_MAKE_ART_ID(ART_ERASE) +#define ART_SWITCH wxART_MAKE_ART_ID(ART_SWITCH) +#define ART_ROTATE wxART_MAKE_ART_ID(ART_ROTATE) +#define ART_REPLACE wxART_MAKE_ART_ID(ART_REPLACE) +#define ART_CHANGE wxART_MAKE_ART_ID(ART_CHANGE) + class ArtProvider : public wxArtProvider { protected: diff --git a/source/common.h b/source/common.h index b388c96c..bcac09a9 100644 --- a/source/common.h +++ b/source/common.h @@ -28,7 +28,7 @@ #include "mt_rand.h" // -inline bool testFlags(size_t flags, size_t test) { +inline bool testFlags(size_t flags, size_t test) noexcept { return (flags & test) != 0; } diff --git a/source/common_windows.cpp b/source/common_windows.cpp index b6d5960a..3c2ba093 100644 --- a/source/common_windows.cpp +++ b/source/common_windows.cpp @@ -266,7 +266,7 @@ void MapPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) // Switch version g_gui.GetCurrentEditor()->getSelection().clear(); - g_gui.GetCurrentEditor()->getHistoryActions()->clear(); + g_gui.GetCurrentEditor()->clearActions(); if(new_ver.client < old_ver.client) { int ret = g_gui.PopupDialog(this, "Notice", diff --git a/source/copybuffer.cpp b/source/copybuffer.cpp index 72e4d03a..7a500f4a 100644 --- a/source/copybuffer.cpp +++ b/source/copybuffer.cpp @@ -133,8 +133,8 @@ void CopyBuffer::cut(Editor& editor, int floor) int item_count = 0; copyPos = Position(0xFFFF, 0xFFFF, floor); - BatchAction* batch = editor.getHistoryActions()->createBatch(ACTION_CUT_TILES); - Action* action = editor.getHistoryActions()->createAction(batch); + BatchAction* batch = editor.createBatch(ACTION_CUT_TILES); + Action* action = editor.createAction(batch); PositionList tilestoborder; @@ -205,7 +205,7 @@ void CopyBuffer::cut(Editor& editor, int floor) tilestoborder.unique(); if(g_settings.getInteger(Config::USE_AUTOMAGIC)) { - action = editor.getHistoryActions()->createAction(batch); + action = editor.createAction(batch); for(PositionList::iterator it = tilestoborder.begin(); it != tilestoborder.end(); ++it) { TileLocation* location = map.createTileL(*it); if(location->get()) { @@ -228,6 +228,8 @@ void CopyBuffer::cut(Editor& editor, int floor) } editor.addBatch(batch); + editor.updateActions(); + std::stringstream ss; ss << "Cut out " << tile_count << " tile" << (tile_count > 1 ? "s" : "") << " (" << item_count << " item" << (item_count > 1? "s" : "") << ")"; g_gui.SetStatusText(wxstr(ss.str())); @@ -241,8 +243,8 @@ void CopyBuffer::paste(Editor& editor, const Position& toPosition) Map& map = editor.getMap(); - BatchAction* batchAction = editor.getHistoryActions()->createBatch(ACTION_PASTE_TILES); - Action* action = editor.getHistoryActions()->createAction(batchAction); + BatchAction* batchAction = editor.createBatch(ACTION_PASTE_TILES); + Action* action = editor.createAction(batchAction); for(MapIterator it = tiles->begin(); it != tiles->end(); ++it) { Tile* buffer_tile = (*it)->get(); Position pos = buffer_tile->getPosition() - copyPos + toPosition; @@ -283,7 +285,7 @@ void CopyBuffer::paste(Editor& editor, const Position& toPosition) batchAction->addAndCommitAction(action); if(g_settings.getInteger(Config::USE_AUTOMAGIC) && g_settings.getInteger(Config::BORDERIZE_PASTE)) { - action = editor.getHistoryActions()->createAction(batchAction); + action = editor.createAction(batchAction); TileList borderize_tiles; // Go through all modified (selected) tiles (might be slow) @@ -328,6 +330,7 @@ void CopyBuffer::paste(Editor& editor, const Position& toPosition) } editor.addBatch(batchAction); + editor.updateActions(); } bool CopyBuffer::canPaste() const diff --git a/source/editor.cpp b/source/editor.cpp index 3d4e468a..5d176db2 100644 --- a/source/editor.cpp +++ b/source/editor.cpp @@ -168,16 +168,101 @@ Editor::~Editor() delete actionQueue; } +Action* Editor::createAction(ActionIdentifier type) +{ + return actionQueue->createAction(type); +} + +Action* Editor::createAction(BatchAction* parent) +{ + return actionQueue->createAction(parent); +} + +BatchAction* Editor::createBatch(ActionIdentifier type) +{ + return actionQueue->createBatch(type); +} + void Editor::addBatch(BatchAction* action, int stacking_delay) { actionQueue->addBatch(action, stacking_delay); - g_gui.UpdateMenus(); } void Editor::addAction(Action* action, int stacking_delay ) { actionQueue->addAction(action, stacking_delay); +} + +bool Editor::canUndo() const +{ + return actionQueue->canUndo(); +} + +bool Editor::canRedo() const +{ + return actionQueue->canRedo(); +} + +void Editor::undo(int indexes) +{ + if(indexes <= 0 || !actionQueue->canUndo()) + return; + + while(indexes > 0) { + if(!actionQueue->undo()) + break; + indexes--; + } + g_gui.UpdateActions(); + g_gui.RefreshView(); +} + +void Editor::redo(int indexes) +{ + if(indexes <= 0 || !actionQueue->canRedo()) + return; + + while(indexes > 0) { + if(!actionQueue->redo()) + break; + indexes--; + } + g_gui.UpdateActions(); + g_gui.RefreshView(); +} + +void Editor::updateActions() +{ + actionQueue->generateLabels(); g_gui.UpdateMenus(); + g_gui.UpdateActions(); +} + +void Editor::resetActionsTimer() +{ + actionQueue->resetTimer(); +} + +void Editor::clearActions() +{ + actionQueue->clear(); + g_gui.UpdateActions(); +} + +bool Editor::hasChanges() const +{ + if(map.hasChanged()) { + if(map.getTileCount() == 0) { + return actionQueue->hasChanges(); + } + return true; + } + return false; +} + +void Editor::clearChanges() +{ + map.clearChanges(); } void Editor::saveMap(FileName filename, bool showdialog) @@ -324,7 +409,6 @@ void Editor::saveMap(FileName filename, bool showdialog) return; } - // Move to permanent backup if(!save_as && g_settings.getInteger(Config::ALWAYS_MAKE_BACKUP)) { // Move temporary backups to their proper files @@ -374,7 +458,7 @@ void Editor::saveMap(FileName filename, bool showdialog) std::remove(backup_spawn_npc.c_str()); } - map.clearChanges(); + clearChanges(); } bool Editor::importMiniMap(FileName filename, int import, int import_x_offset, int import_y_offset, int import_z_offset) @@ -864,18 +948,20 @@ bool Editor::importMap(FileName filename, int import_x_offset, int import_y_offs void Editor::borderizeSelection() { - if(selection.size() == 0) { + if(selection.empty()) { g_gui.SetStatusText("No items selected. Can't borderize."); + return; } Action* action = actionQueue->createAction(ACTION_BORDERIZE); - for(Tile* tile : selection) { - Tile* newTile = tile->deepCopy(map); - newTile->borderize(&map); - newTile->select(); - action->addChange(newd Change(newTile)); + for(const Tile* tile : selection) { + Tile* new_tile = tile->deepCopy(map); + new_tile->borderize(&map); + new_tile->select(); + action->addChange(new Change(new_tile)); } addAction(action); + updateActions(); } void Editor::borderizeMap(bool showdialog) @@ -904,29 +990,31 @@ void Editor::borderizeMap(bool showdialog) void Editor::randomizeSelection() { - if(selection.size() == 0) { + if(selection.empty()) { g_gui.SetStatusText("No items selected. Can't randomize."); + return; } Action* action = actionQueue->createAction(ACTION_RANDOMIZE); - for(Tile* tile : selection) { - Tile* newTile = tile->deepCopy(map); - GroundBrush* groundBrush = newTile->getGroundBrush(); - if(groundBrush && groundBrush->isReRandomizable()) { - groundBrush->draw(&map, newTile, nullptr); - - Item* oldGround = tile->ground; - Item* newGround = newTile->ground; - if(oldGround && newGround) { - newGround->setActionID(oldGround->getActionID()); - newGround->setUniqueID(oldGround->getUniqueID()); + for(const Tile* tile : selection) { + Tile* new_tile = tile->deepCopy(map); + GroundBrush* brush = new_tile->getGroundBrush(); + if(brush && brush->isReRandomizable()) { + brush->draw(&map, new_tile, nullptr); + + Item* old_ground = tile->ground; + Item* new_ground = new_tile->ground; + if(old_ground && new_ground) { + new_ground->setActionID(old_ground->getActionID()); + new_ground->setUniqueID(old_ground->getUniqueID()); } - newTile->select(); - action->addChange(newd Change(newTile)); + new_tile->select(); + action->addChange(new Change(new_tile)); } } addAction(action); + updateActions(); } void Editor::randomizeMap(bool showdialog) @@ -1050,84 +1138,72 @@ void Editor::clearModifiedTileState(bool showdialog) } } -void Editor::moveSelection(Position offset) +void Editor::moveSelection(const Position& offset) { - BatchAction* batchAction = actionQueue->createBatch(ACTION_MOVE); // Our saved action batch, for undo! - Action* action; - - // Remove tiles from the map - action = actionQueue->createAction(batchAction); // Our action! - bool doborders = false; - TileSet tmp_storage; - - // Update the tiles with the newd positions - for(TileSet::iterator it = selection.begin(); it != selection.end(); ++it) { - // First we get the old tile and it's position - Tile* tile = (*it); - //const Position pos = tile->getPosition(); + if(!CanEdit() || !hasSelection()) { + return; + } - // Create the duplicate source tile, which will replace the old one later - Tile* old_src_tile = tile; - Tile* new_src_tile; + bool borderize = false; + int drag_threshold = g_settings.getInteger(Config::BORDERIZE_DRAG_THRESHOLD); + bool create_borders = g_settings.getInteger(Config::USE_AUTOMAGIC) + && g_settings.getInteger(Config::BORDERIZE_DRAG); - new_src_tile = old_src_tile->deepCopy(map); + TileSet storage; + BatchAction* batch_action = actionQueue->createBatch(ACTION_MOVE); + Action* action = actionQueue->createAction(batch_action); - Tile* tmp_storage_tile = map.allocator(tile->getLocation()); + // Update the tiles with the new positions + for(Tile* tile : selection) { + Tile* new_tile = tile->deepCopy(map); + Tile* storage_tile = map.allocator(tile->getLocation()); - // Get all the selected items from the NEW source tile and iterate through them - // This transfers ownership to the temporary tile - ItemVector tile_selection = new_src_tile->popSelectedItems(); - for(ItemVector::iterator iit = tile_selection.begin(); iit != tile_selection.end(); iit++) { - // Add the copied item to the newd destination tile, - Item* item = (*iit); - tmp_storage_tile->addItem(item); + ItemVector selected_items = new_tile->popSelectedItems(); + for(Item* item : selected_items) { + storage_tile->addItem(item); } + // Move monster spawns - if(new_src_tile->spawnMonster && new_src_tile->spawnMonster->isSelected()) { - tmp_storage_tile->spawnMonster = new_src_tile->spawnMonster; - new_src_tile->spawnMonster = nullptr; + if(new_tile->spawnMonster && new_tile->spawnMonster->isSelected()) { + storage_tile->spawnMonster = new_tile->spawnMonster; + new_tile->spawnMonster = nullptr; } // Move monster - if(new_src_tile->monster && new_src_tile->monster->isSelected()) { - tmp_storage_tile->monster = new_src_tile->monster; - new_src_tile->monster = nullptr; + if(new_tile->monster && new_tile->monster->isSelected()) { + storage_tile->monster = new_tile->monster; + new_tile->monster = nullptr; } // Move npc - if(new_src_tile->npc && new_src_tile->npc->isSelected()) { - tmp_storage_tile->npc = new_src_tile->npc; - new_src_tile->npc = nullptr; + if(new_tile->npc && new_tile->npc->isSelected()) { + storage_tile->npc = new_tile->npc; + new_tile->npc = nullptr; } // Move npc spawns - if(new_src_tile->spawnNpc && new_src_tile->spawnNpc->isSelected()) { - tmp_storage_tile->spawnNpc = new_src_tile->spawnNpc; - new_src_tile->spawnNpc = nullptr; + if(new_tile->spawnNpc && new_tile->spawnNpc->isSelected()) { + storage_tile->spawnNpc = new_tile->spawnNpc; + new_tile->spawnNpc = nullptr; } - // Move house data & tile status if ground is transferred - if(tmp_storage_tile->ground) { - tmp_storage_tile->house_id = new_src_tile->house_id; - new_src_tile->house_id = 0; - tmp_storage_tile->setMapFlags(new_src_tile->getMapFlags()); - new_src_tile->setMapFlags(TILESTATE_NONE); - doborders = true; + if(storage_tile->ground) { + storage_tile->house_id = new_tile->house_id; + new_tile->house_id = 0; + storage_tile->setMapFlags(new_tile->getMapFlags()); + new_tile->setMapFlags(TILESTATE_NONE); + borderize = true; } - tmp_storage.insert(tmp_storage_tile); - // Add the tile copy to the action - action->addChange(newd Change(new_src_tile)); + storage.insert(storage_tile); + action->addChange(new Change(new_tile)); } - // Commit changes to map - batchAction->addAndCommitAction(action); + batch_action->addAndCommitAction(action); - // Remove old borders (and create some newd?) - if(g_settings.getInteger(Config::USE_AUTOMAGIC) && - g_settings.getInteger(Config::BORDERIZE_DRAG) && - selection.size() < size_t(g_settings.getInteger(Config::BORDERIZE_DRAG_THRESHOLD))) { - action = actionQueue->createAction(batchAction); + // Remove old borders (and create some new?) + if(create_borders && selection.size() < static_cast(drag_threshold)) { + action = actionQueue->createAction(batch_action); TileList borderize_tiles; // Go through all modified (selected) tiles (might be slow) - for(TileSet::iterator it = tmp_storage.begin(); it != tmp_storage.end(); ++it) { - const Position& pos = (*it)->getPosition(); + for(const Tile* tile : storage) { + const Position& pos = tile->getPosition(); // Go through all neighbours Tile* t; t = map.getTile(pos.x , pos.y , pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t);} @@ -1140,43 +1216,43 @@ void Editor::moveSelection(Position offset) t = map.getTile(pos.x , pos.y+1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t);} t = map.getTile(pos.x+1, pos.y+1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t);} } + // Remove duplicates borderize_tiles.sort(); borderize_tiles.unique(); - // Do le borders! - for(TileList::iterator it = borderize_tiles.begin(); it != borderize_tiles.end(); ++it) { - Tile* tile = *it; - Tile* new_tile = (*it)->deepCopy(map); - if(doborders) new_tile->borderize(&map); + + // Create borders + for(const Tile* tile : borderize_tiles) { + Tile* new_tile = tile->deepCopy(map); + if(borderize) { + new_tile->borderize(&map); + } new_tile->wallize(&map); new_tile->tableize(&map); new_tile->carpetize(&map); - if(tile->ground && tile->ground->isSelected()) new_tile->selectGround(); - action->addChange(newd Change(new_tile)); + if(tile->ground && tile->ground->isSelected()) { + new_tile->selectGround(); + } + action->addChange(new Change(new_tile)); } - // Commit changes to map - batchAction->addAndCommitAction(action); + batch_action->addAndCommitAction(action); } // New action for adding the destination tiles - action = actionQueue->createAction(batchAction); - for(TileSet::iterator it = tmp_storage.begin(); it != tmp_storage.end(); ++it) { - Tile* tile = (*it); - const Position old_pos = tile->getPosition(); - Position new_pos; - - new_pos = old_pos - offset; - + action = actionQueue->createAction(batch_action); + for(Tile* tile : storage) { + const Position& old_pos = tile->getPosition(); + Position new_pos = old_pos - offset; if(new_pos.z < 0 && new_pos.z > MAP_MAX_LAYER) { delete tile; continue; } - // Create the duplicate dest tile, which will replace the old one later + TileLocation* location = map.createTileL(new_pos); Tile* old_dest_tile = location->get(); Tile* new_dest_tile = nullptr; - if(g_settings.getInteger(Config::MERGE_MOVE) || !tile->ground) { + if(!tile->ground || g_settings.getInteger(Config::MERGE_MOVE)) { // Move items if(old_dest_tile) { new_dest_tile = old_dest_tile->deepCopy(map); @@ -1190,65 +1266,62 @@ void Editor::moveSelection(Position offset) tile->setLocation(location); new_dest_tile = tile; } - - action->addChange(newd Change(new_dest_tile)); + action->addChange(new Change(new_dest_tile)); } + batch_action->addAndCommitAction(action); - // Commit changes to the map - batchAction->addAndCommitAction(action); - - // Create borders - if(g_settings.getInteger(Config::USE_AUTOMAGIC) && - g_settings.getInteger(Config::BORDERIZE_DRAG) && - selection.size() < size_t(g_settings.getInteger(Config::BORDERIZE_DRAG_THRESHOLD))) { - action = actionQueue->createAction(batchAction); + if(create_borders && selection.size() < static_cast(drag_threshold)) { + action = actionQueue->createAction(batch_action); TileList borderize_tiles; // Go through all modified (selected) tiles (might be slow) - for(TileSet::iterator it = selection.begin(); it != selection.end(); it++) { + for(Tile* tile : selection) { bool add_me = false; // If this tile is touched - const Position& pos = (*it)->getPosition(); + const Position& pos = tile->getPosition(); // Go through all neighbours Tile* t; - t = map.getTile(pos.x-1, pos.y-1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;} - t = map.getTile(pos.x-1, pos.y-1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;} - t = map.getTile(pos.x , pos.y-1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;} - t = map.getTile(pos.x+1, pos.y-1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;} - t = map.getTile(pos.x-1, pos.y , pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;} - t = map.getTile(pos.x+1, pos.y , pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;} - t = map.getTile(pos.x-1, pos.y+1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;} - t = map.getTile(pos.x , pos.y+1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;} - t = map.getTile(pos.x+1, pos.y+1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;} - if(add_me) borderize_tiles.push_back(*it); + t = map.getTile(pos.x-1, pos.y-1, pos.z); if(t && !t->isSelected()) { borderize_tiles.push_back(t); add_me = true; } + t = map.getTile(pos.x-1, pos.y-1, pos.z); if(t && !t->isSelected()) { borderize_tiles.push_back(t); add_me = true; } + t = map.getTile(pos.x , pos.y-1, pos.z); if(t && !t->isSelected()) { borderize_tiles.push_back(t); add_me = true; } + t = map.getTile(pos.x+1, pos.y-1, pos.z); if(t && !t->isSelected()) { borderize_tiles.push_back(t); add_me = true; } + t = map.getTile(pos.x-1, pos.y , pos.z); if(t && !t->isSelected()) { borderize_tiles.push_back(t); add_me = true; } + t = map.getTile(pos.x+1, pos.y , pos.z); if(t && !t->isSelected()) { borderize_tiles.push_back(t); add_me = true; } + t = map.getTile(pos.x-1, pos.y+1, pos.z); if(t && !t->isSelected()) { borderize_tiles.push_back(t); add_me = true; } + t = map.getTile(pos.x , pos.y+1, pos.z); if(t && !t->isSelected()) { borderize_tiles.push_back(t); add_me = true; } + t = map.getTile(pos.x+1, pos.y+1, pos.z); if(t && !t->isSelected()) { borderize_tiles.push_back(t); add_me = true; } + if(add_me) { + borderize_tiles.push_back(tile); + } } + // Remove duplicates borderize_tiles.sort(); borderize_tiles.unique(); - // Do le borders! - for(TileList::iterator it = borderize_tiles.begin(); it != borderize_tiles.end(); it++) { - Tile* tile = *it; - if(tile->ground) { - if(tile->ground->getGroundBrush()) { - Tile* new_tile = tile->deepCopy(map); - - if(doborders) - new_tile->borderize(&map); - - new_tile->wallize(&map); - new_tile->tableize(&map); - new_tile->carpetize(&map); - if(tile->ground->isSelected()) - new_tile->selectGround(); - action->addChange(newd Change(new_tile)); + // Create borders + for(const Tile* tile : borderize_tiles) { + if(!tile || !tile->ground) { + continue; + } + if(tile->ground->getGroundBrush()) { + Tile* new_tile = tile->deepCopy(map); + if(borderize) { + new_tile->borderize(&map); + } + new_tile->wallize(&map); + new_tile->tableize(&map); + new_tile->carpetize(&map); + if(tile->ground->isSelected()) { + new_tile->selectGround(); } + action->addChange(new Change(new_tile)); } } - // Commit changes to map - batchAction->addAndCommitAction(action); + batch_action->addAndCommitAction(action); } // Store the action for undo - addBatch(batchAction); + addBatch(batch_action); + updateActions(); selection.updateSelectionCount(); } @@ -1342,6 +1415,8 @@ void Editor::destroySelection() } addBatch(batch); + updateActions(); + wxString ss; ss << "Deleted " << tile_count << " tile" << (tile_count > 1 ? "s" : "") << " (" << item_count << " item" << (item_count > 1? "s" : "") << ")"; g_gui.SetStatusText(ss); @@ -1371,18 +1446,30 @@ void doSurroundingBorders(DoodadBrush* doodad_brush, PositionList& tilestoborder void removeDuplicateWalls(Tile* buffer, Tile* tile) { - for(ItemVector::const_iterator iter = buffer->items.begin(); iter != buffer->items.end(); ++iter) { - if((*iter)->getWallBrush()) { - tile->cleanWalls((*iter)->getWallBrush()); + if (!buffer || buffer->items.empty() || !tile || tile->items.empty()) { + return; + } + + for(const Item* item : buffer->items) { + if(item) { + WallBrush* brush = item->getWallBrush(); + if(brush) { + tile->cleanWalls(brush); + } } } } void Editor::drawInternal(Position offset, bool alt, bool dodraw) { + if(!CanEdit()) { + return; + } + Brush* brush = g_gui.GetCurrentBrush(); - if(!brush) + if(!brush) { return; + } if(brush->isDoodad()) { BatchAction* batch = actionQueue->createBatch(ACTION_DRAW); @@ -1499,7 +1586,7 @@ void Editor::drawInternal(Position offset, bool alt, bool dodraw) batch->addAndCommitAction(action); addBatch(batch, 2); } else if(brush->isWall()) { - BatchAction* batch = actionQueue->createBatch(ACTION_DRAW); + BatchAction* batch = actionQueue->createBatch(dodraw ? ACTION_DRAW : ACTION_ERASE); Action* action = actionQueue->createAction(batch); // This will only occur with a size 0, when clicking on a tile (not drawing) Tile* tile = map.getTile(offset); @@ -1520,7 +1607,7 @@ void Editor::drawInternal(Position offset, bool alt, bool dodraw) batch->addAndCommitAction(action); addBatch(batch, 2); } else if(brush->isSpawnMonster() || brush->isMonster()) { - BatchAction* batch = actionQueue->createBatch(ACTION_DRAW); + BatchAction* batch = actionQueue->createBatch(dodraw ? ACTION_DRAW : ACTION_ERASE); Action* action = actionQueue->createAction(batch); Tile* tile = map.getTile(offset); @@ -1574,9 +1661,14 @@ void Editor::drawInternal(Position offset, bool alt, bool dodraw) void Editor::drawInternal(const PositionVector& tilestodraw, bool alt, bool dodraw) { + if(!CanEdit()) { + return; + } + Brush* brush = g_gui.GetCurrentBrush(); - if(!brush) + if(!brush) { return; + } #ifdef __DEBUG__ if(brush->isGround() || brush->isWall()) { @@ -1585,7 +1677,7 @@ void Editor::drawInternal(const PositionVector& tilestodraw, bool alt, bool dodr } #endif - Action* action = actionQueue->createAction(ACTION_DRAW); + Action* action = actionQueue->createAction(dodraw ? ACTION_DRAW : ACTION_ERASE); if(brush->isOptionalBorder()) { // We actually need to do borders, but on the same tiles we draw to @@ -1638,15 +1730,20 @@ void Editor::drawInternal(const PositionVector& tilestodraw, bool alt, bool dodr addAction(action, 2); } - void Editor::drawInternal(const PositionVector& tilestodraw, PositionVector& tilestoborder, bool alt, bool dodraw) { + if(!CanEdit()) { + return; + } + Brush* brush = g_gui.GetCurrentBrush(); - if(!brush) + if(!brush) { return; + } if(brush->isGround() || brush->isEraser()) { - BatchAction* batch = actionQueue->createBatch(ACTION_DRAW); + ActionIdentifier identifier = (dodraw && !brush->isEraser()) ? ACTION_DRAW : ACTION_ERASE; + BatchAction* batch = actionQueue->createBatch(identifier); Action* action = actionQueue->createAction(batch); for(PositionVector::const_iterator it = tilestodraw.begin(); it != tilestodraw.end(); ++it) { diff --git a/source/editor.h b/source/editor.h index 80cd58ef..60cf8d33 100644 --- a/source/editor.h +++ b/source/editor.h @@ -70,6 +70,9 @@ class Editor void QueryNode(int ndx, int ndy, bool underground); void SendNodeRequests(); + bool hasChanges() const; + void clearChanges(); + // Map handling void saveMap(FileName filename, bool showdialog); // "" means default filename @@ -85,10 +88,18 @@ class Editor bool exportSelectionAsMiniMap(FileName directory, wxString fileName); ActionQueue* getHistoryActions() const noexcept { return actionQueue; } - // Adds an action to the action queue (this allows the user to undo the action) - // Invalidates the action pointer + Action* createAction(ActionIdentifier type); + Action* createAction(BatchAction* parent); + BatchAction* createBatch(ActionIdentifier type); void addBatch(BatchAction* action, int stacking_delay = 0); void addAction(Action* action, int stacking_delay = 0); + bool canUndo() const; + bool canRedo() const; + void undo(int indexes = 1); + void redo(int indexes = 1); + void updateActions(); + void resetActionsTimer(); + void clearActions(); // Selection Selection& getSelection() noexcept { return selection; } @@ -96,7 +107,7 @@ class Editor bool hasSelection() const noexcept { return selection.size() != 0; } // Some simple actions that work on the map (these will work through the undo queue) // Moves the selected area by the offset - void moveSelection(Position offset); + void moveSelection(const Position& offset); // Deletes all selected items void destroySelection(); // Borderizes the selected region diff --git a/source/editor_tabs.cpp b/source/editor_tabs.cpp index 14c6d1cd..c293e952 100644 --- a/source/editor_tabs.cpp +++ b/source/editor_tabs.cpp @@ -45,11 +45,6 @@ MapTabbook::MapTabbook(wxWindow *parent, wxWindowID id) : SetSizerAndFit(wxz); } -MapTabbook::~MapTabbook() -{ - ; -} - void MapTabbook::CycleTab(bool forward) { if(!notebook) { @@ -68,33 +63,40 @@ void MapTabbook::CycleTab(bool forward) notebook->SetSelection(selection); } -void MapTabbook::OnNotebookPageClose(wxAuiNotebookEvent& evt) +void MapTabbook::OnNotebookPageClose(wxAuiNotebookEvent& event) { - EditorTab* editorTab = GetTab(evt.GetInt()); + EditorTab* editor_tab = GetTab(event.GetInt()); - MapTab* mapTab = dynamic_cast(editorTab); - if(mapTab && mapTab->IsUniqueReference() && mapTab->GetMap()) { - bool needRefresh = true; - if(mapTab->GetEditor()->IsLive()) { - if(mapTab->GetMap()->hasChanged()) { - SetFocusedTab(evt.GetInt()); + MapTab* map_tab = dynamic_cast(editor_tab); + if(map_tab && map_tab->IsUniqueReference() && map_tab->GetMap()) { + bool need_refresh = true; + Editor* editor = map_tab->GetEditor(); + if(editor->IsLive()) { + if(editor->hasChanges()) { + SetFocusedTab(event.GetInt()); if(!g_gui.root->DoQuerySave(false)) { - needRefresh = false; - evt.Veto(); + need_refresh = false; + event.Veto(); } } + } else if(editor->hasChanges()) { + SetFocusedTab(event.GetInt()); + if(!g_gui.root->DoQuerySave()) { + need_refresh = false; + event.Veto(); + } } - if(needRefresh) { + if(need_refresh) { g_gui.RefreshPalettes(nullptr, false); g_gui.UpdateMenus(); } return; } - LiveLogTab* lt = dynamic_cast(editorTab); - if(lt && lt->IsConnected()) { - evt.Veto(); + LiveLogTab* live_tab = dynamic_cast(editor_tab); + if(live_tab && live_tab->IsConnected()) { + event.Veto(); } } @@ -164,9 +166,9 @@ EditorTab* MapTabbook::GetCurrentTab() return dynamic_cast(GetInternalTab(GetSelection())); } -EditorTab* MapTabbook::GetTab(int idx) +EditorTab* MapTabbook::GetTab(int index) { - return GetInternalTab(idx); + return GetInternalTab(index); } wxWindow* MapTabbook::GetCurrentPage() diff --git a/source/editor_tabs.h b/source/editor_tabs.h index 5dc6ce18..114a38eb 100644 --- a/source/editor_tabs.h +++ b/source/editor_tabs.h @@ -26,7 +26,6 @@ class MapTabbook : public wxPanel { public: MapTabbook(wxWindow* parent, wxWindowID id); - ~MapTabbook(); // Wrapper functions void AddTab(EditorTab* tab, bool select); diff --git a/source/gui.cpp b/source/gui.cpp index fd755e87..f2330454 100644 --- a/source/gui.cpp +++ b/source/gui.cpp @@ -38,6 +38,7 @@ #include "application.h" #include "welcome_dialog.h" #include "spawn_npc_brush.h" +#include "actions_history_window.h" #include "live_client.h" #include "live_tab.h" @@ -48,6 +49,7 @@ #endif const wxEventType EVT_UPDATE_MENUS = wxNewEventType(); +const wxEventType EVT_UPDATE_ACTIONS = wxNewEventType(); // Global GUI instance GUI g_gui; @@ -59,6 +61,7 @@ GUI::GUI() : minimap(nullptr), gem(nullptr), search_result_window(nullptr), + actions_history_window(nullptr), secondary_map(nullptr), doodad_buffer_map(nullptr), @@ -553,14 +556,13 @@ bool GUI::NewMap() auto *mapTab = newd MapTab(tabbook, editor); mapTab->OnSwitchEditorMode(mode); - editor->getMap().clearChanges(); + editor->clearChanges(); SetStatusText("Created new map"); UpdateTitle(); RefreshPalettes(); root->UpdateMenubar(); root->Refresh(); - return true; } @@ -706,17 +708,9 @@ int GUI::GetOpenMapCount() bool GUI::ShouldSave() { - const Map& map = GetCurrentMap(); - if(map.hasChanged()) { - if(map.getTileCount() == 0) { - Editor* editor = GetCurrentEditor(); - ASSERT(editor); - return editor->getHistoryActions()->canUndo(); - } - return true; - } - return false; - + Editor* editor = GetCurrentEditor(); + ASSERT(editor); + return editor->hasChanges(); } void GUI::AddPendingCanvasEvent(wxEvent& event) @@ -879,6 +873,39 @@ void GUI::LoadPerspective() } } + if(g_settings.getInteger(Config::ACTIONS_HISTORY_VISIBLE)) { + if(!actions_history_window) { + wxAuiPaneInfo info; + + const wxString& data = wxstr(g_settings.getString(Config::ACTIONS_HISTORY_LAYOUT)); + aui_manager->LoadPaneInfo(data, info); + + actions_history_window = new ActionsHistoryWindow(root); + aui_manager->AddPane(actions_history_window, info); + } else { + wxAuiPaneInfo& info = aui_manager->GetPane(actions_history_window); + const wxString& data = wxstr(g_settings.getString(Config::ACTIONS_HISTORY_LAYOUT)); + aui_manager->LoadPaneInfo(data, info); + } + + wxAuiPaneInfo& info = aui_manager->GetPane(actions_history_window); + if(info.IsFloatable()) { + bool offscreen = true; + for(uint32_t index = 0; index < wxDisplay::GetCount(); ++index) { + wxDisplay display(index); + wxRect rect = display.GetClientArea(); + if(rect.Contains(info.floating_pos)) { + offscreen = false; + break; + } + } + + if(offscreen) { + info.Dock(); + } + } + } + aui_manager->Update(); root->UpdateMenubar(); } @@ -891,8 +918,8 @@ void GUI::SavePerspective() g_settings.setInteger(Config::WINDOW_MAXIMIZED, root->IsMaximized()); g_settings.setInteger(Config::WINDOW_WIDTH, root->GetSize().GetWidth()); g_settings.setInteger(Config::WINDOW_HEIGHT, root->GetSize().GetHeight()); - g_settings.setInteger(Config::MINIMAP_VISIBLE, minimap? 1: 0); + g_settings.setInteger(Config::ACTIONS_HISTORY_VISIBLE, actions_history_window ? 1 : 0); wxString pinfo; for (auto &palette : palettes) { @@ -906,6 +933,11 @@ void GUI::SavePerspective() g_settings.setString(Config::MINIMAP_LAYOUT, nstr(s)); } + if(actions_history_window) { + wxString info = aui_manager->SavePaneInfo(aui_manager->GetPane(actions_history_window)); + g_settings.setString(Config::ACTIONS_HISTORY_LAYOUT, nstr(info)); + } + root->GetAuiToolBar()->SavePerspective(); } @@ -929,6 +961,28 @@ SearchResultWindow* GUI::ShowSearchWindow() return search_result_window; } +ActionsHistoryWindow* GUI::ShowActionsWindow() +{ + if(!actions_history_window) { + actions_history_window = new ActionsHistoryWindow(root); + aui_manager->AddPane(actions_history_window, wxAuiPaneInfo().Caption("Actions History")); + } else { + aui_manager->GetPane(actions_history_window).Show(); + } + + aui_manager->Update(); + actions_history_window->RefreshActions(); + return actions_history_window; +} + +void GUI::HideActionsWindow() +{ + if(actions_history_window) { + aui_manager->GetPane(actions_history_window).Show(false); + aui_manager->Update(); + } +} + //============================================================================= // Palette Window Interface implementation @@ -950,6 +1004,8 @@ void GUI::RefreshPalettes(Map* m, bool usedefault) palette->OnUpdate(m? m : (usedefault? (IsEditorOpen()? &GetCurrentMap() : nullptr): nullptr)); } SelectBrush(); + + RefreshActions(); } void GUI::RefreshOtherPalettes(PaletteWindow* p) @@ -1320,20 +1376,20 @@ void GUI::EndPasting() bool GUI::CanUndo() { Editor* editor = GetCurrentEditor(); - return (editor && editor->getHistoryActions()->canUndo()); + return (editor && editor->canUndo()); } bool GUI::CanRedo() { Editor* editor = GetCurrentEditor(); - return (editor && editor->getHistoryActions()->canRedo()); + return (editor && editor->canRedo()); } bool GUI::DoUndo() { Editor* editor = GetCurrentEditor(); - if(editor && editor->getHistoryActions()->canUndo()) { - editor->getHistoryActions()->undo(); + if(editor && editor->canUndo()) { + editor->undo(); if(editor->hasSelection()) SetSelectionMode(); SetStatusText("Undo action"); @@ -1348,8 +1404,8 @@ bool GUI::DoUndo() bool GUI::DoRedo() { Editor* editor = GetCurrentEditor(); - if(editor && editor->getHistoryActions()->canRedo()) { - editor->getHistoryActions()->redo(); + if(editor && editor->canRedo()) { + editor->redo(); if(editor->hasSelection()) SetSelectionMode(); SetStatusText("Redo action"); @@ -1445,6 +1501,18 @@ void GUI::UpdateMenus() g_gui.root->AddPendingEvent(evt); } +void GUI::UpdateActions() +{ + wxCommandEvent evt(EVT_UPDATE_ACTIONS); + g_gui.root->AddPendingEvent(evt); +} + +void GUI::RefreshActions() +{ + if(actions_history_window) + actions_history_window->RefreshActions(); +} + void GUI::ShowToolbar(ToolBarID id, bool show) { if (root && root->GetAuiToolBar()) @@ -1481,15 +1549,16 @@ void GUI::SetDrawingMode() std::set al; for(int idx = 0; idx < tabbook->GetTabCount(); ++idx) { EditorTab* editorTab = tabbook->GetTab(idx); - if(auto * mapTab = dynamic_cast(editorTab)) { + if(MapTab* mapTab = dynamic_cast(editorTab)) { if(al.find(mapTab) != al.end()) continue; Editor* editor = mapTab->GetEditor(); Selection& selection = editor->getSelection(); - selection.start(); + selection.start(Selection::NONE, ACTION_UNSELECT); selection.clear(); selection.finish(); + selection.updateSelectionCount(); al.insert(mapTab); } } diff --git a/source/gui.h b/source/gui.h index b2eff147..815af95a 100644 --- a/source/gui.h +++ b/source/gui.h @@ -52,6 +52,7 @@ class MapCanvas; class SearchResultWindow; class MinimapWindow; +class ActionsHistoryWindow; class PaletteWindow; class OldPropertiesWindow; class EditTownsDialog; @@ -60,12 +61,20 @@ class ItemButton; class LiveSocket; extern const wxEventType EVT_UPDATE_MENUS; +extern const wxEventType EVT_UPDATE_ACTIONS; #define EVT_ON_UPDATE_MENUS(id, fn) \ DECLARE_EVENT_TABLE_ENTRY( \ EVT_UPDATE_MENUS, id, wxID_ANY, \ - (wxObjectEventFunction)(wxEventFunction) wxStaticCastEvent( wxCommandEventFunction, &fn ), \ - (wxObject *) nullptr \ + (wxObjectEventFunction)(wxEventFunction) wxStaticCastEvent(wxCommandEventFunction, &fn), \ + (wxObject*) nullptr \ + ), + +#define EVT_ON_UPDATE_ACTIONS(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + EVT_UPDATE_ACTIONS, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction) wxStaticCastEvent(wxCommandEventFunction, &fn), \ + (wxObject*) nullptr \ ), class Hotkey @@ -100,8 +109,6 @@ class Hotkey std::ostream& operator<<(std::ostream& os, const Hotkey& hotkey); std::istream& operator>>(std::istream& os, Hotkey& hotkey); - - class GUI { public: // dtor and ctor @@ -177,6 +184,8 @@ class GUI void SetTitle(wxString newtitle); void UpdateTitle(); void UpdateMenus(); + void UpdateActions(); + void RefreshActions(); void ShowToolbar(ToolBarID id, bool show); void SetStatusText(wxString text); @@ -197,6 +206,9 @@ class GUI SearchResultWindow* ShowSearchWindow(); void HideSearchWindow(); + ActionsHistoryWindow* ShowActionsWindow(); + void HideActionsWindow(); + // Minimap void CreateMinimap(); void HideMinimap(); @@ -370,6 +382,7 @@ class GUI MinimapWindow* minimap; DCButton* gem; // The small gem in the lower-right corner SearchResultWindow* search_result_window; + ActionsHistoryWindow* actions_history_window; GraphicManager gfx; BaseMap* secondary_map; // A buffer map diff --git a/source/live_action.cpp b/source/live_action.cpp index cb2142cb..80a23769 100644 --- a/source/live_action.cpp +++ b/source/live_action.cpp @@ -109,18 +109,14 @@ NetworkedActionQueue::NetworkedActionQueue(Editor& editor) : ActionQueue(editor) { } -NetworkedActionQueue::~NetworkedActionQueue() +Action* NetworkedActionQueue::createAction(ActionIdentifier identifier) const { + return new NetworkedAction(editor, identifier); } -Action* NetworkedActionQueue::createAction(ActionIdentifier ident) +BatchAction* NetworkedActionQueue::createBatch(ActionIdentifier identifier) { - return newd NetworkedAction(editor, ident); -} - -BatchAction* NetworkedActionQueue::createBatch(ActionIdentifier ident) -{ - return newd NetworkedBatchAction(editor, *this, ident); + return new NetworkedBatchAction(editor, *this, identifier); } void NetworkedActionQueue::broadcast(DirtyList& dirty_list) diff --git a/source/live_action.h b/source/live_action.h index 556fdc2d..3d8e87d7 100644 --- a/source/live_action.h +++ b/source/live_action.h @@ -49,13 +49,13 @@ class NetworkedBatchAction : public BatchAction { friend class NetworkedActionQueue; }; -class NetworkedActionQueue : public ActionQueue { +class NetworkedActionQueue : public ActionQueue +{ public: NetworkedActionQueue(Editor& editor); - ~NetworkedActionQueue(); - Action* createAction(ActionIdentifier ident); - BatchAction* createBatch(ActionIdentifier ident); + Action* createAction(ActionIdentifier identifier) const; + BatchAction* createBatch(ActionIdentifier identifier); protected: void broadcast(DirtyList& dirty_list); diff --git a/source/live_client.cpp b/source/live_client.cpp index 07576f0e..c215ca25 100644 --- a/source/live_client.cpp +++ b/source/live_client.cpp @@ -453,9 +453,9 @@ void LiveClient::parseNode(NetworkMessage& message) int32_t ndy = (ind >> 4) & 0x3FFF; bool underground = ind & 1; - Action* action = editor->getHistoryActions()->createAction(ACTION_REMOTE); + Action* action = editor->createAction(ACTION_REMOTE); receiveNode(message, *editor, action, ndx, ndy, underground); - editor->getHistoryActions()->addAction(action); + editor->addAction(action); g_gui.RefreshView(); g_gui.UpdateMinimap(); diff --git a/source/live_peer.cpp b/source/live_peer.cpp index 79b014ef..4ef64267 100644 --- a/source/live_peer.cpp +++ b/source/live_peer.cpp @@ -290,7 +290,7 @@ void LivePeer::parseReceiveChanges(NetworkMessage& message) BinaryNode* rootNode = mapReader.getRootNode(); BinaryNode* tileNode = rootNode->getChild(); - NetworkedAction* action = static_cast(editor.getHistoryActions()->createAction(ACTION_REMOTE)); + NetworkedAction* action = static_cast(editor.createAction(ACTION_REMOTE)); action->owner = clientId; if(tileNode) do { @@ -301,7 +301,7 @@ void LivePeer::parseReceiveChanges(NetworkMessage& message) } while(tileNode->advance()); mapReader.close(); - editor.getHistoryActions()->addAction(action); + editor.addAction(action); g_gui.RefreshView(); g_gui.UpdateMinimap(); diff --git a/source/main_menubar.cpp b/source/main_menubar.cpp index ebef57dc..e72592b1 100644 --- a/source/main_menubar.cpp +++ b/source/main_menubar.cpp @@ -157,6 +157,7 @@ MainMenuBar::MainMenuBar(MainFrame *frame) : frame(frame) MAKE_ACTION(SHOW_MOVEABLES, wxITEM_CHECK, OnChangeViewSettings); MAKE_ACTION(WIN_MINIMAP, wxITEM_NORMAL, OnMinimapWindow); + MAKE_ACTION(WIN_ACTIONS_HISTORY, wxITEM_NORMAL, OnActionsHistoryWindow); MAKE_ACTION(NEW_PALETTE, wxITEM_NORMAL, OnNewPalette); MAKE_ACTION(TAKE_SCREENSHOT, wxITEM_NORMAL, OnTakeScreenshot); @@ -305,8 +306,8 @@ void MainMenuBar::Update() Editor* editor = g_gui.GetCurrentEditor(); if(editor) { - EnableItem(UNDO, editor->getHistoryActions()->canUndo()); - EnableItem(REDO, editor->getHistoryActions()->canRedo()); + EnableItem(UNDO, editor->canUndo()); + EnableItem(REDO, editor->canRedo()); EnableItem(PASTE, editor->copybuffer.canPaste()); } else { EnableItem(UNDO, false); @@ -1135,7 +1136,7 @@ void MainMenuBar::OnRemoveItemOnSelection(wxCommandEvent& WXUNUSED(event)) FindItemDialog dialog(frame, "Remove Item on Selection"); if(dialog.ShowModal() == wxID_OK) { - g_gui.GetCurrentEditor()->getHistoryActions()->clear(); + g_gui.GetCurrentEditor()->clearActions(); g_gui.CreateLoadBar("Searching item on selection to remove..."); OnMapRemoveItems::RemoveItemCondition condition(dialog.getResultID()); int64_t count = RemoveItemOnMap(g_gui.GetCurrentMap(), condition, true); @@ -1293,7 +1294,7 @@ void MainMenuBar::OnMapRemoveItems(wxCommandEvent& WXUNUSED(event)) uint16_t itemid = dialog.getResultID(); g_gui.GetCurrentEditor()->getSelection().clear(); - g_gui.GetCurrentEditor()->getHistoryActions()->clear(); + g_gui.GetCurrentEditor()->clearActions(); OnMapRemoveItems::RemoveItemCondition condition(itemid); g_gui.CreateLoadBar("Searching map for items to remove..."); @@ -1336,7 +1337,7 @@ void MainMenuBar::OnMapRemoveCorpses(wxCommandEvent& WXUNUSED(event)) if(ok == wxID_YES) { g_gui.GetCurrentEditor()->getSelection().clear(); - g_gui.GetCurrentEditor()->getHistoryActions()->clear(); + g_gui.GetCurrentEditor()->clearActions(); OnMapRemoveCorpses::condition func; g_gui.CreateLoadBar("Searching map for items to remove..."); @@ -1410,7 +1411,7 @@ void MainMenuBar::OnMapRemoveUnreachable(wxCommandEvent& WXUNUSED(event)) if(ok == wxID_YES) { g_gui.GetCurrentEditor()->getSelection().clear(); - g_gui.GetCurrentEditor()->getHistoryActions()->clear(); + g_gui.GetCurrentEditor()->clearActions(); OnMapRemoveUnreachable::condition func; g_gui.CreateLoadBar("Searching map for tiles to remove..."); @@ -1473,8 +1474,8 @@ void MainMenuBar::OnMapRemoveEmptyMonsterSpawns(wxCommandEvent& WXUNUSED(event)) monster->reset(); } - BatchAction* batch = editor->getHistoryActions()->createBatch(ACTION_DELETE_TILES); - Action* action = editor->getHistoryActions()->createAction(batch); + BatchAction* batch = editor->createBatch(ACTION_DELETE_TILES); + Action* action = editor->createAction(batch); const size_t count = toDeleteSpawns.size(); size_t removed = 0; @@ -2040,6 +2041,11 @@ void MainMenuBar::OnMinimapWindow(wxCommandEvent& event) g_gui.CreateMinimap(); } +void MainMenuBar::OnActionsHistoryWindow(wxCommandEvent& WXUNUSED(event)) +{ + g_gui.ShowActionsWindow(); +} + void MainMenuBar::OnNewPalette(wxCommandEvent& event) { g_gui.NewPalette(); diff --git a/source/main_menubar.h b/source/main_menubar.h index 4779d257..14e7335f 100644 --- a/source/main_menubar.h +++ b/source/main_menubar.h @@ -122,6 +122,7 @@ namespace MenuBar SHOW_PICKUPABLES, SHOW_MOVEABLES, WIN_MINIMAP, + WIN_ACTIONS_HISTORY, NEW_PALETTE, TAKE_SCREENSHOT, LIVE_START, @@ -271,6 +272,7 @@ class MainMenuBar : public wxEvtHandler // Window Menu void OnMinimapWindow(wxCommandEvent& event); + void OnActionsHistoryWindow(wxCommandEvent& event); void OnNewPalette(wxCommandEvent& event); void OnTakeScreenshot(wxCommandEvent& event); void OnSelectTerrainPalette(wxCommandEvent& event); diff --git a/source/main_toolbar.cpp b/source/main_toolbar.cpp index 5f12a691..c51974ce 100644 --- a/source/main_toolbar.cpp +++ b/source/main_toolbar.cpp @@ -200,8 +200,8 @@ void MainToolBar::UpdateButtons() { Editor* editor = g_gui.GetCurrentEditor(); if(editor) { - standard_toolbar->EnableTool(wxID_UNDO, editor->getHistoryActions()->canUndo()); - standard_toolbar->EnableTool(wxID_REDO, editor->getHistoryActions()->canRedo()); + standard_toolbar->EnableTool(wxID_UNDO, editor->canUndo()); + standard_toolbar->EnableTool(wxID_REDO, editor->canRedo()); standard_toolbar->EnableTool(wxID_PASTE, editor->copybuffer.canPaste()); } else { standard_toolbar->EnableTool(wxID_UNDO, false); @@ -216,6 +216,7 @@ void MainToolBar::UpdateButtons() standard_toolbar->EnableTool(wxID_SAVEAS, is_host); standard_toolbar->EnableTool(wxID_CUT, has_map); standard_toolbar->EnableTool(wxID_COPY, has_map); + standard_toolbar->Refresh(); brushes_toolbar->EnableTool(PALETTE_TERRAIN_OPTIONAL_BORDER_TOOL, has_map); brushes_toolbar->EnableTool(PALETTE_TERRAIN_ERASER, has_map); @@ -229,6 +230,7 @@ void MainToolBar::UpdateButtons() brushes_toolbar->EnableTool(PALETTE_TERRAIN_QUEST_DOOR, has_map); brushes_toolbar->EnableTool(PALETTE_TERRAIN_HATCH_DOOR, has_map); brushes_toolbar->EnableTool(PALETTE_TERRAIN_WINDOW_DOOR, has_map); + brushes_toolbar->Refresh(); position_toolbar->EnableTool(TOOLBAR_POSITION_GO, has_map); x_control->Enable(has_map); @@ -249,6 +251,7 @@ void MainToolBar::UpdateButtons() sizes_toolbar->EnableTool(TOOLBAR_SIZES_5, has_map); sizes_toolbar->EnableTool(TOOLBAR_SIZES_6, has_map); sizes_toolbar->EnableTool(TOOLBAR_SIZES_7, has_map); + sizes_toolbar->Refresh(); } void MainToolBar::UpdateBrushButtons() diff --git a/source/map_display.cpp b/source/map_display.cpp index 0592404e..944d6059 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -284,19 +284,26 @@ void MapCanvas::TakeScreenshot(wxFileName path, wxString format) wxImage screenshot(screensize_x, screensize_y, screenshot_buffer); time_t t = time(nullptr); - struct tm* current_time = localtime(&t); - ASSERT(current_time); + struct tm current_time; +#ifdef _WIN32 + localtime_s(¤t_time, &t); +#else + localtime_r(&t, ¤t_time); +#endif wxString date; - date << "screenshot_" << (1900 + current_time->tm_year); - if(current_time->tm_mon < 9) - date << "-" << "0" << current_time->tm_mon+1; + date << "screenshot_"; + date << (1900 + current_time.tm_year); + if (current_time.tm_mon < 9) + date << "-0" << (current_time.tm_mon + 1); else - date << "-" << current_time->tm_mon+1; - date << "-" << current_time->tm_mday; - date << "-" << current_time->tm_hour; - date << "-" << current_time->tm_min; - date << "-" << current_time->tm_sec; + date << "-" << (current_time.tm_mon + 1); + date << "-" << current_time.tm_mday; + date << "-" << current_time.tm_hour; + date << "-" << current_time.tm_min; + date << "-" << current_time.tm_sec; + + ASSERT(¤t_time != nullptr); int type = 0; path.SetName(date); @@ -627,7 +634,7 @@ void MapCanvas::OnMouseLeftDoubleClick(wxMouseEvent& event) int ret = dialog->ShowModal(); if(ret != 0) { - Action* action = editor.getHistoryActions()->createAction(ACTION_CHANGE_PROPERTIES); + Action* action = editor.createAction(ACTION_CHANGE_PROPERTIES); action->addChange(newd Change(new_tile)); editor.addAction(action); } else { @@ -681,8 +688,6 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) int mouse_map_x, mouse_map_y; ScreenToMap(event.GetX(), event.GetY(), &mouse_map_x, &mouse_map_y); - Selection& selection = editor.getSelection(); - if(event.ControlDown() && event.AltDown()) { Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(tile && tile->size() > 0) { @@ -691,6 +696,7 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) g_gui.SelectBrush(item->getRAWBrush(), TILESET_RAW); } } else if(g_gui.IsSelectionMode()) { + Selection& selection = editor.getSelection(); if(isPasting()) { // Set paste to false (no rendering etc.) EndPasting(); @@ -709,7 +715,7 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) boundbox_selection = true; if(!event.ControlDown()) { - selection.start(); // Start selection session + selection.start(Selection::NONE, ACTION_UNSELECT); // Start selection session selection.clear(); // Clear out selection selection.finish(); // End selection session selection.updateSelectionCount(); @@ -787,7 +793,7 @@ void MapCanvas::OnMouseActionClick(wxMouseEvent& event) } else { Tile* tile = editor.getMap().getTile(mouse_map_x, mouse_map_y, floor); if(!tile) { - selection.start(); // Start selection session + selection.start(Selection::NONE, ACTION_UNSELECT); // Start selection session selection.clear(); // Clear out selection selection.finish(); // End selection session selection.updateSelectionCount(); @@ -1034,7 +1040,6 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) int mouse_map_x, mouse_map_y; ScreenToMap(event.GetX(), event.GetY(), &mouse_map_x, &mouse_map_y); - Selection& selection = editor.getSelection(); int move_x = last_click_map_x - mouse_map_x; int move_y = last_click_map_y - mouse_map_y; int move_z = last_click_map_z - floor; @@ -1043,6 +1048,7 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) if(dragging && (move_x != 0 || move_y != 0 || move_z != 0)) { editor.moveSelection(Position(move_x, move_y, move_z)); } else { + Selection& selection = editor.getSelection(); if(boundbox_selection) { if(mouse_map_x == last_click_map_x && mouse_map_y == last_click_map_y && event.ControlDown()) { // Mouse hasn't moved, do control+shift thingy! @@ -1159,11 +1165,11 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) ASSERT(remainder == 0); selection.start(); // Start a selection session - for(std::vector::iterator iter = threads.begin(); iter != threads.end(); ++iter) { - (*iter)->Execute(); + for(SelectionThread* thread : threads) { + thread->Execute(); } - for(std::vector::iterator iter = threads.begin(); iter != threads.end(); ++iter) { - selection.join(*iter); + for(SelectionThread* thread : threads) { + selection.join(thread); } selection.finish(); // Finish the selection session selection.updateSelectionCount(); @@ -1214,7 +1220,8 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) } } } - editor.getHistoryActions()->resetTimer(); + editor.resetActionsTimer(); + editor.updateActions(); dragging = false; boundbox_selection = false; } else if(g_gui.GetCurrentBrush()){ // Drawing mode @@ -1342,7 +1349,8 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) } } } - editor.getHistoryActions()->resetTimer(); + editor.resetActionsTimer(); + editor.updateActions(); drawing = false; dragging_draw = false; replace_dragging = false; @@ -1590,7 +1598,7 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) popup_menu->Update(); PopupMenu(popup_menu); - editor.getHistoryActions()->resetTimer(); + editor.resetActionsTimer(); dragging = false; boundbox_selection = false; @@ -2055,9 +2063,10 @@ void MapCanvas::OnBrowseTile(wxCommandEvent& WXUNUSED(event)) int ret = w->ShowModal(); if(ret != 0) { - Action* action = editor.getHistoryActions()->createAction(ACTION_DELETE_TILES); + Action* action = editor.createAction(ACTION_DELETE_TILES); action->addChange(newd Change(new_tile)); editor.addAction(action); + editor.updateActions(); } else { // Cancel delete new_tile; @@ -2068,20 +2077,34 @@ void MapCanvas::OnBrowseTile(wxCommandEvent& WXUNUSED(event)) void MapCanvas::OnRotateItem(wxCommandEvent& WXUNUSED(event)) { - Tile* tile = editor.getSelection().getSelectedTile(); - - Action* action = editor.getHistoryActions()->createAction(ACTION_ROTATE_ITEM); + if(!editor.hasSelection()) { + return; + } - Tile* new_tile = tile->deepCopy(editor.getMap()); + Selection& selection = editor.getSelection(); + if(selection.size() != 1) { + return; + } - ItemVector selected_items = new_tile->getSelectedItems(); - ASSERT(selected_items.size() > 0); + Tile* tile = selection.getSelectedTile(); + ItemVector items = tile->getSelectedItems(); + if(items.empty()) { + return; + } - selected_items.front()->doRotate(); + Item* item = items.front(); + if(!item || !item->isRoteable()) { + return; + } - action->addChange(newd Change(new_tile)); + Action* action = editor.createAction(ACTION_ROTATE_ITEM); + Tile* new_tile = tile->deepCopy(editor.getMap()); + Item* new_item = new_tile->getSelectedItems().front(); + new_item->doRotate(); + action->addChange(new Change(new_tile)); - editor.getHistoryActions()->addAction(action); + editor.addAction(action); + editor.updateActions(); g_gui.RefreshView(); } @@ -2115,7 +2138,7 @@ void MapCanvas::OnSwitchDoor(wxCommandEvent& WXUNUSED(event)) { Tile* tile = editor.getSelection().getSelectedTile(); - Action* action = editor.getHistoryActions()->createAction(ACTION_SWITCHDOOR); + Action* action = editor.createAction(ACTION_SWITCHDOOR); Tile* new_tile = tile->deepCopy(editor.getMap()); @@ -2126,7 +2149,8 @@ void MapCanvas::OnSwitchDoor(wxCommandEvent& WXUNUSED(event)) action->addChange(newd Change(new_tile)); - editor.getHistoryActions()->addAction(action); + editor.addAction(action); + editor.updateActions(); g_gui.RefreshView(); } @@ -2299,7 +2323,7 @@ void MapCanvas::OnProperties(wxCommandEvent& WXUNUSED(event)) int ret = w->ShowModal(); if(ret != 0) { - Action* action = editor.getHistoryActions()->createAction(ACTION_CHANGE_PROPERTIES); + Action* action = editor.createAction(ACTION_CHANGE_PROPERTIES); action->addChange(newd Change(new_tile)); editor.addAction(action); } else { @@ -2383,7 +2407,7 @@ void MapCanvas::Reset() last_mmb_click_y = -1; editor.getSelection().clear(); - editor.getHistoryActions()->clear(); + editor.clearActions(); } MapPopupMenu::MapPopupMenu(Editor& editor) : wxMenu(""), editor(editor) diff --git a/source/palette_window.h b/source/palette_window.h index bd8837b4..5a233e04 100644 --- a/source/palette_window.h +++ b/source/palette_window.h @@ -26,7 +26,8 @@ class NpcPalettePanel; class HousePalettePanel; class WaypointPalettePanel; -class PaletteWindow : public wxPanel { +class PaletteWindow : public wxPanel +{ public: PaletteWindow(wxWindow* parent, const TilesetContainer& tilesets); ~PaletteWindow(); @@ -62,6 +63,7 @@ class PaletteWindow : public wxPanel { // Forward key events to the parent window (The Map Window) void OnKey(wxKeyEvent& event); void OnClose(wxCloseEvent&); + protected: static PalettePanel* CreateTerrainPalette(wxWindow* parent, const TilesetContainer& tilesets); static PalettePanel* CreateDoodadPalette(wxWindow* parent, const TilesetContainer& tilesets); diff --git a/source/replace_items_window.cpp b/source/replace_items_window.cpp index 1c622dbe..71962f14 100644 --- a/source/replace_items_window.cpp +++ b/source/replace_items_window.cpp @@ -346,21 +346,24 @@ void ReplaceItemsDialog::OnExecuteButtonClicked(wxCommandEvent& WXUNUSED(event)) foreach_ItemOnMap(editor->getMap(), finder, selectionOnly); uint32_t total = 0; - std::vector>& result = finder.result; + const auto& result = finder.result; if(!result.empty()) { - Action* action = editor->getHistoryActions()->createAction(ACTION_REPLACE_ITEMS); - for(std::vector>::const_iterator rit = result.begin(); rit != result.end(); ++rit) { - Tile* new_tile = rit->first->deepCopy(editor->getMap()); - int index = rit->first->getIndexOf(rit->second); + BatchAction* batch = editor->createBatch(ACTION_REPLACE_ITEMS); + Action* action = editor->createAction(batch); + for(const auto& pair : result) { + Tile* new_tile = pair.first->deepCopy(editor->getMap()); + int index = pair.first->getIndexOf(pair.second); ASSERT(index != wxNOT_FOUND); Item* item = new_tile->getItemAt(index); - ASSERT(item && item->getID() == rit->second->getID()); + ASSERT(item && item->getID() == pair.second->getID()); transformItem(item, info.withId, new_tile); action->addChange(new Change(new_tile)); total++; } - editor->getHistoryActions()->addAction(action); + batch->addAndCommitAction(action); + editor->addBatch(batch); + editor->updateActions(); } done++; diff --git a/source/selection.cpp b/source/selection.cpp index 710b4043..61b3b6d6 100644 --- a/source/selection.cpp +++ b/source/selection.cpp @@ -74,7 +74,7 @@ Position Selection::maxPosition() const return max_pos; } -void Selection::add(Tile* tile, Item* item) +void Selection::add(const Tile* tile, Item* item) { ASSERT(subsession); ASSERT(tile); @@ -95,7 +95,7 @@ void Selection::add(Tile* tile, Item* item) subsession->addChange(newd Change(new_tile)); } -void Selection::add(Tile* tile, SpawnMonster* spawnMonster) +void Selection::add(const Tile* tile, SpawnMonster* spawnMonster) { ASSERT(subsession); ASSERT(tile); @@ -111,7 +111,7 @@ void Selection::add(Tile* tile, SpawnMonster* spawnMonster) subsession->addChange(newd Change(new_tile)); } -void Selection::add(Tile* tile, SpawnNpc* spawnNpc) +void Selection::add(const Tile* tile, SpawnNpc* spawnNpc) { ASSERT(subsession); ASSERT(tile); @@ -127,7 +127,7 @@ void Selection::add(Tile* tile, SpawnNpc* spawnNpc) subsession->addChange(newd Change(new_tile)); } -void Selection::add(Tile* tile, Monster* monster) +void Selection::add(const Tile* tile, Monster* monster) { ASSERT(subsession); ASSERT(tile); @@ -143,7 +143,7 @@ void Selection::add(Tile* tile, Monster* monster) subsession->addChange(newd Change(new_tile)); } -void Selection::add(Tile* tile, Npc* npc) +void Selection::add(const Tile* tile, Npc* npc) { ASSERT(subsession); ASSERT(tile); @@ -159,7 +159,7 @@ void Selection::add(Tile* tile, Npc* npc) subsession->addChange(newd Change(new_tile)); } -void Selection::add(Tile* tile) +void Selection::add(const Tile* tile) { ASSERT(subsession); ASSERT(tile); @@ -280,13 +280,13 @@ void Selection::clear() } } -void Selection::start(SessionFlags flags) +void Selection::start(SessionFlags flags, ActionIdentifier identifier) { if(!(flags & INTERNAL)) { if(!(flags & SUBTHREAD)) { - session = editor.getHistoryActions()->createBatch(ACTION_SELECT); + session = editor.createBatch(identifier); } - subsession = editor.getHistoryActions()->createAction(ACTION_SELECT); + subsession = editor.createAction(identifier); } busy = true; } @@ -303,7 +303,7 @@ void Selection::commit() batch->addAndCommitAction(subsession); // Create a newd action for subsequent selects - subsession = editor.getHistoryActions()->createAction(ACTION_SELECT); + subsession = editor.createAction(ACTION_SELECT); session = batch; } } @@ -323,6 +323,7 @@ void Selection::finish(SessionFlags flags) batch->addAndCommitAction(subsession); editor.addBatch(batch, 2); + editor.updateActions(); session = nullptr; subsession = nullptr; diff --git a/source/selection.h b/source/selection.h index 70c599a0..f19cde86 100644 --- a/source/selection.h +++ b/source/selection.h @@ -20,6 +20,7 @@ #include "position.h" #include "npc.h" +#include "action.h" class Action; class Editor; @@ -35,12 +36,12 @@ class Selection // Selects the items on the tile/tiles // Won't work outside a selection session - void add(Tile* tile, Item* item); - void add(Tile* tile, SpawnMonster* spawnMonster); - void add(Tile* tile, SpawnNpc* spawnNpc); - void add(Tile* tile, Monster* monster); - void add(Tile* tile, Npc* npc); - void add(Tile* tile); + void add(const Tile* tile, Item* item); + void add(const Tile* tile, SpawnMonster* spawnMonster); + void add(const Tile* tile, SpawnNpc* spawnNpc); + void add(const Tile* tile, Monster* monster); + void add(const Tile* tile, Npc* npc); + void add(const Tile* tile); void remove(Tile* tile, Item* item); void remove(Tile* tile, SpawnMonster* spawnMonster); void remove(Tile* tile, SpawnNpc* spawnNpc); @@ -73,7 +74,7 @@ class Selection SUBTHREAD = 2, }; - void start(SessionFlags flags = NONE); + void start(SessionFlags flags = NONE, ActionIdentifier identifier = ACTION_SELECT); void commit(); void finish(SessionFlags flags = NONE); @@ -82,6 +83,7 @@ class Selection void join(SelectionThread* thread); size_t size() const noexcept { return tiles.size(); } + bool empty() const noexcept { return tiles.empty(); } void updateSelectionCount(); TileSet::iterator begin() noexcept { return tiles.begin(); } TileSet::iterator end() noexcept { return tiles.end(); } diff --git a/source/settings.cpp b/source/settings.cpp index 8f686284..a6692f85 100644 --- a/source/settings.cpp +++ b/source/settings.cpp @@ -313,6 +313,8 @@ void Settings::IO(IOMode mode) String(PALETTE_LAYOUT, "name=02c30f6048629894000011bc00000002;caption=Palette;state=2099148;dir=4;layer=0;row=0;pos=0;prop=100000;bestw=245;besth=100;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1"); Int(MINIMAP_VISIBLE, 0); String(MINIMAP_LAYOUT, "name=066e2bc8486298990000259a00000003;caption=Minimap;state=2099151;dir=4;layer=0;row=0;pos=0;prop=100000;bestw=170;besth=130;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=221;floath=164"); + Int(ACTIONS_HISTORY_VISIBLE, 0); + String(ACTIONS_HISTORY_LAYOUT, "name=945c6eb52a414f1B817e8befd4479412;caption=Actions;state=2099151;dir=2;layer=0;row=0;pos=0;prop=100000;bestw=170;besth=130;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=221;floath=164"); Int(WINDOW_HEIGHT, 500); Int(WINDOW_WIDTH, 700); Int(WINDOW_MAXIMIZED, 0); diff --git a/source/settings.h b/source/settings.h index e1c68d33..0277755b 100644 --- a/source/settings.h +++ b/source/settings.h @@ -150,6 +150,8 @@ namespace Config { MINIMAP_UPDATE_DELAY, MINIMAP_VIEW_BOX, MINIMAP_EXPORT_DIR, + ACTIONS_HISTORY_VISIBLE, + ACTIONS_HISTORY_LAYOUT, WINDOW_HEIGHT, WINDOW_WIDTH, WINDOW_MAXIMIZED, @@ -199,6 +201,7 @@ class Settings { void setDefaults() {IO(DEFAULT);} void load(); void save(bool endoftheworld = false); + public: enum DynamicType { TYPE_NONE, diff --git a/source/tile.h b/source/tile.h index 16d52af0..91e8b90b 100644 --- a/source/tile.h +++ b/source/tile.h @@ -153,13 +153,13 @@ class Tile // Borderize this tile void borderize(BaseMap* parent); - bool hasTable() const { return testFlags(statflags, TILESTATE_HAS_TABLE); } + bool hasTable() const noexcept { return testFlags(statflags, TILESTATE_HAS_TABLE); } Item* getTable() const; - bool hasCarpet() const { return testFlags(statflags, TILESTATE_HAS_CARPET); } + bool hasCarpet() const noexcept { return testFlags(statflags, TILESTATE_HAS_CARPET); } Item* getCarpet() const; - bool hasOptionalBorder() const { return testFlags(statflags, TILESTATE_OP_BORDER); } + bool hasOptionalBorder() const noexcept { return testFlags(statflags, TILESTATE_OP_BORDER); } void setOptionalBorder(bool b) { if(b) { statflags |= TILESTATE_OP_BORDER; diff --git a/vcproj/Project/RME.vcxproj b/vcproj/Project/RME.vcxproj index c3ea811d..0f92821f 100644 --- a/vcproj/Project/RME.vcxproj +++ b/vcproj/Project/RME.vcxproj @@ -214,12 +214,14 @@ + + diff --git a/vcproj/rme - Copia.cfg b/vcproj/rme - Copia.cfg new file mode 100644 index 00000000..cec80257 --- /dev/null +++ b/vcproj/rme - Copia.cfg @@ -0,0 +1,142 @@ +file1= +file2= +file3= +file4= +file5= +file6= +file7= +file8= +file9= +GOTO_WEBSITE_ON_BOOT=0 +USE_UPDATER=1 +RECENT_EDITED_MAP_PATH= +RECENT_EDITED_MAP_POSITION= +FIND_ITEM_MODE=0 +JUMP_TO_ITEM_MODE=0 +[View] +TRANSPARENT_FLOORS=0 +TRANSPARENT_ITEMS=0 +SHOW_ALL_FLOORS=1 +SHOW_INGAME_BOX=0 +SHOW_GRID=0 +SHOW_EXTRA=1 +SHOW_SHADE=1 +SHOW_SPECIAL_TILES=1 +SHOW_SPAWNS=1 +SHOW_ITEMS=1 +HIGHLIGHT_ITEMS=0 +SHOW_CREATURES=1 +SHOW_HOUSES=1 +SHOW_BLOCKING=0 +SHOW_TOOLTIPS=1 +SHOW_ONLY_TILEFLAGS=0 +SHOW_ONLY_MODIFIED_TILES=0 +SHOW_PREVIEW=1 +SHOW_WALL_HOOKS=0 +SHOW_PICKUPABLES=0 +SHOW_MOVEABLES=0 +[Version] +VERSION_ID=30800000 +CHECK_SIGNATURES=1 +USE_CUSTOM_DATA_DIRECTORY=0 +DATA_DIRECTORY= +EXTENSIONS_DIRECTORY= +ASSETS_DATA_DIRS=[{"id":"7.4","path":""},{"id":"7.6","path":""},{"id":"8.00","path":""},{"id":"8.10","path":""},{"id":"8.20 - 8.31","path":""},{"id":"8.40","path":""},{"id":"8.50","path":""},{"id":"8.54 (bad)","path":""},{"id":"8.54","path":""},{"id":"8.60 (old)","path":""},{"id":"8.60","path":""},{"id":"8.70","path":""},{"id":"9.10","path":""},{"id":"9.20 - 9.31","path":""},{"id":"9.46","path":""},{"id":"9.54","path":""},{"id":"9.60","path":""},{"id":"9.70","path":""},{"id":"9.86","path":""},{"id":"10.10","path":""},{"id":"10.20","path":""},{"id":"10.21","path":""},{"id":"10.30","path":""},{"id":"10.31","path":""},{"id":"10.41","path":""},{"id":"10.77","path":""},{"id":"10.98","path":""},{"id":"10.100","path":""}] +[Editor] +RECENT_FILES= +WORKER_THREADS=1 +MERGE_MOVE=0 +MERGE_PASTE=0 +UNDO_SIZE=400 +UNDO_MEM_SIZE=40 +GROUP_ACTIONS=1 +SELECTION_TYPE=0 +COMPENSATED_SELECT=1 +SCROLL_SPEED=3.5 +ZOOM_SPEED=1.4 +SWITCH_MOUSEBUTTONS=0 +DOUBLECLICK_PROPERTIES=1 +LISTBOX_EATS_ALL_EVENTS=1 +BORDER_IS_GROUND=1 +BORDERIZE_PASTE=1 +BORDERIZE_DRAG=1 +BORDERIZE_DRAG_THRESHOLD=6000 +BORDERIZE_PASTE_THRESHOLD=10000 +ALWAYS_MAKE_BACKUP=0 +USE_AUTOMAGIC=1 +HOUSE_BRUSH_REMOVE_ITEMS=0 +AUTO_ASSIGN_DOORID=1 +ERASER_LEAVE_UNIQUE=1 +DOODAD_BRUSH_ERASE_LIKE=0 +WARN_FOR_DUPLICATE_ID=1 +AUTO_CREATE_SPAWN=1 +DEFAULT_SPAWNTIME=60 +MAX_SPAWN_RADIUS=30 +CURRENT_SPAWN_RADIUS=5 +DEFAULT_CLIENT_VERSION=-1 +RAW_LIKE_SIMONE=1 +ONLY_ONE_INSTANCE=1 +USE_OTBM_4_FOR_ALL_MAPS=0 +USE_OTGZ=1 +SAVE_WITH_OTB_MAGIC_NUMBER=0 +REPLACE_SIZE=500 +COPY_POSITION_FORMAT=0 +[Graphics] +TEXTURE_MANAGEMENT=1 +TEXTURE_CLEAN_PULSE=15 +TEXTURE_LONGEVITY=20 +TEXTURE_CLEAN_THRESHOLD=2500 +SOFTWARE_CLEAN_THRESHOLD=1800 +SOFTWARE_CLEAN_SIZE=500 +ICON_BACKGROUND=0 +HARD_REFRESH_RATE=200 +HIDE_ITEMS_WHEN_ZOOMED=1 +SCREENSHOT_DIRECTORY=C:\\Users\\nails\\Documents/My Pictures/RME/ +SCREENSHOT_FORMAT=png +USE_MEMCACHED_SPRITES=0 +MINIMAP_UPDATE_DELAY=333 +MINIMAP_VIEW_BOX=1 +MINIMAP_EXPORT_DIR= +CURSOR_RED=0 +CURSOR_GREEN=166 +CURSOR_BLUE=0 +CURSOR_ALPHA=128 +CURSOR_ALT_RED=0 +CURSOR_ALT_GREEN=166 +CURSOR_ALT_BLUE=0 +CURSOR_ALT_ALPHA=128 +[UI] +USE_LARGE_CONTAINER_ICONS=1 +USE_LARGE_CHOOSE_ITEM_ICONS=1 +USE_LARGE_TERRAIN_TOOLBAR=1 +USE_LARGE_DOODAD_SIZEBAR=1 +USE_LARGE_ITEM_SIZEBAR=1 +USE_LARGE_HOUSE_SIZEBAR=1 +USE_LARGE_RAW_SIZEBAR=1 +USE_GUI_SELECTION_SHADOW=0 +PALETTE_COL_COUNT=8 +PALETTE_TERRAIN_STYLE=large icons +PALETTE_DOODAD_STYLE=large icons +PALETTE_ITEM_STYLE=listbox +PALETTE_RAW_STYLE=listbox +[Window] +PALETTE_LAYOUT= +MINIMAP_VISIBLE=0 +MINIMAP_LAYOUT=name=066e2bc8486298990000259a00000003;caption=Minimap;state=2099151;dir=4;layer=0;row=0;pos=0;prop=100000;bestw=170;besth=130;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=221;floath=164 +ACTIONS_HISTORY_VISIBLE=0 +ACTIONS_HISTORY_LAYOUT=name=945c6eb52a414f1B817e8befd4479412;caption=Actions;state=2099151;dir=2;layer=0;row=0;pos=0;prop=100000;bestw=170;besth=130;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=221;floath=164 +WINDOW_HEIGHT=500 +WINDOW_WIDTH=700 +WINDOW_MAXIMIZED=0 +WELCOME_DIALOG=1 +[Hotkeys] +NUMERICAL_HOTKEYS=none:{}\nnone:{}\nnone:{}\nnone:{}\nnone:{}\nnone:{}\nnone:{}\nnone:{}\nnone:{}\nnone:{}\n +SHOW_TOOLBAR_STANDARD=1 +SHOW_TOOLBAR_BRUSHES=0 +SHOW_TOOLBAR_POSITION=0 +SHOW_TOOLBAR_SIZES=0 +SHOW_TOOLBAR_INDICATORS=0 +TOOLBAR_STANDARD_LAYOUT=name=standard_toolbar;caption=;state=2106044;dir=1;layer=10;row=1;pos=1;prop=100000;bestw=272;besth=29;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1 +TOOLBAR_BRUSHES_LAYOUT= +TOOLBAR_POSITION_LAYOUT= +TOOLBAR_SIZES_LAYOUT= From 66798d084c288c57a7f607f97442877a52e9c2cf Mon Sep 17 00:00:00 2001 From: Nailson Date: Fri, 27 Jan 2023 21:39:31 -0300 Subject: [PATCH 23/45] Does not draw tooltips on minimap mode --- source/map_drawer.cpp | 34 +++++++++++++++++++++------------- source/map_drawer.h | 1 + 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index ae9afc98..61ccb3f4 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -125,6 +125,11 @@ bool DrawingOptions::isTileIndicators() const noexcept return show_pickupables || show_moveables || show_houses || show_spawns_monster || show_spawns_npc; } +bool DrawingOptions::isTooltips() const noexcept +{ + return show_tooltips && !isOnlyColors(); +} + MapDrawer::MapDrawer(MapCanvas* canvas) : canvas(canvas), editor(canvas->editor) { //// @@ -219,7 +224,7 @@ void MapDrawer::Draw() DrawGrid(); if(options.show_ingame_box) DrawIngameBox(); - if(options.show_tooltips) + if(options.isTooltips()) DrawTooltips(); } @@ -248,8 +253,8 @@ inline int getFloorAdjustment(int floor) void MapDrawer::DrawShade(int map_z) { - bool only_colors = options.isOnlyColors(); if(map_z == end_z && start_z != end_z) { + bool only_colors = options.isOnlyColors(); if(!only_colors) glDisable(GL_TEXTURE_2D); @@ -347,9 +352,6 @@ void MapDrawer::DrawMap() DrawPositionIndicator(map_z); } - if(only_colors) - glEnable(GL_TEXTURE_2D); - // Draws the doodad preview or the paste preview (or import preview) DrawSecondaryMap(map_z); @@ -383,6 +385,8 @@ void MapDrawer::DrawSecondaryMap(int map_z) } } + glEnable(GL_TEXTURE_2D); + for(int map_x = start_x; map_x <= end_x; map_x++) { for(int map_y = start_y; map_y <= end_y; map_y++) { Position final_pos(map_x, map_y, map_z); @@ -451,6 +455,8 @@ void MapDrawer::DrawSecondaryMap(int map_z) } } } + + glDisable(GL_TEXTURE_2D); } void MapDrawer::DrawIngameBox() @@ -1460,8 +1466,9 @@ void MapDrawer::DrawTile(TileLocation* location) return; const Position& position = location->getPosition(); + bool show_tooltips = options.isTooltips(); - if(options.show_tooltips && location->getWaypointCount() > 0) { + if(show_tooltips && location->getWaypointCount() > 0) { Waypoint* waypoint = canvas->editor.getMap().waypoints.getWaypoint(position); if(waypoint) WriteTooltip(waypoint, tooltip); @@ -1537,13 +1544,14 @@ void MapDrawer::DrawTile(TileLocation* location) } if(only_colors) { + glDisable(GL_TEXTURE_2D); if(options.show_as_minimap) { wxColor color = colorFromEightBit(tile->getMiniMapColor()); glBlitSquare(draw_x, draw_y, color); - } - else if(r != 255 || g != 255 || b != 255) { + } else if(r != 255 || g != 255 || b != 255) { glBlitSquare(draw_x, draw_y, r, g, b, 128); } + glEnable(GL_TEXTURE_2D); } else { if(options.show_preview && zoom <= 2.0) tile->ground->animate(); @@ -1551,7 +1559,7 @@ void MapDrawer::DrawTile(TileLocation* location) BlitItem(draw_x, draw_y, tile, tile->ground, false, r, g, b); } - if(options.show_tooltips && position.z == floor) + if(show_tooltips && position.z == floor) WriteTooltip(tile->ground, tooltip); } @@ -1559,7 +1567,7 @@ void MapDrawer::DrawTile(TileLocation* location) if(!hidden && !tile->items.empty()) { for(Item* item : tile->items) { - if(options.show_tooltips && position.z == floor) + if(show_tooltips && position.z == floor) WriteTooltip(item, tooltip); if(options.show_preview && zoom <= 2.0) @@ -1581,7 +1589,7 @@ void MapDrawer::DrawTile(TileLocation* location) BlitCreature(draw_x, draw_y, tile->npc); } - if(options.show_tooltips) { + if(show_tooltips) { if(location->getWaypointCount() > 0) MakeTooltip(draw_x, draw_y, tooltip.str(), 0, 255, 0); else @@ -1752,8 +1760,8 @@ void MapDrawer::DrawPositionIndicator(int z) int offset = (TILE_SIZE - size) / 2; glDisable(GL_TEXTURE_2D); - drawRect(x + offset + 2, y + offset + 2, size - 4, size - 4, *wxWHITE, 2); - drawRect(x + offset + 1, y + offset + 1, size - 2, size - 2, *wxBLACK, 2); + drawRect(x + offset + 2, y + offset + 2, size - 4, size - 4, *wxWHITE, 2); + drawRect(x + offset + 1, y + offset + 1, size - 2, size - 2, *wxBLACK, 2); glEnable(GL_TEXTURE_2D); } diff --git a/source/map_drawer.h b/source/map_drawer.h index a66546aa..a4435f10 100644 --- a/source/map_drawer.h +++ b/source/map_drawer.h @@ -53,6 +53,7 @@ struct DrawingOptions { bool isOnlyColors() const noexcept; bool isTileIndicators() const noexcept; + bool isTooltips() const noexcept; bool transparent_floors; bool transparent_items; From e3d35ce99de6e4c26c6a285672a0d609584bd52c Mon Sep 17 00:00:00 2001 From: Beats Date: Wed, 5 Apr 2023 23:54:53 -0400 Subject: [PATCH 24/45] Use constexpr --- source/action.cpp | 4 +- source/basemap.cpp | 20 +-- source/common_windows.cpp | 20 +-- source/const.h | 55 ++++++ source/copybuffer.cpp | 2 +- source/definitions.h | 30 ---- source/editor.cpp | 6 +- source/editor.h | 2 +- source/graphics.cpp | 58 +++--- source/gui.cpp | 4 +- source/main.h | 5 +- source/main_menubar.cpp | 6 +- source/main_toolbar.cpp | 6 +- source/map.cpp | 8 +- source/map.h | 2 +- source/map_display.cpp | 88 +++++----- source/map_drawer.cpp | 292 +++++++++++++++---------------- source/map_region.cpp | 16 +- source/map_region.h | 14 +- source/map_window.cpp | 10 +- source/minimap_window.cpp | 8 +- source/old_properties_window.cpp | 8 +- source/position.h | 4 +- source/positionctrl.cpp | 2 +- source/positionctrl.h | 2 +- source/selection.cpp | 2 +- vcproj/Project/RME.vcxproj | 1 + vcproj/rme - Copia.cfg | 142 --------------- 28 files changed, 353 insertions(+), 464 deletions(-) create mode 100644 source/const.h delete mode 100644 vcproj/rme - Copia.cfg diff --git a/source/action.cpp b/source/action.cpp index 97349dc4..2a0563f9 100644 --- a/source/action.cpp +++ b/source/action.cpp @@ -146,7 +146,7 @@ void Action::commit(DirtyList* dirty_list) if(editor.IsLiveClient()) { QTreeNode* node = map.getLeaf(pos.x, pos.y); - if(!node || !node->isVisible(pos.z > GROUND_LAYER)) { + if(!node || !node->isVisible(pos.z > rme::MapGroundLayer)) { change->clear(); continue; } @@ -295,7 +295,7 @@ void Action::undo(DirtyList* dirty_list) if(editor.IsLiveClient()) { QTreeNode* node = map.getLeaf(pos.x, pos.y); - if(!node || !node->isVisible(pos.z > GROUND_LAYER)) { + if(!node || !node->isVisible(pos.z > rme::MapGroundLayer)) { // Delete all changes that affect tiles outside our view change->clear(); continue; diff --git a/source/basemap.cpp b/source/basemap.cpp index e33f9d3b..0d52bd5d 100644 --- a/source/basemap.cpp +++ b/source/basemap.cpp @@ -52,7 +52,7 @@ void BaseMap::clearVisible(uint32_t mask) Tile* BaseMap::createTile(int x, int y, int z) { - ASSERT(z < MAP_LAYERS); + ASSERT(z < rme::MapLayers); QTreeNode* leaf = root.getLeafForce(x, y); TileLocation* loc = leaf->createTile(x, y, z); if(loc->get()) @@ -64,7 +64,7 @@ Tile* BaseMap::createTile(int x, int y, int z) TileLocation* BaseMap::getTileL(int x, int y, int z) { - ASSERT(z < MAP_LAYERS); + ASSERT(z < rme::MapLayers); QTreeNode* leaf = root.getLeaf(x, y); if(leaf) { Floor* floor = leaf->getFloor(z); @@ -93,7 +93,7 @@ const TileLocation* BaseMap::getTileL(const Position& pos) const TileLocation* BaseMap::createTileL(int x, int y, int z) { - ASSERT(z < MAP_LAYERS); + ASSERT(z < rme::MapLayers); QTreeNode* leaf = root.getLeafForce(x, y); Floor* floor = leaf->createFloor(x, y, z); @@ -140,7 +140,7 @@ void BaseMap::setTile(Tile* new_tile, bool remove) Tile* BaseMap::swapTile(int x, int y, int z, Tile* new_tile) { - ASSERT(z < MAP_LAYERS); + ASSERT(z < rme::MapLayers); ASSERT(!new_tile || new_tile->getX() == x); ASSERT(!new_tile || new_tile->getY() == y); ASSERT(!new_tile || new_tile->getZ() == z); @@ -204,7 +204,7 @@ MapIterator BaseMap::begin() if(child->isLeaf) { QTreeNode* leaf = child; //printf("\t%p is leaf\n", child); - for(it.local_z = 0; it.local_z < MAP_LAYERS; ++it.local_z) { + for(it.local_z = 0; it.local_z < rme::MapLayers; ++it.local_z) { if(Floor* floor = leaf->array[it.local_z]) { for(it.local_i = 0; it.local_i < 16; ++it.local_i) { //printf("\tit(%d;%d;%d)\n", it.local_x, it.local_y, it.local_z); @@ -267,17 +267,17 @@ MapIterator& MapIterator::operator++() //printf("Contemplating %p (stack size %d)\n", node, nodestack.size()); bool unwind = false; - for(; index < MAP_LAYERS; ++index) { + for(; index < rme::MapLayers; ++index) { //printf("\tChecking index %d of %p\n", index, node); if(QTreeNode* child = node->child[index]) { if(child->isLeaf) { QTreeNode* leaf = child; //printf("\t%p is leaf\n", child); - for(; local_z < MAP_LAYERS; ++local_z) { + for(; local_z < rme::MapLayers; ++local_z) { //printf("\t\tIterating over Z:%d of %p", local_z, child); if(Floor* floor = leaf->array[local_z]) { //printf("\n"); - for(; local_i < MAP_LAYERS; ++local_i) { + for(; local_i < rme::MapLayers; ++local_i) { //printf("\t\tIterating over Y:%d of %p\n", local_y, child); TileLocation& t = floor->locs[local_i]; if(t.get()) { @@ -294,14 +294,14 @@ MapIterator& MapIterator::operator++() } } - if(local_i > MAP_MAX_LAYER) { + if(local_i > rme::MapMaxLayer) { //printf("\t\tReset local_x\n"); local_i = 0; } } else { //printf(":dead floor\n"); } - } if(local_z == MAP_LAYERS) { + } if(local_z == rme::MapLayers) { //printf("\t\tReset local_z\n"); local_z = 0; } diff --git a/source/common_windows.cpp b/source/common_windows.cpp index 3c2ba093..4b21707e 100644 --- a/source/common_windows.cpp +++ b/source/common_windows.cpp @@ -106,12 +106,12 @@ MapPropertiesWindow::MapPropertiesWindow(wxWindow* parent, MapTab* view, Editor& subsizer->Add( width_spin = newd wxSpinCtrl(this, wxID_ANY, wxstr(i2s(map.getWidth())), - wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 256, MAP_MAX_WIDTH), wxSizerFlags(1).Expand() + wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, rme::MapMinWidth, rme::MapMaxWidth), wxSizerFlags(1).Expand() ); subsizer->Add( height_spin = newd wxSpinCtrl(this, wxID_ANY, wxstr(i2s(map.getHeight())), - wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 256, MAP_MAX_HEIGHT), wxSizerFlags(1).Expand() + wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, rme::MapMinHeight, rme::MapMaxHeight), wxSizerFlags(1).Expand() ); grid_sizer->Add(subsizer, 1, wxEXPAND); } @@ -401,13 +401,13 @@ ImportMapWindow::ImportMapWindow(wxWindow* parent, Editor& editor) : // Import offset tmpsizer = newd wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, "Import Offset"), wxHORIZONTAL); tmpsizer->Add(newd wxStaticText(tmpsizer->GetStaticBox(), wxID_ANY, "Offset X:"), 0, wxALL | wxEXPAND, 5); - x_offset_ctrl = newd wxSpinCtrl(tmpsizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(60, 23), wxSP_ARROW_KEYS, -MAP_MAX_HEIGHT, MAP_MAX_HEIGHT); + x_offset_ctrl = newd wxSpinCtrl(tmpsizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(60, 23), wxSP_ARROW_KEYS, -rme::MapMaxHeight, rme::MapMaxHeight); tmpsizer->Add(x_offset_ctrl, 0, wxALL, 5); tmpsizer->Add(newd wxStaticText(tmpsizer->GetStaticBox(), wxID_ANY, "Offset Y:"), 0, wxALL, 5); - y_offset_ctrl = newd wxSpinCtrl(tmpsizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(60, 23), wxSP_ARROW_KEYS, -MAP_MAX_HEIGHT, MAP_MAX_HEIGHT); + y_offset_ctrl = newd wxSpinCtrl(tmpsizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(60, 23), wxSP_ARROW_KEYS, -rme::MapMaxHeight, rme::MapMaxHeight); tmpsizer->Add(y_offset_ctrl, 0, wxALL, 5); tmpsizer->Add(newd wxStaticText(tmpsizer->GetStaticBox(), wxID_ANY, "Offset Z:"), 0, wxALL, 5); - z_offset_ctrl = newd wxSpinCtrl(tmpsizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(60, 23), wxSP_ARROW_KEYS, -MAP_MAX_LAYER, MAP_MAX_LAYER); + z_offset_ctrl = newd wxSpinCtrl(tmpsizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(60, 23), wxSP_ARROW_KEYS, -rme::MapMaxLayer, rme::MapMaxLayer); tmpsizer->Add(z_offset_ctrl, 0, wxALL, 5); sizer->Add(tmpsizer, 1, wxEXPAND | wxLEFT | wxRIGHT, 5); @@ -562,7 +562,7 @@ ExportMiniMapWindow::ExportMiniMapWindow(wxWindow* parent, Editor& editor) : // Area options tmpsizer = newd wxStaticBoxSizer(wxHORIZONTAL, this, "Area Options"); floor_options = newd wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices); - floor_number = newd wxSpinCtrl(this, wxID_ANY, i2ws(GROUND_LAYER), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, MAP_MAX_LAYER, GROUND_LAYER); + floor_number = newd wxSpinCtrl(this, wxID_ANY, i2ws(rme::MapGroundLayer), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, rme::MapMinLayer, rme::MapMaxLayer, rme::MapGroundLayer); floor_number->Enable(false); floor_options->SetSelection(0); tmpsizer->Add(floor_options, 1, wxALL, 5); @@ -622,7 +622,7 @@ void ExportMiniMapWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) switch(floor_options->GetSelection()) { case 0: { // All floors - for(int floor = 0; floor < MAP_LAYERS; ++floor) { + for(int floor = 0; floor < rme::MapLayers; ++floor) { g_gui.SetLoadScale(int(floor*(100.f/16.f)), int((floor+1)*(100.f/16.f))); FileName file(file_name_text_field->GetValue() + "_" + i2ws(floor) + ".bmp"); file.Normalize(wxPATH_NORM_ALL, directory.GetFullPath()); @@ -632,9 +632,9 @@ void ExportMiniMapWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) } case 1: { // Ground floor - FileName file(file_name_text_field->GetValue() + "_" + i2ws(GROUND_LAYER) + ".bmp"); + FileName file(file_name_text_field->GetValue() + "_" + i2ws(rme::MapGroundLayer) + ".bmp"); file.Normalize(wxPATH_NORM_ALL, directory.GetFullPath()); - editor.exportMiniMap(file, GROUND_LAYER, true); + editor.exportMiniMap(file, rme::MapGroundLayer, true); break; } @@ -1545,7 +1545,7 @@ GotoPositionDialog::GotoPositionDialog(wxWindow* parent, Editor& editor) : // create topsizer wxSizer* sizer = newd wxBoxSizer(wxVERTICAL); - posctrl = newd PositionCtrl(this, "Destination", map.getWidth() / 2, map.getHeight() / 2, GROUND_LAYER, map.getWidth(), map.getHeight()); + posctrl = newd PositionCtrl(this, "Destination", map.getWidth() / 2, map.getHeight() / 2, rme::MapGroundLayer, map.getWidth(), map.getHeight()); sizer->Add(posctrl, 0, wxTOP | wxLEFT | wxRIGHT, 20); // OK/Cancel buttons diff --git a/source/const.h b/source/const.h new file mode 100644 index 00000000..3e12a90d --- /dev/null +++ b/source/const.h @@ -0,0 +1,55 @@ +////////////////////////////////////////////////////////////////////// +// This file is part of Remere's Map Editor +////////////////////////////////////////////////////////////////////// +// Remere's Map Editor is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Remere's Map Editor is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +////////////////////////////////////////////////////////////////////// + +#ifndef RME_CONST_H_ +#define RME_CONST_H_ + +namespace rme { + +constexpr double PI = 3.14159265; + +// The height of the map (there should be more checks for this...) +constexpr int MapLayers = 16; + +constexpr int MapMinWidth = 256; +constexpr int MapMaxWidth = 65000; +constexpr int MapMinHeight = 256; +constexpr int MapMaxHeight = 65000; +constexpr int MapMinLayer = 0; +constexpr int MapMaxLayer = 15; + +// The sea layer +constexpr int MapGroundLayer = 7; + +constexpr int ClientMapWidth = 18; +constexpr int ClientMapHeight = 14; + +// The size of the tile in pixels +constexpr int TileSize = 32; + +// The default size of sprites +constexpr int SpritePixels = 32; +constexpr int SpritePixelsSize = SpritePixels * SpritePixels; + +constexpr int MinUniqueId = 1000; +constexpr int MaxUniqueId = 65535; +constexpr int MinActionId = 100; +constexpr int MaxActionId = 65535; + +} // namespace rme + +#endif // RME_CONST_H_ diff --git a/source/copybuffer.cpp b/source/copybuffer.cpp index 7a500f4a..00e8c2d0 100644 --- a/source/copybuffer.cpp +++ b/source/copybuffer.cpp @@ -292,7 +292,7 @@ void CopyBuffer::paste(Editor& editor, const Position& toPosition) for(MapIterator it = tiles->begin(); it != tiles->end(); ++it) { bool add_me = false; // If this tile is touched Position pos = (*it)->getPosition() - copyPos + toPosition; - if(pos.z < 0 || pos.z >= MAP_LAYERS) { + if(pos.z < rme::MapMinLayer || pos.z > rme::MapMaxLayer) { continue; } // Go through all neighbours diff --git a/source/definitions.h b/source/definitions.h index 524618a1..ff3475ce 100644 --- a/source/definitions.h +++ b/source/definitions.h @@ -106,36 +106,6 @@ # endif #endif -// Mathematical constants -#define PI 3.14159265358979323846264338327950288419716939937510 -#define DEG2RAD (PI/180.0) -#define RAD2DEG (180.0/DEG) - -// The height of the map (there should be more checks for this...) -#define MAP_LAYERS 16 - -#define MAP_MAX_WIDTH 65000 -#define MAP_MAX_HEIGHT 65000 -#define MAP_MAX_LAYER 15 - -#define MIN_UNIQUE_ID 1000 -#define MAX_UNIQUE_ID 65535 -#define MIN_ACTION_ID 100 -#define MAX_ACTION_ID 65535 - -// The size of the tile in pixels -#define TILE_SIZE 32 - -// The default size of sprites -#define SPRITE_PIXELS 32 -#define SPRITE_PIXELS_SIZE SPRITE_PIXELS * SPRITE_PIXELS - -// The sea layer -#define GROUND_LAYER 7 - -#define CLIENT_MAP_WIDTH 18 -#define CLIENT_MAP_HEIGHT 14 - #define MAP_LOAD_FILE_WILDCARD_OTGZ "OpenTibia Binary Map (*.otbm;*.otgz)|*.otbm;*.otgz" #define MAP_SAVE_FILE_WILDCARD_OTGZ "OpenTibia Binary Map (*.otbm)|*.otbm|Compressed OpenTibia Binary Map (*.otgz)|*.otgz" diff --git a/source/editor.cpp b/source/editor.cpp index 5d176db2..39cc3d6f 100644 --- a/source/editor.cpp +++ b/source/editor.cpp @@ -466,7 +466,7 @@ bool Editor::importMiniMap(FileName filename, int import, int import_x_offset, i return false; } -bool Editor::exportMiniMap(FileName filename, int floor /*= GROUND_LAYER*/, bool displaydialog) +bool Editor::exportMiniMap(FileName filename, int floor /*= rme::MapGroundLayer*/, bool displaydialog) { return map.exportMinimap(filename, floor, displaydialog); } @@ -476,7 +476,7 @@ bool Editor::exportSelectionAsMiniMap(FileName directory, wxString fileName) if(!directory.Exists() || !directory.IsDirWritable()) return false; - int min_x = MAP_MAX_WIDTH + 1, min_y = MAP_MAX_HEIGHT + 1, min_z = MAP_MAX_LAYER + 1; + int min_x = rme::MapMaxWidth + 1, min_y = rme::MapMaxHeight + 1, min_z = rme::MapMaxLayer + 1; int max_x = 0, max_y = 0, max_z = 0; const TileSet& tiles = selection.getTiles(); @@ -1243,7 +1243,7 @@ void Editor::moveSelection(const Position& offset) for(Tile* tile : storage) { const Position& old_pos = tile->getPosition(); Position new_pos = old_pos - offset; - if(new_pos.z < 0 && new_pos.z > MAP_MAX_LAYER) { + if(new_pos.z < rme::MapMinLayer && new_pos.z > rme::MapMaxLayer) { delete tile; continue; } diff --git a/source/editor.h b/source/editor.h index 60cf8d33..aa7f7a05 100644 --- a/source/editor.h +++ b/source/editor.h @@ -84,7 +84,7 @@ class Editor wxString getLoaderError() const {return map.getError();} bool importMap(FileName filename, int import_x_offset, int import_y_offset, int import_z_offset, ImportType house_import_type, ImportType spawn_import_type, ImportType spawn_npc_import_type); bool importMiniMap(FileName filename, int import, int import_x_offset, int import_y_offset, int import_z_offset); - bool exportMiniMap(FileName filename, int floor /*= GROUND_LAYER*/, bool displaydialog); + bool exportMiniMap(FileName filename, int floor /*= rme::MapGroundLayer*/, bool displaydialog); bool exportSelectionAsMiniMap(FileName directory, wxString fileName); ActionQueue* getHistoryActions() const noexcept { return actionQueue; } diff --git a/source/graphics.cpp b/source/graphics.cpp index 338aaa82..851ac8fa 100644 --- a/source/graphics.cpp +++ b/source/graphics.cpp @@ -934,7 +934,7 @@ wxMemoryDC* GameSprite::getDC(SpriteSize size) const int bgshade = g_settings.getInteger(Config::ICON_BACKGROUND); - int image_size = std::max(width, height) * SPRITE_PIXELS; + int image_size = std::max(width, height) * rme::SpritePixels; wxImage image(image_size, image_size); image.Clear(bgshade); @@ -944,9 +944,9 @@ wxMemoryDC* GameSprite::getDC(SpriteSize size) const int i = getIndex(w, h, l, 0, 0, 0, 0); uint8_t* data = spriteList[i]->getRGBData(); if(data) { - wxImage img(SPRITE_PIXELS, SPRITE_PIXELS, data); + wxImage img(rme::SpritePixels, rme::SpritePixels, data); img.SetMaskColour(0xFF, 0x00, 0xFF); - image.Paste(img, (width - w - 1) * SPRITE_PIXELS, (height - h - 1) * SPRITE_PIXELS); + image.Paste(img, (width - w - 1) * rme::SpritePixels, (height - h - 1) * rme::SpritePixels); img.Destroy(); } } @@ -954,7 +954,7 @@ wxMemoryDC* GameSprite::getDC(SpriteSize size) } // Now comes the resizing / antialiasing - if(size == SPRITE_SIZE_16x16 || image.GetWidth() > SPRITE_PIXELS || image.GetHeight() > SPRITE_PIXELS) { + if(size == SPRITE_SIZE_16x16 || image.GetWidth() > rme::SpritePixels || image.GetHeight() > rme::SpritePixels) { int new_size = SPRITE_SIZE_16x16 ? 16 : 32; image.Rescale(new_size, new_size); } @@ -1011,7 +1011,7 @@ void GameSprite::Image::createGLTexture(GLuint textureId) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 0x812F); // GL_CLAMP_TO_EDGE glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 0x812F); // GL_CLAMP_TO_EDGE - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SPRITE_PIXELS, SPRITE_PIXELS, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rme::SpritePixels, rme::SpritePixels, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba); delete[] rgba; } @@ -1069,7 +1069,7 @@ uint8_t* GameSprite::NormalImage::getRGBData() } } - const int pixels_data_size = SPRITE_PIXELS * SPRITE_PIXELS * 3; + const int pixels_data_size = rme::SpritePixels * rme::SpritePixels * 3; uint8_t* data = newd uint8_t[pixels_data_size]; uint8_t bpp = g_gui.gfx.hasTransparency() ? 4 : 3; int write = 0; @@ -1120,7 +1120,7 @@ uint8_t* GameSprite::NormalImage::getRGBAData() } } - const int pixels_data_size = SPRITE_PIXELS_SIZE * 4; + const int pixels_data_size = rme::SpritePixelsSize * 4; uint8_t* data = newd uint8_t[pixels_data_size]; bool use_alpha = g_gui.gfx.hasTransparency(); uint8_t bpp = use_alpha ? 4 : 3; @@ -1130,7 +1130,7 @@ uint8_t* GameSprite::NormalImage::getRGBAData() // decompress pixels while(read < size && write < pixels_data_size) { int transparent = dump[read] | dump[read + 1] << 8; - if(use_alpha && transparent >= SPRITE_PIXELS_SIZE) // Corrupted sprite? + if(use_alpha && transparent >= rme::SpritePixelsSize) // Corrupted sprite? break; read += 2; for(int i = 0; i < transparent && write < pixels_data_size; i++) { @@ -1192,24 +1192,24 @@ void GameSprite::EditorImage::createGLTexture(GLuint textureId) { ASSERT(!isGLLoaded); - wxSize size(SPRITE_PIXELS, SPRITE_PIXELS); + wxSize size(rme::SpritePixels, rme::SpritePixels); wxBitmap bitmap = wxArtProvider::GetBitmap(bitmapId, wxART_OTHER, size); wxNativePixelData data(bitmap); if (!data) return; - const int imageSize = SPRITE_PIXELS_SIZE * 4; + const int imageSize = rme::SpritePixelsSize * 4; GLubyte *imageData = new GLubyte[imageSize]; int write = 0; wxNativePixelData::Iterator it(data); it.Offset(data, 0, 0); - for (size_t y = 0; y < SPRITE_PIXELS; ++y) + for(size_t y = 0; y < rme::SpritePixels; ++y) { wxNativePixelData::Iterator row_start = it; - for(size_t x = 0; x < SPRITE_PIXELS; ++x, it++) + for(size_t x = 0; x < rme::SpritePixels; ++x, it++) { uint8_t red = it.Red(); uint8_t green = it.Green(); @@ -1236,7 +1236,7 @@ void GameSprite::EditorImage::createGLTexture(GLuint textureId) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 0x812F); // GL_CLAMP_TO_EDGE glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 0x812F); // GL_CLAMP_TO_EDGE - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SPRITE_PIXELS, SPRITE_PIXELS, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rme::SpritePixels, rme::SpritePixels, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData); delete[] imageData; } @@ -1301,15 +1301,15 @@ uint8_t* GameSprite::TemplateImage::getRGBData() lookFeet = 0; } - for(int y = 0; y < SPRITE_PIXELS; ++y) { - for(int x = 0; x < SPRITE_PIXELS; ++x) { - uint8_t& red = rgbdata[y*SPRITE_PIXELS*3 + x*3 + 0]; - uint8_t& green = rgbdata[y*SPRITE_PIXELS*3 + x*3 + 1]; - uint8_t& blue = rgbdata[y*SPRITE_PIXELS*3 + x*3 + 2]; + for(int y = 0; y < rme::SpritePixels; ++y) { + for(int x = 0; x < rme::SpritePixels; ++x) { + uint8_t& red = rgbdata[y*rme::SpritePixels*3 + x*3 + 0]; + uint8_t& green = rgbdata[y*rme::SpritePixels*3 + x*3 + 1]; + uint8_t& blue = rgbdata[y*rme::SpritePixels*3 + x*3 + 2]; - uint8_t& tred = template_rgbdata[y*SPRITE_PIXELS*3 + x*3 + 0]; - uint8_t& tgreen = template_rgbdata[y*SPRITE_PIXELS*3 + x*3 + 1]; - uint8_t& tblue = template_rgbdata[y*SPRITE_PIXELS*3 + x*3 + 2]; + uint8_t& tred = template_rgbdata[y*rme::SpritePixels*3 + x*3 + 0]; + uint8_t& tgreen = template_rgbdata[y*rme::SpritePixels*3 + x*3 + 1]; + uint8_t& tblue = template_rgbdata[y*rme::SpritePixels*3 + x*3 + 2]; if(tred && tgreen && !tblue) { // yellow => head colorizePixel(lookHead, red, green, blue); @@ -1353,15 +1353,15 @@ uint8_t* GameSprite::TemplateImage::getRGBAData() lookFeet = 0; } - for(int y = 0; y < SPRITE_PIXELS; ++y) { - for(int x = 0; x < SPRITE_PIXELS; ++x) { - uint8_t& red = rgbadata[y*SPRITE_PIXELS*4 + x*4 + 0]; - uint8_t& green = rgbadata[y*SPRITE_PIXELS*4 + x*4 + 1]; - uint8_t& blue = rgbadata[y*SPRITE_PIXELS*4 + x*4 + 2]; + for(int y = 0; y < rme::SpritePixels; ++y) { + for(int x = 0; x < rme::SpritePixels; ++x) { + uint8_t& red = rgbadata[y*rme::SpritePixels*4 + x*4 + 0]; + uint8_t& green = rgbadata[y*rme::SpritePixels*4 + x*4 + 1]; + uint8_t& blue = rgbadata[y*rme::SpritePixels*4 + x*4 + 2]; - uint8_t& tred = template_rgbdata[y*SPRITE_PIXELS*3 + x*3 + 0]; - uint8_t& tgreen = template_rgbdata[y*SPRITE_PIXELS*3 + x*3 + 1]; - uint8_t& tblue = template_rgbdata[y*SPRITE_PIXELS*3 + x*3 + 2]; + uint8_t& tred = template_rgbdata[y*rme::SpritePixels*3 + x*3 + 0]; + uint8_t& tgreen = template_rgbdata[y*rme::SpritePixels*3 + x*3 + 1]; + uint8_t& tblue = template_rgbdata[y*rme::SpritePixels*3 + x*3 + 2]; if(tred && tgreen && !tblue) { // yellow => head colorizePixel(lookHead, red, green, blue); diff --git a/source/gui.cpp b/source/gui.cpp index f2330454..e506b67a 100644 --- a/source/gui.cpp +++ b/source/gui.cpp @@ -1429,7 +1429,7 @@ void GUI::ChangeFloor(int new_floor) MapTab* tab = GetCurrentMapTab(); if(tab) { int old_floor = GetCurrentFloor(); - if(new_floor < 0 || new_floor > MAP_MAX_LAYER) + if(new_floor < rme::MapMinLayer || new_floor > rme::MapMaxLayer) return; if(old_floor != new_floor) @@ -1838,7 +1838,7 @@ void GUI::FillDoodadPreviewBuffer() // There is a huge deviation here with the other formula. area = 5; } else { - area = int(0.5 + GetBrushSize() * GetBrushSize() * PI); + area = int(0.5 + GetBrushSize() * GetBrushSize() * rme::PI); } } const int object_range = (use_custom_thickness ? int(area*custom_thickness_mod) : brush->getThickness() * area / std::max(1, brush->getThicknessCeiling())); diff --git a/source/main.h b/source/main.h index 6e2d89f3..9ac54705 100644 --- a/source/main.h +++ b/source/main.h @@ -125,13 +125,14 @@ _Ret_bytecap_(_Size) inline void* __CRTDECL operator new[](size_t _Size, const c #include #include -using StringVector = std::vector; -using FileName= wxFileName; +typedef std::vector StringVector; +typedef wxFileName FileName; #include "con_vector.h" #include "common.h" #include "threads.h" +#include "const.h" #include "rme_forward_declarations.h" #if wxCHECK_VERSION(3, 1, 0) diff --git a/source/main_menubar.cpp b/source/main_menubar.cpp index e72592b1..5685cf72 100644 --- a/source/main_menubar.cpp +++ b/source/main_menubar.cpp @@ -498,7 +498,7 @@ void MainMenuBar::UpdateFloorMenu() return; } - for (int i = 0; i < MAP_LAYERS; ++i) + for(int i = 0; i < rme::MapLayers; ++i) CheckItem(static_cast(MenuBar::FLOOR_0 + i), false); CheckItem(static_cast(MenuBar::FLOOR_0 + g_gui.GetCurrentFloor()), true); @@ -1385,8 +1385,8 @@ namespace OnMapRemoveUnreachable ez = 9; } else { // underground - sz = std::max(pos.z - 2, GROUND_LAYER); - ez = std::min(pos.z + 2, MAP_MAX_LAYER); + sz = std::max(pos.z - 2, rme::MapGroundLayer); + ez = std::min(pos.z + 2, rme::MapMaxLayer); } for(int z = sz; z <= ez; ++z) { diff --git a/source/main_toolbar.cpp b/source/main_toolbar.cpp index c51974ce..299d7741 100644 --- a/source/main_toolbar.cpp +++ b/source/main_toolbar.cpp @@ -105,11 +105,11 @@ MainToolBar::MainToolBar(wxWindow* parent, wxAuiManager* manager) position_toolbar = newd wxAuiToolBar(parent, TOOLBAR_POSITION, wxDefaultPosition, wxDefaultSize, wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_HORZ_TEXT); position_toolbar->SetToolBitmapSize(icon_size); - x_control = newd NumberTextCtrl(position_toolbar, wxID_ANY, 0, 0, MAP_MAX_WIDTH, wxTE_PROCESS_ENTER, "X", wxDefaultPosition, FROM_DIP(parent, wxSize(60, 20))); + x_control = newd NumberTextCtrl(position_toolbar, wxID_ANY, 0, 0, rme::MapMaxWidth, wxTE_PROCESS_ENTER, "X", wxDefaultPosition, FROM_DIP(parent, wxSize(60, 20))); x_control->SetToolTip("X Coordinate"); - y_control = newd NumberTextCtrl(position_toolbar, wxID_ANY, 0, 0, MAP_MAX_HEIGHT, wxTE_PROCESS_ENTER, "Y", wxDefaultPosition, FROM_DIP(parent, wxSize(60, 20))); + y_control = newd NumberTextCtrl(position_toolbar, wxID_ANY, 0, 0, rme::MapMaxHeight, wxTE_PROCESS_ENTER, "Y", wxDefaultPosition, FROM_DIP(parent, wxSize(60, 20))); y_control->SetToolTip("Y Coordinate"); - z_control = newd NumberTextCtrl(position_toolbar, wxID_ANY, 0, 0, MAP_MAX_LAYER, wxTE_PROCESS_ENTER, "Z", wxDefaultPosition, FROM_DIP(parent, wxSize(35, 20))); + z_control = newd NumberTextCtrl(position_toolbar, wxID_ANY, 0, 0, rme::MapMaxLayer, wxTE_PROCESS_ENTER, "Z", wxDefaultPosition, FROM_DIP(parent, wxSize(35, 20))); z_control->SetToolTip("Z Coordinate"); go_button = newd wxButton(position_toolbar, TOOLBAR_POSITION_GO, wxEmptyString, wxDefaultPosition, FROM_DIP(parent, wxSize(22, 20))); go_button->SetBitmap(go_bitmap); diff --git a/source/map.cpp b/source/map.cpp index 90226fb9..e5f1ea21 100644 --- a/source/map.cpp +++ b/source/map.cpp @@ -78,10 +78,10 @@ bool Map::open(const std::string file) for(int x = 20; ; x += 2) { int y = 22; - Tile* old = getTile(x, y, GROUND_LAYER); + Tile* old = getTile(x, y, rme::MapGroundLayer); if(old) { y -= 2; - Tile* new_ = getTile(x, y, GROUND_LAYER); + Tile* new_ = getTile(x, y, rme::MapGroundLayer); if(new_) { if(old->ground || old->items.size()) { out << "\tvecval.clear();\n"; @@ -610,7 +610,7 @@ SpawnNpcList Map::getSpawnNpcList(int x, int y, int z) const return getSpawnNpcList(tile); } -bool Map::exportMinimap(FileName filename, int floor /*= GROUND_LAYER*/, bool displaydialog) +bool Map::exportMinimap(FileName filename, int floor /*= rme::MapGroundLayer*/, bool displaydialog) { uint8_t* pic = nullptr; @@ -815,7 +815,7 @@ void Map::removeUniqueId(uint16_t uid) bool Map::hasUniqueId(uint16_t uid) const { - if (uid < MIN_UNIQUE_ID || uniqueIds.empty()) + if (uid < rme::MinUniqueId || uniqueIds.empty()) return false; auto it = std::find(uniqueIds.begin(), uniqueIds.end(), uid); diff --git a/source/map.h b/source/map.h index b5526da5..d7e06650 100644 --- a/source/map.h +++ b/source/map.h @@ -38,7 +38,7 @@ class Map : public BaseMap // Operations on the entire map void cleanInvalidTiles(bool showdialog = false); // Save a bmp image of the minimap - bool exportMinimap(FileName filename, int floor = GROUND_LAYER, bool showdialog = false); + bool exportMinimap(FileName filename, int floor = rme::MapGroundLayer, bool showdialog = false); // bool convert(MapVersion to, bool showdialog = false); bool convert(const ConversionMap& cm, bool showdialog = false); diff --git a/source/map_display.cpp b/source/map_display.cpp index 944d6059..7650b637 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -110,7 +110,7 @@ bool MapCanvas::processed[] = {0}; MapCanvas::MapCanvas(MapWindow* parent, Editor& editor, int* attriblist) : wxGLCanvas(parent, wxID_ANY, nullptr, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS), editor(editor), - floor(GROUND_LAYER), + floor(rme::MapGroundLayer), zoom(1.0), cursor_x(-1), cursor_y(-1), @@ -352,23 +352,23 @@ void MapCanvas::ScreenToMap(int screen_x, int screen_y, int* map_x, int* map_y) screen_y *= GetContentScaleFactor(); if(screen_x < 0) { - *map_x = (start_x + screen_x) / TILE_SIZE; + *map_x = (start_x + screen_x) / rme::TileSize; } else { - *map_x = int(start_x + (screen_x * zoom)) / TILE_SIZE; + *map_x = int(start_x + (screen_x * zoom)) / rme::TileSize; } if(screen_y < 0) { - *map_y = (start_y + screen_y) / TILE_SIZE; + *map_y = (start_y + screen_y) / rme::TileSize; } else { - *map_y = int(start_y + (screen_y * zoom)) / TILE_SIZE; + *map_y = int(start_y + (screen_y * zoom)) / rme::TileSize; } - if(floor <= GROUND_LAYER) { - *map_x += GROUND_LAYER - floor; - *map_y += GROUND_LAYER - floor; + if(floor <= rme::MapGroundLayer) { + *map_x += rme::MapGroundLayer - floor; + *map_y += rme::MapGroundLayer - floor; }/* else { - *map_x += MAP_MAX_LAYER - floor; - *map_y += MAP_MAX_LAYER - floor; + *map_x += rme::MapMaxLayer - floor; + *map_y += rme::MapMaxLayer - floor; }*/ } @@ -1094,17 +1094,17 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) case SELECT_ALL_FLOORS: { start_x = last_click_map_x; start_y = last_click_map_y; - start_z = MAP_MAX_LAYER; + start_z = rme::MapMaxLayer; end_x = mouse_map_x; end_y = mouse_map_y; end_z = floor; if(g_settings.getInteger(Config::COMPENSATED_SELECT)) { - start_x -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); - start_y -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); + start_x -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); + start_y -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); - end_x -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); - end_y -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); + end_x -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); + end_y -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); } numtiles = (start_z - end_z) * (end_x - start_x) * (end_y - start_y); @@ -1114,20 +1114,20 @@ void MapCanvas::OnMouseActionRelease(wxMouseEvent& event) start_x = last_click_map_x; start_y = last_click_map_y; if(floor < 8) { - start_z = GROUND_LAYER; + start_z = rme::MapGroundLayer; } else { - start_z = std::min(MAP_MAX_LAYER, floor + 2); + start_z = std::min(rme::MapMaxLayer, floor + 2); } end_x = mouse_map_x; end_y = mouse_map_y; end_z = floor; if(g_settings.getInteger(Config::COMPENSATED_SELECT)) { - start_x -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); - start_y -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); + start_x -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); + start_y -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); - end_x -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); - end_y -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); + end_x -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); + end_y -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); } break; } @@ -1521,17 +1521,17 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) start_x = last_click_map_x; start_y = last_click_map_y; - start_z = MAP_MAX_LAYER; + start_z = rme::MapMaxLayer; end_x = mouse_map_x; end_y = mouse_map_y; end_z = floor; if(g_settings.getInteger(Config::COMPENSATED_SELECT)) { - start_x -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); - start_y -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); + start_x -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); + start_y -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); - end_x -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); - end_y -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); + end_x -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); + end_y -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); } for(int z = start_z; z >= end_z; z--) { @@ -1542,7 +1542,7 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) selection.add(tile); } } - if(z <= GROUND_LAYER && g_settings.getInteger(Config::COMPENSATED_SELECT)) { + if(z <= rme::MapGroundLayer && g_settings.getInteger(Config::COMPENSATED_SELECT)) { start_x++; start_y++; end_x++; end_y++; } @@ -1556,20 +1556,20 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) start_x = last_click_map_x; start_y = last_click_map_y; if(floor < 8) { - start_z = GROUND_LAYER; + start_z = rme::MapGroundLayer; } else { - start_z = std::min(MAP_MAX_LAYER, floor + 2); + start_z = std::min(rme::MapMaxLayer, floor + 2); } end_x = mouse_map_x; end_y = mouse_map_y; end_z = floor; if(g_settings.getInteger(Config::COMPENSATED_SELECT)) { - start_x -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); - start_y -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); + start_x -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); + start_y -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); - end_x -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); - end_y -= (floor < GROUND_LAYER ? GROUND_LAYER - floor : 0); + end_x -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); + end_y -= (floor < rme::MapGroundLayer ? rme::MapGroundLayer - floor : 0); } for(int z = start_z; z >= end_z; z--) { @@ -1580,7 +1580,7 @@ void MapCanvas::OnMousePropertiesRelease(wxMouseEvent& event) selection.add(tile); } } - if(z <= GROUND_LAYER && g_settings.getInteger(Config::COMPENSATED_SELECT)) { + if(z <= rme::MapGroundLayer && g_settings.getInteger(Config::COMPENSATED_SELECT)) { start_x++; start_y++; end_x++; end_y++; } @@ -1770,7 +1770,7 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) else if(zoom == 1.0) tiles = 1; - window->Scroll(start_x, int(start_y - TILE_SIZE * tiles * zoom)); + window->Scroll(start_x, int(start_y - rme::TileSize * tiles * zoom)); UpdatePositionStatus(); Refresh(); break; @@ -1786,7 +1786,7 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) else if(zoom == 1.0) tiles = 1; - window->Scroll(start_x, int(start_y + TILE_SIZE * tiles * zoom)); + window->Scroll(start_x, int(start_y + rme::TileSize * tiles * zoom)); UpdatePositionStatus(); Refresh(); break; @@ -1802,7 +1802,7 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) else if(zoom == 1.0) tiles = 1; - window->Scroll(int(start_x - TILE_SIZE * tiles * zoom), start_y); + window->Scroll(int(start_x - rme::TileSize * tiles * zoom), start_y); UpdatePositionStatus(); Refresh(); break; @@ -1818,7 +1818,7 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) else if(zoom == 1.0) tiles = 1; - window->Scroll(int(start_x + TILE_SIZE * tiles * zoom), start_y); + window->Scroll(int(start_x + rme::TileSize * tiles * zoom), start_y); UpdatePositionStatus(); Refresh(); break; @@ -1881,13 +1881,13 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) if(g_gui.IsSelectionMode()) { int view_start_x, view_start_y; window->GetViewStart(&view_start_x, &view_start_y); - int view_start_map_x = view_start_x / TILE_SIZE, view_start_map_y = view_start_y / TILE_SIZE; + int view_start_map_x = view_start_x / rme::TileSize, view_start_map_y = view_start_y / rme::TileSize; int view_screensize_x, view_screensize_y; window->GetViewSize(&view_screensize_x, &view_screensize_y); - int map_x = int(view_start_map_x + (view_screensize_x * zoom) / TILE_SIZE / 2); - int map_y = int(view_start_map_y + (view_screensize_y * zoom) / TILE_SIZE / 2); + int map_x = int(view_start_map_x + (view_screensize_x * zoom) / rme::TileSize / 2); + int map_y = int(view_start_map_y + (view_screensize_y * zoom) / rme::TileSize / 2); hk = Hotkey(Position(map_x, map_y, floor)); } else if(g_gui.GetCurrentBrush()) { @@ -1907,7 +1907,7 @@ void MapCanvas::OnKeyDown(wxKeyEvent& event) int map_y = hk.GetPosition().y; int map_z = hk.GetPosition().z; - window->Scroll(TILE_SIZE * map_x, TILE_SIZE * map_y, true); + window->Scroll(rme::TileSize * map_x, rme::TileSize * map_y, true); floor = map_z; g_gui.SetStatusText("Used hotkey " + i2ws(index)); @@ -2335,7 +2335,7 @@ void MapCanvas::OnProperties(wxCommandEvent& WXUNUSED(event)) void MapCanvas::ChangeFloor(int new_floor) { - ASSERT(new_floor >= 0 || new_floor <= MAP_MAX_LAYER); + ASSERT(new_floor >= 0 || new_floor <= rme::MapMaxLayer); int old_floor = floor; floor = new_floor; if(old_floor != new_floor) { @@ -2384,7 +2384,7 @@ void MapCanvas::Reset() cursor_y = 0; zoom = 1.0; - floor = GROUND_LAYER; + floor = rme::MapGroundLayer; dragging = false; boundbox_selection = false; diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index 61ccb3f4..b9059e92 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -149,25 +149,25 @@ void MapDrawer::SetupVars() dragging_draw = canvas->dragging_draw; zoom = static_cast(canvas->GetZoom()); - tile_size = int(TILE_SIZE / zoom); // after zoom + tile_size = int(rme::TileSize / zoom); // after zoom floor = canvas->GetFloor(); if(options.show_all_floors) { if(floor < 8) - start_z = GROUND_LAYER; + start_z = rme::MapGroundLayer; else - start_z = std::min(MAP_MAX_LAYER, floor + 2); + start_z = std::min(rme::MapMaxLayer, floor + 2); } else start_z = floor; end_z = floor; - superend_z = (floor > GROUND_LAYER ? 8 : 0); + superend_z = (floor > rme::MapGroundLayer ? 8 : 0); - start_x = view_scroll_x / TILE_SIZE; - start_y = view_scroll_y / TILE_SIZE; + start_x = view_scroll_x / rme::TileSize; + start_y = view_scroll_y / rme::TileSize; - if(floor > GROUND_LAYER) { + if(floor > rme::MapGroundLayer) { start_x -= 2; start_y -= 2; } @@ -245,10 +245,10 @@ void MapDrawer::DrawBackground() inline int getFloorAdjustment(int floor) { - if(floor > GROUND_LAYER) // Underground + if(floor > rme::MapGroundLayer) // Underground return 0; // No adjustment else - return TILE_SIZE * (GROUND_LAYER - floor); + return rme::TileSize * (rme::MapGroundLayer - floor); } void MapDrawer::DrawShade(int map_z) @@ -316,7 +316,7 @@ void MapDrawer::DrawMap() nd->setVisible(false, false); } - if(!live_client || nd->isVisible(map_z > GROUND_LAYER)) { + if(!live_client || nd->isVisible(map_z > rme::MapGroundLayer)) { for(int map_x = 0; map_x < 4; ++map_x) { for(int map_y = 0; map_y < 4; ++map_y) { DrawTile(nd->getTile(map_x, map_y, map_z)); @@ -330,19 +330,19 @@ void MapDrawer::DrawMap() } } } else { - if(!nd->isRequested(map_z > GROUND_LAYER)) { + if(!nd->isRequested(map_z > rme::MapGroundLayer)) { // Request the node - editor.QueryNode(nd_map_x, nd_map_y, map_z > GROUND_LAYER); - nd->setRequested(map_z > GROUND_LAYER, true); + editor.QueryNode(nd_map_x, nd_map_y, map_z > rme::MapGroundLayer); + nd->setRequested(map_z > rme::MapGroundLayer, true); } - int cy = (nd_map_y) * TILE_SIZE - view_scroll_y - getFloorAdjustment(floor); - int cx = (nd_map_x) * TILE_SIZE - view_scroll_x - getFloorAdjustment(floor); + int cy = (nd_map_y) * rme::TileSize - view_scroll_y - getFloorAdjustment(floor); + int cx = (nd_map_x) * rme::TileSize - view_scroll_x - getFloorAdjustment(floor); glColor4ub(255, 0, 255, 128); glBegin(GL_QUADS); - glVertex2f(cx, cy + TILE_SIZE * 4); - glVertex2f(cx + TILE_SIZE * 4, cy + TILE_SIZE * 4); - glVertex2f(cx + TILE_SIZE * 4, cy); + glVertex2f(cx, cy + rme::TileSize * 4); + glVertex2f(cx + rme::TileSize * 4, cy + rme::TileSize * 4); + glVertex2f(cx + rme::TileSize * 4, cy); glVertex2f(cx, cy); glEnd(); } @@ -391,7 +391,7 @@ void MapDrawer::DrawSecondaryMap(int map_z) for(int map_y = start_y; map_y <= end_y; map_y++) { Position final_pos(map_x, map_y, map_z); Position pos = normal_pos + final_pos - to_pos; - if(pos.z < 0 || pos.z >= MAP_LAYERS) { + if(pos.z < 0 || pos.z >= rme::MapLayers) { continue; } @@ -467,13 +467,13 @@ void MapDrawer::DrawIngameBox() int offset_y = 2; int box_start_map_x = center_x; int box_start_map_y = center_y + offset_y; - int box_end_map_x = center_x + CLIENT_MAP_WIDTH; - int box_end_map_y = center_y + CLIENT_MAP_HEIGHT + offset_y; + int box_end_map_x = center_x + rme::ClientMapWidth; + int box_end_map_y = center_y + rme::ClientMapHeight + offset_y; - int box_start_x = box_start_map_x * TILE_SIZE - view_scroll_x; - int box_start_y = box_start_map_y * TILE_SIZE - view_scroll_y; - int box_end_x = box_end_map_x * TILE_SIZE - view_scroll_x; - int box_end_y = box_end_map_y * TILE_SIZE - view_scroll_y; + int box_start_x = box_start_map_x * rme::TileSize - view_scroll_x; + int box_start_y = box_start_map_y * rme::TileSize - view_scroll_y; + int box_end_x = box_end_map_x * rme::TileSize - view_scroll_x; + int box_end_y = box_end_map_y * rme::TileSize - view_scroll_y; if(box_start_map_x >= start_x) { glColor4ub(0, 0, 0, 128); @@ -525,10 +525,10 @@ void MapDrawer::DrawIngameBox() glVertex2f(box_start_x, box_start_y); glEnd(); - box_start_x += TILE_SIZE; - box_start_y += TILE_SIZE; - box_end_x -= 2 * TILE_SIZE; - box_end_y -= 2 * TILE_SIZE; + box_start_x += rme::TileSize; + box_start_y += rme::TileSize; + box_end_x -= 2 * rme::TileSize; + box_end_y -= 2 * rme::TileSize; // client visible tiles glColor4ub(0, 255, 0, 128); @@ -540,10 +540,10 @@ void MapDrawer::DrawIngameBox() glVertex2f(box_start_x, box_start_y); glEnd(); - box_start_x += ((CLIENT_MAP_WIDTH/2)-2) * TILE_SIZE; - box_start_y += ((CLIENT_MAP_HEIGHT/2)-2) * TILE_SIZE; - box_end_x = box_start_x + TILE_SIZE; - box_end_y = box_start_y + TILE_SIZE; + box_start_x += ((rme::ClientMapWidth/2)-2) * rme::TileSize; + box_start_y += ((rme::ClientMapHeight/2)-2) * rme::TileSize; + box_end_x = box_start_x + rme::TileSize; + box_end_y = box_start_y + rme::TileSize; // client player position glColor4ub(0, 255, 0, 128); @@ -561,16 +561,16 @@ void MapDrawer::DrawGrid() for(int y = start_y; y < end_y; ++y) { glColor4ub(255, 255, 255, 128); glBegin(GL_LINES); - glVertex2f(start_x * TILE_SIZE - view_scroll_x, y * TILE_SIZE - view_scroll_y); - glVertex2f(end_x * TILE_SIZE - view_scroll_x, y * TILE_SIZE - view_scroll_y); + glVertex2f(start_x * rme::TileSize - view_scroll_x, y * rme::TileSize - view_scroll_y); + glVertex2f(end_x * rme::TileSize - view_scroll_x, y * rme::TileSize - view_scroll_y); glEnd(); } for(int x = start_x; x < end_x; ++x) { glColor4ub(255, 255, 255, 128); glBegin(GL_LINES); - glVertex2f(x * TILE_SIZE - view_scroll_x, start_y * TILE_SIZE - view_scroll_y); - glVertex2f(x * TILE_SIZE - view_scroll_x, end_y * TILE_SIZE - view_scroll_y); + glVertex2f(x * rme::TileSize - view_scroll_x, start_y * rme::TileSize - view_scroll_y); + glVertex2f(x * rme::TileSize - view_scroll_x, end_y * rme::TileSize - view_scroll_y); glEnd(); } } @@ -592,7 +592,7 @@ void MapDrawer::DrawDraggingShadow() const Position& position = tile->getPosition(); int pos_z = position.z - move_z; - if(pos_z < 0 || pos_z >= MAP_LAYERS) { + if(pos_z < 0 || pos_z >= rme::MapLayers) { continue; } @@ -723,11 +723,11 @@ void MapDrawer::DrawLiveCursors() LiveSocket& live = editor.GetLive(); for(LiveCursor& cursor : live.getCursorList()) { - if(cursor.pos.z <= GROUND_LAYER && floor > GROUND_LAYER) { + if(cursor.pos.z <= rme::MapGroundLayer && floor > rme::MapGroundLayer) { continue; } - if(cursor.pos.z > GROUND_LAYER && floor <= 8) { + if(cursor.pos.z > rme::MapGroundLayer && floor <= 8) { continue; } @@ -741,20 +741,20 @@ void MapDrawer::DrawLiveCursors() } int offset; - if (cursor.pos.z <= GROUND_LAYER) - offset = (GROUND_LAYER - cursor.pos.z) * TILE_SIZE; + if(cursor.pos.z <= rme::MapGroundLayer) + offset = (rme::MapGroundLayer - cursor.pos.z) * rme::TileSize; else - offset = TILE_SIZE * (floor - cursor.pos.z); + offset = rme::TileSize * (floor - cursor.pos.z); - float draw_x = ((cursor.pos.x * TILE_SIZE) - view_scroll_x) - offset; - float draw_y = ((cursor.pos.y * TILE_SIZE) - view_scroll_y) - offset; + float draw_x = ((cursor.pos.x * rme::TileSize) - view_scroll_x) - offset; + float draw_y = ((cursor.pos.y * rme::TileSize) - view_scroll_y) - offset; glColor(cursor.color); glBegin(GL_QUADS); glVertex2f(draw_x, draw_y); - glVertex2f(draw_x + TILE_SIZE, draw_y); - glVertex2f(draw_x + TILE_SIZE, draw_y + TILE_SIZE); - glVertex2f(draw_x, draw_y + TILE_SIZE); + glVertex2f(draw_x + rme::TileSize, draw_y); + glVertex2f(draw_x + rme::TileSize, draw_y + rme::TileSize); + glVertex2f(draw_x, draw_y + rme::TileSize); glEnd(); } } @@ -795,10 +795,10 @@ void MapDrawer::DrawBrush() int last_click_end_map_x = std::max(canvas->last_click_map_x, mouse_map_x)+1; int last_click_end_map_y = std::max(canvas->last_click_map_y, mouse_map_y)+1; - int last_click_start_sx = last_click_start_map_x * TILE_SIZE - view_scroll_x - adjustment; - int last_click_start_sy = last_click_start_map_y * TILE_SIZE - view_scroll_y - adjustment; - int last_click_end_sx = last_click_end_map_x * TILE_SIZE - view_scroll_x - adjustment; - int last_click_end_sy = last_click_end_map_y * TILE_SIZE - view_scroll_y - adjustment; + int last_click_start_sx = last_click_start_map_x * rme::TileSize - view_scroll_x - adjustment; + int last_click_start_sy = last_click_start_map_y * rme::TileSize - view_scroll_y - adjustment; + int last_click_end_sx = last_click_end_map_x * rme::TileSize - view_scroll_x - adjustment; + int last_click_end_sy = last_click_end_map_y * rme::TileSize - view_scroll_y - adjustment; int delta_x = last_click_end_sx - last_click_start_sx; int delta_y = last_click_end_sy - last_click_start_sy; @@ -806,29 +806,29 @@ void MapDrawer::DrawBrush() glColor(brushColor); glBegin(GL_QUADS); { - glVertex2f(last_click_start_sx, last_click_start_sy + TILE_SIZE); - glVertex2f(last_click_end_sx, last_click_start_sy + TILE_SIZE); + glVertex2f(last_click_start_sx, last_click_start_sy + rme::TileSize); + glVertex2f(last_click_end_sx, last_click_start_sy + rme::TileSize); glVertex2f(last_click_end_sx, last_click_start_sy); glVertex2f(last_click_start_sx, last_click_start_sy); } - if(delta_y > TILE_SIZE) { - glVertex2f(last_click_start_sx, last_click_end_sy - TILE_SIZE); - glVertex2f(last_click_start_sx + TILE_SIZE, last_click_end_sy - TILE_SIZE); - glVertex2f(last_click_start_sx + TILE_SIZE, last_click_start_sy + TILE_SIZE); - glVertex2f(last_click_start_sx, last_click_start_sy + TILE_SIZE); + if(delta_y > rme::TileSize) { + glVertex2f(last_click_start_sx, last_click_end_sy - rme::TileSize); + glVertex2f(last_click_start_sx + rme::TileSize, last_click_end_sy - rme::TileSize); + glVertex2f(last_click_start_sx + rme::TileSize, last_click_start_sy + rme::TileSize); + glVertex2f(last_click_start_sx, last_click_start_sy + rme::TileSize); } - if(delta_x > TILE_SIZE && delta_y > TILE_SIZE) { - glVertex2f(last_click_end_sx - TILE_SIZE, last_click_start_sy + TILE_SIZE); - glVertex2f(last_click_end_sx, last_click_start_sy + TILE_SIZE); - glVertex2f(last_click_end_sx, last_click_end_sy - TILE_SIZE); - glVertex2f(last_click_end_sx - TILE_SIZE, last_click_end_sy - TILE_SIZE); + if(delta_x > rme::TileSize && delta_y > rme::TileSize) { + glVertex2f(last_click_end_sx - rme::TileSize, last_click_start_sy + rme::TileSize); + glVertex2f(last_click_end_sx, last_click_start_sy + rme::TileSize); + glVertex2f(last_click_end_sx, last_click_end_sy - rme::TileSize); + glVertex2f(last_click_end_sx - rme::TileSize, last_click_end_sy - rme::TileSize); } - if (delta_y > TILE_SIZE) { - glVertex2f(last_click_start_sx, last_click_end_sy - TILE_SIZE); - glVertex2f(last_click_end_sx, last_click_end_sy - TILE_SIZE); + if(delta_y > rme::TileSize) { + glVertex2f(last_click_start_sx, last_click_end_sy - rme::TileSize); + glVertex2f(last_click_end_sx, last_click_end_sy - rme::TileSize); glVertex2f(last_click_end_sx, last_click_end_sy); glVertex2f(last_click_start_sx, last_click_end_sy); } @@ -862,9 +862,9 @@ void MapDrawer::DrawBrush() raw_brush = brush->asRaw(); for(int y = start_y; y <= end_y; y++) { - int cy = y * TILE_SIZE - view_scroll_y - adjustment; + int cy = y * rme::TileSize - view_scroll_y - adjustment; for(int x = start_x; x <= end_x; x++) { - int cx = x * TILE_SIZE - view_scroll_x - adjustment; + int cx = x * rme::TileSize - view_scroll_x - adjustment; if(brush->isOptionalBorder()) glColorCheck(brush, Position(x, y, floor)); else @@ -877,10 +877,10 @@ void MapDrawer::DrawBrush() int last_click_end_map_x = std::max(canvas->last_click_map_x, mouse_map_x)+1; int last_click_end_map_y = std::max(canvas->last_click_map_y, mouse_map_y)+1; - int last_click_start_sx = last_click_start_map_x * TILE_SIZE - view_scroll_x - adjustment; - int last_click_start_sy = last_click_start_map_y * TILE_SIZE - view_scroll_y - adjustment; - int last_click_end_sx = last_click_end_map_x * TILE_SIZE - view_scroll_x - adjustment; - int last_click_end_sy = last_click_end_map_y * TILE_SIZE - view_scroll_y - adjustment; + int last_click_start_sx = last_click_start_map_x * rme::TileSize - view_scroll_x - adjustment; + int last_click_start_sy = last_click_start_map_y * rme::TileSize - view_scroll_y - adjustment; + int last_click_end_sx = last_click_end_map_x * rme::TileSize - view_scroll_x - adjustment; + int last_click_end_sy = last_click_end_map_y * rme::TileSize - view_scroll_y - adjustment; glColor(brushColor); glBegin(GL_QUADS); @@ -924,10 +924,10 @@ void MapDrawer::DrawBrush() raw_brush = brush->asRaw(); for(int y = start_y-1; y <= end_y+1; y++) { - int cy = y * TILE_SIZE - view_scroll_y - adjustment; + int cy = y * rme::TileSize - view_scroll_y - adjustment; float dy = center_y - y; for(int x = start_x-1; x <= end_x+1; x++) { - int cx = x * TILE_SIZE - view_scroll_x - adjustment; + int cx = x * rme::TileSize - view_scroll_x - adjustment; float dx = center_x - x; //printf("%f;%f\n", dx, dy); @@ -938,9 +938,9 @@ void MapDrawer::DrawBrush() } else { glColor(brushColor); glBegin(GL_QUADS); - glVertex2f(cx, cy + TILE_SIZE); - glVertex2f(cx + TILE_SIZE, cy + TILE_SIZE); - glVertex2f(cx + TILE_SIZE, cy); + glVertex2f(cx, cy + rme::TileSize); + glVertex2f(cx + rme::TileSize, cy + rme::TileSize); + glVertex2f(cx + rme::TileSize, cy); glVertex2f(cx, cy); glEnd(); } @@ -959,10 +959,10 @@ void MapDrawer::DrawBrush() int end_map_x = mouse_map_x + g_gui.GetBrushSize() + 1; int end_map_y = mouse_map_y + g_gui.GetBrushSize() + 1; - int start_sx = start_map_x * TILE_SIZE - view_scroll_x - adjustment; - int start_sy = start_map_y * TILE_SIZE - view_scroll_y - adjustment; - int end_sx = end_map_x * TILE_SIZE - view_scroll_x - adjustment; - int end_sy = end_map_y * TILE_SIZE - view_scroll_y - adjustment; + int start_sx = start_map_x * rme::TileSize - view_scroll_x - adjustment; + int start_sy = start_map_y * rme::TileSize - view_scroll_y - adjustment; + int end_sx = end_map_x * rme::TileSize - view_scroll_x - adjustment; + int end_sy = end_map_y * rme::TileSize - view_scroll_y - adjustment; int delta_x = end_sx - start_sx; int delta_y = end_sy - start_sy; @@ -970,48 +970,48 @@ void MapDrawer::DrawBrush() glColor(brushColor); glBegin(GL_QUADS); { - glVertex2f(start_sx, start_sy + TILE_SIZE); - glVertex2f(end_sx, start_sy + TILE_SIZE); + glVertex2f(start_sx, start_sy + rme::TileSize); + glVertex2f(end_sx, start_sy + rme::TileSize); glVertex2f(end_sx, start_sy); glVertex2f(start_sx, start_sy); } - if(delta_y > TILE_SIZE) { - glVertex2f(start_sx, end_sy - TILE_SIZE); - glVertex2f(start_sx + TILE_SIZE, end_sy - TILE_SIZE); - glVertex2f(start_sx + TILE_SIZE, start_sy + TILE_SIZE); - glVertex2f(start_sx, start_sy + TILE_SIZE); + if(delta_y > rme::TileSize) { + glVertex2f(start_sx, end_sy - rme::TileSize); + glVertex2f(start_sx + rme::TileSize, end_sy - rme::TileSize); + glVertex2f(start_sx + rme::TileSize, start_sy + rme::TileSize); + glVertex2f(start_sx, start_sy + rme::TileSize); } - if(delta_x > TILE_SIZE && delta_y > TILE_SIZE) { - glVertex2f(end_sx - TILE_SIZE, start_sy + TILE_SIZE); - glVertex2f(end_sx, start_sy + TILE_SIZE); - glVertex2f(end_sx, end_sy - TILE_SIZE); - glVertex2f(end_sx - TILE_SIZE, end_sy - TILE_SIZE); + if(delta_x > rme::TileSize && delta_y > rme::TileSize) { + glVertex2f(end_sx - rme::TileSize, start_sy + rme::TileSize); + glVertex2f(end_sx, start_sy + rme::TileSize); + glVertex2f(end_sx, end_sy - rme::TileSize); + glVertex2f(end_sx - rme::TileSize, end_sy - rme::TileSize); } - if(delta_y > TILE_SIZE) { - glVertex2f(start_sx, end_sy - TILE_SIZE); - glVertex2f(end_sx, end_sy - TILE_SIZE); + if(delta_y > rme::TileSize) { + glVertex2f(start_sx, end_sy - rme::TileSize); + glVertex2f(end_sx, end_sy - rme::TileSize); glVertex2f(end_sx, end_sy); glVertex2f(start_sx, end_sy); } glEnd(); } else if(brush->isDoor()) { - int cx = (mouse_map_x) * TILE_SIZE - view_scroll_x - adjustment; - int cy = (mouse_map_y) * TILE_SIZE - view_scroll_y - adjustment; + int cx = (mouse_map_x) * rme::TileSize - view_scroll_x - adjustment; + int cy = (mouse_map_y) * rme::TileSize - view_scroll_y - adjustment; glColorCheck(brush, Position(mouse_map_x, mouse_map_y, floor)); glBegin(GL_QUADS); - glVertex2f(cx, cy + TILE_SIZE); - glVertex2f(cx + TILE_SIZE, cy + TILE_SIZE); - glVertex2f(cx + TILE_SIZE, cy); + glVertex2f(cx, cy + rme::TileSize); + glVertex2f(cx + rme::TileSize, cy + rme::TileSize); + glVertex2f(cx + rme::TileSize, cy); glVertex2f(cx, cy); glEnd(); } else if(brush->isMonster()) { glEnable(GL_TEXTURE_2D); - int cy = (mouse_map_y) * TILE_SIZE - view_scroll_y - adjustment; - int cx = (mouse_map_x) * TILE_SIZE - view_scroll_x - adjustment; + int cy = (mouse_map_y) * rme::TileSize - view_scroll_y - adjustment; + int cx = (mouse_map_x) * rme::TileSize - view_scroll_x - adjustment; MonsterBrush* monster_brush = brush->asMonster(); if(monster_brush->canDraw(&editor.getMap(), Position(mouse_map_x, mouse_map_y, floor))) BlitCreature(cx, cy, monster_brush->getType()->outfit, SOUTH, 255, 255, 255, 160); @@ -1020,8 +1020,8 @@ void MapDrawer::DrawBrush() glDisable(GL_TEXTURE_2D); } else if(brush->isNpc()) { glEnable(GL_TEXTURE_2D); - int cy = (mouse_map_y) * TILE_SIZE - view_scroll_y - getFloorAdjustment(floor); - int cx = (mouse_map_x) * TILE_SIZE - view_scroll_x - getFloorAdjustment(floor); + int cy = (mouse_map_y) * rme::TileSize - view_scroll_y - getFloorAdjustment(floor); + int cx = (mouse_map_x) * rme::TileSize - view_scroll_x - getFloorAdjustment(floor); NpcBrush* npcBrush = brush->asNpc(); if(npcBrush->canDraw(&editor.getMap(), Position(mouse_map_x, mouse_map_y, floor))) BlitCreature(cx, cy, npcBrush->getType()->outfit, SOUTH, 255, 255, 255, 160); @@ -1036,9 +1036,9 @@ void MapDrawer::DrawBrush() } for(int y = -g_gui.GetBrushSize()-1; y <= g_gui.GetBrushSize()+1; y++) { - int cy = (mouse_map_y + y) * TILE_SIZE - view_scroll_y - adjustment; + int cy = (mouse_map_y + y) * rme::TileSize - view_scroll_y - adjustment; for(int x = -g_gui.GetBrushSize()-1; x <= g_gui.GetBrushSize()+1; x++) { - int cx = (mouse_map_x + x) * TILE_SIZE - view_scroll_x - adjustment; + int cx = (mouse_map_x + x) * rme::TileSize - view_scroll_x - adjustment; if(g_gui.GetBrushShape() == BRUSHSHAPE_SQUARE) { if(x >= -g_gui.GetBrushSize() && x <= g_gui.GetBrushSize() && y >= -g_gui.GetBrushSize() && y <= g_gui.GetBrushSize()) { if(brush->isRaw()) { @@ -1055,9 +1055,9 @@ void MapDrawer::DrawBrush() glColor(brushColor); glBegin(GL_QUADS); - glVertex2f(cx, cy + TILE_SIZE); - glVertex2f(cx + TILE_SIZE, cy + TILE_SIZE); - glVertex2f(cx + TILE_SIZE, cy); + glVertex2f(cx, cy + rme::TileSize); + glVertex2f(cx + rme::TileSize, cy + rme::TileSize); + glVertex2f(cx + rme::TileSize, cy); glVertex2f(cx, cy); glEnd(); } @@ -1080,9 +1080,9 @@ void MapDrawer::DrawBrush() glColor(brushColor); glBegin(GL_QUADS); - glVertex2f(cx, cy + TILE_SIZE); - glVertex2f(cx + TILE_SIZE, cy + TILE_SIZE); - glVertex2f(cx + TILE_SIZE, cy); + glVertex2f(cx, cy + rme::TileSize); + glVertex2f(cx + rme::TileSize, cy + rme::TileSize); + glVertex2f(cx + rme::TileSize, cy); glVertex2f(cx, cy); glEnd(); } @@ -1200,7 +1200,7 @@ void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Tile* tile, const Item* pattern_z, frame ); - glBlitTexture(screenx - cx * TILE_SIZE, screeny - cy * TILE_SIZE, texnum, red, green, blue, alpha); + glBlitTexture(screenx - cx * rme::TileSize, screeny - cy * rme::TileSize, texnum, red, green, blue, alpha); } } } @@ -1306,7 +1306,7 @@ void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Position& pos, const It pattern_z, frame ); - glBlitTexture(screenx - cx * TILE_SIZE, screeny - cy * TILE_SIZE, texnum, red, green, blue, alpha); + glBlitTexture(screenx - cx * rme::TileSize, screeny - cy * rme::TileSize, texnum, red, green, blue, alpha); } } } @@ -1333,7 +1333,7 @@ void MapDrawer::BlitSpriteType(int screenx, int screeny, uint32_t spriteid, int for(int cy = 0; cy != sprite->height; ++cy) { for(int cf = 0; cf != sprite->layers; ++cf) { int texnum = sprite->getHardwareID(cx,cy,cf,-1,0,0,0, frame); - glBlitTexture(screenx - cx * TILE_SIZE, screeny - cy * TILE_SIZE, texnum, red, green, blue, alpha); + glBlitTexture(screenx - cx * rme::TileSize, screeny - cy * rme::TileSize, texnum, red, green, blue, alpha); } } } @@ -1351,7 +1351,7 @@ void MapDrawer::BlitSpriteType(int screenx, int screeny, GameSprite* sprite, int for(int cy = 0; cy != sprite->height; ++cy) { for(int cf = 0; cf != sprite->layers; ++cf) { int texnum = sprite->getHardwareID(cx,cy,cf,-1,0,0,0, frame); - glBlitTexture(screenx - cx * TILE_SIZE, screeny - cy * TILE_SIZE, texnum, red, green, blue, alpha); + glBlitTexture(screenx - cx * rme::TileSize, screeny - cy * rme::TileSize, texnum, red, green, blue, alpha); } } } @@ -1375,7 +1375,7 @@ void MapDrawer::BlitCreature(int screenx, int screeny, const Outfit& outfit, Dir for (int cx = 0; cx != mountSpr->width; ++cx) { for (int cy = 0; cy != mountSpr->height; ++cy) { int texnum = mountSpr->getHardwareID(cx, cy, 0, 0, (int)dir, 0, 0, 0); - glBlitTexture(screenx - cx * TILE_SIZE, screeny - cy * TILE_SIZE, texnum, red, green, blue, alpha); + glBlitTexture(screenx - cx * rme::TileSize, screeny - cy * rme::TileSize, texnum, red, green, blue, alpha); } } pattern_z = std::min(1, sprite->pattern_z - 1); @@ -1394,7 +1394,7 @@ void MapDrawer::BlitCreature(int screenx, int screeny, const Outfit& outfit, Dir for(int cx = 0; cx != sprite->width; ++cx) { for(int cy = 0; cy != sprite->height; ++cy) { int texnum = sprite->getHardwareID(cx, cy, (int)dir, pattern_y, pattern_z, outfit, frame); - glBlitTexture(screenx - cx * TILE_SIZE, screeny - cy * TILE_SIZE, texnum, red, green, blue, alpha); + glBlitTexture(screenx - cx * rme::TileSize, screeny - cy * rme::TileSize, texnum, red, green, blue, alpha); } } } @@ -1600,8 +1600,8 @@ void MapDrawer::DrawTile(TileLocation* location) void MapDrawer::DrawBrushIndicator(int x, int y, Brush* brush, uint8_t r, uint8_t g, uint8_t b) { - x += (TILE_SIZE / 2); - y += (TILE_SIZE / 2); + x += (rme::TileSize / 2); + y += (rme::TileSize / 2); // 7----0----1 // | | @@ -1625,8 +1625,8 @@ void MapDrawer::DrawBrushIndicator(int x, int y, Brush* brush, uint8_t r, uint8_ glColor4ub(0x00, 0x00, 0x00, 0x50); glVertex2i(x, y); for(int i = 0; i <= 30; i++) { - float angle = i * 2.0f * PI / 30; - glVertex2f(cos(angle) * (TILE_SIZE / 2) + x, sin(angle) * (TILE_SIZE / 2) + y); + float angle = i * 2.0f * rme::PI / 30; + glVertex2f(cos(angle) * (rme::TileSize / 2) + x, sin(angle) * (rme::TileSize / 2) + y); } glEnd(); @@ -1756,8 +1756,8 @@ void MapDrawer::DrawPositionIndicator(int z) int x, y; getDrawPosition(pos_indicator, x, y); - int size = static_cast(TILE_SIZE * (0.3f + std::abs(500 - time % 1000) / 1000.f)); - int offset = (TILE_SIZE - size) / 2; + int size = static_cast(rme::TileSize * (0.3f + std::abs(500 - time % 1000) / 1000.f)); + int offset = (rme::TileSize - size) / 2; glDisable(GL_TEXTURE_2D); drawRect(x + offset + 2, y + offset + 2, size - 4, size - 4, *wxWHITE, 2); @@ -1801,8 +1801,8 @@ void MapDrawer::DrawTooltips() width = (width + 8.0f) * scale; height = (height + 4.0f) * scale; - float x = tooltip->x + (TILE_SIZE / 2.0f); - float y = tooltip->y + ((TILE_SIZE / 2.0f) * scale); + float x = tooltip->x + (rme::TileSize / 2.0f); + float y = tooltip->y + ((rme::TileSize / 2.0f) * scale); float center = width / 2.0f; float space = (7.0f * scale); float startx = x - center; @@ -1924,15 +1924,15 @@ void MapDrawer::glBlitTexture(int x, int y, int textureId, int red, int green, i glBegin(GL_QUADS); if(adjustZoom) { - float size = TILE_SIZE; - if (zoom < 1.0f) { + float size = rme::TileSize; + if(zoom < 1.0f) { float offset = 10 / (10 * zoom); - size = std::max(16, TILE_SIZE * zoom); + size = std::max(16, rme::TileSize * zoom); x += offset; y += offset; } else if (zoom > 1.f) { float offset = (10 * zoom); - size = TILE_SIZE + offset; + size = rme::TileSize + offset; x -= offset; y -= offset; } @@ -1942,9 +1942,9 @@ void MapDrawer::glBlitTexture(int x, int y, int textureId, int red, int green, i glTexCoord2f(0.f, 1.f); glVertex2f(x, y + size); } else { glTexCoord2f(0.f, 0.f); glVertex2f(x, y); - glTexCoord2f(1.f, 0.f); glVertex2f(x + TILE_SIZE, y); - glTexCoord2f(1.f, 1.f); glVertex2f(x + TILE_SIZE, y + TILE_SIZE); - glTexCoord2f(0.f, 1.f); glVertex2f(x, y + TILE_SIZE); + glTexCoord2f(1.f, 0.f); glVertex2f(x + rme::TileSize, y); + glTexCoord2f(1.f, 1.f); glVertex2f(x + rme::TileSize, y + rme::TileSize); + glTexCoord2f(0.f, 1.f); glVertex2f(x, y + rme::TileSize); } glEnd(); @@ -1955,9 +1955,9 @@ void MapDrawer::glBlitSquare(int x, int y, int red, int green, int blue, int alp glColor4ub(uint8_t(red), uint8_t(green), uint8_t(blue), uint8_t(alpha)); glBegin(GL_QUADS); glVertex2f(x, y); - glVertex2f(x + TILE_SIZE, y); - glVertex2f(x + TILE_SIZE, y + TILE_SIZE); - glVertex2f(x, y + TILE_SIZE); + glVertex2f(x + rme::TileSize, y); + glVertex2f(x + rme::TileSize, y + rme::TileSize); + glVertex2f(x, y + rme::TileSize); glEnd(); } @@ -1966,9 +1966,9 @@ void MapDrawer::glBlitSquare(int x, int y, const wxColor& color) glColor4ub(color.Red(), color.Green(), color.Blue(), color.Alpha()); glBegin(GL_QUADS); glVertex2f(x, y); - glVertex2f(x + TILE_SIZE, y); - glVertex2f(x + TILE_SIZE, y + TILE_SIZE); - glVertex2f(x, y + TILE_SIZE); + glVertex2f(x + rme::TileSize, y); + glVertex2f(x + rme::TileSize, y + rme::TileSize); + glVertex2f(x, y + rme::TileSize); glEnd(); } @@ -2049,11 +2049,11 @@ void MapDrawer::drawRect(int x, int y, int w, int h, const wxColor& color, int w void MapDrawer::getDrawPosition(const Position& position, int& x, int& y) { int offset; - if (position.z <= GROUND_LAYER) - offset = (GROUND_LAYER - position.z) * TILE_SIZE; + if(position.z <= rme::MapGroundLayer) + offset = (rme::MapGroundLayer - position.z) * rme::TileSize; else - offset = TILE_SIZE * (floor - position.z); + offset = rme::TileSize * (floor - position.z); - x = ((position.x * TILE_SIZE) - view_scroll_x) - offset; - y = ((position.y * TILE_SIZE) - view_scroll_y) - offset; + x = ((position.x * rme::TileSize) - view_scroll_x) - offset; + y = ((position.y * rme::TileSize) - view_scroll_y) - offset; } diff --git a/source/map_region.cpp b/source/map_region.cpp index 6034687f..fc350e21 100644 --- a/source/map_region.cpp +++ b/source/map_region.cpp @@ -67,7 +67,7 @@ Floor::Floor(int sx, int sy, int z) sx = sx & ~3; sy = sy & ~3; - for(int i = 0; i < MAP_LAYERS; ++i) { + for(int i = 0; i < rme::MapLayers; ++i) { locs[i].position.x = sx + (i >> 2); locs[i].position.y = sy + (i & 3); locs[i].position.z = z; @@ -82,17 +82,17 @@ QTreeNode::QTreeNode(BaseMap& map) : isLeaf(false) { // Doesn't matter if we're leaf or node - for(int i = 0; i < MAP_LAYERS; ++i) + for(int i = 0; i < rme::MapLayers; ++i) child[i] = nullptr; } QTreeNode::~QTreeNode() { if(isLeaf) { - for(int i = 0; i < MAP_LAYERS; ++i) + for(int i = 0; i < rme::MapLayers; ++i) delete array[i]; } else { - for(int i = 0; i < MAP_LAYERS; ++i) + for(int i = 0; i < rme::MapLayers; ++i) delete child[i]; } } @@ -177,7 +177,7 @@ void QTreeNode::clearVisible(uint32_t u) if(isLeaf) visible &= u; else - for(int i = 0; i < MAP_LAYERS; ++i) + for(int i = 0; i < rme::MapLayers; ++i) if(child[i]) child[i]->clearVisible(u); } @@ -185,7 +185,7 @@ void QTreeNode::clearVisible(uint32_t u) bool QTreeNode::isVisible(uint32_t client, bool underground) { if(underground) { - return testFlags(visible >> MAP_LAYERS, static_cast(1) << client); + return testFlags(visible >> rme::MapLayers, static_cast(1) << client); } else { return testFlags(visible, static_cast(1) << client); } @@ -217,9 +217,9 @@ void QTreeNode::setRequested(bool underground, bool r) void QTreeNode::setVisible(uint32_t client, bool underground, bool value) { if(value) - visible |= (1 << client << (underground ? MAP_LAYERS : 0)); + visible |= (1 << client << (underground ? rme::MapLayers : 0)); else - visible &= ~(1 << client << (underground ? MAP_LAYERS : 0)); + visible &= ~(1 << client << (underground ? rme::MapLayers : 0)); } TileLocation* QTreeNode::getTile(int x, int y, int z) diff --git a/source/map_region.h b/source/map_region.h index 0b7044b5..e13f589f 100644 --- a/source/map_region.h +++ b/source/map_region.h @@ -18,6 +18,7 @@ #ifndef RME_MAP_REGION_H #define RME_MAP_REGION_H +#include "const.h" #include "position.h" class Tile; @@ -79,7 +80,7 @@ class Floor { public: Floor(int x, int y, int z); - TileLocation locs[MAP_LAYERS]; + TileLocation locs[rme::MapLayers]; }; // This is not a QuadTree, but a HexTree (16 child nodes to every node), so the name is abit misleading @@ -124,12 +125,13 @@ class QTreeNode uint32_t visible; bool isLeaf; + union { - QTreeNode* child[MAP_LAYERS]; - Floor* array[MAP_LAYERS]; -#if 16 != MAP_LAYERS -# error "You need to rewrite the QuadTree in order to handle more or less than 16 floors" -#endif + QTreeNode* child[rme::MapLayers]; + Floor* array[rme::MapLayers]; +//#if 16 != rme::MapLayers +//# error "You need to rewrite the QuadTree in order to handle more or less than 16 floors" +//#endif }; friend class BaseMap; diff --git a/source/map_window.cpp b/source/map_window.cpp index 175d2a88..20fe95cd 100644 --- a/source/map_window.cpp +++ b/source/map_window.cpp @@ -125,7 +125,7 @@ void MapWindow::GetViewSize(int* x, int* y) void MapWindow::FitToMap() { const Map& map = editor.getMap(); - SetSize(map.getWidth() * TILE_SIZE, map.getHeight() * TILE_SIZE, true); + SetSize(map.getWidth() * rme::TileSize, map.getHeight() * rme::TileSize, true); } Position MapWindow::GetScreenCenterPosition() @@ -140,12 +140,12 @@ void MapWindow::SetScreenCenterPosition(const Position& position, bool showIndic if(!position.isValid()) return; - int x = position.x * TILE_SIZE; - int y = position.y * TILE_SIZE; + int x = position.x * rme::TileSize; + int y = position.y * rme::TileSize; if(position.z < 8) { // Compensate for floor offset above ground - x -= (GROUND_LAYER - position.z) * TILE_SIZE; - y -= (GROUND_LAYER - position.z) * TILE_SIZE; + x -= (rme::MapGroundLayer - position.z) * rme::TileSize; + y -= (rme::MapGroundLayer - position.z) * rme::TileSize; } const Position& center = GetScreenCenterPosition(); diff --git a/source/minimap_window.cpp b/source/minimap_window.cpp index aacb1265..8d6987ca 100644 --- a/source/minimap_window.cpp +++ b/source/minimap_window.cpp @@ -158,12 +158,12 @@ void MinimapWindow::OnPaint(wxPaintEvent& event) int view_start_x, view_start_y; int view_end_x, view_end_y; - int tile_size = int(TILE_SIZE / canvas->GetZoom()); // after zoom + int tile_size = int(rme::TileSize / canvas->GetZoom()); // after zoom - int floor_offset = (floor > GROUND_LAYER ? 0 : (GROUND_LAYER - floor)); + int floor_offset = (floor > rme::MapGroundLayer ? 0 : (rme::MapGroundLayer - floor)); - view_start_x = view_scroll_x / TILE_SIZE + floor_offset; - view_start_y = view_scroll_y / TILE_SIZE + floor_offset; + view_start_x = view_scroll_x / rme::TileSize + floor_offset; + view_start_y = view_scroll_y / rme::TileSize + floor_offset; view_end_x = view_start_x + screensize_x / tile_size + 1; view_end_y = view_start_y + screensize_y / tile_size + 1; diff --git a/source/old_properties_window.cpp b/source/old_properties_window.cpp index 02c009d9..46205d73 100644 --- a/source/old_properties_window.cpp +++ b/source/old_properties_window.cpp @@ -575,9 +575,9 @@ void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) aid_changed = new_aid != edit_item->getActionID(); if(uid_changed) { - if(new_uid != 0 && (new_uid < MIN_UNIQUE_ID || new_uid > MAX_UNIQUE_ID)) { + if(new_uid != 0 && (new_uid < rme::MinUniqueId || new_uid > rme::MaxUniqueId)) { wxString message = "Unique ID must be between %d and %d."; - g_gui.PopupDialog(this, "Error", wxString::Format(message, MIN_UNIQUE_ID, MAX_UNIQUE_ID), wxOK); + g_gui.PopupDialog(this, "Error", wxString::Format(message, rme::MinUniqueId, rme::MaxUniqueId), wxOK); return; } if(g_gui.GetCurrentMap().hasUniqueId(new_uid)) { @@ -587,9 +587,9 @@ void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) } if(aid_changed) { - if(new_aid != 0 && (new_aid < MIN_ACTION_ID || new_aid > MAX_ACTION_ID)) { + if(new_aid != 0 && (new_aid < rme::MinActionId || new_aid > rme::MaxActionId)) { wxString message = "Action ID must be between %d and %d."; - g_gui.PopupDialog(this, "Error", wxString::Format(message, MIN_ACTION_ID, MAX_ACTION_ID), wxOK); + g_gui.PopupDialog(this, "Error", wxString::Format(message, rme::MinActionId, rme::MaxActionId), wxOK); return; } } diff --git a/source/position.h b/source/position.h index 62dccebf..2e5eacb2 100644 --- a/source/position.h +++ b/source/position.h @@ -81,7 +81,9 @@ class Position { bool isValid() const noexcept { if(x == 0 && y == 0 && z == 0) return false; - return z >= 0 && z <= MAP_MAX_LAYER && x >= 0 && x <= MAP_MAX_WIDTH && y >= 0 && y <= MAP_MAX_HEIGHT; + return (z >= rme::MapMinLayer && z <= rme::MapMaxLayer) + && (x >= 0 && x <= rme::MapMaxWidth) + && (y >= 0 && y <= rme::MapMaxHeight); } }; diff --git a/source/positionctrl.cpp b/source/positionctrl.cpp index 1f226c8a..d964d33b 100644 --- a/source/positionctrl.cpp +++ b/source/positionctrl.cpp @@ -21,7 +21,7 @@ #include "position.h" PositionCtrl::PositionCtrl(wxWindow* parent, const wxString& label, int x, int y, int z, - int maxx /*= MAP_MAX_WIDTH*/, int maxy /*= MAP_MAX_HEIGHT*/, int maxz /*= MAP_MAX_LAYER*/) : + int maxx /*= rme::MapMaxWidth*/, int maxy /*= rme::MapMaxHeight*/, int maxz /*= rme::MapMaxLayer*/) : wxStaticBoxSizer(wxHORIZONTAL, parent, label) { x_field = newd NumberTextCtrl(parent, wxID_ANY, x, 0, maxx, wxTE_PROCESS_ENTER, "X", wxDefaultPosition, wxSize(60, 20)); diff --git a/source/positionctrl.h b/source/positionctrl.h index bfb98226..9b634409 100644 --- a/source/positionctrl.h +++ b/source/positionctrl.h @@ -24,7 +24,7 @@ class PositionCtrl : public wxStaticBoxSizer { public: PositionCtrl(wxWindow* parent, const wxString& label, int x, int y, int z, - int maxx = MAP_MAX_WIDTH, int maxy = MAP_MAX_HEIGHT, int maxz = MAP_MAX_LAYER); + int maxx = rme::MapMaxWidth, int maxy = rme::MapMaxHeight, int maxz = rme::MapMaxLayer); ~PositionCtrl(); long GetX() const { return x_field->GetIntValue(); } diff --git a/source/selection.cpp b/source/selection.cpp index 61b3b6d6..6661d1d9 100644 --- a/source/selection.cpp +++ b/source/selection.cpp @@ -387,7 +387,7 @@ wxThread::ExitCode SelectionThread::Entry() selection.add(tile); } } - if(compesated && z <= GROUND_LAYER) { + if(compesated && z <= rme::MapGroundLayer) { ++start.x; ++start.y; ++end.x; ++end.y; } diff --git a/vcproj/Project/RME.vcxproj b/vcproj/Project/RME.vcxproj index 0f92821f..008f644e 100644 --- a/vcproj/Project/RME.vcxproj +++ b/vcproj/Project/RME.vcxproj @@ -223,6 +223,7 @@ + diff --git a/vcproj/rme - Copia.cfg b/vcproj/rme - Copia.cfg deleted file mode 100644 index cec80257..00000000 --- a/vcproj/rme - Copia.cfg +++ /dev/null @@ -1,142 +0,0 @@ -file1= -file2= -file3= -file4= -file5= -file6= -file7= -file8= -file9= -GOTO_WEBSITE_ON_BOOT=0 -USE_UPDATER=1 -RECENT_EDITED_MAP_PATH= -RECENT_EDITED_MAP_POSITION= -FIND_ITEM_MODE=0 -JUMP_TO_ITEM_MODE=0 -[View] -TRANSPARENT_FLOORS=0 -TRANSPARENT_ITEMS=0 -SHOW_ALL_FLOORS=1 -SHOW_INGAME_BOX=0 -SHOW_GRID=0 -SHOW_EXTRA=1 -SHOW_SHADE=1 -SHOW_SPECIAL_TILES=1 -SHOW_SPAWNS=1 -SHOW_ITEMS=1 -HIGHLIGHT_ITEMS=0 -SHOW_CREATURES=1 -SHOW_HOUSES=1 -SHOW_BLOCKING=0 -SHOW_TOOLTIPS=1 -SHOW_ONLY_TILEFLAGS=0 -SHOW_ONLY_MODIFIED_TILES=0 -SHOW_PREVIEW=1 -SHOW_WALL_HOOKS=0 -SHOW_PICKUPABLES=0 -SHOW_MOVEABLES=0 -[Version] -VERSION_ID=30800000 -CHECK_SIGNATURES=1 -USE_CUSTOM_DATA_DIRECTORY=0 -DATA_DIRECTORY= -EXTENSIONS_DIRECTORY= -ASSETS_DATA_DIRS=[{"id":"7.4","path":""},{"id":"7.6","path":""},{"id":"8.00","path":""},{"id":"8.10","path":""},{"id":"8.20 - 8.31","path":""},{"id":"8.40","path":""},{"id":"8.50","path":""},{"id":"8.54 (bad)","path":""},{"id":"8.54","path":""},{"id":"8.60 (old)","path":""},{"id":"8.60","path":""},{"id":"8.70","path":""},{"id":"9.10","path":""},{"id":"9.20 - 9.31","path":""},{"id":"9.46","path":""},{"id":"9.54","path":""},{"id":"9.60","path":""},{"id":"9.70","path":""},{"id":"9.86","path":""},{"id":"10.10","path":""},{"id":"10.20","path":""},{"id":"10.21","path":""},{"id":"10.30","path":""},{"id":"10.31","path":""},{"id":"10.41","path":""},{"id":"10.77","path":""},{"id":"10.98","path":""},{"id":"10.100","path":""}] -[Editor] -RECENT_FILES= -WORKER_THREADS=1 -MERGE_MOVE=0 -MERGE_PASTE=0 -UNDO_SIZE=400 -UNDO_MEM_SIZE=40 -GROUP_ACTIONS=1 -SELECTION_TYPE=0 -COMPENSATED_SELECT=1 -SCROLL_SPEED=3.5 -ZOOM_SPEED=1.4 -SWITCH_MOUSEBUTTONS=0 -DOUBLECLICK_PROPERTIES=1 -LISTBOX_EATS_ALL_EVENTS=1 -BORDER_IS_GROUND=1 -BORDERIZE_PASTE=1 -BORDERIZE_DRAG=1 -BORDERIZE_DRAG_THRESHOLD=6000 -BORDERIZE_PASTE_THRESHOLD=10000 -ALWAYS_MAKE_BACKUP=0 -USE_AUTOMAGIC=1 -HOUSE_BRUSH_REMOVE_ITEMS=0 -AUTO_ASSIGN_DOORID=1 -ERASER_LEAVE_UNIQUE=1 -DOODAD_BRUSH_ERASE_LIKE=0 -WARN_FOR_DUPLICATE_ID=1 -AUTO_CREATE_SPAWN=1 -DEFAULT_SPAWNTIME=60 -MAX_SPAWN_RADIUS=30 -CURRENT_SPAWN_RADIUS=5 -DEFAULT_CLIENT_VERSION=-1 -RAW_LIKE_SIMONE=1 -ONLY_ONE_INSTANCE=1 -USE_OTBM_4_FOR_ALL_MAPS=0 -USE_OTGZ=1 -SAVE_WITH_OTB_MAGIC_NUMBER=0 -REPLACE_SIZE=500 -COPY_POSITION_FORMAT=0 -[Graphics] -TEXTURE_MANAGEMENT=1 -TEXTURE_CLEAN_PULSE=15 -TEXTURE_LONGEVITY=20 -TEXTURE_CLEAN_THRESHOLD=2500 -SOFTWARE_CLEAN_THRESHOLD=1800 -SOFTWARE_CLEAN_SIZE=500 -ICON_BACKGROUND=0 -HARD_REFRESH_RATE=200 -HIDE_ITEMS_WHEN_ZOOMED=1 -SCREENSHOT_DIRECTORY=C:\\Users\\nails\\Documents/My Pictures/RME/ -SCREENSHOT_FORMAT=png -USE_MEMCACHED_SPRITES=0 -MINIMAP_UPDATE_DELAY=333 -MINIMAP_VIEW_BOX=1 -MINIMAP_EXPORT_DIR= -CURSOR_RED=0 -CURSOR_GREEN=166 -CURSOR_BLUE=0 -CURSOR_ALPHA=128 -CURSOR_ALT_RED=0 -CURSOR_ALT_GREEN=166 -CURSOR_ALT_BLUE=0 -CURSOR_ALT_ALPHA=128 -[UI] -USE_LARGE_CONTAINER_ICONS=1 -USE_LARGE_CHOOSE_ITEM_ICONS=1 -USE_LARGE_TERRAIN_TOOLBAR=1 -USE_LARGE_DOODAD_SIZEBAR=1 -USE_LARGE_ITEM_SIZEBAR=1 -USE_LARGE_HOUSE_SIZEBAR=1 -USE_LARGE_RAW_SIZEBAR=1 -USE_GUI_SELECTION_SHADOW=0 -PALETTE_COL_COUNT=8 -PALETTE_TERRAIN_STYLE=large icons -PALETTE_DOODAD_STYLE=large icons -PALETTE_ITEM_STYLE=listbox -PALETTE_RAW_STYLE=listbox -[Window] -PALETTE_LAYOUT= -MINIMAP_VISIBLE=0 -MINIMAP_LAYOUT=name=066e2bc8486298990000259a00000003;caption=Minimap;state=2099151;dir=4;layer=0;row=0;pos=0;prop=100000;bestw=170;besth=130;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=221;floath=164 -ACTIONS_HISTORY_VISIBLE=0 -ACTIONS_HISTORY_LAYOUT=name=945c6eb52a414f1B817e8befd4479412;caption=Actions;state=2099151;dir=2;layer=0;row=0;pos=0;prop=100000;bestw=170;besth=130;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=221;floath=164 -WINDOW_HEIGHT=500 -WINDOW_WIDTH=700 -WINDOW_MAXIMIZED=0 -WELCOME_DIALOG=1 -[Hotkeys] -NUMERICAL_HOTKEYS=none:{}\nnone:{}\nnone:{}\nnone:{}\nnone:{}\nnone:{}\nnone:{}\nnone:{}\nnone:{}\nnone:{}\n -SHOW_TOOLBAR_STANDARD=1 -SHOW_TOOLBAR_BRUSHES=0 -SHOW_TOOLBAR_POSITION=0 -SHOW_TOOLBAR_SIZES=0 -SHOW_TOOLBAR_INDICATORS=0 -TOOLBAR_STANDARD_LAYOUT=name=standard_toolbar;caption=;state=2106044;dir=1;layer=10;row=1;pos=1;prop=100000;bestw=272;besth=29;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1 -TOOLBAR_BRUSHES_LAYOUT= -TOOLBAR_POSITION_LAYOUT= -TOOLBAR_SIZES_LAYOUT= From f813867952f5b4340d350fcc3c0c14bee4cd7443 Mon Sep 17 00:00:00 2001 From: Beats Date: Wed, 5 Apr 2023 23:56:20 -0400 Subject: [PATCH 25/45] Replace items fix (#408) --- source/replace_items_window.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/replace_items_window.cpp b/source/replace_items_window.cpp index 71962f14..f1dfc9e0 100644 --- a/source/replace_items_window.cpp +++ b/source/replace_items_window.cpp @@ -374,6 +374,8 @@ void ReplaceItemsDialog::OnExecuteButtonClicked(wxCommandEvent& WXUNUSED(event)) tab->Refresh(); close_button->Enable(true); + replace_button->Enable(true); + with_button->Enable(true); UpdateWidgets(); } From 57cae034e2b3b54e0b0c3d9cf2b32bd686358b17 Mon Sep 17 00:00:00 2001 From: Nailson Date: Sat, 4 Feb 2023 15:44:12 -0300 Subject: [PATCH 26/45] Draw grid small optimization --- source/map_drawer.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index b9059e92..79ae3b10 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -220,7 +220,7 @@ void MapDrawer::Draw() DrawSelectionBox(); DrawLiveCursors(); DrawBrush(); - if(options.show_grid) + if(options.show_grid && zoom <= 10.f) DrawGrid(); if(options.show_ingame_box) DrawIngameBox(); @@ -558,21 +558,24 @@ void MapDrawer::DrawIngameBox() void MapDrawer::DrawGrid() { + glDisable(GL_TEXTURE_2D); + glColor4ub(255, 255, 255, 128); + glBegin(GL_LINES); + for(int y = start_y; y < end_y; ++y) { - glColor4ub(255, 255, 255, 128); - glBegin(GL_LINES); - glVertex2f(start_x * rme::TileSize - view_scroll_x, y * rme::TileSize - view_scroll_y); - glVertex2f(end_x * rme::TileSize - view_scroll_x, y * rme::TileSize - view_scroll_y); - glEnd(); + int py = y * rme::TileSize - view_scroll_y; + glVertex2f(start_x * rme::TileSize - view_scroll_x, py); + glVertex2f(end_x * rme::TileSize - view_scroll_x, py); } for(int x = start_x; x < end_x; ++x) { - glColor4ub(255, 255, 255, 128); - glBegin(GL_LINES); - glVertex2f(x * rme::TileSize - view_scroll_x, start_y * rme::TileSize - view_scroll_y); - glVertex2f(x * rme::TileSize - view_scroll_x, end_y * rme::TileSize - view_scroll_y); - glEnd(); + int px = x * rme::TileSize - view_scroll_x; + glVertex2f(px, start_y * rme::TileSize - view_scroll_y); + glVertex2f(px, end_y * rme::TileSize - view_scroll_y); } + + glEnd(); + glEnable(GL_TEXTURE_2D); } void MapDrawer::DrawDraggingShadow() From ac505ff64c6e9535a16fda2b5b08fa69de020e39 Mon Sep 17 00:00:00 2001 From: Nailson Date: Sat, 4 Feb 2023 17:24:23 -0300 Subject: [PATCH 27/45] Small change in selection box and Fix #409 --- source/map_drawer.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index 79ae3b10..eb88bcb1 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -674,8 +674,9 @@ void MapDrawer::DrawHigherFloors() void MapDrawer::DrawSelectionBox() { - if(options.ingame) + if (options.ingame) { return; + } // Draw bounding box @@ -684,7 +685,7 @@ void MapDrawer::DrawSelectionBox() double cursor_rx = canvas->cursor_x * zoom; double cursor_ry = canvas->cursor_y * zoom; - double lines[4][4]; + static double lines[4][4]; lines[0][0] = last_click_rx; lines[0][1] = last_click_ry; @@ -706,8 +707,9 @@ void MapDrawer::DrawSelectionBox() lines[3][2] = last_click_rx; lines[3][3] = last_click_ry; + glDisable(GL_TEXTURE_2D); glEnable(GL_LINE_STIPPLE); - glLineStipple(1, 0xf0); + glLineStipple(2, 0xAAAA); glLineWidth(1.0); glColor4f(1.0,1.0,1.0,1.0); glBegin(GL_LINES); @@ -717,6 +719,7 @@ void MapDrawer::DrawSelectionBox() } glEnd(); glDisable(GL_LINE_STIPPLE); + glEnable(GL_TEXTURE_2D); } void MapDrawer::DrawLiveCursors() @@ -764,12 +767,9 @@ void MapDrawer::DrawLiveCursors() void MapDrawer::DrawBrush() { - if(!g_gui.IsDrawingMode()) - return; - if(!g_gui.GetCurrentBrush()) - return; - if(options.ingame) + if(options.ingame || !g_gui.IsDrawingMode() || !g_gui.GetCurrentBrush()) { return; + } Brush* brush = g_gui.GetCurrentBrush(); @@ -1036,6 +1036,8 @@ void MapDrawer::DrawBrush() if(brush->isRaw()) { // Textured brush glEnable(GL_TEXTURE_2D); raw_brush = brush->asRaw(); + } else { + glDisable(GL_TEXTURE_2D); } for(int y = -g_gui.GetBrushSize()-1; y <= g_gui.GetBrushSize()+1; y++) { @@ -1097,6 +1099,8 @@ void MapDrawer::DrawBrush() if(brush->isRaw()) { // Textured brush glDisable(GL_TEXTURE_2D); + } else { + glEnable(GL_TEXTURE_2D); } } } From a27f423f85d588d322d79407823464adb49cb255 Mon Sep 17 00:00:00 2001 From: Nailson Date: Sat, 11 Feb 2023 16:43:10 -0300 Subject: [PATCH 28/45] Fix some xpm --- icons/mini_fill.xpm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icons/mini_fill.xpm b/icons/mini_fill.xpm index c70596c3..31414792 100644 --- a/icons/mini_fill.xpm +++ b/icons/mini_fill.xpm @@ -1,5 +1,5 @@ /* XPM */ -static char * mini_fill_xpm[] = { +static const char *mini_fill_xpm[] = { "16 16 103 2", " c None", ". c #4884C2", From 64f5a322c73a00729890b99a3cc700e95918e469 Mon Sep 17 00:00:00 2001 From: Nailson Date: Sat, 11 Feb 2023 16:47:45 -0300 Subject: [PATCH 29/45] Ingame box improvements, add lights support. --- data/menubar.xml | 5 +- source/CMakeLists.txt | 1 + source/const.h | 5 ++ source/graphics.cpp | 11 ++- source/graphics.h | 14 +++- source/item.cpp | 18 +++++ source/item.h | 5 ++ source/light_drawer.cpp | 134 ++++++++++++++++++++++++++++++++ source/light_drawer.h | 67 ++++++++++++++++ source/main_menubar.cpp | 3 + source/main_menubar.h | 1 + source/map_display.cpp | 1 + source/map_drawer.cpp | 151 +++++++++++++++++++++++-------------- source/map_drawer.h | 6 ++ source/settings.cpp | 1 + source/settings.h | 1 + vcproj/Project/RME.vcxproj | 2 + 17 files changed, 364 insertions(+), 62 deletions(-) create mode 100644 source/light_drawer.cpp create mode 100644 source/light_drawer.h diff --git a/data/menubar.xml b/data/menubar.xml index 4a2c3514..3962837b 100644 --- a/data/menubar.xml +++ b/data/menubar.xml @@ -120,7 +120,10 @@ - + + + + diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index cd0f74bd..db858c7d 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -68,6 +68,7 @@ target_sources(${PROJECT_NAME} house_brush.cpp house.cpp house_exit_brush.cpp + light_drawer.cpp iomap.cpp iomap_otbm.cpp item_attributes.cpp diff --git a/source/const.h b/source/const.h index 3e12a90d..b1a7ea00 100644 --- a/source/const.h +++ b/source/const.h @@ -45,6 +45,11 @@ constexpr int TileSize = 32; constexpr int SpritePixels = 32; constexpr int SpritePixelsSize = SpritePixels * SpritePixels; +constexpr int MaxLightIntensity = 8; + +constexpr int PixelFormatRGB = 3; +constexpr int PixelFormatRGBA = 4; + constexpr int MinUniqueId = 1000; constexpr int MaxUniqueId = 65535; constexpr int MinActionId = 100; diff --git a/source/graphics.cpp b/source/graphics.cpp index 851ac8fa..a78b2b42 100644 --- a/source/graphics.cpp +++ b/source/graphics.cpp @@ -585,9 +585,16 @@ bool GraphicManager::loadSpriteMetadataFlags(FileReadHandle& file, GameSprite* s file.skip(2); break; - case DatFlagLight: - file.skip(4); + case DatFlagLight: { + SpriteLight light; + uint16_t intensity; + uint16_t color; + file.getU16(intensity); + file.getU16(color); + sType->has_light = true; + sType->light = SpriteLight{ static_cast(intensity), static_cast(color) }; break; + } case DatFlagDisplacement: { if(dat_format >= DAT_FORMAT_11) { diff --git a/source/graphics.h b/source/graphics.h index f6de85f9..662a4af5 100644 --- a/source/graphics.h +++ b/source/graphics.h @@ -46,7 +46,13 @@ class GraphicManager; class FileReadHandle; class Animator; -class Sprite { +struct SpriteLight { + uint8_t intensity = 0; + uint8_t color = 0; +}; + +class Sprite +{ public: Sprite() {} @@ -88,6 +94,9 @@ class GameSprite : public Sprite{ const wxPoint& getDrawOffset() const noexcept { return draw_offset; } uint8_t getMiniMapColor() const noexcept { return minimap_color; } + bool hasLight() const noexcept { return has_light; } + const SpriteLight& getLight() const noexcept { return light; } + static GameSprite* createFromBitmap(const wxArtID& bitmapId); protected: @@ -193,6 +202,9 @@ class GameSprite : public Sprite{ uint16_t minimap_color; + bool has_light = false; + SpriteLight light; + std::vector spriteList; std::list instanced_templates; // Templates that use this sprite diff --git a/source/item.cpp b/source/item.cpp index 5afdcc58..7d89ee14 100644 --- a/source/item.cpp +++ b/source/item.cpp @@ -232,6 +232,24 @@ wxPoint Item::getDrawOffset() const return wxPoint(0, 0); } +bool Item::hasLight() const +{ + const ItemType& type = g_items.getItemType(id); + if(type.sprite) { + return type.sprite->hasLight(); + } + return false; +} + +SpriteLight Item::getLight() const +{ + const ItemType& type = g_items.getItemType(id); + if(type.sprite) { + return type.sprite->getLight(); + } + return SpriteLight{0, 0}; +} + double Item::getWeight() const { const ItemType& type = g_items.getItemType(id); diff --git a/source/item.h b/source/item.h index adc90d54..48e2349b 100644 --- a/source/item.h +++ b/source/item.h @@ -76,6 +76,8 @@ class Door; class Monster; class Npc; +struct SpriteLight; + class Item : public ItemAttributes { public: @@ -176,6 +178,9 @@ class Item : public ItemAttributes uint8_t getMiniMapColor() const; wxPoint getDrawOffset() const; + bool hasLight() const; + SpriteLight getLight() const; + // Item types bool hasProperty(enum ITEMPROPERTY prop) const; bool isBlocking() const { return getItemType().unpassable; } diff --git a/source/light_drawer.cpp b/source/light_drawer.cpp new file mode 100644 index 00000000..d8f18824 --- /dev/null +++ b/source/light_drawer.cpp @@ -0,0 +1,134 @@ +////////////////////////////////////////////////////////////////////// +// This file is part of Remere's Map Editor +////////////////////////////////////////////////////////////////////// +// Remere's Map Editor is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Remere's Map Editor is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +////////////////////////////////////////////////////////////////////// + +#include "main.h" +#include "light_drawer.h" + +LightDrawer::LightDrawer() +{ + texture = 0; + buffer.resize(static_cast(rme::ClientMapWidth * rme::ClientMapHeight * rme::PixelFormatRGBA)); + global_color = wxColor(50, 50, 50, 255); + + createGLTexture(); +} + +LightDrawer::~LightDrawer() +{ + unloadGLTexture(); + + lights.clear(); +} + +void LightDrawer::draw(int map_x, int map_y, int scroll_x, int scroll_y) +{ + constexpr int half_tile_size = rme::TileSize / 2; + + for (int x = 0; x < rme::ClientMapWidth; ++x) { + for (int y = 0; y < rme::ClientMapHeight; ++y) { + int mx = (map_x + x); + int my = (map_y + y); + int px = (mx * rme::TileSize + half_tile_size); + int py = (my * rme::TileSize + half_tile_size); + int index = (y * rme::ClientMapWidth + x); + int color_index = index * rme::PixelFormatRGBA; + + buffer[color_index] = global_color.Red(); + buffer[color_index + 1] = global_color.Green(); + buffer[color_index + 2] = global_color.Blue(); + buffer[color_index + 3] = global_color.Alpha(); + + for (auto& light : lights) { + float intensity = calculateIntensity(mx, my, light); + if (intensity == 0.f) { + continue; + } + wxColor light_color = colorFromEightBit(light.color); + uint8_t red = static_cast(light_color.Red() * intensity); + uint8_t green = static_cast(light_color.Green() * intensity); + uint8_t blue = static_cast(light_color.Blue() * intensity); + buffer[color_index] = std::max(buffer[color_index], red); + buffer[color_index + 1] = std::max(buffer[color_index + 1], green); + buffer[color_index + 2] = std::max(buffer[color_index + 2], blue); + } + } + } + + const int draw_x = map_x * rme::TileSize - scroll_x; + const int draw_y = map_y * rme::TileSize - scroll_y; + constexpr int draw_width = rme::ClientMapWidth * rme::TileSize; + constexpr int draw_height = rme::ClientMapHeight * rme::TileSize; + + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 0x812F); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 0x812F); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rme::ClientMapWidth, rme::ClientMapHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data()); + + glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); + + glEnable(GL_TEXTURE_2D); + glBegin(GL_QUADS); + glTexCoord2f(0.f, 0.f); glVertex2f(draw_x, draw_y); + glTexCoord2f(1.f, 0.f); glVertex2f(draw_x + draw_width, draw_y); + glTexCoord2f(1.f, 1.f); glVertex2f(draw_x + draw_width, draw_y + draw_height); + glTexCoord2f(0.f, 1.f); glVertex2f(draw_x, draw_y + draw_height); + glEnd(); + glDisable(GL_TEXTURE_2D); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + +void LightDrawer::setGlobalLightColor(uint8_t color) +{ + global_color = colorFromEightBit(color); +} + +void LightDrawer::addLight(int map_x, int map_y, const SpriteLight& light) +{ + if (map_x <= 0 || map_x >= rme::MapMaxWidth || map_y <= 0 || map_y >= rme::MapMaxHeight) { + return; + } + + uint8_t intensity = std::min(light.intensity, static_cast(rme::MaxLightIntensity)); + + if (!lights.empty()) { + Light& previous = lights.back(); + if (previous.map_x == map_x && previous.map_y == map_y && previous.color == light.color) { + previous.intensity = std::max(previous.intensity, intensity); + return; + } + } + + lights.push_back(Light{ static_cast(map_x), static_cast(map_y), light.color, intensity }); +} + +void LightDrawer::clear() noexcept +{ + lights.clear(); +} + +void LightDrawer::createGLTexture() +{ + glGenTextures(1, &texture); +} + +void LightDrawer::unloadGLTexture() +{ + glDeleteTextures(1, &texture); +} diff --git a/source/light_drawer.h b/source/light_drawer.h new file mode 100644 index 00000000..06cb45b9 --- /dev/null +++ b/source/light_drawer.h @@ -0,0 +1,67 @@ +////////////////////////////////////////////////////////////////////// +// This file is part of Remere's Map Editor +////////////////////////////////////////////////////////////////////// +// Remere's Map Editor is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Remere's Map Editor is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +////////////////////////////////////////////////////////////////////// + +#ifndef RME_LIGHDRAWER_H +#define RME_LIGHDRAWER_H + +#include "graphics.h" +#include "position.h" + +class LightDrawer +{ + struct Light { + uint16_t map_x = 0; + uint16_t map_y = 0; + uint8_t color = 0; + uint8_t intensity = 0; + }; + +public: + LightDrawer(); + virtual ~LightDrawer(); + + void draw(int map_x, int map_y, int scroll_x, int scroll_y); + + void setGlobalLightColor(uint8_t color); + void addLight(int map_x, int map_y, const SpriteLight& light); + void clear() noexcept; + +private: + void createGLTexture(); + void unloadGLTexture(); + + inline float calculateIntensity(int map_x, int map_y, const Light& light) { + int dx = map_x - light.map_x; + int dy = map_y - light.map_y; + float distance = std::sqrt(dx * dx + dy * dy); + if (distance > rme::MaxLightIntensity) { + return 0.f; + } + float intensity = (-distance + light.intensity) * 0.2f; + if (intensity < 0.01f) { + return 0.f; + } + return std::min(intensity, 1.f); + } + + GLuint texture; + std::vector lights; + std::vector buffer; + wxColor global_color; +}; + +#endif diff --git a/source/main_menubar.cpp b/source/main_menubar.cpp index 5685cf72..2b3054a2 100644 --- a/source/main_menubar.cpp +++ b/source/main_menubar.cpp @@ -139,6 +139,7 @@ MainMenuBar::MainMenuBar(MainFrame *frame) : frame(frame) MAKE_ACTION(HIGHLIGHT_ITEMS, wxITEM_CHECK, OnChangeViewSettings); MAKE_ACTION(SHOW_EXTRA, wxITEM_CHECK, OnChangeViewSettings); MAKE_ACTION(SHOW_INGAME_BOX, wxITEM_CHECK, OnChangeViewSettings); + MAKE_ACTION(SHOW_LIGHTS, wxITEM_CHECK, OnChangeViewSettings); MAKE_ACTION(SHOW_GRID, wxITEM_CHECK, OnChangeViewSettings); MAKE_ACTION(SHOW_MONSTERS, wxITEM_CHECK, OnChangeViewSettings); MAKE_ACTION(SHOW_SPAWNS_MONSTER, wxITEM_CHECK, OnChangeViewSettings); @@ -443,6 +444,7 @@ void MainMenuBar::LoadValues() CheckItem(SHOW_SHADE, g_settings.getBoolean(Config::SHOW_SHADE)); CheckItem(SHOW_INGAME_BOX, g_settings.getBoolean(Config::SHOW_INGAME_BOX)); + CheckItem(SHOW_LIGHTS, g_settings.getBoolean(Config::SHOW_LIGHTS)); CheckItem(SHOW_ALL_FLOORS, g_settings.getBoolean(Config::SHOW_ALL_FLOORS)); CheckItem(GHOST_ITEMS, g_settings.getBoolean(Config::TRANSPARENT_ITEMS)); CheckItem(GHOST_HIGHER_FLOORS, g_settings.getBoolean(Config::TRANSPARENT_FLOORS)); @@ -1998,6 +2000,7 @@ void MainMenuBar::OnChangeViewSettings(wxCommandEvent& event) g_settings.setInteger(Config::TRANSPARENT_FLOORS, IsItemChecked(MenuBar::GHOST_HIGHER_FLOORS)); g_settings.setInteger(Config::TRANSPARENT_ITEMS, IsItemChecked(MenuBar::GHOST_ITEMS)); g_settings.setInteger(Config::SHOW_INGAME_BOX, IsItemChecked(MenuBar::SHOW_INGAME_BOX)); + g_settings.setInteger(Config::SHOW_LIGHTS, IsItemChecked(MenuBar::SHOW_LIGHTS)); g_settings.setInteger(Config::SHOW_GRID, IsItemChecked(MenuBar::SHOW_GRID)); g_settings.setInteger(Config::SHOW_EXTRA, !IsItemChecked(MenuBar::SHOW_EXTRA)); diff --git a/source/main_menubar.h b/source/main_menubar.h index 14e7335f..5b3e8634 100644 --- a/source/main_menubar.h +++ b/source/main_menubar.h @@ -104,6 +104,7 @@ namespace MenuBar GHOST_HIGHER_FLOORS, HIGHLIGHT_ITEMS, SHOW_INGAME_BOX, + SHOW_LIGHTS, SHOW_GRID, SHOW_EXTRA, SHOW_MONSTERS, diff --git a/source/map_display.cpp b/source/map_display.cpp index 7650b637..268d9e09 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -205,6 +205,7 @@ void MapCanvas::OnPaint(wxPaintEvent& event) options.transparent_floors = g_settings.getBoolean(Config::TRANSPARENT_FLOORS); options.transparent_items = g_settings.getBoolean(Config::TRANSPARENT_ITEMS); options.show_ingame_box = g_settings.getBoolean(Config::SHOW_INGAME_BOX); + options.show_lights = g_settings.getBoolean(Config::SHOW_LIGHTS); options.show_grid = g_settings.getInteger(Config::SHOW_GRID); options.ingame = !g_settings.getBoolean(Config::SHOW_EXTRA); options.show_all_floors = g_settings.getBoolean(Config::SHOW_ALL_FLOORS); diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index eb88bcb1..b9365c01 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -30,6 +30,7 @@ #include "map_display.h" #include "copybuffer.h" #include "live_socket.h" +#include "graphics.h" #include "doodad_brush.h" #include "monster_brush.h" @@ -43,6 +44,7 @@ #include "raw_brush.h" #include "table_brush.h" #include "waypoint_brush.h" +#include "light_drawer.h" DrawingOptions::DrawingOptions() { @@ -54,6 +56,7 @@ void DrawingOptions::SetDefault() transparent_floors = false; transparent_items = false; show_ingame_box = false; + show_lights = false; ingame = false; dragging = false; @@ -86,6 +89,7 @@ void DrawingOptions::SetIngame() transparent_floors = false; transparent_items = false; show_ingame_box = false; + show_lights = false; ingame = true; dragging = false; @@ -130,9 +134,14 @@ bool DrawingOptions::isTooltips() const noexcept return show_tooltips && !isOnlyColors(); } +bool DrawingOptions::isDrawLight() const noexcept +{ + return show_ingame_box && show_lights; +} + MapDrawer::MapDrawer(MapCanvas* canvas) : canvas(canvas), editor(canvas->editor) { - //// + light_drawer = std::make_shared(); } MapDrawer::~MapDrawer() @@ -203,6 +212,10 @@ void MapDrawer::Release() } tooltips.clear(); + if(light_drawer) { + light_drawer->clear(); + } + // Disable 2D mode glMatrixMode(GL_PROJECTION); glPopMatrix(); @@ -275,6 +288,14 @@ void MapDrawer::DrawShade(int map_z) void MapDrawer::DrawMap() { + int center_x = start_x + int(screensize_x * zoom / 64); + int center_y = start_y + int(screensize_y * zoom / 64); + int offset_y = 2; + int box_start_map_x = center_x - view_scroll_x; + int box_start_map_y = center_y - view_scroll_x + offset_y; + int box_end_map_x = center_x + rme::ClientMapWidth; + int box_end_map_y = center_y + rme::ClientMapHeight + offset_y; + bool live_client = editor.IsLiveClient(); Brush* brush = g_gui.GetCurrentBrush(); @@ -319,7 +340,14 @@ void MapDrawer::DrawMap() if(!live_client || nd->isVisible(map_z > rme::MapGroundLayer)) { for(int map_x = 0; map_x < 4; ++map_x) { for(int map_y = 0; map_y < 4; ++map_y) { - DrawTile(nd->getTile(map_x, map_y, map_z)); + TileLocation* location = nd->getTile(map_x, map_y, map_z); + DrawTile(location); + if(location && options.isDrawLight()) { + auto& position = location->getPosition(); + if(position.x >= box_start_map_x && position.x <= box_end_map_x && position.y >= box_start_map_y && position.y <= box_end_map_y) { + AddLight(location); + } + } } } if (tile_indicators) { @@ -475,85 +503,52 @@ void MapDrawer::DrawIngameBox() int box_end_x = box_end_map_x * rme::TileSize - view_scroll_x; int box_end_y = box_end_map_y * rme::TileSize - view_scroll_y; + if(options.isDrawLight()) { + light_drawer->draw(box_start_map_x, box_start_map_y, view_scroll_x, view_scroll_y); + } + + static wxColor side_color(0, 0, 0, 200); + + glDisable(GL_TEXTURE_2D); + + // left side if(box_start_map_x >= start_x) { - glColor4ub(0, 0, 0, 128); - glBegin(GL_QUADS); - glVertex2f(0, screensize_y * zoom); - glVertex2f(box_start_x, screensize_y * zoom); - glVertex2f(box_start_x, 0); - glVertex2f(0, 0); - glEnd(); + drawFilledRect(0, 0, box_start_x, screensize_y * zoom, side_color); } + // right side if(box_end_map_x < end_x) { - glColor4ub(0, 0, 0, 128); - glBegin(GL_QUADS); - glVertex2f(box_end_x, screensize_y * zoom); - glVertex2f(screensize_x * zoom, screensize_y * zoom); - glVertex2f(screensize_x * zoom, 0); - glVertex2f(box_end_x, 0); - glEnd(); + drawFilledRect(box_end_x, 0, screensize_x * zoom, screensize_y * zoom, side_color); } + // top side if(box_start_map_y >= start_y) { - glColor4ub(0, 0, 0, 128); - glBegin(GL_QUADS); - glVertex2f(box_start_x, box_start_y); - glVertex2f(box_end_x, box_start_y); - glVertex2f(box_end_x, 0); - glVertex2f(box_start_x, 0); - glEnd(); + drawFilledRect(box_start_x, 0, box_end_x-box_start_x, box_start_y, side_color); } + // bottom side if(box_end_map_y < end_y) { - glColor4ub(0, 0, 0, 128); - glBegin(GL_QUADS); - glVertex2f(box_start_x, screensize_y * zoom); - glVertex2f(box_end_x, screensize_y * zoom); - glVertex2f(box_end_x, box_end_y); - glVertex2f(box_start_x, box_end_y); - glEnd(); + drawFilledRect(box_start_x, box_end_y, box_end_x-box_start_x, screensize_y * zoom, side_color); } - // client hidden tiles - glColor4ub(255, 0, 0, 128); - glBegin(GL_LINE_STRIP); - glVertex2f(box_start_x, box_start_y); - glVertex2f(box_end_x, box_start_y); - glVertex2f(box_end_x, box_end_y); - glVertex2f(box_start_x, box_end_y); - glVertex2f(box_start_x, box_start_y); - glEnd(); + // hidden tiles + drawRect(box_start_x, box_start_y, box_end_x-box_start_x, box_end_y-box_start_y, *wxRED); + // visible tiles box_start_x += rme::TileSize; box_start_y += rme::TileSize; box_end_x -= 2 * rme::TileSize; box_end_y -= 2 * rme::TileSize; + drawRect(box_start_x, box_start_y, box_end_x-box_start_x, box_end_y-box_start_y, *wxGREEN); - // client visible tiles - glColor4ub(0, 255, 0, 128); - glBegin(GL_LINE_STRIP); - glVertex2f(box_start_x, box_start_y); - glVertex2f(box_end_x, box_start_y); - glVertex2f(box_end_x, box_end_y); - glVertex2f(box_start_x, box_end_y); - glVertex2f(box_start_x, box_start_y); - glEnd(); - + // player position box_start_x += ((rme::ClientMapWidth/2)-2) * rme::TileSize; box_start_y += ((rme::ClientMapHeight/2)-2) * rme::TileSize; box_end_x = box_start_x + rme::TileSize; box_end_y = box_start_y + rme::TileSize; + drawRect(box_start_x, box_start_y, box_end_x-box_start_x, box_end_y-box_start_y, *wxGREEN); - // client player position - glColor4ub(0, 255, 0, 128); - glBegin(GL_LINE_STRIP); - glVertex2f(box_start_x, box_start_y); - glVertex2f(box_end_x, box_start_y); - glVertex2f(box_end_x, box_end_y); - glVertex2f(box_start_x, box_end_y); - glVertex2f(box_start_x, box_start_y); - glEnd(); + glEnable(GL_TEXTURE_2D); } void MapDrawer::DrawGrid() @@ -1892,6 +1887,35 @@ void MapDrawer::MakeTooltip(int screenx, int screeny, const std::string& text, u tooltips.push_back(tooltip); } +void MapDrawer::AddLight(TileLocation* location) +{ + if(!options.isDrawLight() || !location) { + return; + } + + auto tile = location->get(); + if(!tile) { + return; + } + + auto& position = location->getPosition(); + + if(tile->ground) { + if (tile->ground->hasLight()) { + light_drawer->addLight(position.x, position.y, tile->ground->getLight()); + } + } + + bool hidden = options.hide_items_when_zoomed && zoom > 10.f; + if(!hidden && !tile->items.empty()) { + for(auto item : tile->items) { + if(item->hasLight()) { + light_drawer->addLight(position.x, position.y, item->getLight()); + } + } + } +} + void MapDrawer::getColor(Brush* brush, const Position& position, uint8_t &r, uint8_t &g, uint8_t &b) { if(brush->canDraw(&editor.getMap(), position)) { @@ -2053,6 +2077,17 @@ void MapDrawer::drawRect(int x, int y, int w, int h, const wxColor& color, int w glEnd(); } +void MapDrawer::drawFilledRect(int x, int y, int w, int h, const wxColor& color) +{ + glColor4ub(color.Red(), color.Green(), color.Blue(), color.Alpha()); + glBegin(GL_QUADS); + glVertex2f(x, y); + glVertex2f(x + w, y); + glVertex2f(x + w, y + h); + glVertex2f(x, y + h); + glEnd(); +} + void MapDrawer::getDrawPosition(const Position& position, int& x, int& y) { int offset; diff --git a/source/map_drawer.h b/source/map_drawer.h index a4435f10..56003c22 100644 --- a/source/map_drawer.h +++ b/source/map_drawer.h @@ -54,10 +54,12 @@ struct DrawingOptions { bool isOnlyColors() const noexcept; bool isTileIndicators() const noexcept; bool isTooltips() const noexcept; + bool isDrawLight() const noexcept; bool transparent_floors; bool transparent_items; bool show_ingame_box; + bool show_lights; bool ingame; bool dragging; @@ -86,12 +88,14 @@ struct DrawingOptions { }; class MapCanvas; +class LightDrawer; class MapDrawer { MapCanvas* canvas; Editor& editor; DrawingOptions options; + std::shared_ptr light_drawer; float zoom; @@ -160,6 +164,7 @@ class MapDrawer void WriteTooltip(const Item* item, std::ostringstream& stream); void WriteTooltip(const Waypoint* item, std::ostringstream& stream); void MakeTooltip(int screenx, int screeny, const std::string& text, uint8_t r = 255, uint8_t g = 255, uint8_t b = 255); + void AddLight(TileLocation* location); enum BrushColor { COLOR_BRUSH, @@ -181,6 +186,7 @@ class MapDrawer void glColor(BrushColor color); void glColorCheck(Brush* brush, const Position& pos); void drawRect(int x, int y, int w, int h, const wxColor& color, int width = 1); + void drawFilledRect(int x, int y, int w, int h, const wxColor& color); private: void getDrawPosition(const Position& position, int &x, int &y); diff --git a/source/settings.cpp b/source/settings.cpp index a6692f85..6684ec0a 100644 --- a/source/settings.cpp +++ b/source/settings.cpp @@ -196,6 +196,7 @@ void Settings::IO(IOMode mode) Int(TRANSPARENT_ITEMS, 0); Int(SHOW_ALL_FLOORS, 1); Int(SHOW_INGAME_BOX, 0); + Int(SHOW_LIGHTS, 1); Int(SHOW_GRID, 0); Int(SHOW_EXTRA, 1); Int(SHOW_SHADE, 1); diff --git a/source/settings.h b/source/settings.h index 0277755b..2bf70c4f 100644 --- a/source/settings.h +++ b/source/settings.h @@ -42,6 +42,7 @@ namespace Config { TRANSPARENT_FLOORS, TRANSPARENT_ITEMS, SHOW_INGAME_BOX, + SHOW_LIGHTS, SHOW_GRID, SHOW_EXTRA, SHOW_ALL_FLOORS, diff --git a/vcproj/Project/RME.vcxproj b/vcproj/Project/RME.vcxproj index 008f644e..7c803472 100644 --- a/vcproj/Project/RME.vcxproj +++ b/vcproj/Project/RME.vcxproj @@ -219,11 +219,13 @@ + + From ba7b73fda32a86f81da24fd4a18e6516145360ad Mon Sep 17 00:00:00 2001 From: wtver <51377408+maattch@users.noreply.github.com> Date: Wed, 22 Feb 2023 08:59:44 -0300 Subject: [PATCH 30/45] Fix go to previous position (#410) --- source/map_window.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/map_window.cpp b/source/map_window.cpp index 20fe95cd..4132bf21 100644 --- a/source/map_window.cpp +++ b/source/map_window.cpp @@ -142,10 +142,11 @@ void MapWindow::SetScreenCenterPosition(const Position& position, bool showIndic int x = position.x * rme::TileSize; int y = position.y * rme::TileSize; + int z = position.z; if(position.z < 8) { // Compensate for floor offset above ground - x -= (rme::MapGroundLayer - position.z) * rme::TileSize; - y -= (rme::MapGroundLayer - position.z) * rme::TileSize; + x -= (rme::MapGroundLayer - z) * rme::TileSize; + y -= (rme::MapGroundLayer - z) * rme::TileSize; } const Position& center = GetScreenCenterPosition(); @@ -156,7 +157,7 @@ void MapWindow::SetScreenCenterPosition(const Position& position, bool showIndic } Scroll(x, y, true); - canvas->ChangeFloor(position.z); + canvas->ChangeFloor(z); if (showIndicator) canvas->ShowPositionIndicator(position); From b94b741a5c924ffaa31c50baba4224934c2909cb Mon Sep 17 00:00:00 2001 From: wtver <51377408+maattch@users.noreply.github.com> Date: Wed, 1 Mar 2023 20:12:38 -0300 Subject: [PATCH 31/45] Fix depot crash (#411) --- source/old_properties_window.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/old_properties_window.cpp b/source/old_properties_window.cpp index 46205d73..6de1b91e 100644 --- a/source/old_properties_window.cpp +++ b/source/old_properties_window.cpp @@ -565,8 +565,8 @@ void OldPropertiesWindow::OnFocusChange(wxFocusEvent& event) void OldPropertiesWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) { if(edit_item) { - int new_uid = unique_id_field->GetValue(); - int new_aid = action_id_field->GetValue(); + int new_uid = (unique_id_field ? unique_id_field->GetValue() : 0); + int new_aid = (action_id_field ? action_id_field->GetValue() : 0); bool uid_changed = false; bool aid_changed = false; From 16af847f6974b6a897e5c1abd8e5db9cc5e0a7a1 Mon Sep 17 00:00:00 2001 From: Nailson Date: Sat, 25 Mar 2023 21:40:44 -0300 Subject: [PATCH 32/45] Fix XPMs From adacd128a3660954d84364194612aaabb29ee4ca Mon Sep 17 00:00:00 2001 From: Nailson Date: Mon, 27 Mar 2023 09:09:14 -0300 Subject: [PATCH 33/45] Export minimap as .otmm (otclient format) or .png (#413) --- source/CMakeLists.txt | 1 + source/common_windows.cpp | 65 +++--- source/common_windows.h | 1 + source/editor.cpp | 95 --------- source/editor.h | 2 - source/filehandle.cpp | 33 ++- source/filehandle.h | 27 ++- source/graphics.cpp | 12 +- source/graphics.h | 1 + source/iominimap.cpp | 406 +++++++++++++++++++++++++++++++++++++ source/iominimap.h | 97 +++++++++ source/item.cpp | 9 + source/item.h | 2 + source/main_menubar.cpp | 9 +- source/tile.cpp | 8 + source/tile.h | 2 + vcproj/Project/RME.vcxproj | 2 + 17 files changed, 608 insertions(+), 164 deletions(-) create mode 100644 source/iominimap.cpp create mode 100644 source/iominimap.h diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index db858c7d..0d7f4eb2 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -71,6 +71,7 @@ target_sources(${PROJECT_NAME} light_drawer.cpp iomap.cpp iomap_otbm.cpp + iominimap.cpp item_attributes.cpp item.cpp items.cpp diff --git a/source/common_windows.cpp b/source/common_windows.cpp index 4b21707e..98501b9f 100644 --- a/source/common_windows.cpp +++ b/source/common_windows.cpp @@ -33,6 +33,8 @@ #include "common_windows.h" #include "positionctrl.h" +#include "iominimap.h" + #ifdef _MSC_VER #pragma warning(disable:4018) // signed/unsigned mismatch #endif @@ -550,6 +552,15 @@ ExportMiniMapWindow::ExportMiniMapWindow(wxWindow* parent, Editor& editor) : tmpsizer->Add(file_name_text_field, 1, wxALL, 5); sizer->Add(tmpsizer, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5); + // Format options + wxArrayString format_choices; + format_choices.Add(".otmm (Client Minimap)"); + format_choices.Add(".png (PNG Image)"); + format_choices.Add(".bmp (Bitmap Image)"); + format_options = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, format_choices); + format_options->SetSelection(0); + tmpsizer->Add(format_options, 1, wxALL, 5); + // Export options wxArrayString choices; choices.Add("All Floors"); @@ -612,59 +623,29 @@ void ExportMiniMapWindow::OnFileNameChanged(wxKeyEvent& event) void ExportMiniMapWindow::OnClickOK(wxCommandEvent& WXUNUSED(event)) { - g_gui.CreateLoadBar("Exporting minimap"); + g_gui.CreateLoadBar("Exporting minimap..."); - try - { - FileName directory(directory_text_field->GetValue()); - g_settings.setString(Config::MINIMAP_EXPORT_DIR, directory_text_field->GetValue().ToStdString()); - - switch(floor_options->GetSelection()) - { - case 0: { // All floors - for(int floor = 0; floor < rme::MapLayers; ++floor) { - g_gui.SetLoadScale(int(floor*(100.f/16.f)), int((floor+1)*(100.f/16.f))); - FileName file(file_name_text_field->GetValue() + "_" + i2ws(floor) + ".bmp"); - file.Normalize(wxPATH_NORM_ALL, directory.GetFullPath()); - editor.exportMiniMap(file, floor, true); - } - break; - } - - case 1: { // Ground floor - FileName file(file_name_text_field->GetValue() + "_" + i2ws(rme::MapGroundLayer) + ".bmp"); - file.Normalize(wxPATH_NORM_ALL, directory.GetFullPath()); - editor.exportMiniMap(file, rme::MapGroundLayer, true); - break; - } + auto format = static_cast(format_options->GetSelection()); + auto mode = static_cast(floor_options->GetSelection()); + std::string directory = directory_text_field->GetValue().ToStdString(); + std::string file_name = file_name_text_field->GetValue().ToStdString(); + int floor = floor_number->GetValue(); - case 2: { // Specific floors - int floor = floor_number->GetValue(); - FileName file(file_name_text_field->GetValue() + "_" + i2ws(floor) + ".bmp"); - file.Normalize(wxPATH_NORM_ALL, directory.GetFullPath()); - editor.exportMiniMap(file, floor, true); - break; - } + g_settings.setString(Config::MINIMAP_EXPORT_DIR, directory); - case 3: { // Selected area - editor.exportSelectionAsMiniMap(directory, file_name_text_field->GetValue()); - break; - } - } - } - catch(std::bad_alloc&) - { - g_gui.PopupDialog("Error", "There is not enough memory available to complete the operation.", wxOK); + IOMinimap io(&editor, format, mode, true); + if (!io.saveMinimap(directory, file_name, floor)) { + g_gui.PopupDialog("Error", io.getError(), wxOK); } g_gui.DestroyLoadBar(); - EndModal(1); + EndModal(wxID_OK); } void ExportMiniMapWindow::OnClickCancel(wxCommandEvent& WXUNUSED(event)) { // Just close this window - EndModal(0); + EndModal(wxID_CANCEL); } void ExportMiniMapWindow::CheckValues() diff --git a/source/common_windows.h b/source/common_windows.h index 227b2bd1..2cd0fff2 100644 --- a/source/common_windows.h +++ b/source/common_windows.h @@ -129,6 +129,7 @@ class ExportMiniMapWindow : public wxDialog Editor& editor; + wxChoice* format_options; wxStaticText* error_field; wxTextCtrl* directory_text_field; wxTextCtrl* file_name_text_field; diff --git a/source/editor.cpp b/source/editor.cpp index 39cc3d6f..ab632952 100644 --- a/source/editor.cpp +++ b/source/editor.cpp @@ -466,101 +466,6 @@ bool Editor::importMiniMap(FileName filename, int import, int import_x_offset, i return false; } -bool Editor::exportMiniMap(FileName filename, int floor /*= rme::MapGroundLayer*/, bool displaydialog) -{ - return map.exportMinimap(filename, floor, displaydialog); -} - -bool Editor::exportSelectionAsMiniMap(FileName directory, wxString fileName) -{ - if(!directory.Exists() || !directory.IsDirWritable()) - return false; - - int min_x = rme::MapMaxWidth + 1, min_y = rme::MapMaxHeight + 1, min_z = rme::MapMaxLayer + 1; - int max_x = 0, max_y = 0, max_z = 0; - - const TileSet& tiles = selection.getTiles(); - for(Tile* tile : tiles) { - if(tile->empty()) - continue; - - const Position& pos = tile->getPosition(); - - if(pos.x < min_x) - min_x = pos.x; - if(pos.x > max_x) - max_x = pos.x; - - if(pos.y < min_y) - min_y = pos.y; - if(pos.y > max_y) - max_y = pos.y; - - if(pos.z < min_z) - min_z = pos.z; - if(pos.z > max_z) - max_z = pos.z; - } - - int numtiles = (max_x - min_x) * (max_y - min_y); - int minimap_width = max_x - min_x + 1; - int minimap_height = max_y - min_y + 1; - - if(numtiles == 0) - return false; - - if(minimap_width > 2048 || minimap_height > 2048) { - g_gui.PopupDialog("Error", "Minimap size greater than 2048px.", wxOK); - return false; - } - - int tiles_iterated = 0; - - for(int z = min_z; z <= max_z; z++) { - uint8_t* pixels = newd uint8_t[minimap_width * minimap_height * 3]; // 3 bytes per pixel - memset(pixels, 0, minimap_width * minimap_height * 3); - - for(Tile* tile : tiles) { - if(tile->getZ() != z) - continue; - - ++tiles_iterated; - if(tiles_iterated % 8192 == 0) - g_gui.SetLoadDone(int(tiles_iterated / double(tiles.size()) * 90.0)); - - if(tile->empty()) - continue; - - uint8_t color = 0; - - for(Item* item : tile->items) { - if(item->getMiniMapColor() != 0) { - color = item->getMiniMapColor(); - break; - } - } - - if(color == 0 && tile->hasGround()) - color = tile->ground->getMiniMapColor(); - - uint32_t index = ((tile->getY() - min_y) * minimap_width + (tile->getX() - min_x)) * 3; - - pixels[index] = (uint8_t)(int(color / 36) % 6 * 51); // red - pixels[index + 1] = (uint8_t)(int(color / 6) % 6 * 51); // green - pixels[index + 2] = (uint8_t)(color % 6 * 51); // blue - } - - FileName file(fileName + "_" + i2ws(z) + ".png"); - file.Normalize(wxPATH_NORM_ALL, directory.GetFullPath()); - wxImage* image = newd wxImage(minimap_width, minimap_height, pixels, true); - image->SaveFile(file.GetFullPath(), wxBITMAP_TYPE_PNG); - image->Destroy(); - delete[] pixels; - } - - return true; -} - bool Editor::importMap(FileName filename, int import_x_offset, int import_y_offset, int import_z_offset, ImportType house_import_type, ImportType spawn_import_type, ImportType spawn_npc_import_type) { selection.clear(); diff --git a/source/editor.h b/source/editor.h index aa7f7a05..0a19d59d 100644 --- a/source/editor.h +++ b/source/editor.h @@ -84,8 +84,6 @@ class Editor wxString getLoaderError() const {return map.getError();} bool importMap(FileName filename, int import_x_offset, int import_y_offset, int import_z_offset, ImportType house_import_type, ImportType spawn_import_type, ImportType spawn_npc_import_type); bool importMiniMap(FileName filename, int import, int import_x_offset, int import_y_offset, int import_z_offset); - bool exportMiniMap(FileName filename, int floor /*= rme::MapGroundLayer*/, bool displaydialog); - bool exportSelectionAsMiniMap(FileName directory, wxString fileName); ActionQueue* getHistoryActions() const noexcept { return actionQueue; } Action* createAction(ActionIdentifier type); diff --git a/source/filehandle.cpp b/source/filehandle.cpp index a0abb1a7..eb9c1ef5 100644 --- a/source/filehandle.cpp +++ b/source/filehandle.cpp @@ -26,6 +26,22 @@ uint8_t NodeFileWriteHandle::NODE_START = ::NODE_START; uint8_t NodeFileWriteHandle::NODE_END = ::NODE_END; uint8_t NodeFileWriteHandle::ESCAPE_CHAR = ::ESCAPE_CHAR; +bool FileHandle::seek(size_t offset, int origin) +{ + if(file) { + return fseek(file, static_cast(offset), origin) == 0; + } + return false; +} + +size_t FileHandle::tell() +{ + if(file) { + return ftell(file); + } + return 0; +} + void FileHandle::close() { if(file) { @@ -126,16 +142,6 @@ bool FileReadHandle::getLongString(std::string& str) return getRAW(str, sz); } -bool FileReadHandle::seek(size_t offset) -{ - return fseek(file, long(offset), SEEK_SET) == 0; -} - -bool FileReadHandle::seekRelative(size_t offset) -{ - return fseek(file, long(offset), SEEK_CUR) == 0; -} - //============================================================================= // Node file read handle @@ -553,6 +559,13 @@ bool FileWriteHandle::addRAW(const uint8_t* ptr, size_t sz) return ferror(file) == 0; } +void FileWriteHandle::flush() +{ + if(file) { + fflush(file); + } +} + //============================================================================= // Disk based node file write handle diff --git a/source/filehandle.h b/source/filehandle.h index f2f9b136..f5189c2b 100644 --- a/source/filehandle.h +++ b/source/filehandle.h @@ -56,10 +56,19 @@ class FileHandle FileHandle() : error_code(FILE_NO_ERROR), file(nullptr) {} virtual ~FileHandle() { close(); } + bool seek(size_t offset, int origin = SEEK_SET); + size_t tell(); + FORCEINLINE void skip(size_t offset) { seek(offset, SEEK_CUR); } + + // Ensures we don't accidentally copy it. + FileHandle(const FileHandle &) = delete; + FileHandle &operator=(const FileHandle &) = delete; + virtual void close(); virtual bool isOpen() {return file != nullptr;} virtual bool isOk() {return isOpen() && error_code == FILE_NO_ERROR && ferror(file) == 0;} std::string getErrorMessage(); + public: FileHandleError error_code; FILE* file; @@ -83,11 +92,8 @@ class FileReadHandle : public FileHandle bool getLongString(std::string& str); virtual void close(); - bool seek(size_t offset); - bool seekRelative(size_t offset); - FORCEINLINE void skip(size_t offset) {seekRelative(offset);} - size_t size() {return file_size;} - size_t tell() {if(file) return ftell(file); return 0;} + size_t size() { return file_size; } + protected: size_t file_size; @@ -236,7 +242,8 @@ class FileWriteHandle : public FileHandle bool addLongString(const std::string& str); bool addRAW(const std::string& str); bool addRAW(const uint8_t* ptr, size_t sz); - bool addRAW(const char* c) {return addRAW(reinterpret_cast(c), strlen(c));} + bool addRAW(const char* c) { return addRAW(reinterpret_cast(c), strlen(c)); } + void flush(); protected: template @@ -297,17 +304,20 @@ class NodeFileWriteHandle : public FileHandle } }; -class DiskNodeFileWriteHandle : public NodeFileWriteHandle { +class DiskNodeFileWriteHandle : public NodeFileWriteHandle +{ public: DiskNodeFileWriteHandle(const std::string& name, const std::string& identifier); virtual ~DiskNodeFileWriteHandle(); virtual void close(); + protected: virtual void renewCache(); }; -class MemoryNodeFileWriteHandle : public NodeFileWriteHandle { +class MemoryNodeFileWriteHandle : public NodeFileWriteHandle +{ public: MemoryNodeFileWriteHandle(); virtual ~MemoryNodeFileWriteHandle(); @@ -317,6 +327,7 @@ class MemoryNodeFileWriteHandle : public NodeFileWriteHandle { uint8_t* getMemory(); size_t getSize(); + protected: virtual void renewCache(); }; diff --git a/source/graphics.cpp b/source/graphics.cpp index a78b2b42..2a7d1f6a 100644 --- a/source/graphics.cpp +++ b/source/graphics.cpp @@ -576,7 +576,6 @@ bool GraphicManager::loadSpriteMetadataFlags(FileReadHandle& file, GameSprite* s case DatFlagChargeable: break; - case DatFlagGround: case DatFlagWritable: case DatFlagWritableOnce: case DatFlagCloth: @@ -585,6 +584,12 @@ bool GraphicManager::loadSpriteMetadataFlags(FileReadHandle& file, GameSprite* s file.skip(2); break; + case DatFlagGround: + uint16_t speed; + file.getU16(speed); + sType->ground_speed = speed; + break; + case DatFlagLight: { SpriteLight light; uint16_t intensity; @@ -702,7 +707,7 @@ bool GraphicManager::loadSpriteData(const FileName& datafile, wxString& error, w wxString ss; ss << "items.spr: Duplicate GameSprite id " << id; warnings.push_back(ss); - fh.seekRelative(size); + fh.skip(size); } else { spr->id = id; spr->size = size; @@ -714,7 +719,7 @@ bool GraphicManager::loadSpriteData(const FileName& datafile, wxString& error, w } } } else { - fh.seekRelative(size); + fh.skip(size); } } #undef safe_get @@ -830,6 +835,7 @@ GameSprite::GameSprite() : frames(0), numsprites(0), animator(nullptr), + ground_speed(0), draw_height(0), minimap_color(0) { diff --git a/source/graphics.h b/source/graphics.h index 662a4af5..167a26d2 100644 --- a/source/graphics.h +++ b/source/graphics.h @@ -197,6 +197,7 @@ class GameSprite : public Sprite{ Animator* animator; + uint16_t ground_speed; uint16_t draw_height; wxPoint draw_offset; diff --git a/source/iominimap.cpp b/source/iominimap.cpp new file mode 100644 index 00000000..12c1d014 --- /dev/null +++ b/source/iominimap.cpp @@ -0,0 +1,406 @@ +////////////////////////////////////////////////////////////////////// +// This file is part of Remere's Map Editor +////////////////////////////////////////////////////////////////////// +// Remere's Map Editor is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Remere's Map Editor is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +////////////////////////////////////////////////////////////////////// + +#include "main.h" + +#include "iominimap.h" + +#include "tile.h" +#include "filehandle.h" +#include "editor.h" +#include "gui.h" + +#include +#include + +void MinimapBlock::updateTile(int x, int y, const MinimapTile& tile) +{ + m_tiles[getTileIndex(x, y)] = tile; +} + +IOMinimap::IOMinimap(Editor* editor, MinimapExportFormat format, MinimapExportMode mode, bool updateLoadbar) : + m_editor(editor), + m_format(format), + m_mode(mode), + m_updateLoadbar(updateLoadbar) +{ +} + +bool IOMinimap::saveMinimap(const std::string& directory, const std::string& name, int floor) +{ + if(m_mode == MinimapExportMode::AllFloors || m_mode == MinimapExportMode::SelectedArea) { + floor = -1; + } else if(m_mode == MinimapExportMode::GroundFloor) { + floor = rme::MapGroundLayer; + } else if(m_mode == MinimapExportMode::SpecificFloor) { + if(floor < rme::MapMinLayer || floor > rme::MapMaxLayer) { + floor = rme::MapGroundLayer; + } + } + + m_floor = floor; + + if (m_format == MinimapExportFormat::Otmm) { + return saveOtmm(wxFileName(directory, name + ".otmm")); + } + return saveImage(directory, name); +} + +bool IOMinimap::saveOtmm(const wxFileName& file) +{ + try + { + FileWriteHandle writer(file.GetFullPath().ToStdString()); + if(!writer.isOk()) { + //error("Unable to open file %s for save minimap", file); + return false; + } + + //TODO: compression flag with zlib + uint32_t flags = 0; + + // header + writer.addU32(OTMM_SIGNATURE); + writer.addU16(0); // data start, will be overwritten later + writer.addU16(OTMM_VERSION); + writer.addU32(flags); + + // version 1 header + writer.addString("OTMM 1.0"); // description + + // go back and rewrite where the map data starts + uint32_t start = writer.tell(); + writer.seek(4); + writer.addU16(start); + writer.seek(start); + + unsigned long blockSize = MMBLOCK_SIZE * MMBLOCK_SIZE * sizeof(MinimapTile); + std::vector buffer(compressBound(blockSize)); + constexpr int COMPRESS_LEVEL = 3; + + readBlocks(); + + for(uint8_t z = 0; z <= rme::MapMaxLayer; ++z) { + for(auto& it : m_blocks[z]) { + int index = it.first; + auto& block = it.second; + + // write index pos + uint16_t x = static_cast((index % (65536 / MMBLOCK_SIZE)) * MMBLOCK_SIZE); + uint16_t y = static_cast((index / (65536 / MMBLOCK_SIZE)) * MMBLOCK_SIZE); + writer.addU16(x); + writer.addU16(y); + writer.addU8(z); + + unsigned long len = blockSize; + int ret = compress2(buffer.data(), &len, (uint8_t*)&block.getTiles(), blockSize, COMPRESS_LEVEL); + assert(ret == Z_OK); + writer.addU16(len); + writer.addRAW(buffer.data(), len); + } + m_blocks[z].clear(); + } + + // end of file is an invalid pos + writer.addU16(65535); + writer.addU16(65535); + writer.addU8(255); + + writer.flush(); + writer.close(); + } catch(std::exception& e) { + m_error = wxString::Format("failed to save OTMM minimap: %s", e.what()); + return false; + } + + return true; +} + +bool IOMinimap::saveImage(const std::string& directory, const std::string& name) +{ + try + { + switch(m_mode) + { + case MinimapExportMode::AllFloors: + case MinimapExportMode::GroundFloor: + case MinimapExportMode::SpecificFloor: { + exportMinimap(directory); + break; + } + case MinimapExportMode::SelectedArea: { + exportSelection(directory, name); + break; + } + } + } + catch(std::bad_alloc&) + { + m_error = "There is not enough memory available to complete the operation."; + } + + return true; +} + +bool IOMinimap::exportMinimap(const std::string& directory) +{ + auto& map = m_editor->getMap(); + if(map.size() == 0) { + return true; + } + + wxRect bounds[rme::MapLayers]; + int min_z = m_floor == -1 ? 0 : m_floor; + int max_z = m_floor == -1 ? rme::MapMaxLayer : m_floor; + + for (size_t z = min_z; z <= max_z; z++) { + auto& rect = bounds[z]; + rect.x = rme::MapMaxWidth + 1; + rect.y = rme::MapMaxHeight + 1; + rect.width = 0; + rect.height = 0; + } + + for(auto it = map.begin(); it != map.end(); ++it) { + auto tile = (*it)->get(); + if(!tile || (!tile->ground && tile->items.empty())) { + continue; + } + + const auto& position = tile->getPosition(); + auto& rect = bounds[position.z]; + if(position.x < rect.x) { + rect.x = position.x; + } + if(position.y < rect.y) { + rect.y = position.y; + } + if (position.x > rect.width) { + rect.width = position.x; + } + if (position.y > rect.height) { + rect.height = position.y; + } + } + + constexpr int image_size = 1024; + constexpr int pixels_size = image_size * image_size * rme::PixelFormatRGB; + uint8_t* pixels = new uint8_t[pixels_size]; + auto image = new wxImage(image_size, image_size, pixels, true); + + for(size_t z = min_z; z <= max_z; z++) { + auto& rect = bounds[z]; + if(rect.IsEmpty()) { + continue; + } + + for (int h = 0; h < rme::MapMaxHeight; h += image_size) { + for (int w = 0; w < rme::MapMaxWidth; w += image_size) { + if (w < rect.x || w > rect.width || h < rect.y || h > rect.height) { + continue; + } + + bool empty = true; + memset(pixels, 0, pixels_size); + + int index = 0; + for (int y = 0; y < image_size; y++) { + for (int x = 0; x < image_size; x++) { + auto tile = map.getTile(w + x, h + y, z); + if(!tile || (!tile->ground && tile->items.empty())) { + index += rme::PixelFormatRGB; + continue; + } + uint8_t color = tile->getMiniMapColor(); + pixels[index ] = (uint8_t)(static_cast(color / 36) % 6 * 51); // red + pixels[index+1] = (uint8_t)(static_cast(color / 6) % 6 * 51); // green + pixels[index+2] = (uint8_t)(color % 6 * 51); // blue + index += rme::PixelFormatRGB; + empty = false; + } + } + + if (!empty) { + image->SetData(pixels, true); + wxString extension = m_format == MinimapExportFormat::Png ? "png" : "bmp"; + wxBitmapType type = m_format == MinimapExportFormat::Png ? wxBITMAP_TYPE_PNG : wxBITMAP_TYPE_BMP; + wxFileName file = wxString::Format("%d-%d-%d.%s", h, w, z, extension); + file.Normalize(wxPATH_NORM_ALL, directory); + image->SaveFile(file.GetFullPath(), type); + } + } + } + } + + image->Destroy(); + delete[] pixels; + return true; +} + +bool IOMinimap::exportSelection(const std::string& directory, const std::string& name) +{ + int min_x = rme::MapMaxWidth + 1; + int min_y = rme::MapMaxHeight + 1; + int min_z = rme::MapMaxLayer + 1; + int max_x = 0, max_y = 0, max_z = 0; + + const auto& selection = m_editor->getSelection(); + const auto& tiles = selection.getTiles(); + + for(auto tile : tiles) { + if(!tile || (!tile->ground && tile->items.empty())) { + continue; + } + + const auto& position = tile->getPosition(); + if(position.x < min_x) { + min_x = position.x; + } + if(position.x > max_x) { + max_x = position.x; + } + + if(position.y < min_y) { + min_y = position.y; + } + if(position.y > max_y) { + max_y = position.y; + } + + if(position.z < min_z) { + min_z = position.z; + } + if(position.z > max_z) { + max_z = position.z; + } + } + + int numtiles = (max_x - min_x) * (max_y - min_y); + if(numtiles == 0) { + return false; + } + + int image_width = max_x - min_x + 1; + int image_height = max_y - min_y + 1; + if(image_width > 2048 || image_height > 2048) { + g_gui.PopupDialog("Error", "Minimap size greater than 2048px.", wxOK); + return false; + } + + int pixels_size = image_width * image_height * rme::PixelFormatRGB; + uint8_t* pixels = new uint8_t[pixels_size]; + auto image = new wxImage(image_width, image_height, pixels, true); + + int tiles_iterated = 0; + for(int z = min_z; z <= max_z; z++) { + bool empty = true; + memset(pixels, 0, pixels_size); + for(auto tile : tiles) { + if(tile->getZ() != z) { + continue; + } + + if (m_updateLoadbar) { + tiles_iterated++; + if(tiles_iterated % 8192 == 0) { + g_gui.SetLoadDone(int(tiles_iterated / double(tiles.size()) * 90.0)); + } + } + + if(!tile->ground && tile->items.empty()) { + continue; + } + + uint8_t color = tile->getMiniMapColor(); + uint32_t index = ((tile->getY() - min_y) * image_width + (tile->getX() - min_x)) * 3; + pixels[index ] = (uint8_t)(static_cast(color / 36) % 6 * 51); // red + pixels[index+1] = (uint8_t)(static_cast(color / 6) % 6 * 51); // green + pixels[index+2] = (uint8_t)(color % 6 * 51); // blue + empty = false; + } + + if (!empty) { + image->SetData(pixels, true); + wxString extension = m_format == MinimapExportFormat::Png ? "png" : "bmp"; + wxBitmapType type = m_format == MinimapExportFormat::Png ? wxBITMAP_TYPE_PNG : wxBITMAP_TYPE_BMP; + wxFileName file = wxString::Format("%s-%d.%s", name, z, extension); + file.Normalize(wxPATH_NORM_ALL, directory); + image->SaveFile(file.GetFullPath(), type); + } + } + + image->Destroy(); + delete[] pixels; + return true; +} + +void IOMinimap::readBlocks() +{ + if (m_mode == MinimapExportMode::SelectedArea && !m_editor->hasSelection()) { + return; + } + + auto& map = m_editor->getMap(); + + int tiles_iterated = 0; + for(auto it = map.begin(); it != map.end(); ++it) { + auto tile = (*it)->get(); + + if (m_updateLoadbar) { + ++tiles_iterated; + if (tiles_iterated % 8192 == 0) { + g_gui.SetLoadDone(int(tiles_iterated / double(map.size()) * 90.0)); + } + } + + if(!tile || (!tile->ground && tile->items.empty())) { + continue; + } + + const auto& position = tile->getPosition(); + + if (m_mode == MinimapExportMode::SelectedArea) { + if (!tile->isSelected()) { + continue; + } + } else if (m_floor != -1 && position.z != m_floor) { + continue; + } + + MinimapTile minimapTile; + minimapTile.color = tile->getMiniMapColor(); + minimapTile.flags |= MinimapTileWasSeen; + if (tile->isBlocking()) { + minimapTile.flags |= MinimapTileNotWalkable; + } + //if (!tile->isPathable()) { + //minimapTile.flags |= MinimapTileNotPathable; + //} + minimapTile.speed = std::min((int)std::ceil(tile->getGroundSpeed() / 10.f), 0xFF); + + auto& blocks = m_blocks[position.z]; + uint32_t index = getBlockIndex(position); + if (blocks.find(index) == blocks.end()) { + blocks.insert({ index, MinimapBlock() }); + } + + auto& block = blocks.at(index); + int offset_x = position.x - (position.x % MMBLOCK_SIZE); + int offset_y = position.y - (position.y % MMBLOCK_SIZE); + block.updateTile(position.x - offset_x, position.y - offset_y, minimapTile); + } +} diff --git a/source/iominimap.h b/source/iominimap.h new file mode 100644 index 00000000..7dfca939 --- /dev/null +++ b/source/iominimap.h @@ -0,0 +1,97 @@ +////////////////////////////////////////////////////////////////////// +// This file is part of Remere's Map Editor +////////////////////////////////////////////////////////////////////// +// Remere's Map Editor is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Remere's Map Editor is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +////////////////////////////////////////////////////////////////////// + +#ifndef RME_OTMM_H_ +#define RME_OTMM_H_ + +#include "map.h" + +enum class MinimapExportFormat { + Otmm, + Png, + Bmp +}; + +enum class MinimapExportMode { + AllFloors, + GroundFloor, + SpecificFloor, + SelectedArea +}; + +enum { + MMBLOCK_SIZE = 64, + OTMM_SIGNATURE = 0x4D4d544F, + OTMM_VERSION = 1 +}; + +enum MinimapTileFlags { + MinimapTileWasSeen = 1, + MinimapTileNotPathable = 2, + MinimapTileNotWalkable = 4 +}; + +#pragma pack(push,1) // disable memory alignment +struct MinimapTile +{ + uint8_t flags = 0; + uint8_t color = INVALID_MINIMAP_COLOR; + uint8_t speed = 10; +}; + +class MinimapBlock +{ +public: + void updateTile(int x, int y, const MinimapTile& tile); + MinimapTile& getTile(int x, int y) { return m_tiles[getTileIndex(x,y)]; } + inline uint32_t getTileIndex(int x, int y) const noexcept { return ((y % MMBLOCK_SIZE) * MMBLOCK_SIZE) + (x % MMBLOCK_SIZE); } + const std::array& getTiles() const noexcept { return m_tiles; } + +private: + std::array m_tiles; +}; +#pragma pack(pop) + +class IOMinimap +{ +public: + IOMinimap(Editor* editor, MinimapExportFormat format, MinimapExportMode mode, bool updateLoadbar); + + bool saveMinimap(const std::string& directory, const std::string& name, int floor = -1); + + const std::string& getError() const noexcept { return m_error; } + +private: + bool saveOtmm(const wxFileName& file); + bool saveImage(const std::string& directory, const std::string& name); + bool exportMinimap(const std::string& directory); + bool exportSelection(const std::string& directory, const std::string& name); + void readBlocks(); + inline uint32_t getBlockIndex(const Position& pos) { + return ((pos.y / MMBLOCK_SIZE) * (65536 / MMBLOCK_SIZE)) + (pos.x / MMBLOCK_SIZE); + } + + Editor* m_editor; + MinimapExportFormat m_format; + MinimapExportMode m_mode; + bool m_updateLoadbar = false; + int m_floor = -1; + std::unordered_map m_blocks[rme::MapLayers]; + std::string m_error; +}; + +#endif diff --git a/source/item.cpp b/source/item.cpp index 7d89ee14..2f7416e5 100644 --- a/source/item.cpp +++ b/source/item.cpp @@ -232,6 +232,15 @@ wxPoint Item::getDrawOffset() const return wxPoint(0, 0); } +uint16_t Item::getGroundSpeed() const +{ + const auto& type = g_items.getItemType(id); + if(type.sprite) { + return type.sprite->ground_speed; + } + return 0; +} + bool Item::hasLight() const { const ItemType& type = g_items.getItemType(id); diff --git a/source/item.h b/source/item.h index 48e2349b..8c7757b5 100644 --- a/source/item.h +++ b/source/item.h @@ -178,6 +178,8 @@ class Item : public ItemAttributes uint8_t getMiniMapColor() const; wxPoint getDrawOffset() const; + uint16_t getGroundSpeed() const; + bool hasLight() const; SpriteLight getLight() const; diff --git a/source/main_menubar.cpp b/source/main_menubar.cpp index 2b3054a2..64dbe351 100644 --- a/source/main_menubar.cpp +++ b/source/main_menubar.cpp @@ -838,11 +838,12 @@ void MainMenuBar::OnImportMinimap(wxCommandEvent& WXUNUSED(event)) void MainMenuBar::OnExportMinimap(wxCommandEvent& WXUNUSED(event)) { - if(g_gui.GetCurrentEditor()) { - ExportMiniMapWindow dlg(frame, *g_gui.GetCurrentEditor()); - dlg.ShowModal(); - dlg.Destroy(); + if(!g_gui.IsEditorOpen()) { + return; } + + ExportMiniMapWindow dialog(frame, *g_gui.GetCurrentEditor()); + dialog.ShowModal(); } void MainMenuBar::OnDebugViewDat(wxCommandEvent& WXUNUSED(event)) diff --git a/source/tile.cpp b/source/tile.cpp index 2a08a6eb..01c4e15a 100644 --- a/source/tile.cpp +++ b/source/tile.cpp @@ -199,6 +199,14 @@ bool Tile::hasProperty(enum ITEMPROPERTY prop) const return false; } +uint16_t Tile::getGroundSpeed() const noexcept +{ + if(ground && !ground->isMetaItem()) { + return ground->getGroundSpeed(); + } + return 0; +} + int Tile::getIndexOf(Item* item) const { if(!item) diff --git a/source/tile.h b/source/tile.h index 91e8b90b..0c627531 100644 --- a/source/tile.h +++ b/source/tile.h @@ -82,6 +82,8 @@ class Tile int getY() const noexcept { return location->getY(); } int getZ() const noexcept { return location->getZ(); } + uint16_t getGroundSpeed() const noexcept; + public: //Functions // Absorb the other tile into this tile void merge(Tile* other); diff --git a/vcproj/Project/RME.vcxproj b/vcproj/Project/RME.vcxproj index 7c803472..9f5b06f8 100644 --- a/vcproj/Project/RME.vcxproj +++ b/vcproj/Project/RME.vcxproj @@ -220,6 +220,7 @@ + @@ -230,6 +231,7 @@ + From afc96153dd071736855045c487b6198ed183a044 Mon Sep 17 00:00:00 2001 From: Beats Date: Thu, 6 Apr 2023 00:20:54 -0400 Subject: [PATCH 34/45] Fix glitch after drawing secondary map --- source/map_drawer.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index b9365c01..f404b3e1 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -312,16 +312,15 @@ void MapDrawer::DrawMap() bool only_colors = options.isOnlyColors(); bool tile_indicators = options.isTileIndicators(); - // Enable texture mode - if(!only_colors) - glEnable(GL_TEXTURE_2D); - for(int map_z = start_z; map_z >= superend_z; map_z--) { if(options.show_shade) { DrawShade(map_z); } if(map_z >= end_z) { + if(!only_colors) + glEnable(GL_TEXTURE_2D); + int nd_start_x = start_x & ~3; int nd_start_y = start_y & ~3; int nd_end_x = (end_x & ~3) + 4; @@ -377,6 +376,9 @@ void MapDrawer::DrawMap() } } + if(!only_colors) + glDisable(GL_TEXTURE_2D); + DrawPositionIndicator(map_z); } From fc54eec513e8eec1c40eaa110681e827eda96f19 Mon Sep 17 00:00:00 2001 From: Beats Date: Sun, 9 Apr 2023 11:48:36 -0400 Subject: [PATCH 35/45] fix --- source/map_display.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/map_display.cpp b/source/map_display.cpp index 268d9e09..fd5eb1b4 100644 --- a/source/map_display.cpp +++ b/source/map_display.cpp @@ -2523,13 +2523,13 @@ void MapPopupMenu::Update() Append( MAP_POPUP_MENU_SELECT_MONSTER_BRUSH, "Select Monster", "Uses the current monster as a monster brush"); if(topSpawnMonster) - Append( MAP_POPUP_MENU_SELECT_SPAWN_BRUSH, "Select Monster", "Select the npc brush"); + Append( MAP_POPUP_MENU_SELECT_SPAWN_BRUSH, "Select Monster Spawn", "Select the npc brush"); if(topNpc) Append( MAP_POPUP_MENU_SELECT_NPC_BRUSH, "Select Npc", "Uses the current npc as a npc brush"); if(topSpawnNpc) - Append( MAP_POPUP_MENU_SELECT_SPAWN_NPC_BRUSH, "Select Npc", "Select the npc brush"); + Append( MAP_POPUP_MENU_SELECT_SPAWN_NPC_BRUSH, "Select Npc Spawn", "Select the npc brush"); Append( MAP_POPUP_MENU_SELECT_RAW_BRUSH, "Select RAW", "Uses the top item as a RAW brush"); From b22a051579563abc582e637b8b75ceae5da2e673 Mon Sep 17 00:00:00 2001 From: Beats Date: Sat, 24 Jun 2023 17:35:32 -0300 Subject: [PATCH 36/45] Update about_window.cpp --- source/about_window.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/about_window.cpp b/source/about_window.cpp index b38a62fb..d098017e 100644 --- a/source/about_window.cpp +++ b/source/about_window.cpp @@ -24,6 +24,7 @@ #include #include + class GamePanel : public wxPanel { public: GamePanel(wxWindow* parent, int width, int height); From 35986c4cd7d20f96335694fe2727be8b658bfe15 Mon Sep 17 00:00:00 2001 From: Beats Date: Sat, 24 Jun 2023 18:54:12 -0300 Subject: [PATCH 37/45] sonar --- source/action.cpp | 4 ++-- source/items.cpp | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/source/action.cpp b/source/action.cpp index 2a0563f9..1e031ae6 100644 --- a/source/action.cpp +++ b/source/action.cpp @@ -652,7 +652,7 @@ bool ActionQueue::undo() } // Update title - if(batch->isNoSelection() && editor.getMap().doChange()) { + if(batch && batch->isNoSelection() && editor.getMap().doChange()) { g_gui.UpdateTitle(); } return true; @@ -670,7 +670,7 @@ bool ActionQueue::redo() current++; // Update title - if(batch->isNoSelection() && editor.getMap().doChange()) { + if(batch && batch->isNoSelection() && editor.getMap().doChange()) { g_gui.UpdateTitle(); } return true; diff --git a/source/items.cpp b/source/items.cpp index ccd6cd60..f07ccf43 100644 --- a/source/items.cpp +++ b/source/items.cpp @@ -345,7 +345,10 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra break; } - item->weight = *reinterpret_cast(&weight); + double actualWeight; + memcpy(&actualWeight, weight, sizeof(actualWeight)); + + item->weight = actualWeight; break; } @@ -545,6 +548,7 @@ bool ItemDatabase::loadFromOtbVer2(BinaryNode* itemNode, wxString& error, wxArra uint8_t value = 0; if(!itemNode->getU8(value)) { warnings.push_back("Invalid item type property (5)"); + break; } item->alwaysOnTopOrder = value; break; From ad9f892dd37db8b0e2c8657b5d335d4f49a79f6a Mon Sep 17 00:00:00 2001 From: Beats Date: Sat, 24 Jun 2023 23:40:39 -0300 Subject: [PATCH 38/45] fix Minimap and progress bar --- source/gui.h | 1 + source/iominimap.cpp | 19 ++++++++++++++++++- source/items.cpp | 4 +++- source/wall_brush.cpp | 2 +- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/source/gui.h b/source/gui.h index 815af95a..7490fd83 100644 --- a/source/gui.h +++ b/source/gui.h @@ -455,6 +455,7 @@ class GUI int disabled_counter; friend class RenderingLock; + friend class IOMinimap; friend MapTab::MapTab(MapTabbook*, Editor*); friend MapTab::MapTab(const MapTab*); }; diff --git a/source/iominimap.cpp b/source/iominimap.cpp index 12c1d014..b8fa165c 100644 --- a/source/iominimap.cpp +++ b/source/iominimap.cpp @@ -175,6 +175,7 @@ bool IOMinimap::exportMinimap(const std::string& directory) rect.height = 0; } + int totalTiles = 0; for(auto it = map.begin(); it != map.end(); ++it) { auto tile = (*it)->get(); if(!tile || (!tile->ground && tile->items.empty())) { @@ -195,6 +196,7 @@ bool IOMinimap::exportMinimap(const std::string& directory) if (position.y > rect.height) { rect.height = position.y; } + totalTiles++; } constexpr int image_size = 1024; @@ -202,6 +204,8 @@ bool IOMinimap::exportMinimap(const std::string& directory) uint8_t* pixels = new uint8_t[pixels_size]; auto image = new wxImage(image_size, image_size, pixels, true); + int processedTiles = 0; + int lastShownProgress = -1; for(size_t z = min_z; z <= max_z; z++) { auto& rect = bounds[z]; if(rect.IsEmpty()) { @@ -225,6 +229,16 @@ bool IOMinimap::exportMinimap(const std::string& directory) index += rme::PixelFormatRGB; continue; } + + processedTiles++; + int progress = static_cast((static_cast(processedTiles) / totalTiles) * 100); + if (progress > lastShownProgress) { + if (m_updateLoadbar) { + g_gui.SetLoadDone(progress); + } + lastShownProgress = progress; + } + uint8_t color = tile->getMiniMapColor(); pixels[index ] = (uint8_t)(static_cast(color / 36) % 6 * 51); // red pixels[index+1] = (uint8_t)(static_cast(color / 6) % 6 * 51); // green @@ -238,7 +252,8 @@ bool IOMinimap::exportMinimap(const std::string& directory) image->SetData(pixels, true); wxString extension = m_format == MinimapExportFormat::Png ? "png" : "bmp"; wxBitmapType type = m_format == MinimapExportFormat::Png ? wxBITMAP_TYPE_PNG : wxBITMAP_TYPE_BMP; - wxFileName file = wxString::Format("%d-%d-%d.%s", h, w, z, extension); + wxString extension_wx = wxString::FromAscii(extension.mb_str()); + wxFileName file = wxString::Format("%s-%s-%s.%s", std::to_string(h), std::to_string(w), std::to_string(z), extension_wx); file.Normalize(wxPATH_NORM_ALL, directory); image->SaveFile(file.GetFullPath(), type); } @@ -246,11 +261,13 @@ bool IOMinimap::exportMinimap(const std::string& directory) } } + g_gui.DestroyLoadBar(); image->Destroy(); delete[] pixels; return true; } + bool IOMinimap::exportSelection(const std::string& directory, const std::string& name) { int min_x = rme::MapMaxWidth + 1; diff --git a/source/items.cpp b/source/items.cpp index f07ccf43..d7ba4aad 100644 --- a/source/items.cpp +++ b/source/items.cpp @@ -698,8 +698,10 @@ bool ItemDatabase::loadFromOtbVer3(BinaryNode* itemNode, wxString& error, wxArra } uint8_t value; - if(!itemNode->getU8(value)) + if(!itemNode->getU8(value)) { warnings.push_back("Invalid item type property (5)"); + break; + } item->alwaysOnTopOrder = value; break; diff --git a/source/wall_brush.cpp b/source/wall_brush.cpp index 71779011..073b06b8 100644 --- a/source/wall_brush.cpp +++ b/source/wall_brush.cpp @@ -693,7 +693,7 @@ void WallDecorationBrush::draw(BaseMap* map, Tile* tile, void* parameter) if(dt.type == doortype) { ASSERT(dt.id); const ItemType& type = g_items.getItemType(dt.id); - ASSERT(it.id != 0); + ASSERT(dt.id != 0); if(type.isOpen == open) { id = dt.id; From f627fe1f933891cdb1ea303511e58439baf92657 Mon Sep 17 00:00:00 2001 From: Beats Date: Sun, 25 Jun 2023 00:23:36 -0300 Subject: [PATCH 39/45] fix erro load items.xml --- source/items.cpp | 18 +++++++++++------- source/items.h | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/source/items.cpp b/source/items.cpp index d7ba4aad..d65e34f4 100644 --- a/source/items.cpp +++ b/source/items.cpp @@ -799,10 +799,11 @@ bool ItemDatabase::loadItemFromGameXml(pugi::xml_node itemNode, uint16_t id) return true; } - if(!isValidID(id)) - return false; + // Não verificar isValidID se o ID estiver entre 1 e 18, mas verificar para outros IDs. + if(!(id >= 1 && id <= 18) && !isValidID(id)) + return false; - ItemType& item = *items[id]; + ItemType& item = getItemType(id); item.name = itemNode.attribute("name").as_string(); item.editorsuffix = itemNode.attribute("editorsuffix").as_string(); @@ -998,13 +999,16 @@ bool ItemDatabase::loadMetaItem(pugi::xml_node node) return false; } -const ItemType& ItemDatabase::getItemType(uint16_t id) const +ItemType& ItemDatabase::getItemType(uint16_t id) { - if(id == 0 || id > maxItemId) + if(id == 0 || id > maxItemId) { return dummy; + } - const ItemType* type = items[id]; - if(type) return *type; + ItemType* type = items[id]; + if(type) { + return *type; + } return dummy; } diff --git a/source/items.h b/source/items.h index 8eeff166..59674bb5 100644 --- a/source/items.h +++ b/source/items.h @@ -363,7 +363,7 @@ class ItemDatabase uint16_t getMinID() const noexcept { return 100; } uint16_t getMaxID() const noexcept { return maxItemId; } - const ItemType& getItemType(uint16_t id) const; + ItemType& getItemType(uint16_t id); ItemType* getRawItemType(uint16_t id); bool isValidID(uint16_t id) const; From 40f9c07efe9da1489bf347cc90c0a0f195c2a2f6 Mon Sep 17 00:00:00 2001 From: Beats Date: Tue, 27 Jun 2023 23:02:34 -0300 Subject: [PATCH 40/45] fix --- data/menubar.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/data/menubar.xml b/data/menubar.xml index 3962837b..2d1eb472 100644 --- a/data/menubar.xml +++ b/data/menubar.xml @@ -139,7 +139,11 @@ - + + + + + From 895c5df607ab5d92ab32da56469857e572ef4347 Mon Sep 17 00:00:00 2001 From: Majesty <32709570+majestyotbr@users.noreply.github.com> Date: Fri, 29 Sep 2023 18:41:22 -0300 Subject: [PATCH 41/45] fix doodad brush --- source/doodad_brush.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/doodad_brush.cpp b/source/doodad_brush.cpp index 7707a9ff..a1bf7de5 100644 --- a/source/doodad_brush.cpp +++ b/source/doodad_brush.cpp @@ -94,7 +94,7 @@ bool DoodadBrush::loadAlternative(pugi::xml_node node, wxArrayString& warnings, } ItemType* type = g_items.getRawItemType(item->getID()); - if(!type) { + if(type) { type->doodad_brush = this; } @@ -152,7 +152,7 @@ bool DoodadBrush::loadAlternative(pugi::xml_node node, wxArrayString& warnings, items.push_back(item); ItemType* type = g_items.getRawItemType(item->getID()); - if(!type) { + if(type) { type->doodad_brush = this; } } From 8ff1e8e2a2f81c76ec49e9c483cd397419b4eb78 Mon Sep 17 00:00:00 2001 From: Luan Santos Date: Mon, 4 Sep 2023 11:08:59 -0700 Subject: [PATCH 42/45] fix: slightly more accurate house size estimation --- .gitignore | 1 + source/house.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 473f5610..98ca7bbc 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ vcproj/Project/x64/ vcproj/Installer/Beta Release/ vcproj/Installer/Debug/ vcproj/Installer/Release/ +vcpkg_installed/ .vscode/ *.filters *.users diff --git a/source/house.cpp b/source/house.cpp index b25aef2a..e1dccc65 100644 --- a/source/house.cpp +++ b/source/house.cpp @@ -108,8 +108,9 @@ size_t House::size() const { size_t count = 0; for(PositionList::const_iterator pos_iter = tiles.begin(); pos_iter != tiles.end(); ++pos_iter) { - Tile* tile = map->getTile(*pos_iter); - if(tile && !tile->isBlocking()) + auto tile = map->getTile(*pos_iter); + auto topItem = tile->getTopItem(); + if(tile && (!tile->getWall() || tile->getTable() || topItem->isDoor())) ++count; } return count; From 40f1edc70f17c423282d546a41541a8fe9b92dcc Mon Sep 17 00:00:00 2001 From: Majesty <32709570+majestyotbr@users.noreply.github.com> Date: Fri, 29 Sep 2023 19:03:08 -0300 Subject: [PATCH 43/45] feat: update items.otb and items.xml --- data/items/items.otb | Bin 1673339 -> 1849211 bytes data/items/items.xml | 26903 +++++++++++++++++++++++++++++++++++------ 2 files changed, 23355 insertions(+), 3548 deletions(-) diff --git a/data/items/items.otb b/data/items/items.otb index 9fecdc9df2436c08eac35f6b33896d5e19f10b6d..c064af60fb133fdbb07ade5354c74a553ca69be3 100644 GIT binary patch delta 120508 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 p@opUN#_>?SwT`opY4iQ{MFKKb$E{{bzE)}#Oc delta 534 zcmezUuHg5Cw1yVO7N#xC-?SxlnHcU02?;WkXO<*qq!z0yBqtUq6c^-|O#i0MypW&4 zfq{WRfQjLukRXVd9M~&9UEmHM$M&;2%%x0x2@u)0AlbJ<(;27nh_t8ZGjC7PXPL(@ z0W>>OQb>RyIio1ExFk2RSRtt>F)ulzoyneMJCi-D&k1>u**lbhx_2lm2rvkQygASJ z_rJu=2{tdj@L%toIX#!1OULHi z0ny^=IrBt0*k-2y9X5OV!y^LX(+@~&fmjHLg@ITEh(&=|42Z?I z2kw`6T+0lMj_KyMlJe7|0y(*+r`Sq*f2oiNac#eAEBRX*B6vR%DA>yb m6y%7K%#afjW=P7fP)IAy$x+BpQ%Fk8$=TjqA-S5L@jn38*|vrN diff --git a/data/items/items.xml b/data/items/items.xml index f54b66c8..1e33fc81 100644 --- a/data/items/items.xml +++ b/data/items/items.xml @@ -1,46 +1,48 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + + + - - - + + + + + + @@ -60,46 +62,58 @@ + + + + + + + + - + + + + + @@ -110,19 +124,24 @@ + + + + + @@ -137,27 +156,33 @@ + + + + + + @@ -167,84 +192,112 @@ + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + @@ -253,11 +306,19 @@ - - + + + + + + - - + + + + + + @@ -267,27 +328,46 @@ + - + + + - + + + - - - - - - + + + + + + + + + + + + + + + + + + + + @@ -297,39 +377,60 @@ - - - - + + + + + + + + + + + + + + + - + + - + + - - + + + + + + + - + + + + @@ -391,8 +492,11 @@ - + + + + @@ -428,19 +532,25 @@ - + + + + - + + + + @@ -464,24 +574,28 @@ + + + + @@ -586,30 +700,43 @@ + + + + + + - - + + + + + + + - + + + @@ -619,8 +746,12 @@ - - + + + + + + @@ -628,7 +759,9 @@ - + + + @@ -636,19 +769,23 @@ + + + + @@ -658,6 +795,7 @@ + @@ -667,92 +805,148 @@ + + + + + - - - + + + + + + + + + + - - + + + + + + - + + + + + - + + + - + + + + + + - - + + + + + + - + + + + - - - + + + + + + + + + - + + + + - - - - + + + + + + + + + + + + + - - + + + + + + @@ -760,23 +954,38 @@ - + + + - + + + + - + + + - - + + + + + + - - + + + + + + @@ -785,7 +994,9 @@ - + + + @@ -793,7 +1004,9 @@ - + + + @@ -808,9 +1021,13 @@ - + + + - + + + @@ -820,44 +1037,58 @@ + - + + + - - + + + + + + + + + + + + + @@ -879,28 +1110,38 @@ + + + + + + + + + + @@ -909,12 +1150,18 @@ + + + + + + @@ -937,486 +1184,892 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + @@ -1424,8 +2077,16 @@ + + + + + + + + @@ -1433,8 +2094,16 @@ + + + + + + + + @@ -1442,24 +2111,43 @@ + + + + + + + + + + + + + + + + + + + @@ -1488,6 +2176,7 @@ + @@ -1495,267 +2184,560 @@ + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1763,15 +2745,27 @@ + + + + + + + + + + + + @@ -1779,102 +2773,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + @@ -1882,13 +2952,16 @@ + - - - + + - + + + + @@ -1926,6 +2999,7 @@ + @@ -1933,29 +3007,48 @@ - - - + + + + + + + + + + - + + + + + + + + + + + - + + + @@ -1964,16 +3057,23 @@ + + + + + + + @@ -1989,36 +3089,55 @@ + + + + + + + + + + + - + + + + + + + + + @@ -2033,56 +3152,70 @@ - - + + + + - + + + + + + + + + + + + + @@ -2102,9 +3235,11 @@ + + @@ -2119,127 +3254,283 @@ - - - + + + + + + + + + - - - - - + + + + + + + + + + + + + + + - + + + + - + + + + - + + + - - + + + + + + + - + + + - + + + - - - + + + + + + + + + - + + + + - - - - + + + + + + + + + + + + - - - - + + + + + + + + + + + + - + + + - - - - + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + @@ -2500,53 +3791,99 @@ - - + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + - + + + + - + + + + - + + + - - - + + + + + + + + + + + + + + + - - - + + + + + + + + + - - + + + + + + @@ -2557,28 +3894,46 @@ - + + + - + + + + + + - - + + + + + + - - + + + + + + - + + + + @@ -2603,6 +3958,7 @@ + @@ -2623,7 +3979,9 @@ - + + + @@ -2641,33 +3999,48 @@ + + + - + + + + + - + + + + - - + + + + + + + @@ -2675,64 +4048,113 @@ - - - + + + + + + + + + - + + + + + + + + - - + + - - + + + + + + + + - + + + - - - - + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + @@ -2742,31 +4164,62 @@ - - - - - + + + + + + + + + + + + + + + - - + + + + + + - - + + + + + + + - - + + + + + + - - - - + + + + + + + + + + + + @@ -2776,6 +4229,9 @@ + + + @@ -2786,21 +4242,30 @@ + + + + + + - + + + + @@ -2810,6 +4275,9 @@ + + + @@ -2819,6 +4287,9 @@ + + + @@ -2828,11 +4299,17 @@ + + + + + + @@ -2842,8 +4319,12 @@ + + + + @@ -2852,15 +4333,25 @@ + + + + + + + + + + @@ -2881,14 +4372,21 @@ + + + + + + + @@ -2897,6 +4395,9 @@ + + + @@ -2906,12 +4407,20 @@ + + + + + + + + @@ -2919,8 +4428,12 @@ + + + + @@ -2928,9 +4441,13 @@ + + + + @@ -2940,6 +4457,7 @@ + @@ -2948,45 +4466,76 @@ + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + - - - - + + + + + + + + + + + + @@ -3003,209 +4552,331 @@ - - - - + + + + + + + + + + + + - - - - + + + + + + + + + + + + - + + + - - - - - - + + + + + + + + + + + + + + + + + + + - - + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + - - - + + + + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + - + + + + @@ -3225,612 +4896,860 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + + + + - + + + - - - - + + + + + + + + + + + + + - - + + + + + + + + + - - + + + + + + + + + + - - + + + + + + - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - - - + + + + + + + + + - + + + - + + + - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3838,12 +5757,14 @@ + + @@ -3856,6 +5777,7 @@ + @@ -3863,6 +5785,7 @@ + @@ -3870,6 +5793,7 @@ + @@ -3884,10 +5808,12 @@ + + @@ -3896,16 +5822,19 @@ + + + @@ -3943,7 +5872,6 @@ - @@ -3980,177 +5908,268 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -4179,52 +6198,74 @@ + + + + + + - + + + + + - - - - + + + + + + + + + + + + + + + + @@ -4237,6 +6278,7 @@ + @@ -4246,302 +6288,470 @@ + + + + + + + + + - - - - + + + + + + + + + + + + + + - + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + @@ -4550,87 +6760,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -4638,9 +6882,9 @@ + - @@ -4650,66 +6894,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -4721,57 +7006,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -4779,6 +7131,16 @@ + + + + + + + + + + @@ -4786,6 +7148,16 @@ + + + + + + + + + + @@ -4793,6 +7165,16 @@ + + + + + + + + + + @@ -4800,49 +7182,83 @@ + + + + + + + + + + - + + + + + + + + + + + + + + - + + + + + + + + + + + + + - @@ -4852,29 +7268,45 @@ + + + + + + + + + + + + + + + + @@ -4882,16 +7314,24 @@ + + + + + + + + @@ -4899,8 +7339,13 @@ + + + + + @@ -4911,71 +7356,108 @@ + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -4983,6 +7465,9 @@ + + + @@ -4995,28 +7480,41 @@ + + + + + + + + + + + + + @@ -5026,45 +7524,58 @@ + + + + + + + + + + + + + @@ -5080,24 +7591,32 @@ + + + - + + + + + + @@ -5109,22 +7628,26 @@ + + + + @@ -5141,32 +7664,38 @@ + + + + + + @@ -5177,182 +7706,215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5360,37 +7922,50 @@ + + + + + + + + - + + + + + + @@ -5400,26 +7975,32 @@ + + + + + + @@ -5431,51 +8012,69 @@ + + + + + + + + + + - + + + + - + + + + + + @@ -5483,55 +8082,65 @@ + + + + + + + + + + @@ -5542,21 +8151,33 @@ + + + - + + + + + + + - + + + + @@ -5564,6 +8185,7 @@ + @@ -5577,39 +8199,51 @@ + + + + + + + + + + + + @@ -5622,47 +8256,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5676,57 +8352,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5739,8 +8462,16 @@ + + + + + + + + @@ -5748,8 +8479,15 @@ + + + + + + + @@ -5763,21 +8501,39 @@ + + + + + + + + + + + + + + + + + + @@ -5785,28 +8541,50 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -5820,45 +8598,82 @@ + + + + + + + + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + + + + + @@ -5872,46 +8687,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5924,8 +8775,14 @@ + + + + + + @@ -5939,8 +8796,15 @@ + + + + + + + @@ -5954,40 +8818,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -6001,14 +8898,26 @@ + + + + + + + + + + + + @@ -6021,8 +8930,15 @@ + + + + + + + @@ -6036,22 +8952,43 @@ + + + + + + + + + + + + + + + + + + + + + @@ -6064,14 +9001,26 @@ + + + + + + + + + + + + @@ -6084,8 +9033,15 @@ + + + + + + + @@ -6098,8 +9054,15 @@ + + + + + + + @@ -6113,8 +9076,15 @@ + + + + + + + @@ -6122,8 +9092,15 @@ + + + + + + + @@ -6132,14 +9109,26 @@ + + + + + + + + + + + + @@ -6152,8 +9141,15 @@ + + + + + + + @@ -6167,14 +9163,26 @@ + + + + + + + + + + + + @@ -6186,31 +9194,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + @@ -6225,6 +9262,12 @@ + + + + + + @@ -6240,8 +9283,16 @@ + + + + + + + + @@ -6254,15 +9305,29 @@ + + + + + + + + + + + + + + @@ -6275,28 +9340,51 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -6309,8 +9397,15 @@ + + + + + + + @@ -6324,8 +9419,15 @@ + + + + + + + @@ -6339,8 +9441,15 @@ + + + + + + + @@ -6353,16 +9462,31 @@ + + + + + + + + + + + + + + + @@ -6375,37 +9499,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -6418,51 +9572,81 @@ + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -6474,12 +9658,20 @@ + + + + + + + + @@ -6491,24 +9683,46 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -6520,8 +9734,12 @@ + + + + @@ -6533,17 +9751,30 @@ + + + + + + + + + + + + + @@ -6554,8 +9785,12 @@ + + + + @@ -6567,44 +9802,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -6616,8 +9893,12 @@ + + + + @@ -6629,20 +9910,38 @@ + + + + + + + + + + + + + + + + + + @@ -6653,8 +9952,12 @@ + + + + @@ -6666,8 +9969,13 @@ + + + + + @@ -6679,8 +9987,12 @@ + + + + @@ -6692,16 +10004,28 @@ + + + + + + + + + + + + @@ -6712,8 +10036,12 @@ + + + + @@ -6725,8 +10053,12 @@ + + + + @@ -6737,8 +10069,12 @@ + + + + @@ -6751,12 +10087,22 @@ + + + + + + + + + + @@ -6768,8 +10114,12 @@ + + + + @@ -6782,13 +10132,21 @@ + + + + + + + + @@ -6800,25 +10158,45 @@ + + + + + + + + + + + + + + + + + + + + @@ -6830,20 +10208,35 @@ + + + + + + + + + + + + + + + @@ -6854,8 +10247,12 @@ + + + + @@ -6868,28 +10265,48 @@ + + + + + + + + + + + + + + + + + + + + @@ -6903,13 +10320,21 @@ + + + + + + + + @@ -6922,14 +10347,21 @@ + + + + + + + @@ -6942,8 +10374,12 @@ + + + + @@ -6956,8 +10392,12 @@ + + + + @@ -6971,13 +10411,21 @@ + + + + + + + + @@ -6991,14 +10439,22 @@ + + + + + + + + @@ -7012,23 +10468,39 @@ + + + + + + + + - + + + + + + + + + @@ -7041,19 +10513,31 @@ + + + + + + + + + + + + @@ -7066,13 +10550,21 @@ + + + + + + + + @@ -7085,8 +10577,12 @@ + + + + @@ -7100,8 +10596,12 @@ + + + + @@ -7114,8 +10614,12 @@ + + + + @@ -7128,8 +10632,12 @@ + + + + @@ -7142,13 +10650,21 @@ + + + + + + + + @@ -7162,18 +10678,30 @@ + + + + + + + + + + + + @@ -7186,13 +10714,21 @@ + + + + + + + + @@ -7205,29 +10741,49 @@ + + + + + + + + + + + + + + + + + + + + @@ -7236,6 +10792,7 @@ + @@ -7244,87 +10801,124 @@ + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + @@ -7332,24 +10926,31 @@ + + + + + + + @@ -7365,59 +10966,84 @@ + - + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + @@ -7445,6 +11071,7 @@ + @@ -7470,95 +11097,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -7571,25 +11270,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -7600,109 +11323,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -7712,231 +11477,450 @@ + + - + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + - + + + + + - - + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - + + + + + - - - - - + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + - - - - - + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + - + + + - - - - - + + + + + + + + + + + + + + + - - - + + + + + + + + + - + + + - - - + + + + + + + + + - + + + @@ -8143,7 +12127,6 @@ - @@ -8164,10 +12147,16 @@ - + + + + + + + @@ -8252,14 +12241,18 @@ + + - + + + @@ -8274,8 +12267,12 @@ - - + + + + + + @@ -8315,7 +12312,6 @@ - @@ -8353,6 +12349,7 @@ + @@ -8370,6 +12367,7 @@ + @@ -8484,6 +12482,7 @@ + @@ -8565,6 +12564,7 @@ + @@ -8617,11 +12617,11 @@ + - @@ -8698,7 +12698,9 @@ - + + + @@ -8717,7 +12719,9 @@ - + + + @@ -8734,7 +12738,6 @@ - @@ -9319,19 +13322,16 @@ - - - @@ -9392,7 +13392,6 @@ - @@ -9458,7 +13457,7 @@ - + @@ -9576,11 +13575,13 @@ + + @@ -9957,20 +13958,35 @@ - + + + - - + + + + + + - + + + - + + + - - + + + + + + + @@ -9978,6 +13994,7 @@ + @@ -9985,6 +14002,7 @@ + @@ -9993,6 +14011,7 @@ + @@ -10001,6 +14020,7 @@ + @@ -10009,38 +14029,52 @@ + + - + + + + - + + + + - + + + + - + + + + @@ -10051,6 +14085,7 @@ + @@ -10058,10 +14093,12 @@ + + @@ -10069,14 +14106,20 @@ + + + + + + @@ -10085,16 +14128,20 @@ + + + + @@ -10109,44 +14156,55 @@ + + + + + + + + + - + + + @@ -10180,18 +14238,26 @@ + + - + + + - + + + - + + + @@ -10208,24 +14274,52 @@ - + + + - + + + - + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -10233,6 +14327,7 @@ + @@ -10240,9 +14335,13 @@ - + + + - + + + @@ -10252,57 +14351,89 @@ - - + + + + + + + - + + + + + + - - + + + + + + - + + + + - + + + + - + + + + - + + + + - - + + + + + + - + + + @@ -10310,21 +14441,37 @@ + - + + + + - - - - - + + + + + + + + + + + + + + + + + @@ -10345,14 +14492,17 @@ + + + @@ -10361,12 +14511,18 @@ + - - + + + + + + + @@ -10553,12 +14709,20 @@ - - + + + + + + - - + + + + + + @@ -10568,8 +14732,12 @@ - - + + + + + + @@ -10639,152 +14807,275 @@ + - + + + + - + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - + + + - + + + - + + + - + + + - - - + + + + + + + + + - - - - + + + + + + + + + + + + - - - - + + + + + + + + + + + + - + + + - + + + - + + + - + + + + + + + + + + + + + - + + + + - + + + + - - - + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - - + + + + + + + + @@ -10803,8 +15094,12 @@ - - + + + + + + @@ -10836,6 +15131,7 @@ + @@ -10843,6 +15139,7 @@ + @@ -10912,22 +15209,41 @@ - - + + + + + + + + - + + + + - - - - - + + + + + + + + + + + + + + + @@ -10949,17 +15265,34 @@ - - - - - - + + + + + + + + + + + + + + + + + + + - - + + + + + + @@ -10994,15 +15327,33 @@ - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -11019,29 +15370,48 @@ + + - - + + + + + + + - - + + + + + + - - - - + + + + + + + + + + + + @@ -11059,16 +15429,25 @@ + - - + + + + + + + - + + + + @@ -11091,7 +15470,9 @@ - + + + @@ -11117,11 +15498,15 @@ - + + + + + @@ -11132,8 +15517,13 @@ + + + + + + - @@ -11154,18 +15544,26 @@ - + + + + - + + + + - + + + @@ -11181,26 +15579,41 @@ - - + + + + + + - - + + + + + + + - - + + + + + + + + @@ -11210,24 +15623,31 @@ + + + + + + + @@ -11236,22 +15656,33 @@ + + + + + + + + + + + @@ -11260,20 +15691,24 @@ + + + + @@ -11281,58 +15716,82 @@ - + + + + - - - + + + + + + + + + + - - + + + + + + + + + + + + + + + + @@ -11357,10 +15816,12 @@ + + @@ -11368,66 +15829,85 @@ + + + + + + + + + + + + + + + + + + + @@ -11449,54 +15929,81 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -11531,6 +16038,7 @@ + @@ -11543,14 +16051,17 @@ + + + @@ -11558,14 +16069,17 @@ + + + @@ -11573,48 +16087,63 @@ + + + + + + + + + + + + + + + + - @@ -11754,7 +16283,6 @@ - @@ -11796,7 +16324,6 @@ - @@ -11814,7 +16341,6 @@ - @@ -11832,7 +16358,6 @@ - @@ -11857,7 +16382,6 @@ - @@ -11886,20 +16410,17 @@ - - - @@ -11912,49 +16433,42 @@ - - - - - - - @@ -11967,7 +16481,6 @@ - @@ -11980,7 +16493,6 @@ - @@ -12201,14 +16713,12 @@ - - @@ -12263,6 +16773,7 @@ + @@ -12292,7 +16803,6 @@ - @@ -12351,11 +16861,12 @@ - + + @@ -12375,32 +16886,47 @@ + + + - + + + + + + + + + + + + + @@ -12415,14 +16941,21 @@ + + + + + + + @@ -12433,31 +16966,37 @@ + + + + + + @@ -12467,31 +17006,44 @@ + + + + + + + + + + + + + + - - + @@ -12500,6 +17052,7 @@ + @@ -12507,23 +17060,36 @@ + + + + + + + + + + - - + + - + + + + @@ -12596,11 +17162,17 @@ - + + + - - + + + + + + @@ -12670,39 +17242,60 @@ - + + + + - + + + + + + - - - - + + + + + + + + + + + + + + + + + @@ -12712,6 +17305,9 @@ + + + @@ -12965,6 +17561,7 @@ + @@ -12980,34 +17577,42 @@ + + + + + + + + @@ -13032,49 +17637,63 @@ + + + + + + - + + + + + - + + + + + @@ -13088,22 +17707,34 @@ + + + + + + - + - + + + - + + + + + @@ -13117,53 +17748,100 @@ + + + + + - + + - + + + + + + - + + + + + + + + - + - + + + + + - + + + + + - + + + + + - + + + + + - + + + + + - - + + + + + + + + + + + @@ -13171,9 +17849,11 @@ + + @@ -13185,34 +17865,43 @@ + + + + + + + + + @@ -13220,14 +17909,17 @@ + + + @@ -13236,12 +17928,15 @@ + + + @@ -13251,9 +17946,11 @@ + + @@ -13272,14 +17969,19 @@ + - + + + + + @@ -13297,28 +17999,51 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -13361,20 +18086,25 @@ + + + + + @@ -13384,6 +18114,7 @@ + @@ -13396,6 +18127,13 @@ + + + + + + + @@ -13412,34 +18150,43 @@ + - + + + + + + + + + @@ -13448,118 +18195,172 @@ + + + + + + + + - + + + + + + + + + + + + + + + + + + - - + + + + + + - + + + - - - - + + + + + + + + + + + + + - - + + + + + + - - + + + + + + - - + + + + + + + + @@ -13596,16 +18397,34 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - + + + + + + @@ -13696,35 +18515,67 @@ - - + + + + + + - - - - + + + + + + + + + + + + + + - - - + + + + + + + + + - - - + + + + + + + + + + + + + - + + + @@ -13798,6 +18649,7 @@ + @@ -13814,10 +18666,16 @@ - - + + + + + + - + + + @@ -13838,69 +18696,108 @@ - - - + + + + + + + + + - + + + - - - + + + + + + + + + + + + + + - + + + - - - - + + + + + + + + + + + + + + + + - + + + + + + + @@ -13908,16 +18805,23 @@ + - - + + + + + + - + + + @@ -13928,14 +18832,16 @@ + - + + @@ -13948,32 +18854,39 @@ + + + + + + + @@ -13993,6 +18906,7 @@ + @@ -14001,15 +18915,21 @@ + - + + + - + + + + @@ -14037,18 +18957,31 @@ + + - - - - - + + + + + + + + + + + + + + + + @@ -14057,6 +18990,7 @@ + @@ -14200,15 +19134,23 @@ + + + + + + + + @@ -14229,58 +19171,104 @@ - + + + + - + + + - + + + - - - + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -14288,32 +19276,54 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -14348,12 +19358,20 @@ + + + + + + + + @@ -14362,8 +19380,15 @@ + + + + + + + @@ -14377,15 +19402,30 @@ + + + + + + + + + + + + + + + @@ -14398,8 +19438,16 @@ + + + + + + + + @@ -14412,8 +19460,15 @@ + + + + + + + @@ -14427,8 +19482,15 @@ + + + + + + + @@ -14441,30 +19503,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -14478,6 +19569,12 @@ + + + + + + @@ -14486,8 +19583,15 @@ + + + + + + + @@ -14500,8 +19604,16 @@ + + + + + + + + @@ -14515,35 +19627,51 @@ + + + + + + + + + + + + + + + + @@ -14556,8 +19684,16 @@ + + + + + + + + @@ -14570,8 +19706,16 @@ + + + + + + + + @@ -14584,8 +19728,15 @@ + + + + + + + @@ -14598,8 +19749,16 @@ + + + + + + + + @@ -14613,8 +19772,16 @@ + + + + + + + + @@ -14627,8 +19794,16 @@ + + + + + + + + @@ -14641,13 +19816,26 @@ + + + + + + + + + + + + + @@ -14661,13 +19849,26 @@ + + + + + + + + + + + + + @@ -14682,15 +19883,30 @@ + + + + + + + + + + + + + + + @@ -14704,8 +19920,16 @@ + + + + + + + + @@ -14719,8 +19943,15 @@ + + + + + + + @@ -14733,8 +19964,15 @@ + + + + + + + @@ -14747,8 +19985,15 @@ + + + + + + + @@ -14761,8 +20006,15 @@ + + + + + + + @@ -14775,6 +20027,12 @@ + + + + + + @@ -14782,8 +20040,15 @@ + + + + + + + @@ -14795,15 +20060,29 @@ + + + + + + + + + + + + + + @@ -14816,8 +20095,16 @@ + + + + + + + + @@ -14830,15 +20117,29 @@ + + + + + + + + + + + + + + @@ -14851,24 +20152,46 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -14882,8 +20205,15 @@ + + + + + + + @@ -14896,8 +20226,15 @@ + + + + + + + @@ -14910,22 +20247,43 @@ + + + + + + + + + + + + + + + + + + + + + @@ -14939,8 +20297,15 @@ + + + + + + + @@ -14953,15 +20318,30 @@ + + + + + + + + + + + + + + + @@ -14974,8 +20354,15 @@ + + + + + + + @@ -14990,35 +20377,47 @@ + + + + + + + + + + + + @@ -15026,11 +20425,19 @@ + + + + + + + + @@ -15038,8 +20445,16 @@ + + + + + + + + @@ -15051,8 +20466,15 @@ + + + + + + + @@ -15065,8 +20487,16 @@ + + + + + + + + @@ -15079,15 +20509,31 @@ + + + + + + + + + + + + + + + + @@ -15100,8 +20546,15 @@ + + + + + + + @@ -15113,15 +20566,26 @@ + + + + + + + - + + + + + @@ -15133,13 +20597,20 @@ + + + + + + + @@ -15152,16 +20623,28 @@ + + + + + + + + + + + + @@ -15174,43 +20657,70 @@ + + + + + + + + - + + + + - - + + + + + + - + + + - + + + - + + + + - - + + + + + + + @@ -15223,12 +20733,17 @@ + + + + + @@ -15276,53 +20791,79 @@ + + + + + - + + + - - - + + + + + + + + + - + + + - + + + - + + + + + + - + + + - + + + @@ -15397,10 +20938,15 @@ - - + + + + + + + @@ -15410,6 +20956,7 @@ + @@ -15418,21 +20965,31 @@ - + + + + - + + + + + + + + @@ -15441,9 +20998,11 @@ + + @@ -15461,79 +21020,138 @@ + - - + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + + + + + + + + - - + + + + + + - - - - + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + - + + + + + + + + + @@ -15541,7 +21159,9 @@ - + + + @@ -15551,6 +21171,7 @@ + @@ -15571,67 +21192,91 @@ + - + + + + - + + + + + + + + + + - - + + + + + + + + - + + + - + + + + @@ -15663,29 +21308,36 @@ + + + + + + + @@ -15701,12 +21353,18 @@ - + + + + - + + + + @@ -15714,59 +21372,87 @@ + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + @@ -15780,8 +21466,16 @@ + + + + + + + + @@ -15795,8 +21489,16 @@ + + + + + + + + @@ -15811,6 +21513,13 @@ + + + + + + + @@ -15827,6 +21536,13 @@ + + + + + + + @@ -15842,8 +21558,16 @@ + + + + + + + + @@ -15858,8 +21582,16 @@ + + + + + + + + @@ -15874,6 +21606,13 @@ + + + + + + + @@ -15882,14 +21621,22 @@ + + + + + + + + - + @@ -15897,6 +21644,13 @@ + + + + + + + @@ -15905,24 +21659,44 @@ + + + + + + + + + - - - + + + + + + + + + + + + + + @@ -15930,123 +21704,242 @@ + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -16061,20 +21954,37 @@ + + + + + + + + + + + + + + + + + @@ -16087,18 +21997,31 @@ + + + + - + + + + + + + + + + + + - - - - + + @@ -16110,11 +22033,16 @@ + + + + + - - + + @@ -16126,35 +22054,62 @@ + + + + + - - + + + + + + + - - + + + + + + + - - + + + + + + + + + + + + + + @@ -16162,25 +22117,43 @@ + + + + + + + + + + + + - + + + + + + + @@ -16191,8 +22164,14 @@ + + + + + + @@ -16203,8 +22182,19 @@ + + + + + + + + + + + @@ -16215,23 +22205,50 @@ + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + @@ -16245,6 +22262,16 @@ + + + + + + + + + + @@ -16257,6 +22284,16 @@ + + + + + + + + + + @@ -16269,12 +22306,28 @@ + + + + + + + + + + + + + + + + @@ -16287,8 +22340,15 @@ + + + + + + + @@ -16301,8 +22361,15 @@ + + + + + + + @@ -16315,15 +22382,30 @@ + + + + + + + + + + + + + + + @@ -16336,6 +22418,12 @@ + + + + + + @@ -16350,8 +22438,16 @@ + + + + + + + + @@ -16364,6 +22460,12 @@ + + + + + + @@ -16378,6 +22480,12 @@ + + + + + + @@ -16385,6 +22493,13 @@ + + + + + + + @@ -16452,6 +22567,7 @@ + @@ -16524,7 +22640,9 @@ - + + + @@ -16586,26 +22704,34 @@ + + - + + + + + + + @@ -16626,26 +22752,31 @@ + + + + + @@ -16653,33 +22784,40 @@ + + + + + + + @@ -16700,19 +22838,25 @@ - + + + + + + + @@ -16728,32 +22872,52 @@ + + + - + + + - - - + + + + + + + + + + - - - - + + + + + + + + + + + + @@ -16814,24 +22978,47 @@ - - + + + + + + + - - - - + + + + + + + + + + + + - - + + + + + + - - - + + + + + + + + + @@ -16885,101 +23072,205 @@ - - - - - - + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + - - - + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + - - + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + + + - - - + + + + + + + + + + - + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + + + + + - - + + + + + + - + + + - + + + - + + + @@ -16988,6 +23279,7 @@ + @@ -17008,8 +23300,12 @@ - - + + + + + + @@ -17022,8 +23318,12 @@ - - + + + + + + @@ -17040,6 +23340,7 @@ + @@ -17055,10 +23356,18 @@ - - - - + + + + + + + + + + + + @@ -17078,17 +23387,26 @@ + - - - + + + + + + + + + + + @@ -17099,6 +23417,7 @@ + @@ -17108,6 +23427,7 @@ + @@ -17132,17 +23452,24 @@ - + + + - - + + + + + + + @@ -17153,19 +23480,24 @@ + + + + + @@ -17178,52 +23510,83 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + - - @@ -17250,9 +23613,13 @@ - + + + - + + + @@ -17285,42 +23652,51 @@ + + + + + + + + + @@ -17332,16 +23708,19 @@ + + + @@ -17356,7 +23735,9 @@ - + + + @@ -17378,13 +23759,16 @@ + + + @@ -17470,6 +23854,7 @@ + @@ -17479,17 +23864,39 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -17561,25 +23968,42 @@ + + + + + + + + + + + + + + + + + @@ -17589,18 +24013,28 @@ + + + + + + + + + + - + @@ -17622,7 +24056,9 @@ - + + + @@ -17631,8 +24067,11 @@ - + + + + @@ -17640,12 +24079,16 @@ + - + + + + @@ -17653,18 +24096,21 @@ + + + - + @@ -17673,9 +24119,11 @@ + + @@ -17720,22 +24168,28 @@ + + + + + + @@ -17763,6 +24217,7 @@ + @@ -17776,12 +24231,14 @@ + + @@ -17822,42 +24279,52 @@ + + + + + + + + + + @@ -17902,105 +24369,153 @@ - + + + + - - - + + + + + + + + + - + + + + + + + + + + - + + + + + - + + + + + + - + + + - - - - + + + + + + + + + + + + + + + + + + + + + - + + + @@ -18008,6 +24523,7 @@ + @@ -18015,6 +24531,7 @@ + @@ -18022,115 +24539,124 @@ + + + + - + + + + + + - - + - + - + - - + - + - + - + - + - + - + - + - + + - + + + - + - + - + - @@ -18148,6 +24674,7 @@ + @@ -18160,10 +24687,12 @@ + + @@ -18173,15 +24702,19 @@ - - - - + + + + + + + + @@ -18190,22 +24723,27 @@ + + + + + @@ -18213,10 +24751,12 @@ + + @@ -18236,16 +24776,19 @@ + + + @@ -18266,19 +24809,31 @@ + + + + + + + + + + + + @@ -18286,6 +24841,7 @@ + @@ -18296,132 +24852,196 @@ + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -18429,8 +25049,13 @@ + + + + + @@ -18438,38 +25063,65 @@ + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + @@ -18538,9 +25190,14 @@ - - + + + + + + + @@ -18554,6 +25211,9 @@ + + + @@ -18561,8 +25221,13 @@ + + + + + @@ -18574,13 +25239,21 @@ + + + + + + + + @@ -18588,6 +25261,10 @@ + + + + @@ -18603,6 +25280,9 @@ + + + @@ -18618,8 +25298,13 @@ + + + + + @@ -18632,6 +25317,9 @@ + + + @@ -18647,6 +25335,9 @@ + + + @@ -18660,6 +25351,9 @@ + + + @@ -18673,19 +25367,29 @@ + + + + + + - + + + + + @@ -18693,14 +25397,22 @@ + + + + - + + + + + @@ -18708,8 +25420,13 @@ + + + + + @@ -18718,10 +25435,12 @@ + + @@ -18729,9 +25448,13 @@ + + + + - + @@ -18741,6 +25464,10 @@ + + + + @@ -18749,11 +25476,16 @@ + + + + + @@ -18770,17 +25502,26 @@ + + + + + + + + + @@ -18806,15 +25547,25 @@ - + + + - - + + + + + + - + + + - + + + @@ -18822,6 +25573,9 @@ + + + @@ -18830,25 +25584,52 @@ + + + + + + + + + + + + - - - - + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -18923,11 +25704,18 @@ - - + + + + + + + + + @@ -18940,15 +25728,24 @@ - + + + + + + + + - + + + @@ -18957,10 +25754,16 @@ - + + + + + + + @@ -18993,36 +25796,56 @@ + + + + + + + + + + + + + + + + + + + + @@ -19048,9 +25871,11 @@ + + @@ -19060,6 +25885,7 @@ + @@ -19084,82 +25910,107 @@ - + + + + - + + + + + + + + + + + + + + + + + + + + + + + @@ -19167,32 +26018,45 @@ + + + + + + + + + + + + + @@ -19202,15 +26066,19 @@ + + + + @@ -19223,10 +26091,12 @@ + + @@ -19243,6 +26113,7 @@ + @@ -19252,9 +26123,11 @@ + + @@ -19263,29 +26136,38 @@ + + + - + + + - + + + + + @@ -19293,18 +26175,32 @@ - + + + - + + + - + + + - - - - + + + + + + + + + + + + @@ -19312,8 +26208,12 @@ - - + + + + + + @@ -19326,7 +26226,9 @@ - + + + @@ -19371,37 +26273,83 @@ - + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - + + + - - + + + + + + - + + + - - - - - - + + + + + + + + + + + + + + + + + + @@ -19419,30 +26367,40 @@ + + + - - + + + + + + - + + + + @@ -19474,29 +26432,44 @@ - + + + - + + + - + + + - + + + + - + + + - - + + + + + + @@ -19506,6 +26479,7 @@ + @@ -19516,14 +26490,17 @@ + + + @@ -19552,23 +26529,32 @@ + - + + + + - + + + + + + @@ -19576,8 +26562,14 @@ + + + + + + @@ -19585,51 +26577,71 @@ + + + + + + + + + + + + + + + + + + + + @@ -19638,10 +26650,12 @@ + + @@ -19664,121 +26678,161 @@ - + + + + - + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + @@ -19788,46 +26842,58 @@ + + + + + + + + + + + + @@ -19835,47 +26901,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -19895,7 +26985,6 @@ - @@ -19920,42 +27009,55 @@ + + + + + + + + + + + + + @@ -20071,11 +27173,18 @@ - + + + + + + + + @@ -20087,21 +27196,32 @@ + + + + - + + - - + + + + + + + + @@ -20114,15 +27234,30 @@ + + + + + + + + + + + + + + + @@ -20135,15 +27270,30 @@ + + + + + + + + + + + + + + + @@ -20156,6 +27306,13 @@ + + + + + + + @@ -20181,6 +27338,7 @@ + @@ -20208,6 +27366,7 @@ + @@ -20215,6 +27374,7 @@ + @@ -20227,17 +27387,27 @@ + + + + + + + + + + @@ -20246,46 +27416,62 @@ + + + + + + + + + + + + + + + + @@ -20293,12 +27479,15 @@ + + + @@ -20327,12 +27516,23 @@ + + + + + + + + + + + @@ -20383,41 +27583,58 @@ + + - + + + + + + + + + + + + + - - + + + + + @@ -20439,55 +27656,92 @@ - + + + + + + + + + + - + + + + - + + + - - - + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -20503,8 +27757,11 @@ - + + + + @@ -20519,17 +27776,29 @@ - - + + + + + + - + + + - + + + - + + + - + + + @@ -20538,72 +27807,122 @@ - + + + - + + + - + + + - + + + + + + - + + + + - - - - + + + + + + + + + + + + - - + + + + + + - + + + + - - + + + + + + + - + + + + + - + + + + - - + + + + + + + - + + + - + + + @@ -20613,6 +27932,7 @@ + @@ -20675,15 +27995,27 @@ - - + + + + + + - - + + + + + + - - + + + + + + @@ -20740,8 +28072,11 @@ - + + + + @@ -20752,21 +28087,30 @@ - + - - - + + + + + + + + + - + + + + @@ -20774,29 +28118,39 @@ - + + + + - + + + + - + + + + + @@ -20806,7 +28160,9 @@ - + + + @@ -20821,7 +28177,9 @@ - + + + @@ -20843,9 +28201,11 @@ + + @@ -20865,14 +28225,19 @@ - + + + + + + @@ -20880,38 +28245,48 @@ + + + + + + + + + + @@ -20922,81 +28297,103 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -21009,31 +28406,40 @@ + + + + + + + + + @@ -21041,43 +28447,63 @@ + + + + - + + + - + + + - + + + - - + + + + + + - - + + + + + + + + @@ -21085,49 +28511,69 @@ + + + + + + + + + + + + + + + + + + - + + + @@ -21140,7 +28586,9 @@ - + + + @@ -21150,6 +28598,7 @@ + @@ -21158,7 +28607,7 @@ - + @@ -21170,10 +28619,12 @@ + + @@ -21380,7 +28831,8 @@ - + + @@ -21392,8 +28844,14 @@ + + + + + + @@ -21417,6 +28875,7 @@ + @@ -21429,19 +28888,30 @@ + + + + + + + + + + + @@ -21465,6 +28935,7 @@ + @@ -21497,11 +28968,16 @@ + - + + + + + @@ -21522,39 +28998,58 @@ + + + + + + + + + + + + + + - + + + + + + @@ -21571,8 +29066,14 @@ + + + + + + @@ -21585,17 +29086,28 @@ + + + + + + - + + + + + + @@ -21610,6 +29122,12 @@ + + + + + + @@ -21624,44 +29142,70 @@ + + + + + + + + + + + + + + + + + + + + + + - + + + - + + + @@ -21671,73 +29215,115 @@ - - + + + + + + - + + + - - - - + + + + + + + + + + + + - + + + + + - - + + + + + + + + + + + + + + - + + + + - + + + + - + + + - + + + - + + + @@ -21746,25 +29332,51 @@ - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - + + + - + + + - + + + @@ -21782,8 +29394,12 @@ - - + + + + + + @@ -21801,36 +29417,56 @@ - + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - + + + + @@ -21839,10 +29475,16 @@ - + + + - - + + + + + + @@ -21858,10 +29500,15 @@ - + + + - + + + + @@ -21885,7 +29532,9 @@ - + + + @@ -21896,18 +29545,24 @@ - + + + + + - + + + @@ -21916,11 +29571,15 @@ + - + + + + @@ -21938,42 +29597,59 @@ - + + + + + + + + + - + + + + - + + + - + + + - + + + @@ -21988,59 +29664,75 @@ + + + + + + + + + + + + + + + + @@ -22048,11 +29740,17 @@ + - - + + + + + + + @@ -22064,6 +29762,7 @@ + @@ -22071,19 +29770,27 @@ - + + + + - + + + + - + + + @@ -22124,29 +29831,37 @@ - + + + + + + + + + @@ -22157,29 +29872,39 @@ + + + + + + + - + + + + @@ -22307,66 +30032,129 @@ - + + + - + + + + - - + + + + + + - - - - - + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + - + + + - + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - - - + + + + + + + + + @@ -22431,8 +30219,8 @@ - + @@ -22443,7 +30231,9 @@ - + + + @@ -22463,11 +30253,15 @@ - + + + + + @@ -22577,22 +30371,34 @@ + + + + + + + + + + + + @@ -22601,6 +30407,7 @@ + @@ -22609,10 +30416,12 @@ + + @@ -22641,10 +30450,13 @@ + - + + + @@ -22652,36 +30464,47 @@ + + + + + + + + + - + + + @@ -22707,55 +30530,100 @@ + + + + + + + - + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + - + + + + - - - - + + + + + + + + + + + + + + - - + + + + + + @@ -22797,15 +30665,20 @@ + + + + + - + @@ -22813,22 +30686,32 @@ + + + + - + + + + + + + @@ -22860,11 +30743,18 @@ - + + + + + + + + @@ -22886,17 +30776,22 @@ + + + - + + + @@ -22919,32 +30814,35 @@ + - + + - - + + + - + @@ -22952,8 +30850,15 @@ + + + + + + + @@ -22962,8 +30867,19 @@ + + + + + + + + + + + @@ -22975,27 +30891,42 @@ + + + + + + + + + + + + + + + @@ -23004,16 +30935,34 @@ + + + + + + + + + + + - - - + + + + + + + + + + @@ -23025,63 +30974,67 @@ + + - + - + - + - - + + - - + - - + + + + + @@ -23091,14 +31044,17 @@ + + + @@ -23106,18 +31062,20 @@ + + - + @@ -23203,7 +31161,6 @@ - @@ -23214,7 +31171,6 @@ - @@ -23238,21 +31194,28 @@ - - + + + + + + + + + @@ -23260,10 +31223,13 @@ + - + + + @@ -23271,10 +31237,18 @@ - - - - + + + + + + + + + + + + @@ -23287,7 +31261,9 @@ - + + + @@ -23300,22 +31276,31 @@ - - + + + + + + - + + + - + + + - - + + + @@ -23331,7 +31316,9 @@ - + + + @@ -23343,14 +31330,26 @@ - - - - + + + + + + + + + + + + - - + + + + + + @@ -23401,9 +31400,14 @@ - - + + + + + + + @@ -23415,20 +31419,43 @@ + - - + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -23488,7 +31515,9 @@ - + + + @@ -23571,9 +31600,14 @@ - - + + + + + + + @@ -23726,29 +31760,59 @@ - + + + - - + + + + + + - - + + + + + + - - - - - + + + + + + + + + + + + + + + - + + + - + + + - + + + - + + + - + + + @@ -23769,7 +31833,9 @@ - + + + @@ -23796,10 +31862,12 @@ + + @@ -23843,30 +31911,52 @@ + + + + + + + + + + - - + + + + + + + + + + + + + + @@ -23881,8 +31971,14 @@ + + + + + + @@ -23896,31 +31992,53 @@ + + + + + + + + + + + + + + + + + - + + + + + + + - - + @@ -23932,14 +32050,26 @@ + + + + + + + + + + + + @@ -23954,8 +32084,14 @@ + + + + + + @@ -23967,6 +32103,12 @@ + + + + + + @@ -24001,16 +32143,20 @@ + + + + @@ -24024,6 +32170,7 @@ + @@ -24031,10 +32178,12 @@ + + @@ -24042,10 +32191,12 @@ + + @@ -24054,9 +32205,11 @@ + + @@ -24076,6 +32229,7 @@ + @@ -24094,7 +32248,7 @@ - + @@ -24118,8 +32272,15 @@ + + + + + + + @@ -24135,20 +32296,34 @@ + + + + + + + + + + + - + + + + @@ -24159,65 +32334,94 @@ + + - + + + + - + + + + + + + + + + + + + + - + + + + + + + - + + + + + + @@ -24230,8 +32434,12 @@ + + + + @@ -24243,6 +32451,12 @@ + + + + + + @@ -24285,59 +32499,84 @@ - - + + + - + + + - + + + + + - + + + + - + + + + + - + + + + - + + + + - + + + - + + + + @@ -24379,33 +32618,37 @@ + - - + + - + + + + - + @@ -24420,8 +32663,16 @@ + + + + + + + + @@ -24429,22 +32680,38 @@ + + + + + + + + + + + + + + + + @@ -24456,34 +32723,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + @@ -24508,18 +32800,23 @@ + + + + + @@ -24562,11 +32859,13 @@ + + @@ -24575,19 +32874,23 @@ + + + + @@ -24595,18 +32898,22 @@ + + + + @@ -24615,10 +32922,12 @@ + + @@ -24633,45 +32942,93 @@ + + + + + + + - + - + + + + + + + + + - - - - - - + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + - - - + + + + + + + + + - + + + - + + + @@ -24689,43 +33046,95 @@ - - - + + + + + + + + + - - - - + + + + + + + + + + + + - - - - + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + - + + + - + + + - + + + - + + + - + + + @@ -24742,33 +33151,61 @@ - + + + - + + + - + + + - - - + + + + + + + + + - - - + + + + + + + + + - - + + + + + + - + + + + + - + + + @@ -24781,130 +33218,231 @@ - + + + - + + + - + + + - + + + - + + + - + + + - - - + + + + + + + + + + - + + + - + + + - - + + + + + + + - - - + + + + + + + + + - + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -24912,14 +33450,22 @@ + - + + + + - - + + + + + + @@ -24930,72 +33476,118 @@ + - + + + + + + + - + + - + + + + + + + - - - - + + + + + + + + + + + + - + + + - + + + - - + + + + + + - - + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + @@ -25003,39 +33595,60 @@ + + + + + + + + + + + + + + + - + + + + + + + @@ -25052,7 +33665,7 @@ - + @@ -25060,58 +33673,76 @@ + + + + + - + + + + - + + + + + + + - - + + + + + + @@ -25186,10 +33817,18 @@ - - - - + + + + + + + + + + + + @@ -25228,7 +33867,9 @@ - + + + @@ -25268,9 +33909,15 @@ - - - + + + + + + + + + @@ -25392,6 +34039,7 @@ + @@ -25415,98 +34063,158 @@ + + - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + - + + + + + + + - + + + + + + - + - + + + + + + + - + + + + + + + + + + + + - + @@ -25518,32 +34226,55 @@ + + + + + + + + + + + + - + + + + + + + + + + + + @@ -25551,85 +34282,142 @@ + + + + - + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -25639,34 +34427,55 @@ + + + + + + + + + + + + + + + + + + + + + @@ -25674,6 +34483,13 @@ + + + + + + + @@ -25715,26 +34531,37 @@ + + + + + + + + + + + @@ -25749,8 +34576,15 @@ + + + + + + + @@ -25764,8 +34598,15 @@ + + + + + + + @@ -25773,8 +34614,16 @@ + + + + + + + + @@ -25789,32 +34638,51 @@ + + + + + + + + + + - - + + + + + + + + - + + + + @@ -25828,6 +34696,12 @@ + + + + + + @@ -25848,8 +34722,12 @@ - - + + + + + + @@ -25926,7 +34804,9 @@ - + + + @@ -25973,11 +34853,13 @@ + + @@ -25987,10 +34869,10 @@ - + @@ -26020,10 +34902,12 @@ + + @@ -26032,12 +34916,17 @@ + + + + + @@ -26047,17 +34936,23 @@ + - + + + + - + + + @@ -26073,27 +34968,53 @@ - + + + - + + + - + + + - + + + - + + + - - - - + + + + + + + + + + + + - + + + - - - + + + + + + + + + @@ -26142,7 +35063,6 @@ - @@ -26150,15 +35070,27 @@ - - + + + + + + + + + + + + + + @@ -26166,11 +35098,29 @@ + + + + + + + + + + + + + + + + + + @@ -26181,8 +35131,12 @@ - - + + + + + + @@ -26194,34 +35148,74 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - - + + + + + + + @@ -26234,96 +35228,150 @@ - - + + + - + + + - + + + - - + + + + + + - + + + - + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - + + + + - + + + - + + + + - + + + - + + + @@ -26509,28 +35557,39 @@ + + + + + - - + + + + + + + + @@ -26541,22 +35600,38 @@ + - - + + + + + + - + + + + - + + + - - - + + + + + + + + + @@ -26625,14 +35700,21 @@ - + + + - + + + + - + + + @@ -26653,16 +35735,30 @@ - - - - - - + + + + + + + + + + + + + + + + + + + + @@ -26677,6 +35773,7 @@ + @@ -26685,8 +35782,11 @@ - + + + + @@ -26750,8 +35850,12 @@ - - + + + + + + @@ -26840,31 +35944,55 @@ - - + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + @@ -26877,44 +36005,65 @@ + + + + + + + + + - + + + + + + + + + + + + + @@ -26923,26 +36072,48 @@ + + + + + + + + + + + + + - - + + + + + + + + + + + @@ -26951,12 +36122,15 @@ + + + @@ -26970,175 +36144,284 @@ + + + + + + + + + + + + + + + + + + + - + - + + + + - + + + - - + + + + + + - + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - + + + - + + + - + + + + - - + + + + + + + + + + - + + + - - + + + - + + + @@ -27207,31 +36490,41 @@ - - - + + + + + + + + + + + + + @@ -27239,12 +36532,15 @@ + - - - - + + + + + + @@ -28580,26 +37876,22 @@ - - - - @@ -28716,26 +38008,22 @@ - - - - @@ -28786,21 +38074,18 @@ - - - @@ -28843,25 +38128,21 @@ - - - - @@ -28890,109 +38171,185 @@ + + + + + + + + + + + + + + - + + + - + + + - - - - - + + + + + + + + + + + + + + + - + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - + + + - - - - + + + + + + + + + + + + - + + + + @@ -29000,6 +38357,7 @@ + @@ -29026,20 +38384,38 @@ - - - - + + + + + + + + + + + + - + + + - + + + - + + + - - + + + + + + @@ -29066,20 +38442,31 @@ - - - + + + + + + + + + - + + + + + + @@ -29093,6 +38480,7 @@ + @@ -29110,16 +38498,21 @@ + + + + + @@ -29381,27 +38774,34 @@ + + + + + + + @@ -29506,101 +38906,136 @@ - + + + - + + + + + - + + + + + - + + + + + + - + + + + + + + + + + + + - - - + + + + + + + + + + + + @@ -29626,34 +39061,42 @@ + + + + + + + + @@ -29681,28 +39124,38 @@ + + - + + + + + - - - + + + + + + + @@ -29729,32 +39182,43 @@ + - - - + + + + + + + - + + + + + + + @@ -29763,8 +39227,12 @@ + + + + @@ -29775,22 +39243,31 @@ + - + + + + + + + + + @@ -29798,11 +39275,13 @@ + + @@ -29812,37 +39291,48 @@ + + + + + + - + + + - + + + + @@ -29852,13 +39342,16 @@ + + + @@ -29866,45 +39359,62 @@ - + + + - + + + + - + + + - + + + + - + + + - + + + - + + + + @@ -29920,13 +39430,26 @@ + + + + + + + + - + + + + + + @@ -29939,17 +39462,26 @@ + + + + + + + + + @@ -29965,8 +39497,14 @@ + + + + + + @@ -29980,16 +39518,25 @@ + + + + + + + + + @@ -30000,13 +39547,18 @@ + - + + + + + @@ -30020,50 +39572,76 @@ + + + + + + + - + + + - - - + + + + + + + + + + - + + + + + + - + + + + - + + + @@ -30083,6 +39661,7 @@ + @@ -30103,55 +39682,109 @@ - + + + - + + + - - + + + + + + - + + + - + + + - + + + - - + + + + + + - + + + - - + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + @@ -30160,7 +39793,9 @@ - + + + @@ -30168,36 +39803,49 @@ + + - + + + + + + + + + + - + + + @@ -30243,16 +39891,26 @@ + + + + + + + + + + @@ -30265,8 +39923,16 @@ + + + + + + + + @@ -30280,15 +39946,31 @@ + + + + + + + + + + + + + + + + @@ -30301,8 +39983,16 @@ + + + + + + + + @@ -30316,15 +40006,31 @@ + + + + + + + + + + + + + + + + @@ -30337,8 +40043,16 @@ + + + + + + + + @@ -30352,15 +40066,31 @@ + + + + + + + + + + + + + + + + @@ -30373,8 +40103,16 @@ + + + + + + + + @@ -30388,15 +40126,31 @@ + + + + + + + + + + + + + + + + @@ -30409,8 +40163,16 @@ + + + + + + + + @@ -30424,15 +40186,31 @@ + + + + + + + + + + + + + + + + @@ -30445,8 +40223,16 @@ + + + + + + + + @@ -30460,8 +40246,16 @@ + + + + + + + + @@ -30469,8 +40263,16 @@ + + + + + + + + @@ -30485,8 +40287,16 @@ + + + + + + + + @@ -30502,8 +40312,16 @@ + + + + + + + + @@ -30511,8 +40329,16 @@ + + + + + + + + @@ -30527,8 +40353,16 @@ + + + + + + + + @@ -30544,24 +40378,38 @@ + + + + + + + - + + - + + + + + + - + + - + @@ -30569,14 +40417,20 @@ + + + + + - + + - + @@ -30584,52 +40438,98 @@ + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + - - + + + + + + - + + + + - + + + + @@ -30642,6 +40542,7 @@ + @@ -30667,11 +40568,16 @@ + + + + + @@ -30795,6 +40701,7 @@ + @@ -30837,15 +40744,24 @@ + + + + + + + + + @@ -30861,6 +40777,7 @@ + @@ -30868,34 +40785,44 @@ - + + + + + + + + + + + @@ -30907,9 +40834,13 @@ - + + + + + @@ -30993,7 +40924,9 @@ - + + + @@ -31014,50 +40947,63 @@ + + + + + + + + + + + + + @@ -31084,33 +41030,48 @@ + + + + + + + - - - + + + + + + + + + - + + + @@ -31139,6 +41100,7 @@ + @@ -31146,6 +41108,7 @@ + @@ -31155,37 +41118,52 @@ + + + + + + + + - - + + + + + + - - + + + - + + + @@ -31258,12 +41236,16 @@ - + + + - + + + @@ -31290,7 +41272,9 @@ - + + + @@ -31306,8 +41290,12 @@ - - + + + + + + @@ -31320,10 +41308,16 @@ - - + + + + + + - + + + @@ -31340,21 +41334,32 @@ - + + + - - - + + + + + + + + + + - + + + @@ -31363,10 +41368,14 @@ - + + + - + + + @@ -31552,6 +41561,7 @@ + @@ -31560,8 +41570,11 @@ - + + + + @@ -31638,6 +41651,7 @@ + @@ -31683,29 +41697,44 @@ - + + + + - - - - + + + + + + + + + + + + + + + + @@ -31717,7 +41746,9 @@ - + + + @@ -31725,10 +41756,12 @@ + + @@ -31738,37 +41771,56 @@ + - + + + - + + + - + + + + + + + + + + + + + + + @@ -31779,17 +41831,29 @@ + + + + + + + - + + + + + + @@ -31803,8 +41867,13 @@ + + + + + @@ -31816,31 +41885,58 @@ + + + - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -31852,40 +41948,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -31893,8 +42028,17 @@ + + + + + + + + + @@ -31902,8 +42046,17 @@ + + + + + + + + + @@ -31911,18 +42064,37 @@ + + + + + + + + + - + + + + + + + + + + + @@ -31932,6 +42104,7 @@ + @@ -31954,46 +42127,59 @@ + + + + + + + + + + + + + @@ -32001,6 +42187,7 @@ + @@ -32015,24 +42202,34 @@ + + + + + + + + + + @@ -32044,46 +42241,65 @@ - + + + + + + + + - + + + + + + + + - + + + + + + @@ -32095,10 +42311,13 @@ + - + + + @@ -32106,8 +42325,12 @@ - - + + + + + + @@ -32115,6 +42338,16 @@ + + + + + + + + + + @@ -32123,14 +42356,26 @@ + + + + + + + + + + + + @@ -32141,12 +42386,15 @@ + + + @@ -32154,10 +42402,12 @@ + + @@ -32169,6 +42419,7 @@ + @@ -32182,13 +42433,14 @@ + + - @@ -32207,45 +42459,71 @@ - + + + + + + + + + + - + + + + + + + + + + - + - - + + + + + + + + + + @@ -32255,6 +42533,7 @@ + @@ -32265,6 +42544,7 @@ + @@ -32272,15 +42552,20 @@ + - + + - + + @@ -32288,10 +42573,15 @@ - + + + + + + @@ -32303,14 +42593,19 @@ + + + + + @@ -32392,16 +42687,21 @@ + + + + + @@ -32410,12 +42710,18 @@ + + + + + + @@ -32423,7 +42729,6 @@ - @@ -32431,31 +42736,34 @@ - - - + - + + + + - + + + @@ -32475,12 +42783,17 @@ - + + + + - + + + @@ -32498,52 +42811,72 @@ + + - - - + + + + + + + + + - + + + + + + + + + + + + + @@ -32551,49 +42884,57 @@ - + - + + + + + + + + + @@ -32603,30 +42944,43 @@ - + + + - + + + + - + + + + + + + - + + + @@ -32634,12 +42988,15 @@ + + + @@ -32656,17 +43013,14 @@ + - - - - @@ -32676,22 +43030,27 @@ + + - + + + + @@ -32704,20 +43063,26 @@ + - + + + + + + @@ -32726,31 +43091,40 @@ + + + - - + + + + - + + + + + @@ -32762,12 +43136,15 @@ + + + @@ -32805,22 +43182,27 @@ + + + + + @@ -32829,15 +43211,20 @@ + - + + + + + @@ -32884,9 +43271,13 @@ - + + + + + @@ -32910,6 +43301,7 @@ + @@ -32925,9 +43317,11 @@ + + @@ -32940,9 +43334,11 @@ + + @@ -32950,7 +43346,6 @@ - @@ -32965,7 +43360,6 @@ - @@ -32990,12 +43384,14 @@ + - - + + + @@ -33018,28 +43414,40 @@ - + + + - + + + + + + + + + + @@ -33064,10 +43472,12 @@ + + @@ -33077,40 +43487,47 @@ + + + - + + + + + @@ -33135,13 +43552,20 @@ + - + + + + + + + @@ -33259,13 +43683,16 @@ + + + @@ -33294,7 +43721,6 @@ - @@ -33348,46 +43774,57 @@ + + + + + + + + + + + @@ -33397,28 +43834,44 @@ + + + + + + + + + + - + + + + + + + @@ -33461,10 +43914,13 @@ + - + + + @@ -33487,41 +43943,60 @@ + + + + + + + + + + + + - + + + + + + + + + - @@ -33547,22 +44022,28 @@ + + + + + + @@ -33570,6 +44051,7 @@ + @@ -33597,25 +44079,21 @@ - - - - @@ -33623,14 +44101,17 @@ + + + @@ -33644,7 +44125,6 @@ - @@ -33654,8 +44134,12 @@ + + + + + - @@ -33665,8 +44149,12 @@ + + + + + - @@ -33676,23 +44164,31 @@ + + + + + - - + + + + + + - @@ -33702,22 +44198,29 @@ + + + + + - + - - + + + + @@ -33800,7 +44303,8 @@ - + @@ -33811,43 +44315,69 @@ + - + + + - + + + - + + + + + + + + + + + + + + + + + + + + + + @@ -33857,35 +44387,57 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -33896,71 +44448,145 @@ + + + + + + + + + + + - + + + + - - + + + + + + + - - - - + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + - - + + + + + + - + + + - + + + - + + + @@ -33990,154 +44616,281 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + - - - @@ -34150,45 +44903,73 @@ - + + + - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + - + + + + + @@ -34197,47 +44978,61 @@ + + + - - + + + + + + + + + + + + + @@ -34246,24 +45041,25 @@ - - - - + + + + + @@ -34277,14 +45073,17 @@ + + + @@ -34296,16 +45095,20 @@ + - + + + + @@ -34314,15 +45117,20 @@ - + + + - + + + + @@ -34339,26 +45147,35 @@ - + + + + + + + + + + @@ -34371,8 +45188,12 @@ + + + + @@ -34385,47 +45206,65 @@ + + + + + + + + + + + + + + + + - + + + @@ -34446,9 +45285,14 @@ + + + + + @@ -34458,7 +45302,9 @@ - + + + @@ -34470,10 +45316,13 @@ + + + - + @@ -34485,6 +45334,11 @@ + + + + + @@ -34492,12 +45346,21 @@ + + + + + + + + + @@ -34510,28 +45373,46 @@ + + + + + + + + + + + - + + + + + + + + @@ -34543,19 +45424,30 @@ + + + + + + + - + + + + + + - @@ -34564,33 +45456,64 @@ + + + + + + + + + + - - + - + + + + + + + + + + + + + + + + + + + + + + + @@ -34606,13 +45529,22 @@ + + + + + + + + + @@ -34673,13 +45605,21 @@ - + + + + - - + + + + + + + @@ -34692,6 +45632,7 @@ + @@ -34707,6 +45648,7 @@ + @@ -34732,15 +45674,17 @@ + - + + @@ -34755,8 +45699,16 @@ + + + + + + + + @@ -34771,13 +45723,22 @@ + + + + + + + + - - + + + @@ -34787,65 +45748,115 @@ - - + + + + + + - + + + + - + + + + - + + + + - + + + + - - + + + + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + @@ -34866,7 +45877,9 @@ - + + + @@ -34890,6 +45903,7 @@ + @@ -34929,14 +45943,17 @@ + + + @@ -34980,67 +45997,83 @@ + - + + + + + + + + + + + + + + + + @@ -35055,6 +46088,7 @@ + @@ -35068,69 +46102,83 @@ + + + + + + + + + + + + + + @@ -35144,46 +46192,57 @@ + + + + + + + + + + + @@ -35198,14 +46257,17 @@ + + + @@ -35218,39 +46280,48 @@ + + + + + + + + + @@ -35259,6 +46330,11 @@ + + + + + @@ -35275,8 +46351,14 @@ + + + + + + @@ -35285,20 +46367,29 @@ - + - + + + + + + + + + + @@ -35323,79 +46414,100 @@ + + + + + + + + + + + + + + + + + + + + + @@ -35403,69 +46515,90 @@ + + + + + + + + + + + + + + + + - + + + + + + - + @@ -35474,6 +46607,11 @@ + + + + + @@ -35486,33 +46624,53 @@ + + + + + + + + + + - + + + + + + + + + + + - + @@ -35521,12 +46679,22 @@ + + + + + + + + + + @@ -35539,26 +46707,36 @@ + + + + + + + + + + @@ -35566,20 +46744,36 @@ + + + + + + + + + + + + + + + + @@ -35656,19 +46850,19 @@ + - - + + - + - @@ -35676,10 +46870,12 @@ + + @@ -35692,10 +46888,12 @@ + + @@ -35704,22 +46902,27 @@ + + - + + + + @@ -35729,155 +46932,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + - + + + + + @@ -35886,51 +47126,65 @@ + + - + + + + + - - - - + + + + + + + + + + + + @@ -35975,49 +47229,76 @@ - + + + + + - - - + + + + + + + + + - - + + + + + + - + + + - - + + + - - + + + + + + - + + + - + + + - + + + @@ -36070,19 +47351,22 @@ + - - - + + + + - + + + - @@ -36093,7 +47377,9 @@ - + + + @@ -36113,168 +47399,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -36282,45 +47630,85 @@ + + - + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + - - - - + + + + + + + + + + + + @@ -36358,33 +47746,45 @@ - - + + + + - + + - + + + + + - - - + + + + + + - + + + @@ -36399,12 +47799,16 @@ - + + + - - + + + + @@ -36418,28 +47822,35 @@ + + - - - - - - - - - + + + + + + + + + + + + + + @@ -36458,6 +47869,7 @@ + @@ -36470,10 +47882,12 @@ + + @@ -36483,61 +47897,79 @@ + + + + + + + + + + + + + + + + + + @@ -36565,35 +47997,51 @@ + + + + + + + + + + + + + - + + + + @@ -36670,6 +48118,7 @@ + @@ -36713,34 +48162,45 @@ + + + + + + + - - + + + + - + - + + + @@ -36771,31 +48231,32 @@ - - + + + + - + - + - + - @@ -36863,12 +48324,15 @@ - + + + + @@ -36876,80 +48340,98 @@ + + + + + + + + + + + + + + + + + + @@ -36962,9 +48444,11 @@ + + @@ -36974,42 +48458,62 @@ - + + + + + + + + + + + + + + + + + + + + - - + + + @@ -37017,12 +48521,14 @@ + + @@ -37030,12 +48536,16 @@ + + - + + + @@ -37048,15 +48558,24 @@ - + + + - + + + + - - + + + + + + @@ -37085,6 +48604,7 @@ + @@ -37092,8 +48612,12 @@ - - + + + + + + @@ -37101,14 +48625,20 @@ + - + + + + - + + + @@ -37124,25 +48654,47 @@ - - - + + + + + + + + + - + + + - + + + - + + + - + + + - + + + - - + + + + + + - + + @@ -37152,62 +48704,87 @@ - - - - + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + - + + - + @@ -37219,21 +48796,38 @@ + + + + + + - - + + + + + + + + + + + + + @@ -37244,13 +48838,14 @@ - - + + + @@ -37258,6 +48853,7 @@ + @@ -37269,21 +48865,25 @@ + + + + @@ -37293,40 +48893,58 @@ + + + + + + + - + + + + + + + + + + + - + + @@ -37335,14 +48953,17 @@ + + + @@ -37351,10 +48972,13 @@ - + + + + @@ -37371,6 +48995,7 @@ + @@ -37378,15 +49003,31 @@ + + + + + + + + + + + + + + + + @@ -37394,13 +49035,23 @@ - + + + + + + + + + + + @@ -37428,43 +49079,62 @@ - + + + - - + + + + + + + + - + + + + + + + + + + - + + + - + @@ -37689,33 +49359,40 @@ - + + + + + + + + @@ -37723,24 +49400,28 @@ + + + + @@ -37753,66 +49434,77 @@ + + + + + + + + + + + @@ -37831,387 +49523,701 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -38224,518 +50230,830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -38754,181 +51072,244 @@ + + + + + - + + + + + + - + + + + + + + - + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -38937,6 +51318,7 @@ + @@ -38945,25 +51327,24 @@ + - - + + + - - - @@ -38972,15 +51353,20 @@ + - + + + + + @@ -39001,140 +51387,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + - + + + @@ -39149,42 +51585,58 @@ + + + + - + + + + - + + + - + + - - - + + + + + + + + + @@ -39197,11 +51649,14 @@ - + + + - - + + + @@ -39212,41 +51667,44 @@ + + - - - - + + + + + @@ -39254,19 +51712,26 @@ - + + + + + + + + - + @@ -39275,25 +51740,39 @@ + + + + + + + - + + + + + + + + - + @@ -39302,25 +51781,39 @@ + + + + + + + - + - + + + + + + + + - + @@ -39329,14 +51822,21 @@ + + + + + + + - + - + @@ -39345,12 +51845,19 @@ + + + + + + + - + @@ -39361,11 +51868,18 @@ + + + + + + + - + @@ -39374,11 +51888,21 @@ + + + + + + + + + + - + @@ -39387,42 +51911,70 @@ + + + + + + + + + + + + + - + + + + + - - - + + + + + + + + + - + + + + + - - + + + @@ -39446,6 +51998,7 @@ + @@ -39453,16 +52006,28 @@ - - - - - + + + + + + + + + + + + + + + + + @@ -39515,28 +52080,44 @@ + + + + + + + + + + + + + + + + @@ -39588,8 +52169,9 @@ - - + + + @@ -39658,9 +52240,14 @@ + + + + + @@ -39668,56 +52255,71 @@ + - + + + + + + + + + + + + + + + @@ -39725,9 +52327,11 @@ + + @@ -39757,20 +52361,26 @@ - + + + + + + + @@ -39779,10 +52389,12 @@ + + @@ -39795,6 +52407,7 @@ + @@ -39894,18 +52507,25 @@ + - - + + + + + + + + @@ -39919,15 +52539,27 @@ + + + + + + - + + + + + + + @@ -39944,12 +52576,18 @@ + + + + + + - + @@ -39960,13 +52598,25 @@ + + + + + + + + + + + + @@ -39974,41 +52624,50 @@ + + + + + + + + + @@ -40039,33 +52698,41 @@ + + + + + + + + @@ -40077,34 +52744,41 @@ + + + + + + + @@ -40118,21 +52792,26 @@ + + + + + @@ -40156,6 +52835,7 @@ + @@ -40223,7 +52903,9 @@ - + + + @@ -40231,7 +52913,9 @@ - + + + @@ -40240,27 +52924,34 @@ + + - - + + + + + + + @@ -40269,15 +52960,14 @@ - - + @@ -40290,16 +52980,19 @@ + + + @@ -40310,13 +53003,10 @@ - - - @@ -40327,28 +53017,25 @@ - - - - - - + + + - + + + - - @@ -40359,15 +53046,12 @@ - - - @@ -40378,14 +53062,20 @@ + - + + + + - + + + @@ -40426,9 +53116,15 @@ - - - + + + + + + + + + @@ -40437,51 +53133,87 @@ - - - - + + + + + + + + + + + + + + + + + + + - - + + + + + + + + - - + + + + + + + + + + + + + + + + + @@ -40502,30 +53234,40 @@ + + + - - + + + - - - + + + + + + + - - + + + + @@ -40536,155 +53278,213 @@ - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -41051,16 +53851,23 @@ + - + + + - + + + - + + + @@ -41074,13 +53881,13 @@ - + - + @@ -41095,13 +53902,13 @@ - + - + @@ -41120,129 +53927,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - + + + + + + @@ -41252,16 +54091,23 @@ + - + + + + + + + @@ -41277,12 +54123,18 @@ + + + + + + - + @@ -41291,12 +54143,23 @@ + + + + + + + + + + + - + @@ -41305,8 +54168,19 @@ + + + + + + + + + + + @@ -41323,8 +54197,16 @@ + + + + + + + + @@ -41338,8 +54220,14 @@ + + + + + + @@ -41348,8 +54236,14 @@ + + + + + + @@ -41364,8 +54258,14 @@ + + + + + + @@ -41380,8 +54280,14 @@ + + + + + + @@ -41396,8 +54302,16 @@ + + + + + + + + @@ -41412,8 +54326,16 @@ + + + + + + + + @@ -41428,6 +54350,13 @@ + + + + + + + @@ -41492,15 +54421,18 @@ - - + + + + + @@ -41637,14 +54569,17 @@ + + + @@ -41780,6 +54715,7 @@ + @@ -41787,9 +54723,11 @@ + + @@ -41797,10 +54735,11 @@ + - + @@ -41809,12 +54748,25 @@ + + + + + + + + + + + - + + + @@ -41823,8 +54775,19 @@ + + + + + + + + + + + @@ -41838,8 +54801,15 @@ + + + + + + + @@ -41852,8 +54822,15 @@ + + + + + + + @@ -41866,8 +54843,15 @@ + + + + + + + @@ -41880,9 +54864,14 @@ + + + + + + - @@ -41910,7 +54899,6 @@ - @@ -41937,8 +54925,11 @@ - + + + + @@ -41974,66 +54965,78 @@ + - + + + + + + + - + + + - + - - - + + + - + - - + + + + + @@ -42047,76 +55050,93 @@ + + + + + + + + + + + + + + + + + @@ -42136,25 +55156,24 @@ - - - - - - + + + - + + + - + + + @@ -42171,7 +55190,9 @@ - + + + @@ -42188,44 +55209,70 @@ - - + + + + + + - - + + + + + + - + + + - + + + + - + + + + + + + + + + + - + + + + @@ -42241,11 +55288,11 @@ - + + + - - @@ -42257,14 +55304,17 @@ - + + + - + - - + + + @@ -42281,19 +55331,18 @@ + - - @@ -42312,24 +55361,30 @@ + + + + + + @@ -42337,51 +55392,61 @@ - + - - - + + + + + + + + + + + + + @@ -42398,11 +55463,19 @@ + + + + + + + + - + @@ -42412,9 +55485,17 @@ + + + + + + + + @@ -42426,12 +55507,20 @@ + + + + + + + + - + - + @@ -42442,8 +55531,14 @@ + + + + + + @@ -42457,8 +55552,16 @@ + + + + + + + + @@ -42472,10 +55575,18 @@ + + + + + + + + - + @@ -42486,21 +55597,32 @@ + + + + + - + + + + + + + - + @@ -42509,11 +55631,21 @@ + + + + + + + + + + - + @@ -42524,8 +55656,14 @@ + + + + + + @@ -42538,14 +55676,32 @@ + + + + + + + + + + + + + + + + + + @@ -42562,11 +55718,17 @@ + + + + + + - + @@ -42577,26 +55739,37 @@ + + + + + - - + + + + + + + + @@ -42612,72 +55785,100 @@ + - + + + + - - + + + - + + + - + + + - + + + + + - - + + + + + + + + - - - - + + + + + + + + + - + + + + + @@ -42686,9 +55887,9 @@ - + @@ -42778,7 +55979,9 @@ - + + + @@ -42822,39 +56025,45 @@ - + + + + - + + + + @@ -42963,6 +56172,7 @@ + @@ -42970,6 +56180,7 @@ + @@ -42977,6 +56188,7 @@ + @@ -42984,11 +56196,13 @@ + + @@ -43039,7 +56253,6 @@ - @@ -43088,6 +56301,7 @@ + @@ -43154,7 +56368,9 @@ - + + + @@ -43269,18 +56485,22 @@ + + + + @@ -43327,11 +56547,15 @@ + + + + @@ -43348,74 +56572,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -43426,109 +56676,140 @@ - + + + + + + + - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -43544,24 +56825,37 @@ + + - - - - + + + + + + + + + + + + + + + @@ -43606,15 +56900,19 @@ + + + + @@ -43624,12 +56922,17 @@ - + + + + + + @@ -43639,28 +56942,41 @@ + + + + + + + + + + + + + @@ -43708,8 +57024,12 @@ - - + + + + + + @@ -43736,47 +57056,62 @@ + + + + + + + + + + + + + + + @@ -43799,31 +57134,38 @@ + + - + - - + + + + + + + @@ -43834,14 +57176,26 @@ + + + + + + + + + + + + @@ -43852,6 +57206,11 @@ + + + + + @@ -43877,52 +57236,65 @@ + + + + + + + + + + + + + @@ -43938,16 +57310,30 @@ + + + + + + + + - + + + + + + + @@ -43960,8 +57346,16 @@ + + + + + + + + @@ -43974,8 +57368,16 @@ + + + + + + + + @@ -43991,8 +57393,14 @@ + + + + + + @@ -44005,11 +57413,19 @@ + + + + + + + + - + @@ -44019,12 +57435,23 @@ + + + + + + + + + + + - - + + @@ -44033,56 +57460,104 @@ + + + + + + + + + + + + + + + + - - - + + + + + + + + + - - - + + + + + + + + - - - - + + + + + + + + + + + + + + - + + + - + + + - + + + + - - + + + + + + @@ -44090,25 +57565,35 @@ - + + + - + + + - - + + + + + + - + + + @@ -44210,14 +57695,18 @@ - + + + + - - + + + @@ -44237,30 +57726,41 @@ + + - - - + + + + + + + + + - + + + - - + + + + + + - - - @@ -44272,42 +57772,56 @@ + + + + + + - - + + + - + + + - + + + - + + + + - + @@ -44327,136 +57841,163 @@ + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + - - @@ -44476,108 +58017,144 @@ - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + - - - + + + + + + + + + @@ -44597,9 +58174,12 @@ - + + + + @@ -44621,44 +58201,64 @@ - - - + + + + + + + + + - - + + + + + + - + + + + + + + - + + + + + @@ -44666,23 +58266,27 @@ + + + - + + @@ -44693,57 +58297,79 @@ - - - + + + + + + + + + + + + - + + + + + - + + + + + + + - + + + + @@ -44755,10 +58381,12 @@ + + @@ -44962,11 +58590,17 @@ + + + + + + @@ -44981,41 +58615,56 @@ + + + + + + + + + + + + + - + + + @@ -45037,21 +58686,27 @@ - + + + + + + + @@ -45065,16 +58720,24 @@ + + - - - + + + + + + + + + @@ -45093,19 +58756,24 @@ + + + + + @@ -45186,7 +58854,9 @@ - + + + @@ -45313,28 +58983,42 @@ + + + + + - + + + + + + + + + + @@ -45361,12 +59045,15 @@ + + + @@ -45374,6 +59061,7 @@ + @@ -45389,11 +59077,17 @@ + + + + + + - + @@ -45403,6 +59097,11 @@ + + + + + @@ -45417,8 +59116,14 @@ + + + + + + @@ -45432,13 +59137,20 @@ + + + + + + + - + @@ -45450,21 +59162,35 @@ + + + + + + + + - + + + + + + + - + @@ -45475,31 +59201,42 @@ + + + + + + + + + + + @@ -45547,14 +59284,16 @@ + + - + @@ -45564,12 +59303,21 @@ + + + + + + + + - + + @@ -45577,32 +59325,50 @@ + + + + + - + + + + + + + + + + + + + + @@ -45614,11 +59380,15 @@ + + + + @@ -45626,6 +59396,10 @@ + + + + @@ -45801,89 +59575,113 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -45895,27 +59693,30 @@ + + + + - @@ -45938,6 +59739,7 @@ + @@ -45945,6 +59747,7 @@ + @@ -45953,15 +59756,20 @@ - + + + + + + @@ -45973,11 +59781,13 @@ + + @@ -45988,10 +59798,9 @@ - + - @@ -46013,41 +59822,49 @@ - + + + + + + + + + @@ -46068,25 +59885,31 @@ + + + + + + @@ -46097,23 +59920,28 @@ + + + + + @@ -46122,88 +59950,111 @@ + + + + + + + + - + + + - + + + + + + + + + + + + + + @@ -46242,48 +60093,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -46328,6 +60206,7 @@ + @@ -46335,6 +60214,7 @@ + @@ -46359,203 +60239,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - + + + + + + - + + + @@ -46597,29 +60527,1029 @@ - - + + + + + + - - + + + + + + - + + + - + + + - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -46672,10 +61602,12 @@ + + @@ -46685,22 +61617,30 @@ + + + + + + + + @@ -46708,6 +61648,7 @@ + @@ -46715,36 +61656,47 @@ + + + + + + + - + + + + + @@ -46778,10 +61730,13 @@ - + + + + @@ -46795,8 +61750,16 @@ + + + + + + + + @@ -46805,40 +61768,66 @@ + + + + + + - + + + + + + - + + + + + + + + + + - + + + + + + + @@ -46853,6 +61842,7 @@ + @@ -46866,25 +61856,26 @@ + + + + + + - - - - - - - - + + + @@ -46897,8 +61888,7 @@ - - + @@ -46907,17 +61897,28 @@ + + + + + + + + - + + + + @@ -46925,6 +61926,7 @@ + @@ -46948,14 +61950,19 @@ + + - + + + + @@ -46981,14 +61988,17 @@ + + + @@ -47077,6 +62087,7 @@ + @@ -47100,24 +62111,31 @@ + + + + + + + @@ -47155,74 +62173,91 @@ + + + + + + + + + + + + + + + + + @@ -47234,48 +62269,131 @@ + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + @@ -47287,6 +62405,7 @@ + @@ -47296,54 +62415,79 @@ + + + + + + - - - - + + + + + + + + + + + + + - - - + + + + + + + + + + + + + @@ -47470,29 +62614,36 @@ + + + + + + + @@ -47513,57 +62664,68 @@ + + + + + + + + + + + @@ -47663,55 +62825,70 @@ + + + + + + + + + + + - + + + + + @@ -47719,26 +62896,29 @@ + + + + - @@ -47747,9 +62927,13 @@ - + + + + + @@ -47771,16 +62955,32 @@ - + + + + + + + + + + + + - - + + + + + + + @@ -47792,18 +62992,25 @@ - - + + + + + + + + + @@ -47813,27 +63020,35 @@ + + + + - + + + + + @@ -48104,10 +63319,12 @@ + + @@ -48188,9 +63405,11 @@ + + @@ -48224,6 +63443,7 @@ + @@ -48231,27 +63451,29 @@ - + + + - + - + @@ -48271,18 +63493,23 @@ + + + + + @@ -48436,19 +63663,27 @@ + + + + + + + + @@ -48472,27 +63707,33 @@ + + + + + + @@ -48514,6 +63755,7 @@ + @@ -48533,42 +63775,51 @@ + + + + + + + + + @@ -48588,46 +63839,56 @@ + + + + + + + + + + @@ -48672,12 +63933,15 @@ + + + @@ -48688,6 +63952,7 @@ + @@ -48700,15 +63965,20 @@ + + + + + - + - + @@ -48721,8 +63991,16 @@ + + + + + + + + @@ -48738,13 +64016,21 @@ + + + + + + + + - + - + @@ -48757,8 +64043,16 @@ + + + + + + + + @@ -48766,7 +64060,7 @@ - + @@ -48774,13 +64068,21 @@ + + + + + + + + - + - + @@ -48793,8 +64095,16 @@ + + + + + + + + @@ -48810,8 +64120,16 @@ + + + + + + + + @@ -48830,8 +64148,16 @@ + + + + + + + + @@ -48850,12 +64176,20 @@ + + + + + + + + - + - + @@ -48865,15 +64199,26 @@ + + + + + + + + + + + - - + + - + @@ -48882,20 +64227,43 @@ + + + + + + + + + + + - + + + + + + + - + + + + + + + @@ -48909,10 +64277,16 @@ + + + + + + - + @@ -48924,10 +64298,16 @@ + + + + + + - + @@ -48938,6 +64318,11 @@ + + + + + @@ -48945,24 +64330,35 @@ - + + + + + + - + + + + + + + @@ -48977,8 +64373,14 @@ + + + + + + @@ -48986,10 +64388,12 @@ + + @@ -48998,11 +64402,15 @@ + - + + + + @@ -49108,60 +64516,73 @@ + + + + + + + + + + + + + - + @@ -49172,11 +64593,19 @@ + + + + + + + + - + @@ -49186,26 +64615,48 @@ + + + + + + + + + + + - - + + - + + + + + + + + + + + - + + - + @@ -49217,8 +64668,14 @@ + + + + + + @@ -49233,8 +64690,14 @@ + + + + + + @@ -49249,8 +64712,16 @@ + + + + + + + + @@ -49265,8 +64736,14 @@ + + + + + + @@ -49282,32 +64759,47 @@ + + + + + + + + + + + + + + + @@ -49315,9 +64807,11 @@ + + @@ -49499,16 +64993,22 @@ + - + + + + - + + + @@ -49523,11 +65023,15 @@ - + + + - + + + @@ -49548,10 +65052,14 @@ + - + + + + @@ -49565,8 +65073,16 @@ + + + + + + + + @@ -49580,42 +65096,59 @@ + + + + + + + + + - + + + + + + + + + @@ -49624,27 +65157,33 @@ + + + + + + @@ -49653,37 +65192,46 @@ + + + + + + + + + @@ -49704,89 +65252,208 @@ + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + - + + - + + - - - + + + + + + + + + + + @@ -49794,10 +65461,12 @@ + + @@ -49828,6 +65497,7 @@ + @@ -49864,31 +65534,37 @@ + + + + + + @@ -49926,91 +65602,201 @@ + - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + @@ -50019,9 +65805,11 @@ + + @@ -50073,6 +65861,7 @@ + @@ -50103,17 +65892,21 @@ + + + + @@ -50125,8 +65918,16 @@ + + + + + + + + @@ -50140,19 +65941,39 @@ + + + + + + + + + + + + + + + + + + + + @@ -50169,30 +65990,50 @@ + + + + + + + + - + + + + + + + - + - + + + + + + + - + @@ -50200,12 +66041,23 @@ + + + + + + + + + + + - + @@ -50213,109 +66065,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + @@ -50331,6 +66240,7 @@ + @@ -50357,110 +66267,418 @@ + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + @@ -50469,95 +66687,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -50566,40 +66810,141 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + - + @@ -50607,17 +66952,20 @@ + + + @@ -50667,6 +67015,7 @@ + @@ -50674,43 +67023,61 @@ + + + + + - - - - - + + + + + + + + + + + + + + + + + + @@ -50743,20 +67110,24 @@ + + + + @@ -50766,15 +67137,22 @@ - - + + + + + + + + + @@ -50783,14 +67161,17 @@ + + + @@ -50824,127 +67205,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -50954,14 +67366,21 @@ + + + + + + + @@ -50969,8 +67388,16 @@ + + + + + + + + @@ -50978,6 +67405,7 @@ + @@ -50985,14 +67413,23 @@ + + + + + + + + + @@ -51000,8 +67437,16 @@ + + + + + + + + @@ -51009,6 +67454,7 @@ + @@ -51016,13 +67462,22 @@ + + + + + + + + + @@ -51031,14 +67486,23 @@ + + + + + + + + + @@ -51047,8 +67511,16 @@ + + + + + + + + @@ -51061,11 +67533,18 @@ + + + + + + + @@ -51078,12 +67557,21 @@ + + + + + + + + + @@ -51096,49 +67584,100 @@ + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + @@ -51148,10 +67687,17 @@ + + + + + + + @@ -51161,11 +67707,20 @@ + + + + + + - + + + + @@ -51176,11 +67731,20 @@ + + + + + + - + + + + @@ -51191,12 +67755,19 @@ + + + + + + - + + @@ -51207,13 +67778,26 @@ + + + + + + + + + + + + - + + @@ -51224,6 +67808,17 @@ + + + + + + + + + + + @@ -51359,6 +67954,7 @@ + @@ -51367,11 +67963,14 @@ - + + + + @@ -51398,225 +67997,277 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -51638,62 +68289,66 @@ - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + + + + + @@ -51701,6 +68356,7 @@ + @@ -51720,81 +68376,90 @@ + + + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + @@ -51819,190 +68484,192 @@ - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + @@ -52025,6 +68692,7 @@ + @@ -52035,6 +68703,7 @@ + @@ -52055,6 +68724,7 @@ + @@ -52075,11 +68745,13 @@ + + @@ -52104,6 +68776,7 @@ + @@ -52116,83 +68789,90 @@ + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + + + + + + @@ -52200,126 +68880,150 @@ - - - - + + + + - - - - + + + + - - - - + + + + - - + + + + + + + - + - + - + - + + + + + + + + + + + + + + + + @@ -52335,36 +69039,135 @@ + + - - + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + @@ -52389,10 +69192,12 @@ + + @@ -52401,26 +69206,31 @@ + + + + + @@ -52439,93 +69249,123 @@ + + + + - - - - + + + + + + + + + + + + + + - + + + + - + + + + + + + + + + + + + + @@ -52540,41 +69380,141 @@ + + + + - - + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - @@ -52606,32 +69546,69 @@ + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -52647,65 +69624,113 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + + @@ -52714,7 +69739,7 @@ - + @@ -52728,10 +69753,11 @@ - + + @@ -52752,187 +69778,241 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -52942,8 +70022,8 @@ - - + + @@ -52956,83 +70036,109 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -53060,6 +70166,7 @@ + @@ -53072,130 +70179,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -53206,53 +70346,62 @@ - + + - + - + + - + - + + + + + - + + + + - + @@ -53272,47 +70421,53 @@ + - + - + - + - + - + - + + - + + - + + - + + - + + @@ -53420,16 +70575,22 @@ + + + + + + @@ -53441,9 +70602,13 @@ + + + - + + @@ -53454,15 +70619,26 @@ + + + + + + + + + + + @@ -53471,13 +70647,15 @@ - + - + + + @@ -53494,38 +70672,50 @@ - + - - - + + + + + + + + + - + + - + + - + + - + + - + + - + + @@ -53533,114 +70723,269 @@ + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - + + + + + + + + + + - - - + + + - - + + - - + + + + - + + + - + + + @@ -53681,29 +71026,48 @@ - - + + + + + + - + + + - + + + - + + + - - + + + + + + + - + + + - + + + @@ -53713,61 +71077,104 @@ - + + + - + + + - + + + - + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + - - - + + + + + + + + + + + @@ -53785,43 +71192,52 @@ - + - + - + - + + - + + + - - + + + + + + - + + + @@ -53834,9 +71250,12 @@ + - + + + @@ -53844,41 +71263,60 @@ - + + + - - + + + + + + - + - + + + - + + + + + + + + - + + + - + + + @@ -53887,7 +71325,9 @@ - + + + @@ -53913,11 +71353,12 @@ + - + @@ -53929,14 +71370,20 @@ + + + + + + - + @@ -53946,9 +71393,16 @@ + + + + + + + @@ -53968,20 +71422,32 @@ + + + + + + + - - - - + + + + + + + + + - - + + @@ -53989,14 +71455,20 @@ + + + + + + - - - + + + @@ -54007,12 +71479,18 @@ + + + + + + - - + + @@ -54020,14 +71498,20 @@ + + + + + + - - - + + + @@ -54038,8 +71522,14 @@ + + + + + + @@ -54053,8 +71543,16 @@ + + + + + + + + @@ -54068,8 +71566,16 @@ + + + + + + + + @@ -54083,8 +71589,16 @@ + + + + + + + + @@ -54092,14 +71606,20 @@ + + + + + + - + @@ -54110,14 +71630,29 @@ + + + + + + + - + + + + + + + + + @@ -54126,13 +71661,19 @@ + + + + + + - - + + @@ -54141,14 +71682,26 @@ + + + + + + + + + + + + - - - + + + @@ -54156,11 +71709,23 @@ + + + + + + + + + + + + - + @@ -54170,10 +71735,16 @@ + + + + + + - + @@ -54185,28 +71756,54 @@ + + + + + + - + + + + + + + - + + + + + + + + - - - - + + + + + + + + + + + @@ -54216,295 +71813,391 @@ - > - - + + + + + + + + - + + - + + + + + + - - - - + + + + + + + + + + + - - + + + + - > - - + + + + + + + + + - - + + + + + + + - - - - + + + + + + + + + + - + + - - - - + + + + - > - - + + + + + + + + + - - - + + + + + + + + + - - - - + + + + + + + + + + - - - + + + - - + + + + + + + + - - + + + + + + + + + + - - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - + + - + + + + + + + + + - - - - + + + + + + + + + - > - + + + + + + + + + + + + + + + @@ -54519,346 +72212,352 @@ - + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + + + + + + + - - @@ -54866,29 +72565,29 @@ - + - + - - + + - - - + + + - - - - + + + + - - - - + + + + @@ -54898,89 +72597,113 @@ - - + + - - - + + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + - + + + + + + + + - + + + @@ -54994,312 +72717,534 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + + - - + + - + + + - - - - + + + + - - - - + + + + - - - + + + - - + + + + + - + + + - + + + + - - - + + + + + + + + + - - - + + + + + + + + + - - + + + + + + - + - + + + @@ -55323,7 +73268,9 @@ - + + + @@ -55335,138 +73282,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - + + + + + + + + + - + + + + @@ -55479,16 +73467,19 @@ + - - - - + + + + + + + - @@ -55502,10 +73493,12 @@ + + @@ -55513,94 +73506,241 @@ + + + - - + + + + - - + + + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -55608,57 +73748,1724 @@ + + + + + + + + + - - + + + + - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 974919c1a5e4b5e6215f159b02e225177154c2f3 Mon Sep 17 00:00:00 2001 From: Luan Santos Date: Sat, 7 Oct 2023 20:23:41 -0700 Subject: [PATCH 44/45] fix: bad merge --- source/action.h | 6 ++---- source/iomap_otbm.cpp | 6 +++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/source/action.h b/source/action.h index 456cdcf5..c4da490c 100644 --- a/source/action.h +++ b/source/action.h @@ -65,10 +65,7 @@ struct WaypointData { }; class Change { -private: - ChangeType type; - void* data; - +public: Change(Tile* tile); ~Change(); @@ -83,6 +80,7 @@ class Change { uint32_t memsize() const; private: + Change(); ChangeType type; void* data; diff --git a/source/iomap_otbm.cpp b/source/iomap_otbm.cpp index 0c117136..74d243d3 100644 --- a/source/iomap_otbm.cpp +++ b/source/iomap_otbm.cpp @@ -216,7 +216,7 @@ void Item::serializeItemAttributes_OTBM(const IOMap& maphandle, NodeFileWriteHan void Item::serializeItemCompact_OTBM(const IOMap& maphandle, NodeFileWriteHandle& stream) const { - stream.addU16(g_items[id].clientID); + stream.addU16(id); /* This is impossible const ItemType& iType = g_items[id]; @@ -230,7 +230,7 @@ void Item::serializeItemCompact_OTBM(const IOMap& maphandle, NodeFileWriteHandle bool Item::serializeItemNode_OTBM(const IOMap& maphandle, NodeFileWriteHandle& file) const { file.addNode(OTBM_ITEM); - file.addU16(g_items[id].clientID); + file.addU16(id); if(maphandle.version.otbm == MAP_OTBM_1) { const ItemType& type = g_items.getItemType(id); if(type.stackable || type.isSplash() || type.isFluidContainer()) { @@ -362,7 +362,7 @@ bool Container::unserializeItemNode_OTBM(const IOMap& maphandle, BinaryNode* nod bool Container::serializeItemNode_OTBM(const IOMap& maphandle, NodeFileWriteHandle& file) const { file.addNode(OTBM_ITEM); - file.addU16(g_items[id].clientID); + file.addU16(id); if(maphandle.version.otbm == MAP_OTBM_1) { // In the ludicrous event that an item is a container AND stackable, we have to do this. :p const ItemType& type = g_items.getItemType(id); From 5bc98a0c81862e790e4042b36ccc7d81b4190fe9 Mon Sep 17 00:00:00 2001 From: Luan Santos Date: Sun, 8 Oct 2023 08:21:17 -0700 Subject: [PATCH 45/45] Revert "feat: update items.otb and items.xml" This reverts commit 40f1edc70f17c423282d546a41541a8fe9b92dcc. --- data/items/items.otb | Bin 1849211 -> 1673339 bytes data/items/items.xml | 26903 ++++++----------------------------------- 2 files changed, 3548 insertions(+), 23355 deletions(-) diff --git a/data/items/items.otb b/data/items/items.otb index c064af60fb133fdbb07ade5354c74a553ca69be3..9fecdc9df2436c08eac35f6b33896d5e19f10b6d 100644 GIT binary patch delta 534 zcmezUuHg5Cw1yVO7N#xC-?SxlnHcU02?;WkXO<*qq!z0yBqtUq6c^-|O#i0MypW&4 zfq{WRfQjLukRXVd9M~&9UEmHM$M&;2%%x0x2@u)0AlbJ<(;27nh_t8ZGjC7PXPL(@ z0W>>OQb>RyIio1ExFk2RSRtt>F)ulzoyneMJCi-D&k1>u**lbhx_2lm2rvkQygASJ z_rJu=2{tdj@L%toIX#!1OULHi z0ny^=IrBt0*k-2y9X5OV!y^LX(+@~&fmjHLg@ITEh(&=|42Z?I z2kw`6T+0lMj_KyMlJe7|0y(*+r`Sq*f2oiNac#eAEBRX*B6vR%DA>yb m6y%7K%#afjW=P7fP)IAy$x+BpQ%Fk8$=TjqA-S5L@jn38*|vrN delta 120508 zcma&v30zF=|3Cg|FGc&li=?7NvZO^JiHcTBT21NKPn=WREcxn=6Ks zBRIiMhwGx94);~z1TACki(1A!R`r$~#2A%o#2A%o#2BI;Pjy^=80~Xy@u82-7n>oc z$xY#+G*U)?Q(P$&*ecj6*qklHD)tKpyuO)xr0E<#diCOUKHfe78uijRKE7{I-_&R! z{gQGCU81}fyF~f8RZ{Kti_$*L;FCc}kksQN{`iSM0pf2Q@h3?930;)b8^5tdv|(5! z?4F4B-YH4+(PMiZ(iUGl$T>lkE1{8R0`Vt&v5`k)+v1BpRw9yN(>S;&6i#B^(mjc( zrh5|emeOQO(Z6$@{=1i>y>U&j^EF~+gi<6pDHKXV&Q%fOPn7r*BmTsRKMCSblK7J% z{-iJFT$TB>or|IpLrYp9t4tHwHJ+bVzChNRHoZZLkN12UF^%)I*2%JxWXZKmlK0|t zBiWzw3_#OeEh~=--^CTHWrLK&B`EGen^iVM`1`8_ZBTJ{^Y;(B*t}WxjIhXW3iCPK znNEzkGo3blGmne{bB*JP8~x2e%rKTL4kC^ew4zSwabop&PE3e0QQd{=E?V+-Ss7YR zzc8OxJR0KDi52n8p*Aj-QzfclNx;5?ir^`Z z&-CAkHy5mouKi%jQAErHF&CJLJwSWXQ?(bW=(&=E>_yXF^t*b`eAXoY`xb{+q&+&t zb*G1%5Vn{^n8b9N+Zql<17aw&?L*r>^gH7jnqepP-LvBI1eSp>!}_VVJH;4AyEYcq;g` z$}gOK621mPtCu?z2%FRrPbde=9U>f+atKgfK2M1AMCx7H;;uU*d!s{q<>@E#14bCn9`ehmV?@jh^ z_vSe!#e}r7!()KQ0R6l!yH;PCLA@`3sH)J>CwVhFOb1K{G@DzjDHFZp^H~|5Lhb0E zE$l7>E(6ZO&AY-QsWP{0sbS6Y)nAj@T_#*6+|L263CiwSCPGUDXSmR)@jUD>3or|C za{8-az5R|-+v1&^3U*tCv%74#Y`BBpgFJ7hzFFnc{fVZw-AJ3=<-p~@eXvqLY1q5N zS|!>{=d%6hL58FLyVc|Z<^s-ZtDUYs)N~?Bexaw?!HQY`3`k)-CwXvraCLWgZ>pZt z-ss_~@%We9_G;Mc z-&?Xyd=-8q|9~AH$AHJ-+Pd?25~7tl7R*eSn^V0diQS!mI|0{mpps*JYvh*C(oYt9 zNnCly?h4@w2}h-ftmAVWkJ3I+^5(D1QKO1~3Q+XsRNOpB?XU{cu zcM9$loWH~ZC+R6E^QR^S2QTw05oC9#;ZDQt3>}FX-{a>kv`e!^dY_t#9TRe>FkT~P z0M7ts&#hnAsd2(RRh$0%z@uMDPYFoumMPdT6R-9nz#>3X-c*CyMOQf{S5KpzUObRT z7!%SI!xUq$BP}c>O171ttt6dhBO#&4cNP!Mrqf!bWEC|_@t_nV2A{bu6~~>wTf=VB z1RCGKDb|Q(FlFo`otiO8s*nk{7fmh`qbwU%T&Wu!#F*7 zZn!+!F{Wh1YiR8j$D~>ox&m|sXyp3i<_hho3#QK7KAt|J?N1m1a^=*()WG=aKlJR- zv3uTX_VSsBrS5&&3_lKWxvQvOMSbVeGi3*#`IVeIzSU;w-lzM>dM)a;sBgLP{6;0! z;9&#BspQJL>X&5w8tT_jKe&B%g?m|ZEKRg#Zd=unS6I37*HONXa*|Y2-kr_UhlwL1 z{s@gZ%~xsHCKJ=I1E>RtuZcKUD0EpZ<>vH`uqoC1$odV`Z=gO=Xnl*#1lj}g z9LzT)>o-xqiTa|{8JF75w?46%9QB^trEf89#$9f4-dm{O!ltUsdmH&Snd_13$=rb4 zK;}EhcgTDf`7W6oksHZ;5BVOMn~G2z<`(1@GPfePlDQ4Jjm+)H?PTsi?jZAh zyf_nw$n^#At zzuI2ltodBs_j;jH2RnQX_!`jLPNGCWu`J9)jax`1u=6>)djt1|3aBzuKK3~6>XUq) z6@4N<>uxb2bHDf&@GYF4wPvu^_8jL$I+epul$M|T=kSgR-vPb@tlgVp^hCDtWDKur z=wK=Rx9K0U2eJo}Iy_5YlQYlYkK0`$f_u02to=j2hkOrN72jEHy3#1y;MmCS%qxnz zf4~ob9{`6FCwtL<9|;I|E2urEK22Za57`UZ3;DTal7aJ-*wpgR4tys$9klcRmE=1A z2>B6G;7Wn^4nKhhbb3j)GOQ*&xMHGUhwg%otXHtVR9g1HRA1s zpB(Hn@MqweUHk!DX8AL<1~2Rz3aIZjg3=34F%_#up@ zYD&Di`%&*lefO1=XA1Y%O?HE&$sndf$sopzmG(02pH*WS7PjQ$5|56; zKgOhTKyv(FlKJxH1mpzV`Se*zT3&-oPX+DFJ$3CK_E#+z92Z<>pP}Z8iVz|3qJsEg z`Ndi6FIsLmZYm)4&cj?GDRaLcxg7`fyHpu(dgLa_1H=O(FW$V!@%Ehn)l;z>%{2Og zh{4G78^)8x3&#tmyilj8^yS^`^)dnpHEVjdF&%RUzz4?%x7M6azx6PQdcZTZk4I5Y zcgxQ|)(k%=KPYAA-0`~pGaXV2)(`Tl2m1U01poyA=dYh9|E^{5(dQe*jZGu_?Eiq{ z0LKA}oUg5T%r`J%khaVvR`vKxvwtLWT?;}ALO$%`czLhs2e1CmmXOom9~rZq1!AFa zrYr<5ltDACnjl3h*5DVQQaH%pdYEJvJhQz;^VB7m=3 z%mvK5;%-m#-N}<>9l4(kQbgfI;hc6Ij+>{r;?DHAx~0z|N^oAvoI#wyi@}M(6|U8{ zDSCKr*U7N6B9Au7Ww1MOIB~{S<)J?4M9CUF<~8w6uY+*ND|RRWD1ia%e>E(=aL&8m zWSz}13kRo-gu}ZUu?8_=NjOP33;xcVQ)M)2ULMxg4qVq&%I>7#q~NYS-b?Gu7m=J` zLSby1(x^yhq}uLR;*&v^$)L3w3n??USy{4O4()Qt(zL5#GJI5dG{|E(Z@0oyZPmp( zJ!_&CORifW%syEKI0ZOGQ}NTEa)V~ios#^+P~Iq&-6_H;!oAfjpRM%MZJ}D6+M}$1 z1P*qm1gDfiC7^3bkk~e@H@PMBQF*x+D~;QjlGsMEVw543F(O5mO3e!2r~7ns@-fSw zCFO);zBJ)f;8fr|W~c0UBF6cetGI9Yo!=7$cBcxb3RgQi-HFSt#&+%Z8%wXposK6a-Drv}IGo>abkPa;pcTSGB@G=7H?JDdbK3Gmh9 zd?LK<71q{j(Ihy!>Plm zPRy6ta{YbsH>+sA&-c0-+1(VlDR34l7Cm>1c?&z2_7_@hPZFcDLk&O;z%A>X%uH@= zco}=(XS-#S`fGMK6>ch=mFAuE=M>M(>)L}{VW|Ax=DPLff0763#SX$5;AZmdNW60?xkfS)j77S*xd}c8I0}!!J6>J zd%OB&gl>qfoyAM1KW3MDka`%gNRsb)kYUtR;ZFO(=J_K#*xgLHnQ*&P_DANWtUhG8 z#@jY)$CDg;>L>nlpu>EQ4d4vmat>acqO_&*R){TCZGA+M*kSew z&jFkRXj>tbcJO4~BY%sPX(6$ZvFvUx++4U-^hhqR7eIYJXl_(i&Z-$0E3jR4I>>Ay9a zf=|x2-*ifmGSS#f!}H+fdmBHPEnpwdJVTVqNihfHv92}qjjb05exlGi zuPk>VJ6wbT7s2h1pwlCd?Fjl5Rc9|G?LUW)9WDl33@Ba}keYtKn-wM=Ihn$&? zLi{6^cnRDR!ci%FN~sF>pM0-K43wLrBa(X$=b0q30J6Yfa>o9h-{*ffQ3+V~cGkza z@+`9yW+_bR+~he@^`;s^2Lq>EH8C|}8A}*T82WDyl`KP5r6p6p7VYbqw{g=b_1~#2 zgIWf4O24=N=K`T+*SZv!Jv;G`KFS)(3djnGZ^HY4*L1oRF(ilo;y9!CKUiux)N-hT zYl4)A`Cm1(tlRlN_6`)Y%nFzljQ!8ogac;2=BFLM_Nti7)SM>CLe@am7)Ug8Xf6LO zDYt2q5R_Ke%Vp$}^N&m%azXHg(^a6eBmiZN#U5N?WG>^bL*=n z7IFY`z(9t&^xxIWFW(*zIKd5>2Tcv;59L&Ok!nSLfVw-@NIULZy_mRksOiVyj_R!=#OyBwByh zsAJKpwk+cg;|`;}W5HeL3sWZ@y|n7Wh^Z8|e&)930pmd!DkWKE zMr7rqS!p(_cKXc|)(K`IPasbW)Ny@j`L+|wV{gjT>`T?YlEX4yFkUdT&1P@USgTX= zE2l!yqB+8XWj4TUfLV1hQ@mAhs6aK`BTG%q|J~?sV*gLRjJ$!ofvoG+&EM`3cShWK zkKL^oZx6Eu@`3SzIs0Jzl{ovOow)^J>Q!Y+p0SKCj4w><+gm#YwK>j++0Q(C=+@R9 zEVB`2Bg}s4(Bh(;eZ?HY%3P_>hXjrg2>*y(q#uwU&r>d;F?y|!qwZFa~CS?WSIb%0GLO!A4uvsYE2U8U3XbGt#t)qsLZJa0tEtH z%k@93vEY(p`?8mF`wwyCvjz%+34%%Ek53XlNb~w>^?pmoi|fl+CKx6d#`MjLW2?J@ z=WVUFRG6@HM;pt8z=XiO?4T-A)S3<~Zxf`CdTwe=T|g-26A}s)3N_=c1D|sBWB2?$ zl83VUTFY1_3?>X_o#%98ia_K(f5q7!RID#7WSMZ7a2WCUmtoUl)?R2>r`^=LP|l5IHp6U&@v2dvYDm0)onbmBa^}V4m!>Qf1r!BzzUIVn z>C&{QC)$d6{?*cBc8^d`RKFh_+iQ0zWYx2SK9o9*EH=sas2Dhw6oj<2P)A$8)@ql4+4;arE0*t1X! zPz=x}=M)v&i-%V8*XG8|^imzO8e?H%VIs||INq+l)1*oJOs8*X;2$$bJAifoRX3+- z8JSjOe;=ZcR{5-N-8yFZcS7xiQhgJ0?Ooy<-W{uU`#PkV8?a_64kiw!H>D2n- z2R*UvO4Hs{vdk`+T`g-Mbafj~HPU05c$j#Yce(fc-%ulOKajh#RQws0 z5=9{9t1$s60Vr;MPkW;Sb-$MIhW?%aeHE734YM0Yf90KP)YCt$Un|H~;_$;|x=K3#3`AUZ0kaP#*U0cxr_ExCaCw`h^xsua@PsgzY(LO`puJr} zw-uDAaa+G7wq7y$V1Iyx4gehhx{xogoHTP})=%pMz0l7WnNY1fB88!2sn zS3y%QbvOJMQBq)1V7|N>@f36wUY<2O?UwHXE)SMTg-L~3rYCfxeUo{0rG|{js?87P zvCJWuLojkRC7-utE&5K~WSBWFxF-253mpbJ4D|NYz5Vx;#0Of#KMe6Gu6#}y=F%U5 zIl>sI?1Jm~BWjz}4_)-scvqRqGBg+(%>BDZvgNIuY!_@kTGqP#_L%qcql}m1QJ`-w zd`UlKEp*~Js?M*(;e<&_Q$I?jkUqs1)$$@#;5+Xg>V1zQ$aN0&r>*d#3CKo0b zX8+-3%B3sZM3?kMU-d50nq2 zkyLrO{@m*k!vY!IM|)>;vj!@FDS(;qL?y`6LRDh&UisTuj(qwoa~$S43};NWfcHtt zB+1KMl0iSO;eCer5}}>|Isr6tqRwQtOXIh;&kr7avx=`^4O9qI2(#fUo!+SCXI?n9 zTv^5BdVC0Lq?14=fwt4mWnK+iS5yzWs*{ zOa@u#G|*`v-cMbtB-0hML^+=oZ+m?c?`zEYJ_BG2<|txnyNPWk5qy2Yk-!6bcKLhFp@=78$eeKL>LT=83_wD0AyQQ%&0$SVOB3?k+2IAi3xGL3&$}OXuYYHy zx5)jd8SiX%cQFIk3S9&&np3J*wA!IP?AlR>rW>mT*kL6Gtb{W>CRAtbYb#-MxA)-p z_*F9Ot_rRSZl?LAeZB*smi6IX5#jf}FSEN#aF+;2rQCSY{$P4*_|jd%oUV5!=X}`(t~tqdja7XG z?h4#+$+~Y3Td761@%iPkWy$`33|IqL1K6-7`SfY}=ydt7^%o0$p6VT8AMq;SRY2*| zo;4xPC)2A_{TI$$zj+b6tA(qDD{7^W`nt&S^i4jMLDlJ6aUp|UUW2>_S#xjNw*_+? z73^}?y^*w=hp!~YEX#Gc>u}s>ik1|w`e`ky6}R0vsC5^+tAne9tG{-}(<8TfJ>QbT zjX#4Z$Fzv!?=b`30K5U{#Qpdbee~ny=(Wr9u6lR8c*{QGO~9Lg?K@5K@8lZ{9KU&I zW2mI&r@7s{KAx{?YRGgl_fvm(If4l-3;2Plm-(?=V$kaQ4cL4v#GT#Nf z3;0rc``r6JyzNu>TwQnffua!m95%u=!W};metOxWs5hZ|uRc_g**=Ng-GjTwI1=Bn zFU=?LtoexRUXAOgS}u+G0u3v%39tzRUXYdgc}19uf4;lW@iTtLk?aFD!!^S-N1xqJ z|9v)dLa(Yx(a|)&ICj_q*aG-y8Fh2>;%&VR=aDu7h;1*vFY1!>_sEJ>u;N*?&ZI9SpJ6t>5{sI5Tu5KmU zsT+4F(0^N&(0^mo88c)DXb0%`ZDsb`<@Zc3l_uWL1wZ7TWQX?w?*p2f32gtI|Gj*= zElqyY$16tc?g88bxJvry(#~(Uqo*nDbfvl-zqVi=yX=JQgzP-{@^Q3T@W(?hZFHn_ z*0HX%WbEM|!aaoZ{}igEO*Jd3Q8*!W(sx%b`*>Y&U2wCGST)X>^S#ZvHhb8k{>M)( zj`?Gk`4QkFz@Csj8Uhi+v3s6>{Ls~-VZa>FguUIGH9yJQe=Kg ze$n|1<{6ovBR?ne3*;AM?ndq=^GoEHWPXMGip;N(Uz7O_@|z5r=rnP1T5rkrcW8e{ z<{so8GQUTDPv#HEAIRK`+)K=}wJ15xN3#7B+COE`IC2EY_RnN{AKLrK+>hK(<}b)! z$ov)gYX&V@Ns#ROjcgx4`#=V*yPi3%L1MinOOob$2CZzVG?{;peh7Yu%)`jTWFA2t zA@fh*a>>bSUfNl*Mj?pzsoXxZz8OS>hk=k^P_&tRYGT9&|D6_BldRbrxX5}fB=91z-o1^Vu$+=-Ivba z9dV#Yp`V<;5SuK@~z>2z6e!Z4HNd?8>Slbc4+$#&uW}$CsiB5}N7>~D{RVu{}MF2(M z=45im)TZ8(*jPiU>o|N8SJ91`uqd1;+_*jmi*H*M9*P$mExNR1O+C94gA;>0klR4* zsmnN!E-`qvD{@Md6+09M6bGb_R#)033h-Xv@TuOd$~I#yJCp#F0Gx8v*VD=+>O!Yk zk&M8z)pG1k5>67%=v29JTOaT4e(I%u@3o;z@3TWGKqi(dm*^Xka`0~%>@PWBUj8lrzM z`da{fbUQDbq^JO@0D5=p1?QU5E?ifxo0FDytBKvI!l}Y#*TqMT%pIQp%m27=vxXGT z62{EoL^$e1z=cYiFBgB*xmhVYd?e&Sk@uvA>Wz~sS<=)ln7a(qiUX2O%Hj|;QZ zA=M$*d#GG@K_AK)FK5Ql?YD#Q+uxL5;P54t^DE?!1Arfv17Bl7NB zd}pSXHHpj3M0w_amS>?n>p#o-DC?sEsHP3>*;5%jlavcJHh19 z8Ia`oh#f6D|Y>0l%C>x<{gtEqguSd-@MfZ0+b@j=7G;aZ;Y>cuo%04QQ zAFQ;M72_N^T<_m0d4aOL3CboYpV6pXk<`3|KAKQFUtprhU_7I{De9)Ew|}h~H+|6J z`m}7wQ&fsGFgFeBxftroc0I{qqkO z#O!kX!MGrkcroKNlzDkHG4I4x5x~1X(dph9SC5I64c*LcznVmBjkx}K5x^pVExA9A zZab6KI8I$bEK}lhJ9+)`V$>I-ej(mM*=bI#&DL2fA8szNu3*%cEJ1w<>N%@-9JWvV z*;06P*GZjSLNAHA`SBcZ%5v7vm)xmpNb5S2x1l28Y}K=G zSDKxF@quQlE-Arym$O27p5x=_WlnKM65S#tPkAqgFnTXX@8u{bE>snptm$vxoaQPn z_|#wyqr3v;6)01@8-<(#K3TXZjISCx$P>#bTcd1^a@ziJ3-;eXx=`qbh*o7yXau8d zgR%|EmiEOvB-C~N5|W+d<3ytuGs?Co+oJ3%I`!3HTVz6Fum^BUJ4p z72PHr=d~d>7e@d`fR?QtTb0#Lx7%!bGV_>fM*z9GIic=^dW=JKbJ2}m*7mXoR6>1g zdKvu}JEQK5dS%>}85_**TX^3+V$=Rep5rf@(`w+=z;6y1f122`j@!Gu$*(nRI!!fG zQbKMG%4<-55I8NoX(r#tweAX^F3WemXRMdCD6d7i`^md`^J|7ORh(UHcdy?~?pfEN zybfgnHM1pCSO1vHci_v1sTI;{=q>Alvde!?dp*kQQMMP!U8}QnViE75UhCnqyfutz zyQ1uhvZmw@N@Psi9cB0b znzpArOiMr>1*S%2p`p^234XAHGoo1XR5D==V+wh@!V|keR-+rIr4eSk^ zz#rL}Q`SASO=jBX2{k2ki)`}?8phkA!%+x13uFO4Ya z=bQ~Mr!#+_;g7mM>i$h%6Z54jB<~EAre&^JGKcIRfO-JxmoE3uoS3}i+%HN~aIdt9 z24ns$0#Oe{Jv};jG5z=Ds&<>Y*%K?zPVxK878?W|1l=gPbwcyhNXz(hrZKyCg6}h) z_h6KRQU2@xF$Cq1zxAfMY4DPJxKNZ!r^uF@N_ToEXbm><-D_FM7(5KU!%)_?jU8wC zxy*dFc~_^O0`2-G7`U-r3n!mF-v zo-OY)qmP`6_aqN{Hle-=^?~;;XVM&9Yi9G+_gxijizn-ms7Ipyu6e%m*IdDVqx@#a zhjv`d{+m(XjQWag70zeIhi;ka*>YXGaoSq4e-!FbsGsxXR11qq5#|c(-#N5xf)cH) zQB0Dtd*6cc{IJAh^D~dQNQ>#&M+T?MlHIqW`&QJ4wwq+WDcaW2$jj&Za{tR$jJo_b z)VHBdAAPTIAn}mm5!D$nVKblRFb_Mo18fI)&*8snM0eesl8b8nVNvE2$O%NF9*z2U z%k{}Coq}B=dCukD7Hi2R>r~VkXTG`WI|NTy_*fO1g!fI^TFg8wjX^yI{euq+dKTNg zTBC47@SzxoD0BL;sK=r{yjyJ|PtB1K1+#-Px%Gk+TCzQJ`FEh~?B61A*F85sc583I ztQNmCa`HRTeJASE-@A)Es#`nmQR(Vz^&OV?$&Uo$P>)0X!+OaXi4UTjTlU!$yfjIj z%YGiQ3vL%&y0GMrsZV2lms4c4+7G|@%I@Of;^8*-cb#rdnDtcP+&SXIdWS=w*kJ-- z0%OI{@^){y-@kar#Iy6G8W!$$V28T_cVooKUx%J+=+96r>e_wnl)K9xXF7Y}_P{L& z@i|8y<(;->{K-e2GBsN+vJbcya4%rCGxb+P-Uxkk!KX0#sLcY^%wcw#2$~3*q5tZH z-(u@cn9u=bcG#N%)9Nn*60?G8&T6@r1$K&{Joo)X7=4HO+bNxR`wcDR3!pi{43QSf8m^ z>{`xaXc^G_$LH6naH(*7md06a2X0rzbw2M>+sX0A3?G6!l!+g0Xgi%d|4X-j?@Hd_ zJDM)MH`ph981OI#yhZU14%Rs~aDx8ZzuVO#@{cF}2;dRGqLffsi%Bmv$14<1Em!)8 z@2$q13e(_daI=<4P`@nO8q5DlaH_^6IY~oycogs`V4qdfaB*ExR= zxHP!Qyl+G9yYDI#OnueGt>%!;?vBA7gZnlie*bQV*J*o~`Y9;y-JWU24$}eC0Vj1B z81_w8`lh4Wr#$se+&y-e0ha;iA?k0+eYS5-`-t<}Kr#ssQeb8XK(8gr? z=qj!i&2V1RyU)^-BzUO;;`#Tdeq@Iy0Z#%xG*^i#QMdbitVdnrc45g@ zc6SQy6x?Uan7o<*>y?RF&oY;P+V#(>!3R0SCkLnDPQz)gouwUEv8Is!yvfc%`J}Rl5HV|qQr?N z(-gxL!?dWGu3uwS)j8R zD7SI-p;Z^V7Rk>}kWoC#^NVFlVM<|KUV9I{>{9t+yPLAv<=qclxXzrRGMF+LBj4+v z>7)K@RUQ``D@aYW=pD2C=b+9pMtUUM6|iiJuwO-Vd|NHwn9E?xVaj2`KS`Ti8@iKb z*T3h7Ns+)}*3>FsDqvFkb?5cAd-AsP#W?RXD;{E*^DyUOsPd|V$(#Cm&eqMh@Y;J+ zam;wJN`Z_94pEa+uT?J~?|m`5Y)FVE;*N*_JtC#E@fucIRiRRdK6Q9sud z(j4tpN^dA~dMUM!8yCzlm+cDB6`*>)i`2>MvZSV+RXD3{zp{#DYG7($BJ-;9hMtxv zN>z=#2-y*`oMo=UT!k^-t|E~!w>Gn&#M5|9P96_o9GDZU1*&DB+QuWaXW^fx4KBSP zG-(+w1!S6QFxOy8c(cw$hn$!EW_3_U#(ru%VVL{Z>oC{J{j00D6rXGz8tTxg$J{$< zFf7LZn~G@clxLE(Sa$&l*&8U|_^-0uO_Xo`r97NEV^Cb~7Rt9!u5K^hBS^bHOP=z4 z;An5QbSlR)ak<+l-~P{XJ<9ceEo1Nolp9bE3v#{kcJ+wKDq;Gl_5_tHG~0LL5^{G? zzw@7U`Map!{agJxW9A!CZ$$m}G{0|`lv}42o93#0-xY1onE87s-}}#U6Ut40EfXi@ za?L0=qwH_tp>$J3Fjqq(D>8m%=vv0$EhxAAXSo&S*1wi9cpJ)XDEk)nan2~tdUDuE zEBV*_7tM^p+fi=+&vFOK9e*uj@cSs=M_HrMB=%QG<)_!{>bq?PJmxS4e}M9X|15W+ z-1*ls27ie1LzEp_C!~LLA9O$C8eku-wbGq2co)iD|5<*7@}vJOKSud6%GGmd&*nc# zP~yH<96HaBXDDA8bXd8r(^^1!=x0E( z-rL7C(VLn@M<42asQ>*oAN{EJ zqyG2Xe0)Lu3+jKr&4=7qfUf|5-sXc=HkVgi_8aQoQ2*(vYE-kWO^Kgt@uIquQ)waL zToQ5vC=Z}KPAqVJ(yO&2w}Q$=!aJNj7%%Zblm}5>e`@9#<^TGFsA(>Ry%Xykp#neYA0U>OlG{B$q%7Cgz`Y; z$2a^EJc8aDuJ`G`WwW~&x33yTeHitSph6$T1N>Av{3@_yAnkT?_}rp*J#1NTF4`pVs@^OFvHO^;O( znnm76k^}R{3&RWZwv?ks`LfqIb=UQM9FdwljC*i2G3JjPjt`VC3+LayzIu~#_kYW8 z^4Zrex3TjIV|f|l@dNQ=ye_SkYcFazMd}__f6t*a68Zm(Cjcq{8uPmJhVL)xsXJbi z{q8&5#MSr29W60?<6y?Y^k(P#*Q(9(FQ9JFX-}x{kN$tg6ND9n)iWVJp`1&nCrU(I zs8!(*6=4l11SACX^x-*?+SRvTD7PBgZ(VP!HFiA4^D!QDJg5^zA=DsYysNnHPJ^4& z95XG(cnmZFXadj$t}^Rb7p3XNk%pSlG0VTOj4+Ha%y_OX?=ucg%`+`|_hiK6>NJ)S zff0dGe3Y8F=F+-}avLiLy{9WaVHr^vQ7X{#O3yA@V!JOE$ zf2&`#d(96!Ild^oMcng3g>{{mq)VZ z-qG=U{Eq!xRT@qj&Tpq;-iNO(I+4%iRVEu+|9kFBB_}KcC<9pJG=8A@2}SADqBmPj zOuG`<2b6`Ag>$&7^-ImdMrFCNzjtSFh6%fqgOh`c|9*GobRMp%GtOI{n($1eu{(Jx zpgf@1A)ZuW4mX~bUs{?baRz@}@~8l(0H=BMm1j~$bLH?*?~v`ps6Vd9zyAUEo`i*us+37^kiJ&X@tSO24!eRboD((FzwTGPSP7O{C&TvTIwcxAanw{4> zZmborr;oD3Nr008^^DS_o~Y(Iy{4AQ8-KYV{>MjjlL03KzDQ3!Q?r_5UCfUg7G61O ze|$cr4yO(`#8JzU(XD8=``H1X&1Vncn&>f~)=Yt$0=LGg;7#Fy6Da4OtXxSnqVY2s_b%gfSRHGBG&{qb>ilv>^H_=U1K`;;(OhMdBz*UwFx)oI(6!F!0CXd zS$EEA=d65@=U;Qc0#JBs%--N#cmWgS zwGHQ3rLBvqjsD|C8Z+Q#Fy4Q-Qr2C!;~L*^%k%UrnOpVv%#eJ~W$csn0QE4ShQ}g> zH0g@T9g_=hONASd?|Te06J{oiYw$1SPCET()@rrry2JtV&8$7(ETCCH$_vkG==U#E zQFXATa`pOrGGifqAblVie&N9GH;W{c3!G{eKJBCbW}(?Yvw=buajKY)YG!hnuQc7I$Qo!K%siOC&9xOdwfR8vf&42(trL^a zl^?pVP2J&F^4*&liHQt>41pf!tQL-ls=u5N?C#yvvBI2X7Qifkk(W8c=f-ie^qYUb z)rR)%#79g2ESeFF5scnezAGs;0UeK4=&Tg5a~t#KW=t3>iZM{=#@tVbH-^@Fe!5Bj zy^w#(ch*QI7|8@^Ip>lqgLV2ohPyX!`|c6zOc)Lo#)>qBG0mb0WO6D0bKmWSXj_PW z|NcUW^#dhW3ZtJHj9C_~dpegmh6^T}&CzU*u7CLf6tn9hm_;y84$rjP)0WDA<3WW5 z_p#-#iE)@_G0fsDTF4w8aq?+r97Qfc^AdF3IDNwdx9uG%c7C)~wmI(jof>hZiA}=- z#)3Rf#T_mAmZD)P8YF1VCbB%#P73il!JdIR)0P017krPOro78krMYo`qjK zEeA5^I9?i%$+I__{#$#Ab#LkemRf<4Rsbc6U$*clFIbcNy?Fa#?i&*b^MY7ZVnMB8 ztYL(%oxQhXyPetk<>tm3mxrRJp|uYJ+~Z=yzyJSo2QPJqq)O zyRBMZ?inWf*=C7}Q@n%xJ*T;c26?!7dU>jN__K9iiS8>I2W~~K#eO!ti(Y+GN_#(8 zy19qwzcNcqltOg%BW5|k%_G9iC&D)zx4UI7?<(|Og^3SToOtp$!cnmJ_5-!XH7@o< z=T&1mFZByk+29u8?}-CwW@kHewnOLRRJC|tr@|w=eBS2=+YL=@iQaZuV#J;F$w{NP zkC&Tgu&?+ow?Fm-%mRBXLME|wU;K1)n&>;N7SzM*bmW2Wzb z?hfcaLXF7{%XZA;TNpr{G9b-YKy-KbqkEWJpr@PvnC_0~?uhQCI&W|OC>@dtcXuf% zNqwkH^mfb=BQ{Ic+=m5wx#8Jn-ZkC{eVx$vRJzUaSJ$YkTAvxOr0UpkXEI+0Oy~^g z47m1|UHyjo-omqSui_tu>py3AtKn9|Ij>YuZYaOVuViRkbUH~QjNPq)TLV|SDq!}z zy!7=6dzGu}sEskKZ+aLn*|mUc0VPFO%`eya@~wtjZgJo=NqhDI*TJoWo1(wY@Dp{V z(FuL;PUnJI57?axoD19p(Zy2^@(p=jFn&>7P^jSpM`f*=^?>UEtM7BPbKQEA@>90X zRq@%qboK#V;auUa(+nfqa`~2Y7b)7joDkc|?%d$q;7Xr9dGumjtF?%v&c^-i0^k01 z6bhAi?YaZH18ymPt>D1x_gHbJl=b#Ws~pEb!g;`XFx)`W-D5ALjJNa#yX!jym9aZd zI8V4#*=-6d=BZxOev@}~kkb0cRn%UDqf)#8Oh{I^wU^YgyNz%g;a)%b_9DeJ z;ft8_#sopZ3nT2#56%zn@rz?V>66u{A+gQZ8a}>C|L1LhdA{He=npvglBQVfpvkR% z-M-B^IalygxG^&r02cuFm%D7jagh7xK)66Sy)DV_w-qlMZ=rr)eZgdEBkpp*L_t77 zKqoSJ?vAY3E#*10nojRKuf}-0S7GewgMos9qSk7jY&uq&)js9;U22iYA6FWLz=gn_ zm+Wdwv|Et3Go;CQjk`_X*d-wL|Dk}PfF9MaSG&Zx?C;lYuAJA9_I@lRE_#9sgA-k1 zw}X4bqZM8Ol@(1pE&jN4Asj9o?(qs`z1nvlr4|m(o)M)lKa+jD2smm4pp=4sp4!^u z1wUsS3P0W-c#a)z0^9^w_WjUFmtBFC@58KDcj_M7#O@;DBH=_1{cy4ie*RgRQz&Vw zu)`B}w;66T+=0VX>3d~-xu+)1lit*3<8_rCMgc|vs@>jRm1Ao-WtP^=Nu5iR*08%R za9iN6`)MS7Q4{r=ekU>RK>I?rRZUzt1-BJ0x_!j-{HDF9C8_B-y*mOrSUXk5bG!|3 z8(_ujuI17FF)yAkYRKw;e)69$rWdmNhL(0x4j#vMj{ z{a^Gaf8y$V`R_$5#AI-ovXj+EIA*P0MeNF`0F5 zi1*WY96Nc0y15gFA%Vm(j9cWGcj5$eO+eR~#WlulrNJ}8t#%rlm~x*YdM4n|$=^4~ z)7RgNI0OmA=>c<+yU~xj8y#sM-h0RF$~>ATrz7p(9A8d!+?^#hp7>w+xP>w%=@S%$ z(->yYJ?Oay9q%UHFq2g~vUARr8*=Bn4QhyvdoZs)ZlS?Z{~YFxnb*DOxfeY{4tMob zTE|f*G`uU%cUhGmM0DMoB_>Jna0?Ce-4qlS9_s7i^Un~hX(wWYM8>pN8Y#KHsLfbt zI{iX~Kym;vKq8JiLVbJ#J-xg_Ronu@{k=jlbyspF??c~x=$oL>ZvM_ehC_tkM+y>3SMER*ny&iQWgX1Z=(CLIZ+u;Kf`4 zN$8%0?$@%O>hP>~F{GO3-lN#RJrPWFPr}6A{D}n!@C^%}5~ku#9BYr6^`qIdE?vra6xdr+X)pS@GiI|aSPx+Kh`-zdM=mYaT>dZn=Q zA<;Vphw5Xe9T*hu73}88n)g)nPep(APqcN_(*m=nUvoU39JcoX(LEJUJaeTpChq6! zk7tf~igO5k520_9V6CqBqz>H$JUinah`Kq9x$NaI(BUlF=prs@DzoDev>idmzua1_ zpWLcwFf^FI+z*dafJ8@ujsj^lF7z^yX!x0-IW280kbbYy-ZGX=DRmnhxAG~dR<3<|Fcuegvo^Y z%Pnq9$R){w$%0uXpX#t*mM$tKA#*NrE}8R?^T?c!oKNNgtlMVs++f-*1i$t+r#0`XI5e1XgtkuMTv8Pimf z?Nw;6%A$#W97p!OM7Cc>`(-j$BUh983i6dKT5JGwd26z0Zb`(?y3u}>G_}aJWWI)c zjm+1PuamhBxsJ>?kZ+LrCh|=(-$K4c=G(}($y|?IPv!>X1~T74zC-4_$al%yh}=l# zd&u|5+=Sdj=4Rw(GPfYNkhvAPmCS9(ZDejoZqK5rHVTu=-jPLXy-ob&9PRf>^8on) znLCj?$@~!cA(^|7yNK;-D|4JjWcy>ZKh7d=BY^ybm=Mu-ypvswg=os0QoK1{to#anR}3X$owApJ()ise;{)& zaxXE@xQzhvN3#7B@~15FHUh|>$@V_vJ~H)^HmEDA|OgWHWY19LOAG=0xVqCT}Bv%tf|yBXg6P2bqV=yvV#{ z=0oNqGe0svnFWvq$UF{t9GL}?1<5RgEJWt<$m7X80eJ$Mg^`8HEP^aTW>I8OGK(RL zky#vBoXir)5@eP{mdvJc2ooC-vQ#$B)>ekh(xj0=yG%CuKLJ3NCEMkY<;X0LET2si zok2XY$O>e;BC=vO?Mp1N14dRN+m(@(iFLb`=~c36szS`HN}7o<6UnTGtVZTZ$dkxC z8F@09)sfZ7JOz0QnKh6#$UGH!Dw#ErHM41MJ;WOYvKHB{jjT=PX~@&aJRNyD;a3s= zyC!5EvRxNhm&`MeXOLMBS&z&!k!O;57V@lYTI@q&M~IL0&`Vwa9CUW#?x;zw5|$7qq*Oc|G!aGP@$XlGzQ}jm+-I z?!>gX#K>uRknNsm_awFlW#)G4MYeB1`vx+5BYP9eXuy0e`;hIvX!j-N?K1Ou*+{ng zq1}(n{>c7h4nPhdb0BgcnS+pn$Q+CuOy&^e5Hg1%hmtuAIgHHV$l+v;K#m~uCge?I zjzo?m=JPyrzpyA3Y8RTv?#mMMiDK_79xqtR*6=$&@P&KuFo9Z=y%`G^Ze86J?DI` z?_4u;&2na%0Vk4^;3RS~oJ>xEQ<%$w82~=bJk?+ZfX|$w830bD{8{)c`5b(Xd>%ee zz5rh!UxY7`)8I66I-E|v1YaUwhA)#d;0)$E#0&suQvC{ig`5RvF&WGNa5mMi!dIEw z3o`(Gjq2Co>*O2o4RQ{g!#ves27qrePhXe;;9Hc*g>%Vya2`1y&L{1wkbE1y zO)i3q$i;9mxdbjD-+}LtOW{&-8C*ub3*RM|!{y|A@I7(`TtU7M-zQhXmEOkCd@tY ztGo4^d+IkWz!S^lcw%V=fO*M$FkdXq05Ct*1z-WPAS_50f`!P!urOH!79oqmqGT~x zj4Td|lOWED1}JrC=$tG%QV)fn~_Duq;^)mLto<^071nzyo4w27m`r zMgdlcr5ONLq`DHUL{^5CV`&C}2T^@6JUEtS09b|Us<0|^-C_oS)naJ|fYm881Rg@x zfHlZN;h|(rSd**;YmtY+!^p$o;bi7xK4u0WkAz3Y(hLBPqWWlfG+7(gChNdDOdc}; zJcjDJur65-)+3LF$CAgvI7Gz7|j3m}3$%06drK*043%2DTy3gXfWLVOz2tY)76C&yS@U0A4_K zd)S`r06UN!VMp>pcp-BC7k=ako0PrTNZ-zIM zx4>J-0dN3wU10`*w^Dr@ye*by0C+pqSul$n2nUjPz&m1T27q@`eHXlo90UiEcf-45 zX$FAzP(2t9CWpWwl97#S5A0|h^QOxdO27r$+7X>o_%%)5<98Eq7A7u_b%mDB)svn1slTW}W$T4sX z`6PUjd20Ptz%sRlCud?uD= z063NMXW_HtbMQIxdH6i}0(^md5xz)HgVV_Aa60)Ce2IJ+zD&-5GnnfTGXR`P^(*id zau%G$WH1B3*;Ky@UuAAD%mDB;s$Yk%lW)K`$T@Hh^HhTw0KUmQePITGZ&4-}&L!u; zdE|UJpIiVJkPG2L@@@Dwxd<*I7sJKm61aqX2fjltg-gk0a2fe7e3x7fmy_?o_sA7+ z1^GUFpIix7lB?h<@&ot*^AZCy0Q@kPW&rpRWvbz7at&NVu7zvKb#NVXTww-)>#6=2 ze#|`lU%n^DvG7>(ICva+JUl**W&n5s)%9V0vH@&Bo(NBj zqZt66MD@w=WU?V_NH&6v$i}cSc?vv*Yyz8*O<_~A8Ei(L3Qr|ZgQt& zwu9}+^Wph%Gy}j3sBRD2lO13OvLozBUI;H_j%UmO@FJ=^!A|7G@M7k&V+MeiP~91J zCcD5cWLMag>;}7$m%>Y#^TG@OFQd9U?9Lnym;qo9s(Zqok<}zXifLBo63-)66 z4Ko0|lIq^DH`xdFA+Lg0kypd3$!p*>WM9~q><9ai*TQSb>)>@{f7qYA9$ru00B;~~ zgf}w#i5URiMD@+^X7Uzz3poG|V6H370Pt3-Z-ckR(F_1@r#cH}kptmC@(y@M9L)gm zPO9&McaekOAo6Z_cO159gB$-~w_XTu8nR-zFEqMdV_*m|Oyvkng~E$fa;8xeP8N z--Yjz%i(hJJ@_8E00qZFayA!ss082!aT%c27tdZ*BfR4_#1OS#S8#{r+f$8LH+^% zAa}x@f4Dzc5|$)O!BS*t zSeh&Y%aCPZS+X1~N0x`><7ozf2gK7101u>$0;~{EGXShebtPDdtPCs1(+mI)qWWNX za6HWbunN^xVO8e3#S8$e#nTJ`t5aqOJcO(PYmkS+L&=)3CRq#CA`gRyk%z;>$s^zq z7uF@~!FuGe@L2LVcpP~=JU*Ug0C)n` z^gFF+S8Ba3+Jd5hH;n`#h*n(^cTav9{EAkw84s%Rm27u>M-5Rzg z+rT#DdGI{4Eo@7+gYC%k;ra121HcQYZV%g&9bgBtBkV|C2rp!gXUqWbBC0#VPUOY# zV&<}A27s4P-5GW!yTC4FSJ;*82D_1$!b_R+!VCZ}qq;ln&KwVz0bmcRd%~XNfW$7*$4I^uYy;RSHr8xYv46xU)Y!I2m6uN!fVOv;B{nw z*q^)}UQgZtZy;}kH!}N)835iy_08~R@)mdtIRFk|t}Dy{@K&mCgSW-g3;=JZItylz z1K~jO4tPgA%>eLDs_%k#k%QnM@@{x{Jk0>`9;ye!!Q>D)gd7ToGLMs(0pPt<-v{p_ z?}zu3!{9LT0r&tp91bTRgb%{B$gyxNIS!5^$HVdD1UP}52q%)0 z;3RS~oJ>xEQ<%$w82~=bJk?+ZfX~F!3;?H6{w#c!d=5TGJ`bNKUw|)=FTxkeX>b}j z9Zn}-f-jLT!^3@#(zh3}Hf;d1gl_#U|et{~rs?~^OxN^%ukMScK3U|wQi27n*N(+mJV zqD(bhO|F4!$hB}Sxel&ljw{Rna6Q!@!;hJVAIt#o6Xv`y1Hexy(*QS+pTW<_jc_Bm z32q`kho6&Qz%R%z;g{rB@GItczzhJtrurNB4Y?U^Cbz&X@#Kn_#M^X z!|$1whnNB24^(f1+sN&3JNYC0k^Bk%#N5{~1HhlD{ssQRJj7xKfWI==8)g9b8*@L! z3;=(pdo@n*Z(4vSfywbC z&B+v{152TC&tdKx60IW!LC0L29 z3@azl3;++J`e1l)0?h!h3e{C%Rpz?I3;?So&qk$?#;dA#6xCf{n<=urYZGJcVomn~+Um zQ?eOsMxF{!B~OE=k$ zb4+3efag-(8n!0ez&7N0@I10DY)iI-?a1@t`3W=wzze8u58IO+U_}b+FJz8q z%mDBrsyo3>2lgSaf>)7O!>h?_;5B4l*q7`F z`;pheYsu^2b!30opS&JkPu>7;Aa8^>GW&@c0NzCP&G2UO7I+Ie01jZTE6f1!R;q7< zweKost3ctma`HX+9=QUpAm4}YlPlp$aur-fegHpU zUSePdfFCB%3;;i(Of_6hu7PXFwQw!D4z6R4E6f0JJ=Gt>kC}%b%mDBc=DaWiz)vaD z05_1I!OzHza3i@1ZX!R2pOas}FUT+9m*iLQE9Q8>3;@5T`WyHSxfyOIx4KWr zkVrECtVnewSc$9*D<{$n01u-2V0dsM%>b|p)m33t=DNiU0IMa^3;?TBW(YiltO09~ zhr&b2ny@BW3)UhJgNKoa!^6oV;1T4J@W@1(0pL+o9}SNtYs1=P9ax9SV+Mf7P+b?+ zCF{X@;K%NLsOr#kAo<#M@@MN+fY)CeOjmXBZ zF?k9+g=_+wkWFDzcp&@K1Sw%*GZf4c*(!Sns0fPnPvA=Tv@D`j*wdd_Sn zGBc5Bo!^kUZ^pooHP;+uH00Ia_he=vGYc8F<-S`NJoxn0W9_cAr>ZVfutO}`quB_} z{`b(I9kM{i0vXoT=l(h_+7~CRKG>Fa%Okhv%q)?yMCQ_sqzb!d4_4baNM~Qqwg~OX zSRrGDO!kIBtXlzjx}0AsQ(xukX|G7ZF3}#%L26ES>hI8>U7Cx~T!gglIP9sa*d=h% zd-3EK&u4V@oSii?*2pXzG_9d-?k_WQ$OG;ojI7oqMyqR~o*i;T z#u1rLjkJOQkDpWeX?Di9yX|_^vqKA!S@`dnKR>g#2$@C5Y|3RvSc%B6)VMc-6Y5T= z*VgeqFTeL)XhPS0ztnH_Cd`kOaeqpga*L5$j9gWQfUAj5n~nG{_AV7DJ&aS)5%_}D`q$M?;-A?LM{bh2Mp69rxQ%N*wXcXRII0!c9c<*`-YOml zdL**bE)5(g;E^b!#Fn}|P=RGXdp7eUQ@m>2j3+XlSgfC|iPz9aPXoV8&dlsu8(7i3 zbKSY+$Sp@Mw=?frbqh3s%Ff^QR5_uDBApmB{he&wA_<`}FMLOI}9Dc238yHsWgT zUe6mjZ|)xUpLzVqSAVA*g-z>US1aKcG<)S(J_!0Ccv?2$;Ebw)MIWxY?u}ya_3s;8 zh1@FSmOk3LZ_xEjht|_t-+~^NaDMd-u10V*f)X=Cc#mv8>bNOT@8P_?4_o`@)*!cr zd&qcO?>f>yF!{;TuMrl<=XBtQS9|TEFM_^UaL*NyCl?MuXsjC-05~Jls=1JFO>&Umf&E&L26RrA_8%S@upWf$Sm8hHGs5=GG&(9yt-_ zFPlo|S6^rC^NLSdS9DQ)Yv1GsBsUXtT-W;T5-!ii%ev+}JPugO`Z2t3a5I9N5j?QbQ`^aH z&G?otw`=N-%*M~__PVyWAh!iMr@J0mHe+5@#(4isS|^l*pP=lO3qURaxeoTL)#txi zH&kmk`A)RooX5?v{yAc|BDfX7Qx(<=y+(fZ{cL}#bB4DPeyg(Ag4>YWhMbn~s=Oo% z-!sxa3tT-`S)A&d+m76J#as`e#Q1p?!uD05X{Ybmw8j|mS1S{ zNjLX}?#X>~LC6ImcPZg~_I|yqCmrG)Kj$g^z~4dWbsg?TZZ~qQa?!-JYsQYeoo%05 z#TN+S7khgJ_aL|j!Hxd43%-e)Jv(^j(uf~J{P6p_y>h|G1tWKRlw8Z?NoS&bm$`ag z>)gA&JJYw?L}@ca!&h2JEz#Qr@UC5#y9Yst9{?xKIHZxXLKMYc)0Hx{dK16&I&zb ziOKd2?niJxg7ekAbY_}rU-8|xnlJBkzudmLFyz9JJMq5Zox;0)dz*Fcuh^?Asu)kibx=Oxo`BQwW;_f->)U^s$Xc;h`f^zTenIWtH)Xo$mK zf9&NTatD#Kzo--!n=|L&xh3-XQ3DDt_C4c6$Q?p1G&o+lKt81`XTztTw#$tATrTYO>W$T79oXM|U%+Q-U3T|^-A^fz$VDQzCSzc!RpBw=({;`DiE1ViOs?0l za2UD6$jJ?PYWzGmA^N#tM!C1gdHl)YUb!gbSWyUi*9eEzwjDduwoz@0$%4l`eS=33 zJc69VhoA2wzo^Gm?U#6P?WFyB$PI;1MbI0V$VaY?bynTF-|F1h}G;-0% z1varhJ}}V@T-DlTddYmD%cs6)d=$Z>2yQqaRh)S4=aiepq5Gqj4m#X7cMQ2>$fXy$ zbAHW<^+N#5EP%X z^{nsk%{(>rt0tUVDWcpr7lT|3a)-@@+fMm?+Ft18WF}*ME~RhoByuN_TM#vK3O_5R zEh%Tu(URn|EQh|qQwW|ykXJd`@8A{bXoITHA4H;n>4hIH zViNoWCXQ;6jgjoTU;=Up$i4rtM*8q#pV)_qFW0Mgja2BHOGGXaxy!ZZGSrQK7Nnn) z`+RHF2g^P=7Ecm_NeHHu+z}Xix_!rpH_J!9l(rY_6XZ!oE*Uw|Af1(bIaMJeo7Pm> z^1gc5HqO zci$DyAbAEWK2g4RuiAI_+9M5d9x;16*7wb&BA1F>QQG%g>AFQ7D>Q#x=y09#=f!6C zRect@v&c>CV97<~n^im=uzTvhxl#S`1Mt0WymJViLoluJr_9dSbN(vBR8n$g#V+fc zJCEFX5yWVcpd-^C^9E7m&MvoZ&FT7Yj`#ms_#2AKp9}Vuqjo?sdi& z5xj`t`h10{!hr=k2j41MA2js&>y=y@a%srjbqV#a_Pt| zI~Ba#$n=Bmw|QE{ChB7aS$%_-5WIxoo=0h#;~zDJ$lJ|yc$Yssp>OUoa+i^-=KRw2 z7#13Qu64gsf@YEUU-y#?1TzqHZa;WHQl;safs*c^ed7<<6 zh_2O9>%AcJc?WXWkX!opXqd0cqLEj8@^b1wPZ-%ZcO5y_bp*XySR0O5%bJaC7&T7K zV%o00!5awPKu&Iy_Fnz;9PO8bHWj@a>iXB=m4jRka?%Y;qsPp289r4!b;4V7UHmok zUPsqWlRB$@nF=iyHbaSb|^) zf~=P4eKoENIh+rz8%AzRy_?lHcn85d2)@2sUp3&&u=QoU`Sq=n;_w2x*B+K4SK8;C z>5N%_opTw2We6TNyt{P|!F%-XF8;z0s{(}zY+1MI=Ml?H zznJT9}kKEa(mt5~1no&2tZV&$>xdO~2F2 z#Wg20)1s$aZ*EM)rT9wGM#xfgjx0j$?y{k?4b^;W76 z&)U{ESdCycf+y@NpYC;d+Ug&)?&;*Yi~qb}?Y<+{AXkGN|CH4Ve0OY(Kbwu%dax$) zVBhs>k*h^c>U_3IbL{4~ou6;A%2rMarq}5I+_UQttV3|~djE8zac)EQzcRGBW_{;J z-v#TDV_q3EH@f`#bE8E&e9KbLeODFzhR5<=SM_7$9wVo%HK=Um$%aaoVf>PjCss2< zKJ&!T^N{ic!6)3{wv8=P-vyR_W8|uv42G0n~4Ei0^AeeUHXKe9 z?_P1v?}HwDN^9J=F@MVJ&yK%B>J?H!vJb^9Cuxki?;|{``LNnXCWANB@fpW!gkJx9 z=+7>_LFNrI?A6UnMTczU(b~0hWKe-!ug_DOk!eOoX36fLmrLvC_&$r$kJMY;>l1|* zWLl7kf6sDUb7jx8kfGKO@1&{B7}s+xwIb9?p}#YKcIYiKZ;=tuf0Hcgm%Lu~qq?B9 z=BBGXm;N0x?~w66I%%D%Ex(M8ak#BO%Jpa54Bh_k5qgi1U#@Y4X`!L^i4R=`a}6(A z_3Y3GWIp_R=FbkbA=8G;qa^p$a<%?$Z%#ZZmDD@N{6U&OH%B`%?Z~9^9NEOmI(AZ4 z>W#|Eq-E(!J)w^XeMD%gt?>RwcD72jr{e}ozf=tG*`ZI!eERpypB?&)%x7edHSZr; z82RmLjenuc$riEV?(@PQRQiI@7lfkUZm1qApna~T>4N^dQMnR5JM3WWN1-=Fbj&N9H>>qdX{t^E+};n7nWYiXHUv-w*f)xfAXr zcfnoEN4NM~9sWsABDdBl2#az!s4)MsD-)!YrFhi>aj)k5;#PklC^wL~%kwjL`9Hni z+}>|)Prkcn%3Kg;JDwzFF`guR0;$fg#(bE~di1uj?oI zEam>ac|NrH(5|tX;(PeTse8_H59&|s7@Nj!vgem&@uSa={^n!bZ@-FJFsI7%-bBvt z%E6h;S$Dr?!#k`32nry$N_uq0u(_uFd1t+TroJty*FcP%Aaa7p#g(Lvo3)dbTIb?E zxhcgBZ}aq8PY5|77J@VGx@kV-_nrHAu}pJSpy_7{@^xQkVFZPdo2R|_+i^RQq^fB( zxz-+S=)(s2Cplwggnny^V-Ctcx34HNqR7ZKOL@j}esyh8%`$xJ zTxK1A6xTjo!(vE@A!QVGpU>$=dQM&9S2^DUvyb$nvm!68#?pct8^U9|U+HWfWiqcmUhiQBg!#5e3C0 zwu`u|yd z+>&Gc9-aI2{c#*~aG24BRYyi0nNHS@{yh5DX$hN)GFOaG58!6#adrqoLl6=ZcZ)MQ zmXaVJA{pZ$&0_vo;Gb(v0~rluMEthS@wj(3wM?@l#=z~Gd{1U5GDDHsTEDRBlFD4Y zf@O1BGR~eB>B(p!qlwI=R{7;DQK?ChN=KgYnSVa$))Ue~NDHCs<91)W;e7dl<-23n zJ9#rMF_&JDuAyPb3`6F!c%0Vdr0?tyuPv$@ABm6b$qYwkI5JN+c616T2&a8bspkB4 zdD^T?Ar>A*Mj$l;DgXIiGuCbEUwQtqp}X)JE!=3`=Qa|Vk;t5DXzn*wC3ouS7fA)y=zq^Dz(nd-fDdC8avac2I zG)H{iY_xKGEA!td{_K$sGCKdUN7L!nAA`&oWU_9jTbn<$+}3<@%>0J?qtlsnkiqke zE<(BpnfKQ(I&kQuaTEX1;5)~kGoNg8Lrg{w89ijwbX;$^bu=g+cG4}#`!H%{Pi8DK zW04ua`E|vq!ZK~2@%Aq-O=KQuF(EU$)y5$-4x!B#mb}=&a^cC}-r@gw*QM|x3gKaN zJVN6UlC0qT;&AenB~z3 zZL#a^m=`)cX3YH$`!^Y($q2pDGJIt8NqPi7=eLnZ|9yILJqwyL57SK65LrWHC7s<9 zK7=jGEf)*&*|a;dl39?+U_B#bjQ%adUGDBb`^UTiV~ngZvObHSPKmaQU1@Sf%^_dI zZx~%(oaYo|rXVwPnbHPdy*H1v;^!RO?Y^TQlbJ>PWrB5WQNdmjoa^{%cC{69=q!K(UQYq zUef=$1*Rf26`|n;gLPGm#}%`pRSRo2zR~N+Ohabc|23n{V~&tHLeHW;bAEeiI`Xg5 z|5VXZq(7Tk$&`-T=?G0vV*AZ!KDZB5>MtNX1C<#`Y;|6lF~T!(VrCM3mjRxI=b(Y? z*mg9)tRrxhTxViq458ZSEI!V;l4@Ra6@*{CQ8m`yyB)XH6S6)(jM8*`Q#94VS0Y zn(=*D7d`KNXu`!Ep&`uW?taRfhs-==s-?F?Z4VlvAyPI(_vm9`gPx2nGPcNAiOhX@ z=z>Aud=IrU&aX0&lRY6jgzOM%ZoW6QCZ%yQ%SxZeu)$$dK~HEtLh}*&Id;0|n6T3- zSHvE~i{6vqJ}(AxpS%|!vjCZQ<@vXrw8b;Fo?alx`MqM^jh=<<5wb_<@~a&uUw8RC z2(FQ;OR4y>ws zz5lGRfAZm;%tB-qA~SK#wQF)m28Sv}>?2st4%Zf2eA#k|<%qpP01;QY?k-ok{spU)Q~v>2f(V;L#gTB|qJ{tAPv z1D?+XaHTvYSL+dUpO#TwP+xO)`?q6G1 zDJula&&R8p zb*Ns!BUkrB^KxXCBNKVJwe+TrhV~oxz|i~CR_F9&Rv@z?NsT4Nb9G%+_@UGQ&aX(3 z#sxl(w}(>-58z%%d10mh3H5per@O>TWLF}a8kar$oJ!{6^7&&srrQ}lVb)^~8?5Jz zj5jjl_PTvG)zi;onJHECh(?{7&0VjG`;0*A`5^0q?D;Pu+3eZ}PKV?=$HXSsV}R*i zZxu4Dkh$`uO-F59UCiKf(ue27=g#R_uKShjYD8BfYO!wc;@C}#+m&nYN&H|v7;DF@ z*ZuNp4MJ-W3aGP|E|Jn*VKV6FUC+!?qn?Z}GQP<8ZP>~AJ%;t5)p+WL5YYoW@rc#E zkRL*R2py{&6lr{Y$~^n35)B|waBp6BE&p$tWAv*KC^U3#DG;}Wo>a2bg#4y zsdWgcY+gP?V!^dn6NWF_W6 z9yRQTVCd7`mPVHrq>hTV>B($DW)m`VWv`3dxXzE7-DX|$)o}U#p3G)sHgkv1U4r^Q z-UMl#9GhhzBI3WKqbIZlp)FV_Wxn@h4-4g|uY(Zf&!2UK*pp(mh;Ol zclk_~R2=+S>Y=l2^S_V$xal};C!g_scT z3xQZDko)R-;`D>h7oED6X)JVfkQwLKuI1dLR{?hhQ(AEc!aL|`({=d(VWpiY?8I)A zCb{in-bk|yS!;jnXQyUCByWSP(k`@j{bxG}?Vx{c>wT3~+>Q2bw6|{2cCywMFS>PM zeZ6J!VD_Px!g7jx(BAW3ZKYtega4(i&3!i{1nm&C!!py`d0vci87HvJ!ET-ZJno){ zq8<95?Y(I4{nvK-Jz1rFXzxQiIQHt3;AcnH+uDk_&Q^E2!(Dto+WY^r9fo$;f3^>x zeE@A?hqZf~vz{olc;)69U$@ZZUa)Yq!~eC-T&YS2(LVTZZT2BcemU-Y1c%Vh_&W2U z^XdbN-v+gPz4g`qE8FaeyeumMn@6C(_tB39PYPQT3=gbQJR4F{*!_x)M~!>zMIsl8 zoRkWWzd_QruQp~i?t8PZWc1A)M(!|jE}b_Eq};a(X3Ck|E_`}FxNj~Bxu_&#CaAOe z8HY3EiuqE`ugM?eMud&SCj)rbOoYz*2%<-@QO4KC44$Fge4SnCBv04jF|_yBS1Cxf&UhNCW+#{1PiQ)AejJ-0 zN8h2j<*kOxDc4t_vyD~n1zn)CKY{)U^wadamfPO`A$M|%{+IO;MWM8P4EizXyOi0K zm!^#{YUkUUF)vX)l$}0FNLKMA`X|wU8b9&e!39~4)`Q3C4jr$?J~WqCPU#fdr_es& z!CQaE=G-E+aVlr`?0u8Vjw=$Oy^lqEXQM>n%(KO7J+t*Us0%9Yi){KWs~m@|u(un2+ty0^4>vFbpH%~x20qs!xm{oc; zLXUV0IKKoM3sPn1082z55drg+Lr*&=uaSyKRcbl@=zsuoE92!%_W_oKToQ7lX9x3e zepl?Cs1(5AW-faEsf&B&m(ae1 zwt3O5XJs3%aei;x(0pK=yp9}OeTImf0{WNHcMc5CX3HMS_SZ^IYWp^nZ5G;JPB{bZ z47456wmS~#9CpSvNwY&{H0QT2mRHO~KNJ1L;vxD9pB}!+`k~@7w*3)%UZ#+o(iOC? zpe-+$wdb@~znP5@S7c_JwnuPxE(`4}wD-i0jIZbX{v!HQI!^k>rJ}3c%a)CPHu?uR zoTbl<%LUwSy>vJ+^q~QpcaWr<(pB`YqR-FfTkCv>H|%q3oTC2XAIG_yUqkyE+KUHS z2}UdX>W}eH{bpX0ahiMX*U`R?wpi_Z+vnH120fg%=RD`PR#PZ<^Bd^jK;NTeT1=l!LA&Z6X`B`kg#r^26nuE60w!}eZOAeGf$(}m7x$2BCck7$j`X<^_bl2Q-=-NJp ztvBwGS&M=Mw|xukTWEI}AJyQ`Y`Gsfyvw-p;-N#_b}rhvXy<%6aC`Ep5Ff|1gW(Sy zW0JV-Jhb!BuDkH%X!~hdoA7}0kEV+ceCM|F(auME*Ns`KCP&J@nnupJRq`>1u9pI| z3%FZ*4f)_Y>h7T3(?{sVRpI~pR7^|`X%VUk4UTEGQ_{FbHXd9x6Ua)sDB6jJLq3g`VhIleEXT3 z_~eu-(5^tc^+^BKB_pPUy~&F(n4Z!yh~2b; zPgeLo`uFJ_mP)viTm@H=AHWZocYN>-VfbMZeM1<2M44*1np^|dkZa*uavfZkMBfmG z>#6=2ew;+#5Qd*H=Y?+w!%r#G05_1I!OzHza3i@1ZX!R2pOas}FUT+9m*iLQt0ek{ zF#MY8Z{RoNX1JN$0=JM`;a2in_${-~_=Yh2j_U8>_sj=3_=Yh2f$D8=8@U~BCx3)L zl0U(plIR=4@Mo%jfxjftH-zD@%=LzE2*cl)qYmE?hQCw31MVRIfPauX;ZAZF+{LVe zPcq@3N!{NN#t9CGdrD21d*WAj>o@n*Z(4vSnaS}ab3Ym5g?Y(*Fkdo#Lm1|#x&SOd z7K8=KLa-277#1drz#?Q(Sd=UVi;=})ak2y~LGB0lBlm~yq_gJ@Qz1EO{I}jyxV7pG@Bnh9^*6 zAJ!)uzy{=r@Wf>LhA=#d>XYHgWJB1HYy=yTjbUT*6nF~R1U4a?!lq<1*o-_Co=Tnu zPa~Vd=H%({bn*;%26-ktGnw95hi6fJHaweb0b7tQVN0?VY(<^}&tZ;9{7Mi!m+IEA zHQ5HXAc*m}1lqJ;YW1bxou~(ozcFW^(4|$=hWu?5jO=#qzdYB7k5G1 z1?`AKBNlw}_gN%vy8c4OwAHHItzFS}Mf;FdKyl=PIE4wGcb07^-a+qDxS{Qa_K|)1 z{?11}W<6S7KVawlH~YA61uR8-DcYrzlB;El^9md187s8k;d{hgd>Puy(5{{pH90kZ zt8h-W+Zm_F#e=wQceLHno}g+lFd#x_U*uKOoSfRJ&D_O3(Dp#vwdVCbt=T6`jx>k* zDSepsmb4+4(cOOGwk6Yb7DW4QX8UOg$tj|}9PKPEm8UyfjmLZsR4S5o z+pvPW_zJXFpk4ZUm~2gL!23u^Pd=6NJ11fBL0)Kkp*^X;WSpFGD(9C?W7y$~XE_{G z?zyi-U?l=YCKDXrS`E*Sc(U^D;mQSvxyyT_?Tz*dDHACZ{;$pouO_U$8a2n0yR{G6 zK4`nHS{S&(%=~g*Z0$t(&kZw~HtqTbRm)pf@3t)WwwAq4!}D77*P?Gzx>YnuCZPY4 z#B<)!{>e|e-y-QAp4TC_4!KRXyDMk=yqjFbdq2%G;N8CN94`;|T^xVp{E^Ezs=ipe z%FOWex>MKEc|vp5nXv|M40Z?CBeK3^reL7pYszVEN(1|&BixFL7B zP|TJL!C}6^{E>>TDt`qxBDfL3%qP#?>~tR*x+M4iI{T~s+JAyHw{Jpl6M|C0(c#R` zn#iBr?WA$hMg5fq#(|le(cg@I#KtGf9X&E+$2H{K<10Gu!Ci>C#CR*e`^}>*2ya37 zw2q^RqQ?c-eP5GyYHJlTzYWH`d88D8egOJziun^-I?k-zTe)!hxgY-e^xn-@^tYm) z8=c+q+(7t>OoBvEDBqBgwEZ^pw{h1WUT`(WH}`z}KTf;$l0@&6HI?L=}XlKXS(BQw8 z+=bw-|68#8SPVii2*EM)YjZR$EjCYaS*)-r(HP&Mz}tG=x!uUE+>PMo`~JgcZ!QX& zb1ZroTQMuKJIGJR!yW|pASa@4`l+kr600rfq+OiY?-?QJhoHYoCnbKb)wsLOiXqR89`9=CeSPz*3E)2lgd!Y@aB6tno3hAB zGWqADW*x~G$$c7A+KcvHv=80TyD!P%Y~NNeE3BmbQ2~3$00B9redzB)zl5z)o)9kJ z#6EkYQfcYv=jc#%Krb(@;3t;b@-`TJ+kZMR;IX zcBi@366ZYb)(6o(i1x8EKHKt>F&EYxR6n*wQ^1e=rZM+5>mju7J$__ziopwC9XNv+Q-ng$k4T|*qQOZRWH2YwUw7d?}L#!e(+h$afFW}thX!kY2)EwvFXE}rP$R} zrgOv0$1#FD8Gr8M%zygCHYc#n32d_|OiVIYgu@9KpX?>(?k+3HY@~OM=kKk!pZdgL zs~Bu`%zN(6_gSli3&R(T`4%Uo#@=ElrKEHc{geN;C)7WM{wef5{SS^3d+)=d=* zKJnk%#ABOyY}4n`v$`+-|6Y3Tb(Vmw60p^+#_)-+PrM%W-P~e{ca+GU|30TgY?Fv> zP8bX=W;r|G9QiiT+$P-d^S^Afp!>#2!bVBhD0nfuc&e<-mIJ#V*t;*C_AeI+&!l|J z4VsK?lCh0-(6#lmh0ctAaLc)?aN@{~Y;_LvhGq)-Dd-Qk*1ddWcHHHW8K*8yynZNv z`lr!9jsBxu-a2~sTS5X()XBg9#JoMl-Tn;vXV71AA>H!Wx3=u*wfy^z1Z-vgv?10{ zML!k&P_>(nOO1w}yS3|xUfoLLt<*n@{#o>cSC0|Z-n6Eq_X=-%l6juv~7!I9;SP}Eq@-l^T}66=+`O!HvM+t#;lq^>!Nt#SH&C<8#?h7Km?Sd-{*OVGy$ychz3O%LraZFh9upoPX^1Ggfie-n_b*^VcQGKrRD0+k>Vz zh8H;7O)?2Bt+aTur0;r}$YmmD#`)du*UxruNnH$UkLd@NVp-qh6(p}9sTpQHtZvU; z5zP>vLkl{5{`wkR7IIn0jk9syo3ZSHXnL> zd*y8r_xc8fl8h^OX|V$jIs(i?l^pZP%e+ebv(;5>broBM$?WfPHuVd9`ZFuVV4243 zf7$5I^Zqq#bPXFN-jqmgxodbirY6aK63@QWzL)Vja@V=He~#FPX@l=xtad!J>F}rN zpRaTWnU{EY#Jqvv4J>Gs=Tyhz)E+xWckbiY2b@3k&E+7MgWP3BfwT7;0}sEI$lIHE zYdl^|ci*g7??aWrV+)o1kSHD-{7819Z_i--wll`lei&kzjz7jA{rq?EU zsOSA}JsX$tJS}d!4DB+s7c`X5G<1%Wnw&YI zAoBIV@7&ijchSC!_9*?}ej$(d82(sh^vvwmh6&tVD@VH=ZJtAuX4Jk@93e1h#xqI8bVZgIal2U`!SK)V9%sDf7pvV~)gSKWBed{3g4 z^DBntu=_~dM?yAZ;IWVq?uJKRTGSghWWQk!j9#y4E0L>2?)xx<7q=457VWvjl6 z9TU2Y+pb2t8g0cWS=Q`>MGpPTAIpW_UZBNo*Pva4_Q$xF>ZOBQzG;TkgdVP5JDuCE zMY|U5QiJQ-#VK0{<}cMM>0f<@`!TCx9olthPcfg@fAE>op;xVWrr8dYXIDOvl~bxm zyB=-(%LVOw6oT5WpY{nZ<$J+BY{oxE`!U)Y!~1*n3*J;_bN}-D>mOM35{kJNFzlJ~ zaIb|Y2tQ%oBgF>`@Y7`O`_&C_1Nj;JjNAw}lAGWr@^kn(`33xf{1Sdieg(f`9s}^x zqws60zk%P7o8e}13*16(g4$4mCI*~Jy-Q%8W`XWXu`Q@jqA+sZ& z{gzkiLbnUutNQ+SDs2(k#vgNoW^cHz$vvumqWu$XmsO*0m#&HyT3J15a9v`%3f(0+ z90ZtunZ(xmO+)o(?T~7lpnKM~A>57GjqZnDOmUoF+~hALDa4*gJO0$|?zQ= zQa~6B2qRGc?b`fBjg`!N+h4BjQ|OIB6c9l`1OX$*K;dH^`W6<$oS6Um(NCoNg{>$8 zq6m!LG<^?mSDLAVe3M|Yh5d2bMKScn&@W6j^Sd;E>#d=~Gf&MDoA!YE;^>Q`AO1v5 z&o5wZ{Z|#`ki81-uCxOZ=u4ol`DFFZD<${ua(|$0NJ@5zM6x7p2#JzpNhNDYrR9pEB-!dF6)h4;XtSk=>{^tRwNlwa3YBg> z^S;A3{PaA}Kbq$C`h4ch%$eoRIdcX==)0Sq4|uQFmj_N- zLaE2!P)wL^&mjf^_GO(W2Fwe5kf(~nCuxOf=!#ySo(F2dWH=u_03H&tx8ZF08|AO1j(uO%E^i^Z zAh;m7jAxO?!;ht#ya!Y(qz>unlQ-r<;6mWHwiUGA>GRJY;(lnq)`V;2_*y*;-ZXeq zFPP4<-dTEnp^l>i+nu#R<2_+`!teyc!d7r)emEXPX|7viQa$GW2*;BMJdtGFn7e$C z3t8uJVVb}HZN^z~_N~UY`5%$GIlW=v^X2xB0Kri31r4H>DH_zuIng(G6ZD^JPt(1yh<&OF4attMyGB?Iu}y`R{^hY``-L^1J_iJ zgKBqKZ(C7YhqhRRZ1TMgg1qiGbZ~x`sXSX@=rRYLm9qkF%K@E5s ze*;xDF+&r9RqstMrT(zj@jpuY&9Tp~X7pF~NLd#`T=+MVqJh76Sg|jDi!m0XzeEK?dUK zrzBOLC0R#Jt&_F!$)!pqhzN-rLNJ8T+B(QS;G(H?;C}AxHMu8elYA-oQgG*m^*qx{ zJ$l5~B%gJuTsfcQM&L%^88=N`ZdP+!*1c`hR=Q+sL-J+d%fKJ=IHpWB8r)XKbs*_{ zdE_>d8-p8z@2ClsjF*qQCH~~|)8jqKP9$Frz8u__vtgg|EUJ~pD8?3c;OprK4W2l;@ox zT4feX2M3PcA@hx1nb*Tx5AQhZl=WWG?|S4z{Aj-)*aqw4sTuvAfAnz~o&;}zzX3k$ znRj(is3x6ys%2;C9-P-%8%qgS_D{uJ$N z^Oc34j@3tPC)iG~*9w>mN^)xNNnRo3{x&JHZmd1}B-0tTb22qEPH6No;Ao;PKwFZj zUFvMJxacQc7tC=XWekir<{YpUXe*Z5u2|;e9epI-%PzfR%hMScgKdnr4c<0*S{!wA z&xzT8uo^hBT6~HkMob>#ZHKoV-mM@5v72oyi<;)G;SqZGeRQ0y(YFI#A-Y0b=Wcm< zovGJnH9tMp>I7ZdpYa)YK->W_`h(v~-hkNq#jdu;HpQh)xZ`(&=LYXZi(*yP3Zdz( zw|$AXJ05NvcP%AqhdWGnnDr)+{1(IYm!H3jQl52DI)D6Yr3+kAh=@^)EiJ&)BX>)_x#}b z!E2+@LVeFJz1W~0SsN!`62v)P+y!wL#00h?ryifrB9!v4iQ9iMn*@&+{UQ28)a9rP zFNxxx8r83Gba+wlgYn*Oc)Q^d18UBw+mm&g=fWwuEIq+PkH(98Ant*9jPvD>X|uxf zZ+VzU1@&7BPuSRdA?}6v$P!(WGooN)p1P3itLNr-07tX1rGfuJ_>yFpZFN?F<`wNr}}qWwCWrZqwLPN zQR}0(;)el;O^VUQ?>O-BNijB9IB+;{V%T)^mNg>znacXoHOw4j|AiC4CxGV%AK{-d zXPw29L-J3ye!e76U$F?_2;jlGjHXiw8ni!59`3J9&OD_`OA;M3PJ*8V?+zB2$3M3x z)a&bLr$h^Udwj2j@wctmVca{9e5DRJ3b%$b^Fci7>Y6N zH@$$6-bsGEFxT zU+9!_qyDU7w-8sm&l>8X&%}EbXTi^ciysUh@;M#sf1x?}!1kCEwbUqHPI5cM1Ml0y zAefU&_1r&5qpcAW$*m{j&msOCgvPr9@toGzq_U~p>piaY?k4$p@blnXg^en;zeJWh zS%xnOdA_!d+832)T}pUw0Ad(P0g#AWcy;A?2Vf2a;G*p%X{Gp}yr=i&e|!4(KsAhbtaDN)~{ zcu#3VV3==9Q7Orjz>~l)n65uFKkuQ^W%g>dYL)&7>LGqkAu-^qz-RBL7o5Ge^SfQO zyL@X3uK^jJ44w>LJ=53YO1YeOa%rQ-mepJ;B)v{dzUZvJSP)ehj1Oj zwVaajy7K;7uVtp$oOf!=NS+3s1}=RorX$+B;L(%ELA)%RGZvEk2KWu|eTP4HU%h@w zeyFdJcuj1dJJnHus9@>f>ELQp9xykZUEg)b;zE>Mc0(8$e-r#B_|8|i)Z7`E4@_?^ zaSQk)S4r{=@C@)f)Et*uj_m^julNU)_HTD4c_w%!_$+3dypQL%?SFKV^BmEecq;YF zS$-k$EbuIFZHdrpugd3^6*f|$smr}I$@p8~x4_THIT@|j=6!J~OIB99?F?~%T<0S9 z-)&%a&V7Armk;(f4ByyN=6tJ;48Mc$JK#xO$Ak}TidA?!bH+uZ%gr-Mei!^M_&0_5 zvK9u-MMlS`Eb3rwiz4|w@O$9r(~k)SnH=7rnU-_Vu-cR?#`VVWP%(BIS@{l3w@Oi-uUqb3$J&MX^AIC~7J{F{JKH zBkE>3aQVNmcm;69BzO}_E>;O#3EaCo%kb8PWYv!SeU0w}uf#~#3yD>MR{e`sgI528 zir0YFfDUrbe^wbd=hMv=rTKj+)9%nW*%RO=lVaR;JOzF_DaKvLGvH^y83~ea^k2M> z5)gR%^e;MIouTkPI3UuWe>R8ivY?Hzx6SqrZgUgqphCGGQzx7_hn zbl{6(#-~DX8#>ZC`31Ze@TNC#6qFxwkN7TkWN!9M+V2BY{zd_^e!K+lm$+%V()viE z`O2C4BJ2bGWar{K#Mgm8qP$9YlHQtLziU-#vu3px**WoF*i{4Mxf@E=y(yFO3Vdumx%XLIknR0#Rl{vG%`@Pd{rUO(2EEfnn44Ahxb zOx@`&I!)|7@Oxm#@;`U5(&(f{Me$A(Zv$=vZtY^Jb-HWPV8CiBG^_G5 z*?cMS0sI3v>jK++)6SQ&G+HtD_5Epzg=FzQLih;5%|Tzl!t3rX1;?(`Knd!|=J^Ev z30&uzwJn3_%`Zb=Udc?+SwIXBik^M#;O*dxxtHyW+sto2!*y+k>jnRbKmR)*c0lZ2 zAM<&Q)3flwq%jX3I^lJ~E97L?X<=6n@VBv>7kRhx)`{Q`A8)7#+$S9(XGhe^P$EQ1Ri~xSlQN@YUxDgUyI-1 zeH+tHfii$O1Bld>o4dn!ck{5dv$0ol>H7=xi}q+gg^^R#AnZZdd-$HaINv*1eSxYk z#V!*&dI=x#hTsjsW2t@Yy(ZejHJg1v)9hyK@sV0QkVKc*a)L*~vyhq|` zr?z`rq;JcjFZl$UVJhUQkQ3yTI|mE>BYp)QUyz|)R56Ln0+|Ie!+ZJQy@NTfR_dwY z4>_(o{go;Iy@0|Bn-#W}|ukvNgkt z9B+@W4(#yQ;VE&y+WRa-^%sY(FEj1W3o%^wM^AqklavD{2h67OINBc(wh!|czxRvF zI=3BP?in=+krN^(#MePPHMRXZbwlo@NosF-l{4Psg2x5#+Qr%@kM69I=!{+F(rNMV z;CPSw8lKE^L(G~T?VnV7w)CpgJ|$kM~`hLhRqXB0^*1fN6ZKH@~N(e zqi>i7a|AKlZOWqOq)32EfKU0gOyu724chfSa_rs`Mk4>tIUO<65fi1EzGKK!Ir!c*O(r1Gmv)%Oy!H7 z8*(=Ec0N3wWxZLlgb8I8qObl;;NB{aPnYjnY&yI~m^1IqtW0uMq!2Cz&g_Wo*#QcB9%tp*? z#ONs2zTLev+g!n$oy|-8xBz`^C1k;6!9||ja;@O?yIs|icgR0?9qkX5KZ)osI0wQU z2vS+EKCQB>HZnaf&&R~>$4hRmx!`lb)fgl>057kdL&$BmIUR zS=r$KjbUUU-}X^Pj51=TXj*Pbzxb?T`4gLH>d6;8d{pkUJZ!8g5LB*F17Gk+X%Y*< zqY+iiQ$TMkZtuWC z&D=)3aR9s!xRNp5PIyb)@(#(LE`>h ztGni&y^ZTQOMG`c?bwdjrLn$_T}W+W6?f~scMzXf~>mWy4UEv8Ks1N6Jv5M;o^~BdJT9E}=3chsA0*x@k2m#Mh8;_{` zT(~I2|4Ysi-$#eYfMwvz#snB+hA{#ng1VlsQMZg+=_`IasHHQP3|J1nd`!R!%vgbd z^Dmb&X&!GHP`v)lWudm{JhI3u!B>I{w^mu4H0}88rJSW@$mbzU@>Srgz#lNJ;y$)` z*{V0alGg@yuW=^%YVg(Iy>$_Z`j^(HmzAyV+id)1F`Y}8fSZ7yUeY1d&-AS(DfKh$ zx9_R=7&3t=1XBpnVVzdlf?=Gi=1yb&8Pcdt=PS&>&A>NFJ>De$Hg%&{ceBEaSMPCz zT8|#iBTpIEKwblxM(e8P3R8(Fy5AA!EP2EuivBFm9NZjy!tj(zz!Da~7Qn>2Azz0% zoo_u3ynpejN)^w2`lBaHa7*yRY+kGDI@er0Tgkz7P9f_u9j^sm3;aJrND@!X#I1m> zfS1H9c&(~*scygI74cuCFC(yUv30=ffGY)j^kx|?>d>$De82gHKUG?SXmYX!CK^zP z?I2${bn{2seSXGgNe+UN^Z_%(ZGdfn#Rv9Y(!3QTz*7?aRlHy*ot}I>@Ot1yvmHX+ zqTcaV-3T&SaFdt%C5(8?y#aUw@UatWLw5r#^Nx!9ipvL`JWPKKX$x!%Y*uP%7+aUr z6V|obBe~{mDLwf{;Elk(6i;Sdwevf6zT7CsVbF+2ff9D0cA#-$HZ!`@HqX#^CB}xg zmpM-kX|V}>6L{JA{j+R~!WkFvPG3-*prnH2;`YGyz?WkWU7i#3B#}pJb!@Lp&;feU zHUn=4USn#kHn6xwS(Q4gX|9PJ+0N$x>;No2r8GBs?}m;3VpkHkyJgIvKg4tdb_BM& z|81Y|8%Y-37U%cs2BK88T6Q6ECtxSwq>k2-@VjPnT=>7MZat%N1Ire326hI1`TeHehp^Bf_Bv=Ec8r zh&~oiqxoN;Ms4CC&)M6-Wv|zE?#bsn`z-%z!GnCG&-CoB2zLdxp2nc*vd3Znp}5eg zifl(NQZI(`3(@aOcK{1J^ozx7?Y{Q7G3G#-&_e1(Nn#ujH$=Muw!4wCB1C-0e!pWj}0PCgPh^yR~5qPY?va)ae zzIysW9DE}3cd$LV#=3)ltq4XkZ$=6eZ=W* z?C>4_5d9$*f0(72Z2S1c8->N~i~Jwejf1<9*a1%lO4|g94cXnfB)-F-TBez?W@y&Z?Fcv3sdsI)#PkKd1sH z`zHy|1o|dSq=}(Sdt&4&v37F^6~*yeN1kGb7yG?QeAMPx6m? zYq<63crO}WG`+&LsBM0>f6lD+r2>q}yRxPxj)=HdCl(w7F$M`+raiHWr1q6%8gwZ; z%c}kuJsd~GSctI@-7Gi#$Tz8=UOx26Q*QlS@&!u#EG09Zf_MsIJ24XThBhba^%^%{ zt0h(IWXWL^{;H>;o`$+@ULaSa`zw*2l}FnmYM%Tz4$a89fC`Zc(aO!AE2#NueC?0S zm&;YJbCAdK8SpdU3$+h6>|^CxbjH|BrRvJ9H1b%E1CIj_IJ!>XC3dQC@b^&3%`=mF zsfWbb$*aX#;6~}^Qy+#iHT0jl*)Yw$=P(%_kMMYKpN<+8nJs1w>KEQ0FA%;mjXV{d z13w48?$lZ1ppK4wmJtZAR&L>XIt}r5dizk35fQ$D2%$!?MzuHJ(?K4$5!>=Sy z1WyD%v-FW+tKI%X-HNk!h{dmxBl$(}i{JszG8Y`_OLR5XpUG>?tNV=Pm%uN97w){8 zadvJ)xm9+JXXCVdZ912@41O7$hl9ss>+5`jH!m5k=hJ?_%qE2^5UxOI%?;nPMxXge zviVX=31Wbh^>kr+5`-iO+#JgcURIy|_KsJ9_B)dHyJL_n!&MkpVVGX!Gf7taP}lZ) z%fY9^D-M#2NCr;^Kb&SUkM?KRr;Sp}!p?6g=Najee+|Ml2;zO^nX#3AMGL2?+gI;7 zMkSl8QovKdcRK8RaKdb1)cefQOhaO>;+RxTM zp|k3Bc-P^baQwdJaIclQ)$4wvIjJi6+WDA=uxaqp=$Gf82c{gjxcb=<3!9kzB`bp0 zj2CY}yn%!Z#WS>38ywkZyecj*FY%htmp>g|Iy|3sYf~bgev)5%Jhk^N)2fl5`{*%& zT6GiNO?Vf1_gY;}@I(F$1Cjjn{w85bDRb6emX|wTyan+V#1kcP zyaxOnvjmJ%pBn8tk6WfO+weBL+wdqy4JzkWZ@csS8S&xaTlKF@#*23#-hp_r_ob7~ zdj0a`w3*^BlF~Xx8k|NCxw{bWLaZ-*e*BcurT5vFs*@CBDul@Dcn|y@_{rPcPRTCa z?@XB&IoxwSc#h=R;Mw4Fy()jXhFaa>K9#VOVcH3ClIMWufL|J}9{MO4Y@XKV8qxGj z;|$4j!E?di_iFM?v1u~BCmVL4UGr@m$@9STz`se{T$T|~ky6ah#9lb%P6f&H!Slg+ zhrB`!EqMa^czA?2YS%0x`F-&F;Nd=kP4~VQ6g3CAxAulSokH>g@B(o2p4kH*<^)vV zHek_Xozo^s=MoRVAAo;MT*1}Q+38fff&Wux4(<0NGQmR#4=eOP)=7 z`=vtia4Q5a1dn%=e&l;$SXyD@6^m_xjP>L9SP{G;c+(?RTB-!q%YR#YA+)eflSUga zK7#lNqM_BWm&O8*Gz&(*563-t){ggz;T6-bfqH^zW&OP!egeJz#kU1qb;gS&5KEA- zrS{1jgL{0RYK4r2b%OaOd`$TBz$lYDT(w}s0fmO=Eo>NI_Qh?cM%i&*&S7pwP-FJL*ma(KJogiKRzj?V*q226t$w6T;%27I4HcQ1 z2(R&C6~rotEh@v5*Mjb^jhL$PczM-F`-U@;r%U-!fx7 zDf?;T>}$lg#^}O~dIeejL>Xa9Xwz7IR5Opvk5DTPw&*2uH@fyx+I6^yiI8`=8 zaWbg2FB3`JkA@}Ep}c|f29De`vrxU91^F|BM9x0H8&^axI8l-4jTPitHb8EG9AIG|s1FGe**~9<$k+VK&3OPMuZ5i zIAYJ{?-EvcZMaqR;|H?(w1T&Se-k%lJGOC)IqgsV>Zw7QIr;Pj(VNL8)}OZsdW)d= z56+vC1`Yh1_AUy=|KLOrHdney^Dse?noc>e!gSOKF4O24CQ06jOGiUH>I+$@FxCw^v7f;^)?X zM*?|#Q$8T*1AQT_Q+yU&`?X8FL7+O(>9p7+K_mAa9})8rF+0_`celBH{O3}{ra_IERq-ULJ0N#Jj-RthG z+ciUQL}Vm4Nf*Q}h`YG<*~OS77wi~r@b}C*Sv$!V8HwpeOgCcI^sHCe+Z%5mX!PRN zqBOVvPALDo=|3Ze@)<$X3TKEL#Lm2SsIql$!(F{!|6WiJf_e~Bu$uPAZe@dd zvkdf-HU1sci=bWvWweTD$y#X8erv>pcjT13uVY3Oy*-)I2dfX3V}tSC1#`XzY06K@ zoXTF;^zY1H5c35w>49>K^=H(Xn%X~6pwS*xps|jACjH+P??+HSf=tx5nyRd_oFDi4 ziZtcOAxiwegT5l@D}ut*KN|+?h|Sl#vVPyOh+9Mdj`@a|Z-~h;-yGu>mQg&L`Rbni zzPp$viJ^?_$^iroAc*~tXt$Tj^ybRo3t6-Gnql0(f2`3UVg?ao6riHc(yyiNv-`b0 zji!_(@$aA^1Pvi5Sem_YVCflwLi_Fqjc&)zi~l?5JA%F=s86BkEBDiPjaiN{K{a*! z4u~Ol+Op)vV?=<+oJO3Agej(^|>Svv!oKH`-v|pFX@VK5d z$%01CH#8c8h`&UXD>F4RKJEK2=~Kn)Z+&)cC63)Ok5Op9=^a>ze+c#H73SJqPHfzM zkL2E0O9@YS_)7ajPx=SuITkxs<)|y(&x2hU+20uzj8DptLM)vjh44~MbnYGIT%(cT z#d~N^&ZUSEZ{)6m5gua-9@EO1=c>4CUl6)Q`;&Uy<-9q1I*fh(ItA(!q%63)jgzQa z;!%9s-U3mfxEPKVnIJMj6zj12vHRAZ#+jE>6K{(>XP6)|Lu7`y$n{aS(t4c%WgCXF z*EQDXc8r=Mk1VIcoC?$Z!EBv~N|Oh@b{Q{A7tD*KH<_>ivjB%0wQDWg_(jPgNm6ga z1tuyTvjVdMrv*pl9t`Gn5@J~Y_6SSi4?1Q8W&_SD7P2VPumioeQHLDk0L8YcU;Hyg)S3|@G=@OF9Y+q_EO+k7i< z{xW<0Z~t`|966`(LFA*r^!>ExDEG3BE4#jY)IK60l}hZKiCx-{*KaYl`7yO2 z-!6V}Jhyk`B(eZx0mx3)TimBtf8X5ta`)7F8Fh>|J3cefvr7=RAnf-|Us(-le};I< zr8Uj_A`=V$M<+Tw!4`te+aq5kbY@CYUc1LG8m;?Q%p~?S*wbKZ^$pyO5ISJ&pkuUk z@mo0>jkGD_dbtQg7l!Va$9Ch@rQ!ETRqjyroNeT;4?#-koDQMWX>AtGd{gVlrjq(wDbjy2^u*Y zN+L)SL1z4m11KxZRo>XM8JT-LzBn2~^miCjINVOpK+Fup46I1<*)>zS%*OC?e)?+b zW}-%qx&4|6ZzjE>+OfuYp(p6HX5~~#8qHy<4RI^X$T0K28#bcb8 z_RU+W{4|Y5o$0dt1#xFOvTdXxNkgh+&y?qCD?2hT{rURsIkBnq+v_`{IY%~&%`Et{ z;Kw{W?Xixfc-6!0hopjY`7vVaNKYv&Tn3&DyzATscV4sCb_So=nq0P{056Hd(`TUn z-kS|?b_%@@hb*RL$>}+mo zW$<EAfq|&+;%*J;pGj118#{&b+(1kTcN}k051SeQ_C;;vQ0iHQ7m6% z?NRxkh+d!ptO0y8T>j0m;Ct#eH+!#KPu8^}D(u9!mo*`4lAC)WrWcaaTA0=vv$+>x z#v)|hm7!IapO7Dzv>`INT3s+E>ZXvmHmEkJvK~KwavWz($ z9pJ=OoO`#;k+j@pTJP*~efLl5Ax?H7`Uzw)aJF;Xor1&*i}_?U%090;OJ$r(^rp~7 za$Vr_EJFQx1rpJ3f|x@Nn|E-M@5Lw)WmKiFHH zd}`w~>7t$cT(}*FE|XjzTp!#~Wm_PVuA5riM@p>D>G^gfHvl)F=MU+*eqOanGb4Aw96;`G0 zGIq=)Hv%^T-!=VA4CQgm>Av0{e@bl4X+m& zZVYY={{DJc;ICG#Z(?Pibsej&{r_+rNe+-ddq2Td(k-~9J>P2p%*#>w8 z@S)mkbJIko{5(mcIp1HV9zb>MA--p}5_~22<0sZ(j+*|}L)@NA4vEjvA=9q{Uj=?E zp@~P9=z94$EyewSJ0q3O#a4r_2EQ!)U{L10tLvVS^vX5uC#V*wM1K|&U=!ePid_kh z^;4oV9#Ow6-r)3_8kIg$cT9oZulALT8?PO{do)|}+>Iqy$fcVh+zi~1_wlh>)AJSH zaba>Zw;Z-2`5N#w;Iu#G1B2Q<4fB)Ca^k-^6Q6dhBl>ojgPVg}-FzCZbkBIxF$Z6z zt%cch$ao8I3-Fr@Syi4rPUq>IL5!bwq;C(&Ex|3pS2-^bdJDZX;3;fn;FOIU$hffJugZ3!;^P`Fh?SKL33>Re6=>maOyP$l4| zvCo3`=WKqkbE5f4$C3JJ4Z#|MWB$HQk(A|q*9%?jdiZ2_kR`AIw*fEGd&KR~e6INP zmu2g?xuPzSd_DMj@WmCnuVqp<1)RH+A)4mUwu$5$z&C(LzMBzmmU3Qt?a}wk!b%R9 zk=z#C7X0D?-by|m)|d?S7xJ=B#~bK;!$$Cp;9r<#g~qbn4vjFaSDDs->HXLfk^_0| zu!C#|xi%%yhb6Q_hh@n<+V8m+7k~SEf!PFUQwm1=oFQ(H|JWm9@&Vm9gKq|(d_Z>x za0l?o2XuD?cLbk&KzAo_C-BJ!baw`K2LGP{-7UmKgeY6Uw}4L^>zmj-{~GGs1wk$d z`u`j1I}o=eTM@JsL8~REA0<9&esdmAe$3_*EL6TD+#FPM4JPK5+u&@2^Z&eeK+5gV zw?j8Q%eF{4R{yfkgIATsZ2fvv$3w(Od%&*1v_I7;N1jw?Fmpb7m`}`?8R&dt_u%rrv02?EmZd z!SREWX!^QDVo^Dz;rRJMJ3dP0p1;yANV_2AtzUJ+AZHmDUtU(~)S6AnaLBFd562&l zA5}iy@DOz#S_p2J%JGky@?^GiPvQi*^!;HCI-UE9N zY_FG%NeT6xeaEg|TY046tO30;jK8bXgRjqX`WQ{B=Ua9`yoH+5HO4x zZ28X2$;b9t%6xFVOs|axARmCN`f+=Flnv$eKBI5;F}K!NdHlC_bnzg>gAmvC5U=KI z_X%gkq!G6puX8Zy^O$W$fk^*_af-hu>897^FPg`Mes2K-7A`fa ze&gctGJV4xfqVqAKx5r$UA^oOv!Dw3s5?p<#&5R}cp>x+r@FoVlKiW3LlvFP_uj3F zCm+#`w?kovBJ2CS1DUg!s5=ihG?i2{TizaD1o~D!3i&AH)7*I{mt34G&eHWZLSvh~ z&Hu>6@qY~VG1%sj^GYJ?PaAVS=!}k2`FH+dAZYWIMS6mZ<5rJkRu^?$~Z{R&`;#Y^ zI;cNnGnBJr|3S{flh~(WpN1Xx+GJJN?%`t<{<>@VUOAJEAmeK_HHAXhRM^*ok~=#4 z%*?lm6seVda3aS%9B-dN>NAl2ubUla+Bx$)Tc_v!M=w1m+c9yF;~;B&y_aA7L_qBF z?3^H_<2PBy6`CSNKVr_pJ`0<@JW5*hl2%dphZh!}e3d80*`yo~IUcfk^yQTGL$$-& zb9ffBrgd$dL_P=k9OT4pZCPLLhu*sKj-z|sqNQbYnKFJA&%-_s`-El7!4<6y?^q8l z+$PM&HQ8>w0QmxB!%*7qrVgq<%c3a`5u3E+4^2{#1lS3%E%M&$Mj7Sq@KRc7OELE~ z>z~97CokA`_ zz680Xv4IkxZpN#)ymCM&R%r8oqsWk#7y9Y+GVIH+(taP`Doa`u1hMf#saFCz(_JjOvUp}epUCo*nlcc6xgMAIQ&9W&P z{nP8(%GUJ&2IL!%OFv9WxA!{v{LxZJRu4}v{3iQb)RE&a9dWlDgsgs#Mq3xQw5H>5^UbG@y-btca%8~HfZf-4`vZ-( z_46j~oG#&Y$=$p}Zpz=HkT;f@&@-W@W^C5u+TDNC=<->L!G`v~BT&${ZWg>OcxOy1 zY&efI1q#2R(rDWZb4R+05^v+uH^eQ7w;=9|NadONb5`N8M?a!cuFR%4B~sAyVdS3n zHq6^F->Q9Tz0CSH>6vw?T9-!*`V8Zc7|D1C-W_J_+54|} z7vf!rO7^xLHbHL$y%j0nNg2s`59&Rr(LC{*BE+Z*;r%n`?Gaujx|6;K z{wB?anGMraqd9(uN>Sgrtzq&T*A2-|5OW~rKwN3bWm>(%PC$W!-#R!(mu#&iGg5Hn z&xM%_b6f4%gKB2HZ0i>>?B@PqD>@-%9>hF|x<=o5g*KjNo7sB(kgoXZFB8Oki1`rh z4icZ%x+0lldM*2)ipiorg;A5-=oE(gQ13$xkX*oZWlsOA*6+8b%zl)UIOZ@R3RwWJ z0N%3ZoyOcjxr+>bo(S^Z{$=Ey%F(^^0Nw+51tu2)%5EEcFOCs=cUkTd#w4J3bQ#&? z4!aOyX@^jS=q=yhrdT-C6<%-SRpcpWOa5@67PWzdi2gwY(T& zF+|zIB(vVmeNLsfmR^vcxW$dHk|pp;;28+qdrEv1B#8H?-{#HvHS?y77I9>)AH#eM zlYi}{tFjbjR+m8e`p*Z9){{MFh-xuX$WoZ4FfT3p;Bo$S`nrX-R*^%Qsf))iy9{0# zyh!3iZfIJ#A>px)uY+GwKRNpF->O>nFe_l1 zoN>zM2($JTVyA>EIV}Hs$h4>WW;bGrx zLT&wXd|T$afBx1tp?~Ewc+cSNRT_GgU{xLv8^xffk@m9czXj84&vSUs;iaU`V`SeD zw^(qnZRuqeo6(-4j0_a=Bv}iy7N+0Yj^X_Vo!r`7((}U z0`?2on>7|M_3r3%VNovkGj*{fJ4B4wL_MP0FJZrgeJeQcQTkocrPn>fJfBtsejrLq z8S_iF4q_d|%J!rxAIoVL^Nr>>ta@=*id?PH#lM303f|0+6ZTC@sn(h^J~?gZ%OTG~ z6AD`oyB>C-bbUgoWX)~Hsa5RH7Oq0;FVSCWLTO(^e+_+A;r00!%Je@Rb6Pvq``uiQ z@!R$dyf^TQ#8@aS51J(PlpTHE&2IU71k=~P0bT>V?hbp!%r*O@&N%j-u-dcyCOw}6 z4mY~k2(b}jcJnab-J#*B@lT}-_;bzv_Kpw4#&3ex1n-6>Z%K01T9z|*!EL`XWGhDs zs88;sW_ZnH15aWfFYD44%xFQN(ojtwz3HuZ~izw|o$nPL4 zd7eMXI)@{ycHo}!jmye`V-||0$M+E5L!5h2V)O8(!2`r+EEt8eRy?;GO-nXZQhTkL zri!;gZ-cIRcvm39rKK%JGv$8VNKg}_9@@_;=g5XiqJtu@Rc8LT zT(Z6OBgBsoor9V(G*t*;?%~SOs_q|*iS4W9DPC}wp16KuD?5$(v2D22y#~K+v&FGyxedm zV~)-CxVJ=5D;e||&SyANAH6u9y})^+yCw(I^IxxiDq+5WFoWNA7bzECUl&hj7b&l; zQl`6noL#*<|7Pexh8|?t(;M92q0cJS)_ywpDAkH`fJo7kA|Ns`#Y*Sx+Z?w$y8q45 ziyXbk5jorPeL;bvRe-2s(UmHbqeP0{NlIbu;^FG(xBYL1K4j=a29M%T#%C8q%$}`j z9lGtS9%C|*qHmHEOSe02^YRHGQjBcBFG%qP+iwPIKc@T1ZTY}gl-1@dW_(5df3$!z zlC|L*yl?RS(V{-GumN}jL_xDk0F&P9YZSN9m+mO{A|3Iu48duPv=nB<2OX< zn2FMj_ZcY&U_?N?jPd#2So0abG9S$n^lZ$V=+jFw1^N`|sk47(7^PoQJLv7oI&a$% znelm<;4#6|v}rA~RZzT~TYOZ^DuzX4LRt!0vzXyC!`Heh^h%=sT#1Tc#KKdqG#5JkT4xJr3 zvz{v@LBXiKX&`b*s8{3B_(^>Z_#E(4;*@7s2XSz|mD}$odb`46qE6pMoX|O;w{KO@ zbGnmQSvB;sSL^PIF=GItQgOlKqChOw{jo?&zy59-%hzF9qvzTa^U}9DH+*jB+6mt> zlOxM@y)NI&GdEk+H&Le-g9kbf^dl8-_6V*kY}_#1u;YTpkH0kq9)*DyA}_>(3-fm^ z5o)DK_4jYNyqiyae3jyZ#|Q6z0&CmgudK4CR5s~{Vp|Uq%O~2hC)8|y=={(Zxn;6` zIN*5oel)+vyqA>=$LYkaAbE@lz!!kO^qbSVoYMvJi7wVU9J~2Pe{>LcEZA&<@C4z> zeTrHew>+*de1Agaj6=tL$K}Nh4s;>tLeTe}b~rbsVQ1r#64rwXtCo&D=D_ml;xvfU zAZk4bI;A{6B5=1yNb%e^@~6gc24Q%@@HFnqrT6G+3eI?(B%>i9v2xPoi$E8FeyIQK zppAT>czn@=b3ARi6jC4Cbspsvg)a)9+23u2k1CsL`4T(Xyieba-}*oW@28svE*|j9&=vlrWuiGe|<0gdVh5%&omT>%u+n zDPO}jWl?e_`t)MVfIkEN3(4dC3*%34?2YhBRW_C%eFKV7ihg;T32!F6pWXGV1X=d% z)G`phW4=}#4Y?!Vk*9yqdrUtvDa1%2M&Ym)rRi$_P|HKx!m9#o(u@E6o}$k{Pb>{d z8d8Uw%CC<%mYdvqdo{q@t%v`wGYifvI0yD#{;{s+>Z+-+(cNk}Uw;t}kp}I%GH_%j zcW~jPKMI)*X*Q%e%HBql+aA3)UrdplwwlZN@4{r^$ij&maOk#Zd=~9}wY6ua-(KQk zJ%vbw%lsTTbKumKuXecbDGyYG^We;b6BaP_vtodY>hW1x7rS!$Oa40YaOB~rlzru4^?en(P-vO_ zkkX4MqXiET_$D*`gM%9TGl_w(<FgTE)jiwg0ryEzklu3*Z#q$+IX) z^7(OHQGE4&RbQLG1=4_{0mn|8FET48P~r_`tN2dMjBPLfN}7-~A=P+psd_HxKV$B@ zM}1<$jm!RSp@nc3PVS5rNDGb@9F?Ckf!FiYiWZ)VwM;zGT>p1ji&D`PvB}+-JdO7JT%-rJkJQdFDmR^@+WEjHYxG zU9u>Gf@TAn4M^gQiK=a;!uCr0tu5BuqSsPAbv|eAnnLFQoda}L&Gv2A0t_amPHM|v zyDDu8aao$mQiLin9X1o>NTQW zuh(7@F!p5W$bka>l-V3+bC?4S@>l!6^zBLQykk+l^pr1Uwt(3J=BjmT$9KsJOnWfF zu<`0eInMVNmM~kwtZg}Dg4F%COADs1W!w+kf0gpKg4qh@Zx7YA2RZ6ST1XjI2@WbL zq|DYZTf=PoPJENb2;oKEV;ht@jI^XE^8%O`z}$61^tf-M=OZEMX}j7#*F?jtK$bs} z;TX*0ZnOVUN_f$vaHgeHVNu(+%apqw6iUGB1RAA}%!^@;4s0=7zx;joB@fN9w_;7x_AoyWnU*^DMQ82V+Hckm zUW$fN+rcb>c?ryQ@66teesbE{ezNcSNsBBTDYFC24lw(a%xur~Ur>LxvqdcC{E*|6 z*%4+(n8$vW+ogZmaKiq&$@ga`;S>5TUnXSl-UVpCzuEBY@ydE>%P>FPo;P1sjP!p!5L;}nD4TGMDAz} zPLnz@&ED|)3dah{z8v=Du*bC+$ryw`zO(X$0h@iWd&?9`-UW6S*qM%{JriRUqFAE} zuRk}g_(YjqVRnW2yP~>&IxV;>@wJ$3Pwe4GFe|#j>;|)DkwdX&8=L*0F!=zReae7E z?X#oc4!|9NNSjy7g$`T$g|$Y~T5Ps$I;HOcy9eyPz036HTRyg*_DH$gXy@Z9%IpcV zC(Lr2Qt2_v))Y5~Fb3{BpeRO}yA!ZwNaJs4YN1QIWt=3 zT%eT+-EbejuS3tS8)l{t%sw!$5a`mIbY{+%Z(9fZNmwP}Q@)=I&$**`U%t59aCmz& zmvsER$wz-M{$R-awBAprPmrBaMhXv~;<&$w4+Q`U0A#xLBBS}Dske%Lu7pPS0y1>u z2?c@)q#h8(y{ukcd$jB2hPMYDrcaGp#D^Gw7!VSZj+xVwmvJLGh;?Q6@%OLzOc0nL zFrja6_~qy?Ha$KzZds~kH5rBR5(@?s4CY{mx4_HQw|q=ap13(U&`wR2K-`bcLI8yT zTJ0BT^C~rdxB55TvS;icB{`@ng;3Z-VIQ+L+Of%LwQ}i>hgLHxZP;ws6~kZ;gMEIR z>|v9%Zt`n1vI%L^@{HL3P)#8mKsbO^o7VR9SF>GnniZb*YS!KYN;>2q~vbB37wu)n{x^F^PC9Gp`0*aArN8iy;ju8sQr_Fu$PZ1*SkIGM;hwqBaS|oI z3g%TXFZ1}k&Ut9kG?!VI(nb}|UdtM}g{)SGc{R-AGVX7lY$&kMZoR`J$u&mDC~s;K ziE1bgt1nrfk$*B#YSlWwvJqcxDf1e5uYq?fCv$k)R^e3mrJ-$Kf z7}@*Msg6%^1I!y>p6PmHZJ>ivB$NGv{LH##sMb)*eGg4!KKt(4x$MLS%DffktuR;Q=4J?snA?98PMvIXOC_8#Z-aRo%tzkOPRV?k zy}G-Qc(Q9p>#YJBbWl$10k!LwI6;q2&d)u2Ge~1Lhqt@3A_mv428qV8fWI zqPuNM<}fppU`~R$@t*e)wO8yPvuxV7*d4ypwzO}zYD}XBo5`S)L0?st3vn}_r`I@6 zcVv0J)hV2nT2Xuka1`?f1zwZkCyh9jTZ1!fmvm}JYf0Lk+SI)~b?Wj-`J zdULlef9Sj$)NUyK1)`a7hN*i1?Ez$vIo)YUyC<`bH zXlcQITg%Aa7E@-E)Y&f$+eH3g_k!IEwz7EaMLm0;#Vd7t$_zhGmiz9~cc* zAPkcW9RPFy(1>OA59Z!_yJXzL_B~fMOz!iA4uUxdM$$R^eUHc}C&{bBIy5_;@8dIv zz#IajHm|vR`U-Dav1#oIi9|W_SWV-mbr{THFeh7?^TyN}7#eJ;KECI~i6k=b!h?fj(9f{2f4>nr}PlUnCw7~`I2-%=~>iEnG76f;8>0+XtIWSzB!I_$04HlHQ?^` z`1`iG&byWU$^)yZ#z2)e7tI8k33ONftR>9R*Fs8)Hrq^+sE_-J(g=!FPXIjuRP(4{ z!RcE!J>Gh=*o04^|iHD{k<)OSOhV>Kfo=B?o8@P-gz-w#=vRQX0g>*OA}sZNl`iFpb9|K;}un zCjndAi#3J}-|SL7)KB@?(Ir`&v;mz0a|%r133>KE*69KEh39KM)Du(f_yL{gQrP-xv`F~$E}DfK(7G3-QQHM zOFw;7!ubuV-vlSJ{~>zDoX+nmpsQ2`X;al#gcC*ZvRNMGvQFw%tkgZ5?BxefPU1Ti zgDLLgRDu&FaOxiBWbx_6sHrXU-Hu$fa=6KNx(4PNRlQ7MPU59FRSLI>iLT|2N6-0u zsVekJF`Iywfn4S~nCoEnMBg6c9zH+&R8P`{ZquoU`OFP4H^8v}F{ZmIpEdQM_uqGF z-FQi~6s}MipfW&3%%eFqGisi#8P;skod1b7g%6bjDhKq8#<265Az!&?!ug7L=V@E{ zOa+*V|BmP;n44hyRK1gDDKoxxNzspuU+#=aB4O?ln@T{HR78IUG-nOf%T>cRY9Pe5lX(#jc;Ww|tqwi!G6FqM8xeMkl z=bGJKA|oPFjT6;bteyTcs>~YvQ3C~|H*KP0&F}cI#e})LuW=Ts@0%5-1 zo*~4U(RW$Ey)69B&OJCc_b1EbE!S$C{vex9lT*q_Ag)eI^9iqX{6fud)5_c#J3Kst@s zdg9BZ&7~!``MA!n^sN}-T3T>Zm^jxX+gxWaMpOVJJk;|yf%_1+kHiJ!Y~D?dahCGe zf3`$+_sKcL|2}f<&G7diulPg5e^2`XTpz&oO?e_2jGt36TFBTg_iDacb{KJfkVW3S zbDcS*#tprhlkEn$H^6<=`K)u!mI{S6S1Rj=y}Cm!MQF&97Nt=c4x;kQb$SS=hj6+P ze79)5_vWyMl|rY}k3DBPkR%^wNsG}Cs9Okw;f{41++u2kTO-_NdTvXiPtBX0)hb+Z z_EsHviNj+afq4W*bX7yZYaj1i=|q>;+a*Fhi1MQ>vf6=L{sBR*p`m=g$MAb>4@Xv+ z{go^CHR6m0Y5HANULsDKIrae~Ea`P|*))M|0{Z#(NEh)r*0KSgBOPte*&h&;vdQ%=jrk5e$4aiSSI71IN6TYLx>NR<*PXzNrlAxZY9J;3aSAkh+_ zQ(7&+TY!5tZ|s#Hzw0e6%YTy5%s~S=oB&Bukfiwx+%s_d&*-$Kti5r)YjC7^QuP&V z6&HuKYI~>%xqV72@K)fHoz_08$~m&&^0sYO1LHMv$#~G1XcEciV4j0HH>+&5)#XL^ zr8&J44a<})wAya01RA(Q-?knwZ(?6ToUqIDCB2}E@8>Z1)%8wX*6ecpY%2J;%sb*7%y zgXL@Y4h(LqbJp5gj)+M95z-q#Z~hMP0(uMPEtr?|D-kaZnM)O-7u*y-SZBcxs2xl@ z80k@D3tqJ{`>xdI8+M6&ZAs-r9e_Fjtr@{wSh;V|yyuUOomeiYEVCRTaU$vj)X9N< zXLu2Hf$0Kc-Y(E^n~48wr(7inK8#*V7m zZb03D0>}40kd-u!sNL~k;XU(`R(?S5!My)F!wcvGm=9D-XMV)-NAMTOQXJ#MUZUG4 z4Ha0oW2<$aqUZtC1E}}O)-S`2{n`o-(jCMDzxQE2f%ya`k+I;>?P~UqwBtuocdoO{ zmgh(J8PMlG5VJ4Ei?0_{FQ|^>H&*gW6O?riWi-y&yA*EAgCgZU2T zw_nNF8QeZZkwXrK#&P7c@8YY>eMUZ)X+ZZHW^59}4&ffU80=YtcYqDfW*& zd3PJi&v}7RAlqC);s=Po{j9@qS~juMvWfYR7cRtqxB$!oF#rBDAFRPs2Mu8g!Y)YJ zJ%%2Y941sEcd9d}=$R@8$3dJD?FXhGn9f_L7Zk4vs$ADK$kgbHjUJy70wV;5rtUg+ z>EVeZI!_(&JeSz2&u4_e2!lB&EHY|KRDP{6^MS<%_Yabl90)^|{($-e5@ZCNF3Zre zIeyLbn%!sj#e@;yl)4BQ5in}G>eHheZY{Tao6xGl9Lf1i;jbO9D11cW6Oy-B)n9kS zTL~ElOXk#61^f;b^?muDz4ZV%4Su|I71kO_IPRfuC_3v+Bf`(H@QUt8bR<&E7)_ zG8(t0MBJK4U7IoPJ+?NpOKbaB1Mu|CYwz zlaPUr4D)|ZV+i;m|F<+`;UoKBN$_{>Lbm0=%l+Td7z&@E|CPqi@duI^27K7hB$$16 zfI@xzy{zQnB>z9BF&y}C;L}Q$KBO&ucgRxP>QUP^=l9&JhQ?_c3fXwou8_^L89P)4 ztE{=n7yNu9M8;|)W<}^JLho9NaXXtW)IVlX;+Jm`pG?sKk$-@c04V`7I>Kh_X-GFk ziOH1Kn4Egk!G}fw8Ud(RKC1A;q321V?~C7E)E4mn!ThPD3`iM}jpJ*TWkwZyAI;rp zn>YLU3%(E?3?0m|xLDfmms!*FCx_Yyg`FdV5?(|j!HfhGDz{+WotV@C>RB5vcMiJV zrzaZ)W)v7^VMImJ!pKY= zjQZahUO;0B!=#M`H1UH=-eZ-I8P-}8rDF0EH}Df12cdCbSdY@g7G&89RXq)#9FdcC zfX`@v(EwvpI&a-Qr!DKPvey>-R40&~EO`NGg3B9^TcIVWReJ zc17Fxbx-+;jR!LxjAuvw0(H&NORdFE4Sc`ja-Yfd31B9G5j$o(=_>4b zq{t6Q8;my96a5MC0@4Ab10gos`H`A_jQsMpefGO9Hf|uRy#=`yI}y-CKw6FEop)Rx z8+bE}9NSLV8St4&U?zd7@Sz{yB)qdmafe~lKzru6D1Jzj0Zj%J>r<3oIy`I>`I$)p zBc+7%n111=HU-cWKt&&e7p~ZKbYAt19rI@U7YFfE(*>go=Ju*HZ(lymSULE0xJ0Gx z5Hc*_MLiYFR4V_GXKhoL#Pzn$ad)i#oPVDr#;Y|wKzb1Rli>xV4@Mu1!MZ0(y*FLb zw8F(te@>Gp8?o>bGXP@%#zJ_`oB-1jiKLw3&lk2FVUkH`9%Kl}5Kz{%_~DzC)UG#r zi_V&B*+pjLcmYiVGwtsTFQDmQrh{?TnB>)!yHeM_?E2oLR|?5*@AA?z0%MeoUx)6# zcOdIr^71cZ7hlS8u5IrF%>Xn5LhBoq3OC54?GgRt7vH9IY6L$ZV=%^lXLtdbfH47c zzjU=H?w zC9!AH99zwO+N~ky!=w2D%?303?+ou1_Z%>Dz%UKGHR5Lb>^InMCK@D@csZRrFd*%% znMQSObHUC9E90A9dAU9Gy6Bxl-v@l~I6!6v=4MOF&^$cdU86lc=w7~om>P0p1ooL# zng{oJaGwz_eVJ94TzHyUnPe*wvy`~c%VrY)5Jp%SnO`9jJORFebYFKLMhHLo`S70) z|MaLMlH<>(Oz;g>EBSbS{zc+HKU-Ry7Rd++poa#L*{nXvn!?Q#ZkpohMOo}01|#3E zFF3X%_+t|BGtDNG8C0^&KsuQz3Bzm#H@{}^G=t}RVU<~%KHk{4vfb#5;Em(>z{M<^ ze5vE%8nS}Ua0~VI@O35ALP7q%fnlC~LN#1E#Ped?;)A)O+y;Hf?kfi>b`$LrwMVk;H6JF)7@M{UH!x8 z?mppxEBHCEgn}g$%yjPGX?dAGW6I~*r~Ow?oJ$lev!w^|lczJ?86ka&%?hqoaLtHt zJ4APpIP7@pYsp7x(`&@lDw}*96XuHCdeD75T|>wcSYD}F!_gX!!vAl)7P3eP|5l35OlvlPP;Q?-an#V$TE<}n2;U%9~x(@d|%$=8M2Rcn6jtkKq zd5)Zdb>WPY?BHexw~cqkC~eJrwqI4*;6TbT=9y#?6@f5{SOjPhphxGtKCB$tG|BW` zKM!9GQG9yRkCuS(J@?^oG0??8&t*BaEG>1{SEITQf0`X1zS#T*iNz6@F~#})I_K&nKkwe z^rXA_yLzDIa0MJ7-~fR|i__bl?i+8v+jw3?%7}KXl@y{;0uI?^Hr6}DHPD03lVSd@ z;|Lu`=uG%(=~XxJOOl<0)8b;Wkq`KRIHEc66zJ~Z9^RhhcFc=pDHN7M;p&6IZ54Xv zC6Q|+x-FcG<@k{-&6bv>B4P4F`9o+KgqA@lY{IiC4eL$o>lj%x?+m_moFB?ET+Kg2 z@o^1v_whvgT3|3k?cO3qMf ztxl3Y7Jq(lYtJpaw+%V5{9v4ash|+ol~hN{4P`k5mP24r%-R_z1JBUMK3c8I)csn2 zgI_Mo|EwYUZ#pi}ae>a8N`bjgHS-%Lw=LURH>C<$>c^>Qmu!4<#&0R8A?jO3ZY*TW zQnE-78cfM0$_q{G9@nhiMOW-Rek+C_i)%Ldr17_6ar6IO$_-L(kP3-C@cH2RgL0@HdfJ{ecp^U@ z_iX85f5g*Ai+iPeK*|GB_eI6_3iqm;2#HibX=&Vhm{hd~dX}FB4f9L&X~^>Y3MX8s1v`=~F5_H@DOJB|ix7U+R~a__N{?s?|?NPMX3W&Y9|(EpV3g_JL(WL58dR6fu&@p65~g@UC* zM@Vt{{&Mwshj_Y1c=jn!Klu8=x5&uR%WbM(!i`(252rn|vi+GACb9Re67q%yT?w}? zS3qC|1oC&xGiLvoy3@1&-QuS2&fz8ejI6*Is85liM1Pg>hm1dD#snMJ&nv2`C|#GQ zSt1{MON+cU^Z(_lb>ogkxDf=vH2|)47lI87M_#rnO8I!CrIv>8|F~CMz%NZAgh6Kd zc^L?Vdm!AWkE;7BTPvn8?)=+rQQ5jDx$&d_3H+^1AOpXsFrdPK%2I)qYGWdqL#rGc zwlH@^pCaCjU)qAVt3M;uhgS)>sRh9~2+rzHj9Q{rZPT@Tc87U-gPQ?y4jPA!*q!*0 zTXYb^eT8Qj-m{T`6>4Dsow_XsLm@buH8-Qb@*raxbuI+wLb9pl3qLjv5@CkoL@1K+ zv>5VmR_vJ~c#AVSR?r!X*KUy^50~$wxc9x{3r73Fg-!0&j$XOFRlp)L$4TcNhUE z8c_6Kpgzn>Ff0F^LC`T^V!#~sdn~ksQFL{jcY4J-6H`-?@fZws+`~gqagikd+(rk# zSop=l&ra0cJlIqsxUAPqHm0EY2Jwsibtp*g3%pSTTvx$$6W{9s*y}$Dj)B%^}zmRd?#`p_w|Z{R~)?3qS7u5`hH&{efd?35eLGss}km!)4FW@NXMo8D)oEpe+oqA$qgN-Qhw|3f4HrO+j^vR zaGkNi+6T8vw>3?da1n6AW@x_$NU}zibUd8m;Us_X`PG8y%Kd0v;S1US9LXC??PJKH zHh|gys(iYOXU4T?`}Es46w<;f?vb|6RoVzqMqX~q$Ty=do!r8fE zR-U@pGHm>`XIk|Syf>Kcqpm*c#q<_1TflgmZn$x!i_tKyE^o!cWi>*in_Rh+Z(=r9KP1ArHEq|~@e^BDeH}>a5kFPwNSqTfruuE^#cu*zk@!~l zGiBcl`@SM_y~%tb#>8n$;J+2!bKk`iVLWec8Ehlo2DEK(AMKJO7^e@kKV#1_zgTwr`-!yI|f0a~S;#?W68x_3&kuHAAlzL{Z|qVcre1$=$43 z%_+}P&g+fb8W`(!9%kkqnD@Z!G&9wzEJJgGhU9?ed0P);lcxOhs|X>^K#v8O1^8cf zUnV8SMfU>T``;+30Y`MX`@rt|Z`Ost1lNN765`S~iZ{Pud z2mV8meD%Re`yj}J|AXWqfQJCCiJBOG*SD&}M=rgJHB-pvx3mufJPc5vYkP&k#<;}p zGu!J`+HYU%15z^tM?fC=A0&?gJo;af>S`G`|0(lB0>+RxZg|cIl~u@J&*DlW;%l^Ba6FG%DL!@X3NtyRhWMgy$-` zXPh$5A2h0Ake((hTUwsx>K5Wl9@oflEQArj2qSyY&_l_voVw$3MY181O-&s~r|y=# zC==W2JlyumU}@HDqLPirSuzRY>;4}SIgrRf9OR3bJ*xu*5B7w{7^T$2G%qF+Ie63x z@r>}LhK2tU2kCN8Lgge>Ud3H2jEFtwJxtc~+jVIPEF3$D+;~QjsYT5H{CjRrLF5!f zP9$&Ir5$^qCw_!+z4@{+HALhTRU{q}u4G%D-$aJ|vgONZsGQ~uNF@i76-sAt;tXWP zuXqf+Ej7jT8HGA)leR55P&lG?u0FzmyBb+~> za*@X%!&Svk?-y?8&r6>NbpBU}$MCw`3t%o}vwUXADlwZmK^Ed%A^a*H3l}hh=du5J z9{1$RjxOcfq<#uXhmhwNa`|%IFT(vI+{rI+tL#tN87a%`%6|&GW%a2~ziRt(&C=Kq;QA8;q+TGLNH@wfh z=T*30h5Ma}dtNfW_&$GswpU^J1R*=(eHB+7ce^IKFVj2FlPs6~Inm9Jp$H;H5P3f& zeb}__iOpLU`q&Tb-L#yD6hVZ$Z4?QCWP&WY^dLia%vAF=ilI>qjkarScJ(ar(Zg2G zmaj84`TCNG6cZ69`OJx1kVMBdz}4TI{KqW~7f#zKfl3Kfe1xLYobHV|{`md%Cwqe4 z;z@^l)m#H}4a~ZBbrG#m$HFgl_PBV7mZXr&tIzJIRQFg4xD@birnsd|*vRPGy$_@> zH|0$3{R@2^^mWiXf{q(DDz0=*U!UC^GW>w(U*H>nZveI~RD9ym`a0Z5f7`*JY)8)K zPUOlYk1D*N%cv1$8R(=D^l?=(7JjbH^HesT5sB(6EkLKDE{AkE;I@$AbBEl`T~xUI ztWLwO54Zcm-14XZTme{7qwPfIEvJAw%a*`1dZT{ZMVicvkPoE1w3bz$?PL|xiq{;rr zWD;i=U7|{@!eCv!E+s-ew?71|xM7gw>-|A0o9D~KxV-Y>Y)(eTIph(r&r&9|+eReN z2%lR`$vRH;Y<9}JeG!4>{(+mQCcu5z=cdEGG#6zj9B&JpniU;frg|A0N(kS#WE>HHBhk&#&N9fKLIk*)QcEscT$nJr$bw=-`-3 z{Jk%!l$!xI1N^Gl*_*e@mu|Y{`xKvbWM{`;6b2y@V(Q~llp~~o|x^tFrIqsW^SA-i+ zdj-&_a77ROnewC$Mv~L@R%RTa#@DO*Je<9T=IdJ7njW_t?4g5Zjnc7-(G`nm= zE>rTwc>7E;BpN`YF1)v3-e$8T^96@7u}WUhm}6*%p&icj5SK39dvY5#%r!2)7V59U zXF9-ifLT*5aZ0|zIZt=*VS0U9iueIdExLA(U{IZ98zf?0v&(*Ry# zU4Xi%(fqgIks}r`#2yb2VRYzz$bZj=-T`_CrNLs;2eekT&AoWPY;J^uu{%GtZZO?o zwy7O8xNm8)VOjoJ0j>H=7zJ`8dJpD3m~WQQcbp?clROz)o1*~K7#oOW_-z>dvA7SFI!|rUwcaNe4j-(Jz#pk=uOp`USEFp zaE-iXmW-CY13#@#U_Mb3NWlyBUuM+431O(%jALpm#q$&U4Cph2JT$W9i-y;|9H3=0 z%wkOTP`*$vm|igc9lCD*k)^R~@9aE#UP+PM)_J-A0_F>tm7->ihaPJl>WzCF9(dzo z_7C@;mG%|T*S{x5BXgd((|iN-4NRU+<#5ZqnR6#yYCoA4qW_SzN@3a^bX9mXbs@JM zf`148J)5P>mXc!~5|k4ez-HqV`JXz+G+9H*vj3sZ{sZCf`#d7*-``YO5T)HZH`v^d z>SoWOx%1#36#N5lPC8AM{OWBEU9LBJLb8|c2kPSJOVe^ldbAwE-eQ%#&MiKeUQ91o zIz@BJRf3XT*!!{qUfCpOp{e69#LTvT6`r$UAeypY5JiT?`m7~cDefnWya zuv+r_$?+c6Bydgwev#p;&UbyS9+4+-=~BPlk)ovCG?V<2#yAMfATXVKE)PhWFnZGP zs1u(J&j-IF4E_;D5{x7m-G}`qJl@1oh?Q8qw{_eRJXE=Gn89EMgAt`Mmnf>Pt#opd zJ65rH`lq8*>&wHMg~2)GfxZ-{SLIC-cdON&B1Lwy*KAvb+oN>Y%Kf=mHxR`#m} z4_8eZ;Q3(PK)3!>V=Lj^^^G~HN&}Y$-sdOY^jT}($x1S1V3UDO`l>*Z#pZx}y?c&+ znzF75A2$ipcH`n9!6VfnK!*T5_bg#Z!YH{B;;YDyGpz3H^8JIA1uF}->cXcJx@IH8 zr@XpjOB$L`^e-$E!g7G+0GGMT$=vTRzw`5C`bBTGj9b63K!*Yy3UsQLX4l@iF(;+m z)SQb>mSs@rh(6&C13C=o>pe40d)miIiuZ^v_b7Ptx(~{Imo5)h9_&EFT16l7+adwo zYG-(XD-V}m4GS%t-Cwa_hzv6cIVA3 zx{0%q(I4mtpd)~K3)@)~F8pH7C~v^y0z z;Ov2EvVx-kZKOzu@36TY5k*dYIF{(aEO=^@0=RWspYVq4-p$JG6sK) zfzJpLbsVcx{;cK)Lq(Wlabhe|71x;`GA;NsJ^5*HN1k?EDM^&OHNrSBbfwW(WZKNZ9r)shM8`@72RbRbX-zX)*dT> zxw+SYkPet9=PII~)R<3k+@5LNYuAUlaMl4x7R?O+pxbsAZ z+?&yVP69It%&9x?#$+ZkM~?_O#VoLUn2uE(oG+Pq>}0T$!OGur7}#WJviN$k^?mXDuh@8dfo+BC)VJM#pt?YHfx0ZIu@-B4ZmGyLFjIOhevPy5 za^I~2rh=Ucc5J7c8*{+1`Z&|xc+D904;zwgZkF@_=>hUCeR1)zl=d`hzmrC>K}QNm z+8FW>)R;5e(FdvzRMb*5c;7rdT`^U_nndHt42p5V0AcH?3!u-q&??NyHY6x_U zepSCG&ELPMUvSjwY`QUx$Z?+?r-7LUrhWH-8iR3Se(M97rruczyxn3=$VZb%cRIl7 z0F~=D2`HIg)A}B?q206h-4*1O(=8f-F#=m^O3@XIZdW5P79A)Oyol*fJ^|Dt33TK zdPvB|P|VbO_2fNLgc0Uk_cOuF1hc*3>X`D@HbJKk?0=jFnQM`uG!L2uXciz_jk!~+ z%4dk1UOY1)T&Cuw{=y9X&U-O=Ay_+vI2h1EWO~z&s^uP!o z%a5{$E~$PT#AoJ$nF}WViRh+B{e;3((&)ZN4C`+3nR#I5{S1itM?|<(<^!4!NGmkE zv0Kr8>9&mblLra1B=|z6U`+odpgEjN&J2thnBkQpFXkSQkE~5xd#6!TgR_S5r_>>ulgdD{~`?nPlm^*>giymJ%vHHI%sJJ>e;MTE31J_F=J z)=;trlj?eP)cbr*53gg@S@WVr2Jo2$U>1N$AE3j^?h-CcQuElBoVoBNpRoaB1E##~ zqJH<&g7GG2GYwp7WCtcJmn*qfjJ%@7FY=)!fR+GC z>z)%S+qr*NkYvi$2sgWCKH~t!0nB5&Wq@ywK^ zz2%N;=?#2nIiTf$rp);!GOS)HbcEfe#xEYONqoiyj0>2`V=|+^4YQrHDYPhW`PisF z`F9253MMM5e1mJx0k^X+OC=?zAEDX|H~(&c+yLDubnXbVo)=J9m)0*i$$KL|F?TTT zU^*AgkiV||A?Qu_jQC^+M>Rg<0mcK&_h#Xfi`0eB=#6KwW-Ku~!Dl?dc!JS6JbENk zE54z&MLK1tpiPY%AMyg^1;{aLaEbMBNxdfNarAcwzmT~aURisC@dmTl-MC-2t+-jY zon{z9l2H4K z`+_5uqeJJ`tREOZFf`@;Mjr+k_$Ch&$l2`~jTr$hvjWTtFyU|B_E=z(~hNdCJ6SLfafJIqfl7)&sjQ|-~GY9uQ(BnEtYcEiC9w<>ajMF$)LCIpPc zR>|Q{e8Qfd>weid*rORbgu#tE6ig_X2MZp=AD_zHQD9XcCX&;zG=~~-^c}&3feiy| zaq4Z#wXFT0T+A*E4XHSP9eSKTDI82VnDx)3@~zJoH?+OD!Fav97k&JLv%|mteB*OC;=(IjrEPV)Q{moUJROa4sr`MXwfDkO}0BhA6RU7@|2t@|8GV z$vKX}aZC=Y+ek{8nx=^5oL`0Wt8!R1+XryYujZU*;yjacyavZ>ILC1~jwAB`u3{X1 zE$93?oL|Q|UXSDToa1;L$LFwglw~;l2G047IKPo|oPgs5&haK3Z^~gw=?~@bn>pvV z;QSWOaUzZrImcUZyp?mj4aeI!$J=qdopZbc$2)M$kxb&8PR8kE&hbth@8lfs!tpN7 p@opUN#_>?SwT`opY4iQ{MFKKb$E{{bzE)}#Oc diff --git a/data/items/items.xml b/data/items/items.xml index 1e33fc81..f54b66c8 100644 --- a/data/items/items.xml +++ b/data/items/items.xml @@ -1,48 +1,46 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - + - - - - - - + + + @@ -62,58 +60,46 @@ - - - - - - - - - - - + - - @@ -124,24 +110,19 @@ - - - - - @@ -156,33 +137,27 @@ - - - - - - @@ -192,112 +167,84 @@ - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - + + @@ -306,19 +253,11 @@ - - - - - - + + - - - - - - + + @@ -328,46 +267,27 @@ - - - - + - - - + - - - - - - - - - - - - - - - - - - + + + + + + - - @@ -377,60 +297,39 @@ - - - - - - - - - - - - + + + + - - - - + - - + - - - - - - - + + - - - - + - @@ -492,11 +391,8 @@ - - - + - @@ -532,25 +428,19 @@ - - - + - - - - + - @@ -574,28 +464,24 @@ - - - - @@ -700,43 +586,30 @@ - - - - - - - - - - - - + + - - - - + @@ -746,12 +619,8 @@ - - - - - - + + @@ -759,9 +628,7 @@ - - - + @@ -769,23 +636,19 @@ - - - - @@ -795,7 +658,6 @@ - @@ -805,148 +667,92 @@ - - - - - - - - - - - - - - + + + - - - - - - - + + - - - + - - - - - + - - - + - - - - - - - - - + + - - - + - - - - - - - - - - + + + - - - + - - - - - - - - - - - - - + + + + - - - - - - - + + @@ -954,38 +760,23 @@ - - - + - - - + - - - - + - - - - - - + + - - - - - - + + @@ -994,9 +785,7 @@ - - - + @@ -1004,9 +793,7 @@ - - - + @@ -1021,13 +808,9 @@ - - - + - - - + @@ -1037,58 +820,44 @@ - - - - + - - - - - - + + - - - - - - - @@ -1110,38 +879,28 @@ - - - - - - - - - - @@ -1150,18 +909,12 @@ - - - - - - @@ -1184,892 +937,486 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - @@ -2077,16 +1424,8 @@ - - - - - - - - @@ -2094,16 +1433,8 @@ - - - - - - - - @@ -2111,43 +1442,24 @@ - - - - - - - - - - - - - - - - - - - @@ -2176,7 +1488,6 @@ - @@ -2184,560 +1495,267 @@ - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2745,27 +1763,15 @@ - - - - - - - - - - - - @@ -2773,178 +1779,102 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - @@ -2952,16 +1882,13 @@ - - - + + + - - - - + @@ -2999,7 +1926,6 @@ - @@ -3007,48 +1933,29 @@ - - - - - - - - - + + + - - - - + - - - - - - - - + - - - @@ -3057,23 +1964,16 @@ - - - - - - - @@ -3089,55 +1989,36 @@ - - - - - - - - - - - + - - - - - - - - - @@ -3152,70 +2033,56 @@ + - - - + - - - - + - - - - - - - - - - @@ -3235,11 +2102,9 @@ - - @@ -3254,283 +2119,127 @@ - - - - - - - - - + + + - - - - - - - - - - - - - - - + + + + + - - - + - - - - + - - - - + - - - - - - + + - - - - + - - - + - - - - - - - - - + + + - - - + - - - - - - - - - - - - - + + + + - - - - - - - - - - - - + + + + - - - + - - - - - - - - - - - - + + + + - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + @@ -3791,99 +2500,53 @@ - - - - - - + + - - - - - - - - - - - - - - - - - - + + + + + + - - - + - - - - + - - - - + - - - - - - - - - + + + - - - - - - - - - - - - - - - + + + - - - - - - + + @@ -3894,46 +2557,28 @@ - - - + - - - + - - - - - - - - - + + - - - - - - + + - - - + - @@ -3958,7 +2603,6 @@ - @@ -3979,9 +2623,7 @@ - - - + @@ -3999,48 +2641,33 @@ - - - - - - + - - - - - + - - - - - - - + + - @@ -4048,113 +2675,64 @@ - - - - - - - - - + + + - - - - - - - - + + + - - - - - - - - + + - - - - - + - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + @@ -4164,62 +2742,31 @@ - - - - - - - - - - - - - - - + + + + + - - - - - - + + - - - - - - + + - - - - - - - + + - - - - - - - - - - - - + + + + @@ -4229,9 +2776,6 @@ - - - @@ -4242,30 +2786,21 @@ - - - - - - - + - - - @@ -4275,9 +2810,6 @@ - - - @@ -4287,9 +2819,6 @@ - - - @@ -4299,17 +2828,11 @@ - - - - - - @@ -4319,12 +2842,8 @@ - - - - @@ -4333,25 +2852,15 @@ - - - - - - - - - - @@ -4372,21 +2881,14 @@ - - - - - - - @@ -4395,9 +2897,6 @@ - - - @@ -4407,20 +2906,12 @@ - - - - - - - - @@ -4428,12 +2919,8 @@ - - - - @@ -4441,13 +2928,9 @@ - - - - @@ -4457,7 +2940,6 @@ - @@ -4466,76 +2948,45 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - - - + + - - - - - - - - - - - - + + + + @@ -4552,331 +3003,209 @@ - - - - - - - - - - - - + + + + - - - - - - - - - - - - + + + + - - - + - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - + - - - - - - - - - - - - - - + + + - - - - - - - + - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - + - @@ -4896,860 +3225,612 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - + - - - - - - + - - - - - - - - - - - - + + + + - - - - - - - - + + - - - - - - - - - + + - - - - - - - - - + + - - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - + + + - - - + - - - + - - - - - - + + - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -5757,14 +3838,12 @@ - - @@ -5777,7 +3856,6 @@ - @@ -5785,7 +3863,6 @@ - @@ -5793,7 +3870,6 @@ - @@ -5808,12 +3884,10 @@ - - @@ -5822,19 +3896,16 @@ - - - @@ -5872,6 +3943,7 @@ + @@ -5908,268 +3980,177 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -6198,74 +4179,52 @@ - - - - - - - - - + - - - - - - - - - - - - - - + + + + - - - - @@ -6278,7 +4237,6 @@ - @@ -6288,470 +4246,302 @@ - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - + - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -6760,121 +4550,87 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -6882,9 +4638,9 @@ - + @@ -6894,107 +4650,66 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -7006,124 +4721,57 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -7131,16 +4779,6 @@ - - - - - - - - - - @@ -7148,16 +4786,6 @@ - - - - - - - - - - @@ -7165,16 +4793,6 @@ - - - - - - - - - - @@ -7182,83 +4800,49 @@ - - - - - - - - - - - + - - - - - - - - - - - - - - + - - - - - - - - - - - - + @@ -7268,45 +4852,29 @@ - - - - - - - - - - - - - - - - @@ -7314,24 +4882,16 @@ - - - - - - - - @@ -7339,13 +4899,8 @@ - - - - - @@ -7356,108 +4911,71 @@ - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -7465,9 +4983,6 @@ - - - @@ -7480,41 +4995,28 @@ - - - - - - - - - - - - - @@ -7524,58 +5026,45 @@ - - - - - - - - - - - - - @@ -7591,32 +5080,24 @@ - - - - - - + - - - @@ -7628,26 +5109,22 @@ - - - - @@ -7664,38 +5141,32 @@ - - - - - - @@ -7706,215 +5177,182 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -7922,50 +5360,37 @@ - - - - - - - - - + - - - - - @@ -7975,32 +5400,26 @@ - - - - - - @@ -8012,69 +5431,51 @@ - - - - - - - - - - - + - - - - + - - - - - @@ -8082,65 +5483,55 @@ - - - - - - - - - - @@ -8151,33 +5542,21 @@ - - - - - - - + - - - - - - + - @@ -8185,7 +5564,6 @@ - @@ -8199,51 +5577,39 @@ - - - - - - - - - - - - @@ -8256,89 +5622,47 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -8352,104 +5676,57 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -8462,16 +5739,8 @@ - - - - - - - - @@ -8479,15 +5748,8 @@ - - - - - - - @@ -8501,39 +5763,21 @@ - - - - - - - - - - - - - - - - - - @@ -8541,50 +5785,28 @@ - - - - - - - - - - - - - - - - - - - - - - @@ -8598,82 +5820,45 @@ - - - - - - - - - - - - - - - - - + - - - - - - - - - - - + - - - - - - - - - - - @@ -8687,82 +5872,46 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -8775,14 +5924,8 @@ - - - - - - @@ -8796,15 +5939,8 @@ - - - - - - - @@ -8818,73 +5954,40 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -8898,26 +6001,14 @@ - - - - - - - - - - - - @@ -8930,15 +6021,8 @@ - - - - - - - @@ -8952,43 +6036,22 @@ - - - - - - - - - - - - - - - - - - - - - @@ -9001,26 +6064,14 @@ - - - - - - - - - - - - @@ -9033,15 +6084,8 @@ - - - - - - - @@ -9054,15 +6098,8 @@ - - - - - - - @@ -9076,15 +6113,8 @@ - - - - - - - @@ -9092,15 +6122,8 @@ - - - - - - - @@ -9109,26 +6132,14 @@ - - - - - - - - - - - - @@ -9141,15 +6152,8 @@ - - - - - - - @@ -9163,26 +6167,14 @@ - - - - - - - - - - - - @@ -9194,60 +6186,31 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -9262,12 +6225,6 @@ - - - - - - @@ -9283,16 +6240,8 @@ - - - - - - - - @@ -9305,29 +6254,15 @@ - - - - - - - - - - - - - - @@ -9340,51 +6275,28 @@ - - - - - - - - - - - - - - - - - - - - - - - @@ -9397,15 +6309,8 @@ - - - - - - - @@ -9419,15 +6324,8 @@ - - - - - - - @@ -9441,15 +6339,8 @@ - - - - - - - @@ -9462,31 +6353,16 @@ - - - - - - - - - - - - - - - @@ -9499,67 +6375,37 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -9572,81 +6418,51 @@ - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - @@ -9658,20 +6474,12 @@ - - - - - - - - @@ -9683,46 +6491,24 @@ - - - - - - - - - - - - - - - - - - - - - - @@ -9734,12 +6520,8 @@ - - - - @@ -9751,30 +6533,17 @@ - - - - - - - - - - - - - @@ -9785,12 +6554,8 @@ - - - - @@ -9802,86 +6567,44 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -9893,12 +6616,8 @@ - - - - @@ -9910,38 +6629,20 @@ - - - - - - - - - - - - - - - - - - @@ -9952,12 +6653,8 @@ - - - - @@ -9969,13 +6666,8 @@ - - - - - @@ -9987,12 +6679,8 @@ - - - - @@ -10004,28 +6692,16 @@ - - - - - - - - - - - - @@ -10036,12 +6712,8 @@ - - - - @@ -10053,12 +6725,8 @@ - - - - @@ -10069,12 +6737,8 @@ - - - - @@ -10087,22 +6751,12 @@ - - - - - - - - - - @@ -10114,12 +6768,8 @@ - - - - @@ -10132,21 +6782,13 @@ - - - - - - - - @@ -10158,45 +6800,25 @@ - - - - - - - - - - - - - - - - - - - - @@ -10208,35 +6830,20 @@ - - - - - - - - - - - - - - - @@ -10247,12 +6854,8 @@ - - - - @@ -10265,48 +6868,28 @@ - - - - - - - - - - - - - - - - - - - - @@ -10320,21 +6903,13 @@ - - - - - - - - @@ -10347,21 +6922,14 @@ - - - - - - - @@ -10374,12 +6942,8 @@ - - - - @@ -10392,12 +6956,8 @@ - - - - @@ -10411,21 +6971,13 @@ - - - - - - - - @@ -10439,22 +6991,14 @@ - - - - - - - - @@ -10468,39 +7012,23 @@ - - - - - - - - - - - - + - - - - - @@ -10513,31 +7041,19 @@ - - - - - - - - - - - - @@ -10550,21 +7066,13 @@ - - - - - - - - @@ -10577,12 +7085,8 @@ - - - - @@ -10596,12 +7100,8 @@ - - - - @@ -10614,12 +7114,8 @@ - - - - @@ -10632,12 +7128,8 @@ - - - - @@ -10650,21 +7142,13 @@ - - - - - - - - @@ -10678,30 +7162,18 @@ - - - - - - - - - - - - @@ -10714,21 +7186,13 @@ - - - - - - - - @@ -10741,49 +7205,29 @@ - - - - - - - - - - - - - - - - - - - - @@ -10792,7 +7236,6 @@ - @@ -10801,124 +7244,87 @@ - - - - - - - - - - - - + - - - - - - - - - - - + - - - - - - - - - - - - - - - - @@ -10926,31 +7332,24 @@ - - - - - - - @@ -10966,84 +7365,59 @@ - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - @@ -11071,7 +7445,6 @@ - @@ -11097,167 +7470,95 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -11270,49 +7571,25 @@ - - - - - - - - - - - - - - - - - - - - - - - - @@ -11323,151 +7600,109 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -11477,450 +7712,231 @@ - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - + + - - - + - - - - - - - - + + - - - - - - - - - - - - - - - - - - - + + + + - - - - + - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - + + - - - - - - - - - - - - - + + + + - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - + + + - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - + + + + + - - - + - - - - - - - - - - - - - - - + + + + + - - - - - - - - - + + + - - - + - - - - - - - - - + + + - - - + @@ -12127,6 +8143,7 @@ + @@ -12147,16 +8164,10 @@ - - + - - - - - @@ -12241,18 +8252,14 @@ - - - - - + @@ -12267,12 +8274,8 @@ - - - - - - + + @@ -12312,6 +8315,7 @@ + @@ -12349,7 +8353,6 @@ - @@ -12367,7 +8370,6 @@ - @@ -12482,7 +8484,6 @@ - @@ -12564,7 +8565,6 @@ - @@ -12617,11 +8617,11 @@ - + @@ -12698,9 +8698,7 @@ - - - + @@ -12719,9 +8717,7 @@ - - - + @@ -12738,6 +8734,7 @@ + @@ -13322,16 +9319,19 @@ + + + @@ -13392,6 +9392,7 @@ + @@ -13457,7 +9458,7 @@ - + @@ -13575,13 +9576,11 @@ - - @@ -13958,35 +9957,20 @@ - - - + - - - - - - + + - - - + - - - + - - - - - - + + - @@ -13994,7 +9978,6 @@ - @@ -14002,7 +9985,6 @@ - @@ -14011,7 +9993,6 @@ - @@ -14020,7 +10001,6 @@ - @@ -14029,52 +10009,38 @@ - - - - - + - - - - + - - - - + - - - - + - @@ -14085,7 +10051,6 @@ - @@ -14093,12 +10058,10 @@ - - @@ -14106,20 +10069,14 @@ - - - - - - @@ -14128,20 +10085,16 @@ - - - - @@ -14156,55 +10109,44 @@ - - - - - - - - - - - - + @@ -14238,26 +10180,18 @@ - - - - - + - - - + - - - + @@ -14274,52 +10208,24 @@ - - - + - - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + @@ -14327,7 +10233,6 @@ - @@ -14335,13 +10240,9 @@ - - - + - - - + @@ -14351,89 +10252,57 @@ - - - - - - + + - - - - + - - - - - - - - - + + - - - + - - - - + - - - - + - - - - + - - - - - - - + + - - - + @@ -14441,37 +10310,21 @@ - - - - + - - - - - - - - - - - - - - - - + + + + + - - @@ -14492,17 +10345,14 @@ - - - @@ -14511,18 +10361,12 @@ - - - - - - - + + - @@ -14709,20 +10553,12 @@ - - - - - - + + - - - - - - + + @@ -14732,12 +10568,8 @@ - - - - - - + + @@ -14807,275 +10639,152 @@ - - - - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - + - - - + - - - + - - - + - - - - - - - - - + + + - - - - - - - - - - - - + + + + - - - - - - - - - - - - + + + + - - - + - - - + - - - + - - - + - - - - - - - - - - - - - + - - - - + - - - - - - - - - - + + + - - - - - - - - - + + + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - + + - - @@ -15094,12 +10803,8 @@ - - - - - - + + @@ -15131,7 +10836,6 @@ - @@ -15139,7 +10843,6 @@ - @@ -15209,41 +10912,22 @@ - - - - - - - + + - - - - + - - - - - - - - - - - - - - - - + + + + + @@ -15265,34 +10949,17 @@ - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - + + @@ -15327,33 +10994,15 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + @@ -15370,48 +11019,29 @@ - - - - - - - - + + - - - - - - - + + - - - - - - - - - - - - + + + + @@ -15429,25 +11059,16 @@ - - - - - - - + + - - - - + - @@ -15470,9 +11091,7 @@ - - - + @@ -15498,15 +11117,11 @@ - - - + - - @@ -15517,13 +11132,8 @@ - - - - - - + @@ -15544,26 +11154,18 @@ - - - + - - - - + - - - - + @@ -15579,41 +11181,26 @@ - - - - - - + + - - - - - - + + - - - - - - - + + - - @@ -15623,31 +11210,24 @@ - - - - - - - @@ -15656,33 +11236,22 @@ - - - - - - - - - - - @@ -15691,24 +11260,20 @@ - - - - @@ -15716,82 +11281,58 @@ - - - + - - - - - - - - - - + + + - - - - - - - + + - - - - - - - - - - @@ -15816,12 +11357,10 @@ - - @@ -15829,85 +11368,66 @@ - - - - - - - - - - - - - - - - - - - @@ -15929,81 +11449,54 @@ - - - + - - - - - - - - - - - - - - - - - - - - - - - - - @@ -16038,7 +11531,6 @@ - @@ -16051,17 +11543,14 @@ - - - @@ -16069,17 +11558,14 @@ - - - @@ -16087,63 +11573,48 @@ - - - - - - - - - - - - - - - - + @@ -16283,6 +11754,7 @@ + @@ -16324,6 +11796,7 @@ + @@ -16341,6 +11814,7 @@ + @@ -16358,6 +11832,7 @@ + @@ -16382,6 +11857,7 @@ + @@ -16410,17 +11886,20 @@ + + + @@ -16433,42 +11912,49 @@ + + + + + + + @@ -16481,6 +11967,7 @@ + @@ -16493,6 +11980,7 @@ + @@ -16713,12 +12201,14 @@ + + @@ -16773,7 +12263,6 @@ - @@ -16803,6 +12292,7 @@ + @@ -16861,12 +12351,11 @@ + - - @@ -16886,47 +12375,32 @@ - - - - - - + - - - - - - - - - - @@ -16941,21 +12415,14 @@ - - - - - - - @@ -16966,37 +12433,31 @@ - - - - - - @@ -17006,44 +12467,31 @@ - - - - - - - - - - - - - - + + - @@ -17052,7 +12500,6 @@ - @@ -17060,36 +12507,23 @@ - - - - - - - - - - + + - - - - - + - @@ -17162,17 +12596,11 @@ - - - + - - - - - - + + @@ -17242,60 +12670,39 @@ - - - + - - - - + - - - - - - - - - - - - - - - + + + + - - - - - @@ -17305,9 +12712,6 @@ - - - @@ -17561,7 +12965,6 @@ - @@ -17577,42 +12980,34 @@ - - - - - - - - @@ -17637,63 +13032,49 @@ - - - - - - - - - + - - - - - + - - @@ -17707,34 +13088,22 @@ - - - - - - + - - - - + - - - + - - @@ -17748,100 +13117,53 @@ - - - - - - - + - - - - - - + - - - - - + - - - - + - - - - - + - - - - - + - - - - - + - - - - - + - - - - - + - - - - - - - - - - + + - @@ -17849,11 +13171,9 @@ - - @@ -17865,43 +13185,34 @@ - - - - - - - - - @@ -17909,17 +13220,14 @@ - - - @@ -17928,15 +13236,12 @@ - - - @@ -17946,11 +13251,9 @@ - - @@ -17969,19 +13272,14 @@ - - - - + - - @@ -17999,51 +13297,28 @@ - - - - - - - - - - - - - - - - - - - - - - - @@ -18086,25 +13361,20 @@ - - - - - @@ -18114,7 +13384,6 @@ - @@ -18127,13 +13396,6 @@ - - - - - - - @@ -18150,43 +13412,34 @@ - - - - + - - - - - - @@ -18195,172 +13448,118 @@ - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - + + - - - + - - - - - - - - - - - - + + + + - - - - - - - + + - - - - - - + + - - - - - - - - + + @@ -18397,34 +13596,16 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - + + @@ -18515,67 +13696,35 @@ - - - - - - + + - - - - - - - - - - - - + + + + - - - - - - - - - - - + + + - - - - - - - - - - - - + + + - - - - + @@ -18649,7 +13798,6 @@ - @@ -18666,16 +13814,10 @@ - - - - - - + + - - - + @@ -18696,108 +13838,69 @@ - - - - - - - - - + + + - - - + - - - - - - - - - + + + - - - - - - - - + - - - - - - - - - - - - + + + + - - - - - - - + - - - - @@ -18805,23 +13908,16 @@ - - - - - - - + + - - - + @@ -18832,16 +13928,14 @@ - - + - @@ -18854,39 +13948,32 @@ - - - - - - - @@ -18906,7 +13993,6 @@ - @@ -18915,21 +14001,15 @@ - - - - + - - - + - @@ -18957,31 +14037,18 @@ - - - - - - - - - - - - - - - - - + + + + + - @@ -18990,7 +14057,6 @@ - @@ -19134,23 +14200,15 @@ - - - - - - - - @@ -19171,104 +14229,58 @@ - - - + - - - - + - - - + - - - - - - - - - + + + - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - @@ -19276,54 +14288,32 @@ - - - - - - - - - - - - - - - - - - - - - - @@ -19358,20 +14348,12 @@ - - - - - - - - @@ -19380,15 +14362,8 @@ - - - - - - - @@ -19402,30 +14377,15 @@ - - - - - - - - - - - - - - - @@ -19438,16 +14398,8 @@ - - - - - - - - @@ -19460,15 +14412,8 @@ - - - - - - - @@ -19482,15 +14427,8 @@ - - - - - - - @@ -19503,59 +14441,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -19569,12 +14478,6 @@ - - - - - - @@ -19583,15 +14486,8 @@ - - - - - - - @@ -19604,16 +14500,8 @@ - - - - - - - - @@ -19627,51 +14515,35 @@ - - - - - - - - - - - - - - - - @@ -19684,16 +14556,8 @@ - - - - - - - - @@ -19706,16 +14570,8 @@ - - - - - - - - @@ -19728,15 +14584,8 @@ - - - - - - - @@ -19749,16 +14598,8 @@ - - - - - - - - @@ -19772,16 +14613,8 @@ - - - - - - - - @@ -19794,16 +14627,8 @@ - - - - - - - - @@ -19816,26 +14641,13 @@ - - - - - - - - - - - - - @@ -19849,26 +14661,13 @@ - - - - - - - - - - - - - @@ -19883,30 +14682,15 @@ - - - - - - - - - - - - - - - @@ -19920,16 +14704,8 @@ - - - - - - - - @@ -19943,15 +14719,8 @@ - - - - - - - @@ -19964,15 +14733,8 @@ - - - - - - - @@ -19985,15 +14747,8 @@ - - - - - - - @@ -20006,15 +14761,8 @@ - - - - - - - @@ -20027,12 +14775,6 @@ - - - - - - @@ -20040,15 +14782,8 @@ - - - - - - - @@ -20060,29 +14795,15 @@ - - - - - - - - - - - - - - @@ -20095,16 +14816,8 @@ - - - - - - - - @@ -20117,29 +14830,15 @@ - - - - - - - - - - - - - - @@ -20152,46 +14851,24 @@ - - - - - - - - - - - - - - - - - - - - - - @@ -20205,15 +14882,8 @@ - - - - - - - @@ -20226,15 +14896,8 @@ - - - - - - - @@ -20247,43 +14910,22 @@ - - - - - - - - - - - - - - - - - - - - - @@ -20297,15 +14939,8 @@ - - - - - - - @@ -20318,30 +14953,15 @@ - - - - - - - - - - - - - - - @@ -20354,15 +14974,8 @@ - - - - - - - @@ -20377,47 +14990,35 @@ - - - - - - - - - - - - @@ -20425,19 +15026,11 @@ - - - - - - - - @@ -20445,16 +15038,8 @@ - - - - - - - - @@ -20466,15 +15051,8 @@ - - - - - - - @@ -20487,16 +15065,8 @@ - - - - - - - - @@ -20509,31 +15079,15 @@ - - - - - - - - - - - - - - - - @@ -20546,15 +15100,8 @@ - - - - - - - @@ -20566,26 +15113,15 @@ - - - - - - - - + - - - - @@ -20597,20 +15133,13 @@ - - - - - - - @@ -20623,28 +15152,16 @@ - - - - - - - - - - - - @@ -20657,70 +15174,43 @@ - - - - - - - - - - - + - - - - - - - + + - - - + - - - + - - - + - - - - - - - + + - @@ -20733,17 +15223,12 @@ - - - - - @@ -20791,79 +15276,53 @@ - - - - - - - - + - - - - - - - - - + + + - - - + - - - + - - - + - - - - - - + - - - + @@ -20938,15 +15397,10 @@ - - - - - - + + - @@ -20956,7 +15410,6 @@ - @@ -20965,31 +15418,21 @@ - - - + - - - - + - - - - - @@ -20998,11 +15441,9 @@ - - @@ -21020,138 +15461,79 @@ - - - - - - - + + - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - + + + - - - - - - - + + - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - + + + + + - - - + - - - - - - @@ -21159,9 +15541,7 @@ - - - + @@ -21171,7 +15551,6 @@ - @@ -21192,91 +15571,67 @@ - - - - + - - - - + - - - - - - - - - - - - - + + - - - - - + - - - + - @@ -21308,36 +15663,29 @@ - - - - - - - @@ -21353,18 +15701,12 @@ - - - + - - - - + - @@ -21372,87 +15714,59 @@ - - - - - - - - - - - - - - - - + - - - + - - - - - - - - - - - @@ -21466,16 +15780,8 @@ - - - - - - - - @@ -21489,16 +15795,8 @@ - - - - - - - - @@ -21513,13 +15811,6 @@ - - - - - - - @@ -21536,13 +15827,6 @@ - - - - - - - @@ -21558,16 +15842,8 @@ - - - - - - - - @@ -21582,16 +15858,8 @@ - - - - - - - - @@ -21606,13 +15874,6 @@ - - - - - - - @@ -21621,22 +15882,14 @@ - - - - - - - - - + @@ -21644,13 +15897,6 @@ - - - - - - - @@ -21659,44 +15905,24 @@ - - - - - - - - - - - - - - - - - - + + + - - - - - @@ -21704,242 +15930,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -21954,37 +16061,20 @@ - - - - - - - - - - - - - - - - - @@ -21997,31 +16087,18 @@ - - - - - - + - - - - - - - - - - + + - - + + @@ -22033,16 +16110,11 @@ - - - - - - - + + @@ -22054,62 +16126,35 @@ - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - - - - - - @@ -22117,43 +16162,25 @@ - - - - - - - - - - - - - + - - - - - - @@ -22164,14 +16191,8 @@ - - - - - - @@ -22182,19 +16203,8 @@ - - - - - - - - - - - @@ -22205,50 +16215,23 @@ - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - @@ -22262,16 +16245,6 @@ - - - - - - - - - - @@ -22284,16 +16257,6 @@ - - - - - - - - - - @@ -22306,28 +16269,12 @@ - - - - - - - - - - - - - - - - @@ -22340,15 +16287,8 @@ - - - - - - - @@ -22361,15 +16301,8 @@ - - - - - - - @@ -22382,30 +16315,15 @@ - - - - - - - - - - - - - - - @@ -22418,12 +16336,6 @@ - - - - - - @@ -22438,16 +16350,8 @@ - - - - - - - - @@ -22460,12 +16364,6 @@ - - - - - - @@ -22480,12 +16378,6 @@ - - - - - - @@ -22493,13 +16385,6 @@ - - - - - - - @@ -22567,7 +16452,6 @@ - @@ -22640,9 +16524,7 @@ - - - + @@ -22704,34 +16586,26 @@ - - - - - + - - - - @@ -22752,31 +16626,26 @@ - - - - - @@ -22784,40 +16653,33 @@ - - - - - - - @@ -22838,25 +16700,19 @@ - - - + - - - - @@ -22872,52 +16728,32 @@ - - - - - - + - - - - - - - - - + + + - - - - - - - - - - - - - + + + + @@ -22978,47 +16814,24 @@ - - - - - - + + - - - - - - - - - - - - - + + + + - - - - - - + + - - - - - - - - - + + + @@ -23072,205 +16885,101 @@ - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - - + + + - - - - - - - - - + + + - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - + + + + + - - - - - - + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - + - - - - - - - - - + + + - - - - + - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - + - - - - - - - - + + - - - + - - - + - - - + @@ -23279,7 +16988,6 @@ - @@ -23300,12 +17008,8 @@ - - - - - - + + @@ -23318,12 +17022,8 @@ - - - - - - + + @@ -23340,7 +17040,6 @@ - @@ -23356,18 +17055,10 @@ - - - - - - - - - - - - + + + + @@ -23387,26 +17078,17 @@ - - - - - - - - - - + + + - - @@ -23417,7 +17099,6 @@ - @@ -23427,7 +17108,6 @@ - @@ -23452,24 +17132,17 @@ - - - + - - - - - - + + - @@ -23480,24 +17153,19 @@ - - - - - @@ -23510,83 +17178,52 @@ - - - + - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - + + @@ -23613,13 +17250,9 @@ - - - + - - - + @@ -23652,51 +17285,42 @@ - - - - - - - - - @@ -23708,19 +17332,16 @@ - - - @@ -23735,9 +17356,7 @@ - - - + @@ -23759,16 +17378,13 @@ - - - @@ -23854,7 +17470,6 @@ - @@ -23864,39 +17479,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + @@ -23968,42 +17561,25 @@ - - - - - - - - - - - - - - - - - @@ -24013,28 +17589,18 @@ - - - - - - - - - - - + @@ -24056,9 +17622,7 @@ - - - + @@ -24067,11 +17631,8 @@ - - - + - @@ -24079,16 +17640,12 @@ - - - - + - @@ -24096,21 +17653,18 @@ - - - - + @@ -24119,11 +17673,9 @@ - - @@ -24168,28 +17720,22 @@ - - - - - - @@ -24217,7 +17763,6 @@ - @@ -24231,14 +17776,12 @@ - - @@ -24279,52 +17822,42 @@ - - - - - - - - - - @@ -24369,153 +17902,105 @@ - - - + - - - - - - - - - - + + + - - + - - - - - - - - + - - - - - - - - + - - - - - - + - - - - - - - - - - - - + + + + - - - - - - - - - - - - + @@ -24523,7 +18008,6 @@ - @@ -24531,7 +18015,6 @@ - @@ -24539,124 +18022,115 @@ - - - - + - - - - - - + + - + - + - + + - + - + - + - + - + - + - + - + - - - - - + - + - + - + + @@ -24674,7 +18148,6 @@ - @@ -24687,12 +18160,10 @@ - - @@ -24702,19 +18173,15 @@ - - - - - - + + + + - - @@ -24723,27 +18190,22 @@ - - - - - @@ -24751,12 +18213,10 @@ - - @@ -24776,19 +18236,16 @@ - - - @@ -24809,31 +18266,19 @@ - - - - - - - - - - - - @@ -24841,7 +18286,6 @@ - @@ -24852,196 +18296,132 @@ - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - @@ -25049,13 +18429,8 @@ - - - - - @@ -25063,65 +18438,38 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - @@ -25190,14 +18538,9 @@ - - - - - - + + - @@ -25211,9 +18554,6 @@ - - - @@ -25221,13 +18561,8 @@ - - - - - @@ -25239,21 +18574,13 @@ - - - - - - - - @@ -25261,10 +18588,6 @@ - - - - @@ -25280,9 +18603,6 @@ - - - @@ -25298,13 +18618,8 @@ - - - - - @@ -25317,9 +18632,6 @@ - - - @@ -25335,9 +18647,6 @@ - - - @@ -25351,9 +18660,6 @@ - - - @@ -25367,29 +18673,19 @@ - - - - - - - + - - - - @@ -25397,22 +18693,14 @@ - - - - - + - - - - @@ -25420,13 +18708,8 @@ - - - - - @@ -25435,12 +18718,10 @@ - - @@ -25448,13 +18729,9 @@ - - - - - + @@ -25464,10 +18741,6 @@ - - - - @@ -25476,16 +18749,11 @@ - - - - - @@ -25502,26 +18770,17 @@ - - - - - - - - - @@ -25547,25 +18806,15 @@ - - - + - - - - - - + + - - - + - - - + @@ -25573,9 +18822,6 @@ - - - @@ -25584,52 +18830,25 @@ - - - - - - - - - - - - + + + - - - + - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - @@ -25704,18 +18923,11 @@ - - - - - + + - - - - @@ -25728,24 +18940,15 @@ - - - + - - - - - - - - + @@ -25754,16 +18957,10 @@ - - - + - - - - @@ -25796,56 +18993,36 @@ - - - - - - - - - - - - - - - - - - - - @@ -25871,11 +19048,9 @@ - - @@ -25885,7 +19060,6 @@ - @@ -25910,107 +19084,82 @@ - - - + - - - - + - - - - - - - - - - - - - - - - - - - - @@ -26018,45 +19167,32 @@ - - - - - - - - - - - - - @@ -26066,19 +19202,15 @@ - - - - @@ -26091,12 +19223,10 @@ - - @@ -26113,7 +19243,6 @@ - @@ -26123,11 +19252,9 @@ - - @@ -26136,38 +19263,29 @@ - - - - - - + - - - + - - @@ -26175,32 +19293,18 @@ - - - + - - - + - - - + - - - - - - - - - - - - + + + + @@ -26208,12 +19312,8 @@ - - - - - - + + @@ -26226,9 +19326,7 @@ - - - + @@ -26273,83 +19371,37 @@ - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - - + - - - + - - - - - - + + - - - + - - - - - - - - - - - - - - - - - - + + + + + + @@ -26367,40 +19419,30 @@ - - - - - - - - - + + - - - + - @@ -26432,44 +19474,29 @@ - - - + - - - + - - - + - - - + - - - - + - - - - - - + + @@ -26479,7 +19506,6 @@ - @@ -26490,17 +19516,14 @@ - - - @@ -26529,32 +19552,23 @@ - - - - + - - - - + - - - @@ -26562,14 +19576,8 @@ - - - - - - @@ -26577,71 +19585,51 @@ - - - - - - - - - - - - - - - - - - - - @@ -26650,12 +19638,10 @@ - - @@ -26678,161 +19664,121 @@ - - - + - - - - + - - - - - - + - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - @@ -26842,58 +19788,46 @@ - - - - - - - - - - - - @@ -26901,71 +19835,47 @@ - - - - - - - - - - - - - - - - - - - - - - - - @@ -26985,6 +19895,7 @@ + @@ -27009,55 +19920,42 @@ - - - - - - - - - - - - - @@ -27173,18 +20071,11 @@ - - + - - - - - - @@ -27196,32 +20087,21 @@ - - - - - - + - - - + + - - - - - @@ -27234,30 +20114,15 @@ - - - - - - - - - - - - - - - @@ -27270,30 +20135,15 @@ - - - - - - - - - - - - - - - @@ -27306,13 +20156,6 @@ - - - - - - - @@ -27338,7 +20181,6 @@ - @@ -27366,7 +20208,6 @@ - @@ -27374,7 +20215,6 @@ - @@ -27387,27 +20227,17 @@ - - - - - - - - - - @@ -27416,62 +20246,46 @@ - - - - - - - - - - - - - - - - @@ -27479,15 +20293,12 @@ - - - @@ -27516,23 +20327,12 @@ - - - - - - - - - - - @@ -27583,58 +20383,41 @@ - - - - + - - - - - - - - - - - - - - - - + + @@ -27656,92 +20439,55 @@ - - - + - - - - - - - - - - + - - - - + - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - @@ -27757,11 +20503,8 @@ - - - + - @@ -27776,29 +20519,17 @@ - - - - - - + + - - - + - - - + - - - + - - - + @@ -27807,122 +20538,72 @@ - - - + - - - + - - - + - - - + - - - - - - + - - - - - - - - - - - - - + + + + - - - - - - + + - - - + - - - - - - - + + - - - - + - - - - - + - - - - - - - + + - - - - + - - - + @@ -27932,7 +20613,6 @@ - @@ -27995,27 +20675,15 @@ - - - - - - + + - - - - - - + + - - - - - - + + @@ -28072,11 +20740,8 @@ - - - + - @@ -28087,30 +20752,21 @@ - + - - - - - - - - - + + + - - - + - @@ -28118,39 +20774,29 @@ - - - + - - - - + - - - - + - - @@ -28160,9 +20806,7 @@ - - - + @@ -28177,9 +20821,7 @@ - - - + @@ -28201,11 +20843,9 @@ - - @@ -28225,19 +20865,14 @@ - - - + - - - @@ -28245,48 +20880,38 @@ - - - - - - - - - - @@ -28297,103 +20922,81 @@ - - - - - - - - - - - - - - - - - - - - - - @@ -28406,40 +21009,31 @@ - - - - - - - - - @@ -28447,63 +21041,43 @@ - - - - - - - + - - - + - - - + - - - - - - + + - - - - - - + + - - @@ -28511,69 +21085,49 @@ - - - - - - - - - - - - - - - - - - - - - + @@ -28586,9 +21140,7 @@ - - - + @@ -28598,7 +21150,6 @@ - @@ -28607,7 +21158,7 @@ - + @@ -28619,12 +21170,10 @@ - - @@ -28831,8 +21380,7 @@ - - + @@ -28844,14 +21392,8 @@ - - - - - - @@ -28875,7 +21417,6 @@ - @@ -28888,30 +21429,19 @@ - - - - - - - - - - - @@ -28935,7 +21465,6 @@ - @@ -28968,16 +21497,11 @@ - - + - - - - @@ -28998,58 +21522,39 @@ - - - - - - - - - - - - - - - + - - - - - @@ -29066,14 +21571,8 @@ - - - - - - @@ -29086,28 +21585,17 @@ - - - - - - - + - - - - - @@ -29122,12 +21610,6 @@ - - - - - - @@ -29142,70 +21624,44 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + @@ -29215,115 +21671,73 @@ - - - - - - + + - - - + - - - - - - - - - - - - + + + + - - - + - - - - - - - - + + - - - - - - - - - - - + - - - - + - - - - + - - - + - - - + @@ -29332,51 +21746,25 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - + - - - + - - - + - - - + @@ -29394,12 +21782,8 @@ - - - - - - + + @@ -29417,56 +21801,36 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - + + - @@ -29475,16 +21839,10 @@ - - - + - - - - - - + + @@ -29500,15 +21858,10 @@ - - - + - - - + - @@ -29532,9 +21885,7 @@ - - - + @@ -29545,24 +21896,18 @@ - - - + - - - - - + @@ -29571,15 +21916,11 @@ - - - - + - @@ -29597,59 +21938,42 @@ - - - + - - - - - - - - - + - - - - + - - - + - - - + @@ -29664,75 +21988,59 @@ - - - - - - - - - - - - - - - - @@ -29740,17 +22048,11 @@ - - - - - - - + + - @@ -29762,7 +22064,6 @@ - @@ -29770,27 +22071,19 @@ - - - + - - - - + - - - - + @@ -29831,37 +22124,29 @@ - - - + - - - - - - @@ -29872,39 +22157,29 @@ - - - - - - - - - - + - @@ -30032,129 +22307,66 @@ - - - + - - - + - - - - - - - + + - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - + + + + - - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - + - - - - - - - - - - - + + + @@ -30219,8 +22431,8 @@ + - @@ -30231,9 +22443,7 @@ - - - + @@ -30253,15 +22463,11 @@ - - - + - - @@ -30371,34 +22577,22 @@ - - - - - - - - - - - - @@ -30407,7 +22601,6 @@ - @@ -30416,12 +22609,10 @@ - - @@ -30450,13 +22641,10 @@ - - - - + @@ -30464,47 +22652,36 @@ - - - - - - - - - - - - + @@ -30530,100 +22707,55 @@ - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - + - - - - - - - - - - - - - + + + + - - - - - - - - + + @@ -30665,20 +22797,15 @@ - - - - - + - @@ -30686,32 +22813,22 @@ - - - - + - - - - - - - @@ -30743,18 +22860,11 @@ - - + - - - - - - @@ -30776,22 +22886,17 @@ - - - - - - + @@ -30814,35 +22919,32 @@ - + - - + - - - + + - @@ -30850,15 +22952,8 @@ - - - - - - - @@ -30867,19 +22962,8 @@ - - - - - - - - - - - @@ -30891,42 +22975,27 @@ - - - - - - - - - - - - - - - @@ -30935,34 +23004,16 @@ - - - - - - - - - - - - - - - - - - - - + + + - @@ -30974,67 +23025,63 @@ - - - + - + - + + - + - + - + + - - - + - - @@ -31044,17 +23091,14 @@ - - - @@ -31062,20 +23106,18 @@ - - + - @@ -31161,6 +23203,7 @@ + @@ -31171,6 +23214,7 @@ + @@ -31194,28 +23238,21 @@ - - - - - - + + - - - @@ -31223,13 +23260,10 @@ - - - - + @@ -31237,18 +23271,10 @@ - - - - - - - - - - - - + + + + @@ -31261,9 +23287,7 @@ - - - + @@ -31276,31 +23300,22 @@ - - - - - - + + - - - + - - - + + - - - + @@ -31316,9 +23331,7 @@ - - - + @@ -31330,26 +23343,14 @@ - - - - - - - - - - - - + + + + - - - - - - + + @@ -31400,14 +23401,9 @@ - - - - - - + + - @@ -31419,43 +23415,20 @@ - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + @@ -31515,9 +23488,7 @@ - - - + @@ -31600,14 +23571,9 @@ - - - - - - + + - @@ -31760,59 +23726,29 @@ - - - + - - - - - - + + - - - - - - + + - - - - - - - - - - - - - - - + + + + + - - - + - - - + - - - + - - - + - - - + @@ -31833,9 +23769,7 @@ - - - + @@ -31862,12 +23796,10 @@ - - @@ -31911,52 +23843,30 @@ - - - - - - - - - - + - - - - - + - - - - - - - - - @@ -31971,14 +23881,8 @@ - - - - - - @@ -31992,53 +23896,31 @@ - - - - - - - - - - - - - - - - - - + - - - - - - - + + @@ -32050,26 +23932,14 @@ - - - - - - - - - - - - @@ -32084,14 +23954,8 @@ - - - - - - @@ -32103,12 +23967,6 @@ - - - - - - @@ -32143,20 +24001,16 @@ - - - - @@ -32170,7 +24024,6 @@ - @@ -32178,12 +24031,10 @@ - - @@ -32191,12 +24042,10 @@ - - @@ -32205,11 +24054,9 @@ - - @@ -32229,7 +24076,6 @@ - @@ -32248,7 +24094,7 @@ - + @@ -32272,15 +24118,8 @@ - - - - - - - @@ -32296,34 +24135,20 @@ - - - - - - - - - - - - - - + - @@ -32334,94 +24159,65 @@ - - - - - + - - - - + - - - - - - - - - - - - + - - - - - - - + - - - - - @@ -32434,12 +24230,8 @@ - - - - @@ -32451,12 +24243,6 @@ - - - - - - @@ -32499,84 +24285,59 @@ - - - + + - - - + - - - + - - - - - + - - - - + - - - - - + - - - - + - - - - + - - - + - @@ -32618,37 +24379,33 @@ - + + - - - - - + - + - @@ -32663,16 +24420,8 @@ - - - - - - - - @@ -32680,38 +24429,22 @@ - - - - - - - - - - - - - - - - @@ -32723,59 +24456,34 @@ - - - - - - - - - - - - - - - - - - - - - - - - - @@ -32800,23 +24508,18 @@ - - - - - @@ -32859,13 +24562,11 @@ - - @@ -32874,23 +24575,19 @@ - - - - @@ -32898,22 +24595,18 @@ - - - - @@ -32922,12 +24615,10 @@ - - @@ -32942,93 +24633,45 @@ - - - - - - - - + - + - - - - - - - - + - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - + + + - - - - - - - - - + + + - - - + - - - + @@ -33046,95 +24689,43 @@ - - - - - - - - - + + + - - - - - - - - - - - - + + + + - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - + + + - - - + - - - + - - - + - - - + - - - + @@ -33151,61 +24742,33 @@ - - - + - - - + - - - + - - - - - - - - - + + + - - - - - - - - - + + + - - - - - - + + - - - + - - - - - + @@ -33218,231 +24781,130 @@ - - - + - - - + - - - + - - - + - - - + - - - + - - - - - - - - - + + + - - - - + - - - + - - - - - - + + - - - - - - - - - - + + + - - - + - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - @@ -33450,22 +24912,14 @@ - - - - + - - - - - - - + + @@ -33476,118 +24930,72 @@ - - - - + - - - - + - - - - - + - - - - - - - - - - - - - - - - + + + + - - - + - - - + - - - - - - + + - - - - - - + + - - - - - - - - - - - - - - - - - - + + + + + + @@ -33595,60 +25003,39 @@ - - - - - - - - - - - - - - - - - - + - - - - @@ -33665,7 +25052,7 @@ - + @@ -33673,76 +25060,58 @@ - - - - - - - - + - - - - + - - - - - - - - - - + + @@ -33817,18 +25186,10 @@ - - - - - - - - - - - - + + + + @@ -33867,9 +25228,7 @@ - - - + @@ -33909,15 +25268,9 @@ - - - - - - - - - + + + @@ -34039,7 +25392,6 @@ - @@ -34063,158 +25415,98 @@ - - - + - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - + - - - - - - - + - - - - - - + - + - - - - - - - - - - - + - - - - - - - - + @@ -34226,55 +25518,32 @@ - - - - - - - - - - - - - + - - - - - - - - - - - @@ -34282,142 +25551,85 @@ - - - - - + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - @@ -34427,55 +25639,34 @@ - - - - - - - - - - - - - - - - - - - - - @@ -34483,13 +25674,6 @@ - - - - - - - @@ -34531,37 +25715,26 @@ - - - - - - - - - - - @@ -34576,15 +25749,8 @@ - - - - - - - @@ -34598,15 +25764,8 @@ - - - - - - - @@ -34614,16 +25773,8 @@ - - - - - - - - @@ -34638,51 +25789,32 @@ - - - - - - - - - - - - - - - - + + - - - - - + - @@ -34696,12 +25828,6 @@ - - - - - - @@ -34722,12 +25848,8 @@ - - - - - - + + @@ -34804,9 +25926,7 @@ - - - + @@ -34853,13 +25973,11 @@ - - @@ -34869,10 +25987,10 @@ + - @@ -34902,12 +26020,10 @@ - - @@ -34916,17 +26032,12 @@ - - - - - @@ -34936,23 +26047,17 @@ - - - - + - - - - + @@ -34968,53 +26073,27 @@ - - - + - - - + - - - + - - - + - - - + - - - - - - - - - - - - + + + + - - - + - - - - - - - - - + + + @@ -35063,6 +26142,7 @@ + @@ -35070,27 +26150,15 @@ - - - - - - + + - - - - - - - - @@ -35098,29 +26166,11 @@ - - - - - - - - - - - - - - - - - - @@ -35131,12 +26181,8 @@ - - - - - - + + @@ -35148,74 +26194,34 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - + - - - - - - + + - @@ -35228,150 +26234,96 @@ - - - + + - - - + - - - + - - - - - - + + - - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - + - - - - + - - - + - - - - + - - - + @@ -35557,39 +26509,28 @@ - - - - - - - - - - - + + - - @@ -35600,38 +26541,22 @@ - - - - - - - + + - - - + - - - - + - - - - - - - - - + + + @@ -35700,21 +26625,14 @@ - - - + - - - + - - - - + @@ -35735,30 +26653,16 @@ - - - - - - - - - - - - - - - - - - + + + + + + - - @@ -35773,7 +26677,6 @@ - @@ -35782,11 +26685,8 @@ - - - + - @@ -35850,12 +26750,8 @@ - - - - - - + + @@ -35944,55 +26840,31 @@ - - - - - - + + - - - - - - - - - - + + + - - - - - - - - - - - - - @@ -36005,65 +26877,44 @@ - - - - - - - - - + - - - - - - - - - - - - - @@ -36072,48 +26923,26 @@ - - - - - - - - - - - - - - - - - - - + + - - - - - @@ -36122,15 +26951,12 @@ - - - @@ -36144,284 +26970,175 @@ - - - - - - - - - - - - - - - - - - - + - - - - + - - - - + - - - - - - + + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + - - - + - - - + - - - - - - - + + - - - - - - - + - - - + + - - - + @@ -36490,41 +27207,31 @@ - - - - - - - + + + - - - - - - @@ -36532,15 +27239,12 @@ - - - - - - - + + + + @@ -37876,22 +28580,26 @@ + + + + @@ -38008,22 +28716,26 @@ + + + + @@ -38074,18 +28786,21 @@ + + + @@ -38128,21 +28843,25 @@ + + + + @@ -38171,185 +28890,109 @@ - - - - - - - - - - - - - - - - - + - - - + - - - - - - - - - - - - - - - + + + + + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - + - - - - + - - - - - - - - - - - - + + + + - - - + - @@ -38357,7 +29000,6 @@ - @@ -38384,38 +29026,20 @@ - - - - - - - - - - - - + + + + - - - + - - - + - - - + - - - - - - + + @@ -38442,31 +29066,20 @@ - - - - - - - - - + + + - - - + - - - @@ -38480,7 +29093,6 @@ - @@ -38498,21 +29110,16 @@ - - - - - @@ -38774,34 +29381,27 @@ - - - - - - - @@ -38906,136 +29506,101 @@ - - - + - - + - - - - - - + - - - - - + - - - - - - + - - - - - - - - - - - - - - - - - - + + + - - - @@ -39061,42 +29626,34 @@ - - - - - - - - @@ -39124,38 +29681,28 @@ - - - - - + - - - - - - - - + + + - @@ -39182,43 +29729,32 @@ - - - - - - - + + + - - - - + - - - - @@ -39227,12 +29763,8 @@ - - - - @@ -39243,31 +29775,22 @@ - - - - + - - - - - - @@ -39275,13 +29798,11 @@ - - @@ -39291,48 +29812,37 @@ - - - - - - - - - + - - - + - @@ -39342,16 +29852,13 @@ - - - @@ -39359,62 +29866,45 @@ - - - + - - - + - - - - + - - - + - - - + - - - - + - - - + - @@ -39430,26 +29920,13 @@ - - - - - - - - - + - - - - - @@ -39462,26 +29939,17 @@ - - - - - - - - - @@ -39497,14 +29965,8 @@ - - - - - - @@ -39518,25 +29980,16 @@ - - - - - - - - - @@ -39547,18 +30000,13 @@ - - - - - + - @@ -39572,76 +30020,50 @@ - - - - - - - - - - + - - - - - - - - - + + + - - + - - - - - - + - - - - - - + @@ -39661,7 +30083,6 @@ - @@ -39682,109 +30103,55 @@ - - - + - - - + - - - - - - + + - - - + - - - + - - - + - - - - - - + + - - - + - - - - - - + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - + - - - - - - - - - - - - - - - - - - - - - + + + + + + + @@ -39793,9 +30160,7 @@ - - - + @@ -39803,49 +30168,36 @@ - - - - - + - - - - - - - - - - + @@ -39891,26 +30243,16 @@ - - - - - - - - - - @@ -39923,16 +30265,8 @@ - - - - - - - - @@ -39946,31 +30280,15 @@ - - - - - - - - - - - - - - - - @@ -39983,16 +30301,8 @@ - - - - - - - - @@ -40006,31 +30316,15 @@ - - - - - - - - - - - - - - - - @@ -40043,16 +30337,8 @@ - - - - - - - - @@ -40066,31 +30352,15 @@ - - - - - - - - - - - - - - - - @@ -40103,16 +30373,8 @@ - - - - - - - - @@ -40126,31 +30388,15 @@ - - - - - - - - - - - - - - - - @@ -40163,16 +30409,8 @@ - - - - - - - - @@ -40186,31 +30424,15 @@ - - - - - - - - - - - - - - - - @@ -40223,16 +30445,8 @@ - - - - - - - - @@ -40246,16 +30460,8 @@ - - - - - - - - @@ -40263,16 +30469,8 @@ - - - - - - - - @@ -40287,16 +30485,8 @@ - - - - - - - - @@ -40312,16 +30502,8 @@ - - - - - - - - @@ -40329,16 +30511,8 @@ - - - - - - - - @@ -40353,16 +30527,8 @@ - - - - - - - - @@ -40378,38 +30544,24 @@ - - - - - - - - - + - + - - - - - - - + - + @@ -40417,20 +30569,14 @@ - - - - - - - + - + @@ -40438,98 +30584,52 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - + + - - - + - - - - + - @@ -40542,7 +30642,6 @@ - @@ -40568,16 +30667,11 @@ - - - - - @@ -40701,7 +30795,6 @@ - @@ -40744,24 +30837,15 @@ - - - - - - - - - @@ -40777,7 +30861,6 @@ - @@ -40785,44 +30868,34 @@ - - - + - - - - - - - - @@ -40834,13 +30907,9 @@ - - - - + - @@ -40924,9 +30993,7 @@ - - - + @@ -40947,63 +31014,50 @@ - - - - - - - - - - - - - @@ -41030,48 +31084,33 @@ - - - - - - - - - - - - - - - - + + + - - - + @@ -41100,7 +31139,6 @@ - @@ -41108,7 +31146,6 @@ - @@ -41118,52 +31155,37 @@ - - - - - - - - - - - - - - + + - - - + + - - - + @@ -41236,16 +31258,12 @@ - - - + - - - + @@ -41272,9 +31290,7 @@ - - - + @@ -41290,12 +31306,8 @@ - - - - - - + + @@ -41308,16 +31320,10 @@ - - - - - - + + - - - + @@ -41334,32 +31340,21 @@ - - - + - - - - - - - - - + + + - - - - + @@ -41368,14 +31363,10 @@ - - - + - - - + @@ -41561,7 +31552,6 @@ - @@ -41570,11 +31560,8 @@ - - - + - @@ -41651,7 +31638,6 @@ - @@ -41697,44 +31683,29 @@ - - - + - - - - - - - - - - - - - + + + + - - - - @@ -41746,9 +31717,7 @@ - - - + @@ -41756,12 +31725,10 @@ - - @@ -41771,56 +31738,37 @@ - - - - + - - - + - - - + - - - - - - - - - - - - @@ -41831,29 +31779,17 @@ - - - - - - - - + - - - - - @@ -41867,13 +31803,8 @@ - - - - - @@ -41885,58 +31816,31 @@ - - - - - + - - - - - - - - - - - - - - - - - - - - - - - @@ -41948,79 +31852,40 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -42028,17 +31893,8 @@ - - - - - - - - - @@ -42046,17 +31902,8 @@ - - - - - - - - - @@ -42064,37 +31911,18 @@ - - - - - - - - - - - - - - - + - - - - - @@ -42104,7 +31932,6 @@ - @@ -42127,59 +31954,46 @@ - - - - - - - - - - - - - @@ -42187,7 +32001,6 @@ - @@ -42202,34 +32015,24 @@ - - - - - - - - - - @@ -42241,65 +32044,46 @@ - - - + - - - - - - - - + - - - - - - - - + - - - @@ -42311,13 +32095,10 @@ - - - - + @@ -42325,12 +32106,8 @@ - - - - - - + + @@ -42338,16 +32115,6 @@ - - - - - - - - - - @@ -42356,26 +32123,14 @@ - - - - - - - - - - - - @@ -42386,15 +32141,12 @@ - - - @@ -42402,12 +32154,10 @@ - - @@ -42419,7 +32169,6 @@ - @@ -42433,14 +32182,13 @@ - - + @@ -42459,71 +32207,45 @@ - + - - - - - - - - - - - - + - - - - - - - + - - - - - - - + + - - - - @@ -42533,7 +32255,6 @@ - @@ -42544,7 +32265,6 @@ - @@ -42552,20 +32272,15 @@ - - - + - - + @@ -42573,15 +32288,10 @@ My sad story is told by few living humans but many dead warriors"/> - - - + - - - @@ -42593,19 +32303,14 @@ My sad story is told by few living humans but many dead warriors"/> - - - - - @@ -42687,21 +32392,16 @@ My sad story is told by few living humans but many dead warriors"/> - - - - - @@ -42710,18 +32410,12 @@ My sad story is told by few living humans but many dead warriors"/> - - - - - - @@ -42729,6 +32423,7 @@ My sad story is told by few living humans but many dead warriors"/> + @@ -42736,34 +32431,31 @@ My sad story is told by few living humans but many dead warriors"/> + + + - - - - + - - - - + @@ -42783,17 +32475,12 @@ My sad story is told by few living humans but many dead warriors"/> - - - + - - - - + @@ -42811,72 +32498,52 @@ My sad story is told by few living humans but many dead warriors"/> - - - - - - - - - - - + + + - - - + - - - - - - - - - - @@ -42884,57 +32551,49 @@ My sad story is told by few living humans but many dead warriors"/> + - + - - - - - - - - - @@ -42944,43 +32603,30 @@ My sad story is told by few living humans but many dead warriors"/> - - - + - - - + - - - - + - - - - - - - + @@ -42988,15 +32634,12 @@ My sad story is told by few living humans but many dead warriors"/> - - - @@ -43013,14 +32656,17 @@ My sad story is told by few living humans but many dead warriors"/> - + + + + @@ -43030,27 +32676,22 @@ My sad story is told by few living humans but many dead warriors"/> - - + - - - - @@ -43063,26 +32704,20 @@ My sad story is told by few living humans but many dead warriors"/> - - - - + - - - @@ -43091,40 +32726,31 @@ My sad story is told by few living humans but many dead warriors"/> - - - - - - + + - - - - + - - @@ -43136,15 +32762,12 @@ My sad story is told by few living humans but many dead warriors"/> - - - @@ -43182,27 +32805,22 @@ My sad story is told by few living humans but many dead warriors"/> - - - - - @@ -43211,20 +32829,15 @@ My sad story is told by few living humans but many dead warriors"/> - - - - + - - @@ -43271,13 +32884,9 @@ My sad story is told by few living humans but many dead warriors"/> - + - - - - @@ -43301,7 +32910,6 @@ My sad story is told by few living humans but many dead warriors"/> - @@ -43317,11 +32925,9 @@ My sad story is told by few living humans but many dead warriors"/> - - @@ -43334,11 +32940,9 @@ My sad story is told by few living humans but many dead warriors"/> - - @@ -43346,6 +32950,7 @@ My sad story is told by few living humans but many dead warriors"/> + @@ -43360,6 +32965,7 @@ My sad story is told by few living humans but many dead warriors"/> + @@ -43384,14 +32990,12 @@ My sad story is told by few living humans but many dead warriors"/> - + - - - + @@ -43414,40 +33018,28 @@ My sad story is told by few living humans but many dead warriors"/> - - - + - - + - - - - - - - - @@ -43472,12 +33064,10 @@ Awarded by TibiaMagazine.com.ve"/> - - @@ -43487,47 +33077,40 @@ Awarded by TibiaMagazine.com.ve"/> - - - + - - - - - @@ -43552,20 +33135,13 @@ Awarded by TibiaMagazine.com.ve"/> - - + - - - - - - @@ -43683,16 +33259,13 @@ Awarded by TibiaMagazine.com.ve"/> - - - @@ -43721,6 +33294,7 @@ Awarded by TibiaMagazine.com.ve"/> + @@ -43774,57 +33348,46 @@ Awarded by TibiaMagazine.com.ve"/> - - - - - - - - - - - @@ -43834,44 +33397,28 @@ Awarded by TibiaMagazine.com.ve"/> - - - - - - - - - - - + - - - - - - @@ -43914,13 +33461,10 @@ Awarded by TibiaMagazine.com.ve"/> - - - - + @@ -43943,60 +33487,41 @@ Awarded by TibiaMagazine.com.ve"/> - - - - - - - - - - - - - + - - - - - - - - + @@ -44022,28 +33547,22 @@ Awarded by TibiaMagazine.com.ve"/> - - - - - - @@ -44051,7 +33570,6 @@ Awarded by TibiaMagazine.com.ve"/> - @@ -44079,21 +33597,25 @@ Awarded by TibiaMagazine.com.ve"/> + + + + @@ -44101,17 +33623,14 @@ Awarded by TibiaMagazine.com.ve"/> - - - @@ -44125,6 +33644,7 @@ Awarded by TibiaMagazine.com.ve"/> + @@ -44134,12 +33654,8 @@ Awarded by TibiaMagazine.com.ve"/> - - - - - + @@ -44149,12 +33665,8 @@ Awarded by TibiaMagazine.com.ve"/> - - - - - + @@ -44164,31 +33676,23 @@ Awarded by TibiaMagazine.com.ve"/> - - - - - + - + - - - - - + @@ -44198,29 +33702,22 @@ Awarded by TibiaMagazine.com.ve"/> - - - - - + - - + + - - - @@ -44303,8 +33800,7 @@ Awarded by TibiaMagazine.com.ve"/> - + @@ -44315,69 +33811,43 @@ Awarded by TibiaMisterios.com.br"/> - - - - + - - - + - - - + - - - - - - - - - - - - - - - - - - - @@ -44387,57 +33857,35 @@ Awarded by TibiaMisterios.com.br"/> - - - - - - - - - - - - - - - - - - - - - - @@ -44448,145 +33896,71 @@ Awarded by TibiaMisterios.com.br"/> - - - - - - - - - - - - - - + - - - - - - - + + - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - + + + + - - - - - - + + - - - + - - - + - - - + @@ -44616,281 +33990,154 @@ Awarded by TibiaMisterios.com.br"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - + - - - - - - - + - - - - - - - + - - - - - - - - - - - - - - + + + @@ -44903,73 +34150,45 @@ Awarded by TibiaMisterios.com.br"/> - - - + - - - + - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - + - - @@ -44978,61 +34197,47 @@ Awarded by TibiaMisterios.com.br"/> - - - - - - - - - + + - - - - - - - @@ -45041,25 +34246,24 @@ Awarded by TibiaMisterios.com.br"/> + + - - - + + - - @@ -45073,17 +34277,14 @@ Awarded by TibiaMisterios.com.br"/> - - - @@ -45095,20 +34296,16 @@ Awarded by TibiaMisterios.com.br"/> - - - - + - @@ -45117,20 +34314,15 @@ Awarded by TibiaMisterios.com.br"/> - - + - - - - + - @@ -45147,35 +34339,26 @@ Awarded by TibiaMisterios.com.br"/> - - - + - - - - - - - @@ -45188,12 +34371,8 @@ Awarded by TibiaMisterios.com.br"/> - - - - @@ -45206,65 +34385,47 @@ Awarded by TibiaMisterios.com.br"/> - - - - - - - - - - - - - - - - - - - + @@ -45285,14 +34446,9 @@ Awarded by TibiaMisterios.com.br"/> - - - - - @@ -45302,9 +34458,7 @@ Awarded by TibiaMisterios.com.br"/> - - - + @@ -45316,13 +34470,10 @@ Awarded by TibiaMisterios.com.br"/> - - - - + @@ -45334,11 +34485,6 @@ Awarded by TibiaMisterios.com.br"/> - - - - - @@ -45346,21 +34492,12 @@ Awarded by TibiaMisterios.com.br"/> - - - - - - - - - @@ -45373,46 +34510,28 @@ Awarded by TibiaMisterios.com.br"/> - - - - - - - - - - - - + - - - - - - - @@ -45424,30 +34543,19 @@ Awarded by TibiaMisterios.com.br"/> - - - - - - - + - - - - - - + @@ -45456,64 +34564,33 @@ Awarded by TibiaMisterios.com.br"/> - - - - - - - - - - + - + - - - - - - - - - - - + - - - - - - - - - - - - @@ -45529,22 +34606,13 @@ Awarded by TibiaMisterios.com.br"/> - - - - - - - - - @@ -45605,21 +34673,13 @@ Awarded by TibiaMisterios.com.br"/> - - - + - - - - - - - + + - @@ -45632,7 +34692,6 @@ Awarded by TibiaMisterios.com.br"/> - @@ -45648,7 +34707,6 @@ Awarded by TibiaMisterios.com.br"/> - @@ -45674,17 +34732,15 @@ Awarded by TibiaMisterios.com.br"/> - + - - @@ -45699,16 +34755,8 @@ Awarded by TibiaMisterios.com.br"/> - - - - - - - - @@ -45723,22 +34771,13 @@ Awarded by TibiaMisterios.com.br"/> - - - - - - - - - - - + + @@ -45748,115 +34787,65 @@ Awarded by TibiaMisterios.com.br"/> - - - - - - + + - - - + - - - - + - - + - - - - + - - - - - - - - - + + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + @@ -45877,9 +34866,7 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - + @@ -45903,7 +34890,6 @@ hands of its owner. Granted by TibiaRoyal.com"/> - @@ -45943,17 +34929,14 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - @@ -45997,83 +34980,67 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - + - - - - - - - - - - - - - @@ -46088,7 +35055,6 @@ hands of its owner. Granted by TibiaRoyal.com"/> - @@ -46102,83 +35068,69 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - - - - - @@ -46192,57 +35144,46 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - - @@ -46257,17 +35198,14 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - @@ -46280,48 +35218,39 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - @@ -46330,11 +35259,6 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - @@ -46351,14 +35275,8 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - @@ -46367,29 +35285,20 @@ hands of its owner. Granted by TibiaRoyal.com"/> - + - + - - - - - - - - - @@ -46414,100 +35323,79 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - - - - - - - - - - - - @@ -46515,90 +35403,69 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - - - - - - - - + - - - - - - + @@ -46607,11 +35474,6 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - @@ -46624,53 +35486,33 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - - + - - - - - - - - - - - + @@ -46679,22 +35521,12 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - @@ -46707,36 +35539,26 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - @@ -46744,36 +35566,20 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - - - - - - - @@ -46850,19 +35656,19 @@ hands of its owner. Granted by TibiaRoyal.com"/> - + - - + + - + @@ -46870,12 +35676,10 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - @@ -46888,12 +35692,10 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - @@ -46902,27 +35704,22 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - + - - @@ -46932,192 +35729,155 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - + - - @@ -47126,65 +35886,51 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - + - - - - - - - - + + + + - - - - - - @@ -47229,76 +35975,49 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - + - - - - - - - - - - - + + + - - - - - - + + - - - + - - - + + - - - - - - + + - - - + - - - + - - - + @@ -47351,22 +36070,19 @@ hands of its owner. Granted by TibiaRoyal.com"/> - + - - - + + - - - - + + @@ -47377,9 +36093,7 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - + @@ -47399,230 +36113,168 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -47630,85 +36282,45 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - + + + + - - - - - - - - - - - - - + + + + @@ -47746,45 +36358,33 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - + + - + - - - - - + - - - - - - - - + + + - - - + @@ -47799,16 +36399,12 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - + - - - + + - @@ -47822,35 +36418,28 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - - - - - + + + + + + + + + - - @@ -47869,7 +36458,6 @@ hands of its owner. Granted by TibiaRoyal.com"/> - @@ -47882,12 +36470,10 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - @@ -47897,79 +36483,61 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - - - - - - - - - @@ -47997,51 +36565,35 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - - - - - - - + - @@ -48118,7 +36670,6 @@ hands of its owner. Granted by TibiaRoyal.com"/> - @@ -48162,45 +36713,34 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - + + - + - - - - + @@ -48231,32 +36771,31 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - + + - + - + - + - + @@ -48324,15 +36863,12 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - + - @@ -48340,98 +36876,80 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - - - - - - - - - - @@ -48444,11 +36962,9 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - @@ -48458,62 +36974,42 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - + - - - - - - - - - - - - - - - - - + + - - - @@ -48521,14 +37017,12 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - @@ -48536,16 +37030,12 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - + @@ -48558,24 +37048,15 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - + - - - + - - - - - - - + + @@ -48604,7 +37085,6 @@ hands of its owner. Granted by TibiaRoyal.com"/> - @@ -48612,12 +37092,8 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - + + @@ -48625,20 +37101,14 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - + - - - - + @@ -48654,47 +37124,25 @@ hands of its owner. Granted by TibiaRoyal.com"/> - - - - - - - - - + + + - - - + - - - + - - - + - - - + - - - + - - - - - - + + - - + @@ -48704,87 +37152,62 @@ TibiaTome.com"/> - - - - - - - - - - - - + + + + - - - + - - - - - - - - - - - - - - - - + - + @@ -48796,38 +37219,21 @@ TibiaTome.com"/> - - - - - - - - + + - - - - - - - - - - - @@ -48838,14 +37244,13 @@ TibiaTome.com"/> + - - - + @@ -48853,7 +37258,6 @@ TibiaTome.com"/> - @@ -48865,25 +37269,21 @@ TibiaTome.com"/> - - - - @@ -48893,58 +37293,40 @@ TibiaTome.com"/> - - - - - - - - + - - - - - - - - - - + - - @@ -48953,17 +37335,14 @@ TibiaTome.com"/> - - - @@ -48972,13 +37351,10 @@ TibiaTome.com"/> - - - + - @@ -48995,7 +37371,6 @@ TibiaTome.com"/> - @@ -49003,31 +37378,15 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - @@ -49035,23 +37394,13 @@ TibiaTome.com"/> - + - - - - - - - - - - @@ -49079,62 +37428,43 @@ TibiaTome.com"/> - - - + - - - - - - + + - - - + - - - - - - - - - - - - + + - @@ -49359,40 +37689,33 @@ TibiaTome.com"/> - - - + - - - - - @@ -49400,28 +37723,24 @@ TibiaTome.com"/> - - - - @@ -49434,77 +37753,66 @@ TibiaTome.com"/> - - - - - - - - - - - @@ -49523,701 +37831,387 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -50230,830 +38224,518 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -51072,244 +38754,181 @@ TibiaTome.com"/> - - - - - - - - + - - - - - + - - - - - - - + - - - - - - - + - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -51318,7 +38937,6 @@ TibiaTome.com"/> - @@ -51327,24 +38945,25 @@ TibiaTome.com"/> - - - - + + + + + @@ -51353,20 +38972,15 @@ TibiaTome.com"/> - - - - + - - @@ -51387,190 +39001,140 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + @@ -51585,58 +39149,42 @@ TibiaTome.com"/> - - - - - - - + - - - - + + - - - - - - - - - - - + + + @@ -51649,14 +39197,11 @@ TibiaTome.com"/> - - - + - - - + + @@ -51667,44 +39212,41 @@ TibiaTome.com"/> - - + + + + - - - - - @@ -51712,26 +39254,19 @@ TibiaTome.com"/> - + - - - - - - - - + @@ -51740,39 +39275,25 @@ TibiaTome.com"/> - - - - - - - - + - - - - - - - - + @@ -51781,39 +39302,25 @@ TibiaTome.com"/> - - - - - - - - + - + - - - - - - - - + @@ -51822,21 +39329,14 @@ TibiaTome.com"/> - - - - - - - - + - + @@ -51845,19 +39345,12 @@ TibiaTome.com"/> - - - - - - - - + @@ -51868,18 +39361,11 @@ TibiaTome.com"/> - - - - - - - - + @@ -51888,21 +39374,11 @@ TibiaTome.com"/> - - - - - - - - - - - + @@ -51911,70 +39387,42 @@ TibiaTome.com"/> - - - - - - - - - - - - - + - - - - - - - - - - - - - - + + + - - - + - - - - - + + @@ -51998,7 +39446,6 @@ TibiaTome.com"/> - @@ -52006,28 +39453,16 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - + + + + + - - @@ -52080,44 +39515,28 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - @@ -52169,9 +39588,8 @@ TibiaTome.com"/> - - - + + @@ -52240,14 +39658,9 @@ TibiaTome.com"/> - - - - - @@ -52255,71 +39668,56 @@ TibiaTome.com"/> - + - - - - - - - - - - - - - - - @@ -52327,11 +39725,9 @@ TibiaTome.com"/> - - @@ -52361,26 +39757,20 @@ TibiaTome.com"/> - - - + - - - - @@ -52389,12 +39779,10 @@ TibiaTome.com"/> - - @@ -52407,7 +39795,6 @@ TibiaTome.com"/> - @@ -52507,25 +39894,18 @@ TibiaTome.com"/> - - - + + - - - - - - @@ -52539,27 +39919,15 @@ TibiaTome.com"/> - - - - - - - + - - - - - - @@ -52576,18 +39944,12 @@ TibiaTome.com"/> - - - - - - - + @@ -52598,25 +39960,13 @@ TibiaTome.com"/> - - - - - - - - - - - - @@ -52624,50 +39974,41 @@ TibiaTome.com"/> - - - - - - - - - @@ -52698,41 +40039,33 @@ TibiaTome.com"/> - - - - - - - - @@ -52744,41 +40077,34 @@ TibiaTome.com"/> - - - - - - - @@ -52792,26 +40118,21 @@ TibiaTome.com"/> - - - - - @@ -52835,7 +40156,6 @@ TibiaTome.com"/> - @@ -52903,9 +40223,7 @@ TibiaTome.com"/> - - - + @@ -52913,9 +40231,7 @@ TibiaTome.com"/> - - - + @@ -52924,34 +40240,27 @@ TibiaTome.com"/> - - - - - + + - - - - @@ -52960,14 +40269,15 @@ TibiaTome.com"/> + + - @@ -52980,19 +40290,16 @@ TibiaTome.com"/> - - - @@ -53003,10 +40310,13 @@ TibiaTome.com"/> + + + @@ -53017,25 +40327,28 @@ TibiaTome.com"/> + + + + - - - + + - - - + + + @@ -53046,12 +40359,15 @@ TibiaTome.com"/> + + + @@ -53062,20 +40378,14 @@ TibiaTome.com"/> - - - - + - - - - + @@ -53116,15 +40426,9 @@ TibiaTome.com"/> - - - - - - - - - + + + @@ -53133,87 +40437,51 @@ TibiaTome.com"/> + - - - - - - - - - - - - - - - - - - - + + + + - - - - - - + - - - - - - - - - - - - - - - + + - - - - @@ -53234,40 +40502,30 @@ TibiaTome.com"/> - - - - - - + + - - - - - - + + + - - - - + + - @@ -53278,213 +40536,155 @@ TibiaTome.com"/> + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -53851,23 +41051,16 @@ TibiaTome.com"/> - - - - + - - - + - - - + @@ -53881,13 +41074,13 @@ TibiaTome.com"/> - + - + @@ -53902,13 +41095,13 @@ TibiaTome.com"/> - + - + @@ -53927,161 +41120,129 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - + - - - @@ -54091,23 +41252,16 @@ TibiaTome.com"/> - - + - - - - - - @@ -54123,18 +41277,12 @@ TibiaTome.com"/> - - - - - - - + @@ -54143,23 +41291,12 @@ TibiaTome.com"/> - - - - - - - - - - - - + @@ -54168,19 +41305,8 @@ TibiaTome.com"/> - - - - - - - - - - - @@ -54197,16 +41323,8 @@ TibiaTome.com"/> - - - - - - - - @@ -54220,14 +41338,8 @@ TibiaTome.com"/> - - - - - - @@ -54236,14 +41348,8 @@ TibiaTome.com"/> - - - - - - @@ -54258,14 +41364,8 @@ TibiaTome.com"/> - - - - - - @@ -54280,14 +41380,8 @@ TibiaTome.com"/> - - - - - - @@ -54302,16 +41396,8 @@ TibiaTome.com"/> - - - - - - - - @@ -54326,16 +41412,8 @@ TibiaTome.com"/> - - - - - - - - @@ -54350,13 +41428,6 @@ TibiaTome.com"/> - - - - - - - @@ -54421,18 +41492,15 @@ TibiaTome.com"/> - - - + + - - @@ -54569,17 +41637,14 @@ TibiaTome.com"/> - - - @@ -54715,7 +41780,6 @@ TibiaTome.com"/> - @@ -54723,11 +41787,9 @@ TibiaTome.com"/> - - @@ -54735,11 +41797,10 @@ TibiaTome.com"/> - - + @@ -54748,25 +41809,12 @@ TibiaTome.com"/> - - - - - - - - - - - - - - + @@ -54775,19 +41823,8 @@ TibiaTome.com"/> - - - - - - - - - - - @@ -54801,15 +41838,8 @@ TibiaTome.com"/> - - - - - - - @@ -54822,15 +41852,8 @@ TibiaTome.com"/> - - - - - - - @@ -54843,15 +41866,8 @@ TibiaTome.com"/> - - - - - - - @@ -54864,14 +41880,9 @@ TibiaTome.com"/> - - - - - - + @@ -54899,6 +41910,7 @@ TibiaTome.com"/> + @@ -54925,11 +41937,8 @@ TibiaTome.com"/> - - - + - @@ -54965,78 +41974,66 @@ TibiaTome.com"/> - - - - + - - - - - - - + + - - - - + + + + - + + - - - - - @@ -55050,93 +42047,76 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - - @@ -55156,24 +42136,25 @@ TibiaTome.com"/> + + + + - - - + + - - - + - - - + @@ -55190,9 +42171,7 @@ TibiaTome.com"/> - - - + @@ -55209,70 +42188,44 @@ TibiaTome.com"/> - - - - - - + + - - - - - - + + - - - + - - - + - - - - + - - - - - - - - - - - + - @@ -55288,11 +42241,11 @@ TibiaTome.com"/> - - - + + + @@ -55304,17 +42257,14 @@ TibiaTome.com"/> - - - + + - - - - + + @@ -55331,18 +42281,19 @@ TibiaTome.com"/> - + + @@ -55361,30 +42312,24 @@ TibiaTome.com"/> - - - - - - @@ -55392,61 +42337,51 @@ TibiaTome.com"/> + - + - - - + + - - - - - - - - - - @@ -55463,19 +42398,11 @@ TibiaTome.com"/> - - - - - - - - - + @@ -55485,17 +42412,9 @@ TibiaTome.com"/> - - - - - - - - @@ -55507,20 +42426,12 @@ TibiaTome.com"/> - - - - - - - - - + - + @@ -55531,14 +42442,8 @@ TibiaTome.com"/> - - - - - - @@ -55552,16 +42457,8 @@ TibiaTome.com"/> - - - - - - - - @@ -55575,18 +42472,10 @@ TibiaTome.com"/> - - - - - - - - - + @@ -55597,32 +42486,21 @@ TibiaTome.com"/> - - - - - - + - - - - - - - + @@ -55631,21 +42509,11 @@ TibiaTome.com"/> - - - - - - - - - - - + @@ -55656,14 +42524,8 @@ TibiaTome.com"/> - - - - - - @@ -55676,32 +42538,14 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - - - @@ -55718,17 +42562,11 @@ TibiaTome.com"/> - - - - - - - + @@ -55739,37 +42577,26 @@ TibiaTome.com"/> - - - - - - - - - + + - - - - @@ -55785,100 +42612,72 @@ TibiaTome.com"/> - - - - + - - - - + + - - - + - - - + + - - - - - + + - - - - - - - - - - - - - - - - - + + + + - - - + - - @@ -55887,9 +42686,9 @@ TibiaTome.com"/> + - @@ -55979,9 +42778,7 @@ TibiaTome.com"/> - - - + @@ -56025,45 +42822,39 @@ TibiaTome.com"/> + - - - - + - - - - @@ -56172,7 +42963,6 @@ TibiaTome.com"/> - @@ -56180,7 +42970,6 @@ TibiaTome.com"/> - @@ -56188,7 +42977,6 @@ TibiaTome.com"/> - @@ -56196,13 +42984,11 @@ TibiaTome.com"/> - - @@ -56253,6 +43039,7 @@ TibiaTome.com"/> + @@ -56301,7 +43088,6 @@ TibiaTome.com"/> - @@ -56368,9 +43154,7 @@ TibiaTome.com"/> - - - + @@ -56485,22 +43269,18 @@ TibiaTome.com"/> - - - - @@ -56547,15 +43327,11 @@ TibiaTome.com"/> - - - - @@ -56572,100 +43348,74 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -56676,140 +43426,109 @@ TibiaTome.com"/> + - - - - - - - - - - + - - - - - - + + - - - - - - - - - - - - - - - - - - - @@ -56825,37 +43544,24 @@ TibiaTome.com"/> - - - - - - - - - - - - - - + + + + - - - @@ -56900,19 +43606,15 @@ TibiaTome.com"/> - - - - @@ -56922,17 +43624,12 @@ TibiaTome.com"/> + - - - - - - @@ -56942,41 +43639,28 @@ TibiaTome.com"/> - - - - - - - - - - - - - @@ -57024,12 +43708,8 @@ TibiaTome.com"/> - - - - - - + + @@ -57056,62 +43736,47 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - @@ -57134,38 +43799,31 @@ TibiaTome.com"/> - - - + + + - - - - - - - @@ -57176,26 +43834,14 @@ TibiaTome.com"/> - - - - - - - - - - - - @@ -57206,11 +43852,6 @@ TibiaTome.com"/> - - - - - @@ -57236,65 +43877,52 @@ TibiaTome.com"/> - - - - - - - - - - - - - @@ -57310,30 +43938,16 @@ TibiaTome.com"/> - - - - - - - - - + - - - - - - @@ -57346,16 +43960,8 @@ TibiaTome.com"/> - - - - - - - - @@ -57368,16 +43974,8 @@ TibiaTome.com"/> - - - - - - - - @@ -57393,14 +43991,8 @@ TibiaTome.com"/> - - - - - - @@ -57413,19 +44005,11 @@ TibiaTome.com"/> - - - - - - - - - + @@ -57435,23 +44019,12 @@ TibiaTome.com"/> - - - - - - - - - - - - - + + @@ -57460,104 +44033,56 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - + + + - - - - - - - - - - - - + + + + - - - - - + - - - + - - - + - - - - - - - + + @@ -57565,35 +44090,25 @@ TibiaTome.com"/> - - - + - - - + - - - - - - + + - - - + @@ -57695,18 +44210,14 @@ TibiaTome.com"/> - - - + - + - - - + @@ -57726,41 +44237,30 @@ TibiaTome.com"/> - - - - - - - - - - - + + + - - - + - - - - - - + + + + + @@ -57772,56 +44272,42 @@ TibiaTome.com"/> - - - - - - + - - - + - - - + - - - + - - - + - - + @@ -57841,163 +44327,136 @@ TibiaTome.com"/> - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - + + @@ -58017,144 +44476,108 @@ TibiaTome.com"/> - - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - + + + @@ -58174,12 +44597,9 @@ TibiaTome.com"/> - + - - - @@ -58201,64 +44621,44 @@ TibiaTome.com"/> - - - - - - - - - + + + - - - - - - + + - - - + - - - - + - - - - - @@ -58266,27 +44666,23 @@ TibiaTome.com"/> - - - + - - @@ -58297,79 +44693,57 @@ TibiaTome.com"/> - - - - - - - - - + + + - - - - - - + - - + - - - - - - - - - - + - @@ -58381,12 +44755,10 @@ TibiaTome.com"/> - - @@ -58590,17 +44962,11 @@ TibiaTome.com"/> - - - - - - @@ -58615,56 +44981,41 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - + @@ -58686,27 +45037,21 @@ TibiaTome.com"/> - - - + - - - - @@ -58720,24 +45065,16 @@ TibiaTome.com"/> - - - - - - - - - - - + + + @@ -58756,24 +45093,19 @@ TibiaTome.com"/> - - - - - @@ -58854,9 +45186,7 @@ TibiaTome.com"/> - - - + @@ -58983,42 +45313,28 @@ TibiaTome.com"/> - - - - - - - + - - - - - - - - @@ -59045,15 +45361,12 @@ TibiaTome.com"/> - - - @@ -59061,7 +45374,6 @@ TibiaTome.com"/> - @@ -59077,17 +45389,11 @@ TibiaTome.com"/> - - - - - - - + @@ -59097,11 +45403,6 @@ TibiaTome.com"/> - - - - - @@ -59116,14 +45417,8 @@ TibiaTome.com"/> - - - - - - @@ -59137,20 +45432,13 @@ TibiaTome.com"/> - - - - - - - - + @@ -59162,35 +45450,21 @@ TibiaTome.com"/> - - - - - - - - - + - - - - - - - + @@ -59201,42 +45475,31 @@ TibiaTome.com"/> - - - - - - - - - - - @@ -59284,16 +45547,14 @@ TibiaTome.com"/> - - - + @@ -59303,21 +45564,12 @@ TibiaTome.com"/> - - - - - - - - - - + @@ -59325,50 +45577,32 @@ TibiaTome.com"/> - - - - - - + - - - - - - - - - - - - - @@ -59380,15 +45614,11 @@ TibiaTome.com"/> - - - - @@ -59396,10 +45626,6 @@ TibiaTome.com"/> - - - - @@ -59575,113 +45801,89 @@ TibiaTome.com"/> - - - + - - - - - - - - - - - - - - - - - - - - - - @@ -59693,30 +45895,27 @@ TibiaTome.com"/> - - - - + @@ -59739,7 +45938,6 @@ TibiaTome.com"/> - @@ -59747,7 +45945,6 @@ TibiaTome.com"/> - @@ -59756,20 +45953,15 @@ TibiaTome.com"/> - - - + - - - @@ -59781,13 +45973,11 @@ TibiaTome.com"/> - - @@ -59798,9 +45988,10 @@ TibiaTome.com"/> - + + @@ -59822,49 +46013,41 @@ TibiaTome.com"/> + - - - - - - - - - @@ -59885,31 +46068,25 @@ TibiaTome.com"/> - - - - - - @@ -59920,28 +46097,23 @@ TibiaTome.com"/> - - - - - @@ -59950,111 +46122,88 @@ TibiaTome.com"/> - - - - - - - - - - - + - - + - - - - - - - - - - - - @@ -60093,75 +46242,48 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -60206,7 +46328,6 @@ TibiaTome.com"/> - @@ -60214,7 +46335,6 @@ TibiaTome.com"/> - @@ -60239,253 +46359,203 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - + - - - - - - + @@ -60527,1029 +46597,29 @@ TibiaTome.com"/> - - - - - - + + - - - - - - + + - - - + - - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - @@ -61602,12 +46672,10 @@ TibiaTome.com"/> - - @@ -61617,30 +46685,22 @@ TibiaTome.com"/> - - - - - - - - @@ -61648,7 +46708,6 @@ TibiaTome.com"/> - @@ -61656,47 +46715,36 @@ TibiaTome.com"/> - - - - - - - - - - + - - @@ -61730,13 +46778,10 @@ TibiaTome.com"/> - - - + - @@ -61750,16 +46795,8 @@ TibiaTome.com"/> - - - - - - - - @@ -61768,66 +46805,40 @@ TibiaTome.com"/> - - - - - - - + - - - - - - + - - - - - - - - - - + - - - - - - @@ -61842,7 +46853,6 @@ TibiaTome.com"/> - @@ -61856,26 +46866,25 @@ TibiaTome.com"/> - - - - - - + - - + + + + + + + - @@ -61888,7 +46897,8 @@ TibiaTome.com"/> - + + @@ -61897,28 +46907,17 @@ TibiaTome.com"/> - - - - - - - - - - - + - @@ -61926,7 +46925,6 @@ TibiaTome.com"/> - @@ -61950,19 +46948,14 @@ TibiaTome.com"/> - - - - - - + @@ -61988,17 +46981,14 @@ TibiaTome.com"/> - - - @@ -62087,7 +47077,6 @@ TibiaTome.com"/> - @@ -62111,31 +47100,24 @@ TibiaTome.com"/> - - - - - - - @@ -62173,91 +47155,74 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - - @@ -62269,131 +47234,48 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - @@ -62405,7 +47287,6 @@ TibiaTome.com"/> - @@ -62415,79 +47296,54 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - + + + - - - - @@ -62614,36 +47470,29 @@ TibiaTome.com"/> - - - - - - - @@ -62664,68 +47513,57 @@ TibiaTome.com"/> - - - - - - - - - - - @@ -62825,70 +47663,55 @@ TibiaTome.com"/> - - - - - - - - - - - - - - + - - @@ -62896,29 +47719,26 @@ TibiaTome.com"/> - - - - + @@ -62927,13 +47747,9 @@ TibiaTome.com"/> - + - - - - @@ -62955,32 +47771,16 @@ TibiaTome.com"/> - - - - - - - - + - - - - - - - - - - + + - @@ -62992,25 +47792,18 @@ TibiaTome.com"/> - - - - - - + + - - - @@ -63020,35 +47813,27 @@ TibiaTome.com"/> - - - - - - - + - - @@ -63319,12 +48104,10 @@ TibiaTome.com"/> - - @@ -63405,11 +48188,9 @@ TibiaTome.com"/> - - @@ -63443,7 +48224,6 @@ TibiaTome.com"/> - @@ -63451,29 +48231,27 @@ TibiaTome.com"/> + - - - - + + - @@ -63493,23 +48271,18 @@ TibiaTome.com"/> - - - - - @@ -63663,27 +48436,19 @@ TibiaTome.com"/> - - - - - - - - @@ -63707,33 +48472,27 @@ TibiaTome.com"/> - - - - - - @@ -63755,7 +48514,6 @@ TibiaTome.com"/> - @@ -63775,51 +48533,42 @@ TibiaTome.com"/> - - - - - - - - - @@ -63839,56 +48588,46 @@ TibiaTome.com"/> - - - - - - - - - - @@ -63933,15 +48672,12 @@ TibiaTome.com"/> - - - @@ -63952,7 +48688,6 @@ TibiaTome.com"/> - @@ -63965,20 +48700,15 @@ TibiaTome.com"/> - - - - - - + - + @@ -63991,16 +48721,8 @@ TibiaTome.com"/> - - - - - - - - @@ -64016,21 +48738,13 @@ TibiaTome.com"/> - - - - - - - - - + - + @@ -64043,16 +48757,8 @@ TibiaTome.com"/> - - - - - - - - @@ -64060,7 +48766,7 @@ TibiaTome.com"/> - + @@ -64068,21 +48774,13 @@ TibiaTome.com"/> - - - - - - - - - + - + @@ -64095,16 +48793,8 @@ TibiaTome.com"/> - - - - - - - - @@ -64120,16 +48810,8 @@ TibiaTome.com"/> - - - - - - - - @@ -64148,16 +48830,8 @@ TibiaTome.com"/> - - - - - - - - @@ -64176,20 +48850,12 @@ TibiaTome.com"/> - - - - - - - - - + - + @@ -64199,26 +48865,15 @@ TibiaTome.com"/> - - - - - - - - - - - - - + + - + @@ -64227,43 +48882,20 @@ TibiaTome.com"/> - - - - - - - - - - - - + - - - - - - - + - - - - - - @@ -64277,16 +48909,10 @@ TibiaTome.com"/> - - - - - - - + @@ -64298,16 +48924,10 @@ TibiaTome.com"/> - - - - - - - + @@ -64318,11 +48938,6 @@ TibiaTome.com"/> - - - - - @@ -64330,35 +48945,24 @@ TibiaTome.com"/> - + - - - - - - + - - - - - - @@ -64373,14 +48977,8 @@ TibiaTome.com"/> - - - - - - @@ -64388,12 +48986,10 @@ TibiaTome.com"/> - - @@ -64402,15 +48998,11 @@ TibiaTome.com"/> - - - - + - @@ -64516,73 +49108,60 @@ TibiaTome.com"/> - - - - - - - - - - - - - - + @@ -64593,19 +49172,11 @@ TibiaTome.com"/> - - - - - - - - - + @@ -64615,48 +49186,26 @@ TibiaTome.com"/> - - - - - - - - - - - - - + + - + - - - - - - - - - - - - + - + @@ -64668,14 +49217,8 @@ TibiaTome.com"/> - - - - - - @@ -64690,14 +49233,8 @@ TibiaTome.com"/> - - - - - - @@ -64712,16 +49249,8 @@ TibiaTome.com"/> - - - - - - - - @@ -64736,14 +49265,8 @@ TibiaTome.com"/> - - - - - - @@ -64759,47 +49282,32 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - @@ -64807,11 +49315,9 @@ TibiaTome.com"/> - - @@ -64993,22 +49499,16 @@ TibiaTome.com"/> - - - - + - - - - + @@ -65023,15 +49523,11 @@ TibiaTome.com"/> - - - + - - - + @@ -65052,14 +49548,10 @@ TibiaTome.com"/> - - - - + - @@ -65073,16 +49565,8 @@ TibiaTome.com"/> - - - - - - - - @@ -65096,59 +49580,42 @@ TibiaTome.com"/> - - - - - - - - - - - - + - - - - - - @@ -65157,33 +49624,27 @@ TibiaTome.com"/> - - - - - - @@ -65192,46 +49653,37 @@ TibiaTome.com"/> - - - - - - - - - @@ -65252,208 +49704,89 @@ TibiaTome.com"/> - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - + - - + - - - - - - - - - + + + - - @@ -65461,12 +49794,10 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - @@ -65497,7 +49828,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - @@ -65534,37 +49864,31 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - @@ -65602,201 +49926,91 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - @@ -65805,11 +50019,9 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - @@ -65861,7 +50073,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - @@ -65892,21 +50103,17 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - @@ -65918,16 +50125,8 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - @@ -65941,39 +50140,19 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - - - - - - - - - - - - @@ -65990,50 +50169,30 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - + - - - - - - - + - + - - - - - - - + @@ -66041,23 +50200,12 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - - - - + @@ -66065,166 +50213,109 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - + - - - - - - @@ -66240,7 +50331,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - @@ -66267,418 +50357,110 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - @@ -66687,121 +50469,95 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -66810,141 +50566,40 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - + - @@ -66952,20 +50607,17 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - @@ -67015,7 +50667,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - @@ -67023,61 +50674,43 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - - - - - - - - - - - - + + + + + - - - @@ -67110,24 +50743,20 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - @@ -67137,22 +50766,15 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - + + - - - @@ -67161,17 +50783,14 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - @@ -67205,158 +50824,127 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -67366,21 +50954,14 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - @@ -67388,16 +50969,8 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - @@ -67405,7 +50978,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - @@ -67413,23 +50985,14 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - @@ -67437,16 +51000,8 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - @@ -67454,7 +51009,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - @@ -67462,22 +51016,13 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - @@ -67486,23 +51031,14 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - @@ -67511,16 +51047,8 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - @@ -67533,18 +51061,11 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - @@ -67557,21 +51078,12 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - @@ -67584,100 +51096,49 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - @@ -67687,17 +51148,10 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - @@ -67707,20 +51161,11 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - - + @@ -67731,20 +51176,11 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - - + @@ -67755,19 +51191,12 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - + @@ -67778,26 +51207,13 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - - - - - - + @@ -67808,17 +51224,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - - - @@ -67954,7 +51359,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - @@ -67963,14 +51367,11 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - + - @@ -67997,277 +51398,225 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - @@ -68289,66 +51638,62 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - @@ -68356,7 +51701,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - @@ -68376,90 +51720,81 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - - - - - - - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + @@ -68484,192 +51819,190 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + @@ -68692,7 +52025,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - @@ -68703,7 +52035,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - @@ -68724,7 +52055,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - @@ -68745,13 +52075,11 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - @@ -68776,7 +52104,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - @@ -68789,90 +52116,83 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - @@ -68880,150 +52200,126 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/> - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - - - + - + - + - + - - - - - - - - - - - - - - - @@ -69039,135 +52335,36 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - @@ -69192,12 +52389,10 @@ Granted by TibiaGoals.com"/> - - @@ -69206,31 +52401,26 @@ Granted by TibiaGoals.com"/> - - - - - @@ -69249,123 +52439,93 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - - - - - - - + + + + - - - - - + - - - + - - - - - - - - - - - - @@ -69380,141 +52540,41 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + @@ -69546,69 +52606,32 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + @@ -69624,113 +52647,65 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - - + @@ -69739,7 +52714,7 @@ Granted by TibiaGoals.com"/> - + @@ -69753,11 +52728,10 @@ Granted by TibiaGoals.com"/> - + - @@ -69778,241 +52752,187 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -70022,8 +52942,8 @@ Granted by TibiaGoals.com"/> - - + + @@ -70036,109 +52956,83 @@ Granted by TibiaGoals.com"/> - + - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -70166,7 +53060,6 @@ Granted by TibiaGoals.com"/> - @@ -70179,163 +53072,130 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -70346,62 +53206,53 @@ Granted by TibiaGoals.com"/> - + - - + - - + - + - - + - - - - + - - - - + @@ -70421,53 +53272,47 @@ Granted by TibiaGoals.com"/> - - + - + - + - + - + - - + - - + - - + - - + - - + @@ -70575,22 +53420,16 @@ Granted by TibiaGoals.com"/> - - - - - - @@ -70602,13 +53441,9 @@ Granted by TibiaGoals.com"/> - - - - - + @@ -70619,26 +53454,15 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - - @@ -70647,15 +53471,13 @@ Granted by TibiaGoals.com"/> - + - - - + @@ -70672,50 +53494,38 @@ Granted by TibiaGoals.com"/> - + - - - - - - - - - + + + - - + - - + - - + - - + - - + - - + @@ -70723,269 +53533,114 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + - - + - - - - - - - - - - - + + + - - + + - - + + - - - - - + - - - + @@ -71026,48 +53681,29 @@ Granted by TibiaGoals.com"/> - - - - - - + + - - - + - - - + - - - + - - - - - - + + - - - - + - - - + @@ -71077,104 +53713,61 @@ Granted by TibiaGoals.com"/> - - - + - - - + - - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - + + + + - - - - - - - - - - - - + + + - - @@ -71192,52 +53785,43 @@ Granted by TibiaGoals.com"/> - + - + - + - + - - - - + - - - - - - + + - - - + @@ -71250,12 +53834,9 @@ Granted by TibiaGoals.com"/> - - - - + @@ -71263,60 +53844,41 @@ Granted by TibiaGoals.com"/> - - - + - - - - - - + + - + - - - + - - - + - - - - - - - - + - - - + @@ -71325,9 +53887,7 @@ Granted by TibiaGoals.com"/> - - - + @@ -71353,12 +53913,11 @@ Granted by TibiaGoals.com"/> - - + @@ -71370,20 +53929,14 @@ Granted by TibiaGoals.com"/> - - - - - - - + @@ -71393,16 +53946,9 @@ Granted by TibiaGoals.com"/> - - - - - - - @@ -71422,32 +53968,20 @@ Granted by TibiaGoals.com"/> - - - - - - - + - - - - - - - - + + + - - - + + @@ -71455,20 +53989,14 @@ Granted by TibiaGoals.com"/> - - - - - - - - - + + + @@ -71479,18 +54007,12 @@ Granted by TibiaGoals.com"/> - - - - - - - - + + @@ -71498,20 +54020,14 @@ Granted by TibiaGoals.com"/> - - - - - - - - - + + + @@ -71522,14 +54038,8 @@ Granted by TibiaGoals.com"/> - - - - - - @@ -71543,16 +54053,8 @@ Granted by TibiaGoals.com"/> - - - - - - - - @@ -71566,16 +54068,8 @@ Granted by TibiaGoals.com"/> - - - - - - - - @@ -71589,16 +54083,8 @@ Granted by TibiaGoals.com"/> - - - - - - - - @@ -71606,20 +54092,14 @@ Granted by TibiaGoals.com"/> - - - - - - - + @@ -71630,29 +54110,14 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - + - - - - - - @@ -71661,19 +54126,13 @@ Granted by TibiaGoals.com"/> - - - - - - - - + + @@ -71682,26 +54141,14 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - - - - - - + + + @@ -71709,23 +54156,11 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - - - - + @@ -71735,16 +54170,10 @@ Granted by TibiaGoals.com"/> - - - - - - - + @@ -71756,54 +54185,28 @@ Granted by TibiaGoals.com"/> - - - - - - - + - - - - - - - + - - - - - - - - - - - - + + + + - - - - - - @@ -71813,391 +54216,295 @@ Granted by TibiaGoals.com"/> - - - + > + + - - - - - - - + - + - - - - - - - - - - + + + + - - - - - - - - - - + + - - - + > + + - - - - - - - - + + - - - - - - - - - - + + + + - - - - - - - + - - - - + + + + - - - + > + + - - - - - - - - - + + + - - - - - - - - - - - - - - - + + + + - - - - + + + - - + + - - - - - - - - + + - - - - - - - - + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + - - - - - - - - + - - - - - - - - - + + + + - - - - + > + - - - - - - - - - - - - @@ -72212,352 +54519,346 @@ Granted by TibiaGoals.com"/> - - - + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - - - - - - - + + + + + + @@ -72565,29 +54866,29 @@ Granted by TibiaGoals.com"/> - + - + - - + + - - - + + + - - - - + + + + - - - - + + + + @@ -72597,113 +54898,89 @@ Granted by TibiaGoals.com"/> - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - + - - - - - - - - + @@ -72717,534 +54994,312 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - + + - - - + + + - - - - + + + + - - - - + + + + - - - + + - - - + - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + - - - - - - + - - - - - - - - - - + + + - - - - - - - - - + + + - - - - - - + + - + - - - + @@ -73268,9 +55323,7 @@ Granted by TibiaGoals.com"/> - - - + @@ -73282,179 +55335,138 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - + - - - - - - - - - + - - @@ -73467,19 +55479,16 @@ Granted by TibiaGoals.com"/> - - - - - - - - + + + + + @@ -73493,12 +55502,10 @@ Granted by TibiaGoals.com"/> - - @@ -73506,241 +55513,94 @@ Granted by TibiaGoals.com"/> - - - - - + + - - - - + + - - - - + + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -73748,1724 +55608,57 @@ Granted by TibiaGoals.com"/> - - - - - - - - - - - + + - - - - + + - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -