diff --git a/code/__defines/dcs/signals.dm b/code/__defines/dcs/signals.dm index b9ea35b8155..24a1c7aa5e5 100644 --- a/code/__defines/dcs/signals.dm +++ b/code/__defines/dcs/signals.dm @@ -292,6 +292,8 @@ ///from base of /obj/item/attack(): (mob/M, mob/user) #define COMSIG_MOB_ITEM_ATTACK "mob_item_attack" #define COMPONENT_ITEM_NO_ATTACK (1<<0) +///from the base of /mob/living/silicon/robot/ClickOn(): (var/atom/A, var/params) +#define COMSIG_ROBOT_ITEM_ATTACK "robot_item_attack" ///from base of /mob/living/proc/apply_damage(): (damage, damagetype, def_zone) #define COMSIG_MOB_APPLY_DAMGE "mob_apply_damage" ///from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters) diff --git a/code/__defines/dcs/signals/signals_mob/signals_mob_main.dm b/code/__defines/dcs/signals/signals_mob/signals_mob_main.dm index ae06f69a025..7ca76e4d5f1 100644 --- a/code/__defines/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__defines/dcs/signals/signals_mob/signals_mob_main.dm @@ -1,2 +1,12 @@ ///from base of /mob/verb/pointed: (atom/A) #define COMSIG_MOB_POINTED "mob_pointed" + +/// from /mob/living/proc/apply_damage(): (damage, damagetype, def_zone, blocked, soaked, sharp, edge, used_weapon, projectile) +/// allows you to add multiplicative damage modifiers to the damage mods argument to adjust incoming damage... UNUSED ATM +/// not sent if the apply damage call was forced +#define COMSIG_MOB_APPLY_DAMAGE_MODIFIERS "mob_apply_damage_modifiers" +/// from base of /mob/living/proc/apply_damage(): (damage, damagetype, def_zone, blocked, soaked, sharp, edge, used_weapon, projectile) +#define COMSIG_MOB_APPLY_DAMAGE "mob_apply_damage" +/// from /mob/living/proc/apply_damage(): (damage, damagetype, def_zone, blocked, soaked, sharp, edge, /obj/used_weapon, projectile) +/// works like above but after the damage is actually inflicted +#define COMSIG_MOB_AFTER_APPLY_DAMAGE "mob_after_apply_damage" diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm index 0ed0dd88a9d..64cfe2e59fe 100644 --- a/code/_helpers/global_lists.dm +++ b/code/_helpers/global_lists.dm @@ -1302,7 +1302,8 @@ GLOBAL_LIST_INIT(robot_modules, list( "Lost" = /obj/item/robot_module/robot/lost, "Protector" = /obj/item/robot_module/robot/syndicate/protector, "Mechanist" = /obj/item/robot_module/robot/syndicate/mechanist, - "Combat Medic" = /obj/item/robot_module/robot/syndicate/combat_medic + "Combat Medic" = /obj/item/robot_module/robot/syndicate/combat_medic, + "Ninja" = /obj/item/robot_module/robot/syndicate/ninja, )) diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm index 906b90096cb..fc44f108f97 100644 --- a/code/_onclick/cyborg.dm +++ b/code/_onclick/cyborg.dm @@ -90,7 +90,7 @@ // cyborgs are prohibited from using storage items so we can I think safely remove (A.loc && isturf(A.loc.loc)) if(isturf(A) || isturf(A.loc)) if(A.Adjacent(src) || (W && W.attack_can_reach(src, A, W.reach))) // see adjacent.dm, allows robots to use ranged melee weapons - + SEND_SIGNAL(src, COMSIG_ROBOT_ITEM_ATTACK, W, src, params) //This is we ATTEMPTED to attack someone. var/resolved = A.attackby(W, src, 1) if(!resolved && A && W) W.afterattack(A, src, 1, params) diff --git a/code/game/objects/items/devices/ai_detector.dm b/code/game/objects/items/devices/ai_detector.dm index c9b94ab2ba9..87def8a152b 100644 --- a/code/game/objects/items/devices/ai_detector.dm +++ b/code/game/objects/items/devices/ai_detector.dm @@ -12,6 +12,13 @@ var/range_warning = 14 // Will turn yellow if the AI's eye is near the holder. var/detect_state = PROXIMITY_NONE origin_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2, TECH_ILLEGAL = 2) + description_antag = "Functions as a normal multitool with one added benefit.
\ + This will change colors and make sounds (that only you can hear) during various events.
\ + BLUE: You are outside of camera range.
\ + GREEN: You are inside of camera range.
\ + RED: You are currently being watched by the AI.
\ + FLASHING RED AND ORANGE: You are currently being TRACKED by the AI.
\ + FLASHING ORANGE AND BLUE: The AI has attempted to track you but has failed to do so due to being outside camera range." /obj/item/multitool/ai_detector/Initialize(mapload) . = ..() diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 73a31b2ed1a..3433c456ec8 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -476,6 +476,7 @@ This function restores all organs. */ /mob/living/carbon/human/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/soaked = 0, var/sharp = FALSE, var/edge = FALSE, var/obj/used_weapon = null, var/projectile = FALSE) + SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMAGE, damage, damagetype, def_zone, blocked, soaked, sharp, edge, used_weapon, projectile) if(GLOB.Debug2) to_world_log("## DEBUG: human/apply_damage() was called on [src], with [damage] damage, an armor value of [blocked], and a soak value of [soaked].") var/obj/item/organ/external/organ = null @@ -601,4 +602,5 @@ This function restores all organs. // Will set our damageoverlay icon to the next level, which will then be set back to the normal level the next mob.Life(). updatehealth() BITSET(hud_updateflag, HEALTH_HUD) + SEND_SIGNAL(src, COMSIG_MOB_AFTER_APPLY_DAMAGE, damage, damagetype, def_zone, blocked, soaked, sharp, edge, used_weapon, projectile) return 1 diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 50e1dd16c7f..d4dfd1c483b 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -9,6 +9,7 @@ standard 0 if fail */ /mob/living/proc/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/soaked = 0, var/sharp = FALSE, var/edge = FALSE, var/obj/used_weapon = null, var/projectile = 0) + SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMAGE, damage, damagetype, def_zone, blocked, soaked, sharp, edge, used_weapon, projectile) if(GLOB.Debug2) to_world_log("## DEBUG: apply_damage() was called on [src], with [damage] damage, and an armor value of [blocked].") if(!damage || (blocked >= 100)) @@ -123,6 +124,7 @@ emp_act(4) flash_weak_pain() updatehealth() + SEND_SIGNAL(src, COMSIG_MOB_AFTER_APPLY_DAMAGE, damage, damagetype, def_zone, blocked, soaked, sharp, edge, used_weapon, projectile) return 1 diff --git a/code/modules/mob/living/silicon/robot/cloak.dm b/code/modules/mob/living/silicon/robot/cloak.dm new file mode 100644 index 00000000000..3548e3492d5 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/cloak.dm @@ -0,0 +1,187 @@ +//Personal shielding for the combat module. +/obj/item/borg/cloak + name = "personal cloaking" + desc = "A powerful experimental module that allows one to adjust their visiblity." + description_info = "Ctrl-Clicking on the cloak will turn it on or off.
\ + Clicking the cloak while selected will allow you to change the strength of the cloak." + icon = 'icons/obj/decals.dmi' + icon_state = "shock" + var/cloak_strength = 0.5 //Percent of visibility, 0 is visible, 1 is fully invisible + var/active = FALSE //If the shield is on +/obj/item/borg/cloak/Initialize(mapload) + . = ..() + START_PROCESSING(SSobj, src) + +/obj/item/borg/cloak/Destroy() + STOP_PROCESSING(SSobj, src) + . = ..() + +/obj/item/borg/cloak/attack_self(mob/user) + set_cloak_level(user) + +/obj/item/borg/cloak/CtrlClick(mob/user) + toggle_cloak(user) + return + +/obj/item/borg/cloak/process() + if(!active || !cloak_strength) //We are not active or cloak strength is set to 0 + return + if(!isliving(src.loc)) //It's not currently in our active modules. + active = FALSE + if(isrobot(loc.loc)) //The robot + var/mob/living/silicon/robot/R = src.loc.loc + update_cloak(R) + else if(isrobot(src.loc)) //We are in a robot. + var/mob/living/silicon/robot/R = src.loc + //MATH: CELLRATE = 0.002 CYBORG_POWER_USAGE_MULTIPLIER = 2 and power_use = amount * CYBORG_POWER_USAGE_MULTIPLIER... + //So 250W = 1 charge. Syndi battery has 25000 charge. + //Let's make it so that 20 charge is used per 2 seconds if we are 100% cloaked. We subtract 100 since that's the idle power used for a module being selected. + if(!R.cell_use_power((cloak_strength * 5000) - 100)) + active = FALSE + update_cloak(R) //Update the cloak strength on the robot. + return //We ran out of power. RIP. + +/obj/item/borg/cloak/proc/update_cloak(var/mob/living/silicon/robot/robot) + if(!robot || !isrobot(robot)) + return + if(active && cloak_strength) //We remove any cloaks they might have + robot.remove_modifiers_of_type(/datum/modifier/robot_cloak) + robot.add_modifier(/datum/modifier/robot_cloak) + else + robot.remove_modifiers_of_type(/datum/modifier/robot_cloak) + active = FALSE + +/obj/item/borg/cloak/verb/set_cloak_level() + set name = "Toggle Cloak Strength" + set category = "Object" + set src in range(0) + var/mob/living/silicon/robot/R = usr + set_cloaking_level(R) + +/obj/item/borg/cloak/proc/set_cloaking_level(mob/living/silicon/robot/R) + if(!isrobot(R)) //sod off + return + + var/N = tgui_input_number(R, "How obscured do you want to be? In %", "Cloak Level", cloak_strength*100, 100, 0) + if(!isnull(N) && N >= 0 && N <= 100) + cloak_strength = N/100 + to_chat(R, span_warning("You will now be [N]% obscured when the cloak is active.")) + update_cloak(R) + else if(!N) + return + else + to_chat(R, span_warning("Invalid cloak level. Must be between 0 and 100.")) + return + +/obj/item/borg/cloak/verb/activate_cloak() + set name = "Toggle Cloak" + set category = "Object" + set src in range(0) + var/mob/living/silicon/robot/R = usr + toggle_cloak(R) + +/obj/item/borg/cloak/proc/toggle_cloak(mob/living/silicon/robot/R) + if(!isrobot(R)) //sod off + return + + active = !active + to_chat(R, span_notice("You [active ? "re" : "de"]activate your personal cloaking device.")) + update_cloak(R) + +/datum/modifier/robot_cloak + name = "robotic stealth" + desc = "You are currently cloaked and harder to see!." + + on_created_text = span_warning("You become harder to see.") + on_expired_text = span_notice("You become fully visible once more.") + var/visibility + ///How many times we have been hit in a short succession. + var/times_hit = 0 //How many times we have been hit while cloaked. + ///How many hits it can sustain before the cloak drops + var/cloak_durability = 3 + ///When we were last hit. + var/last_hit_time = 0 + ///How slow we are to reset the hit counter. + var/hit_dissipation = 5 SECONDS //How long we wait before resetting the hit counter. + ///If our cloak is currently up or not + var/cloaked = TRUE + ///How much evasion we have when our cloak is up. + var/modified_evasion + + stacks = MODIFIER_STACK_FORBID + +/datum/modifier/robot_cloak/can_apply() + if(holder && isrobot(holder) && holder.stat != DEAD) + return TRUE + return FALSE + +/datum/modifier/robot_cloak/on_applied() + var/mob/living/silicon/robot/R = holder + var/obj/item/borg/cloak/cloak = locate() in R //Find the borg cloak module + var/cloak_strength = cloak.cloak_strength + visibility = 255 * (1 - cloak_strength) + modified_evasion = 60*cloak_strength + evasion = modified_evasion //60 at full strength, 30 at half strength. + animate(holder, alpha = visibility, time = 1 SECOND) + RegisterSignal(holder, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(damage_inflicted)) + RegisterSignal(holder, COMSIG_ROBOT_ITEM_ATTACK, PROC_REF(attacked_in_cloak)) + return + +/datum/modifier/robot_cloak/on_expire() + holder.alpha = initial(holder.alpha) + UnregisterSignal(holder, COMSIG_MOB_APPLY_DAMAGE) + UnregisterSignal(holder, COMSIG_ROBOT_ITEM_ATTACK) + remove_wibble(TRUE) + return + +/datum/modifier/robot_cloak/tick() + if(holder.stat == DEAD) + expire(silent = TRUE) + else if(times_hit && (world.time - last_hit_time) > hit_dissipation) //If we have been hit, but the time has passed, reset the hit counter. + if(!cloaked) + to_chat(holder, span_warning("Your cloak whirrs back to life!")) + reset_cloak() + + if(cloaked && !times_hit) //The !times_hit is here so it doesn't interfere with the animation. + animate(holder, alpha = visibility, time = 1 SECOND) + +/datum/modifier/robot_cloak/proc/damage_inflicted(mob/living/source, damage) + if(damage < 5) //weak, don't do anything. + return + times_hit++ + var/alpha_to_show = CLAMP((holder.alpha+(damage*10)), holder.alpha, 255) //The more damage we take, the more visible we become. + flick_cloak(alpha_to_show) + last_hit_time = world.time + if(damage >= 50 || times_hit >= cloak_durability) + to_chat(holder, span_warning("Your cloak buzzes and fails after sustaining too much damage!!")) + drop_cloak() + remove_wibble(TRUE) + return + +/datum/modifier/robot_cloak/proc/flick_cloak(alpha_to_show) + animate(holder, alpha = alpha_to_show, time = 0.1 SECONDS, loop = 0.5 SECONDS) + animate(alpha = visibility, time = 0.1 SECONDS) + apply_wibbly_filters(holder, 0.5 SECONDS) + addtimer(CALLBACK(src, PROC_REF(remove_wibble), 0.1 SECOND), 0.5 SECONDS, TIMER_DELETE_ME) //Calling a proc with no arguments + +/datum/modifier/robot_cloak/proc/attacked_in_cloak() + if(holder && !holder.get_filter("wibbly-[1]")) //We're not wibbled at the moment. + var/alpha_to_show = CLAMP((holder.alpha+(rand(50,200))), holder.alpha, 255) //Become more visible by a significant margin, randomly. + flick_cloak(alpha_to_show) + +/datum/modifier/robot_cloak/proc/remove_wibble(instant) + if(holder && holder.get_filter("wibbly-[1]")) //We just check for the first wibble. If it has one it has them all. + if(instant) + remove_wibbly_filters(holder) + else + remove_wibbly_filters(holder, 0.1 SECOND) + +/datum/modifier/robot_cloak/proc/drop_cloak() + holder.alpha = initial(holder.alpha) + cloaked = FALSE + evasion = 0 + +/datum/modifier/robot_cloak/proc/reset_cloak() + times_hit = 0 + cloaked = TRUE + evasion = modified_evasion diff --git a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm index b89e1fef719..0329c48e8a9 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm @@ -25,6 +25,7 @@ ..() src.modules += new /obj/item/pinpointer/shuttle/merc(src) src.modules += new /obj/item/melee/robotic/blade/syndicate(src) + src.modules += new /obj/item/multitool/ai_detector/cyborg(src) var/datum/matter_synth/cloth = new /datum/matter_synth/cloth(40000) synths += cloth @@ -166,3 +167,22 @@ S.desc = initial(S.desc) S.update_icon() ..() + +/obj/item/robot_module/robot/syndicate/ninja + name = "ninja robot module" + supported_upgrades = list(/obj/item/borg/upgrade/restricted/bellycapupgrade) + +/obj/item/robot_module/robot/syndicate/ninja/create_equipment(var/mob/living/silicon/robot/robot) + ..() + src.modules += new /obj/item/dogborg/sleeper/K9/syndie(src) + src.modules += new /obj/item/dogborg/pounce(src) + src.modules += new /obj/item/gripper/syndicate(src) + src.modules += new /obj/item/robotic_multibelt/syndicate(src) + src.modules += new /obj/item/robotic_multibelt/syndicate(src) + src.modules += new /obj/item/melee/robotic/blade/ninja(src) + src.modules += new /obj/item/borg/cloak(src) + //Removes the default sblade + var/obj/item/melee/robotic/blade/syndicate/sblade = locate() in src.modules + if(sblade) + src.modules -= sblade + qdel(sblade) diff --git a/code/modules/mob/living/silicon/robot/robot_simple_items.dm b/code/modules/mob/living/silicon/robot/robot_simple_items.dm index 6888de5db1b..7228531b677 100644 --- a/code/modules/mob/living/silicon/robot/robot_simple_items.dm +++ b/code/modules/mob/living/silicon/robot/robot_simple_items.dm @@ -184,6 +184,18 @@ icon_state = "toolkit_engiborg_multitool" toolspeed = 0.5 +/obj/item/multitool/ai_detector/cyborg + name = "AI detector multitool" + toolspeed = 0.5 + desc = "Allows you to see if you are being watched by the AI or within network range. Also works as a normal multitool." + description_info = "Functions as a normal multitool with one added benefit.
\ + This will change colors (and make sounds that only you can hear if in your active modules) during various events.
\ + BLUE: You are outside of camera range.
\ + GREEN: You are inside of camera range.
\ + RED: You are currently being watched by the AI.
\ + FLASHING RED AND ORANGE: You are currently being TRACKED by the AI.
\ + FLASHING ORANGE AND BLUE: The AI has attempted to track you but has failed to do so due to being outside camera range." + /obj/item/stack/cable_coil/cyborg name = "cable coil synthesizer" desc = "A device that makes cable." @@ -325,6 +337,18 @@ icon = 'icons/obj/tools_robot.dmi' icon_state = "sili_rolling_pin" +/obj/item/robotic_multibelt/syndicate + name = "Syndicate Robotic multitool" + desc = "An integrated toolbelt that holds various tools. This one comes with a multitool-hacktool." + cyborg_integrated_tools = list( + /obj/item/tool/screwdriver/cyborg = null, + /obj/item/tool/wrench/cyborg = null, + /obj/item/tool/crowbar/cyborg = null, + /obj/item/tool/wirecutters/cyborg = null, + /obj/item/multitool/hacktool = null, + /obj/item/weldingtool/electric/mounted/cyborg = null, + ) + //Admin proc to add new materials to their fabricator /mob/living/silicon/robot/proc/add_new_material(mat_to_add) //Allows us to add a new material to the borg's synth and then make their multibelt refresh. if(!module) @@ -952,6 +976,13 @@ can_hold = list(SHEET_GRIPPER) +/obj/item/gripper/syndicate + name = "syndicate gripper" + desc = "A simple grasping tool for off-the-books syndicate work." + icon_state = "gripper-sec" + + can_hold = list(BASIC_GRIPPER, SECURITY_GRIPPER, MINER_GRIPPER, PAPERWORK_GRIPPER, MEDICAL_GRIPPER, RESEARCH_GRIPPER, CIRCUIT_GRIPPER, SERVICE_GRIPPER, GRAVEYARD_GRIPPER, ORGAN_GRIPPER, ROBOTICS_ORGAN_GRIPPER, EXOSUIT_GRIPPER, SHEET_GRIPPER) + /* * Misc tools */ diff --git a/code/modules/mob/living/silicon/robot/sprites/gooborgs.dm b/code/modules/mob/living/silicon/robot/sprites/gooborgs.dm index 07b09257c30..14d468da273 100644 --- a/code/modules/mob/living/silicon/robot/sprites/gooborgs.dm +++ b/code/modules/mob/living/silicon/robot/sprites/gooborgs.dm @@ -202,7 +202,7 @@ vis_height = 64 //Exploration. -/datum/robot_sprite/dogborg/explo_gooborg +/datum/robot_sprite/dogborg/ninja_gooborg name = "Gooborg" sprite_icon_state = "base" //sprite_hud_icon_state = "syndicat" @@ -216,11 +216,13 @@ sprite_icon = 'icons/mob/robot/gooborgs/custom/gooborg_ninja.dmi' rest_sprite_options = list("Default", "Bellyup", "Sit") belly_capacity_list = list("sleeper" = 2, "throat" =2) - module_type = "Exploration" + sprite_flags = ROBOT_HAS_SPEED_SPRITE | ROBOT_HAS_SHIELD_SPRITE | ROBOT_HAS_BLADE_SPRITE //esword + module_type = "Ninja" + sprite_hud_icon_state = "malf" //malf!! icon_y = 64 vis_height = 64 -/datum/robot_sprite/dogborg/explo_gooborg/get_eyes_overlay(var/mob/living/silicon/robot/ourborg) +/datum/robot_sprite/dogborg/ninja_gooborg/get_eyes_overlay(var/mob/living/silicon/robot/ourborg) if(ourborg.has_active_type(/obj/item/borg/combat/mobility)) return else diff --git a/code/modules/mob/living/silicon/robot/sprites/syndicate.dm b/code/modules/mob/living/silicon/robot/sprites/syndicate.dm index c188fe73edc..5f4bce68a00 100644 --- a/code/modules/mob/living/silicon/robot/sprites/syndicate.dm +++ b/code/modules/mob/living/silicon/robot/sprites/syndicate.dm @@ -259,3 +259,73 @@ sprite_icon_state = "syndimediraptor" has_eye_light_sprites = TRUE rest_sprite_options = list("Default", "Bellyup") + + + +// Ninja models + +/datum/robot_sprite/dogborg/syndicate/ninja + module_type = "Ninja" + sprite_icon = 'icons/mob/robot/ninja.dmi' + sprite_hud_icon_state = "malf" + +/datum/robot_sprite/dogborg/tall/syndicate/ninja + module_type = "Ninja" + sprite_icon = 'icons/mob/robot/tallrobot/tallrobots.dmi' + sprite_hud_icon_state = "malf" + icon_x = 32 + pixel_x = 0 + +/datum/robot_sprite/dogborg/tall/syndicate/ninja/dullahan + name = "dullahan" + sprite_icon = 'icons/mob/robot/dullahan/v3/ninja.dmi' + sprite_icon_state = "dullahanninja" + has_eye_light_sprites = TRUE + has_vore_belly_sprites = TRUE + sprite_decals = list("decals") + rest_sprite_options = list("Default", "Sit") + pixel_x = -16 + icon_x = 64 + +/datum/robot_sprite/dogborg/tall/syndicate/ninja/mekaninja + name = "Meka" + sprite_icon = 'icons/mob/robot/tallrobot/tallrobots.dmi' + sprite_icon_state = "mekaninja" + has_eye_light_sprites = TRUE + has_vore_belly_sprites = TRUE + rest_sprite_options = list("Default", "Sit") + +/datum/robot_sprite/dogborg/tall/syndicate/ninja/fmekaninja + name = "Niko" + sprite_icon = 'icons/mob/robot/tallrobot/tallrobots.dmi' + sprite_icon_state = "fmekaninja" + has_eye_light_sprites = TRUE + has_vore_belly_sprites = TRUE + rest_sprite_options = list("Default", "Sit") + +/datum/robot_sprite/dogborg/tall/syndicate/ninja/mmekaninja + name = "Nika" + sprite_icon = 'icons/mob/robot/tallrobot/tallrobots.dmi' + sprite_icon_state = "mmekaninja" + has_eye_light_sprites = TRUE + has_vore_belly_sprites = TRUE + rest_sprite_options = list("Default", "Sit") + +/datum/robot_sprite/dogborg/tall/syndicate/ninja/mmekaninja + name = "Nika" + sprite_icon = 'icons/mob/robot/tallrobot/tallrobots.dmi' + sprite_icon_state = "mmekaninja" + has_eye_light_sprites = TRUE + has_vore_belly_sprites = TRUE + rest_sprite_options = list("Default", "Sit") + +/datum/robot_sprite/dogborg/tall/syndicate/ninja/dullataurninja + name = "Dullataur" + sprite_icon = 'icons/mob/robot/dullahan/dullataurs/dullataur.dmi' + sprite_icon_state = "dullataurninja" + has_eye_light_sprites = TRUE + has_vore_belly_sprites = FALSE + has_rest_sprites = TRUE + has_rest_eyes_sprites = TRUE + sprite_decals = list("breastplate", "breastplatehalo","swordhalo","tophalo") + rest_sprite_options = list("Default") diff --git a/code/modules/mob/living/silicon/robot/subtypes/syndicate.dm b/code/modules/mob/living/silicon/robot/subtypes/syndicate.dm index 15a8257a499..7f66815e2de 100644 --- a/code/modules/mob/living/silicon/robot/subtypes/syndicate.dm +++ b/code/modules/mob/living/silicon/robot/subtypes/syndicate.dm @@ -7,7 +7,7 @@ braintype = "Drone" idcard_type = /obj/item/card/id/syndicate icon_selected = FALSE - restrict_modules_to = list("Protector", "Mechanist", "Combat Medic") + restrict_modules_to = list("Protector", "Mechanist", "Combat Medic", "Ninja") ui_theme = "syndicate" /mob/living/silicon/robot/syndicate/init() @@ -52,5 +52,12 @@ restrict_modules_to = list("Combat Medic") updatename("Combat Medic") +/mob/living/silicon/robot/syndicate/ninja/init() + ..() + module = new /obj/item/robot_module/robot/syndicate/ninja(src) + modtype = "Ninja" + restrict_modules_to = list("Ninja") + updatename("Ninja") + /mob/living/silicon/robot/syndicate/speech_bubble_appearance() return "synthetic_evil" diff --git a/icons/mob/robot/dullahan/dullataurs/dullataur.dmi b/icons/mob/robot/dullahan/dullataurs/dullataur.dmi index 1978e705cec..2aaec141e79 100644 Binary files a/icons/mob/robot/dullahan/dullataurs/dullataur.dmi and b/icons/mob/robot/dullahan/dullataurs/dullataur.dmi differ diff --git a/icons/mob/robot/dullahan/v3/ninja.dmi b/icons/mob/robot/dullahan/v3/ninja.dmi index 72e27a2c3db..3420b8134f0 100644 Binary files a/icons/mob/robot/dullahan/v3/ninja.dmi and b/icons/mob/robot/dullahan/v3/ninja.dmi differ diff --git a/icons/mob/robot/gooborgs/custom/gooborg_ninja.dmi b/icons/mob/robot/gooborgs/custom/gooborg_ninja.dmi index 16479be64c9..9c395e19a1a 100644 Binary files a/icons/mob/robot/gooborgs/custom/gooborg_ninja.dmi and b/icons/mob/robot/gooborgs/custom/gooborg_ninja.dmi differ diff --git a/icons/mob/robot/ninja.dmi b/icons/mob/robot/ninja.dmi new file mode 100644 index 00000000000..67b2b122bb3 Binary files /dev/null and b/icons/mob/robot/ninja.dmi differ diff --git a/icons/mob/robot/ninja_tall.dmi b/icons/mob/robot/ninja_tall.dmi new file mode 100644 index 00000000000..67b2b122bb3 Binary files /dev/null and b/icons/mob/robot/ninja_tall.dmi differ diff --git a/vorestation.dme b/vorestation.dme index d41171179e7..4d56ca6d484 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -3300,6 +3300,7 @@ #include "code\modules\mob\living\silicon\pai\software.dm" #include "code\modules\mob\living\silicon\pai\software_modules.dm" #include "code\modules\mob\living\silicon\robot\analyzer.dm" +#include "code\modules\mob\living\silicon\robot\cloak.dm" #include "code\modules\mob\living\silicon\robot\component.dm" #include "code\modules\mob\living\silicon\robot\custom_sprites.dm" #include "code\modules\mob\living\silicon\robot\death.dm"