diff --git a/code/__defines/radio.dm b/code/__defines/radio.dm
index 9224603bbc7..d634b6b23b1 100644
--- a/code/__defines/radio.dm
+++ b/code/__defines/radio.dm
@@ -9,6 +9,7 @@
#define AI_FREQ 1343
#define DTH_FREQ 1341
#define SYND_FREQ 1213
+#define NINJ_FREQ 1255
#define RAID_FREQ 1277
#define ENT_FREQ 1461 //entertainment frequency. This is not a diona exclusive frequency.
@@ -35,6 +36,7 @@ var/list/radiochannels = list(
"Response Team" = ERT_FREQ,
"Special Ops" = DTH_FREQ,
"Mercenary" = SYND_FREQ,
+ "Ninja" = NINJ_FREQ,
"Raider" = RAID_FREQ,
"Supply" = SUP_FREQ,
"Service" = SRV_FREQ,
@@ -60,12 +62,14 @@ var/list/CENT_FREQS_ASSOC = list(
// Antag channels, i.e. Syndicate
var/list/ANTAG_FREQS = list(
SYND_FREQ,
- RAID_FREQ
+ RAID_FREQ,
+ NINJ_FREQ
)
var/list/ANTAG_FREQS_ASSOC = list(
"[SYND_FREQ]" = TRUE,
- "[RAID_FREQ]" = TRUE
+ "[RAID_FREQ]" = TRUE,
+ "[NINJ_FREQ]" = TRUE
)
//Department channels, arranged lexically
diff --git a/code/controllers/subsystems/statistics.dm b/code/controllers/subsystems/statistics.dm
index 23c228dc05f..f37ee3cfb7e 100644
--- a/code/controllers/subsystems/statistics.dm
+++ b/code/controllers/subsystems/statistics.dm
@@ -18,6 +18,7 @@
var/list/msg_deathsquad = list()
var/list/msg_syndicate = list()
var/list/msg_raider = list()
+ var/list/msg_ninja = list()
var/list/msg_cargo = list()
var/list/msg_service = list()
diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm
index 653207b7e14..f86939bacef 100644
--- a/code/datums/outfits/outfit_admin.dm
+++ b/code/datums/outfits/outfit_admin.dm
@@ -224,6 +224,32 @@
/obj/item/weapon/implant/explosive
)
+/datum/outfit/admin/syndicate/ninja
+ name = "Infiltrator"
+
+ uniform = /obj/item/clothing/under/syndicate/ninja
+ back = /obj/item/weapon/rig/light/ninja
+ belt = /obj/item/weapon/storage/belt/ninja
+ shoes = /obj/item/clothing/shoes/swat/ert
+ gloves = /obj/item/clothing/ring/ninja
+ mask = /obj/item/clothing/mask/balaclava
+ l_ear = /obj/item/device/radio/headset/ninja
+ glasses = /obj/item/clothing/glasses/sunglasses/sechud/tactical
+ id = /obj/item/weapon/card/id/syndicate
+ l_pocket = /obj/item/device/ninja_uplink
+ r_pocket = null
+ accessory = /obj/item/clothing/accessory/storage/black_pouches
+
+ backpack_contents = list()
+
+ belt_contents = list(
+ /obj/item/device/flashlight/maglight = 1,
+ /obj/item/weapon/crowbar = 1,
+ /obj/item/weapon/screwdriver = 1,
+ /obj/item/device/paicard = 1
+ )
+
+ id_access = "Syndicate Agent"
/datum/outfit/admin/nt
name = "NanoTrasen Representative"
@@ -607,4 +633,4 @@
return "Visitor"
/datum/outfit/admin/random/visitor/get_id_rank()
- return "Visitor"
\ No newline at end of file
+ return "Visitor"
diff --git a/code/game/antagonist/antagonist_create.dm b/code/game/antagonist/antagonist_create.dm
index f1890cb1503..6babfe5bb68 100644
--- a/code/game/antagonist/antagonist_create.dm
+++ b/code/game/antagonist/antagonist_create.dm
@@ -45,6 +45,8 @@
var/obj/item/device/radio/R
switch(freq)
+ if(NINJ_FREQ)
+ R = new/obj/item/device/radio/headset/ninja(player)
if(SYND_FREQ)
R = new/obj/item/device/radio/headset/syndicate(player)
if(RAID_FREQ)
diff --git a/code/game/antagonist/outsider/ninja.dm b/code/game/antagonist/outsider/ninja.dm
index 03c981b3987..13ce0b96805 100644
--- a/code/game/antagonist/outsider/ninja.dm
+++ b/code/game/antagonist/outsider/ninja.dm
@@ -11,9 +11,9 @@ var/datum/antagonist/ninja/ninjas
flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_RANDSPAWN | ANTAG_VOTABLE | ANTAG_SET_APPEARANCE
antaghud_indicator = "hudninja"
- initial_spawn_req = 1
- initial_spawn_target = 1
- hard_cap = 1
+ initial_spawn_req = 2
+ initial_spawn_target = 2
+ hard_cap = 2
hard_cap_round = 3
id_type = /obj/item/weapon/card/id/syndicate
@@ -99,35 +99,20 @@ var/datum/antagonist/ninja/ninjas
player.name = H.name
/datum/antagonist/ninja/equip(var/mob/living/carbon/human/player)
-
if(!..())
return 0
- var/obj/item/device/radio/R = new /obj/item/device/radio/headset(player)
- player.equip_to_slot_or_del(R, slot_l_ear)
- player.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(player), slot_w_uniform)
- player.equip_to_slot_or_del(new /obj/item/device/flashlight(player), slot_belt)
- player.equip_to_slot_or_del(new /obj/item/device/ninja_uplink(player, player.mind), slot_l_store)
- create_id("Infiltrator", player)
-
- var/obj/item/weapon/rig/light/ninja/ninjasuit = new(get_turf(player))
- ninjasuit.seal_delay = 0
- player.put_in_hands(ninjasuit)
- player.equip_to_slot_or_del(ninjasuit,slot_back)
- if(ninjasuit)
- ninjasuit.toggle_seals(src,1)
- ninjasuit.seal_delay = initial(ninjasuit.seal_delay)
-
- if(istype(player.back,/obj/item/weapon/rig))
- var/obj/item/weapon/rig/rig = player.back
- if(rig.air_supply)
- player.internal = rig.air_supply
-
- spawn(10)
- if(player.internal)
- player.internals.icon_state = "internal1"
- else
- to_chat(player, "You forgot to turn on your internals! Quickly, toggle the valve!")
+ for (var/obj/item/I in player)
+ if (istype(I, /obj/item/weapon/implant))
+ continue
+ player.drop_from_inventory(I)
+ if(I.loc != player)
+ qdel(I)
+ player.preEquipOutfit(/datum/outfit/admin/syndicate/ninja, FALSE)
+ player.equipOutfit(/datum/outfit/admin/syndicate/ninja, FALSE)
+ player.force_update_limbs()
+ player.update_eyes()
+ player.regenerate_icons()
/datum/antagonist/ninja/proc/generate_ninja_directive(side)
var/directive = "[side=="face"?"[current_map.company_name]":"A criminal syndicate"] is your employer. "//Let them know which side they're on.
diff --git a/code/game/gamemodes/ninja/ninja.dm b/code/game/gamemodes/ninja/ninja.dm
index a3b37d657d2..0de04faab83 100644
--- a/code/game/gamemodes/ninja/ninja.dm
+++ b/code/game/gamemodes/ninja/ninja.dm
@@ -1,16 +1,16 @@
/datum/game_mode/ninja
- name = "ninja"
+ name = "ninjas"
round_description = "An agent of the Spider Clan is onboard the station!"
extended_round_description = "What was that?! Was that a person or did your eyes just play tricks on you? \
- You have no idea. That slim-suited, cryptic individual is an enigma to you and all of your knowledge. \
+ You have no idea. Those slim-suited, cryptic individuals are an enigma to you and all of your knowledge. \
Their purpose is unknown. Their mission is unknown. How they arrived to this secure and isolated \
- section of the galaxy, you don't know. What you do know is that there is a silent shadow-stalker piercing \
+ section of the galaxy, you don't know. What you do know is that there are silent shadow-stalkers piercing \
through the defenses of the station with technological capabilities eons ahead of your time. They can avoid \
the omniscience of the AI and rival the most hardened weapons your station is capable of. Tread lightly and \
- only hope this unknown assassin isn't here for you."
+ only hope these unknown assassins aren't here for you."
config_tag = "ninja"
- required_players = 2
- max_players = 15
- required_enemies = 1
- end_on_antag_death = 1
+ required_players = 10
+ max_players = 30
+ required_enemies = 2
+ end_on_antag_death = 0
antag_tags = list(MODE_NINJA)
diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm
index 59afb9b58f8..7a610ec7c97 100644
--- a/code/game/machinery/telecomms/broadcaster.dm
+++ b/code/game/machinery/telecomms/broadcaster.dm
@@ -380,6 +380,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
SSfeedback.msg_syndicate += blackbox_msg
if(RAID_FREQ)
SSfeedback.msg_raider += blackbox_msg
+ if(NINJ_FREQ)
+ SSfeedback.msg_ninja += blackbox_msg
if(SUP_FREQ)
SSfeedback.msg_cargo += blackbox_msg
if(SRV_FREQ)
@@ -566,6 +568,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
SSfeedback.msg_syndicate += blackbox_msg
if(RAID_FREQ)
SSfeedback.msg_raider += blackbox_msg
+ if(NINJ_FREQ)
+ SSfeedback.msg_ninja += blackbox_msg
if(SUP_FREQ)
SSfeedback.msg_cargo += blackbox_msg
if(SRV_FREQ)
diff --git a/code/game/objects/items/devices/hacktool.dm b/code/game/objects/items/devices/hacktool.dm
index 6b12c556ee6..2379c9a94f6 100644
--- a/code/game/objects/items/devices/hacktool.dm
+++ b/code/game/objects/items/devices/hacktool.dm
@@ -1,16 +1,22 @@
/obj/item/device/multitool/hacktool
var/is_hacking = 0
- var/max_known_targets
var/in_hack_mode = 0
+ var/list/current_hacks
var/list/known_targets
var/list/supported_types
var/datum/topic_state/default/must_hack/hack_state
+ var/hack_time = 30 SECONDS
+ var/max_known_targets = 7
+ var/silent = FALSE
+ var/multihack = FALSE
+ var/allow_movement = FALSE
+
/obj/item/device/multitool/hacktool/New()
..()
known_targets = list()
- max_known_targets = 5 + rand(1,3)
+ current_hacks = list()
supported_types = list(/obj/machinery/door/airlock)
hack_state = new(src)
@@ -26,7 +32,7 @@
/obj/item/device/multitool/hacktool/attackby(var/obj/item/W, var/mob/user)
if(W.isscrewdriver())
in_hack_mode = !in_hack_mode
- playsound(src.loc, W.usesound, 50, 1)
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
else
..()
@@ -39,13 +45,17 @@
if(!attempt_hack(user, A))
return 0
- A.ui_interact(user, state = hack_state)
+ if(A.Adjacent(user))
+ A.ui_interact(user, state = hack_state)
return 1
/obj/item/device/multitool/hacktool/proc/attempt_hack(var/mob/user, var/atom/target)
- if(is_hacking)
+ if(is_hacking && !multihack)
to_chat(user, "You are already hacking!")
return 0
+ if(target in current_hacks)
+ to_chat(user, span("warning", "You are already hacking this door!"))
+ return 0
if(!is_type_in_list(target, supported_types))
to_chat(user, "\icon[src] Unable to hack this target!")
return 0
@@ -56,13 +66,17 @@
to_chat(user, "You begin hacking \the [target]...")
is_hacking = 1
+ current_hacks += target
+
// On average hackin takes ~30 seconds. Fairly small random span to avoid people simply aborting and trying again
- var/hack_result = do_after(user, (20 SECONDS + rand(0, 10 SECONDS) + rand(0, 10 SECONDS)))
+ var/hack_result = do_after(user, hack_time + rand(-5,5), use_user_turf = (allow_movement ? -1 : FALSE))
is_hacking = 0
+ current_hacks -= target
if(hack_result && in_hack_mode)
to_chat(user, "Your hacking attempt was succesful!")
- playsound(src.loc, 'sound/piano/A#6.ogg', 75)
+ if(!silent)
+ playsound(src.loc, 'sound/piano/A#6.ogg', 75)
else
to_chat(user, "Your hacking attempt failed!")
return 0
@@ -83,6 +97,39 @@
/obj/item/device/multitool/hacktool/proc/on_target_destroy(var/target)
known_targets -= target
+/obj/item/device/multitool/hacktool/rig //For ninjas; Credits to BurgerBB
+ hack_time = 50
+ max_known_targets = 10
+ in_hack_mode = TRUE
+ silent = TRUE
+ multihack = TRUE
+ allow_movement = TRUE
+ reach = 8
+ var/mob/living/creator
+
+/obj/item/device/multitool/hacktool/rig/Initialize()
+ . = ..()
+ START_PROCESSING(SSprocessing, src)
+
+/obj/item/device/multitool/hacktool/rig/Destroy()
+ STOP_PROCESSING(SSprocessing, src)
+ return ..()
+
+/obj/item/device/multitool/hacktool/rig/process()
+ if(!creator || loc != creator || (creator.l_hand != src && creator.r_hand != src))
+ // Tidy up a bit.
+ if(istype(loc,/mob/living))
+ var/mob/living/carbon/human/host = loc
+ if(istype(host))
+ for(var/obj/item/organ/external/organ in host.organs)
+ for(var/obj/item/O in organ.implants)
+ if(O == src)
+ organ.implants -= src
+ host.pinned -= src
+ host.embedded -= src
+ host.drop_from_inventory(src)
+ QDEL_IN(src, 1)
+
/datum/topic_state/default/must_hack
var/obj/item/device/multitool/hacktool/hacktool
@@ -97,4 +144,4 @@
/datum/topic_state/default/must_hack/can_use_topic(var/src_object, var/mob/user)
if(!hacktool || !hacktool.in_hack_mode || !(src_object in hacktool.known_targets))
return STATUS_CLOSE
- return ..()
+ return ..()
\ No newline at end of file
diff --git a/code/game/objects/items/devices/radio/encryptionkey.dm b/code/game/objects/items/devices/radio/encryptionkey.dm
index 4d0bf11e699..e0e885e7c27 100644
--- a/code/game/objects/items/devices/radio/encryptionkey.dm
+++ b/code/game/objects/items/devices/radio/encryptionkey.dm
@@ -27,6 +27,12 @@
origin_tech = list(TECH_ILLEGAL = 2)
syndie = 1
+/obj/item/device/encryptionkey/ninja
+ icon_state = "cypherkey"
+ channels = list("Ninja" = 1)
+ origin_tech = list(TECH_ILLEGAL = 3)
+ syndie = 1
+
/obj/item/device/encryptionkey/binary
icon_state = "cypherkey"
translate_binary = 1
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 8548a89656e..f73f16dd8a2 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -83,6 +83,11 @@
syndie = 1
ks1type = /obj/item/device/encryptionkey/raider
+/obj/item/device/radio/headset/ninja
+ origin_tech = list(TECH_ILLEGAL = 3)
+ syndie = 1
+ ks1type = /obj/item/device/encryptionkey/ninja
+
/obj/item/device/radio/headset/binary
origin_tech = list(TECH_ILLEGAL = 3)
ks1type = /obj/item/device/encryptionkey/binary
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index 2697459f84a..2337ca52d47 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -347,6 +347,45 @@
/obj/item/clothing/gloves/botanic_leather,
)
+/obj/item/weapon/storage/belt/ninja //credits to BurgerBB
+ name = "advanced combat belt"
+ desc = "A very robust belt that can hold various specialized gear such as swords, grenades, shurikens, and food rations."
+ icon_state = "securitybelt"
+ item_state = "security"
+ storage_slots = 9
+ max_w_class = 4
+ max_storage_space = 28
+
+ can_hold = list(
+ /obj/item/weapon/grenade,
+ /obj/item/weapon/handcuffs,
+ /obj/item/device/flash,
+ /obj/item/device/paicard,
+ /obj/item/clothing/glasses,
+ /obj/item/ammo_casing/shotgun,
+ /obj/item/ammo_magazine,
+ /obj/item/weapon/melee/baton,
+ /obj/item/device/flashlight,
+ /obj/item/device/pda,
+ /obj/item/device/radio/headset,
+ /obj/item/weapon/melee,
+ /obj/item/weapon/crowbar,
+ /obj/item/weapon/screwdriver,
+ /obj/item/weapon/shield/energy,
+ /obj/item/weapon/pinpointer,
+ /obj/item/weapon/plastique,
+ /obj/item/weapon/gun/projectile/pistol,
+ /obj/item/weapon/gun/energy/crossbow,
+ /obj/item/ammo_casing/a145,
+ /obj/item/device/radio/uplink,
+ /obj/item/weapon/card/emag,
+ /obj/item/device/multitool/hacktool,
+ /obj/item/weapon/reagent_containers,
+ /obj/item/stack/telecrystal,
+ /obj/item/weapon/material/sword,
+ /obj/item/weapon/material/star
+ )
+
/obj/item/weapon/storage/belt/fannypack
name = "leather fannypack"
desc = "A dorky fannypack for keeping small items in."
diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm
index 2263f9f7c6f..df97f7af736 100644
--- a/code/modules/clothing/gloves/miscellaneous.dm
+++ b/code/modules/clothing/gloves/miscellaneous.dm
@@ -41,6 +41,19 @@
heat_protection = HANDS
max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE
+/obj/item/clothing/ring/ninja
+ desc = "A pair of plain black infiltration gloves. Too thin to protect anything, but can fit underneath a hardsuit gauntlet."
+ name = "black slipgloves"
+ icon = 'icons/obj/clothing/gloves.dmi'
+ icon_state = "s-ninja"
+ item_state = "s-ninja"
+ siemens_coefficient = 0
+ permeability_coefficient = 0.05
+ undergloves = 1
+ cold_protection = HANDS
+ min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE
+ heat_protection = HANDS
+ max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE
/obj/item/clothing/gloves/latex
name = "latex gloves"
diff --git a/code/modules/clothing/spacesuits/rig/modules/ninja.dm b/code/modules/clothing/spacesuits/rig/modules/ninja.dm
index 45c3e263897..680c3fc330e 100644
--- a/code/modules/clothing/spacesuits/rig/modules/ninja.dm
+++ b/code/modules/clothing/spacesuits/rig/modules/ninja.dm
@@ -78,6 +78,7 @@
redundant = 1
usable = 1
selectable = 1
+ var/lastteleport
engage_string = "Emergency Leap"
@@ -106,13 +107,17 @@
/obj/item/rig_module/teleporter/engage(var/atom/target, var/notify_ai)
- if(!..()) return 0
+ if(!..()) return FALSE
var/mob/living/carbon/human/H = holder.wearer
+ if(lastteleport + (5 SECONDS) > world.time)
+ to_chat(H, span("warning", "The teleporter needs time to cool down!"))
+ return FALSE
+
if(!istype(H.loc, /turf))
to_chat(H, "You cannot teleport out of your current location.")
- return 0
+ return FALSE
var/turf/T
if(target)
@@ -122,19 +127,19 @@
if(!T || T.density)
to_chat(H, "You cannot teleport into solid walls.")
- return 0
+ return FALSE
if(T.z in current_map.admin_levels)
to_chat(H, "You cannot use your teleporter on this Z-level.")
- return 0
+ return FALSE
if(T.contains_dense_objects())
to_chat(H, "You cannot teleport to a location with solid objects.")
- return 0
+ return FALSE
if((T.z != H.z || get_dist(T, get_turf(H)) > world.view) && target)
to_chat(H, "You cannot teleport to such a distant object.")
- return 0
+ return FALSE
phase_out(H,get_turf(H))
do_teleport(H,T)
@@ -149,7 +154,8 @@
do_teleport(G.affecting,locate(T.x+rand(-1,1),T.y+rand(-1,1),T.z))
phase_in(G.affecting,get_turf(G.affecting))
- return 1
+ lastteleport = world.time
+ return TRUE
/obj/item/rig_module/fabricator/energy_net
@@ -264,7 +270,7 @@
interface_name = "emergency power generator"
interface_desc = "A high yield power generating device that takes a long time to recharge."
- var/generation_ammount = 1500
+ var/generation_ammount = 2500
category = MODULE_SPECIAL
@@ -280,7 +286,7 @@
playsound(H.loc, 'sound/effects/sparks2.ogg', 50, 1)
holder.cell.give(generation_ammount)
cooldown = 1
- addtimer(CALLBACK(src, /obj/item/rig_module/emergency_powergenerator/proc/reset_cooldown), 240)
+ addtimer(CALLBACK(src, /obj/item/rig_module/emergency_powergenerator/proc/reset_cooldown), 5 MINUTES)
/obj/item/rig_module/emergency_powergenerator/proc/reset_cooldown()
cooldown = 0
@@ -297,3 +303,64 @@
device_type = /obj/item/weapon/robot_emag
category = MODULE_SPECIAL
+
+/obj/item/rig_module/stealth_field/advanced //credits to Burger BB
+ name = "advanced active camouflage module"
+ desc = "A robust hardsuit-integrated stealth module. This model sports a significantly lower cooldown between uses as well as a reduced charge cost."
+ use_power_cost = 10
+ active_power_cost = 2
+ passive_power_cost = 0
+ module_cooldown = 10
+
+ category = MODULE_SPECIAL
+
+/obj/item/rig_module/device/door_hack //credits to BurgerBB
+ name = "advanced door hacking tool"
+ desc = "An advanced door hacking tool that sports a low power cost and incredibly quick door hacking time. The device also supports hacking several signals at once remotely, and the last 10 doors hacked can be instantly accessed."
+ use_power_cost = 10
+ module_cooldown = 5
+
+ usable = 0
+ selectable = 0
+ toggleable = 1
+
+ interface_name = "advanced door hacking tool"
+ interface_desc = "An advanced door hacking tool that sports a low power cost and incredibly quick door hacking time. The device also supports hacking several signals at once remotely, and the last 10 doors hacked can be instantly accessed."
+
+ category = MODULE_SPECIAL
+
+/obj/item/rig_module/device/door_hack/process()
+
+ if(holder && holder.wearer)
+ if(!(locate(/obj/item/device/multitool/hacktool/rig) in holder.wearer))
+ deactivate()
+ return 0
+
+ return ..()
+
+/obj/item/rig_module/device/door_hack/activate()
+
+ ..()
+
+ var/mob/living/M = holder.wearer
+
+ if(M.l_hand && M.r_hand)
+ to_chat(M, "Your hands are full.")
+ deactivate()
+ return
+
+ var/obj/item/device/multitool/hacktool/rig/hacktool = new(M)
+ hacktool.creator = M
+ M.put_in_hands(hacktool)
+
+/obj/item/rig_module/device/door_hack/deactivate()
+
+ ..()
+
+ var/mob/living/M = holder.wearer
+
+ if(!M)
+ return
+
+ for(var/obj/item/device/multitool/hacktool/rig/hacktool in M.contents)
+ qdel(hacktool)
\ No newline at end of file
diff --git a/code/modules/clothing/spacesuits/rig/suits/light.dm b/code/modules/clothing/spacesuits/rig/suits/light.dm
index 2a7d3a8f813..a767a9d1219 100644
--- a/code/modules/clothing/spacesuits/rig/suits/light.dm
+++ b/code/modules/clothing/spacesuits/rig/suits/light.dm
@@ -76,31 +76,40 @@
/obj/item/weapon/rig/light/ninja
name = "stealth suit control module"
suit_type = "stealth suit"
- desc = "A unique, vaccum-proof suit of nano-enhanced armor designed specifically for stealth operations."
+ desc = "A unique, vacuum-proof suit of nano-enhanced armor designed specifically for stealth operations."
icon_state = "ninja_rig"
- armor = list(melee = 50, bullet = 35, laser = 35, energy = 30, bomb = 25, bio = 100, rad = 30)
+ armor = list(melee = 50, bullet = 45, laser = 45, energy = 30, bomb = 35, bio = 100, rad = 100)
emp_protection = 40
slowdown = 0
species_restricted = list("Human","Tajara","Unathi", "Skrell", "Machine", "Vaurca")
+ helm_type = /obj/item/clothing/head/helmet/space/rig/light/ninja
chest_type = /obj/item/clothing/suit/space/rig/light/ninja
glove_type = /obj/item/clothing/gloves/rig/light/ninja
- boot_type = /obj/item/clothing/shoes/rig/light/ninja
+ boot_type = /obj/item/clothing/shoes/magboots/rig/light/ninja
req_access = list(access_syndicate)
initial_modules = list(
- /obj/item/rig_module/teleporter,
/obj/item/rig_module/vision,
/obj/item/rig_module/voice,
+ /obj/item/rig_module/teleporter,
+ /obj/item/rig_module/stealth_field,
+ /obj/item/rig_module/electrowarfare_suite,
/obj/item/rig_module/ai_container,
+ /obj/item/rig_module/device/door_hack,
/obj/item/rig_module/datajack,
+ /obj/item/rig_module/chem_dispenser/ninja,
/obj/item/rig_module/self_destruct,
- /obj/item/rig_module/actuators
+ /obj/item/rig_module/actuators/combat
)
allowed_module_types = MODULE_GENERAL | MODULE_LIGHT_COMBAT | MODULE_HEAVY_COMBAT | MODULE_SPECIAL | MODULE_MEDICAL | MODULE_UTILITY | MODULE_VAURCA
+/obj/item/clothing/head/helmet/space/rig/light/ninja
+ light_overlay = "helmet_light_dual_green"
+ light_color = "#3e7c3e"
+
/obj/item/weapon/rig/light/ninja/equipped
initial_modules = list(
/obj/item/rig_module/teleporter,
@@ -122,7 +131,7 @@
name = "insulated gloves"
siemens_coefficient = 0
-/obj/item/clothing/shoes/rig/light/ninja
+/obj/item/clothing/shoes/magboots/rig/light/ninja
silent = 1
/obj/item/clothing/suit/space/rig/light/ninja
@@ -223,4 +232,4 @@
/obj/item/rig_module/fabricator/energy_net,
/obj/item/rig_module/chem_dispenser/combat,
/obj/item/rig_module/mounted/xray
- )
\ No newline at end of file
+ )
diff --git a/code/modules/clothing/under/syndicate.dm b/code/modules/clothing/under/syndicate.dm
index 782c5e0f0e1..b20dad820ba 100644
--- a/code/modules/clothing/under/syndicate.dm
+++ b/code/modules/clothing/under/syndicate.dm
@@ -28,3 +28,10 @@
icon_state = "fulltracksuit"
item_state = "fulltracksuit"
contained_sprite = 1
+
+/obj/item/clothing/under/syndicate/ninja
+ name = "slipsuit"
+ desc = "A sleek, form-fitting undersuit designed to retain the wearer's mobility. It almost feels like you're wearing nothing at all."
+ icon_state = "ninja"
+ item_state = "ninja"
+ worn_state = "ninja"
\ No newline at end of file
diff --git a/html/changelogs/geeves_duoNinja.yml b/html/changelogs/geeves_duoNinja.yml
new file mode 100644
index 00000000000..848a16f79de
--- /dev/null
+++ b/html/changelogs/geeves_duoNinja.yml
@@ -0,0 +1,52 @@
+################################
+# Example Changelog File
+#
+# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
+#
+# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
+# When it is, any changes listed below will disappear.
+#
+# Valid Prefixes:
+# bugfix
+# wip (For works in progress)
+# tweak
+# soundadd
+# sounddel
+# rscadd (general adding of nice things)
+# rscdel (general deleting of nice things)
+# imageadd
+# imagedel
+# maptweak
+# spellcheck (typo fixes)
+# experiment
+# balance
+# admin
+# backend
+# security
+# refactor
+#################################
+
+# Your name.
+author: Geeves, with some code by BurgerBB
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
+# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - rscadd: "Added a ninja frequency to radios which ninjas spawn with to collaborate."
+ - tweak: "Two ninjas now spawn instead of just one."
+ - rscadd: "Gave the ninja better spawning gear, a syndicate uniform, a belt with some tools and a pAI card."
+ - tweak: "The ninja suit now has new lights, and its shoes are now magboots."
+ - rscadd: "Added a doorhack RIG module. Functions the same as the normal doorhack, but the user can move around after initiating the hack, as well as hack multiple airlocks at once."
+ - tweak: "Gave the ninja teleporter a 5 second cooldown between uses."
+ - rscadd: "Added new advanced combat belt, can hold various gear that a ninja would usually come across."
+ - tweak : "Buffed the ninja's RIG armour values slightly. Still requires feedback, if ninjas die too quickly, it will be buffed more."
+ - rscadd: "Added an additional toolbox, chair, suitcooling unit and ninja spawn point to the ninja shuttle on the centcomm level."
+ - rscadd: Gave the ninja a new uniform + gloves.
+ - tweak: "EMERGENCY power generator now generates 2500 units of power, with a cooldown of five minutes."
+ - wip: "Gnomes still evading capture. Report any occurences of gnomes and gnome activity to Aurora authorities."
diff --git a/icons/mob/hands.dmi b/icons/mob/hands.dmi
index d559cbf534d..ceb37c9d97d 100644
Binary files a/icons/mob/hands.dmi and b/icons/mob/hands.dmi differ
diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi
index 75a85365757..0b03cf93899 100644
Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ
diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi
index 2da123493e5..b7cb92b551b 100644
Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ
diff --git a/maps/aurora/aurora-1_centcomm.dmm b/maps/aurora/aurora-1_centcomm.dmm
index 3d170428f7b..0ce207de579 100644
--- a/maps/aurora/aurora-1_centcomm.dmm
+++ b/maps/aurora/aurora-1_centcomm.dmm
@@ -3788,6 +3788,7 @@
"aki" = (
/obj/structure/table/rack,
/obj/item/device/suit_cooling_unit/improved,
+/obj/item/device/suit_cooling_unit/improved,
/turf/simulated/shuttle/floor{
icon_state = "floor4"
},
@@ -22216,6 +22217,7 @@
/obj/item/weapon/storage/toolbox/syndicate,
/obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle,
/obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle,
+/obj/item/weapon/storage/toolbox/syndicate,
/turf/simulated/shuttle/floor{
icon_state = "floor4"
},
@@ -25376,6 +25378,19 @@
icon_state = "green"
},
/area/centcom/living)
+"wQa" = (
+/obj/effect/landmark{
+ name = "ninjastart"
+ },
+/obj/structure/bed/chair{
+ dir = 1
+ },
+/turf/simulated/shuttle/floor{
+ icon_state = "floor4"
+ },
+/area/syndicate_mothership{
+ name = "\improper Ninja Base"
+ })
"xhq" = (
/obj/machinery/computer/cryopod{
pixel_y = 32
@@ -65562,7 +65577,7 @@ ahn
ajU
aXO
akh
-akh
+wQa
akF
akh
akN