From 428ece899fc80b485cfc3036390b0546a4c03114 Mon Sep 17 00:00:00 2001 From: Adri <33333517+Miraviel@users.noreply.github.com> Date: Fri, 13 Jan 2023 16:24:43 +0100 Subject: [PATCH] Admin tools: Adds a forceMove tool to build mode (#20073) * Admin tools: Adds a forceMove tool to build mode * Updated the misleading explanation * Adds early return, removes dangling return * Ryan review + observer disallow * Replaces copypaste * Adds selection overlay, signals * Removes unnecessary typecasting * this will never work anyhow * Adds signal_handler Co-authored-by: SteelSlayer <42044220+SteelSlayer@users.noreply.github.com> Co-authored-by: SteelSlayer <42044220+SteelSlayer@users.noreply.github.com> --- code/modules/buildmode/submodes/forcemove.dm | 78 +++++++++++++++++++ icons/misc/buildmode.dmi | Bin 4065 -> 1781 bytes paradise.dme | 1 + 3 files changed, 79 insertions(+) create mode 100644 code/modules/buildmode/submodes/forcemove.dm diff --git a/code/modules/buildmode/submodes/forcemove.dm b/code/modules/buildmode/submodes/forcemove.dm new file mode 100644 index 00000000000..0f2364bdfff --- /dev/null +++ b/code/modules/buildmode/submodes/forcemove.dm @@ -0,0 +1,78 @@ +// This tool calls forceMove() on an object/mob that is selected with right-click. +// Once the atom is moved, its selection is cleared to avoid any further moves by accident. +/datum/buildmode_mode/forcemove + key = "forcemove" + var/atom/movable/selected_atom // The atom we want to move + var/image/selected_overlay // Overlay for the selected atom only visible for the build mode user + +/datum/buildmode_mode/forcemove/show_help(mob/user) + to_chat(user, "***********************************************************") + to_chat(user, "Left Mouse Button on obj/mob = Select destination") + to_chat(user, "Right Mouse Button on obj/mob = Select atom to move") + to_chat(user, "Notice: You need to select the movable atom first, then left-click its destination.") + to_chat(user, "***********************************************************") + +/datum/buildmode_mode/forcemove/handle_click(mob/user, params, atom/A) + var/list/pa = params2list(params) + var/left_click = pa.Find("left") + var/right_click = pa.Find("right") + + // Selecting the atom to move + if(right_click) + if(!ismovable(A) || iseffect(A)) + to_chat(user, "You cannot move effects, turfs or areas.") + return + + // If we had something previously selected, handle its signal and overlay + if(selected_atom) + UnregisterSignal(selected_atom, COMSIG_PARENT_QDELETING) + + if(selected_overlay) + remove_selected_overlay(user) + + // We ensure it properly gets GC'd + selected_atom = A + RegisterSignal(selected_atom, COMSIG_PARENT_QDELETING, PROC_REF(on_selected_atom_deleted)) + + // Green overlay for selection + selected_overlay = image(icon = selected_atom.icon, loc = A, icon_state = selected_atom.icon_state) + selected_overlay.color = "#15d12d" + user.client.images += selected_overlay + + to_chat(user, "'[selected_atom]' is selected to be moved.") + return + + // Selecting the destination to move to + if(!left_click) + return + + var/atom/destination = A + + if(!selected_atom) + to_chat(user, "Select an atom to move first (with right-click).") + return + + // Block these as they can only lead to issues + if(iseffect(destination) || isobserver(destination)) + to_chat(user, "You should not move atoms into effects or ghosts.") + return + + selected_atom.forceMove(destination) + + to_chat(user, "'[selected_atom]' is moved to '[destination]'.") + log_admin("Build Mode: [key_name(user)] forcemoved [selected_atom] to [destination] at ([destination.x],[destination.y],[destination.z]).") + + UnregisterSignal(selected_atom, COMSIG_PARENT_QDELETING) + selected_atom = null + remove_selected_overlay(user) + +// Remove the green selection (only visible for the user) +/datum/buildmode_mode/forcemove/proc/remove_selected_overlay(mob/user) + user.client.images -= selected_overlay + selected_overlay = null + +// If it gets deleted mid-movement, remove the overlay and its attachment to the forcemove tool +/datum/buildmode_mode/forcemove/proc/on_selected_atom_deleted() + SIGNAL_HANDLER + UnregisterSignal(selected_atom, COMSIG_PARENT_QDELETING) + selected_atom = null diff --git a/icons/misc/buildmode.dmi b/icons/misc/buildmode.dmi index f5eaff893b30bd66c8c5917ec9e1dc429a4d29bc..149a13d7b71ec048c397b42a407d0fcbb59c51ca 100644 GIT binary patch delta 1777 zcmV3FZsUApJe)CUM^P~ zu~@Ho3qBw@F%y%)kh3$YsJk#8ai#(HIzB>(GD27OsuLR3<4mCsU7m8b^U}htF5V~& zrg@UZ3&{*o^TDyCU|Y$6b(SerD_spLO9q88ON`pnIm@)N*@OG0z6!@v=6E$Vm;YKk zZsiTNhkwQ-;0E0x0k4Q`0v==wDeFc{A!S$cHCX!Iqc6(M;{ID#Yg+^a+^Gxv z000G@Nklx0T3iX{UJs3 zrR|L6m&9Kz%Rhr4@ez8<4?n5n$5-|8_^giSt9p4n%YP4eJYUtzGft?Sn-Z2>&%dOl$k?l^Z9-Xp~=$CBLtX7h-U)*tmY=6W$pF(J|-gm z+fQf!4}V877=!0K=L*7_Xs78afSRA>*S)nC&-dOJgsqsh2yuun2@gm0G=>|{ z&vt{bm501KxtoL+dB}&KN67D=LzrV~w<(0U4)XimI)_jYZLwmTm{>!EYg}(!T(PN& z@oLds z*MHUmC^6jSq4sxeT>u_b!KLHP(UoplM@Hq(pNEj`@`?< z5C7Ks*S9}B?H>;7v#!VuZL;@?-bVSmfgL@FitC~FcLT&A{xNx*(mf6Amjw}|rYL_m z5>rM**EmQRd=>y1vgj8f0!r0$H)H5re8+K@So=GQNq81&82C7ffj^uRyiNQD;eUxD zBt+WC9Ooginp{JWCLXdYAj0As1m6JbnyOwsY8XwM_a)v2T*OL*9Q7i`x$n(Y&#j0g zF)_daIwd@aaq7%-UA7?tHr3rdAw>-xjEpMU1Y2f7+F9{V3hjw;a1z5E5gS6i_sd<8 zPsl?t@tYdua&M>eFuVcq9mU?yi+|^i-o`oJz4dmI9J#G>?CTT zOG0rL1tH+)4z4ylN#Zv=>to;2oP!pw?x)<*3`mG`2toWK%pnv&MEo+N>iwBL_+N8k zsPx+(POx+J39sr8@Q1&ZA22W|)%*W1{t$07O`9pw%gTKi^bwx^8d!ab{(oU|0?ts; zFkSoOBf{8JNHqcru$L}J*ZmZ0(|x|Oe<)QCz<@)y(n}~#M+mty1dyEqBHkc`O%cYv z3=MRSAwYi&D?)0q#`~RPRgZ$M3Hb)RPe+-imI)41^6;9_Z?QjkIm(#5 zR@~Q)5YRN|nWG6E-mD<1w3A}O^jid86V?PZA!)$rR1u~-;6@YHF(M+G;6+Tqn3M%T zy9k#Ft2}Jw9TTGwKU)v0JZ$A1k2)B0x?-n9?DT__m-cuy%H28o-G7BCbNOpRoZ1!P zy7%^nBW7v3oxA;p)^YnQH7|J6AGR-e*Z(yycy}f=FL-w*vdyl7tX>u~u^jvx5-)o{*XzHWQ}KQxBo52;~@# zp{Iy}KO1Fw-QE~w;A+m>#60xZgi7}iuCocjbLPz>{N8gJjSO{)N9Xcx<`@^Zf3paA zD)Zc)LFm|?I_RCt9Wnd}LYNps8enSv|2uj3pRam%{a^Efcl}@Ug0s!iY&-W4Tng>8 T$Ge&G00000NkvXXu0mjfF|A`2 literal 4065 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 diff --git a/paradise.dme b/paradise.dme index 06e60026f96..c1f4c4223f5 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1444,6 +1444,7 @@ #include "code\modules\buildmode\submodes\boom.dm" #include "code\modules\buildmode\submodes\copy.dm" #include "code\modules\buildmode\submodes\fill.dm" +#include "code\modules\buildmode\submodes\forcemove.dm" #include "code\modules\buildmode\submodes\link.dm" #include "code\modules\buildmode\submodes\mapgen.dm" #include "code\modules\buildmode\submodes\save.dm"