diff --git a/code/__DEFINES/bots.dm b/code/__DEFINES/bots.dm
index bb69bfe1e4f..339d272b57e 100644
--- a/code/__DEFINES/bots.dm
+++ b/code/__DEFINES/bots.dm
@@ -35,4 +35,5 @@
//Sentience types
#define SENTIENCE_ORGANIC 1
#define SENTIENCE_ARTIFICIAL 2
-#define SENTIENCE_OTHER 3
\ No newline at end of file
+#define SENTIENCE_OTHER 3
+#define SENTIENCE_MINEBOT 4
\ No newline at end of file
diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm
index 7bd4fd1ad47..6fecd2c21ca 100644
--- a/code/modules/mining/equipment_locker.dm
+++ b/code/modules/mining/equipment_locker.dm
@@ -326,6 +326,10 @@
new /datum/data/mining_equipment("Advanced Scanner", /obj/item/device/t_scanner/adv_mining_scanner, 400),
new /datum/data/mining_equipment("Hivelord Stabilizer", /obj/item/weapon/hivelordstabilizer, 400),
new /datum/data/mining_equipment("Mining Drone", /obj/item/weapon/mining_drone_cube, 500),
+ new /datum/data/mining_equipment("Drone Melee Upgrade", /obj/item/device/mine_bot_ugprade, 400),
+ new /datum/data/mining_equipment("Drone Health Upgrade",/obj/item/device/mine_bot_ugprade/health, 400),
+ new /datum/data/mining_equipment("Drone Ranged Upgrade",/obj/item/device/mine_bot_ugprade/cooldown, 600),
+ new /datum/data/mining_equipment("Drone AI Upgrade", /obj/item/slimepotion/sentience/mining, 1000),
new /datum/data/mining_equipment("GAR mesons", /obj/item/clothing/glasses/meson/gar, 500),
new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/weapon/storage/firstaid/brute, 600),
new /datum/data/mining_equipment("Jaunter", /obj/item/device/wormhole_jaunter, 600),
@@ -708,9 +712,11 @@
melee_damage_lower = 15
melee_damage_upper = 15
environment_smash = 0
+ check_friendly_fire = 1
attacktext = "drills"
attack_sound = 'sound/weapons/circsawhit.ogg'
ranged = 1
+ sentience_type = SENTIENCE_MINEBOT
ranged_message = "shoots"
ranged_cooldown_cap = 3
projectiletype = /obj/item/projectile/kinetic
@@ -811,6 +817,66 @@
..()
+/**********************Minebot Upgrades**********************/
+
+//Melee
+
+/obj/item/device/mine_bot_ugprade
+ name = "minebot melee upgrade"
+ desc = "A minebot upgrade."
+ icon_state = "door_electronics"
+ icon = 'icons/obj/doors/door_assembly.dmi'
+
+/obj/item/device/mine_bot_ugprade/afterattack(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
+ if(!istype(M))
+ return
+ upgrade_bot(M, user)
+
+/obj/item/device/mine_bot_ugprade/proc/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
+ if(M.melee_damage_upper != initial(M.melee_damage_upper))
+ to_chat(user, "[M] already has a combat upgrade installed!")
+ return
+ M.melee_damage_lower = 22
+ M.melee_damage_upper = 22
+ to_chat(user, "You upgrade [M]'s combat module.")
+ qdel(src)
+
+//Health
+
+/obj/item/device/mine_bot_ugprade/health
+ name = "minebot chassis upgrade"
+
+/obj/item/device/mine_bot_ugprade/health/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
+ if(M.maxHealth != initial(M.maxHealth))
+ to_chat(user, "[M] already has a reinforced chassis!")
+ return
+ M.maxHealth = 170
+ to_chat(user, "You reinforce [M]'s chassis.")
+ qdel(src)
+
+
+//Cooldown
+
+/obj/item/device/mine_bot_ugprade/cooldown
+ name = "minebot cooldown upgrade"
+
+/obj/item/device/mine_bot_ugprade/cooldown/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
+ if(M.ranged_cooldown_cap != initial(M.ranged_cooldown_cap))
+ to_chat(user, "[M] already has a decreased weapon cooldown!")
+ return
+ M.ranged_cooldown_cap = 1
+ to_chat(user, "You upgrade [M]'s ranged weaponry, reducing its cooldown.")
+ qdel(src)
+
+
+//AI
+/obj/item/slimepotion/sentience/mining
+ name = "minebot AI upgrade"
+ desc = "Can be used to grant sentience to minebots."
+ icon_state = "door_electronics"
+ icon = 'icons/obj/doors/door_assembly.dmi'
+ sentience_type = SENTIENCE_MINEBOT
+
/**********************Mining drone kit**********************/
/obj/item/weapon/storage/box/drone_kit
diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
index 3ccbb9abec2..4d856ab397a 100644
--- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
@@ -18,6 +18,7 @@
projectilesound = 'sound/weapons/Gunshot.ogg'
projectiletype = /obj/item/projectile/hivebotbullet
faction = list("hivebot")
+ check_friendly_fire = 1
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
speak_emote = list("states")
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 00ca1d65e82..d3a87be35e1 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -15,6 +15,7 @@
var/ranged_message = "fires" //Fluff text for ranged mobs
var/ranged_cooldown = 0 //What the starting cooldown is on ranged attacks
var/ranged_cooldown_cap = 3 //What ranged attacks, after being used are set to, to go back on cooldown, defaults to 3 life() ticks
+ var/check_friendly_fire = 0 // Should the ranged mob check for friendlies when shooting
var/retreat_distance = null //If our mob runs from players when they're too close, set in tile distance. By default, mobs do not retreat.
var/minimum_distance = 1 //Minimum approach distance, so ranged mobs chase targets down, but still keep their distance set in tiles to the target, set higher to make mobs keep distance
@@ -38,7 +39,7 @@
return 0
if(ranged)
ranged_cooldown--
-
+
/mob/living/simple_animal/hostile/process_ai()
..()
if(!AICanContinue())
@@ -250,8 +251,14 @@
walk(src, 0)
/mob/living/simple_animal/hostile/proc/OpenFire(var/the_target)
-
var/target = the_target
+ if(check_friendly_fire)
+ for(var/turf/T in getline(src, target)) // Not 100% reliable but this is faster than simulating actual trajectory
+ for(var/mob/living/L in T)
+ if(L == src || L == target)
+ continue
+ if(faction_check(L) && !attack_same)
+ return
visible_message("[src] [ranged_message] at [target]!")
if(rapid)
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index 64803f06dad..4d6688aa75b 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -24,6 +24,7 @@
var/weapon2
unsuitable_atmos_damage = 15
faction = list("syndicate")
+ check_friendly_fire = 1
status_flags = CANPUSH
/mob/living/simple_animal/hostile/syndicate/death()
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 97b7f11c32f..4e5e6c9b21c 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1425,3 +1425,9 @@ mob/proc/yank_out_object()
/mob/proc/get_access()
return list() //must return list or IGNORE_ACCESS
+
+/mob/proc/faction_check(mob/target)
+ for(var/F in faction)
+ if(F in target.faction)
+ return 1
+ return 0
diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm
index 44384db8187..45ed8f0a08b 100644
--- a/code/modules/research/xenobiology/xenobiology.dm
+++ b/code/modules/research/xenobiology/xenobiology.dm
@@ -199,7 +199,7 @@
to_chat(user, "The potion won't work on [SM].")
return ..()
- to_chat(user, "You offer the sentience potion to [SM]...")
+ to_chat(user, "You offer [src] sentience potion to [SM]...")
being_used = 1
var/list/candidates = pollCandidates("Do you want to play as [SM.name]?", ROLE_SENTIENT, 0, 100)