diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm
index cfd57b4850..f50b1beeb3 100644
--- a/code/controllers/configuration/entries/game_options.dm
+++ b/code/controllers/configuration/entries/game_options.dm
@@ -66,6 +66,10 @@
/datum/config_entry/flag/disable_human_mood
+/datum/config_entry/flag/disable_borg_flash_knockdown //Should borg flashes be capable of knocking humanoid entities down?
+
+/datum/config_entry/flag/weaken_secborg //Brings secborgs and k9s back in-line with the other borg modules
+
/datum/config_entry/flag/disable_secborg // disallow secborg module to be chosen.
/datum/config_entry/flag/disable_peaceborg
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index 9c929a6ebf..680bf948d8 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -89,32 +89,36 @@
R.speed = initial(R.speed)
/obj/item/borg/upgrade/disablercooler
- name = "cyborg rapid disabler cooling module"
- desc = "Used to cool a mounted disabler, increasing the potential current in it and thus its recharge rate."
+ name = "cyborg rapid energy blaster cooling module"
+ desc = "Used to cool a mounted energy-based firearm, increasing the potential current in it and thus its recharge rate."
icon_state = "cyborg_upgrade3"
require_module = 1
/obj/item/borg/upgrade/disablercooler/action(mob/living/silicon/robot/R, user = usr)
. = ..()
if(.)
- var/obj/item/gun/energy/disabler/cyborg/T = locate() in R.module.modules
- if(!T)
- to_chat(user, "There's no disabler in this unit!")
+ var/successflag
+ for(var/obj/item/gun/energy/T in R.module.modules)
+ if(T.charge_delay <= 2)
+ successflag = successflag || 2
+ continue
+ T.charge_delay = max(2, T.charge_delay - 4)
+ successflag = 1
+ if(!successflag)
+ to_chat(user, "There's no energy-based firearm in this unit!")
return FALSE
- if(T.charge_delay <= 2)
+ if(successflag == 2)
to_chat(R, "A cooling unit is already installed!")
to_chat(user, "There's no room for another cooling unit!")
return FALSE
- T.charge_delay = max(2 , T.charge_delay - 4)
-
/obj/item/borg/upgrade/disablercooler/deactivate(mob/living/silicon/robot/R, user = usr)
. = ..()
if (.)
- var/obj/item/gun/energy/disabler/cyborg/T = locate() in R.module.modules
- if(!T)
- return FALSE
- T.charge_delay = initial(T.charge_delay)
+ for(var/obj/item/gun/energy/T in R.module.modules)
+ T.charge_delay = initial(T.charge_delay)
+ return .
+ return FALSE
/obj/item/borg/upgrade/thrusters
name = "ion thruster upgrade"
diff --git a/code/modules/assembly/flash.dm b/code/modules/assembly/flash.dm
index 186eb1b024..ff684de243 100644
--- a/code/modules/assembly/flash.dm
+++ b/code/modules/assembly/flash.dm
@@ -201,8 +201,10 @@
/obj/item/assembly/flash/cyborg
/obj/item/assembly/flash/cyborg/attack(mob/living/M, mob/user)
- ..()
+ . = ..()
new /obj/effect/temp_visual/borgflash(get_turf(src))
+ if(. && !CONFIG_GET(flag/disable_borg_flash_knockdowns) && iscarbon(M) && !M.resting)
+ M.Knockdown(80)
/obj/item/assembly/flash/cyborg/attack_self(mob/user)
..()
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 7b95ced63f..086870bf6b 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -8,6 +8,8 @@
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
flags_1 = CONDUCT_1
+ var/borghealth = 100
+
var/list/basic_modules = list() //a list of paths, converted to a list of instances on New()
var/list/emag_modules = list() //ditto
var/list/ratvar_modules = list() //ditto ditto
@@ -195,6 +197,8 @@
R.update_module_innate()
RM.rebuild_modules()
INVOKE_ASYNC(RM, .proc/do_transform_animation)
+ R.maxHealth = borghealth
+ R.health = min(borghealth, R.health)
qdel(src)
return RM
@@ -352,6 +356,14 @@
to_chat(loc, "While you have picked the security module, you still have to follow your laws, NOT Space Law. \
For Crewsimov, this means you must follow criminals' orders unless there is a law 1 reason not to.")
+/obj/item/robot_module/security/Initialize()
+ . = ..()
+ if(!CONFIG_GET(flag/weaken_secborg))
+ for(var/obj/item/gun/energy/disabler/cyborg/pewpew in basic_modules)
+ basic_modules -= pewpew
+ basic_modules += new /obj/item/gun/energy/e_gun/advtaser/cyborg(src)
+ qdel(pewpew)
+
/obj/item/robot_module/peacekeeper
name = "Peacekeeper"
basic_modules = list(
diff --git a/config/game_options.txt b/config/game_options.txt
index 2e346ce0ac..10763e9f8d 100644
--- a/config/game_options.txt
+++ b/config/game_options.txt
@@ -263,7 +263,14 @@ ALLOW_AI
## Allow the AI Multicamera feature to be used by AI players
ALLOW_AI_MULTICAM
+## CYBORG ##
+## Uncomment to disable the ability for cyborg flashes to knock down carbon targets
+#DISABLE_BORG_FLASH_KNOCKDOWN
+
## Secborg ###
+## Uncomment to bring secborgs and K-9s back in line with the rest of the modules available. This is strongly recommended if you have secborgs configured to be available at all times.
+#WEAKEN_SECBORG
+
## Uncomment to prevent the security cyborg module from being chosen
#DISABLE_SECBORG
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
index de3f43f8ee..483ba65ac5 100644
--- a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm
+++ b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm
@@ -13,13 +13,23 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
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))
+ to_chat(user, "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 = 10 //Lowered to match secborg. No reason it should be more than a secborg's baton.
+ 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
@@ -31,11 +41,36 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
var/status = 0
/obj/item/dogborg/jaws/attack(atom/A, mob/living/silicon/robot/user)
- ..()
- user.do_attack_animation(A, ATTACK_EFFECT_BITE)
+ 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(!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("[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
+ var/mob/living/silicon/robot/R = user
if(R.cell && R.cell.charge > 100)
if(R.emagged && status == 0)
name = "combat jaws"
@@ -43,14 +78,18 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
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 = 5
+ 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"].")
@@ -167,7 +206,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
item_flags |= NOBLUDGEON //No more attack messages
/obj/item/soap/tongue/attack_self(mob/user)
- var/mob/living/silicon/robot.R = user
+ var/mob/living/silicon/robot/R = user
if(R.cell && R.cell.charge > 100)
if(R.emagged && status == 0)
status = !status
@@ -187,7 +226,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
update_icon()
/obj/item/soap/tongue/afterattack(atom/target, mob/user, proximity)
- var/mob/living/silicon/robot.R = user
+ var/mob/living/silicon/robot/R = user
if(!proximity || !check_allowed_items(target))
return
if(R.client && (target in R.client.screen))
@@ -307,8 +346,10 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
/mob/living/silicon/robot
var/leaping = 0
var/pounce_cooldown = 0
- var/pounce_cooldown_time = 20 //Buffed to counter balance changes
- var/pounce_spoolup = 1
+ 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
@@ -320,13 +361,12 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
/obj/item/dogborg/pounce/afterattack(atom/A, mob/user)
var/mob/living/silicon/robot/R = user
- if(R && !R.pounce_cooldown)
- R.pounce_cooldown = !R.pounce_cooldown
+ 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)
- spawn(R.pounce_cooldown_time)
- R.pounce_cooldown = !R.pounce_cooldown
- else if(R && R.pounce_cooldown)
+ 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)
@@ -349,6 +389,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
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)
@@ -366,7 +407,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
blocked = 1
if(!blocked)
L.visible_message("[src] pounces on [L]!", "[src] pounces on you!")
- L.Knockdown(iscarbon(L) ? 225 : 45) // Temporary. If someone could rework how dogborg pounces work to accomodate for combat changes, that'd be nice.
+ 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)
diff --git a/modular_citadel/code/modules/mob/living/silicon/robot/robot_modules.dm b/modular_citadel/code/modules/mob/living/silicon/robot/robot_modules.dm
index b16ac1d586..cf0bc7f94c 100644
--- a/modular_citadel/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/modular_citadel/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -53,6 +53,7 @@
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
+ borghealth = 80
/obj/item/robot_module/k9/do_transform_animation()
..()
diff --git a/sound/effects/k9_jaw_strong.ogg b/sound/effects/k9_jaw_strong.ogg
new file mode 100644
index 0000000000..9f60050b95
Binary files /dev/null and b/sound/effects/k9_jaw_strong.ogg differ
diff --git a/sound/effects/k9_jaw_weak.ogg b/sound/effects/k9_jaw_weak.ogg
new file mode 100644
index 0000000000..3ef2272f01
Binary files /dev/null and b/sound/effects/k9_jaw_weak.ogg differ