diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
index 0a055825a48..2778566923c 100755
--- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
@@ -40,7 +40,7 @@
..()
switch(filter_type)
if(0) //removing hydrocarbons
- filtered_out = list("phoron", "oxygen_agent_b")
+ filtered_out = list("phoron")
if(1) //removing O2
filtered_out = list("oxygen")
if(2) //removing N2
@@ -95,10 +95,10 @@
/obj/machinery/atmospherics/trinary/filter/process()
..()
-
+
last_power_draw = 0
last_flow_rate = 0
-
+
if((stat & (NOPOWER|BROKEN)) || !use_power)
return
diff --git a/code/__defines/unit_tests.dm b/code/__defines/unit_tests.dm
index 478c75fdb25..840673221ce 100644
--- a/code/__defines/unit_tests.dm
+++ b/code/__defines/unit_tests.dm
@@ -1,4 +1,5 @@
#define ASCII_ESC ascii2text(27)
#define ASCII_RED "[ASCII_ESC]\[31m"
#define ASCII_GREEN "[ASCII_ESC]\[32m"
+#define ASCII_YELLOW "[ASCII_ESC]\[33m"
#define ASCII_RESET "[ASCII_ESC]\[0m"
\ No newline at end of file
diff --git a/code/controllers/communications.dm b/code/controllers/communications.dm
index f9e7b67c742..97d193bc5bc 100644
--- a/code/controllers/communications.dm
+++ b/code/controllers/communications.dm
@@ -108,6 +108,7 @@ var/const/ERT_FREQ = 1345
var/const/AI_FREQ = 1343
var/const/DTH_FREQ = 1341
var/const/SYND_FREQ = 1213
+var/const/ENT_FREQ = 1461 //entertainment frequency. This is not a diona exclusive frequency.
// department channels
var/const/PUB_FREQ = 1459
@@ -135,6 +136,7 @@ var/list/radiochannels = list(
"Supply" = SUP_FREQ,
"Service" = SRV_FREQ,
"AI Private" = AI_FREQ,
+ "Entertainment" = ENT_FREQ,
"Medical(I)" = MED_I_FREQ,
"Security(I)" = SEC_I_FREQ
)
@@ -146,7 +148,7 @@ var/list/CENT_FREQS = list(ERT_FREQ, DTH_FREQ)
var/list/ANTAG_FREQS = list(SYND_FREQ)
//Department channels, arranged lexically
-var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, MED_FREQ, SEC_FREQ, SCI_FREQ, SRV_FREQ, SUP_FREQ)
+var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, ENT_FREQ, MED_FREQ, SEC_FREQ, SCI_FREQ, SRV_FREQ, SUP_FREQ)
#define TRANSMISSION_WIRE 0
#define TRANSMISSION_RADIO 1
@@ -177,6 +179,8 @@ var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, MED_FREQ, SEC_FREQ, SCI
return "supradio"
if(frequency == SRV_FREQ) // service
return "srvradio"
+ if(frequency == ENT_FREQ) // entertainment
+ return "entradio"
if(frequency in DEPT_FREQS)
return "deptradio"
diff --git a/code/datums/EPv2.dm b/code/datums/EPv2.dm
index a4e57d346d1..37a1a0ba1f1 100644
--- a/code/datums/EPv2.dm
+++ b/code/datums/EPv2.dm
@@ -112,23 +112,27 @@ var/global/list/all_exonet_connections = list()
return null
// Proc: send_message()
-// Parameters: 3 (target_address - the desired address to send the message to, message - the message to send, text - the message text if message is of type "text")
-// Description: Sends the message to target_address, by calling receive_message() on the desired datum.
-/datum/exonet_protocol/proc/send_message(var/target_address, var/message, var/text)
+// Parameters: 3 (target_address - the desired address to send the message to, data_type - text stating what the content is meant to be used for,
+// content - the actual 'message' being sent to the address)
+// Description: Sends the message to target_address, by calling receive_message() on the desired datum. Returns true if the message is recieved.
+/datum/exonet_protocol/proc/send_message(var/target_address, var/data_type, var/content)
if(!address)
- return 0
+ return FALSE
+ var/obj/machinery/exonet_node/node = get_exonet_node()
+ if(!node) // Telecomms went boom, ion storm, etc.
+ return FALSE
for(var/datum/exonet_protocol/exonet in all_exonet_connections)
if(exonet.address == target_address)
- exonet.receive_message(holder, address, message, text)
- break
+ node.write_log(src.address, target_address, data_type, content)
+ return exonet.receive_message(holder, address, data_type, content)
// Proc: receive_message()
-// Parameters: 4 (origin_atom - the origin datum's holder, origin_address - the address the message originated from, message - the message that was sent,
-// text - the message text if message is of type "text")
+// Parameters: 4 (origin_atom - the origin datum's holder, origin_address - the address the message originated from,
+// data_type - text stating what the content is meant to be used for, content - the actual 'message' being sent from origin_atom)
// Description: Called when send_message() successfully reaches the intended datum. By default, calls receive_exonet_message() on the holder atom.
-/datum/exonet_protocol/proc/receive_message(var/atom/origin_atom, var/origin_address, var/message, var/text)
- holder.receive_exonet_message(origin_atom, origin_address, message, text)
- return
+/datum/exonet_protocol/proc/receive_message(var/atom/origin_atom, var/origin_address, var/data_type, var/content)
+ holder.receive_exonet_message(origin_atom, origin_address, data_type, content)
+ return TRUE // for send_message()
// Proc: receive_exonet_message()
// Parameters: 3 (origin_atom - the origin datum's holder, origin_address - the address the message originated from, message - the message that was sent)
diff --git a/code/datums/underwear/bottom.dm b/code/datums/underwear/bottom.dm
index 379bb1aca41..944d3738894 100644
--- a/code/datums/underwear/bottom.dm
+++ b/code/datums/underwear/bottom.dm
@@ -62,4 +62,9 @@
/datum/category_item/underwear/bottom/striped_panties
name = "Striped Panties"
icon_state = "striped_panties"
+ has_color = TRUE
+
+/datum/category_item/underwear/bottom/longjon
+ name = "Long John Bottoms"
+ icon_state = "ljonb"
has_color = TRUE
\ No newline at end of file
diff --git a/code/datums/underwear/undershirts.dm b/code/datums/underwear/undershirts.dm
index 273c5cba9e0..f4ff3d9505c 100644
--- a/code/datums/underwear/undershirts.dm
+++ b/code/datums/underwear/undershirts.dm
@@ -51,6 +51,18 @@
name = "Tank top, fire, feminine"
icon_state = "tank_fire_fem_s"
+/datum/category_item/underwear/undershirt/tank_top_rainbow
+ name = "Tank top, rainbow"
+ icon_state = "tank_rainbow_s"
+
+/datum/category_item/underwear/undershirt/tank_top_stripes
+ name = "Tank top, striped"
+ icon_state = "tank_stripes_s"
+
+/datum/category_item/underwear/undershirt/tank_top_sun
+ name = "Tank top, sun"
+ icon_state = "tank_sun_s"
+
/datum/category_item/underwear/undershirt/shirt_heart
name = "Shirt, heart"
icon_state = "lover_s"
@@ -125,4 +137,17 @@
/datum/category_item/underwear/undershirt/bowlingw
name = "Bowling Shirt, White"
- icon_state = "bowlingw"
\ No newline at end of file
+ icon_state = "bowlingw"
+
+/datum/category_item/underwear/undershirt/longjon
+ name = "Long John Shirt"
+ icon_state = "longjont"
+ has_color = TRUE
+
+/datum/category_item/underwear/undershirt/longstripe_black
+ name = "Longsleeve Striped Shirt, Black"
+ icon_state = "longstripe"
+
+/datum/category_item/underwear/undershirt/longstripe_blue
+ name = "Longsleeve Striped Shirt, Blue"
+ icon_state = "longstripe_blue"
\ No newline at end of file
diff --git a/code/defines/gases.dm b/code/defines/gases.dm
index 659bd2e21ae..65e45c31efd 100644
--- a/code/defines/gases.dm
+++ b/code/defines/gases.dm
@@ -21,11 +21,11 @@
/decl/xgm_gas/phoron
id = "phoron"
name = "Phoron"
-
+
//Note that this has a significant impact on TTV yield.
//Because it is so high, any leftover phoron soaks up a lot of heat and drops the yield pressure.
specific_heat = 200 // J/(mol*K)
-
+
//Hypothetical group 14 (same as carbon), period 8 element.
//Using multiplicity rule, it's atomic number is 162
//and following a N/Z ratio of 1.5, the molar mass of a monatomic gas is:
@@ -51,9 +51,3 @@
tile_overlay = "sleeping_agent"
overlay_limit = 1
-
-/decl/xgm_gas/oxygen_agent_b
- id = "oxygen_agent_b"
- name = "Oxygen Agent-B" //what is this?
- specific_heat = 300 // J/(mol*K)
- molar_mass = 0.032 // kg/mol
diff --git a/code/game/antagonist/station/changeling.dm b/code/game/antagonist/station/changeling.dm
index 7ace822b1a5..4f60792810d 100644
--- a/code/game/antagonist/station/changeling.dm
+++ b/code/game/antagonist/station/changeling.dm
@@ -56,23 +56,24 @@
return
/datum/antagonist/changeling/can_become_antag(var/datum/mind/player, var/ignore_role)
- if(..())
- if(player.current)
- if(ishuman(player.current))
- var/mob/living/carbon/human/H = player.current
- if(H.isSynthetic())
+ if(!..())
+ return 0
+ if(player.current)
+ if(ishuman(player.current))
+ var/mob/living/carbon/human/H = player.current
+ if(H.isSynthetic())
+ return 0
+ if(H.species.flags & NO_SCAN)
+ return 0
+ return 1
+ else if(isnewplayer(player.current))
+ if(player.current.client && player.current.client.prefs)
+ var/datum/species/S = all_species[player.current.client.prefs.species]
+ if(S && (S.flags & NO_SCAN))
return 0
- if(H.species.flags & NO_SCAN)
+ if(player.current.client.prefs.organ_data["torso"] == "cyborg") // Full synthetic.
return 0
return 1
- else if(isnewplayer(player.current))
- if(player.current.client && player.current.client.prefs)
- var/datum/species/S = all_species[player.current.client.prefs.species]
- if(S && (S.flags & NO_SCAN))
- return 0
- if(player.current.client.prefs.organ_data["torso"] == "cyborg") // Full synthetic.
- return 0
- return 1
return 0
/datum/antagonist/changeling/print_player_full(var/datum/mind/ply)
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index e80b010cab1..eef2dd56afa 100755
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -2162,6 +2162,10 @@ area/space/atmosalert()
name = "\improper Miscellaneous Research"
icon_state = "toxmisc"
+/area/rnd/workshop
+ name = "\improper Workshop"
+ icon_state = "sci_workshop"
+
/area/toxins/server
name = "\improper Server Room"
icon_state = "server"
diff --git a/code/game/gamemodes/game_mode_latespawn.dm b/code/game/gamemodes/game_mode_latespawn.dm
index 4fc1bc6f77f..ecafc0dbc52 100644
--- a/code/game/gamemodes/game_mode_latespawn.dm
+++ b/code/game/gamemodes/game_mode_latespawn.dm
@@ -31,6 +31,16 @@
if(emergency_shuttle.departed || !round_autoantag)
return
+ if(emergency_shuttle.shuttle && (emergency_shuttle.shuttle.moving_status == SHUTTLE_WARMUP || emergency_shuttle.shuttle.moving_status == SHUTTLE_INTRANSIT))
+ return // Don't do anything if the shuttle's coming.
+
+ var/mills = round_duration_in_ticks
+ var/mins = round((mills % 36000) / 600)
+ var/hours = round(mills / 36000)
+
+ if(hours >= 2 && mins >= 40) // Don't do anything in the last twenty minutes of the round, as well.
+ return
+
if(world.time < next_spawn)
return
diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm
index 10091a49185..0fffc9dfa22 100644
--- a/code/game/machinery/atmoalter/scrubber.dm
+++ b/code/game/machinery/atmoalter/scrubber.dm
@@ -17,7 +17,7 @@
var/minrate = 0
var/maxrate = 10 * ONE_ATMOSPHERE
- var/list/scrubbing_gas = list("phoron", "carbon_dioxide", "sleeping_agent", "oxygen_agent_b")
+ var/list/scrubbing_gas = list("phoron", "carbon_dioxide", "sleeping_agent")
/obj/machinery/portable_atmospherics/powered/scrubber/New()
..()
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index 1f0b5f454fe..03d3c1170fa 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -219,6 +219,25 @@
light_range_on = 2
network = list(NETWORK_THUNDER)
circuit = /obj/item/weapon/circuitboard/security/telescreen/entertainment
+ var/obj/item/device/radio/radio = null
+
+/obj/machinery/computer/security/telescreen/entertainment/initialize()
+ ..()
+ radio = new(src)
+ radio.listening = TRUE
+ radio.broadcasting = FALSE
+ radio.set_frequency(ENT_FREQ)
+ radio.canhear_range = 7 // Same as default sight range.
+ power_change()
+
+/obj/machinery/computer/security/telescreen/entertainment/power_change()
+ ..()
+ if(radio)
+ if(stat & NOPOWER)
+ radio.on = FALSE
+ else
+ radio.on = TRUE
+
/obj/machinery/computer/security/wooden_tv
name = "security camera monitor"
desc = "An old TV hooked into the stations camera network."
@@ -228,6 +247,7 @@
circuit = null
light_color = "#3848B3"
light_power_on = 0.5
+
/obj/machinery/computer/security/mining
name = "outpost camera monitor"
desc = "Used to access the various cameras on the outpost."
@@ -236,6 +256,7 @@
network = list("MINE")
circuit = /obj/item/weapon/circuitboard/security/mining
light_color = "#F9BBFC"
+
/obj/machinery/computer/security/engineering
name = "engineering camera monitor"
desc = "Used to monitor fires and breaches."
@@ -243,16 +264,19 @@
icon_screen = "engie_cams"
circuit = /obj/item/weapon/circuitboard/security/engineering
light_color = "#FAC54B"
+
/obj/machinery/computer/security/engineering/New()
if(!network)
network = engineering_networks.Copy()
..()
+
/obj/machinery/computer/security/nuclear
name = "head mounted camera monitor"
desc = "Used to access the built-in cameras in helmets."
icon_state = "syndicam"
network = list(NETWORK_MERCENARY)
circuit = null
+
/obj/machinery/computer/security/nuclear/New()
..()
req_access = list(150)
\ No newline at end of file
diff --git a/code/game/machinery/exonet_node.dm b/code/game/machinery/exonet_node.dm
index aa36e34c9ef..d871a3ec38e 100644
--- a/code/game/machinery/exonet_node.dm
+++ b/code/game/machinery/exonet_node.dm
@@ -15,6 +15,8 @@
var/opened = 0
+ var/list/logs = list() // Gets written to by exonet's send_message() function.
+
// Proc: New()
// Parameters: None
// Description: Adds components to the machine for deconstruction.
@@ -60,6 +62,7 @@
else
on = 0
idle_power_usage = 0
+ update_icon()
// Proc: emp_act()
// Parameters: 1 (severity - how strong the EMP is, with lower numbers being stronger)
@@ -114,6 +117,7 @@
data["allowPDAs"] = allow_external_PDAs
data["allowCommunicators"] = allow_external_communicators
data["allowNewscasters"] = allow_external_newscasters
+ data["logs"] = logs
// update the ui if it exists, returns null if no ui is passed/found
@@ -171,3 +175,14 @@
for(var/obj/machinery/exonet_node/E in machines)
if(E.on)
return E
+
+// Proc: write_log()
+// Parameters: 4 (origin_address - Where the message is from, target_address - Where the message is going, data_type - Instructions on how to interpet content,
+// content - The actual message.
+// Description: This writes to the logs list, so that people can see what people are doing on the Exonet ingame. Note that this is not an admin logging function.
+// Communicators are already logged seperately.
+/obj/machinery/exonet_node/proc/write_log(var/origin_address, var/target_address, var/data_type, var/content)
+ //var/timestamp = time2text(station_time_in_ticks, "hh:mm:ss")
+ var/timestamp = "[stationdate2text()] [stationtime2text()]"
+ var/msg = "[timestamp] | FROM [origin_address] TO [target_address] | TYPE: [data_type] | CONTENT: [content]"
+ logs.Add(msg)
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index acba542dfaf..13168e19f46 100644
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -189,7 +189,7 @@ obj/machinery/recharger
icon = 'icons/obj/stationobjs.dmi'
icon_state = "wrecharger0"
active_power_usage = 25000 //25 kW , It's more specialized than the standalone recharger (guns and batons only) so make it more powerful
- allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton)
+ allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/weapon/cell/device)
icon_state_charged = "wrecharger2"
icon_state_charging = "wrecharger1"
icon_state_idle = "wrecharger0"
diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm
index 4a6aded43b4..93d6743b8ef 100644
--- a/code/game/machinery/telecomms/presets.dm
+++ b/code/game/machinery/telecomms/presets.dm
@@ -56,7 +56,7 @@
id = "Receiver A"
network = "tcommsat"
autolinkers = list("receiverA") // link to relay
- freq_listening = list(AI_FREQ, SCI_FREQ, MED_FREQ, SUP_FREQ, SRV_FREQ, COMM_FREQ, ENG_FREQ, SEC_FREQ)
+ freq_listening = list(AI_FREQ, SCI_FREQ, MED_FREQ, SUP_FREQ, SRV_FREQ, COMM_FREQ, ENG_FREQ, SEC_FREQ, ENT_FREQ)
//Common and other radio frequencies for people to freely use
New()
@@ -102,7 +102,7 @@
/obj/machinery/telecomms/bus/preset_four
id = "Bus 4"
network = "tcommsat"
- freq_listening = list(ENG_FREQ, AI_FREQ, PUB_FREQ)
+ freq_listening = list(ENG_FREQ, AI_FREQ, PUB_FREQ, ENT_FREQ)
autolinkers = list("processor4", "engineering", "common")
/obj/machinery/telecomms/bus/preset_cent
@@ -168,7 +168,7 @@
/obj/machinery/telecomms/server/presets/common
id = "Common Server"
- freq_listening = list(PUB_FREQ, AI_FREQ) // AI Private and Common
+ freq_listening = list(PUB_FREQ, AI_FREQ, ENT_FREQ) // AI Private and Common
autolinkers = list("common")
// "Unused" channels, AKA all others.
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 4565dbc25ff..64e8c5e5398 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -449,6 +449,7 @@ var/list/global/slot_flags_enumeration = list(
/obj/item/proc/eyestab(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
var/mob/living/carbon/human/H = M
+ var/mob/living/carbon/human/U = user
if(istype(H))
for(var/obj/item/protection in list(H.head, H.wear_mask, H.glasses))
if(protection && (protection.body_parts_covered & EYES))
@@ -460,6 +461,14 @@ var/list/global/slot_flags_enumeration = list(
user << "You cannot locate any eyes on [M]!"
return
+ if(U.get_accuracy_penalty(U)) //Should only trigger if they're not aiming well
+ var/hit_zone = get_zone_with_miss_chance(U.zone_sel.selecting, M, U.get_accuracy_penalty(U))
+ if(!hit_zone)
+ U.do_attack_animation(M)
+ playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
+ visible_message("\red [U] attempts to stab [M] in the eyes, but misses!")
+ return
+
user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])"
M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])"
msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") //BS12 EDIT ALG
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index 8562ac7f280..b553f4416ce 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -13,6 +13,8 @@
var/times_used = 0 //Number of times it's been used.
var/broken = 0 //Is the flash burnt out?
var/last_used = 0 //last world.time it was used.
+ var/max_flashes = 10 // How many times the flash can be used before needing to self recharge.
+ var/halloss_per_flash = 30
/obj/item/device/flash/proc/clown_check(var/mob/user)
if(user && (CLUMSY in user.mutations) && prob(50))
@@ -22,15 +24,36 @@
return 1
/obj/item/device/flash/proc/flash_recharge()
- //capacitor recharges over time
- for(var/i=0, i<3, i++)
- if(last_used+600 > world.time)
+ //Every ten seconds the flash doesn't get used, the times_used variable goes down by one, making the flash less likely to burn out,
+ // as well as being able to flash more before reaching max_flashes cap.
+ for(var/i=0, i < max_flashes, i++)
+ if(last_used + 10 SECONDS > world.time)
break
- last_used += 600
- times_used -= 2
+ last_used += 10 SECONDS
+ times_used--
last_used = world.time
times_used = max(0,round(times_used)) //sanity
+// Returns true if the device can flash.
+/obj/item/device/flash/proc/check_capacitor(var/mob/user)
+ //spamming the flash before it's fully charged (60 seconds) increases the chance of it breaking
+ //It will never break on the first use.
+ if(times_used <= max_flashes)
+ last_used = world.time
+ if(prob( round(times_used / 2) )) //if you use it 10 times in a minute it has a 5% chance to break.
+ broken = 1
+ if(user)
+ user << "The bulb has burnt out!"
+ icon_state = "flashburnt"
+ return FALSE
+ else
+ times_used++
+ return TRUE
+ else //can only use it 10 times a minute
+ if(user)
+ user << "*click* *click*"
+ return FALSE
+
//attack_as_weapon
/obj/item/device/flash/attack(mob/living/M, mob/living/user, var/target_zone)
if(!user || !M) return //sanity
@@ -49,20 +72,8 @@
flash_recharge()
- //spamming the flash before it's fully charged (60seconds) increases the chance of it breaking
- //It will never break on the first use.
- switch(times_used)
- if(0 to 5)
- last_used = world.time
- if(prob(times_used)) //if you use it 5 times in a minute it has a 10% chance to break!
- broken = 1
- user << "The bulb has burnt out!"
- icon_state = "flashburnt"
- return
- times_used++
- else //can only use it 5 times a minute
- user << "*click* *click*"
- return
+ if(!check_capacitor(user))
+ return
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.do_attack_animation(M)
@@ -71,12 +82,13 @@
var/flashfail = 0
if(iscarbon(M))
- if(M.stat!=DEAD)
- var/safety = M:eyecheck()
+ var/mob/living/carbon/C = M
+ if(C.stat != DEAD)
+ var/safety = C.eyecheck()
if(safety <= 0)
var/flash_strength = 5
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
+ if(ishuman(C))
+ var/mob/living/carbon/human/H = C
flash_strength *= H.species.flash_mod
if(flash_strength > 0)
@@ -84,6 +96,7 @@
H.eye_blind = max(H.eye_blind, flash_strength)
H.eye_blurry = max(H.eye_blurry, flash_strength + 5)
H.flash_eyes()
+ H.adjustHalLoss(halloss_per_flash * (flash_strength / 5)) // Should take four flashes to stun.
else
flashfail = 1
@@ -132,19 +145,9 @@
flash_recharge()
- //spamming the flash before it's fully charged (60seconds) increases the chance of it breaking
- //It will never break on the first use.
- switch(times_used)
- if(0 to 5)
- if(prob(2*times_used)) //if you use it 5 times in a minute it has a 10% chance to break!
- broken = 1
- user << "The bulb has burnt out!"
- icon_state = "flashburnt"
- return
- times_used++
- else //can only use it 5 times a minute
- user.show_message("*click* *click*", 2)
- return
+ if(!check_capacitor(user))
+ return
+
playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
flick("flash2", src)
if(user && isrobot(user))
@@ -158,32 +161,29 @@
sleep(5)
qdel(animation)
- for(var/mob/living/carbon/M in oviewers(3, null))
- var/safety = M:eyecheck()
+ for(var/mob/living/carbon/C in oviewers(3, null))
+ var/safety = C.eyecheck()
if(!safety)
- if(!M.blinded)
- M.flash_eyes()
+ if(!C.blinded)
+ C.flash_eyes()
return
/obj/item/device/flash/emp_act(severity)
if(broken) return
flash_recharge()
- switch(times_used)
- if(0 to 5)
- if(prob(2*times_used))
- broken = 1
- icon_state = "flashburnt"
- return
- times_used++
- if(istype(loc, /mob/living/carbon))
- var/mob/living/carbon/M = loc
- var/safety = M.eyecheck()
- if(safety <= 0)
- M.Weaken(10)
- M.flash_eyes()
- for(var/mob/O in viewers(M, null))
- O.show_message("[M] is blinded by the flash!")
+ if(!check_capacitor())
+ return
+
+ if(istype(loc, /mob/living/carbon))
+ var/mob/living/carbon/C = loc
+ var/safety = C.eyecheck()
+ if(safety <= 0)
+ C.adjustHalLoss(halloss_per_flash)
+ //C.Weaken(10)
+ C.flash_eyes()
+ for(var/mob/M in viewers(C, null))
+ M.show_message("[C] is blinded by the flash!")
..()
/obj/item/device/flash/synthetic
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 72d4c506859..216e2e59d07 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -43,6 +43,10 @@
icon_state = "medintercom"
frequency = SEC_I_FREQ
+/obj/item/device/radio/intercom/entertainment
+ name = "entertainment intercom"
+ frequency = ENT_FREQ
+
/obj/item/device/radio/intercom/New()
..()
processing_objects += src
@@ -59,6 +63,13 @@
num2text(SEC_I_FREQ) = list(access_security)
)
+/obj/item/device/radio/intercom/entertainment/New()
+ ..()
+ internal_channels = list(
+ num2text(PUB_FREQ) = list(),
+ num2text(ENT_FREQ) = list()
+ )
+
/obj/item/device/radio/intercom/syndicate
name = "illicit intercom"
desc = "Talk through this. Evilly"
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index c173e0344e6..cec23e818fd 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -2,6 +2,7 @@
var/global/list/default_internal_channels = list(
num2text(PUB_FREQ) = list(),
num2text(AI_FREQ) = list(access_synth),
+ num2text(ENT_FREQ) = list(),
num2text(ERT_FREQ) = list(access_cent_specops),
num2text(COMM_FREQ)= list(access_heads),
num2text(ENG_FREQ) = list(access_engine_equip, access_atmospherics),
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index f9d414267f0..56311a52df1 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -81,12 +81,14 @@ REAGENT SCANNER
user.show_message("Localized Damage, Brute/Burn:",1)
if(length(damaged)>0)
for(var/obj/item/organ/external/org in damaged)
- user.show_message(text(" [][]: [][] - []",
- capitalize(org.name),
- (org.robotic >= ORGAN_ROBOT) ? "(Cybernetic)" : "",
- (org.brute_dam > 0) ? "[org.brute_dam]" : 0,
- (org.status & ORGAN_BLEEDING)?"\[Bleeding\]":"",
- (org.burn_dam > 0) ? "[org.burn_dam]" : 0),1)
+ if(org.robotic >= ORGAN_ROBOT)
+ continue
+ else
+ user.show_message(text(" []: [][] - []",
+ capitalize(org.name),
+ (org.brute_dam > 0) ? "[org.brute_dam]" : 0,
+ (org.status & ORGAN_BLEEDING)?"\[Bleeding\]":"",
+ (org.burn_dam > 0) ? "[org.burn_dam]" : 0),1)
else
user.show_message(" Limbs are OK.",1)
diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm
index 40a7381cb0a..2564b3eff08 100644
--- a/code/game/objects/items/devices/taperecorder.dm
+++ b/code/game/objects/items/devices/taperecorder.dm
@@ -370,7 +370,7 @@
matter = list(DEFAULT_WALL_MATERIAL=20, "glass"=5)
force = 1
throwforce = 0
- var/max_capacity = 600
+ var/max_capacity = 1800
var/used_capacity = 0
var/list/storedinfo = new/list()
var/list/timestamp = new/list()
diff --git a/code/game/objects/items/devices/tvcamera.dm b/code/game/objects/items/devices/tvcamera.dm
new file mode 100644
index 00000000000..b449a6ce3b6
--- /dev/null
+++ b/code/game/objects/items/devices/tvcamera.dm
@@ -0,0 +1,95 @@
+/obj/item/device/tvcamera
+ name = "press camera drone"
+ desc = "A Ward-Takahashi EyeBuddy media streaming hovercam. Weapon of choice for war correspondents and reality show cameramen."
+ icon_state = "camcorder"
+ item_state = "camcorder"
+ w_class = ITEMSIZE_LARGE
+ slot_flags = SLOT_BELT
+ var/channel = "NCS Northern Star News Feed"
+ var/obj/machinery/camera/network/thunder/camera
+ var/obj/item/device/radio/radio
+
+/obj/item/device/tvcamera/New()
+ ..()
+ listening_objects += src
+
+/obj/item/device/tvcamera/Destroy()
+ listening_objects -= src
+ qdel(camera)
+ qdel(radio)
+ camera = null
+ radio = null
+ ..()
+
+/obj/item/device/tvcamera/examine()
+ ..()
+ to_chat(usr, "Video feed is [camera.status ? "on" : "off"]")
+ to_chat(usr, "Audio feed is [radio.broadcasting ? "on" : "off"]")
+
+/obj/item/device/tvcamera/initialize()
+ ..()
+ camera = new(src)
+ camera.c_tag = channel
+ camera.status = FALSE
+ radio = new(src)
+ radio.listening = FALSE
+ radio.set_frequency(ENT_FREQ)
+ radio.icon = src.icon
+ radio.icon_state = src.icon_state
+ update_icon()
+
+/obj/item/device/tvcamera/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null)
+ radio.hear_talk(M,msg,verb,speaking)
+ ..()
+
+/obj/item/device/tvcamera/attack_self(mob/user)
+ add_fingerprint(user)
+ user.set_machine(src)
+ var/dat = list()
+ dat += "Channel name is: [channel ? channel : "unidentified broadcast"]
"
+ dat += "Video streaming is [camera.status ? "on" : "off"]
"
+ dat += "Mic is [radio.broadcasting ? "on" : "off"]
"
+ dat += "Sound is being broadcasted on frequency [format_frequency(radio.frequency)] ([get_frequency_name(radio.frequency)])
"
+ var/datum/browser/popup = new(user, "Hovercamera", "Eye Buddy", 300, 390, src)
+ popup.set_content(jointext(dat,null))
+ popup.open()
+
+/obj/item/device/tvcamera/Topic(bred, href_list, state = physical_state)
+ if(..())
+ return 1
+ if(href_list["channel"])
+ var/nc = input(usr, "Channel name", "Select new channel name", channel) as text|null
+ if(nc)
+ channel = nc
+ camera.c_tag = channel
+ to_chat(usr, "New channel name - '[channel]' is set")
+ if(href_list["video"])
+ camera.set_status(!camera.status)
+ if(camera.status)
+ to_chat(usr,"Video streaming activated. Broadcasting on channel '[channel]'")
+ else
+ to_chat(usr,"Video streaming deactivated.")
+ update_icon()
+ if(href_list["sound"])
+ radio.ToggleBroadcast()
+ if(radio.broadcasting)
+ to_chat(usr,"Audio streaming activated. Broadcasting on frequency [format_frequency(radio.frequency)].")
+ else
+ to_chat(usr,"Audio streaming deactivated.")
+ if(!href_list["close"])
+ attack_self(usr)
+
+/obj/item/device/tvcamera/update_icon()
+ ..()
+ if(camera.status)
+ icon_state = "camcorder_on"
+ item_state = "camcorder_on"
+ else
+ icon_state = "camcorder"
+ item_state = "camcorder"
+ var/mob/living/carbon/human/H = loc
+ if(istype(H))
+ H.update_inv_r_hand()
+ H.update_inv_l_hand()
+ H.update_inv_belt()
+
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 17d3e32f92c..eec5638523b 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -54,6 +54,18 @@
part.implants.Remove(src)
..()
+/obj/item/weapon/implant/attackby(obj/item/I, mob/user)
+ if(istype(I, /obj/item/weapon/implanter))
+ var/obj/item/weapon/implanter/implanter = I
+ if(implanter.imp)
+ return // It's full.
+ user.drop_from_inventory(src)
+ forceMove(implanter)
+ implanter.imp = src
+ implanter.update()
+ else
+ ..()
+
/obj/item/weapon/implant/tracking
name = "tracking implant"
desc = "Track with this."
diff --git a/code/game/objects/items/weapons/implants/implantcircuits.dm b/code/game/objects/items/weapons/implants/implantcircuits.dm
new file mode 100644
index 00000000000..cf55cbd7067
--- /dev/null
+++ b/code/game/objects/items/weapons/implants/implantcircuits.dm
@@ -0,0 +1,44 @@
+/obj/item/weapon/implant/integrated_circuit
+ name = "electronic implant"
+ icon = 'icons/obj/electronic_assemblies.dmi'
+ icon_state = "setup_implant"
+ var/obj/item/device/electronic_assembly/implant/IC = null
+
+/obj/item/weapon/implant/integrated_circuit/islegal()
+ return TRUE
+
+/obj/item/weapon/implant/integrated_circuit/New()
+ ..()
+ IC = new(src)
+ IC.implant = src
+
+/obj/item/weapon/implant/integrated_circuit/Destroy()
+ IC.implant = null
+ qdel(IC)
+ ..()
+
+/obj/item/weapon/implant/integrated_circuit/get_data()
+ var/dat = {"
+ Implant Specifications:
+ Name: Modular Implant
+ Life: 3 years.
+ Important Notes: EMP can cause malfunctions in the internal electronics of this implant.
+