diff --git a/code/modules/mob/living/simple_animal/aliens/hivebot.dm b/code/modules/mob/living/simple_animal/aliens/hivebot.dm
index d3193adfb6..02f48d13fa 100644
--- a/code/modules/mob/living/simple_animal/aliens/hivebot.dm
+++ b/code/modules/mob/living/simple_animal/aliens/hivebot.dm
@@ -1,6 +1,11 @@
+// Hivebots are tuned towards how many default lasers are needed to kill them.
+// As such, if laser damage is ever changed, you should change this define.
+#define LASERS_TO_KILL *40
+
+// Default hivebot is melee, and a bit more meaty, so it can meatshield for their ranged friends.
/mob/living/simple_animal/hostile/hivebot
- name = "Hivebot"
- desc = "A small robot"
+ name = "hivebot"
+ desc = "A robot. It appears to be somewhat reslient, but lacking a true weapon."
icon = 'icons/mob/hivebot.dmi'
icon_state = "basic"
icon_living = "basic"
@@ -8,16 +13,16 @@
faction = "hivebot"
intelligence_level = SA_ROBOTIC
- maxHealth = 15
- health = 15
+ maxHealth = 3 LASERS_TO_KILL
+ health = 3 LASERS_TO_KILL
speed = 4
- melee_damage_lower = 2
- melee_damage_upper = 3
+ melee_damage_lower = 15
+ melee_damage_upper = 15
attacktext = "clawed"
projectilesound = 'sound/weapons/Gunshot.ogg'
- projectiletype = /obj/item/projectile/hivebotbullet
+ projectiletype = /obj/item/projectile/bullet/hivebot
min_oxy = 0
max_oxy = 0
@@ -29,19 +34,102 @@
max_n2 = 0
minbodytemp = 0
+ cooperative = TRUE
+ firing_lines = TRUE
+ investigates = TRUE
+
+ speak_chance = 1
+ speak = list(
+ "Resuming task: Protect area.",
+ "No threats found.",
+ "Error: No targets found."
+ )
+ emote_hear = list("humms ominously", "whirrs softly", "grinds a gear")
+ emote_see = list("looks around the area", "turns from side to side")
+ say_understood = list("Affirmative.", "Positive")
+ say_cannot = list("Denied.", "Negative")
+ say_maybe_target = list("Possible threat detected. Investigating.", "Motion detected.", "Investigating.")
+ say_got_target = list("Threat detected.", "New task: Remove threat.", "Threat removal engaged.", "Engaging target.")
+
+// Subtypes.
+
+// Melee like the base type, but more fragile.
+/mob/living/simple_animal/hostile/hivebot/swarm
+ name = "swarm hivebot"
+ desc = "A robot. It looks fragile and weak"
+ maxHealth = 1 LASERS_TO_KILL
+ health = 1 LASERS_TO_KILL
+ melee_damage_lower = 3
+ melee_damage_upper = 3
+
+// This one has a semi-weak ranged attack.
/mob/living/simple_animal/hostile/hivebot/range
- name = "Hivebot"
- desc = "A smallish robot, this one is armed!"
+ name = "ranged hivebot"
+ desc = "A robot. It has a simple ballistic weapon."
ranged = 1
+ maxHealth = 2 LASERS_TO_KILL
+ health = 2 LASERS_TO_KILL
+// This one shoots a burst of three, and is considerably more dangerous.
/mob/living/simple_animal/hostile/hivebot/range/rapid
+ name = "rapid hivebot"
+ desc = "A robot. It has a fast firing ballistic rifle."
+ icon_living = "strong"
rapid = 1
+ maxHealth = 2 LASERS_TO_KILL
+ health = 2 LASERS_TO_KILL
-/mob/living/simple_animal/hostile/hivebot/strong
- name = "Strong Hivebot"
- desc = "A robot, this one is armed and looks tough!"
- health = 80
- ranged = 1
+// Shoots EMPs, to screw over other robots.
+/mob/living/simple_animal/hostile/hivebot/range/ion
+ name = "engineering hivebot"
+ desc = "A robot. It has a tool which emits focused electromagnetic pulses, which are deadly to other synthetic adverseries."
+ projectiletype = /obj/item/projectile/ion
+ projectilesound = 'sound/weapons/Laser.ogg'
+ icon_living = "engi"
+ ranged = TRUE
+ maxHealth = 2 LASERS_TO_KILL
+ health = 2 LASERS_TO_KILL
+
+// Shoots deadly lasers.
+/mob/living/simple_animal/hostile/hivebot/range/laser
+ name = "laser hivebot"
+ desc = "A robot. It has an energy weapon."
+ projectiletype = /obj/item/projectile/beam/blue
+ projectilesound = 'sound/weapons/Laser.ogg'
+ maxHealth = 2 LASERS_TO_KILL
+ health = 2 LASERS_TO_KILL
+
+// Beefy and ranged.
+/mob/living/simple_animal/hostile/hivebot/range/strong
+ name = "strong hivebot"
+ desc = "A robot. This one has reinforced plating, and looks tougher."
+ icon_living = "strong"
+ maxHealth = 4 LASERS_TO_KILL
+ health = 4 LASERS_TO_KILL
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+
+// Also beefy, but tries to stay at their 'home', ideal for base defense.
+/mob/living/simple_animal/hostile/hivebot/range/guard
+ name = "guard hivebot"
+ desc = "A robot. It seems to be guarding something."
+ returns_home = TRUE
+ maxHealth = 4 LASERS_TO_KILL
+ health = 4 LASERS_TO_KILL
+
+// This one is intended for players to use. Well rounded and can make other hivebots follow them with verbs.
+/mob/living/simple_animal/hostile/hivebot/range/player
+ name = "commander hivebot"
+ desc = "A robot. This one seems to direct the others, and it has a laser weapon."
+ icon_living = "commander"
+ maxHealth = 5 LASERS_TO_KILL
+ health = 5 LASERS_TO_KILL
+ projectiletype = /obj/item/projectile/beam/blue
+ projectilesound = 'sound/weapons/Laser.ogg'
+ melee_damage_lower = 15 // Needed to force open airlocks.
+ melee_damage_upper = 15
+
+// Procs.
/mob/living/simple_animal/hostile/hivebot/death()
..()
@@ -52,6 +140,42 @@
s.start()
qdel(src)
+/mob/living/simple_animal/hostile/hivebot/speech_bubble_appearance()
+ return "synthetic_evil"
+
+/mob/living/simple_animal/hostile/hivebot/verb/command_follow()
+ set name = "Command - Follow"
+ set category = "Hivebot"
+ set desc = "This will ask other hivebots to follow you."
+
+ say("Delegating new task: Follow.")
+
+ for(var/mob/living/simple_animal/hostile/hivebot/buddy in hearers(src))
+ if(buddy.faction != faction)
+ continue
+ if(buddy == src)
+ continue
+ buddy.set_follow(src)
+ buddy.FollowTarget()
+ spawn(rand(5, 10))
+ buddy.say( pick(buddy.say_understood) )
+
+/mob/living/simple_animal/hostile/hivebot/verb/command_stop()
+ set name = "Command - Stop Following"
+ set category = "Hivebot"
+ set desc = "This will ask other hivebots to cease following you."
+
+ say("Delegating new task: Stop following.")
+
+ for(var/mob/living/simple_animal/hostile/hivebot/buddy in hearers(src))
+ if(buddy.faction != faction)
+ continue
+ if(buddy == src)
+ continue
+ buddy.LoseFollow()
+ spawn(rand(5, 10))
+ buddy.say( pick(buddy.say_understood) )
+
/mob/living/simple_animal/hostile/hivebot/tele//this still needs work
name = "Beacon"
desc = "Some odd beacon thing"
@@ -107,6 +231,6 @@
if(prob(2))//Might be a bit low, will mess with it likely
warpbots()
-/obj/item/projectile/hivebotbullet
+/obj/item/projectile/bullet/hivebot
damage = 10
damage_type = BRUTE
diff --git a/code/modules/mob/living/simple_animal/animals/giant_spider.dm b/code/modules/mob/living/simple_animal/animals/giant_spider.dm
index 8d7a2ccb32..acc6fe0105 100644
--- a/code/modules/mob/living/simple_animal/animals/giant_spider.dm
+++ b/code/modules/mob/living/simple_animal/animals/giant_spider.dm
@@ -43,6 +43,17 @@
var/poison_per_bite = 5
var/poison_chance = 10
var/poison_type = "spidertoxin"
+ var/image/eye_layer = null
+
+/mob/living/simple_animal/hostile/giant_spider/proc/add_eyes()
+ if(!eye_layer)
+ var/overlay_layer = LIGHTING_LAYER+0.1
+ eye_layer = image(icon, "[icon_state]-eyes", overlay_layer)
+
+ overlays += eye_layer
+
+/mob/living/simple_animal/hostile/giant_spider/proc/remove_eyes()
+ overlays -= eye_layer
//nursemaids - these create webs and eggs
/mob/living/simple_animal/hostile/giant_spider/nurse
@@ -96,6 +107,11 @@
/mob/living/simple_animal/hostile/giant_spider/New(var/location, var/atom/parent)
get_light_and_color(parent)
+ add_eyes()
+ ..()
+
+/mob/living/simple_animal/hostile/giant_spider/death()
+ remove_eyes()
..()
/mob/living/simple_animal/hostile/giant_spider/PunchTarget()
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 3144f9eb09..c4344c052b 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -202,8 +202,9 @@
admin_attack_log(firer, target_mob, attacker_message, victim_message, admin_message)
else
- target_mob.attack_log += "\[[time_stamp()]\] UNKNOWN SUBJECT (No longer exists) shot [target_mob]/[target_mob.ckey] with \a [src]"
- msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with \a [src] (JMP)")
+ if(target_mob) // Sometimes the target_mob gets gibbed or something.
+ target_mob.attack_log += "\[[time_stamp()]\] UNKNOWN SUBJECT (No longer exists) shot [target_mob]/[target_mob.ckey] with \a [src]"
+ msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with \a [src] (JMP)")
//sometimes bullet_act() will want the projectile to continue flying
if (result == PROJECTILE_CONTINUE)
diff --git a/code/modules/xenoarcheaology/artifacts/artifact.dm b/code/modules/xenoarcheaology/artifacts/artifact.dm
index e0ba3b1a3f..2bb6434553 100644
--- a/code/modules/xenoarcheaology/artifacts/artifact.dm
+++ b/code/modules/xenoarcheaology/artifacts/artifact.dm
@@ -259,8 +259,7 @@
..()
/obj/machinery/artifact/bullet_act(var/obj/item/projectile/P)
- if(istype(P,/obj/item/projectile/bullet) ||\
- istype(P,/obj/item/projectile/hivebotbullet))
+ if(istype(P,/obj/item/projectile/bullet))
if(my_effect.trigger == TRIGGER_FORCE)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_FORCE && prob(25))
diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi
index ba259d2154..60153c2d92 100644
Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ
diff --git a/icons/mob/hivebot.dmi b/icons/mob/hivebot.dmi
index cb13996361..ecaa519822 100644
Binary files a/icons/mob/hivebot.dmi and b/icons/mob/hivebot.dmi differ