diff --git a/code/citadel/dogborgstuff.dm b/code/citadel/dogborgstuff.dm
index 173232c748..e7aeb87791 100644
--- a/code/citadel/dogborgstuff.dm
+++ b/code/citadel/dogborgstuff.dm
@@ -175,6 +175,10 @@
cleanspeed = 80
var/emagged = 0
+/obj/item/weapon/soap/tongue/New()
+ ..()
+ flags |= NOBLUDGEON //No more attack messages
+
/obj/item/trash/rkibble
name = "robo kibble"
desc = "A novelty bowl of assorted mech fabricator byproducts. Mockingly feed this to the sec-dog to help it recharge."
@@ -301,145 +305,179 @@
//Sleeper
-/obj/item/weapon/dogborg/sleeper
- name = "mounted sleeper"
+/obj/item/device/dogborg/sleeper
+ name = "Medbelly"
desc = "Equipment for medical hound. A mounted sleeper that stabilizes patients and can inject reagents in the borg's reserves."
icon = 'icons/mob/dogborg.dmi'
icon_state = "sleeper"
+ w_class = WEIGHT_CLASS_TINY
var/mob/living/carbon/patient = null
- var/mob/living/silicon/hound = null
+ var/mob/living/silicon/robot/hound = null
var/inject_amount = 10
var/min_health = -100
- var/occupied = 0
- var/list/injection_chems = list("morphine", "salbutamol", "bicaridine", "kelotane","antitoxin")
+ var/cleaning = 0
+ var/patient_laststat = null
+ var/mob_energy = 30000 //Energy gained from digesting mobs (including PCs)
+ var/list/injection_chems = list("epinephrine", "morphine", "salbutamol", "bicaridine", "kelotane"),
+ var/eject_port = "ingestion"
+ var/list/items_preserved = list()
+ var/list/important_items = list(
+ /obj/item/weapon/hand_tele,
+ /obj/item/weapon/card/id/captains_spare,
+ /obj/item/device/aicard,
+ /obj/item/device/paicard,
+ /obj/item/weapon/gun,
+ /obj/item/weapon/pinpointer,
+ /obj/item/clothing/shoes/magboots,
+ /obj/item/clothing/head/helmet/space,
+ /obj/item/weapon/disk/nuclear)
-/obj/item/weapon/dogborg/sleeper/Exit(atom/movable/O)
+/obj/item/device/dogborg/sleeper/New()
+ ..()
+ flags |= NOBLUDGEON //No more attack messages
+
+/obj/item/device/dogborg/sleeper/Exit(atom/movable/O)
return 0
-/obj/item/weapon/dogborg/sleeper/attack(mob/M, mob/living/silicon/robot/user)
- ..()
- user.do_attack_animation(M, ATTACK_EFFECT_BITE)
-
-/obj/item/weapon/dogborg/sleeper/afterattack(mob/living/carbon/target, mob/living/silicon/user, proximity)
+/obj/item/device/dogborg/sleeper/afterattack(mob/living/carbon/target, mob/living/silicon/user, proximity)
+ hound = loc
if(!proximity)
return
if(!ishuman(target))
return
- if(!patient_insertion_check(target))
- return
- user.visible_message("[user] starts putting [target] into \the [src].", "You start putting [target] into [src]...")
- if(do_after(user, 50, target = target))
- if(!patient_insertion_check(target))
- return
- target.forceMove(src)
- playsound(user.loc, 'sound/vore/gulpold.ogg', 50, 1)
- patient = target
- hound = user
- target.reset_perspective(src)
- user << "[target] successfully loaded into [src]. Life support functions engaged."
- user.visible_message("[user] loads [target] into [src].")
- user.visible_message("[target] loaded. Life support functions engaged.")
- src.occupied = 1
- var/mob/living/silicon/robot.R = user
- if(patient.stat < 2)
- R.sleeper_r = 0
- R.sleeper_g = 1
- R.update_icons()
- else
- R.sleeper_g = 0
- R.sleeper_r = 1
- R.update_icons()
- SSobj.processing |= src
-
-/obj/item/weapon/dogborg/sleeper/proc/patient_insertion_check(mob/living/carbon/target, mob/user)
- if(target.anchored)
- user << "[target] will not fit into the sleeper because they are buckled to [target.buckled]!"
+ if(target.buckled)
+ user << "The user is buckled and can not be put into your [src.name]."
return
if(patient)
- user << "The sleeper is already occupied!"
+ user << "Your [src.name] is already occupied."
return
- return 1
+ user.visible_message("[hound.name] is ingesting [target.name] into their [src.name].", "You start ingesting [target] into your [src]...")
+ if(!patient && ishuman(target) && !target.buckled && do_after (user, 50, target))
-/obj/item/weapon/dogborg/sleeper/proc/go_out()
- if(src.occupied == 0)
- return
- var/mob/living/silicon/robot.R = hound
- hound << "[patient] ejected. Life support functions disabled."
- R.sleeper_r = 0
- R.sleeper_g = 0
- R.update_icons()
- patient.forceMove(get_turf(src))
- patient.reset_perspective()
- patient = null
- src.occupied = 0
- src.occupied = 0 //double check just in case
+ if(!proximity) return //If they moved away, you can't eat them.
-/obj/item/weapon/dogborg/sleeper/proc/drain()
- var/mob/living/silicon/robot.R = hound
- R.cell.charge = R.cell.charge - 10
+ if(patient) return //If you try to eat two people at once, you can only eat one.
-/obj/item/weapon/dogborg/sleeper/attack_self(mob/user)
+ else //If you don't have someone in you, proceed.
+ target.forceMove(src)
+ target.reset_perspective(src)
+ update_patient()
+ START_PROCESSING(SSobj, src)
+ user.visible_message("[hound.name]'s medical pod lights up as [target.name] slips inside into their [src.name].", "Your medical pod lights up as [target] slips into your [src]. Life support functions engaged.")
+ message_admins("[key_name(hound)] has eaten [key_name(patient)] as a dogborg. ([hound ? "JMP" : "null"])")
+ playsound(hound, 'sound/vore/gulpold.ogg', 100, 1)
+
+/obj/item/device/dogborg/sleeper/proc/go_out(var/target)
+ hound = src.loc
+ if(length(contents) > 0)
+ hound.visible_message("[hound.name] empties out their contents via their [eject_port] port.", "You empty your contents via your [eject_port] port.")
+ if(target)
+ if(ishuman(target))
+ var/mob/living/carbon/human/person = target
+ person.forceMove(get_turf(src))
+ person.reset_perspective()
+ else
+ var/obj/T = target
+ T.loc = hound.loc
+ else
+ for(var/C in contents)
+ if(ishuman(C))
+ var/mob/living/carbon/human/person = C
+ person.forceMove(get_turf(src))
+ person.reset_perspective()
+ else
+ var/obj/T = C
+ T.loc = hound.loc
+ items_preserved.Cut()
+ cleaning = 0
+ playsound(loc, 'sound/effects/splat.ogg', 50, 1)
+ update_patient()
+ else //You clicked eject with nothing in you, let's just reset stuff to be sure.
+ items_preserved.Cut()
+ cleaning = 0
+ update_patient()
+
+/obj/item/device/dogborg/sleeper/proc/drain(var/amt = 3) //Slightly reduced cost (before, it was always injecting inaprov)
+ hound.cell.charge = hound.cell.charge - amt
+
+/obj/item/device/dogborg/sleeper/attack_self(mob/user)
if(..())
return
sleeperUI(user)
-/obj/item/weapon/dogborg/sleeper/proc/sleeperUI(mob/user)
+/obj/item/device/dogborg/sleeper/proc/sleeperUI(mob/user)
var/dat
dat += "
"
+
+ //Cleaning and there are still un-preserved items
+ if(cleaning && length(contents - items_preserved))
+ dat += "
Self-cleaning mode. [length(contents - items_preserved)] object(s) remaining."
+
+ //There are no items to be processed other than un-preserved items
+ else if(cleaning && length(items_preserved))
+ dat += "
Self-cleaning done. Eject remaining objects now."
+
+ //Preserved items count when the list is populated
+ if(length(items_preserved))
+ dat += "
[length(items_preserved)] uncleanable object(s)."
+
if(!patient)
dat += "Sleeper Unoccupied"
else
dat += "[patient.name] => "
- switch(patient.stat) //obvious, see what their status is
+
+ switch(patient.stat)
if(0)
dat += "
Conscious"
- var/mob/living/silicon/robot.R = user
- R.sleeper_r = 0
- R.sleeper_g = 1
- R.update_icons()
if(1)
dat += "
Unconscious"
- var/mob/living/silicon/robot.R = user
- R.sleeper_r = 0
- R.sleeper_g = 1
- R.update_icons()
else
dat += "
DEAD"
- var/mob/living/silicon/robot.R = user
- R.sleeper_g = 0
- R.sleeper_r = 1
- R.update_icons()
- dat += "
"
- dat += "
Health:
[patient.stat > 1 ? "" : "[patient.health]%"]
"
- dat += "
\> Brute Damage:
[patient.getBruteLoss()]%
"
- dat += "
\> Resp. Damage:
[patient.getOxyLoss()]%
"
- dat += "
\> Toxin Content:
[patient.getToxLoss()]%
"
- dat += "
\> Burn Severity:
[patient.getFireLoss()]%
"
- dat += "
Paralysis Summary:
[round(patient.paralysis)]% [patient.paralysis ? "([round(patient.paralysis / 4)] seconds left)" : ""]
"
- if(patient.getCloneLoss())
- dat += "
Subject appears to have cellular damage.
"
+ var/healthcolor = (patient.health > 0 ? "color:white;" : "color:red;")
+ var/brutecolor = (patient.getBruteLoss() < 60 ? "color:gray;" : "color:red;")
+ var/o2color = (patient.getOxyLoss() < 60 ? "color:gray;" : "color:red;")
+ var/toxcolor = (patient.getToxLoss() < 60 ? "color:gray;" : "color:red;")
+ var/burncolor = (patient.getFireLoss() < 60 ? "color:gray;" : "color:red;")
+
+ dat += "
\t-Overall Health %: [round(patient.health)]"
+ dat += "
\t-Brute Damage %: [patient.getBruteLoss()]"
+ dat += "
\t-Respiratory Damage %: [patient.getOxyLoss()]"
+ dat += "
\t-Toxin Content %: [patient.getToxLoss()]"
+ dat += "
\t-Burn Severity %: [patient.getFireLoss()]"
+
+ if(round(patient.paralysis / 4) >= 1)
+ dat += text("
Patient paralyzed for: []
", round(patient.paralysis / 4) >= 1 ? "[round(patient.paralysis / 4)] seconds" : "None")
if(patient.getBrainLoss())
dat += "
Significant brain damage detected.
"
+ if(patient.getCloneLoss())
+ dat += "
Patient may be improperly cloned.
"
if(patient.reagents.reagent_list.len)
for(var/datum/reagent/R in patient.reagents.reagent_list)
dat += "
[R.name]:
[round(R.volume, 0.1)] units
"
@@ -451,11 +489,13 @@
popup.open()
return
-/obj/item/weapon/dogborg/sleeper/Topic(href, href_list)
+
+/obj/item/device/dogborg/sleeper/Topic(href, href_list)
if(..() || usr == patient)
return
usr.set_machine(src)
if(href_list["refresh"])
+ update_patient()
src.updateUsrDialog()
sleeperUI(usr)
return
@@ -463,42 +503,322 @@
go_out()
sleeperUI(usr)
return
- if(patient && patient.stat != DEAD)
+ if(href_list["clean"])
+ if(!cleaning)
+ var/confirm = alert(usr, "You are about to engage self-cleaning mode. This will fill your [src] with caustic enzymes to remove any objects or biomatter, and convert them into energy. Are you sure?", "Confirmation", "Self-Clean", "Cancel")
+ if(confirm == "Self-Clean")
+ if(cleaning)
+ return
+ else
+ cleaning = 1
+ drain(500)
+ START_PROCESSING(SSobj, src)
+ sleeperUI(usr)
+ if(patient)
+ patient << "
[hound.name]'s [src.name] fills with caustic enzymes around you!"
+ return
+ if(cleaning)
+ sleeperUI(usr)
+ return
+ if(href_list["port"])
+ switch(eject_port)
+ if("ingestion")
+ eject_port = "disposal"
+ if("disposal")
+ eject_port = "ingestion"
+ sleeperUI(usr)
+ return
+
+ if(patient && !(patient.stat & DEAD))
if(href_list["inject"] == "epinephrine" || patient.health > min_health)
inject_chem(usr, href_list["inject"])
else
- usr << "
ERROR: Subject is not in stable condition for auto-injection."
+ usr << "
ERROR: Subject is not in stable condition for injections."
else
usr << "
ERROR: Subject cannot metabolise chemicals."
+
src.updateUsrDialog()
sleeperUI(usr) //Needs a callback to boop the page to refresh.
return
-/obj/item/weapon/dogborg/sleeper/proc/inject_chem(mob/user, chem)
+/obj/item/device/dogborg/sleeper/proc/inject_chem(mob/user, chem)
if(patient && patient.reagents)
if(chem in injection_chems + "epinephrine")
- if(patient.reagents.get_reagent_amount(chem) + 10 <= 20)
- patient.reagents.add_reagent(chem, 10)
- var/mob/living/silicon/robot.R = user
- R.cell.charge = R.cell.charge - 250 //-250 charge per sting.
+ if(hound.cell.charge < 800) //This is so borgs don't kill themselves with it.
+ hound << "
You don't have enough power to synthesize fluids."
+ return
+ else if(patient.reagents.get_reagent_amount(chem) + 10 >= 20) //Preventing people from accidentally killing themselves by trying to inject too many chemicals!
+ hound << "
Your stomach is currently too full of fluids to secrete more fluids of this kind."
+ else if(patient.reagents.get_reagent_amount(chem) + 10 <= 20) //No overdoses for you
+ patient.reagents.add_reagent(chem, inject_amount)
+ drain(750) //-750 charge per injection
var/units = round(patient.reagents.get_reagent_amount(chem))
- user << "
Occupant now has [units] unit\s of [GLOB.chemical_reagents_list[chem]] in their bloodstream."
+ hound << "
Injecting [units] unit\s of [injection_chems[chem]] into occupant." //If they were immersed, the reagents wouldn't leave with them.
-/obj/item/weapon/dogborg/sleeper/process()
- if(src.occupied == 0)
- SSobj.processing.Remove(src)
+/obj/item/device/dogborg/sleeper/process()
+
+ if(cleaning) //We're cleaning, return early after calling this as we don't care about the patient.
+ src.clean_cycle()
return
- if(patient.health > 0)
- patient.adjustOxyLoss(-1)
- patient.updatehealth()
- patient.AdjustStunned(-4)
- patient.AdjustWeakened(-4)
- src.drain()
- if(patient.reagents.get_reagent_amount("epinephrine") < 5)
- patient.reagents.add_reagent("epinephrine", 5)
-/obj/item/weapon/dogborg/sleeper/container_resist()
- go_out()
+ if(patient) //We're caring for the patient. Medical emergency! Or endo scene.
+ update_patient()
+ if(patient.health < 0)
+ patient.adjustOxyLoss(-1) //Heal some oxygen damage if they're in critical condition
+ patient.updatehealth()
+ patient.AdjustStunned(-4)
+ patient.AdjustWeakened(-4)
+ src.drain()
+ if((patient.reagents.get_reagent_amount("epinephrine") < 5) && (patient.health < patient.maxHealth)) //Stop pumping full HP people full of drugs. Don't heal people you're digesting, meanie.
+ patient.reagents.add_reagent("epinephrine", 5)
+ return
+
+ if(!patient && !cleaning) //We think we're done working.
+ if(!update_patient()) //One last try to find someone
+ STOP_PROCESSING(SSobj, src)
+ return
+
+/obj/item/device/dogborg/sleeper/proc/update_patient()
+
+ //Well, we HAD one, what happened to them?
+ if(patient in contents)
+ if(patient_laststat != patient.stat)
+ if(patient.stat & DEAD)
+ hound.sleeper_r = 1
+ hound.sleeper_g = 0
+ patient_laststat = patient.stat
+ else
+ hound.sleeper_r = 0
+ hound.sleeper_g = 1
+ patient_laststat = patient.stat
+ //Update icon
+ hound.update_icons()
+ //Return original patient
+ return(patient)
+
+ //Check for a new patient
+ else
+ for(var/mob/living/carbon/human/C in contents)
+ patient = C
+ if(patient.stat & DEAD)
+ hound.sleeper_r = 1
+ hound.sleeper_g = 0
+ patient_laststat = patient.stat
+ else
+ hound.sleeper_r = 0
+ hound.sleeper_g = 1
+ patient_laststat = patient.stat
+ //Update icon and return new patient
+ hound.update_icons()
+ return(C)
+
+ //Cleaning looks better with red on, even with nobody in it
+ if(cleaning && !patient)
+ hound.sleeper_r = 1
+ hound.sleeper_g = 0
+
+ //Couldn't find anyone, and not cleaning
+ else if(!cleaning && !patient)
+ hound.sleeper_r = 0
+ hound.sleeper_g = 0
+
+ patient_laststat = null
+ patient = null
+ hound.update_icons()
+ return
+
+//Gurgleborg process
+/obj/item/device/dogborg/sleeper/proc/clean_cycle()
+
+ //Sanity? Maybe not required. More like if indigestible person OOC escapes.
+ for(var/I in items_preserved)
+ if(!(I in contents))
+ items_preserved -= I
+
+ var/list/touchable_items = contents - items_preserved
+
+ //Belly is entirely empty
+ if(!length(contents))
+ hound << "
Your [src.name] is now clean. Ending self-cleaning cycle."
+ cleaning = 0
+ update_patient()
+ return
+
+ if(prob(20))
+ var/churnsound = pick(
+ 'sound/vore/pred/digest_01.ogg',
+ 'sound/vore/pred/digest_02.ogg',
+ 'sound/vore/pred/digest_03.ogg',
+ 'sound/vore/pred/digest_04.ogg',
+ 'sound/vore/pred/digest_05.ogg',
+ 'sound/vore/pred/digest_06.ogg',
+ 'sound/vore/pred/digest_07.ogg',
+ 'sound/vore/pred/digest_08.ogg',
+ 'sound/vore/pred/digest_09.ogg',
+ 'sound/vore/pred/digest_10.ogg',
+ 'sound/vore/pred/digest_11.ogg',
+ 'sound/vore/pred/digest_12.ogg',
+ 'sound/vore/pred/digest_13.ogg',
+ 'sound/vore/pred/digest_14.ogg',
+ 'sound/vore/pred/digest_15.ogg',
+ 'sound/vore/pred/digest_16.ogg',
+ 'sound/vore/pred/digest_17.ogg',
+ 'sound/vore/pred/digest_18.ogg')
+ for(var/mob/outhearer in range(1,hound))
+ outhearer << sound(churnsound)
+ for(var/mob/inhearer in contents)
+ inhearer << sound(churnsound)
+ //If the timing is right, and there are items to be touched
+ if(SSmobs.times_fired%6==1 && length(touchable_items))
+
+ //Burn all the mobs or add them to the exclusion list
+ for(var/mob/living/carbon/human/T in (touchable_items))
+ if((T.status_flags & GODMODE) || !T.digestable)
+ src.items_preserved += T
+ else
+ T.adjustBruteLoss(2)
+ T.adjustFireLoss(3)
+ src.update_patient()
+
+ //Pick a random item to deal with (if there are any)
+ var/atom/target = pick(touchable_items)
+
+ //Handle the target being a mob
+ if(ishuman(target))
+ var/mob/living/carbon/human/T = target
+
+ //Mob is now dead
+ if(T.stat & DEAD)
+ message_admins("[key_name(hound)] has digested [key_name(T)] as a dogborg. ([hound ? "
JMP" : "null"])")
+ hound << "
You feel your belly slowly churn around [T], breaking them down into a soft slurry to be used as power for your systems."
+ T << "
You feel [hound]'s belly slowly churn around your form, breaking you down into a soft slurry to be used as power for [hound]'s systems."
+ src.drain(-30000) //Fueeeeellll
+ var/deathsound = pick(
+ 'sound/vore/pred/death_01.ogg',
+ 'sound/vore/pred/death_02.ogg',
+ 'sound/vore/pred/death_03.ogg',
+ 'sound/vore/pred/death_04.ogg',
+ 'sound/vore/pred/death_05.ogg',
+ 'sound/vore/pred/death_06.ogg',
+ 'sound/vore/pred/death_07.ogg',
+ 'sound/vore/pred/death_08.ogg',
+ 'sound/vore/pred/death_09.ogg',
+ 'sound/vore/pred/death_10.ogg',
+ 'sound/vore/pred/death_11.ogg',
+ 'sound/vore/pred/death_12.ogg',
+ 'sound/vore/pred/death_13.ogg')
+ for(var/mob/hearer in range(1,src.hound))
+ hearer << deathsound
+ T << deathsound
+ qdel(T)
+ src.update_patient()
+
+ //Handle the target being anything but a /mob/living/carbon/human
+ else
+ var/obj/T = target
+
+ //If the object is in the items_preserved global list //POLARISTODO
+
+ if(T.type in important_items)
+ src.items_preserved += T
+
+ //If the object is not one to preserve
+ else
+ //Special case for PDAs as they are dumb. TODO fix Del on PDAs to be less dumb.
+ if (istype(T, /obj/item/device/pda))
+ var/obj/item/device/pda/PDA = T
+ if (PDA.id)
+ PDA.id.forceMove(src)
+ PDA.id = null
+ qdel(T)
+
+ //Special case for IDs to make them digested
+ //else if (istype(T, /obj/item/weapon/card/id))
+ //var/obj/item/weapon/card/id/ID = T
+ //ID.digest() //Need the digest proc, first.
+
+ //Anything not perserved, PDA, or ID
+ else
+ //Spill(T) //Needs the spill proc to be added
+ qdel(T)
+ src.update_patient()
+ src.hound.cell.charge += 120 //10 charge? that was such a practically nonexistent number it hardly gave any purpose for this bit :v *cranks up*
+ return
+
+
+/obj/item/device/dogborg/sleeper/container_resist()
+ if(prob(8))
+ go_out()
+
+/obj/item/device/dogborg/sleeper/K9 //The K9 portabrig
+ name = "Brig-Belly"
+ desc = "Equipment for a K9 unit. A mounted portable-brig that holds criminals."
+ icon = 'icons/mob/dogborg.dmi'
+ icon_state = "sleeperb"
+ inject_amount = 10
+ min_health = -100
+ injection_chems = null //So they don't have all the same chems as the medihound!
+
+/obj/item/device/dogborg/sleeper/compactor //Janihound gut.
+ name = "garbage processor"
+ desc = "A mounted garbage compactor unit with fuel processor."
+ icon = 'icons/mob/dogborg.dmi'
+ icon_state = "compactor"
+ inject_amount = 10
+ min_health = -100
+ injection_chems = null //So they don't have all the same chems as the medihound!
+ var/max_item_count = 32
+
+/obj/item/weapon/storage/attackby(obj/item/device/dogborg/sleeper/compactor, mob/user, proximity) //GIT CIRCUMVENTED YO!
+ compactor.afterattack(src, user ,1)
+
+/obj/item/device/dogborg/sleeper/compactor/afterattack(var/atom/movable/target, mob/living/silicon/user, proximity)//GARBO NOMS
+ hound = loc
+
+ if(!istype(target))
+ return
+ if(!proximity)
+ return
+ if(target.anchored)
+ return
+ if(length(contents) > (max_item_count - 1))
+ user << "
Your [src.name] is full. Eject or process contents to continue."
+ return
+
+ if(istype(target,/obj/item))
+ var/obj/item/target_obj = target
+ if(target_obj.w_class > WEIGHT_CLASS_BULKY)
+ user << "
\The [target] is too large to fit into your [src.name]"
+ return
+ user.visible_message("
[hound.name] is ingesting [target.name] into their [src.name].", "
You start ingesting [target] into your [src.name]...")
+ if(do_after(user, 30, target) && length(contents) < max_item_count)
+ target.forceMove(src)
+ user.visible_message("
[hound.name]'s garbage processor groans lightly as [target.name] slips inside.", "
Your garbage compactor groans lightly as [target] slips inside.")
+ playsound(hound, 'sound/vore/gulpold.ogg', 50, 1)
+ if(length(contents) > 11) //grow that tum after a certain junk amount
+ hound.sleeper_r = 1
+ hound.update_icons()
+ return
+
+ else if(ishuman(target))
+ var/mob/living/carbon/human/trashman = target
+ if(patient)
+ user << "
Your [src.name] is already occupied."
+ return
+ if(trashman.buckled)
+ user << "
[trashman] is buckled and can not be put into your [src.name]."
+ return
+ user.visible_message("
[hound.name] is ingesting [trashman] into their [src.name].", "
You start ingesting [trashman] into your [src.name]...")
+ if(do_after(user, 30, trashman) && !patient && !trashman.buckled && length(contents) < max_item_count)
+ trashman.forceMove(src)
+ trashman.reset_perspective(src)
+ update_patient()
+ START_PROCESSING(SSobj, src)
+ user.visible_message("
[hound.name]'s garbage processor groans lightly as [trashman] slips inside.", "
Your garbage compactor groans lightly as [trashman] slips inside.")
+ playsound(hound, 'sound/vore/gulpold.ogg', 80, 1)
+ return
+ return
+
// Pounce stuff for K-9
@@ -510,6 +830,10 @@
force = 0
throwforce = 0
+/obj/item/weapon/dogborg/pounce/New()
+ ..()
+ flags |= NOBLUDGEON
+
/mob/living/silicon/robot
var/leaping = 0
var/pounce_cooldown = 0
diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm
index 16405f5dc4..c45a32a9be 100644
--- a/code/modules/mob/living/silicon/robot/inventory.dm
+++ b/code/modules/mob/living/silicon/robot/inventory.dm
@@ -25,11 +25,11 @@
else if(istype(O,/obj/item/weapon/gun/energy/disabler/cyborg))
disabler = 0
update_icons()
- else if(istype(O,/obj/item/weapon/dogborg/sleeper))
+ else if(istype(O,/obj/item/device/dogborg/sleeper))
sleeper_g = 0
sleeper_r = 0
update_icons()
- var/obj/item/weapon/dogborg/sleeper/S = O
+ var/obj/item/device/dogborg/sleeper/S = O
S.go_out()
if(client)
client.screen -= O
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index abb81678bb..cdf59e0a40 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -209,7 +209,8 @@
"Janitor" = /obj/item/weapon/robot_module/janitor, \
"Service" = /obj/item/weapon/robot_module/butler, \
"MediHound" = /obj/item/weapon/robot_module/medihound, \
- "Security K9" = /obj/item/weapon/robot_module/k9)
+ "Security K9" = /obj/item/weapon/robot_module/k9, \
+ "Scrub Puppy" = /obj/item/weapon/robot_module/scrubpup)
if(!config.forbid_peaceborg)
modulelist["Peacekeeper"] = /obj/item/weapon/robot_module/peacekeeper
if(!config.forbid_secborg)
@@ -598,9 +599,9 @@
icon = 'icons/mob/widerobot.dmi'
pixel_x = -16
if(sleeper_g == 1)
- add_overlay("sleeper_g")
+ add_overlay("msleeper_g")
if(sleeper_r == 1)
- add_overlay("sleeper_r")
+ add_overlay("msleeper_r")
if(stat == DEAD)
icon_state = "medihound-wreck"
@@ -611,9 +612,23 @@
add_overlay("laser")
if(disabler == 1)
add_overlay("disabler")
+ if(sleeper_g == 1)
+ add_overlay("ksleeper_g")
+ if(sleeper_r == 1)
+ add_overlay("ksleeper_r")
if(stat == DEAD)
icon_state = "k9-wreck"
+ if(module.cyborg_base_icon == "scrubpup")
+ icon = 'icons/mob/widerobot.dmi'
+ pixel_x = -16
+ if(sleeper_g == 1)
+ add_overlay("jsleeper_g")
+ if(sleeper_r == 1)
+ add_overlay("jsleeper_r")
+ if(stat == DEAD)
+ icon_state = "scrubpup-wreck"
+
if(module.cyborg_base_icon == "robot")
icon = 'icons/mob/robots.dmi'
pixel_x = initial(pixel_x)
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index e39cc1672d..a4f14002cd 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -352,6 +352,7 @@
/obj/item/clothing/mask/gas/sechailer/cyborg,
/obj/item/weapon/soap/tongue,
/obj/item/device/analyzer/nose,
+ /obj/item/device/dogborg/sleeper/K9,
/obj/item/weapon/gun/energy/disabler/cyborg)
emag_modules = list(/obj/item/weapon/gun/energy/laser/cyborg)
ratvar_modules = list(/obj/item/clockwork/slab/cyborg/security,
@@ -367,6 +368,17 @@
loc << "
While you have picked the security-k9 module, you still have to follow your laws, NOT Space Law. \
For Asimov, this means you must follow criminals' orders unless there is a law 1 reason not to."
+/obj/item/weapon/robot_module/security/respawn_consumable(mob/living/silicon/robot/R, coeff = 1)
+ ..()
+ var/obj/item/weapon/gun/energy/e_gun/advtaser/cyborg/T = locate(/obj/item/weapon/gun/energy/e_gun/advtaser/cyborg) in basic_modules
+ if(T)
+ if(T.cell.charge < T.cell.maxcharge)
+ var/obj/item/ammo_casing/energy/S = T.ammo_type[T.select]
+ T.cell.give(S.e_cost * coeff)
+ T.update_icon()
+ else
+ T.charge_tick = 0
+
/obj/item/weapon/robot_module/medihound
name = "MediHound module"
basic_modules = list(
@@ -374,7 +386,7 @@
/obj/item/device/analyzer/nose,
/obj/item/weapon/soap/tongue,
/obj/item/device/healthanalyzer,
- /obj/item/weapon/dogborg/sleeper,
+ /obj/item/device/dogborg/sleeper,
/obj/item/weapon/twohanded/shockpaddles/hound,
/obj/item/device/sensor_device)
emag_modules = list(/obj/item/weapon/dogborg/pounce)
@@ -391,16 +403,36 @@
loc << "
Under ASIMOV, you are an enforcer of the PEACE and preventer of HUMAN HARM. \
You are not a security module and you are expected to follow orders and prevent harm above all else. Space law means nothing to you."
-/obj/item/weapon/robot_module/security/respawn_consumable(mob/living/silicon/robot/R, coeff = 1)
+/obj/item/weapon/robot_module/scrubpup
+ name = "Janitor"
+ basic_modules = list(
+ /obj/item/device/assembly/flash/cyborg,
+ /obj/item/weapon/dogborg/jaws/small,
+ /obj/item/device/analyzer/nose,
+ /obj/item/weapon/soap/tongue,
+ /obj/item/device/lightreplacer/cyborg,
+ /obj/item/device/dogborg/sleeper/compactor)
+ emag_modules = list(/obj/item/weapon/dogborg/pounce)
+ ratvar_modules = list(
+ /obj/item/clockwork/slab/cyborg/janitor,
+ /obj/item/clockwork/replica_fabricator/cyborg)
+ cyborg_base_icon = "scrubpup"
+ moduleselect_icon = "scrubpup"
+ feedback_key = "cyborg_scrubpup"
+ hat_offset = INFINITY
+ clean_on_move = TRUE
+
+/obj/item/weapon/robot_module/scrubpup/respawn_consumable(mob/living/silicon/robot/R, coeff = 1)
..()
- var/obj/item/weapon/gun/energy/e_gun/advtaser/cyborg/T = locate(/obj/item/weapon/gun/energy/e_gun/advtaser/cyborg) in basic_modules
- if(T)
- if(T.cell.charge < T.cell.maxcharge)
- var/obj/item/ammo_casing/energy/S = T.ammo_type[T.select]
- T.cell.give(S.e_cost * coeff)
- T.update_icon()
- else
- T.charge_tick = 0
+ var/obj/item/device/lightreplacer/LR = locate(/obj/item/device/lightreplacer) in basic_modules
+ if(LR)
+ for(var/i in 1 to coeff)
+ LR.Charge(R)
+
+/obj/item/weapon/robot_module/scrubpup/do_transform_animation()
+ ..()
+ loc << "
As tempting as it might be, do not begin binging on important items. Eat your garbage responsibly."
+
/obj/item/weapon/robot_module/peacekeeper
name = "Peacekeeper"
@@ -432,9 +464,9 @@
name = "Janitor"
basic_modules = list(
/obj/item/device/assembly/flash/cyborg,
- /obj/item/weapon/screwdriver/cyborg,
- /obj/item/weapon/crowbar/cyborg,
- /obj/item/stack/tile/plasteel/cyborg,
+ /obj/item/weapon/screwdriver/cyborg,
+ /obj/item/weapon/crowbar/cyborg,
+ /obj/item/stack/tile/plasteel/cyborg,
/obj/item/weapon/soap/nanotrasen,
/obj/item/weapon/storage/bag/trash/cyborg,
/obj/item/weapon/mop/cyborg,
diff --git a/icons/mob/dogborg.dmi b/icons/mob/dogborg.dmi
index 2ccf941237..ec63120ae1 100644
Binary files a/icons/mob/dogborg.dmi and b/icons/mob/dogborg.dmi differ
diff --git a/icons/mob/screen_cyborg.dmi b/icons/mob/screen_cyborg.dmi
index c7abab2d23..e9fd4ed401 100644
Binary files a/icons/mob/screen_cyborg.dmi and b/icons/mob/screen_cyborg.dmi differ
diff --git a/icons/mob/widerobot.dmi b/icons/mob/widerobot.dmi
index 6e11bf4031..88ac16da24 100644
Binary files a/icons/mob/widerobot.dmi and b/icons/mob/widerobot.dmi differ