From 33c0d1d5e2591517d2bb124011a86bc4e6a9f02f Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 8 Dec 2019 04:43:59 -0500 Subject: [PATCH 1/2] Bots --- .../mob/living/simple_animal/bot/bot.dm | 12 +++ .../mob/living/simple_animal/bot/cleanbot.dm | 89 ++++++++++++++++++- 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 68995702..b1095b12 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -94,6 +94,10 @@ var/ignorelistcleanuptimer = 1 // This ticks up every automated action, at 300 we clean the ignore list var/robot_arm = /obj/item/bodypart/r_arm/robot + var/commissioned = FALSE // Will other (noncommissioned) bots salute this bot? + var/can_salute = TRUE + var/salute_delay = 60 SECONDS + hud_possible = list(DIAG_STAT_HUD, DIAG_BOT_HUD, DIAG_HUD, DIAG_PATH_HUD = HUD_LIST_LIST) //Diagnostic HUD views /mob/living/simple_animal/bot/proc/get_mode() @@ -244,6 +248,14 @@ if(!on || client) return + if(!commissioned && can_salute) + for(var/mob/living/simple_animal/bot/B in get_hearers_in_view(5, get_turf(src))) + if(B.commissioned) + visible_message("[src] performs an elaborate salute for [B]!") + can_salute = FALSE + addtimer(VARSET_CALLBACK(src, can_salute, TRUE), salute_delay) + break + switch(mode) //High-priority overrides are processed first. Bots can do nothing else while under direct command. if(BOT_RESPONDING) //Called by the AI. call_mode() diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm index e09eb138..27ac57a8 100644 --- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm +++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm @@ -14,7 +14,7 @@ model = "Cleanbot" bot_core_type = /obj/machinery/bot_core/cleanbot window_id = "autoclean" - window_name = "Automatic Station Cleaner v1.2" + window_name = "Automatic Station Cleaner v1.4" pass_flags = PASSMOB path_image_color = "#993299" @@ -32,6 +32,61 @@ var/next_dest var/next_dest_loc + var/obj/item/weapon + var/weapon_orig_force = 0 + + var/list/stolen_valor + + var/static/list/officers = list("Captain", "Head of Personnel", "Head of Security") + var/static/list/command = list("Captain" = "Cpt.","Head of Personnel" = "Lt.") + var/static/list/security = list("Head of Security" = "Maj.", "Warden" = "Sgt.", "Detective" = "Det.", "Security Officer" = "Officer") + var/static/list/engineering = list("Chief Engineer" = "Chief Engineer", "Station Engineer" = "Engineer", "Atmospherics Technician" = "Technician") + var/static/list/medical = list("Chief Medical Officer" = "C.M.O.", "Medical Doctor" = "M.D.", "Chemist" = "Pharm.D.") + var/static/list/research = list("Research Director" = "Ph.D.", "Roboticist" = "M.S.", "Scientist" = "B.S.") + var/static/list/legal = list("Lawyer" = "Esq.") + + var/list/prefixes + var/list/suffixes + + +/mob/living/simple_animal/bot/cleanbot/proc/deputize(obj/item/W, mob/user) + if(in_range(src, user)) + to_chat(user, "You attach \the [W] to \the [src].") + user.transferItemToLoc(W, src) + weapon = W + weapon_orig_force = weapon.force + weapon.force = weapon.force / 2 + icon_state = "cleanbot[on]" + add_overlay(image(icon=weapon.lefthand_file,icon_state=weapon.item_state)) + +/mob/living/simple_animal/bot/cleanbot/proc/update_titles() + var/working_title = "" + + for(var/pref in prefixes) + for(var/title in pref) + if(title in stolen_valor) + working_title += pref[title] + " " + if(title in officers) + commissioned = TRUE + break + + working_title += initial(name) + + for(var/suf in suffixes) + for(var/title in suf) + if(title in stolen_valor) + working_title += " " + suf[title] + break + + name = working_title + +/mob/living/simple_animal/bot/cleanbot/examine(mob/user) + . = ..() + if(weapon) + . += " Is that \a [weapon] taped to it...?" + + + /mob/living/simple_animal/bot/cleanbot/Initialize() . = ..() get_targets() @@ -40,6 +95,17 @@ var/datum/job/janitor/J = new/datum/job/janitor access_card.access += J.get_access() prev_access = access_card.access + stolen_valor = list() + + prefixes = list(command, security, engineering) + suffixes = list(research, medical, legal) + +/mob/living/simple_animal/bot/cleanbot/Destroy() + if(weapon) + var/atom/Tsec = drop_location() + weapon.force = weapon_orig_force + drop_part(weapon, Tsec) + return ..() /mob/living/simple_animal/bot/cleanbot/turn_on() ..() @@ -62,6 +128,23 @@ text_dehack = "[name]'s software has been reset!" text_dehack_fail = "[name] does not seem to respond to your repair code!" +/mob/living/simple_animal/bot/cleanbot/Crossed(atom/movable/AM) + . = ..() + + zone_selected = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + if(weapon && has_gravity() && ismob(AM)) + var/mob/living/carbon/C = AM + if(!istype(C)) + return + + weapon.attack(C, src) + C.Knockdown(20) + + if(!(C.job in stolen_valor)) + stolen_valor += C.job + update_titles() + return + /mob/living/simple_animal/bot/cleanbot/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/card/id)||istype(W, /obj/item/pda)) if(bot_core.allowed(user) && !open && !emagged) @@ -74,6 +157,10 @@ to_chat(user, "Please close the access panel before locking it.") else to_chat(user, "\The [src] doesn't seem to respect your authority.") + else if(istype(W, /obj/item/kitchen/knife) && user.a_intent != INTENT_HARM) + to_chat(user, "You start attaching the [W] to \the [src]...") + if(do_after(user, 40, target = src)) + deputize(W, user) else return ..() From cce634a063c042068b842c05481559e647aaf0d9 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 8 Dec 2019 20:16:11 -0500 Subject: [PATCH 2/2] Adds weapon force emag effect and graffit options to cleanbot --- .../mob/living/simple_animal/bot/cleanbot.dm | 72 +++++++++++-------- 1 file changed, 43 insertions(+), 29 deletions(-) diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm index 27ac57a8..bd53e824 100644 --- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm +++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm @@ -21,6 +21,7 @@ var/blood = 1 var/trash = 0 var/pests = 0 + var/drawn = 0 var/list/target_types var/obj/effect/decal/cleanable/target @@ -34,6 +35,7 @@ var/obj/item/weapon var/weapon_orig_force = 0 + var/chosen_name var/list/stolen_valor @@ -55,8 +57,8 @@ user.transferItemToLoc(W, src) weapon = W weapon_orig_force = weapon.force - weapon.force = weapon.force / 2 - icon_state = "cleanbot[on]" + if(!emagged) + weapon.force = weapon.force / 2 add_overlay(image(icon=weapon.lefthand_file,icon_state=weapon.item_state)) /mob/living/simple_animal/bot/cleanbot/proc/update_titles() @@ -70,7 +72,7 @@ commissioned = TRUE break - working_title += initial(name) + working_title += chosen_name for(var/suf in suffixes) for(var/title in suf) @@ -85,10 +87,10 @@ if(weapon) . += " Is that \a [weapon] taped to it...?" - - /mob/living/simple_animal/bot/cleanbot/Initialize() . = ..() + + chosen_name = name get_targets() icon_state = "cleanbot[on]" @@ -119,6 +121,8 @@ /mob/living/simple_animal/bot/cleanbot/bot_reset() ..() + if(weapon && emagged == 2) + weapon.force = weapon_orig_force ignore_list = list() //Allows the bot to clean targets it previously ignored due to being unreachable. target = null oldloc = null @@ -137,13 +141,12 @@ if(!istype(C)) return - weapon.attack(C, src) - C.Knockdown(20) - if(!(C.job in stolen_valor)) stolen_valor += C.job update_titles() - return + + weapon.attack(C, src) + C.Knockdown(20) /mob/living/simple_animal/bot/cleanbot/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/card/id)||istype(W, /obj/item/pda)) @@ -158,15 +161,18 @@ else to_chat(user, "\The [src] doesn't seem to respect your authority.") else if(istype(W, /obj/item/kitchen/knife) && user.a_intent != INTENT_HARM) - to_chat(user, "You start attaching the [W] to \the [src]...") - if(do_after(user, 40, target = src)) + to_chat(user, "You start attaching \the [W] to \the [src]...") + if(do_after(user, 25, target = src)) deputize(W, user) else return ..() /mob/living/simple_animal/bot/cleanbot/emag_act(mob/user) ..() + if(emagged == 2) + if(weapon) + weapon.force = weapon_orig_force if(user) to_chat(user, "[src] buzzes and beeps.") @@ -219,6 +225,9 @@ if(!target && trash) //Then for trash. target = scan(/obj/item/trash) + if(!target && trash) //Search for dead mices. + target = scan(/obj/item/reagent_containers/food/snacks/deadmouse) + if(!target && auto_patrol) //Search for cleanables it can see. if(mode == BOT_IDLE || mode == BOT_START_PATROL) start_patrol() @@ -264,7 +273,6 @@ /obj/effect/decal/cleanable/oil, /obj/effect/decal/cleanable/vomit, /obj/effect/decal/cleanable/robot_debris, - /obj/effect/decal/cleanable/crayon, /obj/effect/decal/cleanable/molten_object, /obj/effect/decal/cleanable/tomato_smudge, /obj/effect/decal/cleanable/egg_smudge, @@ -286,33 +294,37 @@ target_types += /mob/living/simple_animal/cockroach target_types += /mob/living/simple_animal/mouse + if(drawn) + target_types += /obj/effect/decal/cleanable/crayon + if(trash) target_types += /obj/item/trash + target_types += /obj/item/reagent_containers/food/snacks/deadmouse target_types = typecacheof(target_types) /mob/living/simple_animal/bot/cleanbot/UnarmedAttack(atom/A) - if(istype(A, /obj/effect/decal/cleanable)) - anchored = TRUE + if(is_cleanable(A)) icon_state = "cleanbot-c" - visible_message("[src] begins to clean up [A].") mode = BOT_CLEANING - spawn(50) - if(mode == BOT_CLEANING) - if(A && isturf(A.loc)) - var/atom/movable/AM = A - if(istype(AM, /obj/effect/decal/cleanable)) - for(var/obj/effect/decal/cleanable/C in A.loc) - qdel(C) - anchored = FALSE - target = null - mode = BOT_IDLE - icon_state = "cleanbot[on]" + var/turf/T = get_turf(A) + if(do_after(src, 1, target = T)) + SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM) + visible_message("[src] cleans \the [T].") + for(var/atom/dirtything in T) + if(is_cleanable(dirtything)) + qdel(dirtything) + + target = null + + mode = BOT_IDLE + icon_state = "cleanbot[on]" else if(istype(A, /obj/item) || istype(A, /obj/effect/decal/remains)) visible_message("[src] sprays hydrofluoric acid at [A]!") - playsound(src, 'sound/effects/spray2.ogg', 50, 1, -6) + playsound(src, 'sound/effects/spray2.ogg', 50, TRUE, -6) A.acid_act(75, 10) + target = null else if(istype(A, /mob/living/simple_animal/cockroach) || istype(A, /mob/living/simple_animal/mouse)) var/mob/living/simple_animal/M = target if(!M.stat) @@ -332,7 +344,7 @@ "MY ONLY MISSION IS TO CLEANSE THE WORLD OF EVIL.", "EXTERMINATING PESTS.") say(phrase) victim.emote("scream") - playsound(src.loc, 'sound/effects/spray2.ogg', 50, 1, -6) + playsound(src.loc, 'sound/effects/spray2.ogg', 50, TRUE, -6) victim.acid_act(5, 100) else if(A == src) // Wets floors and spawns foam randomly if(prob(75)) @@ -364,7 +376,6 @@ /obj/machinery/bot_core/cleanbot req_one_access = list(ACCESS_JANITOR, ACCESS_ROBOTICS) - /mob/living/simple_animal/bot/cleanbot/get_controls(mob/user) var/dat dat += hack(user) @@ -376,6 +387,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"}) if(!locked || issilicon(user)|| IsAdminGhost(user)) dat += "
Clean Blood: [blood ? "Yes" : "No"]" dat += "
Clean Trash: [trash ? "Yes" : "No"]" + dat += "
Clean Graffiti: [drawn ? "Yes" : "No"]" dat += "
Exterminate Pests: [pests ? "Yes" : "No"]" dat += "

Patrol Station: [auto_patrol ? "Yes" : "No"]" return dat @@ -391,5 +403,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"}) pests = !pests if("trash") trash = !trash + if("drawn") + drawn = !drawn get_targets() update_controls()