This commit is contained in:
Putnam
2020-01-15 15:57:32 -08:00
1186 changed files with 197837 additions and 199067 deletions
@@ -1,7 +0,0 @@
/obj/effect/spawner/lootdrop/keg
name = "random keg spawner"
lootcount = 1
loot = list(/obj/structure/reagent_dispensers/keg/mead = 5,
/obj/structure/reagent_dispensers/keg/aphro = 2,
/obj/structure/reagent_dispensers/keg/aphro/strong = 2,
/obj/structure/reagent_dispensers/keg/gargle = 1)
@@ -1,15 +0,0 @@
/obj/item
var/list/alternate_screams = list() //REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
// lazy for screaming.
/obj/item/clothing/head/xenos
alternate_screams = list('sound/voice/hiss6.ogg')
/obj/item/clothing/head/cardborg
alternate_screams = list('modular_citadel/sound/voice/scream_silicon.ogg')
/obj/item/clothing/head/ushanka
alternate_screams = list('sound/voice/human/cyka1.ogg', 'sound/voice/human/cheekibreeki.ogg')
/obj/item/proc/grenade_prime_react(obj/item/grenade/nade)
return
@@ -1,92 +0,0 @@
/* BALLS - GLORIOUS BALLS
//
// Includes:-
// 1) Tennis balls, lines 10 - 92
//
//
//
*/
/obj/item/toy/tennis
name = "tennis ball"
desc = "A classical tennis ball. It appears to have faint bite marks scattered all over its surface."
icon = 'modular_citadel/icons/obj/balls.dmi'
icon_state = "tennis_classic"
lefthand_file = 'modular_citadel/icons/mob/inhands/balls_left.dmi'
righthand_file = 'modular_citadel/icons/mob/inhands/balls_right.dmi'
item_state = "tennis_classic"
alternate_worn_icon = 'modular_citadel/icons/mob/mouthball.dmi'
slot_flags = ITEM_SLOT_HEAD | ITEM_SLOT_NECK | ITEM_SLOT_EARS //Fluff item, put it wherever you want!
throw_range = 14
w_class = WEIGHT_CLASS_SMALL
/obj/item/toy/tennis/pre_altattackby(atom/A, mob/living/user, params) //checks if it can do right click memes
altafterattack(A, user, TRUE, params)
return TRUE
/obj/item/toy/tennis/altafterattack(atom/target, mob/living/carbon/user, proximity_flag, click_parameters) //does right click memes
if(istype(user))
user.visible_message("<span class='notice'>[user] waggles [src] at [target].</span>", "<span class='notice'>You waggle [src] at [target].</span>")
return TRUE
/obj/item/toy/tennis/rainbow
name = "pseudo-euclidean interdimensional tennis sphere"
desc = "A tennis ball from another plane of existance. Really groovy."
icon_state = "tennis_rainbow"
item_state = "tennis_rainbow"
actions_types = list(/datum/action/item_action/squeeze) //Giving the masses easy access to unilimted honks would be annoying
/obj/item/toy/tennis/rainbow/Initialize()
. = ..()
AddComponent(/datum/component/squeak)
/obj/item/toy/tennis/rainbow/izzy //izzyinbox's donator item
name = "Katlin's Ball"
desc = "A tennis ball that's seen a good bit of love, being covered in a few black and white hairs and slobber."
icon_state = "tennis_izzy"
item_state = "tennis_izzy"
/obj/item/toy/tennis/red //da red wuns go fasta
name = "red tennis ball"
desc = "A red tennis ball. It goes three times faster!"
icon_state = "tennis_red"
item_state = "tennis_red"
throw_speed = 9
/obj/item/toy/tennis/yellow //because yellow is hot I guess
name = "yellow tennis ball"
desc = "A yellow tennis ball. It seems to have a flame-retardant coating."
icon_state = "tennis_yellow"
item_state = "tennis_yellow"
resistance_flags = FIRE_PROOF
/obj/item/toy/tennis/green //pestilence
name = "green tennis ball"
desc = "A green tennis ball. It seems to have an impermeable coating."
icon_state = "tennis_green"
item_state = "tennis_green"
permeability_coefficient = 0.9
/obj/item/toy/tennis/cyan //electric
name = "cyan tennis ball"
desc = "A cyan tennis ball. It seems to have odd electrical properties."
icon_state = "tennis_cyan"
item_state = "tennis_cyan"
siemens_coefficient = 0.9
/obj/item/toy/tennis/blue //reliability
name = "blue tennis ball"
desc = "A blue tennis ball. It seems ever so slightly more robust than normal."
icon_state = "tennis_blue"
item_state = "tennis_blue"
max_integrity = 300
/obj/item/toy/tennis/purple //because purple dyes have high pH and would neutralize acids I guess
name = "purple tennis ball"
desc = "A purple tennis ball. It seems to have an acid-resistant coating."
icon_state = "tennis_purple"
item_state = "tennis_purple"
resistance_flags = ACID_PROOF
/datum/action/item_action/squeeze
name = "Squeak!"
@@ -1,61 +0,0 @@
/obj/item/boombox
name = "boombox"
desc = "A dusty, gray, bulky, battery-powered, auto-looping stereo cassette player. An ancient relic from prehistoric times on that one planet with humans and stuff. Yeah, that one."
icon = 'modular_citadel/icons/obj/boombox.dmi'
icon_state = "raiqbawks_off"//PLACEHOLDER UNTIL SOMEONE SPRITES PLAIN NON-FANCY BOOMBOXES
w_class = WEIGHT_CLASS_NORMAL
force = 3
var/baseiconstate = "raiqbawks"
var/boomingandboxing = FALSE
var/list/availabletrackids
/obj/item/boombox/attack_self(mob/user)
. = ..()
if(boomingandboxing)
SSjukeboxes.removejukebox(SSjukeboxes.findjukeboxindex(src))
boomingandboxing = FALSE
to_chat(user, "<span class='notice'>You flip a switch on [src], and the music immediately stops.")
update_icon()
return
if(!availabletrackids || !availabletrackids.len)
to_chat(user, "<span class='notice'>[src] flashes as you prod it senselessly. It doesn't have any songs stored on it.</span>")
return
if(!boomingandboxing)
var/list/tracklist = list()
for(var/datum/track/S in SSjukeboxes.songs)
if(istype(S) && S.song_associated_id in availabletrackids)
tracklist[S.song_name] = S
var/selected = input(user, "Play song", "Track:") as null|anything in tracklist
if(QDELETED(src) || !selected || !istype(tracklist[selected], /datum/track))
return
var/jukeboxslottotake = SSjukeboxes.addjukebox(src, tracklist[selected])
if(jukeboxslottotake)
boomingandboxing = TRUE
update_icon()
/obj/item/boombox/Destroy(mob/user)
SSjukeboxes.removejukebox(SSjukeboxes.findjukeboxindex(src))
. = ..()
/obj/item/boombox/update_icon()
icon_state = "[baseiconstate]_[boomingandboxing ? "on" : "off"]"
return
/obj/item/boombox/raiq
name = "Miami Boomer"
desc = "A shiny, fashionable boombox filled to the brim with neon lights, synthesizers, gang violence, and broken R keys. A worn-out sticker on the back states \"Includes three kickin' beats!\""
icon_state = "raiqbawks_off"
baseiconstate = "raiqbawks"
availabletrackids = list("hotline.ogg","chiptune.ogg","genesis.ogg")
/obj/item/boombox/raiq/update_icon()
. = ..()
if(boomingandboxing)
START_PROCESSING(SSobj, src)
else
STOP_PROCESSING(SSobj, src)
set_light(0)
/obj/item/boombox/raiq/process()
set_light(5,0.95,pick("#d87aff","#7a7aff","#89ecff","#b88eff","#ff59ad"))
return
@@ -1,10 +0,0 @@
/obj/item/encryptionkey/heads/qm
name = "\proper the quartermaster's encryption key"
desc = "An encryption key for a radio headset. Channels are as follows: :u - supply, :c - command."
icon_state = "hop_cypherkey"
channels = list("Supply" = 1, "Command" = 1)
/obj/item/encryptionkey/heads/hop
desc = "An encryption key for a radio headset. Channels are as follows: :v - service, :c - command."
channels = list("Service" = 1, "Command" = 1)
@@ -1,10 +0,0 @@
/obj/item/radio/headset/heads/qm
name = "\proper the quartermaster's headset"
desc = "The headset of the king (or queen) of paperwork.\nChannels are as follows: :u - supply, :c - command."
icon_state = "com_headset"
keyslot = new /obj/item/encryptionkey/heads/qm
/obj/item/radio/headset/heads/hop
desc = "The headset of the guy who will one day be captain.\nChannels are as follows: :v - service, :c - command."
keyslot = new /obj/item/encryptionkey/heads/hop
@@ -1,83 +0,0 @@
/obj/item/electropack/shockcollar
name = "shock collar"
desc = "A reinforced metal collar. It seems to have some form of wiring near the front. Strange.."
icon = 'modular_citadel/icons/obj/clothing/cit_neck.dmi'
alternate_worn_icon = 'modular_citadel/icons/mob/citadel/neck.dmi'
icon_state = "shockcollar"
item_state = "shockcollar"
body_parts_covered = NECK
slot_flags = ITEM_SLOT_NECK | ITEM_SLOT_DENYPOCKET //no more pocket shockers
w_class = WEIGHT_CLASS_SMALL
strip_delay = 60
equip_delay_other = 60
materials = list(MAT_METAL=5000, MAT_GLASS=2000)
var/tagname = null
/datum/design/electropack/shockcollar
name = "Shockcollar"
id = "shockcollar"
build_type = AUTOLATHE
build_path = /obj/item/electropack/shockcollar
materials = list(MAT_METAL=5000, MAT_GLASS=2000)
category = list("hacked", "Misc")
/obj/item/electropack/shockcollar/attack_hand(mob/user)
if(loc == user && user.get_item_by_slot(SLOT_NECK))
to_chat(user, "<span class='warning'>The collar is fastened tight! You'll need help taking this off!</span>")
return
..()
/obj/item/electropack/shockcollar/receive_signal(datum/signal/signal)
if(!signal || signal.data["code"] != code)
return
if(isliving(loc) && on)
if(shock_cooldown != 0)
return
shock_cooldown = 1
spawn(100)
shock_cooldown = 0
var/mob/living/L = loc
step(L, pick(GLOB.cardinals))
to_chat(L, "<span class='danger'>You feel a sharp shock from the collar!</span>")
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, L)
s.start()
L.Knockdown(100)
if(master)
master.receive_signal()
return
/obj/item/electropack/shockcollar/attack_self(mob/user) //Turns out can't fully source this from the parent item, spritepath gets confused if power toggled. Will come back to this when I know how to code better and readd powertoggle..
var/option = "Change Name"
option = input(user, "What do you want to do?", "[src]", option) as null|anything in list("Change Name", "Change Frequency")
switch(option)
if("Change Name")
var/t = input(user, "Would you like to change the name on the tag?", "Name your new pet", tagname ? tagname : "Spot") as null|text
if(t)
tagname = copytext(sanitize(t), 1, MAX_NAME_LEN)
name = "[initial(name)] - [tagname]"
if("Change Frequency")
if(!ishuman(user))
return
user.set_machine(src)
var/dat = {"<SK><BR>
<B>Frequency/Code</B> for shock collar:<BR>
Frequency:
<A href='byond://?src=\ref[src];freq=-10'>-</A>
<A href='byond://?src=\ref[src];freq=-2'>-</A> [format_frequency(frequency)]
<A href='byond://?src=\ref[src];freq=2'>+</A>
<A href='byond://?src=\ref[src];freq=10'>+</A><BR>
Code:
<A href='byond://?src=\ref[src];code=-5'>-</A>
<A href='byond://?src=\ref[src];code=-1'>-</A> [code]
<A href='byond://?src=\ref[src];code=1'>+</A>
<A href='byond://?src=\ref[src];code=5'>+</A><BR>
</SK>"}
user << browse(dat, "window=radio")
onclose(user, "radio")
return
@@ -1,41 +0,0 @@
/obj/item/melee/baton/stunsword
name = "stunsword"
desc = "not actually sharp, this sword is functionally identical to a stunbaton"
icon = 'modular_citadel/icons/obj/stunsword.dmi'
icon_state = "stunsword"
item_state = "sword"
lefthand_file = 'modular_citadel/icons/mob/inhands/stunsword_left.dmi'
righthand_file = 'modular_citadel/icons/mob/inhands/stunsword_right.dmi'
/obj/item/melee/baton/stunsword/get_belt_overlay()
if(istype(loc, /obj/item/storage/belt/sabre))
return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "stunsword")
return ..()
/obj/item/melee/baton/stunsword/get_worn_belt_overlay(icon_file)
return mutable_appearance(icon_file, "-stunsword")
/obj/item/ssword_kit
name = "stunsword kit"
desc = "a modkit for making a stunbaton into a stunsword"
icon = 'icons/obj/vending_restock.dmi'
icon_state = "refill_donksoft"
var/product = /obj/item/melee/baton/stunsword //what it makes
var/list/fromitem = list(/obj/item/melee/baton, /obj/item/melee/baton/loaded) //what it needs
afterattack(obj/O, mob/user as mob)
if(istype(O, product))
to_chat(user,"<span class='warning'>[O] is already modified!")
else if(O.type in fromitem) //makes sure O is the right thing
var/obj/item/melee/baton/B = O
if(!B.cell) //checks for a powercell in the baton. If there isn't one, continue. If there is, warn the user to take it out
new product(usr.loc) //spawns the product
user.visible_message("<span class='warning'>[user] modifies [O]!","<span class='warning'>You modify the [O]!")
qdel(O) //Gets rid of the baton
qdel(src) //gets rid of the kit
else
to_chat(user,"<span class='warning'>Remove the powercell first!</span>") //We make this check because the stunsword starts without a battery.
else
to_chat(user, "<span class='warning'> You can't modify [O] with this kit!</span>")
-5
View File
@@ -1,5 +0,0 @@
//init file stolen from hippie
/proc/cit_initialize()
load_mentors()
initialize_global_loadout_items()
@@ -1,7 +1,7 @@
/datum/gear/greytidestationwide
name = "Grey jumpsuit"
name = "Staff Assistant's jumpsuit"
category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/color/grey
path = /obj/item/clothing/under/staffassistant
restricted_roles = list("Assistant")
/datum/gear/neetsuit
@@ -93,6 +93,7 @@
restricted_desc = "Engineering, Security, and Cargo"
restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster")
/*Commenting out Until next Christmas or made automatic
/datum/gear/santahatr
name = "Red Santa Hat"
category = SLOT_HEAD
@@ -102,6 +103,7 @@
name = "Green Santa Hat"
category = SLOT_HEAD
path = /obj/item/clothing/head/christmashatg
*/
/datum/gear/cowboyhat
name = "Cowboy Hat, Brown"
@@ -129,6 +131,3 @@
path = /obj/item/clothing/head/cowboyhat/sec
restricted_desc = "Security"
restricted_roles = list("Warden","Detective","Security Officer","Head of Security")
@@ -390,6 +390,7 @@
path = /obj/item/clothing/under/gear_harness
//Christmas
/*Commenting out Until next Christmas or made automatic
/datum/gear/christmasmaler
name = "Red Masculine Christmas Suit"
category = SLOT_W_UNIFORM
@@ -415,6 +416,7 @@
category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/stripper_pink
cost = 3
*/
/datum/gear/greenstripper
name = "Green stripper outfit"
@@ -1,449 +1,449 @@
/*
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))
. += "<span class='notice'>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.</span>"
/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, "<span class='warning'>You already have [A] in your jaws.</span>")
return
if(nextstuntime >= world.time)
to_chat(user, "<span class='warning'>Your jaw servos are still recharging.</span>")
return
nextstuntime = world.time + stuncooldown
var/mob/living/M = A
var/cachedstam = M.getStaminaLoss()
var/totalstuntime = cachedstam * stamtostunconversion * (M.lying ? 2 : 1)
if(!M.resting)
M.Knockdown(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("<span class='danger'>[user] clamps [user.p_their()] [src] onto [M] and latches on!</span>", "<span class='userdanger'>[user] clamps [user.p_their()] [src] onto you and latches on!</span>")
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, "<span class='notice'>Your jaws are now [status ? "Combat" : "Pup'd"].</span>")
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, "<span class='notice'>Your jaws are now [status ? "Combat" : "Pup'd"].</span>")
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.", "<span class='warning'>You sniff the air for gas traces.</span>")
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, "<span class='info'><B>Results:</B></span>")
if(abs(pressure - ONE_ATMOSPHERE) < 10)
to_chat(user, "<span class='info'>Pressure: [round(pressure,0.1)] kPa</span>")
else
to_chat(user, "<span class='alert'>Pressure: [round(pressure,0.1)] kPa</span>")
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, "<span class='info'>Nitrogen: [round(n2_concentration*100, 0.01)] %</span>")
else
to_chat(user, "<span class='alert'>Nitrogen: [round(n2_concentration*100, 0.01)] %</span>")
if(abs(o2_concentration - O2STANDARD) < 2)
to_chat(user, "<span class='info'>Oxygen: [round(o2_concentration*100, 0.01)] %</span>")
else
to_chat(user, "<span class='alert'>Oxygen: [round(o2_concentration*100, 0.01)] %</span>")
if(co2_concentration > 0.01)
to_chat(user, "<span class='alert'>CO2: [round(co2_concentration*100, 0.01)] %</span>")
else
to_chat(user, "<span class='info'>CO2: [round(co2_concentration*100, 0.01)] %</span>")
if(plasma_concentration > 0.005)
to_chat(user, "<span class='alert'>Plasma: [round(plasma_concentration*100, 0.01)] %</span>")
else
to_chat(user, "<span class='info'>Plasma: [round(plasma_concentration*100, 0.01)] %</span>")
for(var/id in env_gases)
if(id in GLOB.hardcoded_gases)
continue
var/gas_concentration = env_gases[id]/total_moles
to_chat(user, "<span class='alert'>[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] %</span>")
to_chat(user, "<span class='info'>Temperature: [round(environment.temperature-T0C)] &deg;C</span>")
/obj/item/analyzer/nose/afterattack(atom/target, mob/user, proximity)
. = ..()
if(!proximity)
return
do_attack_animation(target, null, src)
user.visible_message("<span class='notice'>[user] [pick(attack_verb)] \the [target.name] with their nose!</span>")
//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, "<span class='notice'>Your tongue is now [status ? "Energized" : "Normal"].</span>")
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, "<span class='notice'>Your tongue is now [status ? "Energized" : "Normal"].</span>")
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, "<span class='warning'>You need to take that [target.name] off before cleaning it!</span>")
else if(is_cleanable(target))
R.visible_message("[R] begins to lick off \the [target.name].", "<span class='warning'>You begin to lick off \the [target.name]...</span>")
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, "<span class='notice'>You finish licking off \the [target.name].</span>")
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].", "<span class='warning'>You begin to nibble away at \the [target.name]...</span>")
if(!do_after(R, src.cleanspeed, target = target))
return //If they moved away, you can't eat them.
to_chat(R, "<span class='notice'>You finish off \the [target.name].</span>")
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.", "<span class='warning'>You begin cramming \the [target.name] down your throat...</span>")
if(!do_after(R, 50, target = target))
return //If they moved away, you can't eat them.
to_chat(R, "<span class='notice'>You finish off \the [target.name].</span>")
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!", "<span class='warning'>You begin chewing up \the [target.name]...</span>")
if(!do_after(R, 100, target = I)) //Nerf dat time yo
return //If they moved away, you can't eat them.
visible_message("<span class='warning'>[R] chews up \the [target.name] and cleans off the debris!</span>")
to_chat(R, "<span class='notice'>You finish off \the [target.name].</span>")
qdel(I)
R.cell.give(500)
return
R.visible_message("[R] begins to lick \the [target.name] clean...", "<span class='notice'>You begin to lick \the [target.name] clean...</span>")
else if(ishuman(target))
var/mob/living/L = target
if(status == 0 && check_zone(R.zone_selected) == "head")
R.visible_message("<span class='warning'>\the [R] affectionally licks \the [L]'s face!</span>", "<span class='notice'>You affectionally lick \the [L]'s face!</span>")
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
if(istype(L) && L.fire_stacks > 0)
L.adjust_fire_stacks(-10)
return
else if(status == 0)
R.visible_message("<span class='warning'>\the [R] affectionally licks \the [L]!</span>", "<span class='notice'>You affectionally lick \the [L]!</span>")
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
if(istype(L) && L.fire_stacks > 0)
L.adjust_fire_stacks(-10)
return
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.Knockdown(80)
L.apply_effect(EFFECT_STUTTER, 4)
L.visible_message("<span class='danger'>[R] has shocked [L] with its tongue!</span>", \
"<span class='userdanger'>[R] has shocked you with its tongue!</span>")
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...", "<span class='notice'>You begin to lick \the [target.name] clean...</span>")
if(do_after(user, src.cleanspeed, target = target))
to_chat(user, "<span class='notice'>You clean \the [target.name].</span>")
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...", "<span class='notice'>You begin to lick \the [target.name] clean...</span>")
if(do_after(user, src.cleanspeed, target = target))
to_chat(user, "<span class='notice'>You clean \the [target.name].</span>")
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/soap/tongue/flavour
desc = "For giving affectionate kisses."
/obj/item/soap/tongue/flavour/attack_self(mob/user)
return
/obj/item/soap/tongue/flavour/afterattack(atom/target, mob/user, proximity)
if(!proximity)
return
var/mob/living/silicon/robot/R = user
if(ishuman(target))
var/mob/living/L = target
if(status == 0 && check_zone(R.zone_selected) == "head")
R.visible_message("<span class='warning'>\the [R] affectionally licks \the [L]'s face!</span>", "<span class='notice'>You affectionally lick \the [L]'s face!</span>")
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
return
else if(status == 0)
R.visible_message("<span class='warning'>\the [R] affectionally licks \the [L]!</span>", "<span class='notice'>You affectionally lick \the [L]!</span>")
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
return
//Same as above but for noses
/obj/item/analyzer/nose/flavour/AltClick(mob/user)
return
/obj/item/analyzer/nose/flavour/attack_self(mob/user)
return
/obj/item/analyzer/nose/flavour/afterattack(atom/target, mob/user, proximity)
if(!proximity)
return
do_attack_animation(target, null, src)
user.visible_message("<span class='notice'>[user] [pick(attack_verb)] \the [target.name] with their nose!</span>")
//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, "<span class ='warning'>Your targeting systems lock on to [A]...</span>")
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, "<span class='danger'>Your leg actuators are still recharging!</span>")
/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,"<span class='danger'>It is unsafe to leap without gravity!</span>")
//It's also extremely buggy visually, so it's balance+bugfix
return
if(cell.charge <= 750)
to_chat(src,"<span class='danger'>Insufficent reserves for jump actuators!</span>")
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/A)
if(!leaping)
return ..()
if(A)
if(isliving(A))
var/mob/living/L = A
if(!L.check_shields(0, "the [name]", src, attack_type = LEAP_ATTACK))
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
L.Knockdown(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")
else
Knockdown(15, 1, 1)
pounce_cooldown = !pounce_cooldown
spawn(pounce_cooldown_time) //3s by default
pounce_cooldown = !pounce_cooldown
else if(A.density && !A.CanPass(src))
visible_message("<span class ='danger'>[src] smashes into [A]!</span>", "<span class ='userdanger'>You smash into [A]!</span>")
playsound(src, 'sound/items/trayhit1.ogg', 50, 1)
Knockdown(15, 1, 1)
if(leaping)
leaping = 0
pixel_y = initial(pixel_y)
update_icons()
update_canmove()
/*
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))
. += "<span class='notice'>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.</span>"
/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, "<span class='warning'>You already have [A] in your jaws.</span>")
return
if(nextstuntime >= world.time)
to_chat(user, "<span class='warning'>Your jaw servos are still recharging.</span>")
return
nextstuntime = world.time + stuncooldown
var/mob/living/M = A
var/cachedstam = M.getStaminaLoss()
var/totalstuntime = cachedstam * stamtostunconversion * (M.lying ? 2 : 1)
if(!M.resting)
M.Knockdown(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("<span class='danger'>[user] clamps [user.p_their()] [src] onto [M] and latches on!</span>", "<span class='userdanger'>[user] clamps [user.p_their()] [src] onto you and latches on!</span>")
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, "<span class='notice'>Your jaws are now [status ? "Combat" : "Pup'd"].</span>")
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, "<span class='notice'>Your jaws are now [status ? "Combat" : "Pup'd"].</span>")
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.", "<span class='warning'>You sniff the air for gas traces.</span>")
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, "<span class='info'><B>Results:</B></span>")
if(abs(pressure - ONE_ATMOSPHERE) < 10)
to_chat(user, "<span class='info'>Pressure: [round(pressure,0.1)] kPa</span>")
else
to_chat(user, "<span class='alert'>Pressure: [round(pressure,0.1)] kPa</span>")
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, "<span class='info'>Nitrogen: [round(n2_concentration*100, 0.01)] %</span>")
else
to_chat(user, "<span class='alert'>Nitrogen: [round(n2_concentration*100, 0.01)] %</span>")
if(abs(o2_concentration - O2STANDARD) < 2)
to_chat(user, "<span class='info'>Oxygen: [round(o2_concentration*100, 0.01)] %</span>")
else
to_chat(user, "<span class='alert'>Oxygen: [round(o2_concentration*100, 0.01)] %</span>")
if(co2_concentration > 0.01)
to_chat(user, "<span class='alert'>CO2: [round(co2_concentration*100, 0.01)] %</span>")
else
to_chat(user, "<span class='info'>CO2: [round(co2_concentration*100, 0.01)] %</span>")
if(plasma_concentration > 0.005)
to_chat(user, "<span class='alert'>Plasma: [round(plasma_concentration*100, 0.01)] %</span>")
else
to_chat(user, "<span class='info'>Plasma: [round(plasma_concentration*100, 0.01)] %</span>")
for(var/id in env_gases)
if(id in GLOB.hardcoded_gases)
continue
var/gas_concentration = env_gases[id]/total_moles
to_chat(user, "<span class='alert'>[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] %</span>")
to_chat(user, "<span class='info'>Temperature: [round(environment.temperature-T0C)] &deg;C</span>")
/obj/item/analyzer/nose/afterattack(atom/target, mob/user, proximity)
. = ..()
if(!proximity)
return
do_attack_animation(target, null, src)
user.visible_message("<span class='notice'>[user] [pick(attack_verb)] \the [target.name] with their nose!</span>")
//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, "<span class='notice'>Your tongue is now [status ? "Energized" : "Normal"].</span>")
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, "<span class='notice'>Your tongue is now [status ? "Energized" : "Normal"].</span>")
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, "<span class='warning'>You need to take that [target.name] off before cleaning it!</span>")
else if(is_cleanable(target))
R.visible_message("[R] begins to lick off \the [target.name].", "<span class='warning'>You begin to lick off \the [target.name]...</span>")
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, "<span class='notice'>You finish licking off \the [target.name].</span>")
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].", "<span class='warning'>You begin to nibble away at \the [target.name]...</span>")
if(!do_after(R, src.cleanspeed, target = target))
return //If they moved away, you can't eat them.
to_chat(R, "<span class='notice'>You finish off \the [target.name].</span>")
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.", "<span class='warning'>You begin cramming \the [target.name] down your throat...</span>")
if(!do_after(R, 50, target = target))
return //If they moved away, you can't eat them.
to_chat(R, "<span class='notice'>You finish off \the [target.name].</span>")
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!", "<span class='warning'>You begin chewing up \the [target.name]...</span>")
if(!do_after(R, 100, target = I)) //Nerf dat time yo
return //If they moved away, you can't eat them.
visible_message("<span class='warning'>[R] chews up \the [target.name] and cleans off the debris!</span>")
to_chat(R, "<span class='notice'>You finish off \the [target.name].</span>")
qdel(I)
R.cell.give(500)
return
R.visible_message("[R] begins to lick \the [target.name] clean...", "<span class='notice'>You begin to lick \the [target.name] clean...</span>")
else if(ishuman(target))
var/mob/living/L = target
if(status == 0 && check_zone(R.zone_selected) == "head")
R.visible_message("<span class='warning'>\the [R] affectionally licks \the [L]'s face!</span>", "<span class='notice'>You affectionally lick \the [L]'s face!</span>")
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
if(istype(L) && L.fire_stacks > 0)
L.adjust_fire_stacks(-10)
return
else if(status == 0)
R.visible_message("<span class='warning'>\the [R] affectionally licks \the [L]!</span>", "<span class='notice'>You affectionally lick \the [L]!</span>")
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
if(istype(L) && L.fire_stacks > 0)
L.adjust_fire_stacks(-10)
return
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.Knockdown(80)
L.apply_effect(EFFECT_STUTTER, 4)
L.visible_message("<span class='danger'>[R] has shocked [L] with its tongue!</span>", \
"<span class='userdanger'>[R] has shocked you with its tongue!</span>")
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...", "<span class='notice'>You begin to lick \the [target.name] clean...</span>")
if(do_after(user, src.cleanspeed, target = target))
to_chat(user, "<span class='notice'>You clean \the [target.name].</span>")
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...", "<span class='notice'>You begin to lick \the [target.name] clean...</span>")
if(do_after(user, src.cleanspeed, target = target))
to_chat(user, "<span class='notice'>You clean \the [target.name].</span>")
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/soap/tongue/flavour
desc = "For giving affectionate kisses."
/obj/item/soap/tongue/flavour/attack_self(mob/user)
return
/obj/item/soap/tongue/flavour/afterattack(atom/target, mob/user, proximity)
if(!proximity)
return
var/mob/living/silicon/robot/R = user
if(ishuman(target))
var/mob/living/L = target
if(status == 0 && check_zone(R.zone_selected) == "head")
R.visible_message("<span class='warning'>\the [R] affectionally licks \the [L]'s face!</span>", "<span class='notice'>You affectionally lick \the [L]'s face!</span>")
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
return
else if(status == 0)
R.visible_message("<span class='warning'>\the [R] affectionally licks \the [L]!</span>", "<span class='notice'>You affectionally lick \the [L]!</span>")
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
return
//Same as above but for noses
/obj/item/analyzer/nose/flavour/AltClick(mob/user)
return
/obj/item/analyzer/nose/flavour/attack_self(mob/user)
return
/obj/item/analyzer/nose/flavour/afterattack(atom/target, mob/user, proximity)
if(!proximity)
return
do_attack_animation(target, null, src)
user.visible_message("<span class='notice'>[user] [pick(attack_verb)] \the [target.name] with their nose!</span>")
//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, "<span class ='warning'>Your targeting systems lock on to [A]...</span>")
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, "<span class='danger'>Your leg actuators are still recharging!</span>")
/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,"<span class='danger'>It is unsafe to leap without gravity!</span>")
//It's also extremely buggy visually, so it's balance+bugfix
return
if(cell.charge <= 750)
to_chat(src,"<span class='danger'>Insufficent reserves for jump actuators!</span>")
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/A)
if(!leaping)
return ..()
if(A)
if(isliving(A))
var/mob/living/L = A
if(!L.check_shields(0, "the [name]", src, attack_type = LEAP_ATTACK))
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
L.Knockdown(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")
else
Knockdown(15, 1, 1)
pounce_cooldown = !pounce_cooldown
spawn(pounce_cooldown_time) //3s by default
pounce_cooldown = !pounce_cooldown
else if(A.density && !A.CanPass(src))
visible_message("<span class ='danger'>[src] smashes into [A]!</span>", "<span class ='userdanger'>You smash into [A]!</span>")
playsound(src, 'sound/items/trayhit1.ogg', 50, 1)
Knockdown(15, 1, 1)
if(leaping)
leaping = 0
pixel_y = initial(pixel_y)
update_icons()
update_canmove()