/mob/living/basic/mining_drone name = "\improper Nanotrasen minebot" desc = "The instructions printed on the side read: This is a small robot used to support miners, can be set to search and collect loose ore, or to help fend off wildlife." gender = NEUTER icon = 'icons/mob/silicon/aibots.dmi' icon_state = "mining_drone" icon_living = "mining_drone" basic_mob_flags = DEL_ON_DEATH status_flags = CANSTUN|CANKNOCKDOWN|CANPUSH mouse_opacity = MOUSE_OPACITY_ICON combat_mode = TRUE habitable_atmos = null minimum_survivable_temperature = 0 health = 125 maxHealth = 125 melee_damage_lower = 15 melee_damage_upper = 15 obj_damage = 10 attack_verb_continuous = "drills" attack_verb_simple = "drill" attack_sound = 'sound/items/weapons/circsawhit.ogg' sentience_type = SENTIENCE_MINEBOT speak_emote = list("states") mob_biotypes = MOB_ROBOTIC faction = list(FACTION_STATION, FACTION_NEUTRAL) death_message = "blows apart!" light_system = OVERLAY_LIGHT light_range = 6 // I want this to be a bit more dim, for vibes light_power = 0.6 light_color = "#ff9933" light_on = FALSE combat_mode = FALSE ai_controller = /datum/ai_controller/basic_controller/minebot damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, STAMINA = 0, OXY = 1) ///the gun we use to kill var/obj/item/gun/energy/recharge/kinetic_accelerator/minebot/stored_gun ///our normal overlay var/mutable_appearance/neutral_overlay ///our combat mode overlay var/mutable_appearance/combat_overlay ///our current color, if any var/selected_color ///the commands our owner can give us var/static/list/pet_commands = list( /datum/pet_command/idle/minebot, /datum/pet_command/move, /datum/pet_command/protect_owner/minebot, /datum/pet_command/minebot_ability/light, /datum/pet_command/minebot_ability/dump, /datum/pet_command/automate_mining, /datum/pet_command/free/minebot, /datum/pet_command/follow/start_active, /datum/pet_command/attack/minebot, ) ///possible colors the bot can have var/static/list/possible_colors= list( "Default" = null, //default color state "Blue" = "#70d5e7", "Red" = "#ee7fb9", "Green" = "#5fea94", ) /mob/living/basic/mining_drone/Initialize(mapload) . = ..() neutral_overlay = mutable_appearance(icon = 'icons/mob/silicon/aibots.dmi', icon_state = "mining_drone_grey") combat_overlay = mutable_appearance(icon = 'icons/mob/silicon/aibots.dmi', icon_state = "mining_drone_offense_grey") AddComponent(/datum/component/obeys_commands, pet_commands) AddElement(/datum/element/death_drops, /obj/effect/decal/cleanable/blood/gibs/robot_debris/old) add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE, TRAIT_MINING_AOE_IMMUNE), INNATE_TRAIT) AddElement(/datum/element/footstep, FOOTSTEP_OBJ_ROBOT, 1, -6, sound_vary = TRUE) var/static/list/innate_actions = list( /datum/action/cooldown/mob_cooldown/missile_launcher = BB_MINEBOT_MISSILE_ABILITY, /datum/action/cooldown/mob_cooldown/drop_landmine = BB_MINEBOT_LANDMINE_ABILITY, /datum/action/cooldown/mob_cooldown/minedrone/toggle_light = BB_MINEBOT_LIGHT_ABILITY, /datum/action/cooldown/mob_cooldown/minedrone/toggle_meson_vision = null, /datum/action/cooldown/mob_cooldown/minedrone/dump_ore = BB_MINEBOT_DUMP_ABILITY, ) grant_actions_by_list(innate_actions) stored_gun = new(src) var/obj/item/implant/radio/mining/comms = new(src) comms.implant(src) assign_access() /mob/living/basic/mining_drone/set_combat_mode(new_mode, silent = TRUE) . = ..() icon_state = combat_mode ? "mining_drone_offense" : "mining_drone" balloon_alert(src, "now [combat_mode ? "attacking" : "collecting"]") /mob/living/basic/mining_drone/examine(mob/user) . = ..() if(health < maxHealth) if(health >= maxHealth * 0.5) . += span_warning("[p_They()] look slightly dented.") else . += span_boldwarning("[p_They()] look severely dented!") if(isnull(stored_gun) || !stored_gun.max_mod_capacity) return . += "[stored_gun.get_remaining_mod_capacity()]% mod capacity remaining." for(var/obj/item/borg/upgrade/modkit/modkit as anything in stored_gun.modkits) . += span_notice("There is \a [modkit] installed, using [modkit.cost]% capacity.") if(ai_controller && ai_controller.ai_status == AI_STATUS_IDLE) . += "The [src] appears to be in sleep mode. You can restore normal functions by tapping it." /mob/living/basic/mining_drone/welder_act(mob/living/user, obj/item/welder) if(user.combat_mode) return FALSE if(combat_mode) user.balloon_alert(user, "can't repair in attack mode!") return TRUE if(maxHealth == health) user.balloon_alert(user, "at full integrity!") return TRUE if(welder.use_tool(src, user, 0, volume=40)) adjust_brute_loss(-15) user.balloon_alert(user, "successfully repaired!") return TRUE /mob/living/basic/mining_drone/attackby(obj/item/item_used, mob/user, list/modifiers, list/attack_modifiers) if(item_used.tool_behaviour == TOOL_CROWBAR || istype(item_used, /obj/item/borg/upgrade/modkit)) item_used.melee_attack_chain(user, stored_gun, modifiers) return return ..() /mob/living/basic/mining_drone/attack_hand(mob/living/carbon/human/user, list/modifiers) if(!user.combat_mode) if(ai_controller && ai_controller.ai_status == AI_STATUS_IDLE) ai_controller.set_ai_status(AI_STATUS_ON) if(LAZYACCESS(modifiers, LEFT_CLICK)) //Lets Right Click be specifically for re-enabling their AI (and avoiding the UI popup), while Left Click simply does both. ui_interact(user) return return ..() /mob/living/basic/mining_drone/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "MineBot", name) ui.open() /mob/living/basic/mining_drone/ui_data(mob/user) var/list/data = list() data["auto_defend"] = ai_controller.blackboard[BB_MINEBOT_AUTO_DEFEND] data["repair_node_drone"] = ai_controller.blackboard[BB_MINEBOT_REPAIR_DRONE] data["plant_mines"] = ai_controller.blackboard[BB_MINEBOT_PLANT_MINES] data["bot_maintain_distance"] = ai_controller.blackboard[BB_MINIMUM_SHOOTING_DISTANCE] data["bot_name"] = name data["bot_mode"] = combat_mode data["bot_health"] = health data["bot_maxhealth"] = maxHealth data["bot_color"] = "" var/color_value = neutral_overlay.color for(var/index in possible_colors) if(possible_colors[index] == color_value) data["bot_color"] = index break return data /mob/living/basic/mining_drone/ui_static_data(mob/user) var/list/data = list() data["bot_icon"] = icon2base64(getFlatIcon(src, no_anim = TRUE)) data["possible_colors"] = list() for(var/color in possible_colors) data["possible_colors"] += list(list( "color_name" = color, "color_value" = possible_colors[color], )) return data /mob/living/basic/mining_drone/ui_act(action, params, datum/tgui/ui) . = ..() switch(action) if("change_min_distance") var/new_distance = clamp(params["distance"], 0, 5) ai_controller.set_blackboard_key(BB_MINIMUM_SHOOTING_DISTANCE, new_distance) if("toggle_defend") var/new_toggle = !ai_controller.blackboard[BB_MINEBOT_AUTO_DEFEND] ai_controller.set_blackboard_key(BB_MINEBOT_AUTO_DEFEND, new_toggle) if("toggle_repair") var/new_defend = !ai_controller.blackboard[BB_MINEBOT_REPAIR_DRONE] ai_controller.set_blackboard_key(BB_MINEBOT_REPAIR_DRONE, new_defend) if("toggle_mines") var/new_mines = !ai_controller.blackboard[BB_MINEBOT_PLANT_MINES] ai_controller.set_blackboard_key(BB_MINEBOT_PLANT_MINES, new_mines) if("set_name") var/input_name = sanitize_name(params["chosen_name"], allow_numbers = TRUE) name = (input_name ? input_name : initial(name)) if("toggle_mode") set_combat_mode(!combat_mode) if("set_color") change_color(params["chosen_color"]) update_static_data(ui.user, ui) return TRUE /mob/living/basic/mining_drone/proc/change_color(new_color) selected_color = new_color if(!isnull(selected_color)) neutral_overlay.color = selected_color combat_overlay.color = selected_color update_appearance() /mob/living/basic/mining_drone/click_alt(mob/living/user) if(user.combat_mode) return CLICK_ACTION_BLOCKING set_combat_mode(!combat_mode) balloon_alert(user, "now [combat_mode ? "attacking wildlife" : "collecting loose ore"]") return CLICK_ACTION_SUCCESS /mob/living/basic/mining_drone/RangedAttack(atom/target, list/modifiers) if(!combat_mode) return stored_gun.try_fire_gun(target, src, list2params(modifiers)) /mob/living/basic/mining_drone/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) . = ..() if(!. || !proximity_flag || combat_mode) return if(istype(attack_target, /obj/item/stack/ore)) var/obj/item/target_ore = attack_target target_ore.forceMove(src) /mob/living/basic/mining_drone/proc/drop_ore() to_chat(src, span_notice("You dump your stored ore.")) for(var/obj/item/stack/ore/dropped_item in contents) dropped_item.forceMove(get_turf(src)) /mob/living/basic/mining_drone/death(gibbed) drop_ore() if(isnull(stored_gun)) return ..() for(var/obj/item/borg/upgrade/modkit/modkit as anything in stored_gun.modkits) modkit.uninstall(stored_gun) return ..() /mob/living/basic/mining_drone/Destroy() QDEL_NULL(stored_gun) return ..() /mob/living/basic/mining_drone/early_melee_attack(atom/target, list/modifiers, ignore_cooldown) . = ..() if(!.) return FALSE if(!istype(target, /mob/living/basic/node_drone)) return TRUE repair_node_drone(target) return FALSE /mob/living/basic/mining_drone/proc/repair_node_drone(mob/living/my_target) do_sparks(5, FALSE, source = my_target) if(!do_after(src, 6 SECONDS, my_target)) return my_target.heal_overall_damage(brute = 50) /mob/living/basic/mining_drone/update_overlays() . = ..() if(stat == DEAD || isnull(selected_color)) return . += combat_mode ? combat_overlay : neutral_overlay /mob/living/basic/mining_drone/proc/assign_access() var/static/list/required_access if(isnull(required_access)) var/datum/id_trim/access_card = SSid_access.trim_singletons_by_path[/datum/id_trim/job/shaft_miner] required_access = access_card.access AddElement(/datum/element/mob_access, required_access)