diff --git a/aurora.dme b/aurora.dme
index 84b372b3..6faa3539 100644
--- a/aurora.dme
+++ b/aurora.dme
@@ -1062,6 +1062,7 @@
#include "code\modules\mob\living\silicon\decoy\decoy.dm"
#include "code\modules\mob\living\silicon\decoy\life.dm"
#include "code\modules\mob\living\silicon\pai\death.dm"
+#include "code\modules\mob\living\silicon\pai\emote.dm"
#include "code\modules\mob\living\silicon\pai\examine.dm"
#include "code\modules\mob\living\silicon\pai\hud.dm"
#include "code\modules\mob\living\silicon\pai\life.dm"
diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm
index 882f1618..5bc86fd8 100644
--- a/code/game/gamemodes/autotraitor/autotraitor.dm
+++ b/code/game/gamemodes/autotraitor/autotraitor.dm
@@ -5,9 +5,11 @@
/datum/game_mode/traitor/autotraitor
name = "AutoTraitor"
config_tag = "extend-a-traitormongous"
+ restricted_jobs = list("Cyborg", "Internal Affairs Agent", "Head of Security", "Captain") //To ensure the setting stay from /traitor
var/list/possible_traitors
var/num_players = 0
+ var/afk_traitor_count = 0
/datum/game_mode/traitor/autotraitor/announce()
..()
@@ -87,7 +89,7 @@
playercount += 1
if (player.client && player.mind && player.mind.special_role && player.stat != 2)
traitorcount += 1
- if (player.client && player.mind && !player.mind.special_role && player.stat != 2 && (player.client && player.client.prefs.be_special & BE_TRAITOR) && !jobban_isbanned(player, "Syndicate"))
+ if (player.client && player.mind && !player.mind.special_role && player.stat != 2 && (player.client && player.client.prefs.be_special & BE_TRAITOR) && !jobban_isbanned(player, "Syndicate") && !player.client.is_afk())
possible_traitors += player
for(var/datum/mind/player in possible_traitors)
for(var/job in restricted_jobs)
@@ -100,6 +102,19 @@
// for(var/mob/living/traitorlist in possible_traitors)
// message_admins("[traitorlist.real_name]")
+ var/afk_traitors = 0
+ var/need_new_traitor = 0
+
+ for(var/mob/living/player in traitors)
+ if(player.client.is_afk())
+ afk_traitors += 1
+
+ if(afk_traitors > afk_traitor_count)
+ log_debug("debug: Traitors are afk, forcing a new traitor")
+ need_new_traitor = 1
+ log_debug("debug: afk_traitors = [afk_traitors] | afk_traitor_count = [afk_traitor_count]")
+ afk_traitors = afk_traitor_count
+
// var/r = rand(5)
// var/target_traitors = 1
var/max_traitors = 1
@@ -110,18 +125,23 @@
traitor_prob += 50
- if(traitorcount < max_traitors)
+
+ if(traitorcount < max_traitors || need_new_traitor)
//message_admins("Number of Traitors is below maximum. Rolling for new Traitor.")
//message_admins("The probability of a new traitor is [traitor_prob]%")
if(prob(traitor_prob))
message_admins("Making a new Traitor.")
if(!possible_traitors.len)
+ if(need_new_traitor)
+ log_debug("debug: No potential traitors. Cancelling new traitor.")
message_admins("No potential traitors. Cancelling new traitor.")
traitorcheckloop()
return
var/mob/living/newtraitor = pick(possible_traitors)
//message_admins("[newtraitor.real_name] is the new Traitor.")
+ if(need_new_traitor)
+ log_debug("Traitor forced and selected")
if (!config.objectives_disabled)
forge_traitor_objectives(newtraitor.mind)
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index 272e80f6..d6bab36a 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -5,8 +5,8 @@
/datum/game_mode/traitor
name = "traitor"
config_tag = "traitor"
- restricted_jobs = list("Cyborg")//They are part of the AI if he is traitor so are they, they use to get double chances
- protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain")//AI", Currently out of the list as malf does not work for shit
+ restricted_jobs = list("Cyborg", "Internal Affairs Agent", "Head of Security", "Captain")//Borgs are part of the AI if he is traitor so are they, they use to get double chances Added Implanted
+ protected_jobs = list("Security Officer", "Warden", "Detective")//AI", Currently out of the list as malf does not work for shit
required_players = 0
required_enemies = 1
recommended_enemies = 4
diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm
index 0a65ada4..ea9647b9 100644
--- a/code/game/objects/effects/spiders.dm
+++ b/code/game/objects/effects/spiders.dm
@@ -1,3 +1,7 @@
+/var/global/total_spiders = 0
+/var/global/spider_can_spawn = 1
+/var/global/spider_limit_bypass = 0
+
//generic procs copied from obj/effect/alien
/obj/effect/spider
name = "web"
@@ -186,9 +190,11 @@
if(isturf(loc) && amount_grown > 0)
amount_grown += rand(0,2)
if(amount_grown >= 100)
- var/spawn_type = pick(typesof(/mob/living/simple_animal/hostile/giant_spider))
- new spawn_type(src.loc)
- del(src)
+ amount_grown = 101 //To avoid growing too much
+ if(spider_can_spawn || spider_limit_bypass)
+ var/spawn_type = pick(typesof(/mob/living/simple_animal/hostile/giant_spider))
+ new spawn_type(src.loc)
+ del(src)
/obj/effect/decal/cleanable/spiderling_remains
name = "spiderling remains"
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 5f8becc5..7c14d1e8 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -2070,6 +2070,9 @@
if(aliens_allowed)
create_xeno()
if("spiders")
+ if(!spider_limit_bypass) //Allow the admin to disable the max spider limit. Once enabled it's on for the round.
+ if (alert(usr, "Bypass the spider limit? This only needs to be done once", "Bypass?", "Yes", "No") == "Yes") //Let admins cause havoc if they want
+ spider_limit_bypass = 1
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","SL")
new /datum/event/spider_infestation
diff --git a/code/modules/mob/living/silicon/pai/emote.dm b/code/modules/mob/living/silicon/pai/emote.dm
new file mode 100644
index 00000000..b9658454
--- /dev/null
+++ b/code/modules/mob/living/silicon/pai/emote.dm
@@ -0,0 +1,102 @@
+/mob/living/silicon/pai/emote(var/act,var/m_type=1,var/message = null)
+/* if (findtext(act, "-", 1, null))
+ var/t1 = findtext(act, "-", 1, null)
+ param = copytext(act, t1 + 1, length(act) + 1)
+ act = copytext(act, 1, t1)
+*/
+ if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_'
+ act = copytext(act,1,length(act))
+
+ switch(act)
+ if ("me")
+ if (src.client)
+ if(client.prefs.muted & MUTE_IC)
+ src << "You cannot send IC messages (muted)."
+ return
+ if (src.client.handle_spam_prevention(message,MUTE_IC))
+ return
+ if (stat)
+ return
+ if(!(message))
+ return
+ else
+ return custom_emote(m_type, message)
+
+ if ("custom")
+ return custom_emote(m_type, message)
+
+ if ("salute")
+ message = "[src] displays an image of a person saluting."
+ m_type = 1
+ if ("bow")
+ message = "[src] displays an image of a person bowing."
+ m_type = 1
+
+ if ("clap")
+ message = "[src] displays an image of hands clapping."
+ m_type = 2
+ if ("flap")
+ message = "[src] displays an image of wings flapping."
+ m_type = 2
+
+ if ("aflap")
+ message = "[src] displays an image of wings flapping ANGRILY!"
+ m_type = 2
+
+ if ("twitch")
+ message = "[src] displays an image of a person twitching violently."
+ m_type = 1
+
+ if ("twitch_s")
+ message = "[src] displays an image of a person twitching."
+ m_type = 1
+
+ if ("nod")
+ message = "[src] displays an image of a person nodding."
+ m_type = 1
+
+ if("beep")
+ message = "[src] beeps."
+ playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
+ m_type = 1
+
+ if("ping")
+ message = "[src] pings."
+ playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
+ m_type = 1
+
+ if("buzz")
+ message = "[src] buzzes."
+ playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
+ m_type = 1
+
+ if("law")
+ if (src:secHUD)
+ message = "[src] flashes its legal authorization barcode."
+ playsound(src.loc, 'sound/voice/biamthelaw.ogg', 50, 0)
+ m_type = 2
+ else
+ src << "You are not THE LAW, pal."
+
+ if("halt")
+ if (src:secHUD)
+ message = "[src]'s speakers skreech, \"Halt! Security!\"."
+
+ playsound(src.loc, 'sound/voice/halt.ogg', 50, 0)
+ m_type = 2
+ else
+ src << "You are not security."
+
+ if ("help")
+ src << "salute, bow, clap, flap, aflap, twitch, twitch_s, nod, beep, ping, \nbuzz, law, halt"
+ else
+ src << "\blue Unusable emote '[act]'. Say *help for a list."
+
+ if ((message && src.stat == 0))
+ if (m_type & 1)
+ for(var/mob/O in viewers(src, null))
+ O.show_message(message, m_type)
+ else
+ for(var/mob/O in hearers(src, null))
+ O.show_message(message, m_type)
+ return
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index d0da6eed..18e09497 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -4,7 +4,9 @@
icon_state = "shadow"
robot_talk_understand = 0
- emote_type = 2 // pAIs emotes are heard, not seen, so they can be seen through a container (eg. person)
+
+// Good roleplayers can emote well, why not let them.
+// emote_type = 2 // pAIs emotes are heard, not seen, so they can be seen through a container (eg. person)
var/network = "SS13"
var/obj/machinery/camera/current = null
@@ -76,20 +78,20 @@
..()
usr << browse_rsc('html/paigrid.png') // Go ahead and cache the interface resources as early as possible
-
+
// this function shows the information about being silenced as a pAI in the Status panel
/mob/living/silicon/pai/proc/show_silenced()
if(src.silence_time)
var/timeleft = round((silence_time - world.timeofday)/10 ,1)
stat(null, "Communications system reboot in -[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]")
-
-
+
+
/mob/living/silicon/pai/Stat()
..()
statpanel("Status")
if (src.client.statpanel == "Status")
show_silenced()
-
+
if (proc_holder_list.len)//Generic list for proc_holder objects.
for(var/obj/effect/proc_holder/P in proc_holder_list)
statpanel("[P.panel]","",P)
diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
index 46a33a4f..caf8add0 100644
--- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
+++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
@@ -3,6 +3,7 @@
#define LAYING_EGGS 2
#define MOVING_TO_TARGET 3
#define SPINNING_COCOON 4
+#define MAX_SPIDERS 20
//basic spider mob, these generally guard nests
/mob/living/simple_animal/hostile/giant_spider
@@ -35,6 +36,33 @@
move_to_delay = 6
speed = 3
+/mob/living/simple_animal/hostile/giant_spider/New()
+ total_spiders += 1
+ if(total_spiders == MAX_SPIDERS)
+ spider_can_spawn = 0
+ ..()
+
+/mob/living/simple_animal/hostile/giant_spider/death()
+ total_spiders -= 1
+ if(total_spiders <= (MAX_SPIDERS - 2) && !spider_can_spawn)
+ spider_can_spawn = 1
+ if(total_spiders < 0) //Admin mess around protection
+ total_spiders = 0 //If it worked right we won't get -1
+ ..()
+
+/mob/living/simple_animal/hostile/giant_spider/Life() //Checks to see if spider has been respawned from var edits
+ if(stat == DEAD)
+ if(health > 0)
+ total_spiders += 1
+ ..()
+
+/mob/living/simple_animal/hostile/giant_spider/Del() //The other form of admin protection.
+ if(stat == DEAD)
+ ..()
+ else
+ total_spiders -= 1
+ ..()
+
//nursemaids - these create webs and eggs
/mob/living/simple_animal/hostile/giant_spider/nurse
desc = "Furry and black, it makes you shudder to look at it. This one has brilliant green eyes."
diff --git a/code/modules/projectiles/guns/energy/nuclear.dm b/code/modules/projectiles/guns/energy/nuclear.dm
index f683f1cb..ad06671c 100644
--- a/code/modules/projectiles/guns/energy/nuclear.dm
+++ b/code/modules/projectiles/guns/energy/nuclear.dm
@@ -36,6 +36,7 @@
/obj/item/weapon/gun/energy/rifle/gun/nuclear
name = "Advanced Energy Gun"
desc = "An energy gun with an experimental miniaturized reactor."
+ icon = 'icons/obj/gun.dmi' //Overrides .../rifle
icon_state = "nucgun"
origin_tech = "combat=3;materials=5;powerstorage=3"