diff --git a/code/datums/beepsky_fashion.dm b/code/datums/beepsky_fashion.dm new file mode 100644 index 0000000000..1156822c93 --- /dev/null +++ b/code/datums/beepsky_fashion.dm @@ -0,0 +1,221 @@ +//similar to dog_fashion, but for beepsky, who has far more refined fashion tastes +/datum/beepsky_fashion + var/name //not setting the name and desc makes them go to the default + var/desc + + var/icon_file = 'icons/mob/secbot_accessories.dmi' //we sell secbots and secbot accessories + var/obj_icon_state + var/obj_alpha + var/obj_color + + var/list/stun_sounds //sound that replaces the stun attack when set + var/ignore_sound = FALSE //whether to ignore sounds entirely or not + + //emotes (don't set them if you want the default value) + var/death_emote //what is said when beepsky dies + var/capture_one //what is said when cuffing someone + var/capture_two //what is said when cuffing someone, directly to the person being cuffed + var/infraction //the level of threat detected + var/taunt // beepsky pointing at a criminal + var/attack_one //text when attacking criminal + var/attack_two //text when attacking criminal, but directly to the criminal + var/patrol_emote //engaging patrol text + var/patrol_fail_emote //failing to engage patrol text + var/list/arrest_texts //first is for not-cuffing, second is for cuffing + var/arrest_emote //text stating that you're cuffing some criminal C with a threat of level X in location Y + + //for reference, the following words are replaced when processed before speech: + //LOCATION = the location passed, if any (this is only used by arrest_emote) + //CRIMINAL = the name of the criminal (this is used by everything but patrol_emote and infraction) + //BOT = the name of the bot (this can be used on any of the emotes) + //THREAT_LEVEL = the level of the threat detected (can be used on arrest_emote and infraction) + +/datum/beepsky_fashion/proc/get_overlay(var/dir) + if(icon_file && obj_icon_state) + var/image/beepsky_overlay = image(icon_file, obj_icon_state, dir = dir) + beepsky_overlay.alpha = obj_alpha + beepsky_overlay.color = obj_color + return beepsky_overlay + +/datum/beepsky_fashion/proc/stun_attack(mob/living/carbon/C) //fired when beepsky does a stun attack with the fashion worn, for sounds/overlays/etc + return + +//actual fashions from here on out +/datum/beepsky_fashion/wizard + obj_icon_state = "wizard" + name = "Archmage Beepsky" + desc = "A secbot stolen from the wizard federation." + death_emote = "BOT casts EI NATH on themselves!" + capture_one = "BOT is casting cable ties on CRIMINAL!" + capture_two = "BOT is casting cable ties on you!" + infraction = "Magical disturbance of magnitude THREAT_LEVEL detected!" + taunt = "BOT points his staff towards CRIMINAL!" + attack_one = "BOT casts magic missile on CRIMINAL!" + attack_two = "BOT casts magic missile on you!" + patrol_emote = "Beginning search for magical disturbances." + patrol_fail_emote = "Failure to find magical disturbances. Recallibrating." + arrest_emote = "ARREST_TYPE level THREAT_LEVEL magical practitioner CRIMINAL in LOCATION." + stun_sounds = list('sound/magic/lightningbolt.ogg', + 'sound/magic/fireball.ogg', + 'sound/weapons/zapbang.ogg', + 'sound/magic/knock.ogg', + 'sound/magic/fleshtostone.ogg', + 'sound/effects/magic.ogg', + 'sound/magic/disintegrate.ogg') + +/datum/beepsky_fashion/cowboy + obj_icon_state = "cowboy" + name = "Sheriff Beepsky" + desc = "The sheriff of this here station." + capture_one = "BOT is tying CRIMINAL up!" + capture_two = "BOT is tying you up!" + infraction = "Outlaws with a bounty of THREAT_LEVEL000 space dollars detected!" + taunt = "BOT aims his revolver towards CRIMINAL!" + attack_one = "BOT unloads his revolver onto CRIMINAL!" + attack_two = "BOT unloads his revolver onto you!" + patrol_emote = "Engaging bounty hunting protocols." + patrol_fail_emote = "Unable to find any bounties due to error. Rebooting." + arrest_emote = "ARREST_TYPE outlaw CRIMINAL with a bounty of THREAT_LEVEL000 in LOCATION." + stun_sounds = list('sound/weapons/Gunshot.ogg', + 'sound/weapons/Gunshot2.ogg', + 'sound/weapons/Gunshot3.ogg', + 'sound/weapons/Gunshot4.ogg') + +/datum/beepsky_fashion/chef + obj_icon_state = "chef" + name = "Chef Beepsky" + desc = "Cooking up the finest foods the station has ever seen." + death_emote = "Mamma-mia!" + infraction = "Grade THREAT_LEVEL prosciutto detected!" + taunt = "BOT glares at CRIMINAL." + attack_one = "BOT CQCs CRIMINAL!" + attack_two = "BOT CQCs you!" + patrol_emote = "Beginning search for the bad prosciutto." + patrol_fail_emote = "All prosciutto is stale. Rebooting." + arrest_texts = list("Frying", "Grilling") //any good secoff knows the difference + arrest_emote = "ARREST_TYPE grade THREAT_LEVEL prosciutto CRIMINAL in LOCATION." + stun_sounds = list('sound/weapons/cqchit1.ogg', + 'sound/weapons/cqchit2.ogg') + +/datum/beepsky_fashion/cat + obj_icon_state = "cat" + name = "OwOfficer Bweepskwee" + desc = "A beepsky unit with cat ears. Catgirl science has gone too far." + death_emote = "Nya!" + capture_one = "BOT is tying CRIMINAL up!!" + capture_two = "BOT is tying you up!" + infraction = "Wevel THREAT_LEVEL infwactwion awert!!!" + taunt = "BOT points at CRIMINAL and nyas!" + attack_one = "BOT shoves CRIMINAL onto a table!" + attack_two = "BOT shoves you onto a table!" + patrol_emote = "Enwgagwing patwol mwodies.." + patrol_fail_emote = "Unawbwle two stwawt patwollies. Nya." + arrest_texts = list("Dwetwaining", "Awwesting") + arrest_emote = "ARREST_TYPE wevel THREAT_LEVEL scwumbwag CRIMINAL in LOCATION. Nya." + ignore_sound = TRUE //we instead make the stunned person fire the nya emote + +/datum/beepsky_fashion/cat/stun_attack(var/mob/living/carbon/C) //makes a fake table under you on hit, makes cat people nya when hit + if(iscatperson(C)) + C.emote("nya") + var/turf/target_turf = get_turf(C) + if(target_turf) //slams you on a fake table + playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 50, 1) + var/obj/effect/overlay_holder = new(target_turf) + overlay_holder.name = "Catboy Table" + overlay_holder.desc = "Where bad catboys go." + var/image/table_overlay = image('icons/obj/smooth_structures/table.dmi', "table") + overlay_holder.add_overlay(table_overlay) + QDEL_IN(overlay_holder, 10) + +/datum/beepsky_fashion/cake //nothing else. it's just beepsky. with a cake on his head. + obj_icon_state = "cake" + name = "Cakesky" + desc = "It's a secbot, wearing a cake on his head!" + +/datum/beepsky_fashion/captain + obj_icon_state = "captain" + name = "Captainsky" + desc = "The real captain of this station." + capture_one = "BOT is lecturing CRIMINAL on why he is the captain!" + capture_two = "BOT is lecturing you on why he is the captain!" + infraction = "Level THREAT_LEVEL greytider detected." + attack_one = "BOT beats CRIMINAL with the chain of command!" + attack_two = "BOT beats you with the chain of command!" + patrol_emote = "Uselessness protocols engaged." + patrol_fail_emote = "Unit has been found as useless. Rebooting." + arrest_texts = list("Demoting", "Firing") + arrest_emote = "ARREST_TYPE level THREAT_LEVEL lesser crewmember CRIMINAL in LOCATION." + stun_sounds = list('sound/weapons/chainhit.ogg') + +/datum/beepsky_fashion/king + obj_icon_state = "king" + name = "King Beepsky" + desc = "He who has ascended to bare the right of king, sits atop the throne." + capture_one = "BOT is calling the guards onto CRIMINAL!" + capture_two = "BOT is calling the guards onto you!" + infraction = "Treason of level THREAT_LEVEL detected!" + attack_one = "BOT strikes CRIMINAL with his kingly authority!" + attack_two = "BOT strikes you with his kingly authority!" + patrol_emote = "Searching for peasants to beat up." + patrol_fail_emote = "Peasants are using dark magic. Recallibrating." + arrest_texts = list("Knighting", "Executing") + arrest_emote = "ARREST_TYPE level THREAT_LEVEL peasant CRIMINAL in LOCATION." + stun_sounds = list('sound/weapons/punch1.ogg', + 'sound/weapons/punch2.ogg', + 'sound/weapons/punch3.ogg', + 'sound/weapons/punch4.ogg') + +/datum/beepsky_fashion/pirate + obj_icon_state = "pirate" + name = "Beepsbeard the Pirate" + desc = "Sailor of the seven seas, all sea-faring bots fear the one known as Beepsbeard." + capture_one = "BOT is making CRIMINAL walk the plank!" + capture_two = "BOT is making you walk the plank!" + infraction = "Enemy vessel spotted with threat level THREAT_LEVEL!" + attack_one = "BOT strikes CRIMINAL with his cutlass!" + attack_two = "BOT strikes you with his cutlass!" + patrol_emote = "Searching for enemy vessels to board." + patrol_fail_emote = "No way to engage enemy vessels. Rebooting." + arrest_texts = list("Boarding", "Sinking") + arrest_emote = "ARREST_TYPE level THREAT_LEVEL vessel CRIMINAL in LOCATION." + stun_sounds = list('sound/weapons/bladeslice.ogg') + +/datum/beepsky_fashion/engineer + obj_icon_state = "engineer" + name = "Chief Engineer Beepsky" + desc = "He fixes criminals with a wrench to the face." + capture_one = "BOT is tying CRIMINAL up!" + capture_two = "BOT is tying you up!" + infraction = "Structural integrity issue spotted with threat level THREAT_LEVEL" + attack_one = "BOT strikes CRIMINAL with his wrench!" + attack_two = "BOT strikes you with his wrench!" + arrest_texts = list("Fixing", "Repairing") + arrest_emote = "ARREST_TYPE level THREAT_LEVEL structural issue in LOCATION" + stun_sounds = list('sound/weapons/genhit.ogg') + +/datum/beepsky_fashion/tophat + obj_icon_state = "tophat" + name = "Fancy Beepsky" + desc = "It's a secbot, wearing a top hat! How fancy." + +/datum/beepsky_fashion/fedora + obj_icon_state = "fedora" + name = "Fedorasky" + desc = "It's a secbot, wearing a fedora!" + +/datum/beepsky_fashion/sombrero + obj_icon_state = "sombrero" + name = "Sombrerosky" + desc = "A secbot wearing a sombrero. Truly, a hombre to all." + +/datum/beepsky_fashion/santa + obj_icon_state = "santa" + name = "Saint Beepsky" + desc = "Have you been a level 7 infraction this holiday season?" + capture_one = "BOT is tying CRIMINAL up with fairy lights!" + capture_two = "BOT is tying you up with fairy lights!" + infraction = "Level THREAT_LEVEL threat to holiday cheer spotted!" + attack_one = "BOT crushes CRIMINAL with their holiday spirit!" + attack_two = "BOT crushes you with their holiday spirit!" + arrest_emote = "ARREST_TYPE level THREAT_LEVEL threat to holiday cheer in LOCATION" + diff --git a/code/datums/dog_fashion.dm b/code/datums/dog_fashion.dm index 744f57c391..2e80feac67 100644 --- a/code/datums/dog_fashion.dm +++ b/code/datums/dog_fashion.dm @@ -38,7 +38,6 @@ corgI.color = obj_color return corgI - /datum/dog_fashion/head icon_file = 'icons/mob/corgi_head.dmi' @@ -53,7 +52,6 @@ name = "Sous chef REAL_NAME" desc = "Your food will be taste-tested. All of it." - /datum/dog_fashion/head/captain name = "Captain REAL_NAME" desc = "Probably better than the last captain." diff --git a/code/modules/clothing/head/_head.dm b/code/modules/clothing/head/_head.dm index 9682787de5..dc07d5e050 100644 --- a/code/modules/clothing/head/_head.dm +++ b/code/modules/clothing/head/_head.dm @@ -8,6 +8,7 @@ var/blockTracking = 0 //For AI tracking var/can_toggle = null dynamic_hair_suffix = "+generic" + var/datum/beepsky_fashion/beepsky_fashion //the associated datum for applying this to a secbot /obj/item/clothing/head/Initialize() . = ..() diff --git a/code/modules/clothing/head/collectable.dm b/code/modules/clothing/head/collectable.dm index 314142d0cc..20cb7cc824 100644 --- a/code/modules/clothing/head/collectable.dm +++ b/code/modules/clothing/head/collectable.dm @@ -27,7 +27,9 @@ icon_state = "chef" item_state = "chef" dynamic_hair_suffix = "" + dog_fashion = /datum/dog_fashion/head/chef + beepsky_fashion = /datum/beepsky_fashion/chef /obj/item/clothing/head/collectable/paper name = "collectable paper hat" @@ -42,6 +44,8 @@ icon_state = "tophat" item_state = "that" + beepsky_fashion = /datum/beepsky_fashion/tophat + /obj/item/clothing/head/collectable/captain name = "collectable captain's hat" desc = "A collectable hat that'll make you look just like a real comdom!" @@ -49,6 +53,7 @@ item_state = "caphat" dog_fashion = /datum/dog_fashion/head/captain + beepsky_fashion = /datum/beepsky_fashion/captain /obj/item/clothing/head/collectable/police name = "collectable police officer's hat" @@ -91,6 +96,7 @@ item_state = "pirate" dog_fashion = /datum/dog_fashion/head/pirate + beepsky_fashion = /datum/beepsky_fashion/pirate /obj/item/clothing/head/collectable/kitty name = "collectable kitty ears" @@ -100,6 +106,7 @@ dynamic_hair_suffix = "" dog_fashion = /datum/dog_fashion/head/kitty + beepsky_fashion = /datum/beepsky_fashion/cat /obj/item/clothing/head/collectable/rabbitears name = "collectable rabbit ears" @@ -116,6 +123,7 @@ icon_state = "wizard" dog_fashion = /datum/dog_fashion/head/blue_wizard + beepsky_fashion = /datum/beepsky_fashion/wizard /obj/item/clothing/head/collectable/hardhat name = "collectable hard hat" diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index 80d0b7c8a8..12a4a43ca7 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -15,6 +15,7 @@ dynamic_hair_suffix = "+generic" dog_fashion = /datum/dog_fashion/head + beepsky_fashion = /datum/beepsky_fashion/engineer /obj/item/clothing/head/hardhat/ComponentInitialize() diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index 638a0c2f23..5af694ea1b 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -13,7 +13,9 @@ strip_delay = 10 equip_delay_other = 10 dynamic_hair_suffix = "" + dog_fashion = /datum/dog_fashion/head/chef + beepsky_fashion = /datum/beepsky_fashion/chef /obj/item/clothing/head/chefhat/suicide_act(mob/user) user.visible_message("[user] is donning [src]! It looks like [user.p_theyre()] trying to become a chef.") @@ -33,7 +35,9 @@ flags_inv = 0 armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) strip_delay = 60 + dog_fashion = /datum/dog_fashion/head/captain + beepsky_fashion = /datum/beepsky_fashion/captain //Captain: This is no longer space-worthy /obj/item/clothing/head/caphat/parade diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index 416d0d2383..72d0f68c18 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -20,9 +20,11 @@ desc = "It's an amish looking hat." icon_state = "tophat" item_state = "that" - dog_fashion = /datum/dog_fashion/head throwforce = 1 + dog_fashion = /datum/dog_fashion/head + beepsky_fashion = /datum/beepsky_fashion/tophat + /obj/item/clothing/head/canada name = "striped red tophat" desc = "It smells like fresh donut holes. / Il sent comme des trous de beignets frais." @@ -126,7 +128,9 @@ desc = "Yarr." icon_state = "pirate" item_state = "pirate" + dog_fashion = /datum/dog_fashion/head/pirate + beepsky_fashion = /datum/beepsky_fashion/pirate /obj/item/clothing/head/pirate/captain name = "pirate captain hat" @@ -189,6 +193,8 @@ desc = "A really cool hat if you're a mobster. A really lame hat if you're not." pocket_storage_component_path = /datum/component/storage/concrete/pockets/small + beepsky_fashion = /datum/beepsky_fashion/fedora + /obj/item/clothing/head/fedora/suicide_act(mob/user) if(user.gender == FEMALE) return 0 @@ -205,7 +211,9 @@ item_state = "sombrero" desc = "You can practically taste the fiesta." flags_inv = HIDEHAIR + dog_fashion = /datum/dog_fashion/head/sombrero + beepsky_fashion = /datum/beepsky_fashion/sombrero /obj/item/clothing/head/sombrero/green name = "green sombrero" @@ -213,6 +221,7 @@ item_state = "greensombrero" desc = "As elegant as a dancing cactus." flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS + dog_fashion = null /obj/item/clothing/head/sombrero/shamebrero @@ -220,6 +229,7 @@ icon_state = "shamebrero" item_state = "shamebrero" desc = "Once it's on, it never comes off." + dog_fashion = null /obj/item/clothing/head/sombrero/shamebrero/Initialize() @@ -248,7 +258,9 @@ item_state = "that" cold_protection = HEAD min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT + dog_fashion = /datum/dog_fashion/head/santa + beepsky_fashion = /datum/beepsky_fashion/santa /obj/item/clothing/head/jester name = "jester hat" @@ -286,6 +298,8 @@ resistance_flags = FIRE_PROOF dynamic_hair_suffix = "" + beepsky_fashion = /datum/beepsky_fashion/king + /obj/item/clothing/head/crown/fancy name = "magnificent crown" desc = "A crown worn by only the highest emperors of the land space." @@ -391,7 +405,9 @@ name = "cowboy hat" desc = "A standard brown cowboy hat, yeehaw." icon_state = "cowboyhat" - item_state= "cowboyhat" + item_state = "cowboyhat" + + beepsky_fashion = /datum/beepsky_fashion/cowboy /obj/item/clothing/head/cowboyhat/black name = "black cowboy hat" diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 54561c8a24..1d9c3dd325 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -50,6 +50,8 @@ flags_cover = HEADCOVERSEYES heat = 1000 + beepsky_fashion = /datum/beepsky_fashion/cake + /obj/item/clothing/head/hardhat/cakehat/process() var/turf/location = src.loc if(ishuman(location)) @@ -131,6 +133,7 @@ dynamic_hair_suffix = "" dog_fashion = /datum/dog_fashion/head/kitty + beepsky_fashion = /datum/beepsky_fashion/cat /obj/item/clothing/head/kitty/equipped(mob/living/carbon/human/user, slot) if(ishuman(user) && slot == SLOT_HEAD) diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm index 7a5a031e79..94f7ee179a 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -8,6 +8,7 @@ var/modifies_speech = FALSE var/mask_adjusted = 0 var/adjusted_flags = null + var/datum/beepsky_fashion/beepsky_fashion //the associated datum for applying this to a secbot /obj/item/clothing/mask/attack_self(mob/user) if(CHECK_BITFIELD(clothing_flags, VOICEBOX_TOGGLABLE)) diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index 94273d2c73..977e916f87 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -9,6 +9,7 @@ equip_delay_other = 50 resistance_flags = FIRE_PROOF | ACID_PROOF dog_fashion = /datum/dog_fashion/head/blue_wizard + beepsky_fashion = /datum/beepsky_fashion/wizard var/magic_flags = SPELL_WIZARD_HAT /obj/item/clothing/head/wizard/ComponentInitialize() diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index a347b04e50..3ad19deeac 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -102,6 +102,10 @@ var/can_salute = TRUE var/salute_delay = 60 SECONDS + //emotes/speech stuff + var/patrol_emote = "Engaging patrol mode." + var/patrol_fail_emote = "Unable to start patrol." + /mob/living/simple_animal/bot/proc/get_mode() if(client) //Player bots do not have modes, thus the override. Also an easy way for PDA users/AI to know when a bot is a player. if(paicard) @@ -612,7 +616,7 @@ Pass a positive integer as an argument to override a bot's default speed. if(tries >= BOT_STEP_MAX_RETRIES) //Bot is trapped, so stop trying to patrol. auto_patrol = 0 tries = 0 - speak("Unable to start patrol.") + speak(patrol_fail_emote) return @@ -628,7 +632,7 @@ Pass a positive integer as an argument to override a bot's default speed. return mode = BOT_PATROL else // no patrol target, so need a new one - speak("Engaging patrol mode.") + speak(patrol_emote) find_patrol_target() tries++ return diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index cfff3eb751..9d45b96831 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -33,6 +33,20 @@ var/check_records = TRUE //Does it check security records? var/arrest_type = FALSE //If true, don't handcuff + var/obj/item/clothing/head/bot_accessory + var/datum/beepsky_fashion/stored_fashion + + //emotes (BOT is replaced with bot name, CRIMINAL with criminal name, THREAT_LEVEL with threat level) + var/death_emote = "BOT blows apart!" + var/capture_one = "BOT is trying to put zipties on CRIMINAL!" + var/capture_two = "BOT is trying to put zipties on you!" + var/infraction = "Level THREAT_LEVEL infraction alert!" + var/taunt = "BOT points at CRIMINAL!" + var/attack_one = "BOT has stunned CRIMINAL!" + var/attack_two = "BOT has stunned you!" + var/list/arrest_texts = list("Detaining", "Arresting") + var/arrest_emote = "ARREST_TYPE level THREAT_LEVEL scumbag CRIMINAL in LOCATION." + /mob/living/simple_animal/bot/secbot/beepsky name = "Officer Beep O'sky" desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey." @@ -49,6 +63,103 @@ resize = 0.8 update_transform() +/mob/living/simple_animal/bot/secbot/proc/process_emote(var/emote_type, var/atom/criminal, var/threat, var/arrest = -1, var/location) + var/emote = "The continuity of space itself collapses around [src]. You should probably report that to someone higher up." + switch(emote_type) + if("DEATH") + emote = death_emote + if("CAPTURE_ONE") + emote = capture_one + if("CAPTURE_TWO") + emote = capture_two + if("INFRACTION") + emote = infraction + if("TAUNT") + emote = taunt + if("ATTACK_ONE") + emote = attack_one + if("ATTACK_TWO") + emote = attack_two + if("ARREST") + emote = arrest_emote + + //now replace pieces of the text with the information we have + if(emote_type != "TAUNT" && emote_type != "ARREST") + emote = replacetext(emote, "BOT", name) + else + emote = replacetext(emote, "BOT", "[name]") //needs to be bold if its a taunt or an arrest text + if(criminal) + emote = replacetext(emote, "CRIMINAL", criminal.name) + if(threat) + emote = replacetext(emote, "THREAT_LEVEL", threat) + if(arrest > -1) + emote = replacetext(emote, "ARREST_TYPE", arrest_texts[arrest + 1]) + if(location) + emote = replacetext(emote, "LOCATION", location) + return emote + +/mob/living/simple_animal/bot/secbot/proc/apply_fashion(var/datum/beepsky_fashion/fashion) + stored_fashion = new fashion + if(stored_fashion.name) + name = stored_fashion.name + + if(stored_fashion.desc) + desc = stored_fashion.desc + + if(stored_fashion.death_emote) + death_emote = stored_fashion.death_emote + + if(stored_fashion.capture_one) + capture_one = stored_fashion.capture_one + + if(stored_fashion.capture_two) + capture_two = stored_fashion.capture_two + + if(stored_fashion.infraction) + infraction = stored_fashion.infraction + + if(stored_fashion.taunt) + taunt = stored_fashion.taunt + + if(stored_fashion.attack_one) + attack_one = stored_fashion.attack_one + + if(stored_fashion.attack_two) + attack_two = stored_fashion.attack_two + + if(stored_fashion.patrol_emote) + patrol_emote = stored_fashion.patrol_emote + + if(stored_fashion.patrol_fail_emote) + patrol_fail_emote = stored_fashion.patrol_fail_emote + + if(stored_fashion.arrest_texts) + arrest_texts = stored_fashion.arrest_texts + + if(stored_fashion.arrest_emote) + arrest_emote = stored_fashion.arrest_emote + + regenerate_icons() + +/mob/living/simple_animal/bot/secbot/proc/reset_fashion() + bot_accessory.forceMove(get_turf(src)) + //reset all emotes/sounds and name/desc + name = initial(name) + desc = initial(desc) + death_emote = initial(death_emote) + capture_one = initial(capture_one) + capture_two = initial(capture_two) + infraction = initial(infraction) + taunt = initial(taunt) + attack_one = initial(attack_one) + attack_two = initial(attack_two) + arrest_texts = initial(arrest_texts) + arrest_emote = initial(arrest_emote) + patrol_emote = initial(patrol_emote) + arrest_texts = initial(arrest_texts) + arrest_emote = initial(arrest_emote) + bot_accessory = null + regenerate_icons() /mob/living/simple_animal/bot/secbot/beepsky/explode() var/atom/Tsec = drop_location() @@ -178,6 +289,11 @@ Auto Patrol: []"}, retaliate(H) if(special_retaliate_after_attack(H)) return + if(H.a_intent == INTENT_HELP && bot_accessory) + + to_chat(H, "You knock [bot_accessory] off of [src]'s head!") + reset_fashion() + return return ..() @@ -185,11 +301,48 @@ Auto Patrol: []"}, ..() if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM) // Any intent but harm will heal, so we shouldn't get angry. return + if(istype(W, /obj/item/clothing/head)) + attempt_place_on_head(user, W) + return if(!istype(W, /obj/item/screwdriver) && (W.force) && (!target) && (W.damtype != STAMINA) ) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass. retaliate(user) if(special_retaliate_after_attack(user)) return +/mob/living/simple_animal/bot/secbot/proc/attempt_place_on_head(mob/user, obj/item/clothing/head/H) + if(user && !user.temporarilyRemoveItemFromInventory(H)) + to_chat(user, "\The [H] is stuck to your hand, you cannot put it on [src]'s head!") + return + if(bot_accessory) + to_chat("\[src] already has an accessory, and the laws of physics disallow him from wearing a second!") + return + + if(H.beepsky_fashion) + to_chat(user, "You set [H] on [src].") + bot_accessory = H + H.forceMove(src) + apply_fashion(H.beepsky_fashion) + else + to_chat(user, "You set [H] on [src]'s head, but it falls off!") + H.forceMove(drop_location()) + +/mob/living/simple_animal/bot/secbot/regenerate_icons() + ..() + if(bot_accessory) + if(!stored_fashion) + stored_fashion = new bot_accessory.beepsky_fashion + if(!stored_fashion.obj_icon_state) + stored_fashion.obj_icon_state = bot_accessory.icon_state + if(!stored_fashion.obj_alpha) + stored_fashion.obj_alpha = bot_accessory.alpha + if(!stored_fashion.obj_color) + stored_fashion.obj_color = bot_accessory.color + add_overlay(stored_fashion.get_overlay()) + else + if(stored_fashion) + cut_overlay(stored_fashion.get_overlay()) + stored_fashion = null + /mob/living/simple_animal/bot/secbot/emag_act(mob/user) . = ..() if(emagged == 2) @@ -233,8 +386,8 @@ Auto Patrol: []"}, /mob/living/simple_animal/bot/secbot/proc/cuff(mob/living/carbon/C) mode = BOT_ARREST playsound(src, 'sound/weapons/cablecuff.ogg', 30, TRUE, -2) - C.visible_message("[src] is trying to put zipties on [C]!",\ - "[src] is trying to put zipties on you!") + C.visible_message("[process_emote("CAPTURE_ONE", C)]",\ + "[process_emote("CAPTURE_TWO", C)]") if(do_after(src, 60, FALSE, C)) attempt_handcuff(C) @@ -249,16 +402,22 @@ Auto Patrol: []"}, /mob/living/simple_animal/bot/secbot/proc/stun_attack(mob/living/carbon/C) var/judgement_criteria = judgement_criteria() - playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1) icon_state = "secbot-c" addtimer(CALLBACK(src, /atom/.proc/update_icon), 2) var/threat = 5 if(ishuman(C)) + if(stored_fashion) + stored_fashion.stun_attack(C) + if(stored_fashion.stun_sounds && !stored_fashion.ignore_sound) + playsound(src, pick(stored_fashion.stun_sounds), 50, TRUE, -1) + else + playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1) C.stuttering = 5 C.DefaultCombatKnockdown(100) var/mob/living/carbon/human/H = C threat = H.assess_threat(judgement_criteria, weaponcheck=CALLBACK(src, .proc/check_for_weapons)) else + playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1) C.DefaultCombatKnockdown(100) C.stuttering = 5 threat = C.assess_threat(judgement_criteria, weaponcheck=CALLBACK(src, .proc/check_for_weapons)) @@ -266,9 +425,9 @@ Auto Patrol: []"}, log_combat(src,C,"stunned") if(declare_arrests) var/area/location = get_area(src) - speak("[arrest_type ? "Detaining" : "Arresting"] level [threat] scumbag [C] in [location].", radio_channel) - C.visible_message("[src] has stunned [C]!",\ - "[src] has stunned you!") + speak(process_emote("ARREST", C, threat, arrest_type, location), radio_channel) + C.visible_message("[process_emote("ATTACK_ONE", C)]",\ + "[process_emote("ATTACK_TWO", C)]") /mob/living/simple_animal/bot/secbot/handle_automated_action() if(!..()) @@ -355,7 +514,6 @@ Auto Patrol: []"}, look_for_perp() bot_patrol() - return /mob/living/simple_animal/bot/secbot/proc/back_to_idle() @@ -391,9 +549,9 @@ Auto Patrol: []"}, else if(threatlevel >= 4) target = C oldtarget_name = C.name - speak("Level [threatlevel] infraction alert!") + speak(process_emote("INFRACTION", target, threatlevel)) playsound(loc, pick('sound/voice/beepsky/criminal.ogg', 'sound/voice/beepsky/justice.ogg', 'sound/voice/beepsky/freeze.ogg'), 50, FALSE) - visible_message("[src] points at [C.name]!") + visible_message(process_emote("TAUNT", target, threatlevel)) mode = BOT_HUNT INVOKE_ASYNC(src, .proc/handle_automated_action) break @@ -408,7 +566,7 @@ Auto Patrol: []"}, /mob/living/simple_animal/bot/secbot/explode() walk_to(src,0) - visible_message("[src] blows apart!") + visible_message("[process_emote("DEATH")]") var/atom/Tsec = drop_location() var/obj/item/bot_assembly/secbot/Sa = new (Tsec) diff --git a/icons/mob/secbot_accessories.dmi b/icons/mob/secbot_accessories.dmi new file mode 100644 index 0000000000..b6c7bad6fa Binary files /dev/null and b/icons/mob/secbot_accessories.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 2a7156f043..6b3bf6eb88 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -353,6 +353,7 @@ #include "code\datums\ai_laws.dm" #include "code\datums\armor.dm" #include "code\datums\beam.dm" +#include "code\datums\beepsky_fashion.dm" #include "code\datums\browser.dm" #include "code\datums\callback.dm" #include "code\datums\chatmessage.dm"