diff --git a/code/game/objects/items/robot/robot_upgrades_vr.dm b/code/game/objects/items/robot/robot_upgrades_vr.dm new file mode 100644 index 0000000000..80ca38113b --- /dev/null +++ b/code/game/objects/items/robot/robot_upgrades_vr.dm @@ -0,0 +1,23 @@ +/* + +/obj/item/borg/upgrade/reset/action/proc/resetborg(var/mob/living/silicon/robot/R) + if(..()) return 0 + R.uneq_all() + R.modtype = initial(R.modtype) + R.hands.icon_state = initial(R.hands.icon_state) + R.icon = 'icons/mob/robots.dmi' + R.pixel_x = initial(pixel_x) + R.pixel_y = initial(pixel_y) + + R.notify_ai(ROBOT_NOTIFICATION_MODULE_RESET, R.module.name) + R.module.Reset(R) + qdel(R.module) + R.module = null + R.updatename("Default") +*/ + +//Make it so reset module doesn't bug up borgs. Not a huge problem, but should be added in before launch. + +//Could probably do +//if(attempt_vr(src,"resetborg(var/mob/living/silicon/robot/R)",args)) return //VOREStation Code +//or something like that \ No newline at end of file diff --git a/code/global_vr.dm b/code/global_vr.dm new file mode 100644 index 0000000000..58936d9486 --- /dev/null +++ b/code/global_vr.dm @@ -0,0 +1,4 @@ +/hook/startup/proc/modules_vr() + robot_module_types += "Medihound" + robot_module_types += "K9" + return 1 \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm new file mode 100644 index 0000000000..3c58ec7442 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm @@ -0,0 +1,284 @@ +/obj/item/weapon/dogborg/jaws/big + name = "combat jaws" + icon = 'icons/mob/dogborg_vr.dmi' + icon_state = "jaws" + desc = "The jaws of the law." + flags = CONDUCT + force = 10 + throwforce = 0 + hitsound = 'sound/weapons/bite.ogg' + attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced") + w_class = 3 + +/obj/item/weapon/dogborg/jaws/small + name = "puppy jaws" + icon = 'icons/mob/dogborg_vr.dmi' + icon_state = "smalljaws" + desc = "The jaws of a small dog." + flags = CONDUCT + force = 5 + throwforce = 0 + hitsound = 'sound/weapons/bite.ogg' + attack_verb = list("nibbled", "bit", "gnawed", "chomped", "nommed") + w_class = 3 + var/emagged = 0 + +/obj/item/weapon/dogborg/jaws/small/attack_self(mob/user) + var/mob/living/silicon/robot.R = user + if(R.emagged) + emagged = !emagged + if(emagged) + name = "combat jaws" + icon = 'icons/mob/dogborg_vr.dmi' + icon_state = "jaws" + desc = "The jaws of the law." + flags = CONDUCT + force = 10 + throwforce = 0 + hitsound = 'sound/weapons/bite.ogg' + attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced") + w_class = 3 + else + name = "puppy jaws" + icon = 'icons/mob/dogborg_vr.dmi' + icon_state = "smalljaws" + desc = "The jaws of a small dog." + flags = CONDUCT + force = 5 + throwforce = 0 + hitsound = 'sound/weapons/bite.ogg' + attack_verb = list("nibbled", "bit", "gnawed", "chomped", "nommed") + w_class = 3 + update_icon() + + +//Boop //New and improved, now a simple reagent sniffer. +/obj/item/device/dogborg/boop_module + name = "boop module" + icon = 'icons/mob/dogborg_vr.dmi' + icon_state = "nose" + desc = "The BOOP module, a simple reagent and atmosphere sniffer." + flags = CONDUCT + force = 0 + throwforce = 0 + attack_verb = list("nuzzled", "nosed", "booped") + w_class = 1 + +/obj/item/device/dogborg/boop_module/New() + ..() + flags |= NOBLUDGEON //No more attack messages + +/obj/item/device/dogborg/boop_module/attack_self(mob/user) + if (!( istype(user.loc, /turf) )) + return + + var/datum/gas_mixture/environment = user.loc.return_air() + + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles + + user.visible_message("[user] sniffs the air.", "You sniff the air...") + + user << "\blue Smells like:" + if(abs(pressure - ONE_ATMOSPHERE) < 10) + user << "\blue Pressure: [round(pressure,0.1)] kPa" + else + user << "\red Pressure: [round(pressure,0.1)] kPa" + if(total_moles) + for(var/g in environment.gas) + user << "\blue [gas_data.name[g]]: [round((environment.gas[g] / total_moles) * 100)]%" + user << "\blue Temperature: [round(environment.temperature-T0C,0.1)]°C ([round(environment.temperature,0.1)]K)" + +/obj/item/device/dogborg/boop_module/afterattack(obj/O, mob/user as mob, proximity) + if(!proximity) + return + if (user.stat) + return + if(!istype(O)) + return + + user.visible_message("[user] sniffs at \the [O.name].", "You sniff \the [O.name]...") + + if(!isnull(O.reagents)) + var/dat = "" + if(O.reagents.reagent_list.len > 0) + for (var/datum/reagent/R in O.reagents.reagent_list) + dat += "\n \t \blue [R]" + + if(dat) + user << "\blue Your BOOP module indicates: [dat]" + else + user << "\blue No active chemical agents smelled in [O]." + else + user << "\blue No significant chemical agents smelled in [O]." + + return + + +//Delivery +/* +/obj/item/weapon/storage/bag/borgdelivery + name = "fetching storage" + desc = "Fetch the thing!" + icon = 'icons/mob/dogborg_vr.dmi' + icon_state = "dbag" + w_class = 5 + max_w_class = 2 + max_combined_w_class = 2 + storage_slots = 1 + collection_mode = 0 + can_hold = list() // any + cant_hold = list(/obj/item/weapon/disk/nuclear) +*/ + +/obj/item/device/dogborg/dog_zapper //TODO + name = "paws of life" + icon = 'icons/mob/dogborg_vr.dmi' + icon_state = "defibpaddles0" + desc = "Zappy paws. For fixing cardiac arrest." + flags = CONDUCT + force = 0 + throwforce = 0 + hitsound = 'sound/weapons/bite.ogg' + attack_verb = list("batted", "pawed", "bopped", "whapped") + w_class = 1 + var/charge = 0 + var/charge_required = 1000 + var/charge_per = 100 + var/state = 0 //0 = Off, 1 = Charging, 2 = Ready + + //[round(((world.realtime - src.disconnect_time) / 10) / 60)] + +/obj/item/device/dogborg/dog_zapper/attack_self(mob/user) + switch(state) + if(0) // Was off when clicked + if(charge < charge_required) //Turned on and now charging + state = 1 + //TODO Change Icon + //TODO Start charging + user << "[name] now charging." + else //Turned on and was already charged + state = 2 + user << "[name] now READY." + if(1) // Was charging when clicked + state = 0 + //TODO Change Icon + user << "[name] now turned off." + if(2) // Was ready when clicked + state = 0 + //TODO Change Icon + user << "[name] now turned off (fully charged)." +/* +/obj/item/device/dogborg/dog_zapper/proc/charge() + var/mob/living/silicon/robot.R = usr + + do + R.cell.charge -= charge_per + charge += charge_per + sleep(1) + while(state = 1 && charge < charge_required && (R.cell.charge > (charge_required - charge))) + + if(charge = charge_required) + usr << "[name] now READY." + + +/obj/item/device/dogborg/dog_zapper/afterattack(mob/living/carbon/target, mob/living/silicon/user, proximity) +*/ +//Tongue stuff +/obj/item/device/dogborg/tongue + name = "synthetic tongue" + desc = "Useful for slurping mess off the floor before affectionally licking the crew members in the face." + icon = 'icons/mob/dogborg_vr.dmi' + icon_state = "synthtongue" + hitsound = 'sound/effects/attackblob.ogg' + var/emagged = 0 + +/obj/item/device/dogborg/tongue/New() + ..() + flags |= NOBLUDGEON //No more attack messages + +/obj/item/device/dogborg/tongue/attack_self(mob/user) + var/mob/living/silicon/robot.R = user + if(R.emagged) + emagged = !emagged + if(emagged) + name = "hacked tongue of doom" + desc = "Your tongue has been upgraded successfully. Congratulations." + icon = 'icons/mob/dogborg_vr.dmi' + icon_state = "syndietongue" + else + name = "synthetic tongue" + desc = "Useful for slurping mess off the floor before affectionally licking the crew members in the face." + icon = 'icons/mob/dogborg_vr.dmi' + icon_state = "synthtongue" + update_icon() + +/obj/item/device/dogborg/tongue/afterattack(atom/target, mob/user, proximity) + if(!proximity) + return + if(user.client && (target in user.client.screen)) + user << "You need to take that [target.name] off before cleaning it!" + else if(istype(target,/obj/effect/decal/cleanable)) + user.visible_message("[user] begins to lick off \the [target.name].", "You begin to lick off \the [target.name]...") + if(do_after (user, 50)) + user << "You finish licking off \the [target.name]." + del(target) + var/mob/living/silicon/robot.R = user + R.cell.charge = R.cell.charge + 50 + else if(istype(target,/obj/item)) + if(istype(target,/obj/item/trash)) + user.visible_message("[user] nibbles away at \the [target.name].", "You begin to nibble away at \the [target.name]...") + if(do_after (user, 50)) + user.visible_message("[user] finishes eating \the [target.name].", "You finish eating \the [target.name].") + user << "You finish off \the [target.name]." + del(target) + var/mob/living/silicon/robot.R = user + R.cell.charge = R.cell.charge + 250 + return + if(istype(target,/obj/item/weapon/cell)) + user.visible_message("[user] begins cramming \the [target.name] down its throat.", "You begin cramming \the [target.name] down your throat...") + if(do_after (user, 50)) + user.visible_message("[user] finishes gulping down \the [target.name].", "You finish swallowing \the [target.name].") + user << "You finish off \the [target.name], and gain some charge!" + var/mob/living/silicon/robot.R = user + var/obj/item/weapon/cell.C = target + R.cell.charge = R.cell.charge + (C.maxcharge / 3) + del(target) + return + user.visible_message("[user] begins to lick \the [target.name] clean...", "You begin to lick \the [target.name] clean...") + if(do_after (user, 50)) + user << "You clean \the [target.name]." + var/obj/effect/decal/cleanable/C = locate() in target + del(C) + target.clean_blood() + else if(ishuman(target)) + if(src.emagged) + var/mob/living/silicon/robot.R = user + var/mob/living/L = target + if(R.cell.charge <= 666) + return + L.Stun(4) // normal stunbaton is force 7 gimme a break good sir! + L.Weaken(4) + L.apply_effect(STUTTER, 4) + L.visible_message("[user] has shocked [L] with its tongue!", \ + "[user] has shocked you with its tongue! You can feel the betrayal.") + playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) + R.cell.charge = R.cell.charge - 666 + else + user.visible_message("\the [user] affectionally licks all over \the [target]'s face!", "You affectionally lick all over \the [target]'s face!") + playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1) + return + else if(istype(target, /obj/structure/window)) + user.visible_message("[user] begins to lick \the [target.name] clean...", "You begin to lick \the [target.name] clean...") + if(do_after (user, 50)) + user << "You clean \the [target.name]." + target.color = initial(target.color) + //target.SetOpacity(initial(target.opacity)) //Apparantly this doesn't work? + else + user.visible_message("[user] begins to lick \the [target.name] clean...", "You begin to lick \the [target.name] clean...") + if(do_after (user, 50)) + user << "You clean \the [target.name]." + var/obj/effect/decal/cleanable/C = locate() in target + del(C) + target.clean_blood() + return \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm new file mode 100644 index 0000000000..1d2746bdec --- /dev/null +++ b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm @@ -0,0 +1,427 @@ +//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_vr.dmi' + icon_state = "sleeper" + w_class = 1 + var/mob/living/carbon/patient = null + var/mob/living/silicon/robot/hound = null + var/inject_amount = 10 + var/min_health = -100 + var/cleaning = 0 + var/patient_laststat = null + var/mob_energy = 30000 //Energy gained from digesting mobs (including PCs) + var/list/injection_chems = list("dexalin", "bicaridine", "kelotane","anti_toxin", "alkysine", "imidazoline", "spaceacillin", "paracetamol") //The borg is able to heal every damage type. As a nerf, they use 750 charge per injection. + var/eject_port = "ingestion" + var/list/items_preserved = list() + +/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/device/dogborg/sleeper/afterattack(mob/living/carbon/target, mob/living/silicon/user, proximity) + hound = loc + if(!proximity) + return + if(!ishuman(target)) + return + if(target.buckled) + user << "\red The user is buckled and can not be put into your [src.name]." + return + if(patient) + user << "\red Your [src.name] is already occupied." + return + 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)) + + if(!proximity) return //If they moved away, you can't eat them. + + if(patient) return //If you try to eat two people at once, you can only eat one. + + else //If you don't have someone in you, proceed. + target.forceMove(src) + target.reset_view(src) + update_patient() + processing_objects.Add(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/gulp.ogg', 100, 1) //POLARISTODO + +/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_view() + 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_view() + 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/device/dogborg/sleeper/proc/sleeperUI(mob/user) + var/dat + dat += "

