diff --git a/code/game/objects/items/devices/dogborg_sleeper.dm b/code/game/objects/items/devices/dogborg_sleeper.dm index 2614775906..41a12136ef 100644 --- a/code/game/objects/items/devices/dogborg_sleeper.dm +++ b/code/game/objects/items/devices/dogborg_sleeper.dm @@ -3,7 +3,7 @@ /obj/item/dogborg/sleeper name = "hound sleeper" desc = "nothing should see this." - icon = 'icons/mob/dogborg.dmi' + icon = 'icons/mob/robot_items.dmi' icon_state = "sleeper" w_class = WEIGHT_CLASS_TINY var/mob/living/carbon/patient @@ -418,29 +418,15 @@ var/units = round(patient.reagents.get_reagent_amount(chem)) to_chat(hound, "Injecting [units] unit\s of [chem] into occupant.") //If they were immersed, the reagents wouldn't leave with them. -/obj/item/dogborg/sleeper/medihound //Medihound sleeper - name = "Mobile Sleeper" - 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" - breakout_time = 30 //Medical sleepers should be designed to be as easy as possible to get out of. - /obj/item/dogborg/sleeper/K9 //The K9 portabrig name = "Mobile Brig" desc = "Equipment for a K9 unit. A mounted portable-brig that holds criminals." - icon = 'icons/mob/dogborg.dmi' icon_state = "sleeperb" inject_amount = 0 min_health = -100 injection_chems = null //So they don't have all the same chems as the medihound! breakout_time = 300 -/obj/item/storage/attackby(obj/item/dogborg/sleeper/K9, mob/user, proximity) - if(istype(K9)) - K9.afterattack(src, user ,1) - else - . = ..() - /obj/item/dogborg/sleeper/K9/afterattack(mob/living/carbon/target, mob/living/silicon/user, proximity) var/mob/living/silicon/robot/hound = get_host() if(!hound || !istype(target) || !proximity || target.anchored) @@ -462,70 +448,6 @@ user.visible_message("[hound.name]'s mobile brig clunks in series as [target] slips inside.", "Your mobile brig groans lightly as [target] slips inside.") playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) // Really don't need ERP sound effects for robots - -/obj/item/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 = 0 - min_health = -100 - injection_chems = null //So they don't have all the same chems as the medihound! - var/max_item_count = 30 - -/obj/item/storage/attackby(obj/item/dogborg/sleeper/compactor, mob/user, proximity) //GIT CIRCUMVENTED YO! - if(istype(compactor)) - compactor.afterattack(src, user ,1) - else - . = ..() - -/obj/item/dogborg/sleeper/compactor/afterattack(atom/movable/target, mob/living/silicon/user, proximity)//GARBO NOMS - var/mob/living/silicon/robot/hound = get_host() - if(!hound || !istype(target) || !proximity || target.anchored) - return - if(length(contents) > (max_item_count - 1)) - to_chat(user,"Your [src] is full. Eject or process contents to continue.") - return - if(isitem(target)) - var/obj/item/I = target - if(CheckAccepted(I)) - to_chat(user,"[I] registers an error code to your [src]") - return - if(I.w_class > WEIGHT_CLASS_NORMAL) - to_chat(user,"[I] is too large to fit into your [src]") - return - user.visible_message("[hound.name] is ingesting [I] into their [src.name].", "You start ingesting [target] into your [src.name]...") - if(do_after(user, 15, target = target) && length(contents) < max_item_count) - I.forceMove(src) - I.visible_message("[hound.name]'s garbage processor groans lightly as [I] slips inside.", "Your garbage compactor groans lightly as [I] slips inside.") - playsound(hound, 'sound/machines/disposalflush.ogg', 50, 1) - if(length(contents) > 11) //grow that tum after a certain junk amount - hound.sleeper_r = 1 - hound.update_icons() - else - hound.sleeper_r = 0 - hound.update_icons() - return - - if(iscarbon(target) || issilicon(target)) - var/mob/living/trashman = target - if(!CHECK_BITFIELD(trashman.vore_flags,DEVOURABLE)) - to_chat(user, "[target] registers an error code to your [src]") - return - if(patient) - to_chat(user,"Your [src] is already occupied.") - return - if(trashman.buckled) - to_chat(user,"[trashman] is buckled and can not be put into your [src].") - return - user.visible_message("[hound.name] is ingesting [trashman] into their [src].", "You start ingesting [trashman] into your [src.name]...") - if(do_after(user, 30, target = trashman) && !patient && !trashman.buckled && length(contents) < max_item_count) - trashman.forceMove(src) - trashman.reset_perspective(src) - update_gut() - 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/effects/bin_close.ogg', 80, 1) - /obj/item/dogborg/sleeper/K9/flavour name = "Recreational Sleeper" desc = "A mounted, underslung sleeper, intended for holding willing occupants for leisurely purposes." diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index abb2d12a1f..9700d8e6cd 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -902,4 +902,47 @@ name = "mining point card" desc = "A robotic ID strip used for claiming and transferring mining points. Must be held in an active slot to transfer points." access = list(ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MAILSORTING, ACCESS_MINERAL_STOREROOM) - icon_state = "data_1" \ No newline at end of file + icon_state = "data_1" + + +///Mere cosmetic dogborg items, remnants of what were once the most annoying cyborg modules. +/obj/item/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/robot_items.dmi' + icon_state = "synthtongue" + hitsound = 'sound/effects/attackblob.ogg' + desc = "For giving affectionate kisses." + item_flags = NOBLUDGEON + +/obj/item/dogborg_tongue/afterattack(atom/target, mob/user, proximity) + . = ..() + if(!proximity || !isliving(target)) + return + var/mob/living/silicon/robot/R = user + var/mob/living/L = target + if(L.ckey && !(L.client?.prefs.vore_flags & LICKABLE)) + to_chat(R, "ERROR ERROR: Target not lickable. Aborting display-of-affection subroutine.") + return + + if(check_zone(R.zone_selected) == "head") + R.visible_message("\the [R] affectionally licks \the [L]'s face!", "You affectionally lick \the [L]'s face!") + playsound(R, 'sound/effects/attackblob.ogg', 50, 1) + else + R.visible_message("\the [R] affectionally licks \the [L]!", "You affectionally lick \the [L]!") + playsound(R, 'sound/effects/attackblob.ogg', 50, 1) + +/obj/item/dogborg_nose + name = "boop module" + desc = "The BOOP module" + icon = 'icons/mob/robot_items.dmi' + icon_state = "nose" + flags_1 = CONDUCT_1|NOBLUDGEON + force = 0 + +/obj/item/dogborg_nose/afterattack(atom/target, mob/user, proximity) + . = ..() + if(!proximity) + return + do_attack_animation(target, null, src) + user.visible_message("[user] [pick("nuzzles", "pushes", "boops")] \the [target.name] with their nose!") diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 508dc67dd7..98a5f0f234 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -3,122 +3,7 @@ real_name = "Cyborg" icon = 'icons/mob/robots.dmi' icon_state = "robot" - maxHealth = 100 - health = 100 bubble_icon = "robot" - designation = "Default" //used for displaying the prefix & getting the current module of cyborg - has_limbs = 1 - hud_type = /datum/hud/robot - - blocks_emissive = EMISSIVE_BLOCK_UNIQUE - - var/custom_name = "" - var/braintype = "Cyborg" - var/obj/item/robot_suit/robot_suit = null //Used for deconstruction to remember what the borg was constructed out of.. - var/obj/item/mmi/mmi = null - - var/shell = FALSE - var/deployed = FALSE - var/mob/living/silicon/ai/mainframe = null - var/datum/action/innate/undeployment/undeployment_action = new - -//Hud stuff - - var/obj/screen/inv1 = null - var/obj/screen/inv2 = null - var/obj/screen/inv3 = null - var/obj/screen/lamp_button = null - var/obj/screen/thruster_button = null - var/obj/screen/hands = null - - var/shown_robot_modules = 0 //Used to determine whether they have the module menu shown or not - var/obj/screen/robot_modules_background - -//3 Modules can be activated at any one time. - var/obj/item/robot_module/module = null - var/obj/item/module_active = null - held_items = list(null, null, null) //we use held_items for the module holding, because that makes sense to do! - - var/mutable_appearance/eye_lights - - var/mob/living/silicon/ai/connected_ai = null - var/obj/item/stock_parts/cell/cell = null - - var/opened = 0 - var/emagged = FALSE - var/emag_cooldown = 0 - var/wiresexposed = 0 - - var/ident = 0 - var/locked = TRUE - var/list/req_access = list(ACCESS_ROBOTICS) - - var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list(), "Burglar"=list()) - - var/speed = 0 // VTEC speed boost. - var/magpulse = FALSE // Magboot-like effect. - var/ionpulse = FALSE // Jetpack-like effect. - var/ionpulse_on = FALSE // Jetpack-like effect. - var/datum/effect_system/trail_follow/ion/ion_trail // Ionpulse effect. - - var/low_power_mode = 0 //whether the robot has no charge left. - var/datum/effect_system/spark_spread/spark_system // So they can initialize sparks whenever/N - - var/lawupdate = 1 //Cyborgs will sync their laws with their AI by default - var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them. - var/locked_down //Boolean of whether the borg is locked down or not - - var/toner = 0 - var/tonermax = 40 - - var/lamp_max = 10 //Maximum brightness of a borg lamp. Set as a var for easy adjusting. - var/lamp_intensity = 0 //Luminosity of the headlamp. 0 is off. Higher settings than the minimum require power. - light_color = "#FFCC66" - light_power = 0.8 - var/lamp_cooldown = 0 //Flag for if the lamp is on cooldown after being forcibly disabled. - - var/sight_mode = 0 - hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_TRACK_HUD) - - var/list/upgrades = list() - - var/hasExpanded = FALSE - var/obj/item/hat - var/hat_offset = -3 - var/list/equippable_hats = list(/obj/item/clothing/head/caphat, - /obj/item/clothing/head/hardhat, - /obj/item/clothing/head/centhat, - /obj/item/clothing/head/HoS, - /obj/item/clothing/head/beret, - /obj/item/clothing/head/kitty, - /obj/item/clothing/head/hopcap, - /obj/item/clothing/head/wizard, - /obj/item/clothing/head/nursehat, - /obj/item/clothing/head/sombrero, - /obj/item/clothing/head/helmet/chaplain/witchunter_hat, - /obj/item/clothing/head/soft/, //All baseball caps - /obj/item/clothing/head/that, //top hat - /obj/item/clothing/head/collectable/tophat, //Not sure where this one is found, but it looks the same so might as well include - /obj/item/clothing/mask/bandana/, //All bandanas (which only work in hat mode) - /obj/item/clothing/head/fedora, - /obj/item/clothing/head/beanie/, //All beanies - /obj/item/clothing/ears/headphones, - /obj/item/clothing/head/helmet/skull, - /obj/item/clothing/head/crown/fancy) - - can_buckle = TRUE - buckle_lying = FALSE - var/static/list/can_ride_typecache = typecacheof(/mob/living/carbon/human) - - var/sitting = 0 - var/bellyup = 0 - var/dogborg = FALSE - - var/cansprint = 1 - - var/orebox = null - -/mob/living/silicon/robot /mob/living/silicon/robot/get_cell() return cell diff --git a/code/modules/mob/living/silicon/robot/robot_defines.dm b/code/modules/mob/living/silicon/robot/robot_defines.dm new file mode 100644 index 0000000000..860d531608 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/robot_defines.dm @@ -0,0 +1,123 @@ + +/mob/living/silicon/robot + designation = "Default" //used for displaying the prefix & getting the current module of cyborg + has_limbs = TRUE + hud_type = /datum/hud/robot + + blocks_emissive = EMISSIVE_BLOCK_UNIQUE + + maxHealth = 100 + health = 100 + + var/custom_name = "" + var/braintype = "Cyborg" + var/obj/item/robot_suit/robot_suit = null //Used for deconstruction to remember what the borg was constructed out of.. + var/obj/item/mmi/mmi = null + + var/shell = FALSE + var/deployed = FALSE + var/mob/living/silicon/ai/mainframe = null + var/datum/action/innate/undeployment/undeployment_action = new + +//Hud stuff + + var/obj/screen/inv1 = null + var/obj/screen/inv2 = null + var/obj/screen/inv3 = null + var/obj/screen/lamp_button = null + var/obj/screen/thruster_button = null + var/obj/screen/hands = null + + var/shown_robot_modules = 0 //Used to determine whether they have the module menu shown or not + var/obj/screen/robot_modules_background + +//3 Modules can be activated at any one time. + var/obj/item/robot_module/module = null + var/obj/item/module_active = null + held_items = list(null, null, null) //we use held_items for the module holding, because that makes sense to do! + + var/mutable_appearance/eye_lights + + var/mob/living/silicon/ai/connected_ai = null + var/obj/item/stock_parts/cell/cell = null + + var/opened = 0 + var/emagged = FALSE + var/emag_cooldown = 0 + var/wiresexposed = 0 + + var/ident = 0 + var/locked = TRUE + var/list/req_access = list(ACCESS_ROBOTICS) + + var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list(), "Burglar"=list()) + + var/speed = 0 // VTEC speed boost. + var/magpulse = FALSE // Magboot-like effect. + var/ionpulse = FALSE // Jetpack-like effect. + var/ionpulse_on = FALSE // Jetpack-like effect. + var/datum/effect_system/trail_follow/ion/ion_trail // Ionpulse effect. + + var/low_power_mode = 0 //whether the robot has no charge left. + var/datum/effect_system/spark_spread/spark_system // So they can initialize sparks whenever/N + + var/lawupdate = 1 //Cyborgs will sync their laws with their AI by default + var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them. + var/locked_down //Boolean of whether the borg is locked down or not + + var/toner = 0 + var/tonermax = 40 + + var/lamp_max = 10 //Maximum brightness of a borg lamp. Set as a var for easy adjusting. + var/lamp_intensity = 0 //Luminosity of the headlamp. 0 is off. Higher settings than the minimum require power. + light_color = "#FFCC66" + light_power = 0.8 + var/lamp_cooldown = 0 //Flag for if the lamp is on cooldown after being forcibly disabled. + + var/sight_mode = 0 + hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_TRACK_HUD) + + var/list/upgrades = list() + + var/hasExpanded = FALSE + var/obj/item/hat + var/hat_offset = -3 + var/list/equippable_hats = list(/obj/item/clothing/head/caphat, + /obj/item/clothing/head/hardhat, + /obj/item/clothing/head/centhat, + /obj/item/clothing/head/HoS, + /obj/item/clothing/head/beret, + /obj/item/clothing/head/kitty, + /obj/item/clothing/head/hopcap, + /obj/item/clothing/head/wizard, + /obj/item/clothing/head/nursehat, + /obj/item/clothing/head/sombrero, + /obj/item/clothing/head/helmet/chaplain/witchunter_hat, + /obj/item/clothing/head/soft/, //All baseball caps + /obj/item/clothing/head/that, //top hat + /obj/item/clothing/head/collectable/tophat, //Not sure where this one is found, but it looks the same so might as well include + /obj/item/clothing/mask/bandana/, //All bandanas (which only work in hat mode) + /obj/item/clothing/head/fedora, + /obj/item/clothing/head/beanie/, //All beanies + /obj/item/clothing/ears/headphones, + /obj/item/clothing/head/helmet/skull, + /obj/item/clothing/head/crown/fancy) + + can_buckle = TRUE + buckle_lying = FALSE + var/static/list/can_ride_typecache = typecacheof(/mob/living/carbon/human) + + var/sitting = 0 + var/bellyup = 0 + var/dogborg = FALSE + + var/cansprint = 1 + + var/orebox = null + + //doggie borg stuff. + var/disabler + var/laser + var/sleeper_g + var/sleeper_r + var/sleeper_nv \ No newline at end of file diff --git a/icons/mob/dogborg.dmi b/icons/mob/dogborg.dmi deleted file mode 100644 index 856724be1f..0000000000 Binary files a/icons/mob/dogborg.dmi and /dev/null differ diff --git a/icons/mob/robot_items.dmi b/icons/mob/robot_items.dmi index 862e1be384..06521f1a84 100644 Binary files a/icons/mob/robot_items.dmi and b/icons/mob/robot_items.dmi differ diff --git a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm deleted file mode 100644 index f59d18686a..0000000000 --- a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm +++ /dev/null @@ -1,459 +0,0 @@ -/* -DOG BORG EQUIPMENT HERE -SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm ! -*/ - -/obj/item/dogborg/jaws - name = "Dogborg jaws" - desc = "The jaws of the debug errors oh god." - icon = 'icons/mob/dogborg.dmi' - flags_1 = CONDUCT_1 - force = 1 - throwforce = 0 - w_class = 3 - hitsound = 'sound/weapons/bite.ogg' - sharpness = IS_SHARP - var/stamtostunconversion = 0.1 //Total stamloss gets multiplied by this value for the help intent hard stun. Resting adds an additional 2x multiplier on top. Keep this low or so help me god. - var/stuncooldown = 4 SECONDS //How long it takes before you're able to attempt to stun a target again - var/nextstuntime - -/obj/item/dogborg/jaws/examine(mob/user) - . = ..() - if(!CONFIG_GET(flag/weaken_secborg)) - . += "Use help intent to attempt to non-lethally incapacitate the target by latching on with your maw. This is more effective against exhausted and resting targets." - -/obj/item/dogborg/jaws/big - name = "combat jaws" - desc = "The jaws of the law. Very sharp." - icon_state = "jaws" - force = 15 //Chomp chomp. Crew harm. - attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced") - stamtostunconversion = 0.2 // 100*0.2*2=40. Stun's just long enough to slap on cuffs with click delay if the target is near hard stamcrit. - stuncooldown = 6 SECONDS - - -/obj/item/dogborg/jaws/small - name = "puppy jaws" - desc = "Rubberized teeth designed to protect accidental harm. Sharp enough for specialized tasks however." - icon_state = "smalljaws" - force = 6 - attack_verb = list("nibbled", "bit", "gnawed", "chomped", "nommed") - var/status = 0 - -/obj/item/dogborg/jaws/attack(atom/A, mob/living/silicon/robot/user) - if(!istype(user)) - return - if(!CONFIG_GET(flag/weaken_secborg) && user.a_intent != INTENT_HARM && istype(A, /mob/living)) - if(A == user.pulling) - to_chat(user, "You already have [A] in your jaws.") - return - if(nextstuntime >= world.time) - to_chat(user, "Your jaw servos are still recharging.") - return - nextstuntime = world.time + stuncooldown - var/mob/living/M = A - var/cachedstam = M.getStaminaLoss() - var/totalstuntime = cachedstam * stamtostunconversion * (M.lying ? 2 : 1) - if(CHECK_MOBILITY(M, MOBILITY_STAND)) - M.DefaultCombatKnockdown(cachedstam*2) //BORK BORK. GET DOWN. - M.Stun(totalstuntime) - user.do_attack_animation(A, ATTACK_EFFECT_BITE) - user.start_pulling(M, TRUE) //Yip yip. Come with. - user.changeNext_move(CLICK_CD_MELEE) - M.visible_message("[user] clamps [user.p_their()] [src] onto [M] and latches on!", "[user] clamps [user.p_their()] [src] onto you and latches on!") - if(totalstuntime >= 4 SECONDS) - playsound(usr, 'sound/effects/k9_jaw_strong.ogg', 75, FALSE, 2) //Wuff wuff. Big stun. - else - playsound(usr, 'sound/effects/k9_jaw_weak.ogg', 50, TRUE, -1) //Arf arf. Pls buff. - else - . = ..() - user.do_attack_animation(A, ATTACK_EFFECT_BITE) - -/obj/item/dogborg/jaws/small/attack_self(mob/user) - var/mob/living/silicon/robot/R = user - if(R.cell && R.cell.charge > 100) - if(R.emagged && status == 0) - name = "combat jaws" - icon_state = "jaws" - desc = "The jaws of the law." - force = 12 - attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced") - stamtostunconversion = 0.15 - stuncooldown = 5 SECONDS - status = 1 - to_chat(user, "Your jaws are now [status ? "Combat" : "Pup'd"].") - else - name = "puppy jaws" - icon_state = "smalljaws" - desc = "The jaws of a small dog." - force = initial(force) - attack_verb = list("nibbled", "bit", "gnawed", "chomped", "nommed") - stamtostunconversion = initial(stamtostunconversion) - stuncooldown = initial(stuncooldown) - status = 0 - if(R.emagged) - to_chat(user, "Your jaws are now [status ? "Combat" : "Pup'd"].") - update_icon() - -//Boop - -/obj/item/analyzer/nose - name = "boop module" - icon = 'icons/mob/dogborg.dmi' - icon_state = "nose" - desc = "The BOOP module" - flags_1 = CONDUCT_1 - force = 0 - throwforce = 0 - attack_verb = list("nuzzles", "pushes", "boops") - w_class = 1 - -/obj/item/analyzer/nose/attack_self(mob/user) - user.visible_message("[user] sniffs around the air.", "You sniff the air for gas traces.") - - var/turf/location = user.loc - if(!istype(location)) - return - - var/datum/gas_mixture/environment = location.return_air() - - var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles() - - to_chat(user, "Results:") - if(abs(pressure - ONE_ATMOSPHERE) < 10) - to_chat(user, "Pressure: [round(pressure,0.1)] kPa") - else - to_chat(user, "Pressure: [round(pressure,0.1)] kPa") - if(total_moles) - var/list/env_gases = environment.gases - - var/o2_concentration = env_gases[/datum/gas/oxygen]/total_moles - var/n2_concentration = env_gases[/datum/gas/nitrogen]/total_moles - var/co2_concentration = env_gases[/datum/gas/carbon_dioxide]/total_moles - var/plasma_concentration = env_gases[/datum/gas/plasma]/total_moles - GAS_GARBAGE_COLLECT(environment.gases) - - if(abs(n2_concentration - N2STANDARD) < 20) - to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] %") - else - to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] %") - - if(abs(o2_concentration - O2STANDARD) < 2) - to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] %") - else - to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] %") - - if(co2_concentration > 0.01) - to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] %") - else - to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] %") - - if(plasma_concentration > 0.005) - to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] %") - else - to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] %") - - - for(var/id in env_gases) - if(id in GLOB.hardcoded_gases) - continue - var/gas_concentration = env_gases[id]/total_moles - to_chat(user, "[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] %") - to_chat(user, "Temperature: [round(environment.temperature-T0C)] °C") - -/obj/item/analyzer/nose/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity) - return - do_attack_animation(target, null, src) - user.visible_message("[user] [pick(attack_verb)] \the [target.name] with their nose!") - -//Delivery -/obj/item/storage/bag/borgdelivery - name = "fetching storage" - desc = "Fetch the thing!" - icon = 'icons/mob/dogborg.dmi' - icon_state = "dbag" - w_class = WEIGHT_CLASS_BULKY - -/obj/item/storage/bag/borgdelivery/ComponentInitialize() - . = ..() - var/datum/component/storage/STR = GetComponent(/datum/component/storage) - STR.max_w_class = WEIGHT_CLASS_BULKY - STR.max_combined_w_class = 5 - STR.max_items = 1 - STR.cant_hold = typecacheof(list(/obj/item/disk/nuclear, /obj/item/radio/intercom)) - -//Tongue stuff -/obj/item/soap/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.dmi' - icon_state = "synthtongue" - hitsound = 'sound/effects/attackblob.ogg' - cleanspeed = 80 - var/status = 0 - -/obj/item/soap/tongue/scrubpup - cleanspeed = 25 //slightly faster than a mop. - -/obj/item/soap/tongue/New() - ..() - item_flags |= NOBLUDGEON //No more attack messages - -/obj/item/soap/tongue/attack_self(mob/user) - var/mob/living/silicon/robot/R = user - if(R.cell && R.cell.charge > 100) - if(R.emagged && status == 0) - status = !status - name = "energized tongue" - desc = "Your tongue is energized for dangerously maximum efficency." - icon_state = "syndietongue" - to_chat(user, "Your tongue is now [status ? "Energized" : "Normal"].") - cleanspeed = 10 //(nerf'd)tator soap stat - else - status = 0 - name = "synthetic tongue" - desc = "Useful for slurping mess off the floor before affectionally licking the crew members in the face." - icon_state = "synthtongue" - cleanspeed = initial(cleanspeed) - if(R.emagged) - to_chat(user, "Your tongue is now [status ? "Energized" : "Normal"].") - update_icon() - -/obj/item/soap/tongue/afterattack(atom/target, mob/user, proximity) - var/mob/living/silicon/robot/R = user - if(!proximity || !check_allowed_items(target)) - return - if(R.client && (target in R.client.screen)) - to_chat(R, "You need to take that [target.name] off before cleaning it!") - else if(is_cleanable(target)) - R.visible_message("[R] begins to lick off \the [target.name].", "You begin to lick off \the [target.name]...") - if(do_after(R, src.cleanspeed, target = target)) - if(!in_range(src, target)) //Proximity is probably old news by now, do a new check. - return //If they moved away, you can't eat them. - to_chat(R, "You finish licking off \the [target.name].") - qdel(target) - R.cell.give(50) - else if(isobj(target)) //hoo boy. danger zone man - if(istype(target,/obj/item/trash)) - R.visible_message("[R] nibbles away at \the [target.name].", "You begin to nibble away at \the [target.name]...") - if(!do_after(R, src.cleanspeed, target = target)) - return //If they moved away, you can't eat them. - to_chat(R, "You finish off \the [target.name].") - qdel(target) - R.cell.give(250) - return - if(istype(target,/obj/item/stock_parts/cell)) - R.visible_message("[R] begins cramming \the [target.name] down its throat.", "You begin cramming \the [target.name] down your throat...") - if(!do_after(R, 50, target = target)) - return //If they moved away, you can't eat them. - to_chat(R, "You finish off \the [target.name].") - var/obj/item/stock_parts/cell/C = target - R.cell.charge = R.cell.charge + (C.charge / 3) //Instant full cell upgrades op idgaf - qdel(target) - return - var/obj/item/I = target //HAHA FUCK IT, NOT LIKE WE ALREADY HAVE A SHITTON OF WAYS TO REMOVE SHIT - if(!I.anchored && R.emagged) - R.visible_message("[R] begins chewing up \the [target.name]. Looks like it's trying to loophole around its diet restriction!", "You begin chewing up \the [target.name]...") - if(!do_after(R, 100, target = I)) //Nerf dat time yo - return //If they moved away, you can't eat them. - visible_message("[R] chews up \the [target.name] and cleans off the debris!") - to_chat(R, "You finish off \the [target.name].") - qdel(I) - R.cell.give(500) - return - R.visible_message("[R] begins to lick \the [target.name] clean...", "You begin to lick \the [target.name] clean...") - else if(isliving(target)) - var/mob/living/L = target - if(!status) - if(L.ckey && !(L.client?.prefs.vore_flags & LICKABLE)) - to_chat(R, "ERROR ERROR: Target not lickable. Aborting display-of-affection subroutine.") - return - if(check_zone(R.zone_selected) == "head") - R.visible_message("\the [R] affectionally licks \the [L]'s face!", "You affectionally lick \the [L]'s face!") - playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1) - if(istype(L) && L.fire_stacks > 0) - L.adjust_fire_stacks(-10) - else - R.visible_message("\the [R] affectionally licks \the [L]!", "You affectionally lick \the [L]!") - playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1) - if(istype(L) && L.fire_stacks > 0) - L.adjust_fire_stacks(-10) - else - if(R.cell.charge <= 800) - to_chat(R, "Insufficent Power!") - return - L.Stun(4) // normal stunbaton is force 7 gimme a break good sir! - L.DefaultCombatKnockdown(80) - L.apply_effect(EFFECT_STUTTER, 4) - L.visible_message("[R] has shocked [L] with its tongue!", \ - "[R] has shocked you with its tongue!") - playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) - R.cell.use(666) - log_combat(R, L, "tongue stunned") - - else if(istype(target, /obj/structure/window)) - R.visible_message("[R] begins to lick \the [target.name] clean...", "You begin to lick \the [target.name] clean...") - if(do_after(user, src.cleanspeed, target = target)) - to_chat(user, "You clean \the [target.name].") - target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - target.set_opacity(initial(target.opacity)) - else - R.visible_message("[R] begins to lick \the [target.name] clean...", "You begin to lick \the [target.name] clean...") - if(do_after(user, src.cleanspeed, target = target)) - to_chat(user, "You clean \the [target.name].") - var/obj/effect/decal/cleanable/C = locate() in target - qdel(C) - target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - SEND_SIGNAL(target, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM) - target.wash_cream() - return - -//Nerfed tongue for flavour reasons (haha geddit?). Used for aux skins for regular borgs -/obj/item/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.dmi' - icon_state = "synthtongue" - hitsound = 'sound/effects/attackblob.ogg' - desc = "For giving affectionate kisses." - item_flags = NOBLUDGEON - -/obj/item/dogborg_tongue/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity || !isliving(target)) - return - var/mob/living/silicon/robot/R = user - var/mob/living/L = target - if(L.ckey && !(L.client?.prefs.vore_flags & LICKABLE)) - to_chat(R, "ERROR ERROR: Target not lickable. Aborting display-of-affection subroutine.") - return - - if(check_zone(R.zone_selected) == "head") - R.visible_message("\the [R] affectionally licks \the [L]'s face!", "You affectionally lick \the [L]'s face!") - playsound(R, 'sound/effects/attackblob.ogg', 50, 1) - else - R.visible_message("\the [R] affectionally licks \the [L]!", "You affectionally lick \the [L]!") - playsound(R, 'sound/effects/attackblob.ogg', 50, 1) - - -/obj/item/dogborg_nose - name = "boop module" - icon = 'icons/mob/dogborg.dmi' - icon_state = "nose" - desc = "The BOOP module" - flags_1 = CONDUCT_1|NOBLUDGEON - force = 0 - -/obj/item/dogborg_nose/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity) - return - do_attack_animation(target, null, src) - user.visible_message("[user] [pick(attack_verb)] \the [target.name] with their nose!") - - -//Dogfood - -/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." - icon = 'icons/mob/dogborg.dmi' - icon_state= "kibble" - -// Pounce stuff for K-9 - -/obj/item/dogborg/pounce - name = "pounce" - icon = 'icons/mob/dogborg.dmi' - icon_state = "pounce" - desc = "Leap at your target to momentarily stun them." - force = 0 - throwforce = 0 - -/obj/item/dogborg/pounce/New() - ..() - item_flags |= NOBLUDGEON - -/mob/living/silicon/robot - var/leaping = 0 - var/pounce_cooldown = 0 - var/pounce_cooldown_time = 30 //Time in deciseconds between pounces - var/pounce_spoolup = 5 //Time in deciseconds for the pounce to happen after clicking - var/pounce_stamloss_cap = 120 //How much staminaloss pounces alone are capable of bringing a spaceman to - var/pounce_stamloss = 80 //Base staminaloss value of the pounce - var/leap_at - var/disabler - var/laser - var/sleeper_g - var/sleeper_r - var/sleeper_nv - -#define MAX_K9_LEAP_DIST 4 //because something's definitely borked the pounce functioning from a distance. - -/obj/item/dogborg/pounce/afterattack(atom/A, mob/user) - var/mob/living/silicon/robot/R = user - if(R && (world.time >= R.pounce_cooldown)) - R.pounce_cooldown = world.time + R.pounce_cooldown_time - to_chat(R, "Your targeting systems lock on to [A]...") - playsound(R, 'sound/effects/servostep.ogg', 100, TRUE) - addtimer(CALLBACK(R, /mob/living/silicon/robot.proc/leap_at, A), R.pounce_spoolup) - else if(R && (world.time < R.pounce_cooldown)) - to_chat(R, "Your leg actuators are still recharging!") - -/mob/living/silicon/robot/proc/leap_at(atom/A) - if(leaping || stat || buckled || lying) - return - - if(!has_gravity(src) || !has_gravity(A)) - to_chat(src,"It is unsafe to leap without gravity!") - //It's also extremely buggy visually, so it's balance+bugfix - return - - if(cell.charge <= 750) - to_chat(src,"Insufficent reserves for jump actuators!") - return - - else - leaping = 1 - weather_immunities += "lava" - pixel_y = 10 - update_icons() - throw_at(A, MAX_K9_LEAP_DIST, 1, spin=0, diagonals_first = 1) - cell.use(750) //Less than a stunbaton since stunbatons hit everytime. - playsound(src, 'sound/effects/stealthoff.ogg', 25, TRUE, -1) - weather_immunities -= "lava" - -/mob/living/silicon/robot/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) - - if(!leaping) - return ..() - - if(hit_atom) - if(isliving(hit_atom)) - var/mob/living/L = hit_atom - if(L.run_block(0, "the [name]", src, ATTACK_TYPE_TACKLE, 0, src) & BLOCK_SUCCESS) - DefaultCombatKnockdown(15, 1, 1) - else - L.visible_message("[src] pounces on [L]!", "[src] pounces on you!") - L.DefaultCombatKnockdown(iscarbon(L) ? 60 : 45, override_stamdmg = clamp(pounce_stamloss, 0, pounce_stamloss_cap-L.getStaminaLoss())) // Temporary. If someone could rework how dogborg pounces work to accomodate for combat changes, that'd be nice. - playsound(src, 'sound/weapons/Egloves.ogg', 50, 1) - sleep(2)//Runtime prevention (infinite bump() calls on hulks) - step_towards(src,L) - log_combat(src, L, "borg pounced") - - pounce_cooldown = !pounce_cooldown - spawn(pounce_cooldown_time) //3s by default - pounce_cooldown = !pounce_cooldown - else if(hit_atom.density && !hit_atom.CanPass(src)) - visible_message("[src] smashes into [hit_atom]!", "You smash into [hit_atom]!") - playsound(src, 'sound/items/trayhit1.ogg', 50, 1) - DefaultCombatKnockdown(15, 1, 1) - - if(leaping) - leaping = 0 - pixel_y = initial(pixel_y) - update_icons() - update_mobility() diff --git a/tgstation.dme b/tgstation.dme index bb27ca021c..d115bac2d1 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2432,6 +2432,7 @@ #include "code\modules\mob\living\silicon\robot\login.dm" #include "code\modules\mob\living\silicon\robot\robot.dm" #include "code\modules\mob\living\silicon\robot\robot_defense.dm" +#include "code\modules\mob\living\silicon\robot\robot_defines.dm" #include "code\modules\mob\living\silicon\robot\robot_mobility.dm" #include "code\modules\mob\living\silicon\robot\robot_modules.dm" #include "code\modules\mob\living\silicon\robot\robot_movement.dm" @@ -3360,7 +3361,6 @@ #include "modular_citadel\code\modules\mob\living\carbon\reindex_screams.dm" #include "modular_citadel\code\modules\mob\living\carbon\human\human.dm" #include "modular_citadel\code\modules\mob\living\carbon\human\human_defense.dm" -#include "modular_citadel\code\modules\mob\living\silicon\robot\dogborg_equipment.dm" #include "modular_citadel\code\modules\projectiles\gun.dm" #include "modular_citadel\code\modules\projectiles\ammunition\caseless.dm" #include "modular_citadel\code\modules\projectiles\ammunition\ballistic\smg\smg.dm"