diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm
index d55faf2343..e1f55da551 100644
--- a/code/game/machinery/requests_console.dm
+++ b/code/game/machinery/requests_console.dm
@@ -9,7 +9,7 @@ GLOBAL_LIST_EMPTY(allConsoles)
#define NO_NEW_MESSAGE 0
#define NORMAL_MESSAGE_PRIORITY 1
#define HIGH_MESSAGE_PRIORITY 2
-#define EXTREME_MESSAGE_PRIORITY 3 // not implemented, will probably require some hacking... everything needs to have a hidden feature in this game.
+#define EXTREME_MESSAGE_PRIORITY 3 // is implimented, does require hacking. everything needs to have a hidden feature in this game.
/obj/machinery/requests_console
name = "requests console"
@@ -48,9 +48,9 @@ GLOBAL_LIST_EMPTY(allConsoles)
var/announceAuth = FALSE //Will be set to 1 when you authenticate yourself for announcements
var/msgVerified = "" //Will contain the name of the person who verified it
var/msgStamped = "" //If a message is stamped, this will contain the stamp name
- var/message = "";
- var/dpt = ""; //the department which will be receiving the message
- var/priority = -1 ; //Priority of the message being sent
+ var/message = ""
+ var/dpt = "" //the department which will be receiving the message
+ var/priority = NORMAL_MESSAGE_PRIORITY //Priority of the message being sent. why is the default -1??
var/obj/item/radio/Radio
var/emergency //If an emergency has been called by this device. Acts as both a cooldown and lets the responder know where it the emergency was triggered from
var/receive_ore_updates = FALSE //If ore redemption machines will send an update when it receives new ores.
@@ -62,16 +62,17 @@ GLOBAL_LIST_EMPTY(allConsoles)
update_icon()
/obj/machinery/requests_console/update_icon_state()
- if(stat & NOPOWER)
+ if(CHECK_BITFIELD(stat, NOPOWER))
set_light(0)
else
- set_light(1.4,0.7,"#34D352")//green light
+ set_light(1.4, 0.7, "#34D352")//green light
+
if(open)
if(!hackState)
icon_state="req_comp_open"
else
icon_state="req_comp_rewired"
- else if(stat & NOPOWER)
+ else if(CHECK_BITFIELD(stat, NOPOWER))
if(icon_state != "req_comp_off")
icon_state = "req_comp_off"
else
@@ -122,7 +123,7 @@ GLOBAL_LIST_EMPTY(allConsoles)
GLOB.req_console_information += department
Radio = new /obj/item/radio(src)
- Radio.listening = 0
+ Radio.listening = FALSE
/obj/machinery/requests_console/Destroy()
QDEL_NULL(Radio)
@@ -131,164 +132,173 @@ GLOBAL_LIST_EMPTY(allConsoles)
/obj/machinery/requests_console/ui_interact(mob/user)
. = ..()
+ if(open) //no.
+ return
+
var/dat = ""
- if(!open)
- switch(screen)
- if(1) //req. assistance
- dat += "Which department do you need assistance from?
"
- dat += "
| [dpt] | " - dat += "Normal High" - if(hackState) - dat += "EXTREME" - dat += " | " - dat += "
| [dpt] | " + dat += "" + dat += "Normal" + dat += "High" + if(hackState) + dat += "EXTREME" + dat += " | " + dat += "
| [dpt] | " - dat += "Normal High" - if(hackState) - dat += "EXTREME" - dat += " | " - dat += "
| [dpt] | " - dat += "Normal High" - if(hackState) - dat += "EXTREME" - dat += " | " - dat += "
| [dpt] | " + dat += "" + dat += "Normal" + dat += "High" + if(hackState) + dat += "EXTREME" + dat += " | " + dat += "
| X | Sender | Recipient | Message |
|---|---|---|---|
| [pda.sender] | [pda.recipient] | [pda.message][pda.picture ? " (Photo)":""] |
| Sender | -Sender's Job | -Recipient | -Message |
| [customsender] | -[customjob] | -[customrecepient ? customrecepient.owner : "NONE"] | -[custommessage] |
| X | Sending Dep. | Receiving Dep. | -Message | Stamp | ID Auth. | Priority. |
|---|---|---|---|---|---|---|
| [rc.send_dpt] | -[rc.rec_dpt] | [rc.message] | [rc.stamp] | [rc.id_auth] | [rc.priority] |
" \
- + "", "window=pdaphoto;size=[picture.psize_x]x[picture.psize_y];can-close=true")
+
+ M << browse_rsc(picture.picture_image, "pda_photo.png")
+
+ var/dat = ""
+
+ var/datum/browser/popup = new(M, "pdaphoto", "PDA Photo", picture.psize_x, picture.psize_y)
+ popup.set_content(dat)
+ popup.open()
onclose(M, "pdaphoto")
/datum/data_rc_msg
diff --git a/code/game/machinery/telecomms/machines/server.dm b/code/game/machinery/telecomms/machines/server.dm
index ad4599b4c3..6f80cfbf0e 100644
--- a/code/game/machinery/telecomms/machines/server.dm
+++ b/code/game/machinery/telecomms/machines/server.dm
@@ -33,7 +33,7 @@
totaltraffic += traffic // add current traffic to total traffic
// Delete particularly old logs
- if (log_entries.len >= 400)
+ if(LAZYLEN(log_entries) >= 400) //[list].len is not safe
log_entries.Cut(1, 2)
var/datum/comm_log_entry/log = new
diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm
index d21edffea1..e1b345f507 100644
--- a/code/game/machinery/telecomms/telecomunications.dm
+++ b/code/game/machinery/telecomms/telecomunications.dm
@@ -117,9 +117,9 @@ GLOBAL_LIST_EMPTY(telecomms_list)
icon_state = "[initial(icon_state)]_off"
/obj/machinery/telecomms/proc/update_power()
-
if(toggled)
- if(stat & (BROKEN|NOPOWER|EMPED)) // if powered, on. if not powered, off. if too damaged, off
+ // if powered, on. if not powered, off. if too damaged, off
+ if(CHECK_BITFIELD(stat, (BROKEN | NOPOWER | EMPED)))
on = FALSE
else
on = TRUE
@@ -137,11 +137,11 @@ GLOBAL_LIST_EMPTY(telecomms_list)
/obj/machinery/telecomms/emp_act(severity)
. = ..()
- if(. & EMP_PROTECT_SELF)
+ if(CHECK_BITFIELD(., EMP_PROTECT_SELF))
return
- if(prob(100/severity))
- if(!(stat & EMPED))
- stat |= EMPED
- var/duration = (300 * 10)/severity
+ if(prob(100 / severity))
+ if(!CHECK_BITFIELD(stat, EMPED))
+ ENABLE_BITFIELD(stat, EMPED)
+ var/duration = (300 * 10) / severity
spawn(rand(duration - 20, duration + 20)) // Takes a long time for the machines to reboot.
- stat &= ~EMPED
+ DISABLE_BITFIELD(stat, EMPED)
diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm
index acfc9a6e85..6f5e99e5aa 100644
--- a/code/game/objects/items/twohanded.dm
+++ b/code/game/objects/items/twohanded.dm
@@ -582,7 +582,7 @@
force_wielded = 18
throwforce = 20
throw_speed = 4
- embedding = list("embedded_impact_pain_multiplier" = 3, "embed_chance" = 90)
+ embedding = list("embedded_impact_pain_multiplier" = 1.5, "embed_chance" = 65)
armour_penetration = 10
custom_materials = list(/datum/material/iron=1150, /datum/material/glass=2075)
hitsound = 'sound/weapons/bladeslice.ogg'
@@ -667,6 +667,7 @@
force_wielded = 19
force_unwielded = 11
throwforce = 21
+ embedding = getEmbeddingBehavior(embed_chance = 75, embedded_pain_multiplier = 1.5) //plasmaglass spears are sharper
icon_prefix = "spearplasma"
qdel(tip)
var/obj/item/twohanded/spear/S = locate() in parts_list
@@ -681,6 +682,7 @@
if(G)
explosive = G
name = "explosive lance"
+ embedding = getEmbeddingBehavior(embed_chance = 0, embedded_pain_multiplier = 1)//elances should not be embeddable
desc = "A makeshift spear with [G] attached to it."
update_icon()
diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm
index bd6dcb2aff..a4ee2f16e2 100644
--- a/code/game/objects/structures/bedsheet_bin.dm
+++ b/code/game/objects/structures/bedsheet_bin.dm
@@ -41,7 +41,7 @@ LINEN BINS
return
/obj/item/bedsheet/attackby(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/wirecutters) || I.get_sharpness())
+ if(!(flags_1 & HOLOGRAM_1) && (istype(I, /obj/item/wirecutters) || I.get_sharpness()))
var/obj/item/stack/sheet/cloth/C = new (get_turf(src), 3)
transfer_fingerprints_to(C)
C.add_fingerprint(user)
@@ -369,4 +369,4 @@ LINEN BINS
/obj/structure/bedsheetbin/color
sheet_types = list(/obj/item/bedsheet, /obj/item/bedsheet/blue, /obj/item/bedsheet/green, /obj/item/bedsheet/orange, \
/obj/item/bedsheet/purple, /obj/item/bedsheet/red, /obj/item/bedsheet/yellow, /obj/item/bedsheet/brown, \
- /obj/item/bedsheet/black)
\ No newline at end of file
+ /obj/item/bedsheet/black)
diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm
index a2fc3aec88..cde63adffd 100644
--- a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm
@@ -2,15 +2,16 @@
name = "A Perfectly Generic Boss Placeholder"
desc = ""
threat = 10
- robust_searching = 1
+ robust_searching = TRUE
stat_attack = UNCONSCIOUS
- status_flags = 0
+ status_flags = NONE
a_intent = INTENT_HARM
gender = NEUTER
has_field_of_vision = FALSE //You are a frikkin boss
var/list/boss_abilities = list() //list of /datum/action/boss
var/datum/boss_active_timed_battle/atb
- var/point_regen_delay = 1
+ var/point_regen_delay = 20
+ var/point_regen_amount = 1
/mob/living/simple_animal/hostile/boss/Initialize()
@@ -18,6 +19,7 @@
atb = new()
atb.point_regen_delay = point_regen_delay
+ atb.point_regen_amount = point_regen_amount
atb.boss = src
for(var/ab in boss_abilities)
@@ -40,6 +42,7 @@
required_mobility_flags = NONE
var/boss_cost = 100 //Cost of usage for the boss' AI 1-100
var/usage_probability = 100
+ var/list/req_statuses //If set, will only trigger if the mob AI status is present in this list.
var/mob/living/simple_animal/hostile/boss/boss
var/boss_type = /mob/living/simple_animal/hostile/boss
var/needs_target = TRUE //Does the boss need to have a target? (Only matters for the AI)
@@ -57,7 +60,7 @@
. = ..()
boss = null
-/datum/action/boss/Trigger()
+/datum/action/boss/IsAvailable(silent = FALSE)
. = ..()
if(!.)
return
@@ -69,6 +72,11 @@
return FALSE
if(!boss.client && needs_target && !boss.target)
return FALSE
+
+/datum/action/boss/Trigger()
+ . = ..()
+ if(!.)
+ return
if(!boss.atb.spend(boss_cost))
return FALSE
if(say_when_triggered)
@@ -85,7 +93,8 @@
//Designed for boss mobs only
/datum/boss_active_timed_battle
var/list/abilities //a list of /datum/action/boss owned by a boss mob
- var/point_regen_delay = 5
+ var/point_regen_delay = 20
+ var/point_regen_amount = 1
var/max_points = 100
var/points = 50 //start with 50 so we can use some abilities but not insta-buttfug somebody
var/next_point_time = 0
@@ -93,48 +102,45 @@
var/highest_cost = 0
var/mob/living/simple_animal/hostile/boss/boss
-
/datum/boss_active_timed_battle/New()
..()
START_PROCESSING(SSobj, src)
-
/datum/boss_active_timed_battle/proc/assign_abilities(list/L)
if(!L)
- return 0
+ return FALSE
abilities = L
for(var/ab in abilities)
var/datum/action/boss/AB = ab
if(AB.boss_cost > highest_cost)
highest_cost = AB.boss_cost
-
/datum/boss_active_timed_battle/proc/spend(cost)
if(cost <= points)
- points = max(0,points-cost)
+ points -= cost
return TRUE
return FALSE
-
/datum/boss_active_timed_battle/proc/refund(cost)
points = min(points+cost, max_points)
-
/datum/boss_active_timed_battle/process()
if(world.time >= next_point_time && points < max_points)
next_point_time = world.time + point_regen_delay
- points = min(max_points, ++points) //has to be out of 100
+ points = min(max_points, points + point_regen_amount)
- if(abilities)
- chance_to_hold_onto_points = highest_cost*0.5
- if(points != max_points && prob(chance_to_hold_onto_points))
- return //Let's save our points for a better ability (unless we're at max points, in which case we can't save anymore!)
- if(!boss.client)
- abilities = shuffle(abilities)
- for(var/ab in abilities)
- var/datum/action/boss/AB = ab
- if(prob(AB.usage_probability) && AB.Trigger())
- break
+ if(!abilities)
+ return
+ chance_to_hold_onto_points = highest_cost*0.5
+ if(points != max_points && prob(chance_to_hold_onto_points))
+ return //Let's save our points for a better ability (unless we're at max points, in which case we can't save anymore!)
+ if(!boss.client)
+ abilities = shuffle(abilities)
+ for(var/ab in abilities)
+ var/datum/action/boss/AB = ab
+ if(!boss.client && (!AB.req_statuses || (boss.AIStatus in AB.req_statuses)) && prob(AB.usage_probability) && AB.Trigger())
+ break
+ AB.UpdateButtonIcon(TRUE)
/datum/boss_active_timed_battle/Destroy()
diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm
index 4d45120a59..fe00af9384 100644
--- a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm
@@ -36,6 +36,7 @@
boss_cost = 30
boss_type = /mob/living/simple_animal/hostile/boss/paper_wizard
needs_target = FALSE
+ req_statuses = list(AI_ON)
say_when_triggered = "Rise, my creations! Jump off your pages and into this realm!"
var/list/summoned_minions = list()
var/maximum_stickmen = 6
@@ -85,6 +86,7 @@
usage_probability = 30
boss_cost = 40
boss_type = /mob/living/simple_animal/hostile/boss/paper_wizard
+ req_statuses = list(AI_ON)
say_when_triggered = ""
/datum/action/boss/wizard_mimic/Trigger()
diff --git a/icons/obj/machines/implantchair.dmi b/icons/obj/machines/implantchair.dmi
index e91f614fad..7cc3493885 100644
Binary files a/icons/obj/machines/implantchair.dmi and b/icons/obj/machines/implantchair.dmi differ
diff --git a/tgui-next/packages/tgui/interfaces/TelecommsInteraction.js b/tgui-next/packages/tgui/interfaces/TelecommsInteraction.js
new file mode 100644
index 0000000000..a67bfdf987
--- /dev/null
+++ b/tgui-next/packages/tgui/interfaces/TelecommsInteraction.js
@@ -0,0 +1,238 @@
+import { Fragment } from 'inferno';
+import { useBackend } from '../backend';
+import { toFixed } from 'common/math';
+import { RADIO_CHANNELS } from '../constants';
+import { Button, LabeledList, NumberInput, NoticeBox, Section, Input } from '../components';
+
+export const TeleInteract = props => {
+ const { act, data } = useBackend(props);
+ const {
+ notice = "",
+ multitool = false,
+ multitool_buf = null,
+ machine = null,
+ links = [],
+ freq_listening = [],
+ } = data;
+ const {
+ power = false,
+ id = "NULL",
+ network,
+ prefab = false,
+ hidden = false,
+ isrelay = false,
+ isbus = false,
+ } = machine;
+ return (
+