[round((health / maxHealth) * 100, 0.5)]% "
/mob/living/simple_animal/hostile/clockwork/guardian/proc/update_stats()
if(GLOB.ratvar_awakens)
diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm
index 9e550091d4..ae4a9599d4 100644
--- a/code/modules/antagonists/devil/true_devil/_true_devil.dm
+++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm
@@ -95,7 +95,7 @@
visible_message("
[src] easily breaks out of [p_their()] handcuffs! ", \
"
With just a thought your handcuffs fall off. ")
-/mob/living/carbon/true_devil/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE, check_resting=FALSE)
+/mob/living/carbon/true_devil/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(incapacitated())
to_chat(src, "
You can't do that right now! ")
return FALSE
diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm
index 07a9b6aba1..7f533c87b4 100644
--- a/code/modules/antagonists/revenant/revenant.dm
+++ b/code/modules/antagonists/revenant/revenant.dm
@@ -150,7 +150,7 @@
essencecolor = "#9A5ACB" //oh boy you've got a lot of essence
else if(!essence)
essencecolor = "#1D2953" //oh jeez you're dying
- hud_used.healths.maptext = MAPTEXT("
[essence]E
")
+ hud_used.healths.maptext = "
[essence]E
"
/mob/living/simple_animal/revenant/med_hud_set_health()
return //we use no hud
diff --git a/code/modules/balloon_alert/balloon_alert.dm b/code/modules/balloon_alert/balloon_alert.dm
index f529768b1d..c273722607 100644
--- a/code/modules/balloon_alert/balloon_alert.dm
+++ b/code/modules/balloon_alert/balloon_alert.dm
@@ -48,7 +48,7 @@
balloon_alert.appearance_flags = RESET_ALPHA|RESET_COLOR|RESET_TRANSFORM
balloon_alert.maptext = MAPTEXT("
[text] ")
balloon_alert.maptext_x = (BALLOON_TEXT_WIDTH - bound_width) * -0.5
- WXH_TO_HEIGHT(viewer_client?.MeasureText(text, null, BALLOON_TEXT_WIDTH), balloon_alert.maptext_height)
+ balloon_alert.maptext_height = WXH_TO_HEIGHT(viewer_client?.MeasureText(text, null, BALLOON_TEXT_WIDTH))
balloon_alert.maptext_width = BALLOON_TEXT_WIDTH
viewer_client?.images += balloon_alert
diff --git a/code/modules/clothing/glasses/engine_goggles.dm b/code/modules/clothing/glasses/engine_goggles.dm
index 013084e38f..461648c270 100644
--- a/code/modules/clothing/glasses/engine_goggles.dm
+++ b/code/modules/clothing/glasses/engine_goggles.dm
@@ -99,7 +99,7 @@
var/strength = round(rad_places[i] / 1000, 0.1)
var/image/pic = image(loc = place)
var/mutable_appearance/MA = new()
- MA.maptext = MAPTEXT("[strength]k")
+ MA.maptext = "
[strength]k "
MA.color = "#04e604"
MA.layer = RAD_TEXT_LAYER
MA.plane = GAME_PLANE
diff --git a/code/modules/integrated_electronics/subtypes/smart.dm b/code/modules/integrated_electronics/subtypes/smart.dm
index 7ebb57e9f0..67a1508b1d 100644
--- a/code/modules/integrated_electronics/subtypes/smart.dm
+++ b/code/modules/integrated_electronics/subtypes/smart.dm
@@ -237,7 +237,7 @@
brainholder.do_work(6)
-/mob/living/brain/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE, check_resting=FALSE)
+/mob/living/brain/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
return check_bot_self
/obj/item/integrated_circuit/smart/advanced_pathfinder/proc/hippie_xor_decrypt()
@@ -369,5 +369,5 @@
paiholder.do_work(6)
-/mob/living/silicon/pai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE, check_resting=FALSE)
+/mob/living/silicon/pai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
return check_bot_self
diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm
index 75b647809a..69b5de963d 100644
--- a/code/modules/mining/minebot.dm
+++ b/code/modules/mining/minebot.dm
@@ -82,7 +82,8 @@
Field repairs can be done with a welder."
if(stored_gun && stored_gun.max_mod_capacity)
. += "
[stored_gun.get_remaining_mod_capacity()]% mod capacity remaining."
- for(var/obj/item/borg/upgrade/modkit/M in stored_gun.modkits)
+ for(var/A in stored_gun.get_modkits())
+ var/obj/item/borg/upgrade/modkit/M = A
. += "
There is \a [M] installed, using [M.cost]% capacity. "
/mob/living/simple_animal/hostile/mining_drone/welder_act(mob/living/user, obj/item/I)
@@ -135,7 +136,8 @@
if(istype(O, /obj/item/projectile/kinetic))
var/obj/item/projectile/kinetic/K = O
if(K.kinetic_gun)
- for(var/obj/item/borg/upgrade/modkit/M in K.kinetic_gun.modkits)
+ for(var/A in K.kinetic_gun.get_modkits())
+ var/obj/item/borg/upgrade/modkit/M = A
if(istype(M, /obj/item/borg/upgrade/modkit/minebot_passthrough))
return TRUE
if(istype(O, /obj/item/projectile/destabilizer))
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 746d9f68dd..42316b6832 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -840,7 +840,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
update_icon()
-/mob/dead/observer/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE, check_resting=FALSE)
+/mob/dead/observer/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
return IsAdminGhost(usr)
/mob/dead/observer/is_literate()
diff --git a/code/modules/mob/living/carbon/alien/screen.dm b/code/modules/mob/living/carbon/alien/screen.dm
index 1f8902a584..4d90fd4b32 100644
--- a/code/modules/mob/living/carbon/alien/screen.dm
+++ b/code/modules/mob/living/carbon/alien/screen.dm
@@ -1,7 +1,7 @@
/mob/living/carbon/alien/proc/updatePlasmaDisplay()
if(hud_used) //clientless aliens
- hud_used.alien_plasma_display.maptext = MAPTEXT("
[round(getPlasma())]
")
+ hud_used.alien_plasma_display.maptext = "
[round(getPlasma())]
"
/mob/living/carbon/alien/larva/updatePlasmaDisplay()
return
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 3f6779c03b..be33694b37 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -130,7 +130,7 @@
spreadFire(AM)
/mob/living/carbon/human/Topic(href, href_list)
- if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY, check_resting = FALSE))
+ if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
if(href_list["embedded_object"])
var/obj/item/bodypart/L = locate(href_list["embedded_limb"]) in bodyparts
if(!L)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 5f06d2d53c..3f16412e6d 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1093,7 +1093,7 @@
/mob/living/proc/harvest(mob/living/user) //used for extra objects etc. in butchering
return
-/mob/living/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE, check_resting=FALSE)
+/mob/living/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(incapacitated())
to_chat(src, "
You can't do that right now! ")
return FALSE
diff --git a/code/modules/mob/living/living_mobility.dm b/code/modules/mob/living/living_mobility.dm
index bc3f18e1df..6b397cdef8 100644
--- a/code/modules/mob/living/living_mobility.dm
+++ b/code/modules/mob/living/living_mobility.dm
@@ -108,10 +108,8 @@
mobility_flags |= MOBILITY_STAND
lying = 0
- if(restrained || incapacitated())
- mobility_flags &= ~MOBILITY_UI
- if(should_be_lying)
- mobility_flags &= ~MOBILITY_PULL
+ if(should_be_lying || restrained || incapacitated())
+ mobility_flags &= ~(MOBILITY_UI|MOBILITY_PULL)
else
mobility_flags |= MOBILITY_UI|MOBILITY_PULL
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 1888178f07..58887a0cbf 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -843,7 +843,7 @@
return TRUE
return ..()
-/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE, check_resting=FALSE)
+/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(control_disabled || incapacitated())
to_chat(src, "
You can't do that right now! ")
return FALSE
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 715894efa3..1787523578 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -210,7 +210,7 @@
// See software.dm for Topic()
-/mob/living/silicon/pai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE, check_resting=FALSE)
+/mob/living/silicon/pai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(be_close && !in_range(M, src))
to_chat(src, "
You are too far away! ")
return FALSE
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 4146aea3e7..96f2ec557b 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -28,13 +28,11 @@
inv2 = new /atom/movable/screen/robot/module2()
inv3 = new /atom/movable/screen/robot/module3()
- ident = rand(1, 999)
-
if(!shell)
aiPDA = new/obj/item/pda/ai(src)
aiPDA.owner = real_name
aiPDA.ownjob = "Cyborg"
- aiPDA.name = real_name + " ([aiPDA.ownjob])"
+ aiPDA.name = real_name + " (" + aiPDA.ownjob + ")"
previous_health = health
@@ -61,29 +59,26 @@
update_icons()
. = ..()
- //If this body is meant to be a borg controlled by the AI player
//If this body is meant to be a borg controlled by the AI player
if(shell)
- var/obj/item/borg/upgrade/ai/board = new(src)
- make_shell(board)
- add_to_upgrades(board)
- else
- //MMI stuff. Held togheter by magic. ~Miauw
- if(!mmi?.brainmob)
- mmi = new (src)
- mmi.brain = new /obj/item/organ/brain(mmi)
- mmi.brain.organ_flags |= ORGAN_FROZEN
- mmi.brain.name = "[real_name]'s brain"
- mmi.icon_state = "mmi_full"
- mmi.name = "[initial(mmi.name)]: [real_name]"
- mmi.brainmob = new(mmi)
- mmi.brainmob.name = src.real_name
- mmi.brainmob.real_name = src.real_name
- mmi.brainmob.container = mmi
- mmi.update_appearance()
+ make_shell()
+
+ //MMI stuff. Held togheter by magic. ~Miauw
+ else if(!mmi || !mmi.brainmob)
+ mmi = new (src)
+ mmi.brain = new /obj/item/organ/brain(mmi)
+ mmi.brain.organ_flags |= ORGAN_FROZEN
+ mmi.brain.name = "[real_name]'s brain"
+ mmi.icon_state = "mmi_full"
+ mmi.name = "Man-Machine Interface: [real_name]"
+ mmi.brainmob = new(mmi)
+ mmi.brainmob.name = src.real_name
+ mmi.brainmob.real_name = src.real_name
+ mmi.brainmob.container = mmi
INVOKE_ASYNC(src, .proc/updatename)
+ playsound(loc, 'sound/voice/liveagain.ogg', 75, TRUE)
aicamera = new/obj/item/camera/siliconcam/robot_camera(src)
toner = tonermax
diag_hud_set_borgcell()
@@ -338,145 +333,194 @@
return FALSE
return ISINRANGE(T1.x, T0.x - interaction_range, T0.x + interaction_range) && ISINRANGE(T1.y, T0.y - interaction_range, T0.y + interaction_range)
-/mob/living/silicon/robot/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/stack/cable_coil) && wiresexposed)
+/mob/living/silicon/robot/proc/attempt_welder_repair(obj/item/W, mob/user)
+ if(!W.tool_behaviour == TOOL_WELDER)
+ return
+ if(!getBruteLoss())
+ to_chat(user, "
[src] is already in good condition! ")
+ return
+ if(!W.tool_start_check(user, amount=0)) //The welder has 1u of fuel consumed by it's afterattack, so we don't need to worry about taking any away.
+ return
+ user.DelayNextAction(CLICK_CD_MELEE)
+ if(src == user)
+ to_chat(user, "
You start fixing yourself... ")
+ if(!W.use_tool(src, user, 50))
+ return
+ adjustBruteLoss(-10)
+ else
+ to_chat(user, "
You start fixing [src]... ")
+ if(!do_after(user, 30, target = src))
+ return
+ adjustBruteLoss(-30)
+ updatehealth()
+ add_fingerprint(user)
+ visible_message("
[user] has fixed some of the dents on [src]. ")
+
+/mob/living/silicon/robot/proc/attempt_cable_repair(obj/item/stack/cable_coil/W, mob/user)
+ if (getFireLoss() > 0 || getToxLoss() > 0)
user.DelayNextAction(CLICK_CD_MELEE)
- if (getFireLoss() > 0 || getToxLoss() > 0)
- if(src == user)
- to_chat(user, span_notice("You start fixing yourself..."))
- if(!W.use_tool(src, user, 5 SECONDS, 1, skill_gain_mult = TRIVIAL_USE_TOOL_MULT))
- to_chat(user, span_warning("You need more cable to repair [src]!"))
- return
- adjustFireLoss(-10)
- adjustToxLoss(-10)
- else
- to_chat(user, span_notice("You start fixing [src]..."))
- if(!W.use_tool(src, user, 3 SECONDS, 1))
- to_chat(user, span_warning("You need more cable to repair [src]!"))
- adjustFireLoss(-30)
- adjustToxLoss(-30)
- updatehealth()
- user.visible_message(span_notice("[user] has fixed some of the burnt wires on [src]."), span_notice("You fix some of the burnt wires on [src]."))
+ if(src == user)
+ to_chat(user, "
You start fixing yourself... ")
+ if(!W.use_tool(src, user, 50, 1, skill_gain_mult = TRIVIAL_USE_TOOL_MULT))
+ to_chat(user, "
You need more cable to repair [src]! ")
+ return
+ adjustFireLoss(-10)
+ adjustToxLoss(-10)
else
- to_chat(user, span_warning("The wires seem fine, there's no need to fix them."))
+ to_chat(user, "
You start fixing [src]... ")
+ if(!W.use_tool(src, user, 30, 1))
+ to_chat(user, "
You need more cable to repair [src]! ")
+ return
+ adjustFireLoss(-30)
+ adjustToxLoss(-30)
+ updatehealth()
+ user.visible_message("[user] has fixed some of the burnt wires on [src].", "
You fix some of the burnt wires on [src]. ")
+ else
+ to_chat(user, "The wires seem fine, there's no need to fix them.")
+
+/mob/living/silicon/robot/attackby(obj/item/W, mob/user, params)
+ if(W.tool_behaviour == TOOL_WELDER && (user.a_intent != INTENT_HARM || user == src))
+ INVOKE_ASYNC(src, .proc/attempt_welder_repair, W, user)
return
- if(istype(W, /obj/item/stock_parts/cell) && opened) // trying to put a cell inside
+ else if(istype(W, /obj/item/stack/cable_coil) && wiresexposed)
+ INVOKE_ASYNC(src, .proc/attempt_cable_repair, W, user)
+ return
+
+ else if(W.tool_behaviour == TOOL_CROWBAR) // crowbar means open or close the cover
+ if(opened)
+ to_chat(user, "
You close the cover. ")
+ opened = 0
+ update_icons()
+ else
+ if(locked)
+ to_chat(user, "
The cover is locked and cannot be opened! ")
+ else
+ to_chat(user, "
You open the cover. ")
+ opened = 1
+ update_icons()
+
+ else if(istype(W, /obj/item/stock_parts/cell) && opened) // trying to put a cell inside
if(wiresexposed)
- to_chat(user, span_warning("Close the cover first!"))
+ to_chat(user, "
Close the cover first! ")
else if(cell)
- to_chat(user, span_warning("There is a power cell already installed!"))
+ to_chat(user, "
There is a power cell already installed! ")
else
if(!user.transferItemToLoc(W, src))
return
cell = W
- to_chat(user, span_notice("You insert the power cell."))
+ to_chat(user, "
You insert the power cell. ")
update_icons()
diag_hud_set_borgcell()
- return
- if(is_wire_tool(W))
+ else if(is_wire_tool(W))
if (wiresexposed)
wires.interact(user)
else
- to_chat(user, span_warning("You can't reach the wiring!"))
- return
+ to_chat(user, "
You can't reach the wiring! ")
- if(istype(W, /obj/item/aiModule))
+ else if(W.tool_behaviour == TOOL_SCREWDRIVER && opened && !cell) // haxing
+ wiresexposed = !wiresexposed
+ to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]")
+ update_icons()
+
+ else if((W.tool_behaviour == TOOL_SCREWDRIVER) && opened && cell) // radio
+ if(shell)
+ to_chat(user, "You cannot seem to open the radio compartment") //Prevent AI radio key theft
+ else if(radio)
+ radio.attackby(W,user)//Push it to the radio to let it handle everything
+ else
+ to_chat(user, "
Unable to locate a radio! ")
+ update_icons()
+
+ else if(W.tool_behaviour == TOOL_WRENCH && opened && !cell) //Deconstruction. The flashes break from the fall, to prevent this from being a ghetto reset module.
+ if(!locked_down)
+ to_chat(user, "
[src]'s bolts spark! Maybe you should lock them down first! ")
+ spark_system.start()
+ return
+ else
+ to_chat(user, "
You start to unfasten [src]'s securing bolts... ")
+ if(W.use_tool(src, user, 50, volume=50) && !cell)
+ user.visible_message("[user] deconstructs [src]!", "
You unfasten the securing bolts, and [src] falls to pieces! ")
+ deconstruct()
+
+ else if(istype(W, /obj/item/aiModule))
var/obj/item/aiModule/MOD = W
if(!opened)
- to_chat(user, span_warning("You need access to the robot's insides to do that!"))
+ to_chat(user, "
You need access to the robot's insides to do that! ")
return
if(wiresexposed)
- to_chat(user, span_warning("You need to close the wire panel to do that!"))
+ to_chat(user, "
You need to close the wire panel to do that! ")
return
if(!cell)
- to_chat(user, span_warning("You need to install a power cell to do that!"))
+ to_chat(user, "
You need to install a power cell to do that! ")
return
if(shell) //AI shells always have the laws of the AI
- to_chat(user, span_warning("[src] is controlled remotely! You cannot upload new laws this way!"))
+ to_chat(user, "
[src] is controlled remotely! You cannot upload new laws this way! ")
return
- if(connected_ai && lawupdate)
- to_chat(user, span_warning("[src] is receiving laws remotely from a synced AI!"))
- return
- if(emagged)
- to_chat(user, span_warning("The law interface glitches out!"))
- emote("buzz")
+ if(emagged || (connected_ai && lawupdate)) //Can't be sure which, metagamers
+ emote("buzz-[user.name]")
return
if(!mind) //A player mind is required for law procs to run antag checks.
- to_chat(user, span_warning("[src] is entirely unresponsive!"))
+ to_chat(user, "
[src] is entirely unresponsive! ")
return
MOD.install(laws, user) //Proc includes a success mesage so we don't need another one
return
- if(istype(W, /obj/item/encryptionkey) && opened)
+ else if(istype(W, /obj/item/encryptionkey/) && opened)
if(radio)//sanityyyyyy
radio.attackby(W,user)//GTFO, you have your own procs
else
- to_chat(user, span_warning("Unable to locate a radio!"))
- return
+ to_chat(user, "
Unable to locate a radio! ")
- if (W.GetID()) // trying to unlock the interface with an ID card
+ else if (istype(W, /obj/item/card/id)||istype(W, /obj/item/pda)) // trying to unlock the interface with an ID card
+ if(emagged)//still allow them to open the cover
+ to_chat(user, "
The interface seems slightly damaged. ")
if(opened)
- to_chat(user, span_warning("You must close the cover to swipe an ID card!"))
+ to_chat(user, "
You must close the cover to swipe an ID card! ")
else
if(allowed(usr))
locked = !locked
- to_chat(user, span_notice("You [ locked ? "lock" : "unlock"] [src]'s cover."))
+ to_chat(user, "
You [ locked ? "lock" : "unlock"] [src]'s cover. ")
update_icons()
- if(emagged)
- to_chat(user, span_notice("The cover interface glitches out for a split second."))
- logevent("ChÃ¥vÃis cover lock has been [locked ? "engaged" : "released"]") //ChÃ¥vÃis: see above line
- else
- logevent("Chassis cover lock has been [locked ? "engaged" : "released"]")
else
- to_chat(user, span_danger("Access denied."))
- return
+ to_chat(user, "
Access denied. ")
- if(istype(W, /obj/item/borg/upgrade))
+ else if(istype(W, /obj/item/borg/upgrade/))
var/obj/item/borg/upgrade/U = W
if(!opened)
- to_chat(user, span_warning("You must access the cyborg's internals!"))
- return
- if(!module && U.require_module)
- to_chat(user, span_warning("The cyborg must choose a model before it can be upgraded!"))
- return
- if(U.locked)
- to_chat(user, span_warning("The upgrade is locked and cannot be used yet!"))
- return
- if(!user.canUnEquip(U))
- to_chat(user, span_warning("The upgrade is stuck to you and you can't seem to let go of it!"))
- return
- apply_upgrade(U, user)
- return
+ to_chat(user, "
You must access the borg's internals! ")
+ else if(!src.module && U.require_module)
+ to_chat(user, "
The borg must choose a module before it can be upgraded! ")
+ else if(U.locked)
+ to_chat(user, "
The upgrade is locked and cannot be used yet! ")
+ else
+ if(!user.temporarilyRemoveItemFromInventory(U))
+ return
+ if(U.action(src))
+ to_chat(user, "
You apply the upgrade to [src]. ")
+ if(U.one_use)
+ U.afterInstall(src)
+ qdel(U)
+ else
+ U.forceMove(src)
+ upgrades += U
+ U.afterInstall(src)
+ else
+ to_chat(user, "
Upgrade error. ")
+ U.forceMove(drop_location())
- if(istype(W, /obj/item/toner))
+ else if(istype(W, /obj/item/toner))
if(toner >= tonermax)
- to_chat(user, span_warning("The toner level of [src] is at its highest level possible!"))
- return
- if(!user.temporarilyRemoveItemFromInventory(W))
- return
- toner = tonermax
- qdel(W)
- to_chat(user, span_notice("You fill the toner level of [src] to its max capacity."))
- return
-
- if(istype(W, /obj/item/flashlight))
- if(!opened)
- to_chat(user, span_warning("You need to open the panel to repair the headlamp!"))
- return
- if(lamp_functional)
- to_chat(user, span_warning("The headlamp is already functional!"))
- return
- if(!user.temporarilyRemoveItemFromInventory(W))
- to_chat(user, span_warning("[W] seems to be stuck to your hand. You'll have to find a different light."))
- return
- lamp_functional = TRUE
- qdel(W)
- to_chat(user, span_notice("You replace the headlamp bulbs."))
- return
-
- return ..()
+ to_chat(user, "
The toner level of [src] is at its highest level possible! ")
+ else
+ if(!user.temporarilyRemoveItemFromInventory(W))
+ return
+ toner = tonermax
+ qdel(W)
+ to_chat(user, "
You fill the toner level of [src] to its max capacity. ")
+ else
+ return ..()
/mob/living/silicon/robot/crowbar_act(mob/living/user, obj/item/I) //TODO: make fucking everything up there in that attackby() proc use the proper tool_act() procs. But honestly, who has time for that? 'cause I know for sure that you, the person reading this, sure as hell doesn't.
var/validbreakout = FALSE
@@ -834,7 +878,7 @@
if(DISCONNECT) //Tampering with the wires
to_chat(connected_ai, "
NOTICE - Remote telemetry lost with [name]. ")
-/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE, check_resting=FALSE)
+/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(stat || locked_down || low_power_mode)
to_chat(src, "
You can't do that right now! ")
return FALSE
@@ -1018,49 +1062,33 @@
*Checking Exited() to detect if a hat gets up and walks off.
*Drones and pAIs might do this, after all.
*/
-/mob/living/silicon/robot/Exited(atom/movable/gone)
- . = ..()
- if(hat == gone)
+/mob/living/silicon/robot/Exited(atom/A)
+ if(hat && hat == A)
hat = null
if(!QDELETED(src)) //Don't update icons if we are deleted.
update_icons()
+ return ..()
- if(gone == cell)
- cell = null
-
- if(gone == mmi)
- mmi = null
-
-///Called when a mob uses an upgrade on an open borg. Checks to make sure the upgrade can be applied
-/mob/living/silicon/robot/proc/apply_upgrade(obj/item/borg/upgrade/new_upgrade, mob/user, admin_added)
- if(!admin_added && isnull(user))
- return FALSE
+///Use this to add upgrades to robots. It'll register signals for when the upgrade is moved or deleted, if not single use.
+/mob/living/silicon/robot/proc/add_to_upgrades(obj/item/borg/upgrade/new_upgrade, mob/user)
if(new_upgrade in upgrades)
return FALSE
- if(!admin_added && !user.temporarilyRemoveItemFromInventory(new_upgrade)) //calling the upgrade's dropped() proc /before/ we add action buttons
+ if(!user.temporarilyRemoveItemFromInventory(new_upgrade)) //calling the upgrade's dropped() proc /before/ we add action buttons
return FALSE
if(!new_upgrade.action(src, user))
- to_chat(user, span_danger("Upgrade error."))
- if(admin_added)
- qdel(new_upgrade)
- else
- new_upgrade.forceMove(loc) //gets lost otherwise
+ to_chat(user, "
Upgrade error. ")
+ new_upgrade.forceMove(loc) //gets lost otherwise
return FALSE
- to_chat(user, span_notice("You apply the upgrade to [src]."))
- add_to_upgrades(new_upgrade)
- return TRUE
-
-///Moves the upgrade inside the robot and registers relevant signals.
-/mob/living/silicon/robot/proc/add_to_upgrades(obj/item/borg/upgrade/new_upgrade)
+ to_chat(user, "
You apply the upgrade to [src]. ")
to_chat(src, "----------------\nNew hardware detected...Identified as \"
[new_upgrade] \"...Setup complete.\n----------------")
if(new_upgrade.one_use)
logevent("Firmware [new_upgrade] run successfully.")
qdel(new_upgrade)
- return
+ return FALSE
upgrades += new_upgrade
new_upgrade.forceMove(src)
- RegisterSignal(new_upgrade, COMSIG_MOVABLE_MOVED, PROC_REF(remove_from_upgrades))
- RegisterSignal(new_upgrade, COMSIG_PARENT_QDELETING, PROC_REF(on_upgrade_deleted))
+ RegisterSignal(new_upgrade, COMSIG_MOVABLE_MOVED, .proc/remove_from_upgrades)
+ RegisterSignal(new_upgrade, COMSIG_PARENT_QDELETING, .proc/on_upgrade_deleted)
logevent("Hardware [new_upgrade] installed successfully.")
///Called when an upgrade is moved outside the robot. So don't call this directly, use forceMove etc.
@@ -1087,17 +1115,15 @@
* * board - B.O.R.I.S. module board used for transforming the cyborg into AI shell
*/
/mob/living/silicon/robot/proc/make_shell(obj/item/borg/upgrade/ai/board)
- if(isnull(board))
- stack_trace("make_shell was called without a board argument! This is never supposed to happen!")
- return FALSE
-
+ if(!board)
+ upgrades |= new /obj/item/borg/upgrade/ai(src)
shell = TRUE
braintype = "AI Shell"
name = "Empty AI Shell-[ident]"
real_name = name
GLOB.available_ai_shells |= src
if(!QDELETED(builtInCamera))
- builtInCamera.c_tag = real_name //update the camera name too
+ builtInCamera.c_tag = real_name //update the camera name too
diag_hud_set_aishell()
notify_ai(AI_SHELL)
diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm
index f8217945db..d5a1058a61 100644
--- a/code/modules/mob/living/silicon/robot/robot_defense.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defense.dm
@@ -94,76 +94,6 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real
apply_status_effect(/datum/status_effect/vtec_disabled, time)
update_movespeed()
-/mob/living/silicon/robot/welder_act(mob/living/user, obj/item/tool)
- if(user.a_intent == INTENT_HARM)
- return FALSE
- . = TRUE
- if (!getBruteLoss())
- to_chat(user, span_warning("[src] is already in good condition!"))
- return
- if (!tool.tool_start_check(user, amount=0)) //The welder has 1u of fuel consumed by it's afterattack, so we don't need to worry about taking any away.
- return
- user.DelayNextAction(CLICK_CD_MELEE)
- if(src == user)
- to_chat(user, span_notice("You start fixing yourself..."))
- if(!tool.use_tool(src, user, 50))
- return
- adjustBruteLoss(-10)
- else
- to_chat(user, span_notice("You start fixing [src]..."))
- if(!do_after(user, 3 SECONDS, target = src))
- return
- adjustBruteLoss(-30)
- updatehealth()
- add_fingerprint(user)
- visible_message(span_notice("[user] has fixed some of the dents on [src]."))
-
-/mob/living/silicon/robot/crowbar_act(mob/living/user, obj/item/tool)
- . = TRUE
- if(opened)
- to_chat(user, span_notice("You close the cover."))
- opened = FALSE
- update_icons()
- else
- if(locked)
- to_chat(user, span_warning("The cover is locked and cannot be opened!"))
- else
- to_chat(user, span_notice("You open the cover."))
- opened = TRUE
- update_icons()
-
- return TRUE
-
-/mob/living/silicon/robot/screwdriver_act(mob/living/user, obj/item/tool)
- if(!opened)
- return FALSE
- . = TRUE
- if(!cell) // haxing
- wiresexposed = !wiresexposed
- to_chat(user, span_notice("The wires have been [wiresexposed ? "exposed" : "unexposed"]."))
- else // radio
- if(shell)
- to_chat(user, span_warning("You cannot seem to open the radio compartment!")) //Prevent AI radio key theft
- else if(radio)
- radio.screwdriver_act(user, tool) // Push it to the radio to let it handle everything
- else
- to_chat(user, span_warning("Unable to locate a radio!"))
- update_icons()
-
-/mob/living/silicon/robot/wrench_act(mob/living/user, obj/item/tool)
- if(!(opened && !cell)) // Deconstruction. The flashes break from the fall, to prevent this from being a ghetto reset module.
- return FALSE
- . = TRUE
- if(!locked_down)
- to_chat(user, span_boldannounce("[src]'s bolts spark! Maybe you should lock them down first!"))
- spark_system.start()
- return
- to_chat(user, span_notice("You start to unfasten [src]'s securing bolts..."))
- if(tool.use_tool(src, user, 5 SECONDS, volume = 50) && !cell)
- user.visible_message(span_notice("[user] deconstructs [src]!"), span_notice("You unfasten the securing bolts, and [src] falls to pieces!"))
- deconstruct()
- return
-
/mob/living/silicon/robot/fire_act()
if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them
IgniteMob()
diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm
index 4c8872ffbf..6faf8f0db5 100644
--- a/code/modules/mob/living/simple_animal/guardian/guardian.dm
+++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm
@@ -257,7 +257,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - summoner.health) / abs(HEALTH_THRESHOLD_DEAD - summoner.maxHealth)) * 100)
else
resulthealth = round((summoner.health / summoner.maxHealth) * 100, 0.5)
- hud_used.healths.maptext = MAPTEXT("
[resulthealth]%
")
+ hud_used.healths.maptext = "
[resulthealth]%
"
/mob/living/simple_animal/hostile/guardian/adjustHealth(amount, updating_health = TRUE, forced = FALSE) //The spirit is invincible, but passes on damage to the summoner
. = amount
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 4a1c0f75c8..dd172bc8c7 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -449,7 +449,7 @@
if(target)
return new childspawn(target)
-/mob/living/simple_animal/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE, check_resting=FALSE)
+/mob/living/simple_animal/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(incapacitated())
to_chat(src, "
You can't do that right now! ")
return FALSE
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 17eedaca46..73dc71b037 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -833,7 +833,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
return IsAdminGhost(src) || Adjacent(A) || A.hasSiliconAccessInArea(src)
//Can the mob use Topic to interact with machines
-/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE, check_resting=FALSE)
+/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
return
/mob/proc/canUseStorage()
diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm
index a01c98778a..e1733bb6f9 100644
--- a/code/modules/modular_computers/computers/item/computer.dm
+++ b/code/modules/modular_computers/computers/item/computer.dm
@@ -92,7 +92,7 @@
if(issilicon(user))
return
- if(user.canUseTopic(src, BE_CLOSE, check_resting = w_class <= WEIGHT_CLASS_SMALL))
+ if(user.canUseTopic(src, BE_CLOSE))
var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2]
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
return (card_slot2?.try_eject(user) || card_slot?.try_eject(user)) //Try the secondary one first.
@@ -157,7 +157,7 @@
/obj/item/modular_computer/MouseDrop(obj/over_object, src_location, over_location)
var/mob/M = usr
- if((!istype(over_object, /atom/movable/screen)) && usr.canUseTopic(src, BE_CLOSE, w_class <= WEIGHT_CLASS_SMALL))
+ if((!istype(over_object, /atom/movable/screen)) && usr.canUseTopic(src, BE_CLOSE))
return attack_self(M)
return ..()
diff --git a/code/modules/modular_computers/computers/item/tablet.dm b/code/modules/modular_computers/computers/item/tablet.dm
index 9148d0a453..f495dadbf2 100644
--- a/code/modules/modular_computers/computers/item/tablet.dm
+++ b/code/modules/modular_computers/computers/item/tablet.dm
@@ -57,7 +57,7 @@
SStgui.update_uis(src)
/obj/item/modular_computer/tablet/proc/remove_pen()
- if(hasSiliconAccessInArea(usr) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK, check_resting = FALSE))
+ if(hasSiliconAccessInArea(usr) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if(inserted_item)
diff --git a/code/modules/paperwork/ticketmachine.dm b/code/modules/paperwork/ticketmachine.dm
index 6022853fad..9683601670 100644
--- a/code/modules/paperwork/ticketmachine.dm
+++ b/code/modules/paperwork/ticketmachine.dm
@@ -142,7 +142,7 @@
maptext_x = 10
if(100)
maptext_x = 8
- maptext = MAPTEXT("[current_number]") //Finally, apply the maptext
+ maptext = "[current_number]" //Finally, apply the maptext
/obj/machinery/ticket_machine/attackby(obj/item/I, mob/user, params)
..()
@@ -182,7 +182,11 @@
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 100, FALSE)
ticket_number ++
to_chat(user, "
You take a ticket from [src], looks like you're ticket number #[ticket_number]... ")
- var/obj/item/ticket_machine_ticket/theirticket = new /obj/item/ticket_machine_ticket(get_turf(src), ticket_number)
+ var/obj/item/ticket_machine_ticket/theirticket = new /obj/item/ticket_machine_ticket(get_turf(src))
+ theirticket.name = "Ticket #[ticket_number]"
+ theirticket.maptext = "
[ticket_number] "
+ theirticket.saved_maptext = "
[ticket_number] "
+ theirticket.ticket_number = ticket_number
theirticket.source = src
theirticket.owner = user
user.put_in_hands(theirticket)
@@ -207,25 +211,10 @@
w_class = WEIGHT_CLASS_TINY
resistance_flags = FLAMMABLE
max_integrity = 50
- var/number
var/saved_maptext = null
var/mob/living/carbon/owner
var/obj/machinery/ticket_machine/source
-
-/obj/item/ticket_machine_ticket/Initialize(mapload, num)
- . = ..()
- number = num
- if(!isnull(num))
- name += " #[num]"
- saved_maptext = MAPTEXT(num)
- maptext = saved_maptext
-
-/obj/item/ticket_machine_ticket/examine(mob/user)
- . = ..()
- if(!isnull(number))
- . += span_notice("The ticket reads shimmering text that tells you that you are number [number] in queue.")
- if(source)
- . += span_notice("Below that, you can see that you are [number - source.current_number] spot\s away from being served.")
+ var/ticket_number
/obj/item/ticket_machine_ticket/attack_hand(mob/user)
. = ..()
@@ -244,7 +233,7 @@
/obj/item/ticket_machine_ticket/Destroy()
if(owner && source)
source.ticket_holders -= owner
- source.tickets[number] = null
+ source.tickets[ticket_number] = null
owner = null
source = null
return ..()
diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm
index c2acb46ff3..49821e55e0 100644
--- a/code/modules/photography/camera/camera.dm
+++ b/code/modules/photography/camera/camera.dm
@@ -50,7 +50,7 @@
/obj/item/camera/AltClick(mob/user)
. = ..()
- if(!user.canUseTopic(src, BE_CLOSE, check_resting = FALSE))
+ if(!user.canUseTopic(src, BE_CLOSE))
return
var/desired_x = input(user, "How high do you want the camera to shoot, between [picture_size_x_min] and [picture_size_x_max]?", "Zoom", picture_size_x) as num
var/desired_y = input(user, "How wide do you want the camera to shoot, between [picture_size_y_min] and [picture_size_y_max]?", "Zoom", picture_size_y) as num
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index 9c9ccd2b8d..5fd158c028 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -57,24 +57,25 @@
. = ..()
if(max_mod_capacity)
. += "
[get_remaining_mod_capacity()]% mod capacity remaining."
- for(var/obj/item/borg/upgrade/modkit/M in modkits)
+ for(var/A in get_modkits())
+ var/obj/item/borg/upgrade/modkit/M = A
. += "
There is \a [M] installed, using [M.cost]% capacity. "
/obj/item/gun/energy/kinetic_accelerator/crowbar_act(mob/living/user, obj/item/I)
. = TRUE
if(modkits.len)
- to_chat(user, span_notice("You pry all the modifications out."))
+ to_chat(user, "
You pry the modifications out. ")
I.play_tool_sound(src, 100)
for(var/obj/item/borg/upgrade/modkit/M in modkits)
- M.forceMove(drop_location()) //uninstallation handled in Exited(), or /mob/living/silicon/robot/remove_from_upgrades() for borgs
+ M.uninstall(src)
else
- to_chat(user, span_notice("There are no modifications currently installed."))
+ to_chat(user, "
There are no modifications currently installed. ")
-/obj/item/gun/energy/kinetic_accelerator/Exited(atom/movable/gone)
- if(gone in modkits)
- var/obj/item/borg/upgrade/modkit/MK = gone
- MK.uninstall(src)
- return ..()
+/obj/item/gun/energy/kinetic_accelerator/Exited(atom/movable/AM)
+ . = ..()
+ if((AM in modkits) && istype(AM, /obj/item/borg/upgrade/modkit))
+ var/obj/item/borg/upgrade/modkit/M = AM
+ M.uninstall(src, FALSE)
/obj/item/gun/energy/kinetic_accelerator/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/borg/upgrade/modkit))
@@ -85,13 +86,20 @@
/obj/item/gun/energy/kinetic_accelerator/proc/get_remaining_mod_capacity()
var/current_capacity_used = 0
- for(var/obj/item/borg/upgrade/modkit/M in modkits)
+ for(var/A in get_modkits())
+ var/obj/item/borg/upgrade/modkit/M = A
current_capacity_used += M.cost
return max_mod_capacity - current_capacity_used
+/obj/item/gun/energy/kinetic_accelerator/proc/get_modkits()
+ . = list()
+ for(var/A in modkits)
+ . += A
+
/obj/item/gun/energy/kinetic_accelerator/proc/modify_projectile(obj/item/projectile/kinetic/K)
K.kinetic_gun = src //do something special on-hit, easy!
- for(var/obj/item/borg/upgrade/modkit/M in modkits)
+ for(var/A in get_modkits())
+ var/obj/item/borg/upgrade/modkit/M = A
M.modify_projectile(K)
/obj/item/gun/energy/kinetic_accelerator/cyborg
@@ -251,7 +259,7 @@
if(!target_turf)
target_turf = get_turf(src)
if(kinetic_gun) //hopefully whoever shot this was not very, very unfortunate.
- var/list/mods = kinetic_gun.modkits
+ var/list/mods = kinetic_gun.get_modkits()
for(var/obj/item/borg/upgrade/modkit/M in mods)
M.projectile_strike_predamage(src, target_turf, target, kinetic_gun)
for(var/obj/item/borg/upgrade/modkit/M in mods)
@@ -270,7 +278,7 @@
icon = 'icons/obj/objects.dmi'
icon_state = "modkit"
w_class = WEIGHT_CLASS_SMALL
- require_module = TRUE
+ require_module = 1
module_type = list(/obj/item/robot_module/miner)
module_flags = BORG_MODULE_MINER
var/denied_type = null
@@ -290,24 +298,26 @@
else
..()
-/obj/item/borg/upgrade/modkit/action(mob/living/silicon/robot/R)
- . = ..()
- if (.)
- for(var/obj/item/gun/energy/kinetic_accelerator/H in R.module.modules)
- return install(H, usr, FALSE)
+/obj/item/borg/upgrade/modkit/afterInstall(mob/living/silicon/robot/R)
+ for(var/obj/item/gun/energy/kinetic_accelerator/H in R.module.modules)
+ if(install(H, R)) //It worked
+ return
+ to_chat(R, "
Upgrade error - Aborting Kinetic Accelerator linking. ") //No applicable KA found, insufficient capacity, or some other problem.
-/obj/item/borg/upgrade/modkit/proc/install(obj/item/gun/energy/kinetic_accelerator/KA, mob/user, transfer_to_loc = TRUE)
+/obj/item/borg/upgrade/modkit/proc/install(obj/item/gun/energy/kinetic_accelerator/KA, mob/user)
. = TRUE
+ if(src in KA.modkits) // Sanity check to prevent installing the same modkit twice thanks to occasional click/lag delays.
+ return FALSE
if(minebot_upgrade)
if(minebot_exclusive && !istype(KA.loc, /mob/living/simple_animal/hostile/mining_drone))
- to_chat(user, span_notice("The modkit you're trying to install is only rated for minebot use."))
+ to_chat(user, "
The modkit you're trying to install is only rated for minebot use. ")
return FALSE
else if(istype(KA.loc, /mob/living/simple_animal/hostile/mining_drone))
- to_chat(user, span_notice("The modkit you're trying to install is not rated for minebot use."))
+ to_chat(user, "
The modkit you're trying to install is not rated for minebot use. ")
return FALSE
if(denied_type)
var/number_of_denied = 0
- for(var/A in KA.modkits)
+ for(var/A in KA.get_modkits())
var/obj/item/borg/upgrade/modkit/M = A
if(istype(M, denied_type))
number_of_denied++
@@ -316,25 +326,21 @@
break
if(KA.get_remaining_mod_capacity() >= cost)
if(.)
- if(transfer_to_loc && !user.transferItemToLoc(src, KA))
- return
- to_chat(user, span_notice("You install the modkit."))
- playsound(loc, 'sound/items/screwdriver.ogg', 100, TRUE)
+ if(!user.transferItemToLoc(src, KA))
+ return FALSE
+ to_chat(user, "
You install the modkit. ")
+ playsound(loc, 'sound/items/screwdriver.ogg', 100, 1)
KA.modkits += src
else
- to_chat(user, span_notice("The modkit you're trying to install would conflict with an already installed modkit. Use a crowbar to remove existing modkits."))
+ to_chat(user, "
The modkit you're trying to install would conflict with an already installed modkit. Use a crowbar to remove existing modkits. ")
else
- to_chat(user, span_notice("You don't have room(
[KA.get_remaining_mod_capacity()]% remaining, [cost]% needed) to install this modkit. Use a crowbar to remove existing modkits."))
+ to_chat(user, "
You don't have room([KA.get_remaining_mod_capacity()]% remaining, [cost]% needed) to install this modkit. Use a crowbar to remove existing modkits. ")
. = FALSE
-/obj/item/borg/upgrade/modkit/deactivate(mob/living/silicon/robot/R, user = usr)
- . = ..()
- if (.)
- for(var/obj/item/gun/energy/kinetic_accelerator/KA in R.module.modules)
- uninstall(KA)
-
-/obj/item/borg/upgrade/modkit/proc/uninstall(obj/item/gun/energy/kinetic_accelerator/KA)
+/obj/item/borg/upgrade/modkit/proc/uninstall(obj/item/gun/energy/kinetic_accelerator/KA, forcemove = TRUE)
KA.modkits -= src
+ if(forcemove)
+ forceMove(get_turf(KA))
/obj/item/borg/upgrade/modkit/proc/modify_projectile(obj/item/projectile/kinetic/K)
@@ -461,7 +467,6 @@
/obj/item/borg/upgrade/modkit/minebot_passthrough
name = "minebot passthrough"
desc = "Causes kinetic accelerator shots to pass through minebots."
- denied_type = /obj/item/borg/upgrade/modkit/minebot_passthrough // If you have something cost zero, you can keep adding forever, why
cost = 0
//Tendril-unique modules
diff --git a/html/changelogs/archive/2023-12.yml b/html/changelogs/archive/2023-12.yml
index 5b9f1ffad0..ea5f82e9ad 100644
--- a/html/changelogs/archive/2023-12.yml
+++ b/html/changelogs/archive/2023-12.yml
@@ -34,18 +34,6 @@
- refactor: Small refactor of card code.
- balance: Decreased cost of clothing items in loadout menu, certain items like
modular computers and laptops, and some accessories.
-2023-12-10:
- SandPoot:
- - refactor: Optimizes interaction code.
- - rscadd: Added a print button to the communication console's messages, disabled
- auto-print as well.
-2023-12-11:
- SandPoot:
- - rscadd: Interaction subsystem reports initialized interactions during init.
- - rscadd: Interaction subsystem shows some info at the MC tab.
-2023-12-13:
- SandPoot:
- - tweak: Changed some interaction requirements to make more sense.
2023-12-14:
Anonymous:
- imageadd: 'Added new emojis for the PDA/OOC: clueless, dawgnotdoin, ratdoin, kisser,
diff --git a/modular_sand/code/_globalvars/bitfields.dm b/modular_sand/code/_globalvars/bitfields.dm
index e821b1dc15..7a2bb8d87d 100644
--- a/modular_sand/code/_globalvars/bitfields.dm
+++ b/modular_sand/code/_globalvars/bitfields.dm
@@ -24,48 +24,6 @@ DEFINE_BITFIELD(flags_inv, list(
"HIDEWRISTS" = HIDEWRISTS,
))
-DEFINE_BITFIELD(interaction_flags, list(
- "INTERACTION_FLAG_ADJACENT" = INTERACTION_FLAG_ADJACENT,
- "INTERACTION_FLAG_EXTREME_CONTENT" = INTERACTION_FLAG_EXTREME_CONTENT,
- "INTERACTION_FLAG_OOC_CONSENT" = INTERACTION_FLAG_OOC_CONSENT,
- "INTERACTION_FLAG_TARGET_NOT_TIRED" = INTERACTION_FLAG_TARGET_NOT_TIRED,
- "INTERACTION_FLAG_USER_IS_TARGET" = INTERACTION_FLAG_USER_IS_TARGET,
- "INTERACTION_FLAG_USER_NOT_TIRED" = INTERACTION_FLAG_USER_NOT_TIRED,
-))
-
-DEFINE_BITFIELD(required_from_user, list(
- "INTERACTION_REQUIRE_BOTTOMLESS" = INTERACTION_REQUIRE_BOTTOMLESS,
- "INTERACTION_REQUIRE_HANDS" = INTERACTION_REQUIRE_HANDS,
- "INTERACTION_REQUIRE_MOUTH" = INTERACTION_REQUIRE_MOUTH,
- "INTERACTION_REQUIRE_TOPLESS" = INTERACTION_REQUIRE_TOPLESS,
-))
-
-DEFINE_BITFIELD(required_from_user_exposed, list(
- "INTERACTION_REQUIRE_ANUS" = INTERACTION_REQUIRE_ANUS,
- "INTERACTION_REQUIRE_BALLS" = INTERACTION_REQUIRE_BALLS,
- "INTERACTION_REQUIRE_BREASTS" = INTERACTION_REQUIRE_BREASTS,
- "INTERACTION_REQUIRE_EARS" = INTERACTION_REQUIRE_EARS,
- "INTERACTION_REQUIRE_EARSOCKETS" = INTERACTION_REQUIRE_EARSOCKETS,
- "INTERACTION_REQUIRE_EYES" = INTERACTION_REQUIRE_EYES,
- "INTERACTION_REQUIRE_EYESOCKETS" = INTERACTION_REQUIRE_EYESOCKETS,
- "INTERACTION_REQUIRE_FEET" = INTERACTION_REQUIRE_FEET,
- "INTERACTION_REQUIRE_PENIS" = INTERACTION_REQUIRE_PENIS,
- "INTERACTION_REQUIRE_VAGINA" = INTERACTION_REQUIRE_VAGINA,
-))
-
-DEFINE_BITFIELD(required_from_user_unexposed, list(
- "INTERACTION_REQUIRE_ANUS" = INTERACTION_REQUIRE_ANUS,
- "INTERACTION_REQUIRE_BALLS" = INTERACTION_REQUIRE_BALLS,
- "INTERACTION_REQUIRE_BREASTS" = INTERACTION_REQUIRE_BREASTS,
- "INTERACTION_REQUIRE_EARS" = INTERACTION_REQUIRE_EARS,
- "INTERACTION_REQUIRE_EARSOCKETS" = INTERACTION_REQUIRE_EARSOCKETS,
- "INTERACTION_REQUIRE_EYES" = INTERACTION_REQUIRE_EYES,
- "INTERACTION_REQUIRE_EYESOCKETS" = INTERACTION_REQUIRE_EYESOCKETS,
- "INTERACTION_REQUIRE_FEET" = INTERACTION_REQUIRE_FEET,
- "INTERACTION_REQUIRE_PENIS" = INTERACTION_REQUIRE_PENIS,
- "INTERACTION_REQUIRE_VAGINA" = INTERACTION_REQUIRE_VAGINA,
-))
-
DEFINE_BITFIELD(slot_flags, list(
"ITEM_SLOT_ACCESSORY" = ITEM_SLOT_ACCESSORY,
"ITEM_SLOT_BACK" = ITEM_SLOT_BACK,
@@ -95,39 +53,6 @@ DEFINE_BITFIELD(slot_flags, list(
"ITEM_SLOT_WRISTS" = ITEM_SLOT_WRISTS,
))
-DEFINE_BITFIELD(required_from_target, list(
- "INTERACTION_REQUIRE_BOTTOMLESS" = INTERACTION_REQUIRE_BOTTOMLESS,
- "INTERACTION_REQUIRE_HANDS" = INTERACTION_REQUIRE_HANDS,
- "INTERACTION_REQUIRE_MOUTH" = INTERACTION_REQUIRE_MOUTH,
- "INTERACTION_REQUIRE_TOPLESS" = INTERACTION_REQUIRE_TOPLESS,
-))
-
-DEFINE_BITFIELD(required_from_target_exposed, list(
- "INTERACTION_REQUIRE_ANUS" = INTERACTION_REQUIRE_ANUS,
- "INTERACTION_REQUIRE_BALLS" = INTERACTION_REQUIRE_BALLS,
- "INTERACTION_REQUIRE_BREASTS" = INTERACTION_REQUIRE_BREASTS,
- "INTERACTION_REQUIRE_EARS" = INTERACTION_REQUIRE_EARS,
- "INTERACTION_REQUIRE_EARSOCKETS" = INTERACTION_REQUIRE_EARSOCKETS,
- "INTERACTION_REQUIRE_EYES" = INTERACTION_REQUIRE_EYES,
- "INTERACTION_REQUIRE_EYESOCKETS" = INTERACTION_REQUIRE_EYESOCKETS,
- "INTERACTION_REQUIRE_FEET" = INTERACTION_REQUIRE_FEET,
- "INTERACTION_REQUIRE_PENIS" = INTERACTION_REQUIRE_PENIS,
- "INTERACTION_REQUIRE_VAGINA" = INTERACTION_REQUIRE_VAGINA,
-))
-
-DEFINE_BITFIELD(required_from_target_unexposed, list(
- "INTERACTION_REQUIRE_ANUS" = INTERACTION_REQUIRE_ANUS,
- "INTERACTION_REQUIRE_BALLS" = INTERACTION_REQUIRE_BALLS,
- "INTERACTION_REQUIRE_BREASTS" = INTERACTION_REQUIRE_BREASTS,
- "INTERACTION_REQUIRE_EARS" = INTERACTION_REQUIRE_EARS,
- "INTERACTION_REQUIRE_EARSOCKETS" = INTERACTION_REQUIRE_EARSOCKETS,
- "INTERACTION_REQUIRE_EYES" = INTERACTION_REQUIRE_EYES,
- "INTERACTION_REQUIRE_EYESOCKETS" = INTERACTION_REQUIRE_EYESOCKETS,
- "INTERACTION_REQUIRE_FEET" = INTERACTION_REQUIRE_FEET,
- "INTERACTION_REQUIRE_PENIS" = INTERACTION_REQUIRE_PENIS,
- "INTERACTION_REQUIRE_VAGINA" = INTERACTION_REQUIRE_VAGINA,
-))
-
DEFINE_BITFIELD(vis_flags_inv, list(
"HIDEACCESSORY" = HIDEACCESSORY,
"HIDEEARS" = HIDEEARS,
diff --git a/modular_sand/code/controllers/subsystem/interactions.dm b/modular_sand/code/controllers/subsystem/interactions.dm
index 9c4aa05006..dee26167c3 100644
--- a/modular_sand/code/controllers/subsystem/interactions.dm
+++ b/modular_sand/code/controllers/subsystem/interactions.dm
@@ -26,14 +26,6 @@ SUBSYSTEM_DEF(interactions)
/datum/controller/subsystem/interactions/Initialize(timeofday)
prepare_interactions()
prepare_blacklisted_mobs()
- . = ..()
- var/extra_info = "
↳ Loaded [LAZYLEN(interactions)] interactions!"
- to_chat(world, span_boldannounce(extra_info))
- log_subsystem(src, extra_info)
-
-/datum/controller/subsystem/interactions/stat_entry(msg)
- msg += "|🖐:[LAZYLEN(interactions)]|"
- msg += "🚫👨:[LAZYLEN(blacklisted_mobs)]"
return ..()
/// Makes the interactions, they're also a global list because having it as a list and just hanging around there is stupid
diff --git a/modular_sand/code/datums/components/interaction_menu_granter.dm b/modular_sand/code/datums/components/interaction_menu_granter.dm
index 0790bb825e..9d1253001a 100644
--- a/modular_sand/code/datums/components/interaction_menu_granter.dm
+++ b/modular_sand/code/datums/components/interaction_menu_granter.dm
@@ -41,8 +41,6 @@
/datum/component/interaction_menu_granter/UnregisterFromParent()
UnregisterSignal(parent, COMSIG_MOB_CTRLSHIFTCLICKON)
- if(target)
- UnregisterSignal(target, COMSIG_PARENT_QDELETING)
. = ..()
/// The one interacting is clicker, the interacted is clicked.
@@ -53,20 +51,10 @@
// Don't cancel admin quick spawn
if(isobserver(clicked) && check_rights_for(clicker.client, R_SPAWN))
return FALSE
- // Changing targets!!
- if(target)
- UnregisterSignal(target, COMSIG_PARENT_QDELETING)
target = clicked
- RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/on_target_deleted)
ui_interact(clicker)
return COMSIG_MOB_CANCEL_CLICKON
-/// Such a shame
-/datum/component/interaction_menu_granter/proc/on_target_deleted(datum/source, ...)
- UnregisterSignal(target, COMSIG_PARENT_QDELETING)
- target = null
- SStgui.close_user_uis(parent, src)
-
/datum/component/interaction_menu_granter/ui_state(mob/user)
// Funny admin, don't you dare be the extra funny now.
if(user.client.holder && !user.client.holder.deadmined)
@@ -100,247 +88,35 @@
.["selfAttributes"] = self.list_interaction_attributes(self)
.["lust"] = self.get_lust()
.["maxLust"] = self.get_lust_tolerance() * 3
-
- .["max_distance"] = 0
- .["user_is_blacklisted"] = SSinteractions.is_blacklisted(self)
- var/required_from_user = NONE
- if(self.has_mouth())
- required_from_user |= INTERACTION_REQUIRE_MOUTH
- if(self.has_hands())
- required_from_user |= INTERACTION_REQUIRE_HANDS
- if(self.is_topless())
- required_from_user |= INTERACTION_REQUIRE_TOPLESS
- if(self.is_bottomless())
- required_from_user |= INTERACTION_REQUIRE_BOTTOMLESS
- .["required_from_user"] = required_from_user
-
- var/required_from_user_exposed = NONE
- var/required_from_user_unexposed = NONE
-
- var/user_has_penis = self.has_penis()
- switch(user_has_penis)
- if(HAS_EXPOSED_GENITAL)
- required_from_user_exposed |= INTERACTION_REQUIRE_PENIS
- if(HAS_UNEXPOSED_GENITAL)
- required_from_user_unexposed |= INTERACTION_REQUIRE_PENIS
- if(TRUE)
- required_from_user_exposed |= INTERACTION_REQUIRE_PENIS
- required_from_user_unexposed |= INTERACTION_REQUIRE_PENIS
-
- var/user_has_anus = self.has_anus()
- switch(user_has_anus)
- if(HAS_EXPOSED_GENITAL)
- required_from_user_exposed |= INTERACTION_REQUIRE_ANUS
- if(HAS_UNEXPOSED_GENITAL)
- required_from_user_unexposed |= INTERACTION_REQUIRE_ANUS
- if(TRUE)
- required_from_user_exposed |= INTERACTION_REQUIRE_ANUS
- required_from_user_unexposed |= INTERACTION_REQUIRE_ANUS
-
- var/user_has_vagina = self.has_vagina()
- switch(user_has_vagina)
- if(HAS_EXPOSED_GENITAL)
- required_from_user_exposed |= INTERACTION_REQUIRE_VAGINA
- if(HAS_UNEXPOSED_GENITAL)
- required_from_user_unexposed |= INTERACTION_REQUIRE_VAGINA
- if(TRUE)
- required_from_user_exposed |= INTERACTION_REQUIRE_VAGINA
- required_from_user_unexposed |= INTERACTION_REQUIRE_VAGINA
-
- var/user_has_breasts = self.has_breasts()
- switch(user_has_breasts)
- if(HAS_EXPOSED_GENITAL)
- required_from_user_exposed |= INTERACTION_REQUIRE_BREASTS
- if(HAS_UNEXPOSED_GENITAL)
- required_from_user_unexposed |= INTERACTION_REQUIRE_BREASTS
- if(TRUE)
- required_from_user_exposed |= INTERACTION_REQUIRE_BREASTS
- required_from_user_unexposed |= INTERACTION_REQUIRE_BREASTS
-
- var/user_has_feet = self.has_feet()
- switch(user_has_feet)
- if(HAS_EXPOSED_GENITAL)
- required_from_user_exposed |= INTERACTION_REQUIRE_FEET
- if(HAS_UNEXPOSED_GENITAL)
- required_from_user_unexposed |= INTERACTION_REQUIRE_FEET
- if(TRUE)
- required_from_user_exposed |= INTERACTION_REQUIRE_FEET
- required_from_user_unexposed |= INTERACTION_REQUIRE_FEET
-
- var/user_has_balls = self.has_balls()
- switch(user_has_balls)
- if(HAS_EXPOSED_GENITAL)
- required_from_user_exposed |= INTERACTION_REQUIRE_BALLS
- if(HAS_UNEXPOSED_GENITAL)
- required_from_user_unexposed |= INTERACTION_REQUIRE_BALLS
- if(TRUE)
- required_from_user_exposed |= INTERACTION_REQUIRE_BALLS
- required_from_user_unexposed |= INTERACTION_REQUIRE_BALLS
-
- var/user_has_ears = self.has_ears()
- if(self.getorganslot(ORGAN_SLOT_EARS))
- switch(user_has_ears)
- if(HAS_EXPOSED_GENITAL)
- required_from_user_exposed |= INTERACTION_REQUIRE_EARS
- if(HAS_UNEXPOSED_GENITAL)
- required_from_user_unexposed |= INTERACTION_REQUIRE_EARS
- else
- switch(user_has_ears)
- if(HAS_EXPOSED_GENITAL)
- required_from_user_exposed |= INTERACTION_REQUIRE_EARSOCKETS
- if(HAS_UNEXPOSED_GENITAL)
- required_from_user_unexposed |= INTERACTION_REQUIRE_EARSOCKETS
-
- var/user_has_eyes = self.has_eyes()
- if(self.getorganslot(ORGAN_SLOT_EYES))
- switch(user_has_eyes)
- if(HAS_EXPOSED_GENITAL)
- required_from_user_exposed |= INTERACTION_REQUIRE_EYES
- if(HAS_UNEXPOSED_GENITAL)
- required_from_user_unexposed |= INTERACTION_REQUIRE_EYES
- else
- switch(user_has_eyes)
- if(HAS_EXPOSED_GENITAL)
- required_from_user_exposed |= INTERACTION_REQUIRE_EYESOCKETS
- if(HAS_UNEXPOSED_GENITAL)
- required_from_user_unexposed |= INTERACTION_REQUIRE_EYESOCKETS
-
- .["required_from_user_exposed"] = required_from_user_exposed
- .["required_from_user_unexposed"] = required_from_user_unexposed
- .["user_num_feet"] = self.get_num_feet()
-
- // Let's clear it in case the user goes directly from interacting with someone to themself
- .["theirAttributes"] = null
- .["target_has_active_player"] = null
- .["max_distance"] = null
- .["target_is_blacklisted"] = null
- .["required_from_target"] = null
- .["required_from_target_exposed"] = null
- .["required_from_target_unexposed"] = null
- .["target_num_feet"] = null
- .["theirPrefs"] = null
- .["theirLust"] = null
- .["theyAllowLewd"] = null
- .["theyAllowExtreme"] = null
if(target != self)
.["theirAttributes"] = target.list_interaction_attributes(self)
-
- // Always TRUE if has key, 2 if cliented, FALSE if nobody owns it
- .["target_has_active_player"] = target.ckey ? (target.client ? 2 : TRUE) : FALSE
- .["max_distance"] = get_dist(self, target)
- .["target_is_blacklisted"] = SSinteractions.is_blacklisted(target)
- var/required_from_target = NONE
- if(target.has_mouth())
- required_from_target |= INTERACTION_REQUIRE_MOUTH
- if(target.has_hands())
- required_from_target |= INTERACTION_REQUIRE_HANDS
- if(target.is_topless())
- required_from_target |= INTERACTION_REQUIRE_TOPLESS
- if(target.is_bottomless())
- required_from_target |= INTERACTION_REQUIRE_BOTTOMLESS
- .["required_from_target"] = required_from_target
-
- var/required_from_target_exposed = NONE
- var/required_from_target_unexposed = NONE
-
- var/target_has_penis = target.has_penis()
- switch(target_has_penis)
- if(HAS_EXPOSED_GENITAL)
- required_from_target_exposed |= INTERACTION_REQUIRE_PENIS
- if(HAS_UNEXPOSED_GENITAL)
- required_from_target_unexposed |= INTERACTION_REQUIRE_PENIS
- if(TRUE)
- required_from_target_exposed |= INTERACTION_REQUIRE_PENIS
- required_from_target_unexposed |= INTERACTION_REQUIRE_PENIS
-
- var/target_has_anus = target.has_anus()
- switch(target_has_anus)
- if(HAS_EXPOSED_GENITAL)
- required_from_target_exposed |= INTERACTION_REQUIRE_ANUS
- if(HAS_UNEXPOSED_GENITAL)
- required_from_target_unexposed |= INTERACTION_REQUIRE_ANUS
- if(TRUE)
- required_from_target_exposed |= INTERACTION_REQUIRE_ANUS
- required_from_target_unexposed |= INTERACTION_REQUIRE_ANUS
-
- var/target_has_vagina = target.has_vagina()
- switch(target_has_vagina)
- if(HAS_EXPOSED_GENITAL)
- required_from_target_exposed |= INTERACTION_REQUIRE_VAGINA
- if(HAS_UNEXPOSED_GENITAL)
- required_from_target_unexposed |= INTERACTION_REQUIRE_VAGINA
- if(TRUE)
- required_from_target_exposed |= INTERACTION_REQUIRE_VAGINA
- required_from_target_unexposed |= INTERACTION_REQUIRE_VAGINA
-
- var/target_has_breasts = target.has_breasts()
- switch(target_has_breasts)
- if(HAS_EXPOSED_GENITAL)
- required_from_target_exposed |= INTERACTION_REQUIRE_BREASTS
- if(HAS_UNEXPOSED_GENITAL)
- required_from_target_unexposed |= INTERACTION_REQUIRE_BREASTS
- if(TRUE)
- required_from_target_exposed |= INTERACTION_REQUIRE_BREASTS
- required_from_target_unexposed |= INTERACTION_REQUIRE_BREASTS
-
- var/target_has_feet = target.has_feet()
- switch(target_has_feet)
- if(HAS_EXPOSED_GENITAL)
- required_from_target_exposed |= INTERACTION_REQUIRE_FEET
- if(HAS_UNEXPOSED_GENITAL)
- required_from_target_unexposed |= INTERACTION_REQUIRE_FEET
- if(TRUE)
- required_from_target_exposed |= INTERACTION_REQUIRE_FEET
- required_from_target_unexposed |= INTERACTION_REQUIRE_FEET
-
- var/target_has_balls = target.has_balls()
- switch(target_has_balls)
- if(HAS_EXPOSED_GENITAL)
- required_from_target_exposed |= INTERACTION_REQUIRE_BALLS
- if(HAS_UNEXPOSED_GENITAL)
- required_from_target_unexposed |= INTERACTION_REQUIRE_BALLS
- if(TRUE)
- required_from_target_exposed |= INTERACTION_REQUIRE_BALLS
- required_from_target_unexposed |= INTERACTION_REQUIRE_BALLS
-
- var/target_has_ears = target.has_ears()
- if(target.getorganslot(ORGAN_SLOT_EARS))
- switch(target_has_ears)
- if(HAS_EXPOSED_GENITAL)
- required_from_target_exposed |= INTERACTION_REQUIRE_EARS
- if(HAS_UNEXPOSED_GENITAL)
- required_from_target_unexposed |= INTERACTION_REQUIRE_EARS
- else
- switch(target_has_ears)
- if(HAS_EXPOSED_GENITAL)
- required_from_target_exposed |= INTERACTION_REQUIRE_EARSOCKETS
- if(HAS_UNEXPOSED_GENITAL)
- required_from_target_unexposed |= INTERACTION_REQUIRE_EARSOCKETS
-
- var/target_has_eyes = target.has_eyes()
- if(target.getorganslot(ORGAN_SLOT_EYES))
- switch(target_has_eyes)
- if(HAS_EXPOSED_GENITAL)
- required_from_target_exposed |= INTERACTION_REQUIRE_EYES
- if(HAS_UNEXPOSED_GENITAL)
- required_from_target_unexposed |= INTERACTION_REQUIRE_EYES
- else
- switch(target_has_eyes)
- if(HAS_EXPOSED_GENITAL)
- required_from_target_exposed |= INTERACTION_REQUIRE_EYESOCKETS
- if(HAS_UNEXPOSED_GENITAL)
- required_from_target_unexposed |= INTERACTION_REQUIRE_EYESOCKETS
-
- .["required_from_target_exposed"] = required_from_target_exposed
- .["required_from_target_unexposed"] = required_from_target_unexposed
- .["target_num_feet"] = target.get_num_feet()
- if(target?.client?.prefs)
- .["theyAllowLewd"] = !!(target.client.prefs.toggles & VERB_CONSENT)
- .["theyAllowExtreme"] = !!pref_to_num(target.client.prefs.extremepref)
if(HAS_TRAIT(user, TRAIT_ESTROUS_DETECT))
.["theirLust"] = target.get_lust()
.["theirMaxLust"] = target.get_lust_tolerance() * 3
+ //Getting interactions
+ var/list/sent_interactions = list()
+ for(var/interaction_key in SSinteractions.interactions)
+ var/datum/interaction/I = SSinteractions.interactions[interaction_key]
+ if(I.evaluate_user(self, action_check = FALSE) && I.evaluate_target(self, target))
+ if(I.user_is_target && target != self)
+ continue
+ var/list/interaction = list()
+ interaction["key"] = I.type
+ var/description = replacetext(I.description, "%COCK%", self.has_penis() ? "cock" : "strapon")
+ interaction["desc"] = description
+ if(istype(I, /datum/interaction/lewd))
+ var/datum/interaction/lewd/O = I
+ if(O.extreme)
+ interaction["type"] = INTERACTION_EXTREME
+ else
+ interaction["type"] = INTERACTION_LEWD
+ else
+ interaction["type"] = INTERACTION_NORMAL
+ interaction["additionalDetails"] = I.additional_details
+ sent_interactions += list(interaction)
+ .["interactions"] = sent_interactions
+
//Get their genitals
var/list/genitals = list()
var/mob/living/carbon/get_genitals = self
@@ -425,40 +201,6 @@
.["edging_pref"] = !!CHECK_BITFIELD(prefs.cit_toggles, EDGING)
.["cum_onto_pref"] = !!CHECK_BITFIELD(prefs.cit_toggles, CUM_ONTO)
-/datum/component/interaction_menu_granter/ui_static_data(mob/user)
- . = ..()
- //Getting interactions
- var/list/sent_interactions = list()
- for(var/interaction_key in SSinteractions.interactions)
- var/datum/interaction/I = SSinteractions.interactions[interaction_key]
- var/list/interaction = list()
- interaction["key"] = I.type
- interaction["desc"] = I.description
- if(istype(I, /datum/interaction/lewd))
- var/datum/interaction/lewd/O = I
- if(O.interaction_flags & INTERACTION_FLAG_EXTREME_CONTENT)
- interaction["type"] = INTERACTION_EXTREME
- else
- interaction["type"] = INTERACTION_LEWD
- interaction["require_user_num_feet"] = O.require_user_num_feet
- interaction["require_target_num_feet"] = O.require_target_num_feet
- else
- interaction["type"] = INTERACTION_NORMAL
- interaction["maxDistance"] = I.max_distance
-
- interaction["interactionFlags"] = I.interaction_flags
-
- interaction["required_from_user"] = I.required_from_user
- interaction["required_from_user_exposed"] = I.required_from_user_exposed
- interaction["required_from_user_unexposed"] = I.required_from_user_unexposed
-
- interaction["required_from_target"] = I.required_from_target
- interaction["required_from_target_exposed"] = I.required_from_target_exposed
- interaction["required_from_target_unexposed"] = I.required_from_target_unexposed
- interaction["additionalDetails"] = I.additional_details
- sent_interactions += list(interaction)
- .["interactions"] = sent_interactions
-
/proc/num_to_pref(num)
switch(num)
if(1)
diff --git a/modular_sand/code/datums/interactions/_interaction.dm b/modular_sand/code/datums/interactions/_interaction.dm
index fefb51e55f..28d6c4e441 100644
--- a/modular_sand/code/datums/interactions/_interaction.dm
+++ b/modular_sand/code/datums/interactions/_interaction.dm
@@ -31,16 +31,14 @@
var/interaction_sound
var/max_distance = 1
+ var/require_ooc_consent = FALSE
+ var/require_user_mouth
+ var/require_user_hands
+ var/require_target_mouth
+ var/require_target_hands
+ var/needs_physical_contact
- var/interaction_flags = INTERACTION_FLAG_ADJACENT
-
- var/required_from_user = NONE
- var/required_from_user_exposed = NONE
- var/required_from_user_unexposed = NONE
-
- var/required_from_target = NONE
- var/required_from_target_exposed = NONE
- var/required_from_target_unexposed = NONE
+ var/user_is_target = FALSE //Boolean. Pretty self explanatory.
/// Refuses to accept more than one entry for some reason, fix sometime
var/list/additional_details
@@ -50,22 +48,21 @@
if(SSinteractions.is_blacklisted(user))
return FALSE
- if(required_from_user & INTERACTION_REQUIRE_MOUTH)
- if(!user.has_mouth())
+ if(require_user_mouth)
+ if(!user.has_mouth() && !issilicon(user)) //Again, silicons do not have the required parts normally.
if(!silent)
to_chat(user, span_warning("You don't have a mouth."))
return FALSE
- if(!user.mouth_is_free())
+ if(!user.mouth_is_free() && !issilicon(user)) //Borgs cannot wear mouthgear, bypassing the check.
if(!silent)
to_chat(user, span_warning("Your mouth is covered."))
return FALSE
- if(required_from_user & INTERACTION_REQUIRE_HANDS)
- if(!user.has_hands())
- if(!silent)
- to_chat(user, span_warning("You don't have hands."))
- return FALSE
+ if(require_user_hands && !user.has_hands() && !issilicon(user)) //Edited to allow silicons to interact.
+ if(!silent)
+ to_chat(user, span_warning("You don't have hands."))
+ return FALSE
if(COOLDOWN_FINISHED(user, last_interaction_time))
return TRUE
@@ -80,41 +77,40 @@
if(SSinteractions.is_blacklisted(target))
return FALSE
- if(!(interaction_flags & INTERACTION_FLAG_USER_IS_TARGET))
+ if(!user_is_target)
if(user == target)
if(!silent)
- to_chat(user, span_warning("You can't do that to yourself."))
+ to_chat(user, "
You can't do that to yourself. ")
return FALSE
- if(required_from_target & INTERACTION_REQUIRE_MOUTH)
+ if(require_target_mouth)
if(!target.has_mouth())
if(!silent)
- to_chat(user, span_warning("They don't have a mouth."))
+ to_chat(user, "
They don't have a mouth. ")
return FALSE
- if(!target.mouth_is_free())
+ if(!target.mouth_is_free() && !issilicon(target))
if(!silent)
- to_chat(user, span_warning("Their mouth is covered."))
+ to_chat(user, "
Their mouth is covered. ")
return FALSE
- if(required_from_target & INTERACTION_REQUIRE_HANDS)
- if(!target.has_hands())
- if(!silent)
- to_chat(user, span_warning("They don't have hands."))
- return FALSE
+ if(require_target_hands && !target.has_hands() && !issilicon(target))
+ if(!silent)
+ to_chat(user, "
They don't have hands. ")
+ return FALSE
return TRUE
/// Actually doing the action, has a few checks to see if it's valid, usually overwritten to be make things actually happen and what-not
/datum/interaction/proc/do_action(mob/living/user, mob/living/target)
- if(!(interaction_flags & INTERACTION_FLAG_USER_IS_TARGET))
+ if(!user_is_target)
if(user == target) //tactical href fix
to_chat(user, span_warning("You cannot target yourself."))
return
if(get_dist(user, target) > max_distance)
to_chat(user, span_warning("They are too far away."))
return
- if(interaction_flags & INTERACTION_FLAG_ADJACENT && !(user.Adjacent(target) && target.Adjacent(user)))
+ if(needs_physical_contact && !(user.Adjacent(target) && target.Adjacent(user)))
to_chat(user, span_warning("You cannot get to them."))
return
if(!evaluate_user(user, silent = FALSE))
diff --git a/modular_sand/code/datums/interactions/interaction_datums/interaction_definitions.dm b/modular_sand/code/datums/interactions/interaction_datums/interaction_definitions.dm
index e325ac45fb..486c91e04d 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/interaction_definitions.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/interaction_definitions.dm
@@ -1,60 +1,60 @@
/datum/interaction/handshake
description = "Shake their hand."
simple_message = "USER shakes the hand of TARGET."
- required_from_user = INTERACTION_REQUIRE_HANDS
- required_from_target = INTERACTION_REQUIRE_HANDS
+ require_user_hands = TRUE
+ needs_physical_contact = TRUE
/datum/interaction/pat
description = "Pat their shoulder."
simple_message = "USER pats TARGET's shoulder."
- required_from_user = INTERACTION_REQUIRE_HANDS
+ require_user_hands = TRUE
+ needs_physical_contact = TRUE
/datum/interaction/cheer
description = "Cheer them on."
- required_from_user = INTERACTION_REQUIRE_MOUTH
+ require_user_mouth = TRUE
simple_message = "USER cheers TARGET on!"
- interaction_flags = NONE
/datum/interaction/highfive
description = "Give them a high-five."
+ require_user_mouth = TRUE
simple_message = "USER high fives TARGET!"
interaction_sound = 'modular_sand/sound/interactions/slap.ogg'
- required_from_user = INTERACTION_REQUIRE_HANDS
- required_from_target = INTERACTION_REQUIRE_HANDS
+ needs_physical_contact = TRUE
/datum/interaction/headpat
description = "Pat their head. Aww..."
+ require_user_hands = TRUE
simple_message = "USER headpats TARGET!"
- required_from_user = INTERACTION_REQUIRE_HANDS
+ needs_physical_contact = TRUE
/datum/interaction/salute
description = "Give them a firm salute!"
+ require_user_hands = TRUE
simple_message = "USER salutes TARGET sharply!"
- required_from_user = INTERACTION_REQUIRE_HANDS
max_distance = 25
- interaction_flags = NONE
/datum/interaction/fistbump
description = "Bump it!"
+ require_user_hands = TRUE
simple_message = "USER fistbumps TARGET! Yeah!"
- required_from_user = INTERACTION_REQUIRE_HANDS
- required_from_target = INTERACTION_REQUIRE_HANDS
+ needs_physical_contact = TRUE
/datum/interaction/pinkypromise
description = "Make a pinky promise with them!"
+ require_user_hands = TRUE
simple_message = "USER hooks their pinky with TARGET's! Pinky Promise!"
- required_from_user = INTERACTION_REQUIRE_HANDS
- required_from_target = INTERACTION_REQUIRE_HANDS
+ needs_physical_contact = TRUE
/datum/interaction/bird
description = "Flip them the bird!"
+ require_user_hands = TRUE
simple_message = "USER gives TARGET the bird!"
- required_from_user = INTERACTION_REQUIRE_HANDS
max_distance = 25
- interaction_flags = NONE
/datum/interaction/holdhand
description = "Hold their hand."
+ require_user_hands = TRUE
simple_message = "USER holds TARGET's hand."
- required_from_user = INTERACTION_REQUIRE_HANDS
- required_from_target = INTERACTION_REQUIRE_HANDS
+ needs_physical_contact = TRUE
+ max_distance = 25
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/breasts.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/breasts.dm
index b3d662ac75..258e012e15 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/breasts.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/breasts.dm
@@ -1,7 +1,8 @@
/datum/interaction/lewd/do_breastfeed
- description = "Breastfeed them"
- required_from_user_exposed = INTERACTION_REQUIRE_BREASTS
- required_from_target = INTERACTION_REQUIRE_MOUTH
+ description = "Breastfeed them."
+ require_user_breasts = REQUIRE_EXPOSED
+ require_target_mouth = TRUE
+ max_distance = 1
write_log_user = "breastfed"
write_log_target = "was breastfed by"
interaction_sound = null
@@ -48,12 +49,12 @@
/datum/interaction/lewd/titgrope
description = "Grope their breasts."
- required_from_user = INTERACTION_REQUIRE_HANDS
- required_from_target_exposed = INTERACTION_REQUIRE_BREASTS
- required_from_target_unexposed = INTERACTION_REQUIRE_BREASTS
+ require_user_hands = TRUE
+ require_target_breasts = REQUIRE_ANY
write_log_user = "groped"
write_log_target = "was groped by"
interaction_sound = null
+ max_distance = 1
additional_details = list(
list(
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/earfuck.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/earfuck.dm
index df10e5e5c2..390e44a7a5 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/earfuck.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/earfuck.dm
@@ -1,15 +1,17 @@
/datum/interaction/lewd/earfuck
description = "Fuck their ear."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_PENIS
- required_from_target_exposed = INTERACTION_REQUIRE_EARS
- interaction_flags = INTERACTION_FLAG_ADJACENT | INTERACTION_FLAG_OOC_CONSENT | INTERACTION_FLAG_EXTREME_CONTENT
+ require_user_penis = REQUIRE_EXPOSED
+ require_target_ears = REQUIRE_EXPOSED
+ max_distance = 1
write_log_user = "earfucked"
write_log_target = "had their ear fucked by"
+ extreme = TRUE
/datum/interaction/lewd/earfuck/earsocketfuck
description = "Fuck their earsocket."
- required_from_target_exposed = INTERACTION_REQUIRE_EARSOCKETS
+ require_target_ears = null
+ require_target_earsockets = REQUIRE_EXPOSED
write_log_user = "earsocket fucked"
write_log_target = "had their earsocket fucked by"
@@ -39,7 +41,7 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/champ1.ogg',
'modular_sand/sound/interactions/champ2.ogg'), 50, 1, -1)
- user.visible_message(message = span_lewd("
\The [user] [message]"), ignored_mobs = user.get_unconsenting(interaction_flags))
+ user.visible_message(message = span_lewd("
\The [user] [message]"), ignored_mobs = user.get_unconsenting(TRUE))
if(user.can_penetrating_genital_cum())
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_EARS, partner, ORGAN_SLOT_PENIS) //SPLURT edit
partner.handle_post_sex(LOW_LUST, null, user)
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/eyefuck.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/eyefuck.dm
index e2c31c8549..f4005a6083 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/eyefuck.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/eyefuck.dm
@@ -1,15 +1,17 @@
/datum/interaction/lewd/eyefuck
description = "Fuck their eye."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_PENIS
- required_from_target_exposed = INTERACTION_REQUIRE_EYES
- interaction_flags = INTERACTION_FLAG_ADJACENT | INTERACTION_FLAG_OOC_CONSENT | INTERACTION_FLAG_EXTREME_CONTENT
+ require_user_penis = REQUIRE_EXPOSED
+ require_target_eyes = REQUIRE_EXPOSED
+ max_distance = 1
write_log_user = "eyefucked"
write_log_target = "had their eye fucked by"
+ extreme = TRUE
/datum/interaction/lewd/eyefuck/eyesocketfuck
description = "Fuck their eyesocket."
- required_from_target_exposed = INTERACTION_REQUIRE_EYESOCKETS
+ require_target_eyes = null
+ require_target_eyesockets = REQUIRE_EXPOSED
write_log_user = "eyesocketfucked"
write_log_target = "had their eyesocket fucked by"
@@ -39,7 +41,7 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/champ1.ogg',
'modular_sand/sound/interactions/champ2.ogg'), 50, 1, -1)
- user.visible_message(span_lewd("
\The [user] [message]"), ignored_mobs = user.get_unconsenting(interaction_flags))
+ user.visible_message(span_lewd("
\The [user] [message]"), ignored_mobs = user.get_unconsenting(TRUE))
if(user.can_penetrating_genital_cum())
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_EYES, partner, ORGAN_SLOT_PENIS) //SPLURT edit
partner.handle_post_sex(LOW_LUST, null, user)
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/facefuck.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/facefuck.dm
index 2ef46e07de..963478fdc4 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/facefuck.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/facefuck.dm
@@ -1,13 +1,15 @@
/datum/interaction/lewd/facefuck
description = "Fuck their mouth using your %COCK%."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_PENIS
- required_from_target = INTERACTION_REQUIRE_MOUTH
+ require_target_mouth = TRUE
+ require_user_penis = REQUIRE_EXPOSED
+ max_distance = 1
var/fucktarget = "penis"
/datum/interaction/lewd/facefuck/vag
- description = "Fuck their mouth using your vagina"
- required_from_user_exposed = INTERACTION_REQUIRE_VAGINA
+ description = "Fuck their mouth using your vagina."
+ require_user_penis = null
+ require_user_vagina = REQUIRE_EXPOSED
fucktarget = "vagina"
/datum/interaction/lewd/facefuck/display_interaction(mob/living/user, mob/living/partner)
@@ -18,7 +20,7 @@
var/u_His = user.p_their()
var/t_Him = partner.p_them()
var/t_Hes = partner.p_theyre()
-
+
if(user.is_fucking(partner, CUM_TARGET_MOUTH))
var/improv = FALSE
switch(fucktarget)
@@ -112,8 +114,9 @@
/datum/interaction/lewd/throatfuck
description = "Fuck their throat. | Does oxy damage."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_PENIS
- required_from_target = INTERACTION_REQUIRE_MOUTH
+ require_user_penis = REQUIRE_EXPOSED
+ require_target_mouth = TRUE
+ max_distance = 1
/datum/interaction/lewd/throatfuck/display_interaction(mob/living/user, mob/living/partner)
var/message
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/feet.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/feet.dm
index 79ba8552ac..7d933864fe 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/feet.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/feet.dm
@@ -1,10 +1,10 @@
/datum/interaction/lewd/grindface
description = "Feet grind their face."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_FEET
- required_from_user_unexposed = INTERACTION_REQUIRE_FEET
+ require_target_mouth = TRUE
require_user_num_feet = 1
- required_from_target = INTERACTION_REQUIRE_MOUTH
+ require_user_feet = REQUIRE_ANY
+ max_distance = 1
/datum/interaction/lewd/grindface/display_interaction(mob/living/user, mob/living/partner)
var/message
@@ -56,10 +56,10 @@
/datum/interaction/lewd/grindmouth
description = "Feet grind their mouth."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_FEET
- required_from_user_unexposed = INTERACTION_REQUIRE_FEET
+ require_target_mouth = TRUE
require_user_num_feet = 1
- required_from_target = INTERACTION_REQUIRE_MOUTH
+ require_user_feet = REQUIRE_ANY
+ max_distance = 1
/datum/interaction/lewd/grindmouth/display_interaction(mob/living/user, mob/living/partner)
var/message
@@ -111,10 +111,10 @@
/datum/interaction/lewd/footjob
description = "Jerk them off with your foot."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_FEET
- required_from_user_unexposed = INTERACTION_REQUIRE_FEET
require_user_num_feet = 1
- required_from_target_exposed = INTERACTION_REQUIRE_PENIS
+ require_user_feet = REQUIRE_ANY
+ require_target_penis = REQUIRE_EXPOSED
+ max_distance = 1
/datum/interaction/lewd/footjob/display_interaction(mob/living/user, mob/living/partner)
var/message
@@ -169,7 +169,8 @@
/datum/interaction/lewd/footjob/vagina
description = "Rub their vagina with your foot."
- required_from_target_exposed = INTERACTION_REQUIRE_VAGINA
+ require_target_vagina = REQUIRE_EXPOSED
+ require_target_penis = null
/datum/interaction/lewd/footjob/vagina/display_interaction(mob/living/user, mob/living/partner)
var/message
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/finger.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/finger.dm
index a785f5ca53..6a9adac908 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/finger.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/finger.dm
@@ -1,8 +1,9 @@
/datum/interaction/lewd/finger
description = "Finger their pussy."
- required_from_user = INTERACTION_REQUIRE_HANDS
- required_from_target_exposed = INTERACTION_REQUIRE_VAGINA
+ require_user_hands = TRUE
+ require_target_vagina = REQUIRE_EXPOSED
interaction_sound = null
+ max_distance = 1
additional_details = list(
list(
@@ -40,8 +41,9 @@
/datum/interaction/lewd/fingerass
description = "Finger their ass."
interaction_sound = null
- required_from_user = INTERACTION_REQUIRE_HANDS
- required_from_target_exposed = INTERACTION_REQUIRE_ANUS
+ require_user_hands = TRUE
+ require_target_anus = REQUIRE_EXPOSED
+ max_distance = 1
/datum/interaction/lewd/fingerass/display_interaction(mob/living/user, mob/living/partner)
user.visible_message("
\The [user] [pick("fingers \the [partner] .",
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/frotting.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/frotting.dm
index 4859d6b72f..621f534908 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/frotting.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/frotting.dm
@@ -1,7 +1,8 @@
/datum/interaction/lewd/frotting
- description = "Rub your penis against theirs"
- required_from_user_exposed = INTERACTION_REQUIRE_PENIS
- required_from_target_exposed = INTERACTION_REQUIRE_PENIS
+ description = "Rub your %COCK% against theirs"
+ require_user_penis = REQUIRE_EXPOSED
+ require_target_penis = REQUIRE_EXPOSED
+ max_distance = 1
write_log_user = "frotted"
write_log_target = "was frotted by"
interaction_sound = null
@@ -22,8 +23,9 @@
/datum/interaction/lewd/tribadism
description = "Grind your pussy against theirs."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_VAGINA
- required_from_target_exposed = INTERACTION_REQUIRE_VAGINA
+ require_target_vagina = REQUIRE_EXPOSED
+ require_user_vagina = REQUIRE_EXPOSED
+ max_distance = 1
/datum/interaction/lewd/tribadism/display_interaction(mob/living/user, mob/living/partner)
var/message
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/fuck.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/fuck.dm
index d40743eceb..460812fd4b 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/fuck.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/fuck.dm
@@ -1,10 +1,11 @@
/datum/interaction/lewd/fuck
description = "Fuck their pussy."
- required_from_user_exposed = INTERACTION_REQUIRE_PENIS
- required_from_target_exposed = INTERACTION_REQUIRE_VAGINA
+ require_user_penis = REQUIRE_EXPOSED
+ require_target_vagina = REQUIRE_EXPOSED
write_log_user = "fucked"
write_log_target = "was fucked by"
interaction_sound = null
+ max_distance = 1
/datum/interaction/lewd/fuck/display_interaction(mob/living/user, mob/living/partner)
var/message
@@ -30,7 +31,8 @@
/datum/interaction/lewd/fuck/anal
description = "Fuck their ass."
- required_from_target_exposed = INTERACTION_REQUIRE_ANUS
+ require_target_vagina = null
+ require_target_anus = REQUIRE_EXPOSED
/datum/interaction/lewd/fuck/anal/display_interaction(mob/living/user, mob/living/partner)
var/message
@@ -62,8 +64,9 @@
/datum/interaction/lewd/breastfuck
description = "Fuck their breasts."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_PENIS
- required_from_target_exposed = INTERACTION_REQUIRE_BREASTS
+ require_user_penis = REQUIRE_EXPOSED
+ require_target_breasts = REQUIRE_EXPOSED
+ max_distance = 1
/datum/interaction/lewd/breastfuck/display_interaction(mob/living/user, mob/living/partner)
var/message
@@ -90,10 +93,10 @@
/datum/interaction/lewd/footfuck
description = "Rub your %COCK% on their foot."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_PENIS
- required_from_target_exposed = INTERACTION_REQUIRE_FEET
- required_from_target_unexposed = INTERACTION_REQUIRE_FEET
require_target_num_feet = 1
+ require_target_feet = REQUIRE_ANY
+ require_user_penis = REQUIRE_EXPOSED
+ max_distance = 1
/datum/interaction/lewd/footfuck/display_interaction(mob/living/user, mob/living/partner)
var/message
@@ -152,8 +155,11 @@
/datum/interaction/lewd/footfuck/vag
description = "Rub your vagina on their foot."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_VAGINA
require_target_num_feet = 1
+ require_target_feet = REQUIRE_ANY
+ require_user_vagina = REQUIRE_EXPOSED
+ require_user_penis = REQUIRE_NONE
+ max_distance = 1
/datum/interaction/lewd/footfuck/vag/display_interaction(mob/living/user, mob/living/partner)
var/message
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/handjob.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/handjob.dm
index 0cb73f60fa..1d55dc76bc 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/handjob.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/handjob.dm
@@ -1,8 +1,9 @@
/datum/interaction/lewd/handjob
description = "Jerk them off."
interaction_sound = null
- required_from_user = INTERACTION_REQUIRE_HANDS
- required_from_target_exposed = INTERACTION_REQUIRE_PENIS
+ require_user_hands = TRUE
+ require_target_penis = REQUIRE_EXPOSED
+ max_distance = 1
additional_details = list(
list(
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/kiss.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/kiss.dm
index 4aded3a99e..8e196c8a19 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/kiss.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/kiss.dm
@@ -1,10 +1,11 @@
/datum/interaction/lewd/kiss
description = "Kiss them deeply."
- required_from_user = INTERACTION_REQUIRE_MOUTH
- required_from_target = INTERACTION_REQUIRE_MOUTH
+ require_user_mouth = TRUE
+ require_target_mouth = TRUE
write_log_user = "kissed"
write_log_target = "was kissed by"
interaction_sound = null
+ max_distance = 1
/datum/interaction/lewd/kiss/post_interaction(mob/living/user, mob/living/partner)
. = ..()
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/lick.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/lick.dm
index c806c08d39..30a0f7f1c2 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/lick.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/lick.dm
@@ -1,8 +1,9 @@
/datum/interaction/lewd/rimjob
description = "Lick their ass."
interaction_sound = null
- required_from_user = INTERACTION_REQUIRE_MOUTH
- required_from_target_exposed = INTERACTION_REQUIRE_ANUS
+ require_user_mouth = TRUE
+ require_target_anus = REQUIRE_EXPOSED
+ max_distance = 1
/datum/interaction/lewd/rimjob/display_interaction(mob/living/user, mob/living/partner)
user.visible_message(span_lewd("\The [user] licks \the [partner] 's asshole."), ignored_mobs = user.get_unconsenting())
@@ -12,10 +13,10 @@
/datum/interaction/lewd/lickfeet
description = "Lick their feet."
interaction_sound = null
- required_from_user = INTERACTION_REQUIRE_MOUTH
- required_from_target_exposed = INTERACTION_REQUIRE_FEET
- required_from_target_unexposed = INTERACTION_REQUIRE_FEET
+ require_user_mouth = TRUE
+ require_target_feet = REQUIRE_ANY
require_target_num_feet = 1
+ max_distance = 1
/datum/interaction/lewd/lickfeet/display_interaction(mob/living/user, mob/living/partner)
var/message
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/mount.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/mount.dm
index 2c69e82814..de5675734d 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/mount.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/mount.dm
@@ -1,8 +1,9 @@
/datum/interaction/lewd/mount
description = "Mount with your pussy."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_VAGINA
- required_from_target_exposed = INTERACTION_REQUIRE_PENIS
+ require_user_vagina = REQUIRE_EXPOSED
+ require_target_penis = REQUIRE_EXPOSED
+ max_distance = 1
/datum/interaction/lewd/mount/display_interaction(mob/living/user, mob/living/partner)
var/message
@@ -26,8 +27,9 @@
/datum/interaction/lewd/mountass
description = "Mount with your ass."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_ANUS
- required_from_target_exposed = INTERACTION_REQUIRE_PENIS
+ require_user_anus = REQUIRE_EXPOSED
+ require_target_penis = REQUIRE_EXPOSED
+ max_distance = 1
/datum/interaction/lewd/mountass/display_interaction(mob/living/user, mob/living/partner)
var/message
@@ -51,8 +53,9 @@
/datum/interaction/lewd/mountface
description = "Ass to face."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_ANUS
- required_from_target = INTERACTION_REQUIRE_MOUTH
+ require_target_mouth = TRUE
+ require_user_anus = REQUIRE_EXPOSED
+ max_distance = 1
/datum/interaction/lewd/mountface/display_interaction(mob/living/user, mob/living/partner)
var/message
@@ -75,9 +78,10 @@
user.handle_post_sex(LOW_LUST, null, partner)
/datum/interaction/lewd/thighs
- description = "Smother them using your penis."
- required_from_user_exposed = INTERACTION_REQUIRE_PENIS
- required_from_target = INTERACTION_REQUIRE_MOUTH
+ description = "Smother them using your %COCK%."
+ max_distance = 1
+ require_user_penis = REQUIRE_EXPOSED
+ require_target_mouth = TRUE
interaction_sound = null
write_log_user = "thigh-trapped (penis)"
write_log_target = "was smothered (penis) by"
@@ -85,7 +89,8 @@
/datum/interaction/lewd/thighs/vagina
description = "Smother them using your vagina."
- required_from_user_exposed = INTERACTION_REQUIRE_VAGINA
+ require_user_penis = REQUIRE_NONE
+ require_user_vagina = REQUIRE_EXPOSED
write_log_user = "thigh-trapped (vagina)"
write_log_target = "was smothered (vagina) by"
fucktarget = "vagina"
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/nipsuck.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/nipsuck.dm
index 8b65b38272..66a4ed55ba 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/nipsuck.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/nipsuck.dm
@@ -1,10 +1,11 @@
/datum/interaction/lewd/nipsuck
description = "Suck their nipples."
- required_from_user = INTERACTION_REQUIRE_MOUTH
- required_from_target_exposed = INTERACTION_REQUIRE_BREASTS
+ require_target_breasts = REQUIRE_EXPOSED
+ require_user_mouth = TRUE
write_log_user = "sucked nipples"
write_log_target = "had their nipples sucked by"
interaction_sound = null
+ max_distance = 1
/datum/interaction/lewd/nipsuck/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
if((user.a_intent == INTENT_HELP) || (user.a_intent == INTENT_DISARM))
@@ -12,8 +13,7 @@
pick(span_lewd("\The [user] gently sucks on \the [target] 's [pick("nipple", "nipples")]."),
span_lewd("\The [user] gently nibs \the [target] 's [pick("nipple", "nipples")]."),
span_lewd("\The [user] licks \the [target] 's [pick("nipple", "nipples")].")))
- var/has_breasts = target.has_breasts()
- if(has_breasts == TRUE || has_breasts == HAS_EXPOSED_GENITAL)
+ if(target.has_breasts(REQUIRE_EXPOSED))
var/modifier = 1
var/obj/item/organ/genital/breasts/B = target.getorganslot(ORGAN_SLOT_BREASTS)
switch(B.size)
@@ -33,8 +33,7 @@
user.visible_message(
pick(span_lewd("\The [user] bites \the [target] 's [pick("nipple", "nipples")]."),
span_lewd("\The [user] aggressively sucks \the [target] 's [pick("nipple", "nipples")].")))
- var/has_breasts = target.has_breasts()
- if(has_breasts == TRUE || has_breasts == HAS_EXPOSED_GENITAL)
+ if(target.has_breasts(REQUIRE_EXPOSED))
var/modifier = 1
var/obj/item/organ/genital/breasts/B = target.getorganslot(ORGAN_SLOT_BREASTS)
switch(B.size)
@@ -55,8 +54,7 @@
pick(span_lewd("\The [user] sucks \the [target] 's [pick("nipple", "nipples")] intently."),
span_lewd("\The [user] feasts \the [target] 's [pick("nipple", "nipples")]."),
span_lewd("\The [user] glomps \the [target] 's [pick("nipple", "nipples")].")))
- var/has_breasts = target.has_breasts()
- if(has_breasts == TRUE || has_breasts == HAS_EXPOSED_GENITAL)
+ if(target.has_breasts(REQUIRE_EXPOSED))
var/modifier = 1
var/obj/item/organ/genital/breasts/B = target.getorganslot(ORGAN_SLOT_BREASTS)
switch(B.size)
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/nuts.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/nuts.dm
index b5fd82721a..3210d01ed3 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/nuts.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/nuts.dm
@@ -1,8 +1,9 @@
/datum/interaction/lewd/nuts
description = "Nuts to face."
interaction_sound = null
- required_from_user_exposed = INTERACTION_REQUIRE_BALLS
- required_from_target = INTERACTION_REQUIRE_MOUTH
+ require_user_balls = REQUIRE_EXPOSED
+ require_target_mouth = TRUE
+ max_distance = 1
write_log_user = "make-them-suck-their-nuts"
write_log_target = "was made to suck nuts by"
@@ -35,7 +36,8 @@
description = "Smack their nuts."
interaction_sound = 'modular_sand/sound/interactions/slap.ogg'
simple_message = "USER slaps TARGET's nuts!"
- required_from_user = INTERACTION_REQUIRE_HANDS
- required_from_target_exposed = INTERACTION_REQUIRE_BALLS
+ require_target_balls = REQUIRE_EXPOSED
+ needs_physical_contact = TRUE
+ max_distance = 1
write_log_user = "slapped-nuts"
write_log_target = "had their nuts slapped by"
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/oral.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/oral.dm
index d9407bb26d..4994e6f4bf 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/oral.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/oral.dm
@@ -1,15 +1,17 @@
/datum/interaction/lewd/oral
description = "Go down on them."
- required_from_user = INTERACTION_REQUIRE_MOUTH
- required_from_target_exposed = INTERACTION_REQUIRE_VAGINA
+ require_user_mouth = TRUE
+ require_target_vagina = REQUIRE_EXPOSED
write_log_user = "gave head to"
write_log_target = "was given head by"
interaction_sound = null
+ max_distance = 1
var/fucktarget = "vagina"
/datum/interaction/lewd/oral/blowjob
description = "Suck them off."
- required_from_target_exposed = INTERACTION_REQUIRE_PENIS
+ require_target_vagina = null
+ require_target_penis = REQUIRE_EXPOSED
fucktarget = "penis"
/datum/interaction/lewd/oral/display_interaction(mob/living/user, mob/living/partner)
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/self/breasts.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/self/breasts.dm
index 20927a02ae..b9991235cf 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/self/breasts.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/self/breasts.dm
@@ -1,9 +1,8 @@
/datum/interaction/lewd/titgrope_self
description = "Grope your own breasts."
- required_from_user = INTERACTION_REQUIRE_HANDS
- required_from_user_exposed = INTERACTION_REQUIRE_BREASTS
- required_from_user_unexposed = INTERACTION_REQUIRE_BREASTS
- interaction_flags = INTERACTION_FLAG_OOC_CONSENT | INTERACTION_FLAG_USER_IS_TARGET
+ require_user_hands = TRUE
+ require_user_breasts = REQUIRE_ANY
+ user_is_target = TRUE
interaction_sound = null
max_distance = 0
write_log_user = "groped own breasts"
@@ -79,9 +78,9 @@
/datum/interaction/lewd/self_nipsuck
description = "Suck your own nips."
- required_from_user = INTERACTION_REQUIRE_MOUTH
- required_from_user_exposed = INTERACTION_REQUIRE_BREASTS
- interaction_flags = INTERACTION_FLAG_OOC_CONSENT | INTERACTION_FLAG_USER_IS_TARGET
+ require_user_breasts = REQUIRE_EXPOSED
+ require_user_mouth = TRUE
+ user_is_target = TRUE
interaction_sound = null
max_distance = 0
write_log_user = "sucked their own nips"
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/self/finger.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/self/finger.dm
index 620c3f006e..c5a18ca447 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/self/finger.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/self/finger.dm
@@ -1,9 +1,9 @@
/datum/interaction/lewd/fingerass_self
description = "Finger yourself."
interaction_sound = null
- required_from_user = INTERACTION_REQUIRE_HANDS
- required_from_user_exposed = INTERACTION_REQUIRE_ANUS
- interaction_flags = INTERACTION_FLAG_OOC_CONSENT | INTERACTION_FLAG_USER_IS_TARGET
+ require_user_hands = TRUE
+ require_user_anus = REQUIRE_EXPOSED
+ user_is_target = TRUE
max_distance = 0
write_log_user = "fingered self"
write_log_target = null
@@ -21,10 +21,10 @@
/datum/interaction/lewd/finger_self
description = "Finger your own pussy."
- required_from_user = INTERACTION_REQUIRE_HANDS
- required_from_user_exposed = INTERACTION_REQUIRE_VAGINA
+ require_user_hands = TRUE
+ require_user_vagina = REQUIRE_EXPOSED
interaction_sound = null
- interaction_flags = INTERACTION_FLAG_OOC_CONSENT | INTERACTION_FLAG_USER_IS_TARGET
+ user_is_target = TRUE
max_distance = 0
write_log_user = "fingered own pussy"
write_log_target = null
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/self/jack.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/self/jack.dm
index ce81d358ca..36f74316ec 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/self/jack.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/self/jack.dm
@@ -1,9 +1,9 @@
/datum/interaction/lewd/jack
description = "Jerk yourself off."
interaction_sound = null
- required_from_user = INTERACTION_REQUIRE_HANDS
- required_from_user_exposed = INTERACTION_REQUIRE_PENIS
- interaction_flags = INTERACTION_FLAG_OOC_CONSENT | INTERACTION_FLAG_USER_IS_TARGET
+ require_user_hands = TRUE
+ require_user_penis = REQUIRE_EXPOSED
+ user_is_target = TRUE
max_distance = 0
write_log_user = "jerked off"
write_log_target = null
diff --git a/modular_sand/code/datums/interactions/interaction_mob.dm b/modular_sand/code/datums/interactions/interaction_mob.dm
index f6dc946f38..4fa398ea72 100644
--- a/modular_sand/code/datums/interactions/interaction_mob.dm
+++ b/modular_sand/code/datums/interactions/interaction_mob.dm
@@ -10,11 +10,5 @@
/mob/living/proc/foot_is_free()
return is_barefoot()
-/mob/living/silicon/robot/mouth_is_free()
- return TRUE
-
/mob/living/carbon/human/has_mouth()
return get_bodypart(BODY_ZONE_HEAD)
-
-/mob/living/carbon/human/has_hands() // technically should be an and but i'll replicate original behavior
- return get_bodypart(BODY_ZONE_L_ARM) || get_bodypart(BODY_ZONE_R_ARM)
diff --git a/modular_sand/code/datums/interactions/lewd_definitions.dm b/modular_sand/code/datums/interactions/lewd_definitions.dm
index a3348a0076..056eefcb70 100644
--- a/modular_sand/code/datums/interactions/lewd_definitions.dm
+++ b/modular_sand/code/datums/interactions/lewd_definitions.dm
@@ -91,32 +91,42 @@
/mob/living/proc/toggle_anus_always_accessible(accessibility)
anus_always_accessible = isnull(accessibility) ? !anus_always_accessible : accessibility
-/mob/living/proc/has_genital(slot)
+/mob/living/proc/has_genital(slot, visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(istype(C))
var/obj/item/organ/genital/genital = C.getorganslot(slot)
if(genital)
- if(genital.is_exposed() || genital.always_accessible)
- return HAS_EXPOSED_GENITAL
- else
- return HAS_UNEXPOSED_GENITAL
+ switch(visibility)
+ if(REQUIRE_ANY)
+ return TRUE
+ if(REQUIRE_EXPOSED)
+ return genital.is_exposed() || genital.always_accessible
+ if(REQUIRE_UNEXPOSED)
+ return !genital.is_exposed()
+ else
+ return TRUE
return FALSE
-/mob/living/proc/has_penis()
+/mob/living/proc/has_penis(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(has_penis && !istype(C))
return TRUE
- return has_genital(ORGAN_SLOT_PENIS)
+ return has_genital(ORGAN_SLOT_PENIS, visibility)
-/mob/living/proc/has_strapon()
+/mob/living/proc/has_strapon(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(istype(C))
var/obj/item/clothing/underwear/briefs/strapon/strapon = C.get_strapon()
if(strapon)
- if(strapon.is_exposed())
- return HAS_EXPOSED_GENITAL
- else
- return HAS_UNEXPOSED_GENITAL
+ switch(visibility)
+ if(REQUIRE_ANY)
+ return TRUE
+ if(REQUIRE_EXPOSED)
+ return strapon.is_exposed()
+ if(REQUIRE_UNEXPOSED)
+ return !strapon.is_exposed()
+ else
+ return TRUE
return FALSE
/mob/living/proc/get_strapon()
@@ -130,117 +140,220 @@
return has_penis()
/mob/living/proc/get_penetrating_genital_name(long = FALSE)
- return has_penis() ? (long ? pick(GLOB.dick_nouns) : pick("cock", "dick")) : "strapon"
+ return has_penis() ? (long ? pick(GLOB.dick_nouns) : pick("cock", "dick")) : pick("strapon")
-/mob/living/proc/has_balls()
+/mob/living/proc/has_balls(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(has_balls && !istype(C))
return TRUE
- return has_genital(ORGAN_SLOT_TESTICLES)
+ return has_genital(ORGAN_SLOT_TESTICLES, visibility)
-/mob/living/proc/has_vagina()
+/mob/living/proc/has_vagina(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(has_vagina && !istype(C))
return TRUE
- return has_genital(ORGAN_SLOT_VAGINA)
+ return has_genital(ORGAN_SLOT_VAGINA, visibility)
-/mob/living/proc/has_breasts()
+/mob/living/proc/has_breasts(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(has_breasts && !istype(C))
return TRUE
- return has_genital(ORGAN_SLOT_BREASTS)
+ return has_genital(ORGAN_SLOT_BREASTS, visibility)
-/mob/living/proc/has_butt()
- var/mob/living/carbon/C = src
- if(has_butt && !istype(C))
- return TRUE
- return has_genital(ORGAN_SLOT_BUTT)
-
-/mob/living/proc/has_anus()
+/mob/living/proc/has_anus(visibility = REQUIRE_ANY)
if(has_anus && !iscarbon(src))
return TRUE
- if (has_anus && anus_always_accessible)
- return HAS_EXPOSED_GENITAL
- switch(anus_exposed)
- if(-1)
- return HAS_UNEXPOSED_GENITAL
- if(1)
- return HAS_EXPOSED_GENITAL
- else
- if(is_bottomless())
- return HAS_EXPOSED_GENITAL
+ switch(visibility)
+ if(REQUIRE_ANY)
+ return TRUE
+ if(REQUIRE_EXPOSED)
+ if (has_anus && anus_always_accessible)
+ return TRUE
+ switch(anus_exposed)
+ if(-1)
+ return FALSE
+ if(1)
+ return TRUE
+ else
+ if(is_bottomless())
+ return TRUE
+ else
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(anus_exposed == -1)
+ if(!anus_exposed)
+ if(!is_bottomless())
+ return TRUE
+ else
+ return FALSE
+ else
+ return FALSE
else
- return HAS_UNEXPOSED_GENITAL
+ return TRUE
+ else
+ return TRUE
-/mob/living/proc/has_hand()
+/mob/living/proc/has_hand(visibility = REQUIRE_ANY)
if(iscarbon(src))
var/mob/living/carbon/C = src
var/handcount = 0
var/covered = 0
+ var/iscovered = FALSE
for(var/obj/item/bodypart/l_arm/L in C.bodyparts)
handcount++
for(var/obj/item/bodypart/r_arm/R in C.bodyparts)
handcount++
- if(!handcount)
- return FALSE
if(C.get_item_by_slot(ITEM_SLOT_HANDS))
var/obj/item/clothing/gloves/G = C.get_item_by_slot(ITEM_SLOT_HANDS)
covered = G.body_parts_covered
if(covered & HANDS)
- return HAS_UNEXPOSED_GENITAL
- else
- return HAS_EXPOSED_GENITAL
+ iscovered = TRUE
+ switch(visibility)
+ if(REQUIRE_ANY)
+ return handcount
+ if(REQUIRE_EXPOSED)
+ if(iscovered)
+ return FALSE
+ else
+ return handcount
+ if(REQUIRE_UNEXPOSED)
+ if(!iscovered)
+ return FALSE
+ else
+ return handcount
+ else
+ return handcount
return FALSE
-/mob/living/proc/has_feet()
+/mob/living/proc/has_feet(visibility = REQUIRE_ANY)
if(iscarbon(src))
var/mob/living/carbon/C = src
var/feetcount = 0
var/covered = 0
+ var/iscovered = FALSE
for(var/obj/item/bodypart/l_leg/L in C.bodyparts)
feetcount++
for(var/obj/item/bodypart/r_leg/R in C.bodyparts)
feetcount++
- if(!feetcount)
- return FALSE
if(!C.is_barefoot())
covered = TRUE
if(covered)
- return HAS_UNEXPOSED_GENITAL
- else
- return HAS_EXPOSED_GENITAL
+ iscovered = TRUE
+ switch(visibility)
+ if(REQUIRE_ANY)
+ return feetcount
+ if(REQUIRE_EXPOSED)
+ if(iscovered)
+ return FALSE
+ else
+ return feetcount
+ if(REQUIRE_UNEXPOSED)
+ if(!iscovered)
+ return FALSE
+ else
+ return feetcount
+ else
+ return feetcount
return FALSE
/mob/living/proc/get_num_feet()
- return 0
-
-/mob/living/carbon/get_num_feet()
- . = ..()
- for(var/obj/item/bodypart/l_leg/L in bodyparts)
- .++
- for(var/obj/item/bodypart/r_leg/R in bodyparts)
- .++
+ return has_feet(REQUIRE_ANY)
//weird procs go here
-//please check for existance separately
-/mob/living/proc/has_ears()
+/mob/living/proc/has_ears(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(istype(C))
- if(C.get_item_by_slot(ITEM_SLOT_EARS_LEFT) || C.get_item_by_slot(ITEM_SLOT_EARS_RIGHT))
- return HAS_UNEXPOSED_GENITAL
- else
- return HAS_EXPOSED_GENITAL
+ var/obj/item/organ/peepee = C.getorganslot(ORGAN_SLOT_EARS)
+ if(peepee)
+ switch(visibility)
+ if(REQUIRE_ANY)
+ return TRUE
+ if(REQUIRE_EXPOSED)
+ if(C.get_item_by_slot(ITEM_SLOT_EARS_LEFT) || C.get_item_by_slot(ITEM_SLOT_EARS_RIGHT))
+ return FALSE
+ else
+ return TRUE
+ if(REQUIRE_UNEXPOSED)
+ if(!C.get_item_by_slot(ITEM_SLOT_EARS_LEFT || C.get_item_by_slot(ITEM_SLOT_EARS_RIGHT)))
+ return FALSE
+ else
+ return TRUE
+ else
+ return TRUE
return FALSE
-/mob/living/proc/has_eyes()
+/mob/living/proc/has_earsockets(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(istype(C))
- if(C.get_item_by_slot(ITEM_SLOT_EYES))
- return HAS_UNEXPOSED_GENITAL
- else
- return HAS_EXPOSED_GENITAL
+ var/obj/item/organ/peepee = C.getorganslot(ORGAN_SLOT_EARS)
+ if(!peepee)
+ switch(visibility)
+ if(REQUIRE_ANY)
+ return TRUE
+ if(REQUIRE_EXPOSED)
+ if(C.get_item_by_slot(ITEM_SLOT_EARS_LEFT) || C.get_item_by_slot(ITEM_SLOT_EARS_RIGHT))
+ return FALSE
+ else
+ return TRUE
+ if(REQUIRE_UNEXPOSED)
+ if(!C.get_item_by_slot(ITEM_SLOT_EARS_LEFT) || !C.get_item_by_slot(ITEM_SLOT_EARS_RIGHT))
+ return FALSE
+ else
+ return TRUE
+ else
+ return TRUE
return FALSE
+/mob/living/proc/has_eyes(visibility = REQUIRE_ANY)
+ var/mob/living/carbon/C = src
+ if(istype(C))
+ var/obj/item/organ/peepee = C.getorganslot(ORGAN_SLOT_EYES)
+ if(peepee)
+ switch(visibility)
+ if(REQUIRE_ANY)
+ return TRUE
+ if(REQUIRE_EXPOSED)
+ if(C.get_item_by_slot(ITEM_SLOT_EYES))
+ return FALSE
+ else
+ return TRUE
+ if(REQUIRE_UNEXPOSED)
+ if(!C.get_item_by_slot(ITEM_SLOT_EYES))
+ return FALSE
+ else
+ return TRUE
+ else
+ return TRUE
+ return FALSE
+
+/mob/living/proc/has_eyesockets(visibility = REQUIRE_ANY)
+ var/mob/living/carbon/C = src
+ if(istype(C))
+ var/obj/item/organ/peepee = C.getorganslot(ORGAN_SLOT_EYES)
+ if(!peepee)
+ switch(visibility)
+ if(REQUIRE_ANY)
+ return TRUE
+ if(REQUIRE_EXPOSED)
+ if(get_item_by_slot(ITEM_SLOT_EYES))
+ return FALSE
+ else
+ return TRUE
+ if(REQUIRE_UNEXPOSED)
+ if(!get_item_by_slot(ITEM_SLOT_EYES))
+ return FALSE
+ else
+ return TRUE
+ else
+ return TRUE
+ return FALSE
+
+/mob/living/proc/has_butt(visibility = REQUIRE_ANY)
+ var/mob/living/carbon/C = src
+ if(has_butt && !istype(C))
+ return TRUE
+ return has_genital(ORGAN_SLOT_BUTT, visibility)
+
///Are we wearing something that covers our chest?
/mob/living/proc/is_topless()
for(var/slot in GLOB.slots)
@@ -338,8 +451,7 @@
else
message = "cums on \the [partner] 's face."
if(CUM_TARGET_VAGINA)
- var/has_vagina = partner.has_vagina()
- if(has_vagina == TRUE || has_vagina == HAS_EXPOSED_GENITAL)
+ if(partner.has_vagina(REQUIRE_EXPOSED))
if(partner_carbon_check)
target_gen = c_partner.getorganslot(ORGAN_SLOT_VAGINA)
message = "cums in \the [partner] 's pussy."
@@ -347,20 +459,18 @@
else
message = "cums on \the [partner] 's belly."
if(CUM_TARGET_ANUS)
- var/has_anus = partner.has_anus()
- if(has_anus == TRUE || has_anus == HAS_EXPOSED_GENITAL)
+ if(partner.has_anus(REQUIRE_EXPOSED))
message = "cums in \the [partner] 's asshole."
cumin = TRUE
else
message = "cums on \the [partner] 's backside."
if(CUM_TARGET_HAND)
- if(partner.has_hand())
+ if(partner.has_hand(REQUIRE_ANY))
message = "cums in \the [partner] 's hand."
else
message = "cums on \the [partner] ."
if(CUM_TARGET_BREASTS)
- var/has_breasts = partner.has_breasts()
- if(has_breasts == TRUE || has_breasts == HAS_EXPOSED_GENITAL)
+ if(partner.has_breasts(REQUIRE_EXPOSED))
message = "cums onto \the [partner] 's breasts."
else
message = "cums on \the [partner] 's chest and neck."
@@ -368,8 +478,7 @@
if(partner.has_mouth() && partner.mouth_is_free())
message = "vigorously ruts [u_His] nutsack into \the [partner] 's mouth before shooting [u_His] thick, sticky jizz all over [t_His] eyes and hair."
if(THIGH_SMOTHERING)
- var/has_penis = has_penis()
- if(has_penis == TRUE || has_penis == HAS_EXPOSED_GENITAL) //it already checks for the cock before, why the hell would you do this redundant shit
+ if(has_penis(REQUIRE_EXPOSED)) //it already checks for the cock before, why the hell would you do this redundant shit
message = "keeps \the [partner] locked in [u_His] thighs as [u_His] cock throbs, dumping its heavy load all over [t_His] face."
else
message = "reaches [u_His] peak, locking [u_His] legs around \the [partner] 's head extra hard as [u_He] cum[u_S] straight onto the head stuck between [u_His] thighs"
@@ -382,7 +491,7 @@
message = "cums on the floor!"
else
if(partner.has_feet())
- message = "cums on \the [partner] 's [last_lewd_datum.require_target_num_feet == 1 ? pick("foot", "sole") : pick("feet", "soles")]."
+ message = "cums on \the [partner] 's [last_lewd_datum.require_target_feet == 1 ? pick("foot", "sole") : pick("feet", "soles")]."
else
message = "cums on the floor!"
//weird shit goes here
@@ -400,8 +509,7 @@
cumin = TRUE
//
if(CUM_TARGET_PENIS)
- var/has_penis = partner.has_penis()
- if(has_penis == TRUE || has_penis == HAS_EXPOSED_GENITAL)
+ if(partner.has_penis(REQUIRE_EXPOSED))
message = "cums on \the [partner] ."
else
message = "cums on the floor!"
@@ -425,27 +533,24 @@
else
message = "squirts on \the [partner] 's face."
if(CUM_TARGET_VAGINA)
- var/has_vagina = partner.has_vagina()
- if(has_vagina == TRUE || has_vagina == HAS_EXPOSED_GENITAL)
+ if(partner.has_vagina(REQUIRE_EXPOSED))
message = "squirts on \the [partner] 's pussy."
cumin = TRUE
else
message = "squirts on \the [partner] 's belly."
if(CUM_TARGET_ANUS)
- var/has_anus = partner.has_anus()
- if(has_anus == TRUE || has_anus == HAS_EXPOSED_GENITAL)
+ if(partner.has_anus(REQUIRE_EXPOSED))
message = "squirts on \the [partner] 's asshole."
cumin = TRUE
else
message = "squirts on \the [partner] 's backside."
if(CUM_TARGET_HAND)
- if(partner.has_hand())
+ if(partner.has_hand(REQUIRE_ANY))
message = "squirts on \the [partner] 's hand."
else
message = "squirts on \the [partner] ."
if(CUM_TARGET_BREASTS)
- var/has_breasts = partner.has_breasts()
- if(has_breasts == TRUE || has_breasts == HAS_EXPOSED_GENITAL)
+ if(partner.has_breasts(REQUIRE_EXPOSED))
message = "squirts onto \the [partner] 's breasts."
else
message = "squirts on \the [partner] 's chest and neck."
@@ -463,7 +568,7 @@
message = "squirts on the floor!"
else
if(partner.has_feet())
- message = "squirts on \the [partner] 's [last_lewd_datum.require_target_num_feet == 1 ? pick("foot", "sole") : pick("feet", "soles")]."
+ message = "squirts on \the [partner] 's [last_lewd_datum.require_target_feet == 1 ? pick("foot", "sole") : pick("feet", "soles")]."
else
message = "squirts on the floor!"
//weird shit goes here
@@ -481,8 +586,7 @@
cumin = TRUE
//
if(CUM_TARGET_PENIS)
- var/has_penis = partner.has_penis()
- if(has_penis == TRUE || has_penis == HAS_EXPOSED_GENITAL)
+ if(partner.has_penis(REQUIRE_EXPOSED))
message = "squirts on \the [partner] 's penis"
else
message = "squirts on the floor!"
@@ -511,8 +615,7 @@
else
message = "cums on \the [partner] 's face."
if(CUM_TARGET_VAGINA)
- var/has_vagina = partner.has_vagina()
- if(has_vagina == TRUE || has_vagina == HAS_EXPOSED_GENITAL)
+ if(partner.has_vagina(REQUIRE_EXPOSED))
if(partner_carbon_check)
target_gen = c_partner.getorganslot(ORGAN_SLOT_VAGINA)
message = "cums in \the [partner] 's pussy."
@@ -520,8 +623,7 @@
else
message = "cums on \the [partner] 's belly."
if(CUM_TARGET_ANUS)
- var/has_anus = partner.has_anus()
- if(has_anus == TRUE || has_anus == HAS_EXPOSED_GENITAL)
+ if(partner.has_anus(REQUIRE_EXPOSED))
message = "cums in \the [partner] 's asshole."
cumin = TRUE
else
@@ -553,7 +655,7 @@
message = "cums on the floor!"
else
if(partner.has_feet())
- message = "cums on \the [partner] 's [last_lewd_datum.require_target_num_feet == 1 ? pick("foot", "sole") : pick("feet", "soles")]."
+ message = "cums on \the [partner] 's [last_lewd_datum.require_target_feet == 1 ? pick("foot", "sole") : pick("feet", "soles")]."
else
message = "cums on the floor!"
//weird shit goes here
@@ -571,8 +673,7 @@
cumin = TRUE
//
if(CUM_TARGET_PENIS)
- var/has_penis = partner.has_penis()
- if(has_penis == TRUE || has_penis == HAS_EXPOSED_GENITAL)
+ if(partner.has_penis(REQUIRE_EXPOSED))
message = "cums on \the [partner] ."
else
message = "cums on the floor!"
@@ -596,15 +697,13 @@
else
message = "squirts on \the [partner] 's face."
if(CUM_TARGET_VAGINA)
- var/has_vagina = partner.has_vagina()
- if(has_vagina == TRUE || has_vagina == HAS_EXPOSED_GENITAL)
+ if(partner.has_vagina(REQUIRE_EXPOSED))
message = "squirts on \the [partner] 's pussy."
cumin = TRUE
else
message = "squirts on \the [partner] 's belly."
if(CUM_TARGET_ANUS)
- var/has_anus = partner.has_anus()
- if(has_anus == TRUE || has_anus == HAS_EXPOSED_GENITAL)
+ if(partner.has_anus(REQUIRE_EXPOSED))
message = "squirts on \the [partner] 's asshole."
cumin = TRUE
else
@@ -615,8 +714,7 @@
else
message = "squirts on \the [partner] ."
if(CUM_TARGET_BREASTS)
- var/has_breasts = partner.has_breasts()
- if(has_breasts == TRUE || has_breasts == HAS_EXPOSED_GENITAL)
+ if(partner.has_breasts(REQUIRE_EXPOSED))
message = "squirts onto \the [partner] 's breasts."
else
message = "squirts on \the [partner] 's chest and neck."
@@ -635,7 +733,7 @@
message = "squirts on the floor!"
else
if(partner.has_feet())
- message = "squirts on \the [partner] 's [last_lewd_datum.require_target_num_feet == 1 ? pick("foot", "sole") : pick("feet", "soles")]."
+ message = "squirts on \the [partner] 's [last_lewd_datum.require_target_feet == 1 ? pick("foot", "sole") : pick("feet", "soles")]."
else
message = "squirts on the floor!"
//weird shit goes here
@@ -653,8 +751,7 @@
cumin = TRUE
//
if(CUM_TARGET_PENIS)
- var/has_penis = partner.has_penis()
- if(has_penis == TRUE || has_penis == HAS_EXPOSED_GENITAL)
+ if(partner.has_penis(REQUIRE_EXPOSED))
message = "squirts on \the [partner] 's penis"
else
message = "squirts on the floor!"
@@ -760,7 +857,7 @@
return TRUE
return FALSE
-/mob/living/proc/get_unconsenting(interaction_flags, list/ignored_mobs)
+/mob/living/proc/get_unconsenting(extreme = FALSE, list/ignored_mobs)
var/list/nope = list()
nope += ignored_mobs
for(var/mob/M in range(7, src))
@@ -768,7 +865,7 @@
var/client/cli = M.client
if(!(cli.prefs.toggles & VERB_CONSENT)) //Note: This probably could do with a specific preference
nope += M
- else if(interaction_flags & INTERACTION_FLAG_EXTREME_CONTENT && (cli.prefs.extremepref == "No"))
+ else if(extreme && (cli.prefs.extremepref == "No"))
nope += M
else
nope += M
diff --git a/modular_sand/code/datums/interactions/lewd_interactions.dm b/modular_sand/code/datums/interactions/lewd_interactions.dm
index bc628a89b2..ccd0708d93 100644
--- a/modular_sand/code/datums/interactions/lewd_interactions.dm
+++ b/modular_sand/code/datums/interactions/lewd_interactions.dm
@@ -5,16 +5,66 @@
simple_message = "USER slaps TARGET right on the ass!"
simple_style = "danger"
interaction_sound = 'sound/weapons/slap.ogg'
- interaction_flags = INTERACTION_FLAG_ADJACENT | INTERACTION_FLAG_OOC_CONSENT
+ needs_physical_contact = TRUE
+ require_ooc_consent = TRUE
+ max_distance = 1
write_log_user = "ass-slapped"
write_log_target = "was ass-slapped by"
- /// Use the number of required feet.
+ var/user_not_tired = FALSE
+ var/target_not_tired = FALSE
+ //Avoid using these!
+ //Should only really use in case there are no related organs
+ //but you want the target or user to be topless/bottomless.
+ //Example: Nipple licking/sucking.
+ //Otherwise, simply use the "require" vars, which
+ //i have changed to actually check for the appropriate organs.
+ //This is better because it means that exposing a genital while still
+ //wearing something actually means you can do the s*x.
+ var/require_user_topless
+ var/require_target_topless
+ var/require_user_bottomless
+ var/require_target_bottomless
+ //
+
+ //REQUIRE_NONE for doesn't require.
+ //REQUIRE_EXPOSED for requires exposed.
+ //REQUIRE_ANY for both exposed and unexposed.
+ //REQUIRE_UNEXPOSED for requires unexposed.
+ var/require_user_penis
+ var/require_user_anus
+ var/require_user_vagina
+ var/require_user_breasts
+ var/require_user_feet
+ var/require_user_balls
+
+ //Different from the others above. Use the number of required feet.
var/require_user_num_feet
+
+ //Same logic presented before
+ var/require_target_penis
+ var/require_target_anus
+ var/require_target_vagina
+ var/require_target_breasts
+ var/require_target_feet
+ var/require_target_balls
+
var/require_target_num_feet
- /// Time before actions can be done again
+ //"just fucking kill me" variables
+ //also the same logic as before
+ var/extreme = FALSE //Boolean. Used to hide extreme shit from those who do not want it.
+ var/require_target_ears
+ var/require_target_earsockets
+ var/require_target_eyes
+ var/require_target_eyesockets
+ var/require_user_ears
+ var/require_user_earsockets
+ var/require_user_eyes
+ var/require_user_eyesockets
+ //
+
var/user_refractory_cost
var/target_refractory_cost
@@ -22,218 +72,207 @@
. = ..()
if(!.)
return FALSE
- if((interaction_flags & INTERACTION_FLAG_USER_NOT_TIRED) && !COOLDOWN_FINISHED(user, refractory_period))
+ if(user_not_tired && !COOLDOWN_FINISHED(user, refractory_period))
if(!silent) //bye spam
to_chat(user, span_warning("You're still exhausted from the last time. You need to wait [DisplayTimeText(COOLDOWN_TIMELEFT(user, refractory_period), 1)] until you can do that!"))
return FALSE
- if((required_from_user & INTERACTION_REQUIRE_BOTTOMLESS) && !user.is_bottomless())
+ if(require_user_bottomless && !user.is_bottomless())
if(!silent)
to_chat(user, span_warning("Your pants are in the way."))
return FALSE
- if((required_from_user & INTERACTION_REQUIRE_TOPLESS) && !user.is_topless())
+ if(require_user_topless && !user.is_topless())
if(!silent)
to_chat(user, span_warning("Your top is in the way."))
return FALSE
- var/user_require_penis_exposed = !!(required_from_user_exposed & INTERACTION_REQUIRE_PENIS)
- var/user_require_penis_unexposed = !!(required_from_user_unexposed & INTERACTION_REQUIRE_PENIS)
- if(user_require_penis_exposed || user_require_penis_unexposed)
- var/has_penis = user.has_penis() || user.has_strapon()
- if(!has_penis)
- if(!silent)
- to_chat(user, span_warning("You don't have a penis."))
- return FALSE
+ if(require_user_penis)
+ switch(require_user_penis)
+ if(REQUIRE_EXPOSED)
+ if(!user.has_penis(REQUIRE_EXPOSED) && !user.has_strapon(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your penis need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!user.has_penis(REQUIRE_ANY) && !user.has_strapon(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("You don't have a penis."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!user.has_penis(REQUIRE_UNEXPOSED) && !user.has_strapon(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your penis need to be unexposed."))
+ return FALSE
- // Special behavior for things like non-humans and if both sides are allowed
- if(!(has_penis == TRUE) || !(user_require_penis_exposed && user_require_penis_unexposed))
- if((user_require_penis_exposed) && has_penis == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your penis need to be exposed."))
- return FALSE
- if((user_require_penis_unexposed) && has_penis == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your penis need to be unexposed."))
- return FALSE
+ if(require_user_balls)
+ switch(require_user_balls)
+ if(REQUIRE_EXPOSED)
+ if(!user.has_balls(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your balls need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!user.has_balls(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("You don't have balls."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!user.has_balls(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your balls need to be unexposed."))
+ return FALSE
- var/user_require_balls_exposed = !!(required_from_user_exposed & INTERACTION_REQUIRE_BALLS)
- var/user_require_balls_unexposed = !!(required_from_user_unexposed & INTERACTION_REQUIRE_BALLS)
- if(user_require_balls_exposed || user_require_balls_unexposed)
- var/has_balls = user.has_balls()
- if(!has_balls)
- if(!silent)
- to_chat(user, span_warning("You don't have balls."))
- return FALSE
+ if(require_user_anus)
+ switch(require_user_anus)
+ if(REQUIRE_EXPOSED)
+ if(!user.has_anus(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your anus need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!user.has_anus(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("You don't have an anus."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!user.has_anus(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your anus need to be unexposed."))
+ return FALSE
- if(!(has_balls == TRUE) || !(user_require_balls_exposed && user_require_balls_unexposed))
- if((user_require_balls_exposed) && has_balls == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your balls need to be exposed."))
- return FALSE
- if((user_require_balls_unexposed) && has_balls == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your balls need to be unexposed."))
- return FALSE
+ if(require_user_vagina)
+ switch(require_user_vagina)
+ if(REQUIRE_EXPOSED)
+ if(!user.has_vagina(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your vagina need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!user.has_vagina(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("You don't have a vagina."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!user.has_vagina(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your vagina need to be unexposed."))
+ return FALSE
- var/user_require_anus_exposed = !!(required_from_user_exposed & INTERACTION_REQUIRE_ANUS)
- var/user_require_anus_unexposed = !!(required_from_user_unexposed & INTERACTION_REQUIRE_ANUS)
- if(user_require_anus_exposed || user_require_anus_unexposed)
- var/has_anus = user.has_anus()
- if(!has_anus)
- if(!silent)
- to_chat(user, span_warning("You don't have an anus."))
- return FALSE
+ if(require_user_breasts)
+ switch(require_user_breasts)
+ if(REQUIRE_EXPOSED)
+ if(!user.has_breasts(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your breasts need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!user.has_breasts(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("You don't have breasts."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!user.has_breasts(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your breasts need to be unexposed."))
+ return FALSE
- if(!(has_anus == TRUE) || !(user_require_anus_exposed && user_require_anus_unexposed))
- if(user_require_anus_exposed && has_anus == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your anus needs to be exposed."))
- return FALSE
- if(user_require_anus_unexposed && has_anus == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your anus needs to be unexposed."))
- return FALSE
-
- var/user_require_vagina_exposed = !!(required_from_user_exposed & INTERACTION_REQUIRE_VAGINA)
- var/user_require_vagina_unexposed = !!(required_from_user_unexposed & INTERACTION_REQUIRE_VAGINA)
- if(user_require_vagina_exposed || user_require_vagina_unexposed)
- var/has_vagina = user.has_vagina()
- if(!has_vagina)
- if(!silent)
- to_chat(user, span_warning("You don't have a vagina."))
- return FALSE
-
- if(!(has_vagina == TRUE) || !(user_require_vagina_exposed && user_require_vagina_unexposed))
- if(user_require_vagina_exposed && has_vagina == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your vagina needs to be exposed."))
- return FALSE
- if(user_require_vagina_unexposed && has_vagina == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your vagina needs to be unexposed."))
- return FALSE
-
- var/user_require_breasts_exposed = !!(required_from_user_exposed & INTERACTION_REQUIRE_BREASTS)
- var/user_require_breasts_unexposed = !!(required_from_user_unexposed & INTERACTION_REQUIRE_BREASTS)
- if(user_require_breasts_exposed || user_require_breasts_unexposed)
- var/has_breasts = user.has_breasts()
- if(!has_breasts)
- if(!silent)
- to_chat(user, span_warning("You don't have breasts."))
- return FALSE
-
- if(!(has_breasts == TRUE) || !(user_require_breasts_exposed && user_require_breasts_unexposed))
- if(user_require_breasts_exposed && has_breasts == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your breasts need to be exposed."))
- return FALSE
- if(user_require_breasts_unexposed && has_breasts == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your breasts need to be unexposed."))
- return FALSE
-
- var/user_require_feet_exposed = !!(required_from_user_exposed & INTERACTION_REQUIRE_FEET)
- var/user_require_feet_unexposed = !!(required_from_user_unexposed & INTERACTION_REQUIRE_FEET)
- if(user_require_feet_exposed || user_require_feet_unexposed)
- var/has_feet = user.has_feet()
- if(!has_feet)
- if(!silent)
- to_chat(user, span_warning("You don't have feet."))
- return FALSE
-
- if(!(user_require_feet_exposed && user_require_feet_unexposed))
- if(user_require_feet_exposed && has_feet == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your feet need to be exposed."))
- return FALSE
- if(user_require_feet_unexposed && has_feet == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your feet need to be unexposed."))
- return FALSE
+ if(require_user_feet)
+ switch(require_user_feet)
+ if(REQUIRE_EXPOSED)
+ if(!user.has_feet(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your feet need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!user.has_feet(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("You don't have enough feet."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!user.has_feet(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your feet need to be unexposed."))
+ return FALSE
if(require_user_num_feet && (user.get_num_feet() < require_user_num_feet))
if(!silent)
to_chat(user, span_warning("You don't have enough feet."))
return FALSE
- var/user_require_eyes_exposed = !!(required_from_user_exposed & INTERACTION_REQUIRE_EYES)
- var/user_require_eyes_unexposed = !!(required_from_user_unexposed & INTERACTION_REQUIRE_EYES)
- if(user_require_eyes_exposed || user_require_eyes_unexposed)
- var/has_eyes = user.has_eyes()
- if(!user.getorganslot(ORGAN_SLOT_EYES))
- if(!silent)
- to_chat(user, span_warning("You don't have eyes."))
- return FALSE
+ if(require_user_eyes)
+ switch(require_user_eyes)
+ if(REQUIRE_EXPOSED)
+ if(!user.has_eyes(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your eyes need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!user.has_eyes(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("You don't have eyes."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!user.has_eyes(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your eyes need to be unexposed."))
+ return FALSE
- if(!(user_require_eyes_exposed && user_require_eyes_unexposed))
- if(user_require_eyes_exposed && has_eyes == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your eyes need to be exposed."))
- return FALSE
- if(user_require_eyes_unexposed && has_eyes == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your eyes need to be unexposed."))
- return FALSE
+ if(require_user_eyesockets)
+ switch(require_user_eyesockets)
+ if(REQUIRE_EXPOSED)
+ if(!user.has_eyesockets(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your eyesockets need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!user.has_eyesockets(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("You still have eyes."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!user.has_eyesockets(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your eyesockets need to be unexposed."))
+ return FALSE
- var/user_require_eyesockets_exposed = !!(required_from_user_exposed & INTERACTION_REQUIRE_EYESOCKETS)
- var/user_require_eyesockets_unexposed = !!(required_from_user_unexposed & INTERACTION_REQUIRE_EYESOCKETS)
- if(user_require_eyesockets_exposed || user_require_eyesockets_unexposed)
- var/has_eyes = user.has_eyes()
- if(user.getorganslot(ORGAN_SLOT_EYES))
- if(!silent)
- to_chat(user, span_warning("You have eyes!"))
- return FALSE
+ if(require_user_ears)
+ switch(require_user_ears)
+ if(REQUIRE_EXPOSED)
+ if(!user.has_ears(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your ears need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!user.has_ears(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("You don't have ears."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!user.has_ears(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your ears need to be unexposed."))
+ return FALSE
- if(!(user_require_eyesockets_exposed && user_require_eyesockets_unexposed))
- if(user_require_eyesockets_exposed && has_eyes == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your eyesockets need to be exposed."))
- return FALSE
- if(user_require_eyesockets_unexposed && has_eyes == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your eyesockets need to be unexposed."))
- return FALSE
+ if(require_user_earsockets)
+ switch(require_user_earsockets)
+ if(REQUIRE_EXPOSED)
+ if(!user.has_earsockets(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your earsockets need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!user.has_earsockets(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("You still have eyes."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!user.has_earsockets(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Your earsockets need to be unexposed."))
+ return FALSE
- var/user_require_ear_exposed = !!(required_from_user_exposed & INTERACTION_REQUIRE_EARS)
- var/user_require_ear_unexposed = !!(required_from_user_unexposed & INTERACTION_REQUIRE_EARS)
- if(user_require_ear_exposed || user_require_ear_unexposed)
- var/has_ears = user.has_ears()
- if(!user.getorganslot(ORGAN_SLOT_EARS))
- if(!silent)
- to_chat(user, span_warning("You don't have ears."))
- return FALSE
-
- if(!(user_require_ear_exposed && user_require_ear_unexposed))
- if(user_require_ear_exposed && has_ears == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your ears need to be exposed."))
- return FALSE
- if(user_require_ear_unexposed && has_ears == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your ears need to be unexposed."))
- return FALSE
-
- var/user_require_earsockets_exposed = !!(required_from_user_exposed & INTERACTION_REQUIRE_EARSOCKETS)
- var/user_require_earsockets_unexposed = !!(required_from_user_unexposed & INTERACTION_REQUIRE_EARSOCKETS)
- if(user_require_earsockets_exposed || user_require_earsockets_unexposed)
- var/has_ears = user.has_ears()
- if(user.getorganslot(ORGAN_SLOT_EARS))
- if(!silent)
- to_chat(user, span_warning("You have ears!"))
- return FALSE
-
- if(!(user_require_earsockets_exposed && user_require_earsockets_unexposed))
- if(user_require_earsockets_exposed && has_ears == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your earsockets need to be exposed."))
- return FALSE
- if(user_require_earsockets_unexposed && has_ears == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(user, span_warning("Your earsockets need to be unexposed."))
- return FALSE
-
- if(interaction_flags & INTERACTION_FLAG_EXTREME_CONTENT)
+ if(extreme)
var/client/cli = user.client
if(cli)
if(cli.prefs.extremepref == "No")
@@ -241,7 +280,7 @@
to_chat(user, span_warning("That's way too much for you."))
return FALSE
- if(interaction_flags & INTERACTION_FLAG_OOC_CONSENT)
+ if(require_ooc_consent)
if((!user.ckey) || (user.client && user.client.prefs.toggles & VERB_CONSENT))
return TRUE
if(action_check)
@@ -252,217 +291,207 @@
. = ..()
if(!.)
return FALSE
- if((required_from_target & INTERACTION_FLAG_TARGET_NOT_TIRED) && !COOLDOWN_FINISHED(target, refractory_period))
+ if(target_not_tired && !COOLDOWN_FINISHED(target, refractory_period))
if(!silent) //same with this
to_chat(user, span_warning("They're still exhausted from the last time. They need to wait [DisplayTimeText(COOLDOWN_TIMELEFT(target, refractory_period), 1)] until you can do that!"))
return FALSE
- if((required_from_target & INTERACTION_REQUIRE_BOTTOMLESS) && !target.is_bottomless())
+ if(require_target_bottomless && !target.is_bottomless())
if(!silent)
to_chat(user, span_warning("Their pants are in the way."))
return FALSE
- if((required_from_target & INTERACTION_REQUIRE_TOPLESS) && !target.is_bottomless())
+ if(require_target_topless && !target.is_topless())
if(!silent)
to_chat(user, span_warning("Their clothes are in the way."))
return FALSE
- var/target_require_penis_exposed = !!(required_from_target_exposed & INTERACTION_REQUIRE_PENIS)
- var/target_require_penis_unexposed = !!(required_from_target_unexposed & INTERACTION_REQUIRE_PENIS)
- if(target_require_penis_exposed || target_require_penis_unexposed)
- var/has_penis = target.has_penis() || target.has_strapon()
- if(!has_penis)
- if(!silent)
- to_chat(target, span_warning("They don't have a penis."))
- return FALSE
+ if(require_target_penis)
+ switch(require_target_penis)
+ if(REQUIRE_EXPOSED)
+ if(!target.has_penis(REQUIRE_EXPOSED) && !target.has_strapon(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their penis needs to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!target.has_penis(REQUIRE_ANY) && !target.has_strapon(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("They don't have a penis."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!target.has_penis(REQUIRE_UNEXPOSED) && !target.has_strapon(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their penis needs to be unexposed."))
+ return FALSE
- if(!(has_penis == TRUE) || !(target_require_penis_exposed && target_require_penis_unexposed))
- if(target_require_penis_exposed && has_penis == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their penis needs to be exposed."))
- return FALSE
- if(target_require_penis_unexposed && has_penis == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their penis needs to be unexposed."))
- return FALSE
+ if(require_target_balls)
+ switch(require_target_balls)
+ if(REQUIRE_EXPOSED)
+ if(!target.has_balls(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their balls need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!target.has_balls(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("They don't have balls."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!target.has_balls(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their balls need to be unexposed."))
+ return FALSE
- var/target_require_balls_exposed = !!(required_from_target_exposed & INTERACTION_REQUIRE_BALLS)
- var/target_require_balls_unexposed = !!(required_from_target_unexposed & INTERACTION_REQUIRE_BALLS)
- if(target_require_balls_exposed || target_require_balls_unexposed)
- var/has_balls = target.has_balls()
- if(!has_balls)
- if(!silent)
- to_chat(target, span_warning("They don't have balls."))
- return FALSE
+ if(require_target_anus)
+ switch(require_target_anus)
+ if(REQUIRE_EXPOSED)
+ if(!target.has_anus(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their anus needs to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!target.has_anus(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("They don't have an anus."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!target.has_anus(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their anus needs to be unexposed."))
+ return FALSE
- if(!(has_balls == TRUE) || !(target_require_balls_exposed && target_require_balls_unexposed))
- if(target_require_balls_exposed && has_balls == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their balls need to be exposed."))
- return FALSE
- if(target_require_balls_unexposed && has_balls == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their balls need to be unexposed."))
- return FALSE
+ if(require_target_vagina)
+ switch(require_target_vagina)
+ if(REQUIRE_EXPOSED)
+ if(!target.has_vagina(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their vagina needs to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!target.has_vagina(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("They don't have a vagina."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!target.has_vagina(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their vagina needs to be unexposed."))
+ return FALSE
- var/target_require_anus_exposed = !!(required_from_target_exposed & INTERACTION_REQUIRE_ANUS)
- var/target_require_anus_unexposed = !!(required_from_target_unexposed & INTERACTION_REQUIRE_ANUS)
- if(target_require_anus_exposed || target_require_anus_unexposed)
- var/has_anus = target.has_anus()
- if(!has_anus)
- if(!silent)
- to_chat(target, span_warning("They don't have an anus."))
- return FALSE
+ if(require_target_breasts)
+ switch(require_target_breasts)
+ if(REQUIRE_EXPOSED)
+ if(!target.has_breasts(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their breasts need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!target.has_breasts(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("They don't have breasts."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!target.has_breasts(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their breasts need to be unexposed."))
+ return FALSE
- if(!(has_anus == TRUE) || !(target_require_anus_exposed && target_require_anus_unexposed))
- if(target_require_anus_exposed && has_anus == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their anus needs to be exposed."))
- return FALSE
- if(target_require_anus_unexposed && has_anus == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their anus needs to be unexposed."))
- return FALSE
-
- var/target_require_vagina_exposed = !!(required_from_target_exposed & INTERACTION_REQUIRE_VAGINA)
- var/target_require_vagina_unexposed = !!(required_from_target_unexposed & INTERACTION_REQUIRE_VAGINA)
- if(target_require_vagina_exposed || target_require_vagina_unexposed)
- var/has_vagina = target.has_vagina()
- if(!has_vagina)
- if(!silent)
- to_chat(target, span_warning("They don't have a vagina."))
- return FALSE
-
- if(!(has_vagina == TRUE) || !(target_require_vagina_exposed && target_require_vagina_unexposed))
- if(target_require_vagina_exposed && has_vagina == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their vagina needs to be exposed."))
- return FALSE
- if(target_require_vagina_unexposed && has_vagina == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their vagina needs to be unexposed."))
- return FALSE
-
- var/target_require_breasts_exposed = !!(required_from_target_exposed & INTERACTION_REQUIRE_BREASTS)
- var/target_require_breasts_unexposed = !!(required_from_target_unexposed & INTERACTION_REQUIRE_BREASTS)
- if(target_require_breasts_exposed || target_require_breasts_unexposed)
- var/has_breasts = target.has_breasts()
- if(!has_breasts)
- if(!silent)
- to_chat(target, span_warning("They don't have breasts."))
- return FALSE
-
- if(!(has_breasts == TRUE) || !(target_require_breasts_exposed && target_require_breasts_unexposed))
- if(target_require_breasts_exposed && has_breasts == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their breasts need to be exposed."))
- return FALSE
- if(target_require_breasts_unexposed && has_breasts == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their breasts need to be unexposed."))
- return FALSE
-
- var/target_require_feet_exposed = !!(required_from_target_exposed & INTERACTION_REQUIRE_FEET)
- var/target_require_feet_unexposed = !!(required_from_target_unexposed & INTERACTION_REQUIRE_FEET)
- if(target_require_feet_exposed || target_require_feet_unexposed)
- var/has_feet = target.has_feet()
- if(!has_feet)
- if(!silent)
- to_chat(target, span_warning("They don't have feet."))
- return FALSE
-
- if(!(target_require_feet_exposed && target_require_feet_unexposed))
- if(target_require_feet_exposed && has_feet == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their feet need to be exposed."))
- return FALSE
- if(target_require_feet_unexposed && has_feet == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their feet need to be unexposed."))
- return FALSE
+ if(require_target_feet)
+ switch(require_target_feet)
+ if(REQUIRE_EXPOSED)
+ if(!target.has_feet(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their feet need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!target.has_feet(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("They don't have enough feet."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!target.has_feet(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their feet need to be unexposed."))
+ return FALSE
if(require_target_num_feet && (target.get_num_feet() < require_target_num_feet))
if(!silent)
- to_chat(target, span_warning("They don't have enough feet."))
+ to_chat(user, span_warning("They don't have enough feet."))
return FALSE
- var/target_require_eyes_exposed = !!(required_from_target_exposed & INTERACTION_REQUIRE_EYES)
- var/target_require_eyes_unexposed = !!(required_from_target_unexposed & INTERACTION_REQUIRE_EYES)
- if(target_require_eyes_exposed || target_require_eyes_unexposed)
- var/has_eyes = target.has_eyes()
- if(!target.getorganslot(ORGAN_SLOT_EYES))
- if(!silent)
- to_chat(target, span_warning("They don't have eyes."))
- return FALSE
+ if(require_target_eyes)
+ switch(require_target_eyes)
+ if(REQUIRE_EXPOSED)
+ if(!target.has_eyes(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their eyes need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!target.has_eyes(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("They don't have eyes."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!target.has_eyes(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their eyes need to be unexposed."))
+ return FALSE
- if(!(target_require_eyes_exposed && target_require_eyes_unexposed))
- if(target_require_eyes_exposed && has_eyes == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their eyes need to be exposed."))
- return FALSE
- if(target_require_eyes_unexposed && has_eyes == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their eyes need to be unexposed."))
- return FALSE
+ if(require_target_eyesockets)
+ switch(require_target_eyesockets)
+ if(REQUIRE_EXPOSED)
+ if(!target.has_eyesockets(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their eyesockets need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!target.has_eyesockets(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("They still have eyes."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!target.has_eyesockets(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their eyesockets need to be unexposed."))
+ return FALSE
- var/target_require_eyesockets_exposed = !!(required_from_target_exposed & INTERACTION_REQUIRE_EYESOCKETS)
- var/target_require_eyesockets_unexposed = !!(required_from_target_unexposed & INTERACTION_REQUIRE_EYESOCKETS)
- if(target_require_eyesockets_exposed || target_require_eyesockets_unexposed)
- var/has_eyes = target.has_eyes()
- if(target.getorganslot(ORGAN_SLOT_EYES))
- if(!silent)
- to_chat(target, span_warning("They have eyes!"))
- return FALSE
+ if(require_target_ears)
+ switch(require_target_ears)
+ if(REQUIRE_EXPOSED)
+ if(!target.has_ears(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their ears need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!target.has_ears(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("They don't have ears."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!target.has_ears(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their ears need to be unexposed."))
+ return FALSE
- if(!(target_require_eyesockets_exposed && target_require_eyesockets_unexposed))
- if(target_require_eyesockets_exposed && has_eyes == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their eyesockets need to be exposed."))
- return FALSE
- if(target_require_eyesockets_unexposed && has_eyes == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their eyesockets need to be unexposed."))
- return FALSE
+ if(require_target_earsockets)
+ switch(require_target_earsockets)
+ if(REQUIRE_EXPOSED)
+ if(!target.has_earsockets(REQUIRE_EXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their earsockets need to be exposed."))
+ return FALSE
+ if(REQUIRE_ANY)
+ if(!target.has_earsockets(REQUIRE_ANY))
+ if(!silent)
+ to_chat(user, span_warning("They still have eyes."))
+ return FALSE
+ if(REQUIRE_UNEXPOSED)
+ if(!target.has_earsockets(REQUIRE_UNEXPOSED))
+ if(!silent)
+ to_chat(user, span_warning("Their earsockets need to be unexposed."))
+ return FALSE
- var/target_require_ears_exposed = !!(required_from_target_exposed & INTERACTION_REQUIRE_EARS)
- var/target_require_ears_unexposed = !!(required_from_target_unexposed & INTERACTION_REQUIRE_EARS)
- if(target_require_ears_exposed || target_require_ears_unexposed)
- var/has_ears = target.has_ears()
- if(!target.getorganslot(ORGAN_SLOT_EARS))
- if(!silent)
- to_chat(target, span_warning("They don't have ears."))
- return FALSE
-
- if(!(target_require_ears_exposed && target_require_ears_unexposed))
- if(target_require_ears_exposed && has_ears == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their ears need to be exposed."))
- return FALSE
- if(target_require_ears_unexposed && has_ears == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their ears need to be unexposed."))
- return FALSE
-
- var/target_require_earsockets_exposed = !!(required_from_target_exposed & INTERACTION_REQUIRE_EARSOCKETS)
- var/target_require_earsockets_unexposed = !!(required_from_target_unexposed & INTERACTION_REQUIRE_EARSOCKETS)
- if(target_require_earsockets_exposed || target_require_earsockets_unexposed)
- var/has_ears = target.has_ears()
- if(target.getorganslot(ORGAN_SLOT_EARS))
- if(!silent)
- to_chat(target, span_warning("They have ears!"))
- return FALSE
-
- if(!(target_require_earsockets_exposed && target_require_earsockets_unexposed))
- if(target_require_earsockets_exposed && has_ears == HAS_UNEXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their earsockets need to be exposed."))
- return FALSE
- if(target_require_earsockets_unexposed && has_ears == HAS_EXPOSED_GENITAL)
- if(!silent)
- to_chat(target, span_warning("Their earsockets need to be unexposed."))
- return FALSE
-
- if(interaction_flags & INTERACTION_FLAG_EXTREME_CONTENT)
+ if(extreme)
var/client/cli = target.client
if(cli)
if(target.client.prefs.extremepref == "No")
@@ -470,7 +499,7 @@
to_chat(user, span_warning("For some reason, you don't want to do this to [target]."))
return FALSE
- if(interaction_flags & INTERACTION_FLAG_OOC_CONSENT)
+ if(require_ooc_consent)
if((!target.ckey) || (target.client && target.client.prefs.toggles & VERB_CONSENT))
return TRUE
return FALSE
@@ -530,20 +559,20 @@
. += "...are partially clothed."
else
. += "...are clothed."
- if(has_breasts() == HAS_EXPOSED_GENITAL)
+ if(has_breasts(REQUIRE_EXPOSED))
. += "...have breasts."
- if(has_penis() == HAS_EXPOSED_GENITAL)
+ if(has_penis(REQUIRE_EXPOSED))
. += "...have a penis."
- if(has_strapon() == HAS_EXPOSED_GENITAL)
+ if(has_strapon(REQUIRE_EXPOSED))
. += "...have a strapon."
- if(has_balls() == HAS_EXPOSED_GENITAL)
+ if(has_balls(REQUIRE_EXPOSED))
. += "...have a ballsack."
- if(has_vagina() == HAS_EXPOSED_GENITAL)
+ if(has_vagina(REQUIRE_EXPOSED))
. += "...have a vagina."
- if(has_anus() == HAS_EXPOSED_GENITAL)
+ if(has_anus(REQUIRE_EXPOSED))
. += "...have an anus."
- if(has_feet() == HAS_EXPOSED_GENITAL)
- switch(get_num_feet())
+ if(has_feet(REQUIRE_EXPOSED))
+ switch(has_feet(REQUIRE_EXPOSED))
if(2)
. += "...have a pair of feet."
if(1)
diff --git a/modular_sand/code/datums/interactions/lewd_objects.dm b/modular_sand/code/datums/interactions/lewd_objects.dm
index 0af25b9e07..8a16494225 100644
--- a/modular_sand/code/datums/interactions/lewd_objects.dm
+++ b/modular_sand/code/datums/interactions/lewd_objects.dm
@@ -13,14 +13,12 @@
if(BODY_ZONE_PRECISE_GROIN)
switch(hole)
if(CUM_TARGET_VAGINA)
- var/has_vagina = M.has_vagina()
- if(has_vagina == TRUE || has_vagina == HAS_EXPOSED_GENITAL)
+ if(M.has_vagina(REQUIRE_EXPOSED))
message = (user == M) ? pick("fucks [possessive_verb] own pussy with \the [src]","shoves \the [src] into [possessive_verb] pussy", "jams \the [src] into [possessive_verb] pussy") : pick("fucks [M] right in the pussy with \the [src]", "jams \the [src] right into [M]'s pussy")
lust_amt = NORMAL_LUST
organ = CUM_TARGET_VAGINA //SPLURT edit
if(CUM_TARGET_ANUS)
- var/has_anus = M.has_anus()
- if(has_anus == TRUE || has_anus == HAS_EXPOSED_GENITAL)
+ if(M.has_anus(REQUIRE_EXPOSED))
message = (user == M) ? pick("fucks [possessive_verb] own ass with \the [src]","shoves \the [src] into [possessive_verb] ass", "jams \the [src] into [possessive_verb] ass") : pick("fucks [M]'s asshole with \the [src]", "jams \the [src] into [M]'s ass")
lust_amt = NORMAL_LUST
organ = CUM_TARGET_ANUS //SPLURT edit
diff --git a/modular_sand/code/game/objects/items/fleshlight.dm b/modular_sand/code/game/objects/items/fleshlight.dm
index 1684a7c9e5..9b2b03916c 100644
--- a/modular_sand/code/game/objects/items/fleshlight.dm
+++ b/modular_sand/code/game/objects/items/fleshlight.dm
@@ -56,10 +56,9 @@
if(ishuman(M) && (M?.client?.prefs?.toggles & VERB_CONSENT))
switch(user.zone_selected)
if(BODY_ZONE_PRECISE_GROIN)
- var/has_penis = M.has_penis() || M.has_strapon()
- if(has_penis == TRUE || has_penis == HAS_EXPOSED_GENITAL)
+ if(M.has_penis(REQUIRE_EXPOSED) || M.has_strapon(REQUIRE_EXPOSED))
var/genital_name = (user == M) ? user.get_penetrating_genital_name() : M.get_penetrating_genital_name()
- message = (user == M) ? pick("pumps [src] on [possessive_verb] [genital_name]") : pick("pumps \the [src] on [M]'s [genital_name]")
+ message = (user == M) ? "pumps [src] on [possessive_verb] [genital_name]" : "pumps \the [src] on [M]'s [genital_name]"
lust_amt = NORMAL_LUST
if(message)
user.visible_message(span_lewd("[user] [message]."))
@@ -142,20 +141,192 @@
if(ishuman(M) && (M?.client?.prefs?.toggles & VERB_CONSENT) && useable) // I promise all those checks are worth it!
switch(user.zone_selected)
if(BODY_ZONE_PRECISE_GROIN)
- var/has_penis = M.has_penis()
- if(has_penis == TRUE || has_penis == HAS_EXPOSED_GENITAL)
- message = (user == M) ? pick("fucks into [src]") : pick("forces [M] to fuck into [src]")
- lust_amt = NORMAL_LUST
- P = M.getorganslot(ORGAN_SLOT_PENIS)
- target = P
+ switch(targetting)
+ if(CUM_TARGET_PENIS)
+ if(M.has_penis(REQUIRE_EXPOSED) || M.has_strapon(REQUIRE_EXPOSED))
+ switch(portalunderwear.targetting)
+ if(CUM_TARGET_PENIS)
+ user_message = (user == M) ? "frots with the [penis_names[3]] [name]" : "forces \the [M] to frot with the [penis_names[3]] [name]"
+ target_message = "frot with you"
+ target = CUM_TARGET_PENIS
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = NORMAL_LUST
+ if(CUM_TARGET_VAGINA)
+ user_message = (user == M) ? "fucks \the [src]'s pussy" : "forces \the [M] to fuck \the [src]'s pussy"
+ target_message = "fuck your pussy with their [penis_names[1]] [penis_names[2]]"
+ target = CUM_TARGET_PENIS
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = NORMAL_LUST
+ if(CUM_TARGET_ANUS)
+ user_message = (user == M) ? "fucks \the [src] anally" : "forces \the [M] to fuck \the [src] anally"
+ target_message = "fuck you anally with their [penis_names[1]] [penis_names[2]]"
+ target = CUM_TARGET_PENIS
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = NORMAL_LUST
+ if(CUM_TARGET_MOUTH)
+ user_message = (user == M) ? "fucks \the [src]'s mouth" : "forces \the [M] to fuck \the [src]'s mouth"
+ target_message = "fuck your mouth with their [penis_names[1]] [penis_names[2]]"
+ target = CUM_TARGET_PENIS
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = LOW_LUST
+ if(CUM_TARGET_URETHRA)
+ user_message = (user == M) ? "fucks \the [src]'s urethra" : "forces \the [M] to fuck \the [src]'s urethra"
+ target_message = "fuck your urethra with their [penis_names[1]] [penis_names[2]]"
+ target = CUM_TARGET_PENIS
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = LOW_LUST
+ else
+ to_chat(user, "The penis is covered or there is none! ")
+ if(CUM_TARGET_VAGINA)
+ if(M.has_vagina(REQUIRE_EXPOSED))
+ switch(portalunderwear.targetting)
+ if(CUM_TARGET_PENIS)
+ user_message = (user == M) ? "fucks the [penis_names[3]] [name]" : "fucks \the [M] with the [penis_names[3]] [name]"
+ target_message = "fuck your [penis_names[4]] with their pussy"
+ target = CUM_TARGET_VAGINA
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = NORMAL_LUST
+ if(CUM_TARGET_VAGINA)
+ user_message = (user == M) ? "grinds [M.p_their()] pussy into \the [src]'s pussy" : "rubs \the [src]'s pussy against \the [M]'s pussy"
+ target_message = "grind their pussy into yours"
+ target = CUM_TARGET_VAGINA
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = NORMAL_LUST
+ if(CUM_TARGET_ANUS)
+ user_message = (user == M) ? "grinds [M.p_their()] pussy into \the [src]'s anus" : "rubs \the [src]'s anus against \the [M]'s pussy"
+ target_message = "grind their pussy into your anus"
+ target = CUM_TARGET_VAGINA
+ user_lust_amt = LOW_LUST
+ target_lust_amt = LOW_LUST
+ if(CUM_TARGET_MOUTH)
+ user_message = (user == M) ? "grinds [M.p_their()] pussy into \the [src]'s mouth" : "rubs \the [src]'s mouth against \the [M]'s pussy"
+ target_message = "grind their pussy into your mouth"
+ target = CUM_TARGET_VAGINA
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = LOW_LUST
+ /* // i don't know how this would work
+ if(CUM_TARGET_URETHRA)
+ user_message = (user == M) ? "fucking urethra" : "force someone to fuck urethra"
+ target_message = "urethra fucked by pussy"
+ target = CUM_TARGET_VAGINA
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = LOW_LUST
+ */
+ else
+ to_chat(user, "The vagina is covered or there is none! ")
+ if(CUM_TARGET_ANUS)
+ if(M.has_anus(REQUIRE_EXPOSED))
+ switch(portalunderwear.targetting)
+ if(CUM_TARGET_PENIS)
+ user_message = (user == M) ? "uses the [penis_names[3]] [name] to fuck [M.p_them()]self anally" : "fucks \the [M] anally with the [penis_names[3]] [name]"
+ target_message = "fuck your [penis_names[4]] with an anus"
+ target = CUM_TARGET_ANUS
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = NORMAL_LUST
+ if(CUM_TARGET_VAGINA)
+ user_message = (user == M) ? "grinds [M.p_their()] anus into \the [src]'s pussy" : "rubs \the [src]'s pussy against \the [M]'s anus"
+ target_message = "grind their anus into your pussy"
+ target = CUM_TARGET_ANUS
+ user_lust_amt = LOW_LUST
+ target_lust_amt = LOW_LUST
+ if(CUM_TARGET_ANUS)
+ user_message = (user == M) ? "grinds [M.p_their()] anus into \the [src]'s anus" : "rubs \the [src]'s anus against \the [M]'s anus"
+ target_message = "grind their anus into yours"
+ target = CUM_TARGET_ANUS
+ user_lust_amt = LOW_LUST
+ target_lust_amt = LOW_LUST
+ if(CUM_TARGET_MOUTH)
+ user_message = (user == M) ? "grinds [M.p_their()] anus into \the [src]'s mouth" : "rubs \the [src]'s mouth against \the [M]'s anus"
+ target_message = "grind their anus into your mouth"
+ target = CUM_TARGET_ANUS
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = LOW_LUST
+ /* // i don't know how this would work
+ if(CUM_TARGET_URETHRA)
+ user_message = (user == M) ? "fucking urethra" : "force someone to fuck urethra"
+ target_message = "urethra fucked by ass"
+ target = CUM_TARGET_ANUS
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = LOW_LUST
+ */
+ else
+ to_chat(user, "The anus is covered or there is none! ")
+ if(CUM_TARGET_URETHRA)
+ if(M.has_penis(REQUIRE_EXPOSED) || M.has_strapon(REQUIRE_EXPOSED))
+ switch(portalunderwear.targetting)
+ if(CUM_TARGET_PENIS)
+ user_message = (user == M) ? "fuck your urethra with dick" : "fuck someone elses urethra with dick"
+ target_message = "dick is fucked by urethra"
+ target = CUM_TARGET_URETHRA
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = NORMAL_LUST
+ /* // I don't know how these would work
+ if(CUM_TARGET_VAGINA)
+ user_message = (user == M) ? "fuck your urethra with pussy" : "fuck someone elses urethra with pussy"
+ target_message = "pussy is fucked by urethra"
+ target = CUM_TARGET_URETHRA
+ user_lust_amt = LOW_LUST
+ target_lust_amt = LOW_LUST
+ if(CUM_TARGET_ANUS)
+ user_message = (user == M) ? "fuck your urethra with ass" : "fuck someone elses urethra with ass"
+ target_message = "ass is fucked by urethra"
+ target = CUM_TARGET_URETHRA
+ user_lust_amt = LOW_LUST
+ target_lust_amt = LOW_LUST
+ if(CUM_TARGET_MOUTH)
+ user_message = (user == M) ? "fuck your urethra with mouth" : "fuck someone elses urethra with mouth"
+ target_message = "mouth is fucked by urethra"
+ target = CUM_TARGET_URETHRA
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = LOW_LUST
+ if(CUM_TARGET_URETHRA)
+ user_message = (user == M) ? "fuck your urethra with partner urethra" : "fuck someone elses urethra with partner urethra"
+ target_message = "partner urethra is fucked by urethra"
+ target = CUM_TARGET_URETHRA
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = LOW_LUST
+ */
+ else
+ to_chat(user, "The urethra is covered or there is none! ")
if(BODY_ZONE_PRECISE_MOUTH)
- if(M.has_mouth() && !M.is_mouth_covered())
- message = (user == M) ? pick("licks into [src]") : pick("forces [M] to lick into [src]")
- lust_amt = NORMAL_LUST
- arouse_only_target = TRUE
- target = "mouth"
- if(BODY_ZONE_R_ARM)
- if(M.has_hand())
+ if((M.has_mouth() && !M.is_mouth_covered()))
+ switch(portalunderwear.targetting)
+ if(CUM_TARGET_PENIS)
+ user_message = (user == M) ? "sucks on the [penis_names[3]] [name]" : "forces \the [M] to suck on the [penis_names[3]] [name]"
+ target_message = "suck on your [penis_names[4]]"
+ target = CUM_TARGET_MOUTH
+ user_lust_amt = LOW_LUST
+ target_lust_amt = NORMAL_LUST
+ if(CUM_TARGET_VAGINA)
+ user_message = (user == M) ? "laps at \the [src]'s pussy" : "rubs \the [src]'s pussy against \the [M]'s mouth"
+ target_message = "lap at your pussy"
+ target = CUM_TARGET_MOUTH
+ user_lust_amt = LOW_LUST
+ target_lust_amt = NORMAL_LUST
+ if(CUM_TARGET_ANUS)
+ user_message = (user == M) ? "laps at \the [src]'s anus" : "rubs \the [src]'s anus against \the [M]'s mouth"
+ target_message = "lap at your anus"
+ target = CUM_TARGET_MOUTH
+ user_lust_amt = LOW_LUST
+ target_lust_amt = NORMAL_LUST
+ if(CUM_TARGET_MOUTH)
+ user_message = (user == M) ? "kisses \the [src]'s mouth" : "forces \the [src]'s lips and \the [M]'s lips together"
+ target_message = "kiss your mouth"
+ target = CUM_TARGET_MOUTH
+ user_lust_amt = LOW_LUST
+ target_lust_amt = LOW_LUST
+ /* // i don't know how this would work
+ if(CUM_TARGET_URETHRA)
+ user_message = (user == M) ? "fucking urethra" : "force someone to fuck urethra"
+ target_message = "urethra fucked by mouth"
+ target = CUM_TARGET_MOUTH
+ user_lust_amt = NORMAL_LUST
+ target_lust_amt = LOW_LUST
+ */
+ else
+ to_chat(user, "The mouth is covered or there is none! ")
+ if(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM)
+ if(M.has_hand(REQUIRE_ANY))
var/can_interact = FALSE
if(user.zone_selected == BODY_ZONE_R_ARM)
for(var/obj/item/bodypart/r_arm/R in M.bodyparts)
@@ -509,21 +680,19 @@
var/mob/living/carbon/human/human = M
switch(targetting)
if(CUM_TARGET_VAGINA)
- var/has_vagina = !human.has_vagina()
- if(has_vagina == TRUE || has_vagina == HAS_EXPOSED_GENITAL)
+ if(!human.has_vagina(REQUIRE_EXPOSED))
to_chat(human, span_warning("The vagina is covered or there is none!"))
return FALSE
if(CUM_TARGET_ANUS)
- var/has_anus = !human.has_anus()
- if(has_anus == TRUE || has_anus == HAS_EXPOSED_GENITAL)
+ if(!human.has_anus(REQUIRE_EXPOSED))
to_chat(human, span_warning("The anus is covered or there is none!"))
return FALSE
if(CUM_TARGET_PENIS)
- if(!human.has_penis() == HAS_EXPOSED_GENITAL && !human.has_strapon() == HAS_EXPOSED_GENITAL)
+ if(!human.has_penis(REQUIRE_EXPOSED) && !human.has_strapon(REQUIRE_EXPOSED))
to_chat(human, "The penis is covered or there is none! ")
return FALSE
if(CUM_TARGET_URETHRA)
- if(!human.has_penis() == HAS_EXPOSED_GENITAL && !human.has_strapon() == HAS_EXPOSED_GENITAL)
+ if(!human.has_penis(REQUIRE_EXPOSED) && !human.has_strapon(REQUIRE_EXPOSED))
to_chat(human, "The urethra is covered or there is none! ")
return FALSE
if(CUM_TARGET_MOUTH)
diff --git a/modular_sand/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/modular_sand/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index 54d3c8e407..7ae265d5f8 100644
--- a/modular_sand/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/modular_sand/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -61,7 +61,7 @@
/obj/item/projectile/kinetic/nopenalty/prehit_pierce(atom/target)
if(kinetic_gun)
- var/list/mods = kinetic_gun.modkits
+ var/list/mods = kinetic_gun.get_modkits()
for(var/obj/item/borg/upgrade/modkit/M in mods)
M.projectile_prehit(src, target, kinetic_gun)
return PROJECTILE_PIERCE_NONE
@@ -71,7 +71,7 @@
if(!target_turf)
target_turf = get_turf(src)
if(kinetic_gun) //hopefully whoever shot this was not very, very unfortunate.
- var/list/mods = kinetic_gun.modkits
+ var/list/mods = kinetic_gun.get_modkits()
for(var/obj/item/borg/upgrade/modkit/M in mods)
M.projectile_strike_predamage(src, target_turf, target, kinetic_gun)
for(var/obj/item/borg/upgrade/modkit/M in mods)
@@ -504,7 +504,7 @@
/obj/item/projectile/kinetic/etenmm/prehit_pierce(atom/target)
if(kinetic_gun)
- var/list/mods = kinetic_gun.modkits
+ var/list/mods = kinetic_gun.get_modkits()
for(var/obj/item/borg/upgrade/modkit/M in mods)
M.projectile_prehit(src, target, kinetic_gun)
return TRUE
@@ -514,7 +514,7 @@
if(!target_turf)
target_turf = get_turf(src)
if(kinetic_gun) //hopefully whoever shot this was not very, very unfortunate.
- var/list/mods = kinetic_gun.modkits
+ var/list/mods = kinetic_gun.get_modkits()
for(var/obj/item/borg/upgrade/modkit/M in mods)
M.projectile_strike_predamage(src, target_turf, target, kinetic_gun)
for(var/obj/item/borg/upgrade/modkit/M in mods)
diff --git a/tgui/packages/tgui-panel/chat/renderer.js b/tgui/packages/tgui-panel/chat/renderer.js
index 495ed32228..32a9b74ed0 100644
--- a/tgui/packages/tgui-panel/chat/renderer.js
+++ b/tgui/packages/tgui-panel/chat/renderer.js
@@ -443,9 +443,7 @@ class ChatRenderer {
const cssRules = styleSheets[i].cssRules;
for (let i = 0; i < cssRules.length; i++) {
const rule = cssRules[i];
- if (rule && typeof rule.cssText === 'string') {
- cssText += rule.cssText + '\n';
- }
+ cssText += rule.cssText + '\n';
}
}
cssText += 'body, html { background-color: #141414 }\n';
diff --git a/tgui/packages/tgui/interfaces/BorgPanel.js b/tgui/packages/tgui/interfaces/BorgPanel.js
index d92b7dd408..40d612679f 100644
--- a/tgui/packages/tgui/interfaces/BorgPanel.js
+++ b/tgui/packages/tgui/interfaces/BorgPanel.js
@@ -1,5 +1,5 @@
import { useBackend } from '../backend';
-import { Box, Button, Icon, LabeledList, ProgressBar, Section } from '../components';
+import { Box, Button, LabeledList, ProgressBar, Section } from '../components';
import { Window } from '../layouts';
export const BorgPanel = (props, context) => {
@@ -12,9 +12,6 @@ export const BorgPanel = (props, context) => {
const upgrades = data.upgrades || [];
const ais = data.ais || [];
const laws = data.laws || [];
-
- const active_upgrades = data.active_upgrades || [];
- const ka_remaining_capacity = data.ka_remaining_capacity || 0;
return (
{
))}
- {upgrades.map(upgrade => {
- if (!upgrade.module_type
- || (upgrade.module_type.includes(borg.active_module))) {
- const installedCount
- = active_upgrades.filter(installed_upgrade =>
- installed_upgrade.type === upgrade.type).length;
- const isInstalled = installedCount > 0;
- return (
- <>
- 1)
- && upgrade.cost
- !== null ? `(${installedCount} installed)` : ''}`
- : upgrade.name}
- selected={isInstalled}
- onClick={() => act('toggle_upgrade', {
- upgrade: upgrade.type,
- })} />
- {
- (!upgrade.denied_type || upgrade.maximum_of_type > 1)
- && upgrade.cost !== null
- ? (
- <>
- }
- disabled={ka_remaining_capacity < upgrade.cost
- || (upgrade.denied_type
- && (installedCount === upgrade.maximum_of_type))}
- onClick={() => act('add_upgrade', {
- upgrade: upgrade.type,
- })}
- />
- }
- disabled={!isInstalled}
- onClick={() => act('remove_upgrade', {
- upgrade: upgrade.type,
- })}
- />
- >
- ) : ""
- }
- >
- );
- } })}
+ {upgrades.map(upgrade => (
+ act('toggle_upgrade', {
+ upgrade: upgrade.type,
+ })} />
+ ))}
- {
- ka_remaining_capacity !== null
- && (
-
- {ka_remaining_capacity}
-
- )
- }
{ais.map(ai => (
{
const PageMessages = (props, context) => {
const { act, data } = useBackend(context);
const messages = data.messages || [];
- const { printerCooldown } = data;
const children = [];
@@ -705,15 +704,10 @@ const PageMessages = (props, context) => {
content={answer}
color={message.answered === answerIndex + 1 ? "good" : undefined}
key={answerIndex}
- onClick={
- message.answered
- ? undefined
- : () =>
- act("answerMessage", {
- message: parseInt(messageIndex, 10) + 1,
- answer: answerIndex + 1,
- })
- }
+ onClick={message.answered ? undefined : () => act("answerMessage", {
+ message: parseInt(messageIndex, 10) + 1,
+ answer: answerIndex + 1,
+ })}
/>
))}
@@ -729,24 +723,14 @@ const PageMessages = (props, context) => {
title={message.title}
key={messageIndex}
buttons={(
- <>
- act("printMessage", {
- message: parseInt(messageIndex, 10) + 1,
- })}
- />
- act("deleteMessage", {
- message: parseInt(messageIndex, 10) + 1,
- })}
- />
- >
+ act("deleteMessage", {
+ message: messageIndex + 1,
+ })}
+ />
)}>
@@ -777,7 +761,7 @@ export const CommunicationsConsole = (props, context) => {
return (
diff --git a/tgui/packages/tgui/interfaces/MobInteraction.tsx b/tgui/packages/tgui/interfaces/MobInteraction.tsx
index 4dedb2348f..f48a90f1a2 100644
--- a/tgui/packages/tgui/interfaces/MobInteraction.tsx
+++ b/tgui/packages/tgui/interfaces/MobInteraction.tsx
@@ -20,8 +20,6 @@ type HeaderInfo = {
type ContentInfo = {
interactions: InteractionData[];
- user_is_blacklisted: boolean;
- target_is_blacklisted: boolean;
}
type InteractionData = {
@@ -82,17 +80,6 @@ type ContentPrefsInfo = {
cum_onto_pref: boolean,
}
-const INTERACTION_NORMAL = 0;
-const INTERACTION_LEWD = 1;
-const INTERACTION_EXTREME = 2;
-
-const INTERACTION_FLAG_ADJACENT = (1<<0);
-const INTERACTION_FLAG_EXTREME_CONTENT = (1<<1);
-const INTERACTION_FLAG_OOC_CONSENT = (1<<2);
-const INTERACTION_FLAG_TARGET_NOT_TIRED = (1<<3);
-const INTERACTION_FLAG_USER_IS_TARGET = (1<<4);
-const INTERACTION_FLAG_USER_NOT_TIRED = (1<<5);
-
export const MobInteraction = (props, context) => {
const { act, data } = useBackend(context);
const {
@@ -148,15 +135,15 @@ export const MobInteraction = (props, context) => {
-
- {(!isTargetSelf && (theirLust !== null) ? (
+ {(!isTargetSelf && !isNaN(theirLust)) ? (
- ) : (null))}
+ ) : (null)}
@@ -210,12 +197,7 @@ const InteractionsTab = (props, context) => {
searchText,
setSearchText,
] = useLocalState(context, 'searchText', '');
- const interactions = sortInteractions(
- data.interactions,
- searchText,
- data)
- || [];
- const { user_is_blacklisted, target_is_blacklisted } = data;
+ const interactions = sortInteractions(data.interactions, searchText) || [];
return (
@@ -226,9 +208,7 @@ const InteractionsTab = (props, context) => {
act('interact', {
@@ -253,10 +233,11 @@ const InteractionsTab = (props, context) => {
) : (
{
- user_is_blacklisted || target_is_blacklisted
- ? `${user_is_blacklisted ? "Your" : "Their"} mob type is blacklisted from interactions`
- : searchText ? "No matching results."
- : "No interactions available."
+ searchText ? (
+ "No matching results."
+ ) : (
+ "No interactions available."
+ )
}
)
@@ -269,106 +250,14 @@ const InteractionsTab = (props, context) => {
/**
* Interaction sorter! also search box
*/
-export const sortInteractions = (interactions, searchText = '', data) => {
+export const sortInteractions = (interactions, searchText = '') => {
const testSearch = createSearch(searchText,
interaction => interaction.desc);
- const {
- extreme_pref,
- isTargetSelf,
- target_has_active_player,
- target_is_blacklisted,
- theyAllowExtreme,
- theyAllowLewd,
- user_is_blacklisted,
- verb_consent,
-
-
- max_distance,
- required_from_user,
- required_from_user_exposed,
- required_from_user_unexposed,
- user_num_feet,
-
- required_from_target,
- required_from_target_exposed,
- required_from_target_unexposed,
- target_num_feet,
- } = data;
return flow([
- // Blacklists completely disable any and all interactions
- filter(interaction =>
- !user_is_blacklisted && !target_is_blacklisted),
-
- // Optional search term, do before the others so we don't even run the tests
+ // Optional search term
searchText && filter(testSearch),
-
- // Filter off interactions depending on pref
- filter(interaction =>
- // Regular interaction
- (interaction.type === INTERACTION_NORMAL ? true
- // Lewd interaction
- : interaction.type === INTERACTION_LEWD ? verb_consent
- // Extreme interaction
- : verb_consent && extreme_pref)),
-
- // Filter off interactions depending on target's pref
- filter(interaction =>
- // If it's ourself, we've just checked it above, ignore
- ((isTargetSelf || (target_has_active_player === 0)) ? true
- // Regular interaction
- : interaction.type === INTERACTION_NORMAL ? true
- // Lewd interaction
- : interaction.type === INTERACTION_LEWD ? theyAllowLewd
- // Extreme interaction
- : theyAllowLewd && theyAllowExtreme)),
-
- // Is self
- filter(interaction =>
- (isTargetSelf ? (INTERACTION_FLAG_USER_IS_TARGET
- & interaction.interactionFlags)
- : !(INTERACTION_FLAG_USER_IS_TARGET & interaction.interactionFlags))),
- // Has a player or none at all
- filter(interaction =>
- (!isTargetSelf && (target_has_active_player === 1)
- ? !(INTERACTION_FLAG_OOC_CONSENT
- & interaction.interactionFlags) : true)),
- // Distance
- filter(interaction =>
- interaction.maxDistance >= max_distance),
- // User requirements
- filter(interaction =>
- interaction.required_from_user
- ? !!(required_from_user & interaction.required_from_user) : true),
- // User requires exposed
- filter(interaction => interaction.required_from_user_exposed
- ? !!(required_from_user_exposed
- & interaction.required_from_user_exposed) : true),
- // User requires unexposed
- filter(interaction => interaction.required_from_user_unexposed
- ? !!(required_from_user_unexposed
- & interaction.required_from_user_unexposed) : true),
- // User required feet amount
- filter(interaction => interaction.user_num_feet
- ? (interaction.user_num_feet <= user_num_feet) : true),
- // Target requirements
- filter(interaction => interaction.required_from_target
- ? !!(required_from_target
- & interaction.required_from_target) : true),
- // Target requires exposed
- filter(interaction => interaction.required_from_target_exposed
- ? !!(required_from_target_exposed
- & interaction.required_from_target_exposed) : true),
- // Target requires unexposed
- filter(interaction => interaction.required_from_target_unexposed
- ? !!(required_from_target_unexposed
- & interaction.required_from_target_unexposed) : true),
- // Target required feet amount
- filter(interaction => interaction.target_num_feet
- ? (interaction.target_num_feet <= target_num_feet) : true),
-
- // Searching by "desc"
+ // Slightly expensive, but way better than sorting in BYOND
sortBy(interaction => interaction.desc),
- // Searching by type
sortBy(interaction => interaction.type),
])(interactions);
};
diff --git a/tgui/packages/tgui/interfaces/NtosRobotact.js b/tgui/packages/tgui/interfaces/NtosRobotact.js
index 3cf85e0605..584b73c2de 100644
--- a/tgui/packages/tgui/interfaces/NtosRobotact.js
+++ b/tgui/packages/tgui/interfaces/NtosRobotact.js
@@ -213,16 +213,13 @@ export const NtosRobotactContent = (props, context) => {
)}
{tab_sub === 2 && (
- {borgUpgrades.filter((upgrade, index, arr) =>
- arr.indexOf(upgrade) === index).map(upgrade => {
- const upgradeCount = borgUpgrades.filter(u =>
- u === upgrade).length;
- return (
-
- {upgrade} {upgradeCount > 1 ? `x${upgradeCount}` : ''}
-
- );
- })}
+ {borgUpgrades.map(upgrade => (
+
+ {upgrade}
+
+ ))}
)}
{tab_sub === 3 && (