Injector

" + + if(patient && !(patient.stat & DEAD)) //Why inject dead people with innaprov? Dundonuffin in Bay. + dat += "Inject Inaprovaline" + else + dat += "Inject Inaprovaline" + if(patient && patient.health > min_health) + for(var/re in injection_chems) + var/datum/reagent/C = chemical_reagents_list[re] + if(C) + dat += "
Inject [C.name]" + else + for(var/re in injection_chems) + var/datum/reagent/C = chemical_reagents_list[re] + if(C) + dat += "
Inject [C.name]" + + dat += "

Sleeper Status

" + dat += "Refresh" + dat += "Eject All" + dat += "Eject port: [eject_port]" + if(!cleaning) + dat += "Self-Clean" + else + dat += "Self-Clean" + + 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) + if(0) + dat += "Conscious" + if(1) + dat += "Unconscious" + else + dat += "DEAD" + + dat += text("[]\t-Pulse, bpm: []
", (patient.pulse == PULSE_NONE || patient.pulse == PULSE_THREADY ? "" : ""), patient.get_pulse(GETPULSE_TOOL)) + dat += text("[]\t-Overall Health %: []
", (patient.health > 0 ? "" : ""), round(patient.health)) + dat += text("[]\t-Brute Damage %: []
", (patient.getBruteLoss() < 60 ? "" : ""), patient.getBruteLoss()) + dat += text("[]\t-Respiratory Damage %: []
", (patient.getOxyLoss() < 60 ? "" : ""), patient.getOxyLoss()) + dat += text("[]\t-Toxin Content %: []
", (patient.getToxLoss() < 60 ? "" : ""), patient.getToxLoss()) + dat += text("[]\t-Burn Severity %: []
", (patient.getFireLoss() < 60 ? "" : ""), 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

