diff --git a/baystation12.dme b/baystation12.dme
index b694860cd8d..890997d4e92 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -577,6 +577,7 @@
#include "code\game\objects\kitchen.dm"
#include "code\game\objects\lamarr.dm"
#include "code\game\objects\mineral_doors.dm"
+#include "code\game\objects\new_year.dm"
#include "code\game\objects\noticeboard.dm"
#include "code\game\objects\object_procs.dm"
#include "code\game\objects\portals.dm"
diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm
index fcfa830ebef..91ae88093ea 100644
--- a/code/game/machinery/telecomms/broadcaster.dm
+++ b/code/game/machinery/telecomms/broadcaster.dm
@@ -62,7 +62,7 @@
machinetype = 6
heatgen = 0
var/intercept = 0 // if nonzero, broadcasts all messages to syndicate channel
- var/syndi = 1 //If 1, it goes to syndicate frequency. Else, goes to deathsquad
+ var/syndi = 1 //If 1, it goes to syndicate frequency. Else, goes to deathsquad/Response Team
receive_signal(datum/signal/signal)
@@ -210,7 +210,7 @@
// --- Broadcast to response team radio! ---
- else if(data == 3)
+ else if(data == 4)
var/datum/radio_frequency/syndicateconnection = radio_controller.return_frequency(1439)
for (var/obj/item/device/radio/R in syndicateconnection.devices["[RADIO_CHAT]"])
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 8029addbfe3..9283f50e04c 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -283,13 +283,8 @@ the implant may become unstable and either pre-maturely inject the subject or si
if(M.stat == 2)
var/turf/t = get_turf(M)
var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null)
- var/mob/living/carbon/human/G = new /mob/living/carbon/human(null)
- G.real_name = "[mobname]'s death alarm"
- G.name = "[mobname]'s death alarm"
- G.universal_speak = 1
- a.talk_into(G,"[mobname] has died in [t.loc.name]!")
+ a.autosay("[mobname] has died in [t.loc.name]!", "[mobname]'s Death Alarm")
del(a)
- del(G)
processing_objects.Remove(src)
diff --git a/code/game/objects/radio/radio.dm b/code/game/objects/radio/radio.dm
index 1643c38ec3c..79faf801839 100644
--- a/code/game/objects/radio/radio.dm
+++ b/code/game/objects/radio/radio.dm
@@ -183,6 +183,121 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
updateDialog()
add_fingerprint(usr)
+/obj/item/device/radio/proc/autosay(var/message, var/from, var/channel)
+ var/datum/radio_frequency/connection = null
+ if(channel && channels && channels.len > 0)
+ if (channel == "department")
+ //world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\""
+ channel = channels[1]
+ connection = secure_radio_connections[channel]
+ else
+ connection = radio_connection
+ channel = null
+ if (!istype(connection))
+ return
+
+ if(subspace_transmission)
+ // First, we want to generate a new radio signal
+ var/datum/signal/signal = new
+ signal.transmission_method = 2 // 2 would be a subspace transmission.
+ // transmission_method could probably be enumerated through #define. Would be neater.
+
+ // --- Finally, tag the actual signal with the appropriate values ---
+ signal.data = list(
+ // Identity-associated tags:
+ "mob" = new /mob/living/silicon/ai(src), // store a reference to the mob
+ "mobtype" = /mob/living/silicon/ai, // the mob's type
+ "realname" = from, // the mob's real name
+ "name" = from, // the mob's display name
+ "job" = "(Automated Announcement)", // the mob's job
+ "key" = "none", // the mob's key
+ "vmessage" = "*garbled automated announcement*", // the message to display if the voice wasn't understood
+ "vname" = "synthesized voice", // the name to display if the voice wasn't understood
+ "vmask" = 0, // 1 if the mob is using a voice gas mask
+
+ // We store things that would otherwise be kept in the actual mob
+ // so that they can be logged even AFTER the mob is deleted or something
+
+ // Other tags:
+ "compression" = rand(45,50), // compressed radio signal
+ "message" = message, // the actual sent message
+ "connection" = connection, // the radio connection to use
+ "radio" = src, // stores the radio used for transmission
+ "slow" = 0, // how much to sleep() before broadcasting - simulates net lag
+ "traffic" = 0 // dictates the total traffic sum that the signal went through
+ )
+ signal.frequency = connection.frequency // Quick frequency set
+
+ //#### Sending the signal to all subspace receivers ####//
+ for(var/obj/machinery/telecomms/receiver/R in world)
+ R.receive_signal(signal)
+
+ // Allinone can act as receivers.
+ for(var/obj/machinery/telecomms/allinone/R in world)
+ R.receive_signal(signal)
+
+ // Receiving code can be located in Telecommunications.dm
+ return
+
+
+ /* ###### Intercoms and station-bounced radios ###### */
+
+ var/filter_type = 2
+
+ /* --- Intercoms can only broadcast to other intercoms, but bounced radios can broadcast to bounced radios and intercoms --- */
+ if(istype(src, /obj/item/device/radio/intercom))
+ filter_type = 1
+
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 2
+
+
+ /* --- Try to send a normal subspace broadcast first */
+
+ signal.data = list(
+
+ "mob" = new /mob/living/silicon/ai(src), // store a reference to the mob
+ "mobtype" = /mob/living/silicon/ai, // the mob's type
+ "realname" = from, // the mob's real name
+ "name" = from, // the mob's display name
+ "job" = "(Automated Announcement)", // the mob's job
+ "key" = "none", // the mob's key
+ "vmessage" = "*garbled automated announcement*", // the message to display if the voice wasn't understood
+ "vname" = "synthesized voice", // the name to display if the voice wasn't understood
+ "vmask" = 0, // 1 if the mob is using a voice gas mask
+
+ // We store things that would otherwise be kept in the actual mob
+ // so that they can be logged even AFTER the mob is deleted or something
+
+ // Other tags:
+ "compression" = 0, // compressed radio signal
+ "message" = message, // the actual sent message
+ "connection" = connection, // the radio connection to use
+ "radio" = src, // stores the radio used for transmission
+ "slow" = 0, // how much to sleep() before broadcasting - simulates net lag
+ "traffic" = 0 // dictates the total traffic sum that the signal went through
+ )
+ signal.frequency = connection.frequency // Quick frequency set
+
+ for(var/obj/machinery/telecomms/receiver/R in world)
+ R.receive_signal(signal)
+
+
+ sleep(rand(10,25)) // wait a little...
+
+ if(signal.data["done"])
+ del(signal) // delete the signal - we're done here.
+ return
+
+ // Oh my god; the comms are down or something because the signal hasn't been broadcasted yet.
+ // Send a mundane broadcast with limited targets:
+
+ Broadcast_Message(connection, new /mob/living/silicon/ai(src), 0, "*garbled automated announcement*",
+ src, message, from, "(Automated Announcement)", from, "synthesized voice",
+ filter_type, signal.data["compression"])
+ return
+
/obj/item/device/radio/talk_into(mob/M as mob, message, channel)
if(GLOBAL_RADIO_TYPE == 1) // NEW RADIO SYSTEMS: By Doohl
diff --git a/code/game/response_team.dm b/code/game/response_team.dm
index 31316ec6d87..edb8811e955 100644
--- a/code/game/response_team.dm
+++ b/code/game/response_team.dm
@@ -22,14 +22,12 @@ client/verb/JoinResponseTeam()
var/new_name = input(usr, "Pick a name","Name") as null|text
if(!new_name) return
- var/gender = alert(usr, "Pick a gender","Gender","Male","Female")
-
- var/mob/living/carbon/human/new_commando = create_response_team(L, leader_selected, new_name, gender)
+ var/mob/living/carbon/human/new_commando = create_response_team(L, leader_selected, new_name)
new_commando.mind.key = usr.key
new_commando.key = usr.key
- new_commando << "\blue You are [!leader_selected?"member":"LEADER"] of an armed response team in CentComm's service. Something went down on [station_name()] and they're now on code red. Go in there and fix the problem."
+ new_commando << "\blue You are [!leader_selected?" a member":" the LEADER"] of an armed response team in CentComm's service. Something went down on [station_name()] and they're now on code red. Go in there and fix the problem."
new_commando << "You should first gear up and discuss a plan with your team. More members may be joining, don't move out before you're ready."
else
@@ -75,30 +73,105 @@ proc/trigger_armed_response_team()
send_emergency_team = 1
-/client/proc/create_response_team(obj/spawn_location, leader_selected = 0, commando_name, gender)
+/client/proc/create_response_team(obj/spawn_location, leader_selected = 0, commando_name)
- var/mob/living/carbon/human/new_commando = new(spawn_location.loc)
- new_commando.gender = ((gender == "Male") ? MALE : FEMALE)
+ var/mob/living/carbon/human/M = new(spawn_location.loc)
- var/datum/preferences/A = new()//Randomize appearance for the commando.
- A.randomize_appearance_for(new_commando)
+ var/new_facial = input("Please select facial hair color.", "Character Generation") as color
+ if(new_facial)
+ M.r_facial = hex2num(copytext(new_facial, 2, 4))
+ M.g_facial = hex2num(copytext(new_facial, 4, 6))
+ M.b_facial = hex2num(copytext(new_facial, 6, 8))
- new_commando.real_name = commando_name
- new_commando.age = !leader_selected ? rand(23,35) : rand(35,45)
+ var/new_hair = input("Please select hair color.", "Character Generation") as color
+ if(new_facial)
+ M.r_hair = hex2num(copytext(new_hair, 2, 4))
+ M.g_hair = hex2num(copytext(new_hair, 4, 6))
+ M.b_hair = hex2num(copytext(new_hair, 6, 8))
- new_commando.dna.ready_dna(new_commando)//Creates DNA.
+ var/new_eyes = input("Please select eye color.", "Character Generation") as color
+ if(new_eyes)
+ M.r_eyes = hex2num(copytext(new_eyes, 2, 4))
+ M.g_eyes = hex2num(copytext(new_eyes, 4, 6))
+ M.b_eyes = hex2num(copytext(new_eyes, 6, 8))
+
+ var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation") as text
+
+ if (new_tone)
+ M.s_tone = max(min(round(text2num(new_tone)), 220), 1)
+ M.s_tone = -M.s_tone + 35
+
+ // hair
+ var/list/all_hairs = typesof(/datum/sprite_accessory/hair) - /datum/sprite_accessory/hair
+ var/list/hairs = list()
+
+ // loop through potential hairs
+ for(var/x in all_hairs)
+ var/datum/sprite_accessory/hair/H = new x // create new hair datum based on type x
+ hairs.Add(H.name) // add hair name to hairs
+ del(H) // delete the hair after it's all done
+
+ var/new_style = input("Please select hair style", "Character Generation") as null|anything in hairs
+
+ // if new style selected (not cancel)
+ if (new_style)
+ M.h_style = new_style
+
+ for(var/x in all_hairs) // loop through all_hairs again. Might be slightly CPU expensive, but not significantly.
+ var/datum/sprite_accessory/hair/H = new x // create new hair datum
+ if(H.name == new_style)
+ M.hair_style = H // assign the hair_style variable a new hair datum
+ break
+ else
+ del(H) // if hair H not used, delete. BYOND can garbage collect, but better safe than sorry
+
+ // facial hair
+ var/list/all_fhairs = typesof(/datum/sprite_accessory/facial_hair) - /datum/sprite_accessory/facial_hair
+ var/list/fhairs = list()
+
+ for(var/x in all_fhairs)
+ var/datum/sprite_accessory/facial_hair/H = new x
+ fhairs.Add(H.name)
+ del(H)
+
+ new_style = input("Please select facial style", "Character Generation") as null|anything in fhairs
+
+ if(new_style)
+ M.f_style = new_style
+ for(var/x in all_fhairs)
+ var/datum/sprite_accessory/facial_hair/H = new x
+ if(H.name == new_style)
+ M.facial_hair_style = H
+ break
+ else
+ del(H)
+
+ var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female")
+ if (new_gender)
+ if(new_gender == "Male")
+ M.gender = MALE
+ else
+ M.gender = FEMALE
+ M.update_body()
+ M.update_face()
+ M.update_clothing()
+
+ M.real_name = commando_name
+ M.age = !leader_selected ? rand(23,35) : rand(35,45)
+
+ M.dna.ready_dna(M)//Creates DNA.
//Creates mind stuff.
- new_commando.mind = new
- new_commando.mind.current = new_commando
- new_commando.mind.original = new_commando
- new_commando.mind.assigned_role = "MODE"
- new_commando.mind.special_role = "Response Team"
- if(!(new_commando.mind in ticker.minds))
- ticker.minds += new_commando.mind//Adds them to regular mind list.
- new_commando.equip_strike_team(leader_selected)
+ M.mind = new
+ M.mind.current = M
+ M.mind.original = M
+ M.mind.assigned_role = "MODE"
+ M.mind.special_role = "Response Team"
+ if(!(M.mind in ticker.minds))
+ ticker.minds += M.mind//Adds them to regular mind list.
+ M.equip_strike_team(leader_selected)
del(spawn_location)
- return new_commando
+ return M
/mob/living/carbon/human/proc/equip_strike_team(leader_selected = 0)
@@ -144,7 +217,10 @@ proc/trigger_armed_response_team()
var/obj/item/weapon/card/id/W = new(src)
W.name = "[real_name]'s ID Card"
W.icon_state = "centcom"
- W.access = get_access("Head of Personnel")
+ if(leader_selected)
+ W.access = get_access("Captain")
+ else
+ W.access = get_access("Head of Personnel")
W.access += list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage)//Let's add their alloted CentCom access.
W.assignment = "Emergency Response Team"
W.registered = real_name
diff --git a/code/game/specops_shuttle.dm b/code/game/specops_shuttle.dm
index 906ea0b5455..f05c6326cab 100644
--- a/code/game/specops_shuttle.dm
+++ b/code/game/specops_shuttle.dm
@@ -10,7 +10,6 @@ var/specops_shuttle_at_station = 0
var/specops_shuttle_can_send = 1
var/specops_shuttle_time = 0
var/specops_shuttle_timeleft = 0
-var/specops_shuttle_timereset = 0
/obj/machinery/computer/specops_shuttle
name = "Spec. Ops. Shuttle Console"
@@ -20,15 +19,16 @@ var/specops_shuttle_timereset = 0
var/temp = null
var/hacked = 0
var/allowedtocall = 0
+ var/specops_shuttle_timereset = 0
/proc/specops_return()
- var/area/centcom/control/cent_com = locate()//To find announcer. This area should exist for this proc to work.
- var/mob/living/silicon/decoy/announcer = locate() in cent_com//We need a fake AI to announce some stuff below. Otherwise it will be wonky.
+ var/obj/item/device/radio/intercom/announcer = new /obj/item/device/radio/intercom(null)//We need a fake AI to announce some stuff below. Otherwise it will be wonky.
+ announcer.config(list("Response Team" = 0))
var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values.
- var/message = "THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown.
+ var/message = "THE SPECIAL OPERATIONS SHUTTLE IS PREPARING TO RETURN"//Initial message shown.
if(announcer)
- announcer.say(message)
+ announcer.autosay(message, "A.L.I.C.E.", "Response Team")
while(specops_shuttle_time - world.timeofday > 0)
var/ticksleft = specops_shuttle_time - world.timeofday
@@ -44,7 +44,7 @@ var/specops_shuttle_timereset = 0
message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN"
if(rounded_time_left==0)
message = "ALERT: TAKEOFF"
- announcer.say(message)
+ announcer.autosay(message, "A.L.I.C.E.", "Response Team")
message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle.
//Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that.
@@ -82,17 +82,22 @@ var/specops_shuttle_timereset = 0
var/mob/M = locate(/mob) in T
M << "\red You have arrived at Central Command. Operation has ended!"
+ for(var/obj/machinery/computer/specops_shuttle/S in world)
+ S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY
+
+ del(announcer)
+
/proc/specops_process()
- var/area/centcom/control/cent_com = locate()//To find announcer. This area should exist for this proc to work.
var/area/centcom/specops/special_ops = locate()//Where is the specops area located?
- var/mob/living/silicon/decoy/announcer = locate() in cent_com//We need a fake AI to announce some stuff below. Otherwise it will be wonky.
+ var/obj/item/device/radio/intercom/announcer = new /obj/item/device/radio/intercom(null)//We need a fake AI to announce some stuff below. Otherwise it will be wonky.
+ announcer.config(list("Response Team" = 0))
var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values.
var/message = "THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown.
if(announcer)
- announcer.say(message)
+ announcer.autosay(message, "A.L.I.C.E.", "Response Team")
message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD"
- announcer.say(message)
+ announcer.autosay(message, "A.L.I.C.E.", "Response Team")
while(specops_shuttle_time - world.timeofday > 0)
var/ticksleft = specops_shuttle_time - world.timeofday
@@ -108,7 +113,7 @@ var/specops_shuttle_timereset = 0
message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN"
if(rounded_time_left==0)
message = "ALERT: TAKEOFF"
- announcer.say(message)
+ announcer.autosay(message, "A.L.I.C.E.", "Response Team")
message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle.
//Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that.
@@ -218,17 +223,19 @@ var/specops_shuttle_timereset = 0
var/mob/M = locate(/mob) in T
M << "\red You have arrived to [station_name]. Commence operation!"
+ for(var/obj/machinery/computer/specops_shuttle/S in world)
+ S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY
+
+ del(announcer)
+
/proc/specops_can_move()
if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom)
return 0
- else if(world.time <= specops_shuttle_timereset)
- return 0
+ for(var/obj/machinery/computer/specops_shuttle/S in world)
+ if(world.time <= S.specops_shuttle_timereset)
+ return 0
return 1
-/obj/machinery/computer/specops_shuttle/proc/make_move()
- specops_shuttle_timereset = world.time
- return
-
/obj/machinery/computer/specops_shuttle/attack_ai(var/mob/user as mob)
return attack_hand(user)
@@ -280,7 +287,9 @@ var/specops_shuttle_timereset = 0
if (!specops_can_move())
usr << "\blue Central Command will not allow the Special Operations shuttle to return yet."
if(world.time <= specops_shuttle_timereset)
- usr << "\blue [(world.time - specops_shuttle_timereset)/10] seconds remain!"
+ if (((world.time - specops_shuttle_timereset)/10) > 60)
+ usr << "\blue [-((world.time - specops_shuttle_timereset)/10)/60] minutes remain!"
+ usr << "\blue [-(world.time - specops_shuttle_timereset)/10] seconds remain!"
return
usr << "\blue The Special Operations shuttle will arrive at Central Command in [(SPECOPS_MOVETIME/10)] seconds."
@@ -290,7 +299,6 @@ var/specops_shuttle_timereset = 0
specops_shuttle_moving_to_centcom = 1
specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME
- specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY
spawn(0)
specops_return()
@@ -312,7 +320,6 @@ var/specops_shuttle_timereset = 0
specops_shuttle_moving_to_station = 1
specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME
- specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY
spawn(0)
specops_process()
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 99357250ce6..2c3aa31f76e 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -690,7 +690,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
var/obj/item/clothing/glasses/sunglasses/V = new(M)
V.loc = K
M.equip_if_possible(K, M.slot_wear_suit)
- M.equip_if_possible(new /obj/item/weapon/gun/energy(M), M.slot_s_store)
+ M.equip_if_possible(new /obj/item/weapon/gun/energy/gun(M), M.slot_s_store)
var/obj/item/device/pda/heads/pda = new(M)
pda.owner = M.real_name
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index af2c6097c03..6d3ac0648ee 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -270,15 +270,9 @@
proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank)
if (ticker.current_state == GAME_STATE_PLAYING)
- var/ailist[] = list()
- for (var/mob/living/silicon/ai/A in world)
- if (!A.stat)
- ailist += A
- if (ailist.len)
- var/mob/living/silicon/ai/announcer = pick(ailist)
- if(character.mind)
- if((character.mind.assigned_role != "Cyborg") && (character.mind.special_role != "MODE"))
- announcer.say("[character.real_name] has signed up as [rank].")
+ var/obj/item/device/radio/intercom/a = new /obj/item/device/radio/intercom(null)
+ a.autosay("[character.real_name] has arrived on the station.", "Arrivals Announcement Computer")
+ del(a)
proc/ManifestLateSpawn(var/mob/living/carbon/human/H, icon/H_icon) // Attempted fix to add late joiners to various databases -- TLE
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 92ba2cb0c05..4b66e30ca74 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -50,6 +50,15 @@
M.drop_item()
del(src)
return
+ if (target == user && user.zone_sel.selecting == "mouth")
+ M.visible_message("\red [user] sticks their gun in their mouth, ready to pull the trigger...")
+ if(!do_after(user, 20))
+ M.visible_message("\blue [user] decided life was worth living")
+ return
+ M.visible_message("\red [user] pulls the trigger.")
+ M.apply_damage(60, BRUTE, "head")
+ M.apply_damage(90, BRUTE, "chest")
+ return
if (!user.IsAdvancedToolUser())
user << "\red You don't have the dexterity to do this!"
diff --git a/code/stylesheet.dm b/code/stylesheet.dm
index 0cc4bfb71e9..120caff798a 100644
--- a/code/stylesheet.dm
+++ b/code/stylesheet.dm
@@ -94,7 +94,8 @@ h1, h2, h3, h4, h5, h6
.comradio
{
- color: #ACA82D;
+ color:#0028FF;
+ background: #FFD700;
}
.syndradio
diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi
index 8fe609fbb67..92a4a81987a 100644
Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