From 165379c0b8062a010d3eb4981c74155f7dc73d0e Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Fri, 10 Apr 2020 02:19:19 -0700 Subject: [PATCH] storage --- code/__DEFINES/storage.dm | 17 ++++++-- code/_onclick/hud/screen_objects/storage.dm | 46 ++++++++++++-------- code/datums/components/storage/storage.dm | 45 ++++++++++++------- icons/mob/screen_gen.dmi | Bin 119011 -> 119019 bytes 4 files changed, 71 insertions(+), 37 deletions(-) diff --git a/code/__DEFINES/storage.dm b/code/__DEFINES/storage.dm index 3ec3e06961..bdcb638666 100644 --- a/code/__DEFINES/storage.dm +++ b/code/__DEFINES/storage.dm @@ -1,12 +1,17 @@ // storage_flags variable on /datum/component/storage -// Storage limits. These can be combined I guess but you really, really shouldn't (don't do it really) +// Storage limits. These can be combined (and usually are combined). /// Check max_items and contents.len when trying to insert #define STORAGE_LIMIT_MAX_ITEMS (1<<0) -/// Check w_class and max_combined_w_class, aka legacy behavior if you combine it with [STORAGE_LIMIT_MAX_ITEMS]. +/// Check max_combined_w_class. #define STORAGE_LIMIT_COMBINED_W_CLASS (1<<1) -/// Use max_w_class for maximum w_class but use the new volume system. Will automatically force rendering to use the new volume/baystation scaling UI so this is kind of incompatible with stuff like stack storage etc etc. +/// Use the new volume system. Will automatically force rendering to use the new volume/baystation scaling UI so this is kind of incompatible with stuff like stack storage etc etc. #define STORAGE_LIMIT_VOLUME (1<<2) +/// Use max_w_class +#define STORAGE_LIMIT_MAX_W_CLASS (1<<3) + +#define STORAGE_FLAGS_LEGACY_DEFAULT (STORAGE_LIMIT_MAX_ITEMS | STORAGE_LIMIT_COMBINED_W_CLASS | STORAGE_LIMIT_MAX_W_CLASS) +#define STORAGE_FLAGS_VOLUME_DEFAULT (STORAGE_LIMIT_MAX_ITEMS | STORAGE_LIMIT_VOLUME | STORAGE_LIMIT_MAX_W_CLASS) //ITEM INVENTORY WEIGHT, FOR w_class /// Usually items smaller then a human hand, ex: Playing Cards, Lighter, Scalpel, Coins/Money @@ -28,7 +33,11 @@ #define AUTO_SCALE_STORAGE_VOLUME(w_class, max_combined_w_class) (AUTO_SCALE_VOLUME(w_class) * (max_combined_w_class / w_class)) // UI defines +/// Size of volumetric box icon +#define VOLUMETRIC_STORAGE_BOX_ICON_SIZE 32 +/// Size of EACH left/right border icon for volumetric boxes +#define VOLUMETRIC_STORAGE_BOX_BORDER_SIZE 1 /// Minimum pixels an item must have in volumetric scaled storage UI -#define MINIMUM_PIXELS_PER_ITEM 2 +#define MINIMUM_PIXELS_PER_ITEM 6 /// Maximum number of objects that will be allowed to be displayed using the volumetric display system. Arbitrary number to prevent server lockups. #define MAXIMUM_VOLUMETRIC_ITEMS 256 diff --git a/code/_onclick/hud/screen_objects/storage.dm b/code/_onclick/hud/screen_objects/storage.dm index bf560841bb..5b73d8721a 100644 --- a/code/_onclick/hud/screen_objects/storage.dm +++ b/code/_onclick/hud/screen_objects/storage.dm @@ -55,40 +55,52 @@ /obj/screen/storage/volumetric_box icon_state = "stored_continue" var/obj/item/our_item - var/obj/screen/storage/stored_left/left - var/obj/screen/storage/stored_right/right - -/obj/screen/storage/volumetric_box/Destroy() - QDEL_NULL(left) - QDEL_NULL(right) - our_item = null - return ..() /obj/screen/storage/volumetric_box/Initialize(mapload, new_master, our_item) src.our_item = our_item - left = new(null, src, our_item) - right = new(null, src, our_item) + return ..() + +/obj/screen/storage/volumetric_box/Destroy() + our_item = null return ..() /obj/screen/storage/volumetric_box/Click(location, control, params) return our_item.Click(location, control, params) -/obj/screen/storage/volumetric_box/proc/on_screen_objects() +/obj/screen/storage/volumetric_box/center + icon_state = "stored_continue" + var/obj/screen/storage/stored_left/left + var/obj/screen/storage/stored_right/right + +/obj/screen/storage/volumetric_box/center/Initialize(mapload, new_master, our_item) + left = new(null, src, our_item) + right = new(null, src, our_item) + return ..() + +/obj/screen/storage/volumetric_box/center/Destroy() + QDEL_NULL(lefT) + QDEL_NULL(right) + return ..() + +/obj/screen/storage/volumetric_box/center/proc/on_screen_objects() return list(src, left, right) -#define BOX_ICON_PIXELS 32 -/obj/screen/storage/volumetric_box/proc/set_pixel_size(pixels) +/** + * Sets the size of this box screen object and regenerates its left/right borders. This includes the actual border's size! + */ +/obj/screen/storage/volumetric_box/center/proc/set_pixel_size(pixels) cut_overlays() //our icon size is 32 pixels. - transform = matrix(pixels / BOX_ICON_PIXELS, 0, 0, 0, 1, 0) - left.pixel_x = -((BOX_ICON_PIXELS - pixels) * 0.5) - 4 - right.pixel_x = ((BOX_ICON_PIXELS - pixels) * 0.5) + 4 + transform = matrix((pixels - (VOLUMETRIC_STORAGE_BOX_BORDER_SIZE * 2)) / VOLUMETRIC_STORAGE_BOX_ICON_SIZE, 0, 0, 0, 1, 0) + left.pixel_x = -((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) - VOLUMETRIC_STORAGE_BOX_BORDER_SIZE + right.pixel_x = ((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) + VOLUMETRIC_STORAGE_BOX_BORDER_SIZE add_overlay(left) add_overlay(right) -#undef BOX_ICON_PIXELS /obj/screen/storage/stored_left icon_state = "stored_start" + appearance_flags = APPEARANCE_UI | KEEP_APART | RESET_TRANSFORM // Yes I know RESET_TRANSFORM is in APPEARANCE_UI but we're hard-asserting this incase someone changes it. /obj/screen/storage/stored_right icon_state = "stored_end" + appearance_flags = APPEARANCE_UI | KEEP_APART | RESET_TRANSFORM diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index 25646598d3..7cf820239c 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -22,7 +22,7 @@ var/locked = FALSE //when locked nothing can see inside or use it. /// Storage flags, including what kinds of limiters we use for how many items we can hold - var/storage_flags = STORAGE_LIMIT_VOLUME + var/storage_flags = STORAGE_FLAGS_VOLUME_DEFAULT /// Max w_class we can hold. Applies to [STORAGE_LIMIT_COMBINED_W_CLASS] and [STORAGE_LIMIT_VOLUME] var/max_w_class = WEIGHT_CLASS_SMALL /// Max combined w_class. Applies to [STORAGE_LIMIT_COMBINED_W_CLASS] @@ -496,10 +496,6 @@ if(M && !stop_messages) host.add_fingerprint(M) return FALSE - if(real_location.contents.len >= max_items) - if(!stop_messages) - to_chat(M, "[host] is full, make some space!") - return FALSE //Storage item is full if(length(can_hold)) if(!is_type_in_typecache(I, can_hold)) if(!stop_messages) @@ -509,17 +505,34 @@ if(!stop_messages) to_chat(M, "[host] cannot hold [I]!") return FALSE - if(I.w_class > max_w_class) - if(!stop_messages) - to_chat(M, "[I] is too big for [host]!") - return FALSE - var/sum_w_class = I.w_class - for(var/obj/item/_I in real_location) - sum_w_class += _I.w_class //Adds up the combined w_classes which will be in the storage item if the item is added to it. - if(sum_w_class > max_combined_w_class) - if(!stop_messages) - to_chat(M, "[I] won't fit in [host], make some space!") - return FALSE + // STORAGE LIMITS + if(storage_flags & STORAGE_LIMIT_MAX_ITEMS) + if(real_location.contents.len >= max_items) + if(!stop_messages) + to_chat(M, "[host] has too many things in it, make some space!") + return FALSE //Storage item is full + if(storage_flags & STORAGE_LIMIT_MAX_W_CLASS) + if(I.w_class > max_w_class) + if(!stop_messages) + to_chat(M, "[I] is too long for [host]!") + return FALSE + if(storage_flags & STORAGE_LIMIT_COMBINED_W_CLASS) + var/sum_w_class = I.w_class + for(var/obj/item/_I in real_location) + sum_w_class += _I.w_class //Adds up the combined w_classes which will be in the storage item if the item is added to it. + if(sum_w_class > max_combined_w_class) + if(!stop_messages) + to_chat(M, "[I] won't fit in [host], make some space!") + return FALSE + if(storage_flags & STORAGE_LIMIT_VOLUME) + var/sum_volume = I.get_w_volume() + for(var/obj/item/_I in real_location) + sum_volume += _I.get_w_volume() + if(sum_volume > get_max_volume()) + if(!stop_messages) + to_chat(M, "[I] is too spacious to fit in [host], make some space!") + return FALSE + ///////////////// if(isitem(host)) var/obj/item/IP = host var/datum/component/storage/STR_I = I.GetComponent(/datum/component/storage) diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi index d00d0b079c8b1ea8d1409111656a000ad6aca300..60c413c372a7e495568a68b51cdbab64048acd42 100644 GIT binary patch delta 6455 zcmZv92|SeR-}gNXs<9L&j@?02(p1QnMy0aFR3z)@D7%Ox%gjA;I+1K`wk)kg$dc?s zWy><6i6X|5iJ=+Gm@#JNes9is-uHR`&oiITJ)i6PUEkmJ+rHQDy6?%yV)Vyi#45zS zYA{g2@`kbl`S8e^BKeVN7^6E!FRU$-aq=iN+GkpPP?kp^Et&eL#9J;T5Jd&Jp<1m) zZtWMZ&O|$;J`?w5;bjM%dw%hW3_^luIOnby>8@(yv8>T)zyy6E>=a9EvWM0$m$S*2 z3O(l2HOe47ulo8#CredUF+PAg_7-GJrVXa=ZP=Sj+rF|h^m!~a9jmQTW{=iaz3FjP zJwKLR?$xedmXef|uAm{EZ7~HwQ0&)=xiZuYya&5GLS!wzzIVqrTDuRM~4?J zLTpc0B8Hn-ci`=_Kr$nxA)<`6wjwhj_W-H%ea#HUrYW~Yb#(q%-_Y*Sq45AJDVqI@ z6K8iD=ODdRQedBBvR!#)s+0PA;-t?O0W0I2G;^1q76O;nS4X^aKm>}i)!A&M)}yu@ z|JPc7W#?}^`u-A4&occuCfTYGjUjWs-vG^CJU|Zp4q{xHW$pU+0L45E@S7G(oG1z% zp)zdr5x%SQA50e~hoxSTk-p3^70$`V(563Vr6ZMxW%Ae4nJrjcGyEaw!MNmY?xT*0 z^G;35O;3G!UjM~MNS|XU3=XWK7$4&njOls^1-N3QnfWFAj(*M~Rwf_;*JkW0gEk3H z;9}l$ZDFfHv7`&$q1G?tMqjTR0RNswR_)DuHfbpD;0M z)+P+A33BAD#0AH*^n`J)5O!E0_E5hlq~4Pmi=J~Es6L^VQq@AT4DLxc&>A}a2gv0mR>(6Tzu$Tys)zoFh7&9y3? zERfhRlr5GU=&F%=^4mJ}qF%_{Pz{@JOw};Ew>fbWNQCnj zDrWkT$BlZ=PeB{Q%cktBN|+4h$fi8qz9+xq+OiU&64a5=FhZ!h`zb$;VCF>Ijf`Ijl=&_I`B(Z5l~ zvdZbN>ktZ{y9`hwkV-z>FYrEk2V=yIKV-O^`e1j%Iq2lUvKc~1SI4x$7jHxrmvrg6 z<7`;9cv;0kR6Ygz^hxlUb|-noHCv=_7J8A^@|hN>AYZkyCMXGeNuC)q(N_IN@~Fly z$?HtA=htcuH3Vp~jHMU~!&3+Mbuy{clDw0^AbnydNoDD3pPit z@nnM9TbnLlkp9SiifLyP4)2AZ(Q9t~bX9#B85x*vX-iaU z#9fcKGbLZwLZRtX+Y-Kt{A35;wyfl9cLg4iO=^46K=CE?2Gs-ZzUMmL-YMM5(s`|+E$7vCILTg_hNPkK&r`4PEQt$Y@@k2<1x!QhLma;v(I;lp1#z8(AmZcBsOH3@l~z157GCh1iRi(M>it0 z!FR2Op(*H!kpU81(pL{S>Mt_4zEb#I*7>zw)3?Uxh^<8Jp!a^efZzdLCOOJ&%Rw&m zevo@=@adDlm1O$E`_4l@Nm4lanZc(;22FG_X45Rlr{lUZ^?WQWre-O{p_6SAtMB_% zV!Xzo5BHa z2B2F1cNv5t9hl%k5ZvP8{2|v$wiiyWyi!uF6asng+_3Y( z`m(UZPYY%L!%b}KAf$SkRl8qLb*(NwCma~IS6Xf?5YvbSYbZWf{K1_o;c4FLR5P=T zVkwfb;9lBoLJft+@6szTOB`|*^IU-f9^gQdY2#LU=W#U&zRkGAR_mF%{P}AN& zeU#0!!s>S@MYg^D^gfTKa4?Fq|~GxP8Y@!hwH+0%SD=8o28 ztM+bkPxO^aVIcLT1y~ddzWP#Xp6)X@-}GmHGlsFhaf=uyGI_?)sF@sQTh_nK8QzFu zEGhC1>GK+dzru(3!_^TZKMH<^0}50hJR?p^i6dt~2Wq5Czu_9A9D8$2waZ9?I^KLR zc<;p1ZAwqucPM*#pa6##2EeU|vWKf}p%l!BS7X3Muyzr5Kkn8E4M*s8$Pd!aoLu45 zX?a9sc$B1hmJf1@GGh$*K%=3YVE+|d!8Mrcx|{N zNNSNA1!1sxm(sj1l&unK%yyR551{^4?Z4SL-r86n!FUKeRehW^-r8L4_Z;(*Od4Km zw${fOGCKQ0YjyX&Uia*;a4-;Iva}d5nnF|2Yyu;_cbRB-au(*rLZ^QWMhR~H^dZ$u z<aeF^(dQ)&Xtstg8#p?;W*B@;e3>!Ed&*;k?A6i*7THP{b0sn5J=m)!7$(oJjd_sYTuF+CR#Kpx2;QN= z>q{iTDmb>34AV9{_%hjyP#VwxYO!g-KNKoPehuu}NKv6f0ARurXtQ_`Zs^q01x%+w7&v!Uyxa4sN{n4ni^pZmoLu|Zr z13`Cz|BP*tbML`re&&xxJKE4itxce+nsdZ_IliR3zU_R|xi9Wvfw->qrUwE$9R`u+ zK8T6ke7H~C7=>Q1wnf(#L)IH2`0h;lE_>CR>+x%r)bC8Jv4)D06ytP{zRx0~I-K}U zCaA4WGh?LSoz-m8r}N$J|4J}b42|+e$k2N_%n71=mI84s!C``FbwBj;F{X7zfVPw9 zgkOVf`Ao{lBo1nUB5mY6Qt-h&G`4mrs>Ai)ZEyzrlmfRYT#JbMBZ7sS*<WKovrOuso++-oL?|KVK}mbXVT7TA@C!2bJ}YC@(^m$-_VEcMaGN_yHu822&>qC z7TDAjrR;(m!H=>p@qUnZ+lyeLF58m*&Ho#$C300I-+5 zSA;)M?Uvav{DqcRrIH_?L;N+?@O33!;XOjlk}^$z@7G06b*ra)Gkkf~!i=*N&7y$O z?7qQ4ZPeMW;aIJC(Py2_?>K(Xx9 z&D^1YaNbPPU|sM%7V}eQpGE_FhY|+S`54N$31xn-d}LQ{o;Vz)}bxCjcOEg#sBE`mKmSiTtcN@kw$zOn1} zk_->!n34eCY9cnf5qiOVGPd47NfucxU>X^*3C-oNe}?d+KT*dBEZj{wesc1Pn69~r zUZ3xt3&)Hu0|08o%HoKF>>0k(_;FJ93DG!NwJ@#xO+C&;R+^@#Cp}1hD9Tithqf(| zx+Ya|Jbh;?LPb2?Qjddv!d1O2JbNzvOe?|)(UbnD6>$oL`l(~rHb~gti&5aEpXS?J z3w`v55?rH0WP5c$Q+`@^OoUbM88>C$c-!{|h|xg(EeudbjO@c<0s6_b_%-&Ct6n0#z;nJ8ylN*vI4EIDCcLVYkYJyLAhAeL{4|WmGF05Fie-Q7=GBux%}$(;1UszHNDF|A^s5e-A(Xk zXtF5e!iUIvDA4OKE<}wIv{ZcjtJRet?uc-Pmik zO331F#Pnu1owh~bXe*uS$IFcaDY?k_iyU6D3NJAgNComsEdd}u4lAuDeF`~&G=n1J z!0pyT7EfY*ALY{y1vATz!h7m(O_5n1p-BiFcW&;`C;Xz~bhQzny8L12!Pft_kD7?a zHp`1TOhfqub9L8PQl}+S`s)_nsT1m{9WK=1+gd`M=PapZF$?6|@%JAfGbUFjRD<#E z*3zEIv_w(?D|{Cs^6MnR3U&!7+%NI5>rX93h5PA71kJB~`3)ZyHVej;Hp6QGR^wV; z28e`5`Tbk$ftZDqwTV1dYsBF}?DJ>@EOyHm>4-f?nykFUXjoTB1&k&V8PO9If5vrq zTGOrooOBa|E-~uh8PQ)2QCQ~VKDLhhcoKy@_2~w@H`cxz_aTDmBpipN!heVYN| zx5u!@SOmIOA>(*6fIWcYRpwql={6-kqBv^hW1LN-2gVWGn0N>1`c0M zUD7qgO#=ZC6+pjvla{@fz@w#BHhzIzr!XeNh;;I*KLLkrFp)s3JrCwXpVE!jnltWn zW>A#RYGz231Z^MPA&U@((`fKc9R7z(sd^1BY`)znW981Way7TYW;m%i5V4uh&wDT} zX@Emtk6B`n+Kn#S|MXaq-6sg}O9{dsB;W3k19d8{r$>)_)W`v~eL{bI3lJH@p#%1( ziVmCP?uE}NdRU3vkSE<{2nnKHa0QYd!;*2c*MXvAGTU29dA_dd%fvHm}?%wsaraWeW zecy=S=Y;^CfNs@ls}p(8MP7EwsI+J{ahmA4Mm3X(V8h(OonhSvWPokk>>D(u`S%YI zrk3`a?qq+6F6mwXfM2!oY?q)>^z9CtORWliZM+b9!wR9k8^Q(M#E}+`-C*q2RAJ!u z^phc1%6>nD{}VVUI1AVWB+)$t9uY$w)Dc@wvlYPjTR% zk%X_1`Fhj$&=5XFUe_-!HN59O}AMja;t|C$f z{+7u02r(ACvaMHAF;9Z4SZE+2=-ToTzuqTQBhrw6>5RJIM_*qUK$Qx8l2AO@7(xfX zB+(v;dmtP$V&m5`3oD+H19yy=Vt1^crC*ps3)TUm%n#9{6g#ZxwYeBai;JO)9}$Bs z+7C&py>~idIERZ4YdpqOPSajs$eIZAs13d2gNE3LrV+p5<2&lYkClzq>P0j!%zw@$ zVBGu#dum82RTIC`^L*4yr2!BKXWykO?(C`yr{BPg)#}lhc52dmLQM#*_t8>x$L<-z zYNTid93%BUx(VlvvdbxXW*w~TFur#BW^~7&&%dLwj<8X;;!~*PfNsDckv?mx_fJO& zDLJTXRC?O1gk)qr1y<$A5Yc!XDQ}G7CqSkO$jy#ax1hH_E}umWi)FJ56KE?rK(t9ZLGwA?NjmjrUvmjpQ%^7Q(GT=d$gO1Tf-R z_rlg63G4=#1_y-0oH|t~1O6}Hv7c^Xr?y(xA(Ae z+6sI|{-*{UO1@SGqEL2_65$OHxo`}`to$e!T}KYVVO*u+ydN9o0Jm*e71RSL6Ls8P zak$^YX~h0-@e{K=Me|+UoW?Q{z-%HC0Q_&v`n~zj3Seda|LmKe!v4?9!>aN`|10iz zA5owXz240WHy0I9&fH|2-2Us2#0S?%=8iCN&Hp3cfWc$RfN8|Eq*2p$OM{}X_wG4K zzH&8OE~2kl>ipVZ$a-(i+9YOOsW%Y!UL%|4K5GBHR?>~-)6Bv@qs$O|d|rsTkI1|} zv$6dL5v#YCzhAerFceT)=6?>oalD!T=Kp3K&L8l`Ar|?;YC;5nr0z_*-I0CK1uFu8 N)p0wE(xaX?{txxuil+bo delta 6447 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

eHmaPT9!R7X=YKZc|C=eayPJG`l6FDLcn u+dd8FtPL>GbmYu%*=rglkJ5|yX+vwjKjs2Q9-cb@aCSIkU$yr{@_zwI9EN28