" + dat += "
" + + var/datum/browser/popup = new(user, "sleeper", "Sleeper Console", 520, 540) //Set up the popup browser window + popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) + popup.set_content(dat) + popup.open() + return + +/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 + if(href_list["eject"]) + go_out() + sleeperUI(usr) + return + 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") + cleaning = 1 + drain(500) + processing_objects.Add(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)) //What is bitwise NOT? ... Thought it was tilde. + if(href_list["inject"] == "inaprovaline" || patient.health > min_health) + inject_chem(usr, href_list["inject"]) + else + 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/device/dogborg/sleeper/proc/inject_chem(mob/user, chem) + if(patient && patient.reagents) + if(chem in injection_chems + "inaprovaline") + 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)) + hound << "Injecting [units] unit\s of [chemical_reagents_list[chem]] into occupant." //If they were immersed, the reagents wouldn't leave with them. + +//For if the dogborg's existing patient uh, doesn't make it. +/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.updateicon() + //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.updateicon() + 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.updateicon() + 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(10)) + var/churnsound = pick( + 'sound/vore/digest1.ogg', + 'sound/vore/digest2.ogg', + 'sound/vore/digest3.ogg', + 'sound/vore/digest4.ogg', + 'sound/vore/digest5.ogg', + 'sound/vore/digest6.ogg', + 'sound/vore/digest7.ogg', + 'sound/vore/digest8.ogg', + 'sound/vore/digest9.ogg', + 'sound/vore/digest10.ogg', + 'sound/vore/digest11.ogg', + 'sound/vore/digest12.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(air_master.current_cycle%2==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/death1.ogg', + 'sound/vore/death2.ogg', + 'sound/vore/death3.ogg', + 'sound/vore/death4.ogg', + 'sound/vore/death5.ogg', + 'sound/vore/death6.ogg', + 'sound/vore/death7.ogg', + 'sound/vore/death8.ogg', + 'sound/vore/death9.ogg', + 'sound/vore/death10.ogg') + for(var/mob/hearer in range(1,src.hound)) + hearer << deathsound + T << deathsound + //Spill(T) //TODOPOLARIS + T.Del() + 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.loc = src + PDA.id = null + T.Del() + + //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 + T.Del() + src.update_patient() + src.hound.cell.charge += 10 + return + +/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) //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("inaprovaline") < 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("inaprovaline", 5) + return + + if(!patient && !cleaning) //We think we're done working. + if(!update_patient()) //One last try to find someone + processing_objects.Remove(src) + return + +/mob/living/silicon/robot + var/sleeper_g + var/sleeper_r + +/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_vr.dmi' + icon_state = "sleeper" + inject_amount = 10 + min_health = -100 + injection_chems = null //So they don't have all the same chems as the medihound! \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/robot_modules_vr.dm b/code/modules/mob/living/silicon/robot/robot_modules_vr.dm new file mode 100644 index 0000000000..e6d298cee2 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/robot_modules_vr.dm @@ -0,0 +1,71 @@ +/hook/startup/proc/robot_modules_vr() + robot_modules["Medihound"] = /obj/item/weapon/robot_module/medihound + robot_modules["K9"] = /obj/item/weapon/robot_module/knine + return 1 + + +/obj/item/weapon/robot_module/knine + name = "k9 robot module" + sprites = list("K9 hound" = "k9") + channels = list("Security" = 1) + networks = list(NETWORK_SECURITY) + can_be_pushed = 0 + +/obj/item/weapon/robot_module/knine/New(var/mob/living/silicon/robot/R) + src.modules += new /obj/item/device/flash(src) + src.modules += new /obj/item/weapon/handcuffs/cyborg(src) //You need cuffs to be a proper sec borg! + src.modules += new /obj/item/weapon/dogborg/jaws/big(src) //In case there's some kind of hostile mob. + src.modules += new /obj/item/weapon/melee/baton/robot(src) //Since the pounce module refused to work, they get a stunbaton instead. + src.modules += new /obj/item/device/dogborg/boop_module(src) //Boop people on the nose. + src.modules += new /obj/item/device/dogborg/tongue(src) //This is so they can clean up bloody evidence after it's examined, and so they can lick crew. + src.modules += new /obj/item/taperoll/police(src) //Block out crime scenes. + src.modules += new /obj/item/device/dogborg/sleeper/K9(src) //Eat criminals. Bring them to the brig. + src.modules += new /obj/item/weapon/gun/energy/taser/mounted/cyborg(src) //They /are/ a security borg, after all. + src.modules += new /obj/item/borg/sight/hud/sec(src) //Security hud to see criminals. + src.emag = new /obj/item/weapon/gun/energy/laser/mounted(src) //Emag. Not a big problem. + R.icon = 'icons/mob/widerobot_vr.dmi' + R.hands.icon = 'icons/mob/screen1_robot_vr.dmi' + R.icon_state = "k9" + R.pixel_x = -16 + ..() + +/obj/item/weapon/robot_module/knine/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) + var/obj/item/device/flash/F = locate() in src.modules + if(F.broken) + F.broken = 0 + F.times_used = 0 + F.icon_state = "flash" + else if(F.times_used) + F.times_used-- + var/obj/item/weapon/gun/energy/taser/mounted/cyborg/T = locate() in src.modules + if(T.power_supply.charge < T.power_supply.maxcharge) + T.power_supply.give(T.charge_cost * amount) + T.update_icon() + else + T.charge_tick = 0 + var/obj/item/weapon/melee/baton/robot/B = locate() in src.modules + if(B && B.bcell) + B.bcell.give(amount) + + +/obj/item/weapon/robot_module/medihound + name = "MediHound module" + channels = list("Medical" = 1) + networks = list(NETWORK_MEDICAL) + can_be_pushed = 0 + sprites = list("Medical Hound" = "medihound") + +/obj/item/weapon/robot_module/medihound/New(var/mob/living/silicon/robot/R) + src.modules += new /obj/item/weapon/dogborg/jaws/small(src) //In case a patient is being attacked by carp. + src.modules += new /obj/item/device/dogborg/boop_module(src) //Boop the crew. + src.modules += new /obj/item/device/dogborg/tongue(src) //Clean up bloody items by licking them, and eat rubbish for minor energy. + src.modules += new /obj/item/device/healthanalyzer(src) // See who's hurt specificially. + src.modules += new /obj/item/device/dogborg/sleeper(src) //So they can nom people and heal them + src.modules += new /obj/item/borg/sight/hud/med(src) //See who's hurt generally. + src.modules += new /obj/item/weapon/extinguisher/mini(src) //So they can put burning patients out. + src.modules += new /obj/item/weapon/reagent_containers/syringe(src) //In case the chemist is nice! + R.icon = 'icons/mob/widerobot_vr.dmi' + R.hands.icon = 'icons/mob/screen1_robot_vr.dmi' + R.icon_state = "medihound" + R.pixel_x = -16 + ..() \ No newline at end of file diff --git a/icons/mob/dogborg_vr.dmi b/icons/mob/dogborg_vr.dmi new file mode 100644 index 0000000000..ea5a095bb9 Binary files /dev/null and b/icons/mob/dogborg_vr.dmi differ diff --git a/icons/mob/screen1_robot_vr.dmi b/icons/mob/screen1_robot_vr.dmi new file mode 100644 index 0000000000..310df85058 Binary files /dev/null and b/icons/mob/screen1_robot_vr.dmi differ diff --git a/icons/mob/widerobot_vr.dmi b/icons/mob/widerobot_vr.dmi new file mode 100644 index 0000000000..096d18c948 Binary files /dev/null and b/icons/mob/widerobot_vr.dmi differ diff --git a/vorestation.dme b/vorestation.dme index 6df9398b99..0085f19409 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -13,6 +13,7 @@ #include "code\_macros.dm" #include "code\_unit_tests.dm" #include "code\global.dm" +#include "code\global_vr.dm" #include "code\hub.dm" #include "code\names.dm" #include "code\stylesheet.dm" @@ -651,6 +652,7 @@ #include "code\game\objects\items\robot\robot_items.dm" #include "code\game\objects\items\robot\robot_parts.dm" #include "code\game\objects\items\robot\robot_upgrades.dm" +#include "code\game\objects\items\robot\robot_upgrades_vr.dm" #include "code\game\objects\items\stacks\matter_synth.dm" #include "code\game\objects\items\stacks\medical.dm" #include "code\game\objects\items\stacks\nanopaste.dm" @@ -1435,8 +1437,11 @@ #include "code\modules\mob\living\silicon\robot\robot_damage.dm" #include "code\modules\mob\living\silicon\robot\robot_items.dm" #include "code\modules\mob\living\silicon\robot\robot_modules.dm" +#include "code\modules\mob\living\silicon\robot\robot_modules_vr.dm" #include "code\modules\mob\living\silicon\robot\robot_movement.dm" #include "code\modules\mob\living\silicon\robot\syndicate.dm" +#include "code\modules\mob\living\silicon\robot\dogborg\dog_modules_vr.dm" +#include "code\modules\mob\living\silicon\robot\dogborg\dog_sleeper_vr.dm" #include "code\modules\mob\living\silicon\robot\drone\drone.dm" #include "code\modules\mob\living\silicon\robot\drone\drone_abilities.dm" #include "code\modules\mob\living\silicon\robot\drone\drone_console.dm"