Merge pull request #14011 from Kyep/tgui_turret_control

[TGUI] Turrets & Turret Controls
This commit is contained in:
AffectedArc07
2020-09-15 16:16:44 +01:00
committed by GitHub
9 changed files with 650 additions and 443 deletions
+6 -5
View File
@@ -182,13 +182,14 @@
// TURRETCONTROL
// These two will be changed with TGUI turrets/turretcontrol.
/obj/machinery/turretid/AICtrlClick() //turns off/on Turrets
Topic(src, list("src" = UID(), "command"="enable", "value"="[!enabled]"), 1) // 1 meaning no window (consistency!)
/obj/machinery/turretid/AICtrlClick(mob/living/silicon/ai/user) //turns off/on Turrets
enabled = !enabled
updateTurrets()
/obj/machinery/turretid/AIAltClick() //toggles lethal on turrets
Topic(src, list("src" = UID(), "command"="lethal", "value"="[!lethal]"), 1) // 1 meaning no window (consistency!)
if(lethal_is_configurable)
lethal = !lethal
updateTurrets()
// AIRLOCKS
+23
View File
@@ -510,3 +510,26 @@ proc/get_all_job_icons() //For all existing HUD icons
return rankName
return "Unknown" //Return unknown if none of the above apply
proc/get_accesslist_static_data(num_min_region = REGION_GENERAL, num_max_region = REGION_COMMAND)
var/list/retval
for(var/i in num_min_region to num_max_region)
var/list/accesses = list()
var/list/available_accesses
if(i == REGION_CENTCOMM) // Override necessary, because get_region_accesses(REGION_CENTCOM) returns BOTH CC and crew accesses.
available_accesses = get_all_centcom_access()
else
available_accesses = get_region_accesses(i)
for(var/access in available_accesses)
var/access_desc = (i == REGION_CENTCOMM) ? get_centcom_access_desc(access) : get_access_desc(access)
if (access_desc)
accesses += list(list(
"desc" = replacetext(access_desc, "&nbsp", " "),
"ref" = access,
))
retval += list(list(
"name" = get_region_accesses_name(i),
"regid" = i,
"accesses" = accesses
))
return retval
+16 -36
View File
@@ -6,6 +6,14 @@
// Reasonable defaults, in case someone manually spawns us
var/lasercolor = "r" //Something to do with lasertag turrets, blame Sieve for not adding a comment.
installation = /obj/item/gun/energy/laser/tag/red
targetting_is_configurable = FALSE
lethal_is_configurable = FALSE
shot_delay = 30
iconholder = 1
has_cover = FALSE
always_up = TRUE
raised = TRUE
req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE)
/obj/machinery/porta_turret/tag/red
@@ -18,43 +26,15 @@
icon_state = "[lasercolor]grey_target_prism"
/obj/machinery/porta_turret/tag/weapon_setup(var/obj/item/gun/energy/E)
switch(E.type)
if(/obj/item/gun/energy/laser/tag/blue)
eprojectile = /obj/item/gun/energy/laser/tag/blue
lasercolor = "b"
req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE)
check_arrest = 0
check_records = 0
check_weapons = 1
check_access = 0
check_anomalies = 0
shot_delay = 30
return
if(/obj/item/gun/energy/laser/tag/red)
eprojectile = /obj/item/gun/energy/laser/tag/red
lasercolor = "r"
req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE)
check_arrest = 0
check_records = 0
check_weapons = 1
check_access = 0
check_anomalies = 0
shot_delay = 30
iconholder = 1
/obj/machinery/porta_turret/tag/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 300)
ui.open()
ui.set_auto_update(1)
/obj/machinery/porta_turret/tag/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
var/data[0]
data["access"] = !isLocked(user)
data["locked"] = locked
data["enabled"] = enabled
data["is_lethal"] = 0
/obj/machinery/porta_turret/tag/tgui_data(mob/user)
var/list/data = list(
"locked" = isLocked(user), // does the current user have access?
"on" = enabled, // is turret turned on?
"lethal" = FALSE,
"lethal_is_configurable" = lethal_is_configurable
)
return data
/obj/machinery/porta_turret/tag/update_icon()
+234 -225
View File
@@ -7,18 +7,18 @@
name = "turret"
icon = 'icons/obj/turrets.dmi'
icon_state = "turretCover"
anchored = 1
density = 0
anchored = TRUE
density = FALSE
use_power = IDLE_POWER_USE //this turret uses and requires power
idle_power_usage = 50 //when inactive, this turret takes up constant 50 Equipment power
active_power_usage = 300 //when active, this turret takes up constant 300 Equipment power
power_channel = EQUIP //drains power from the EQUIPMENT channel
armor = list(melee = 50, bullet = 30, laser = 30, energy = 30, bomb = 30, bio = 0, rad = 0, fire = 90, acid = 90)
var/raised = 0 //if the turret cover is "open" and the turret is raised
var/raising= 0 //if the turret is currently opening or closing its cover
var/raised = FALSE //if the turret cover is "open" and the turret is raised
var/raising= FALSE //if the turret is currently opening or closing its cover
var/health = 80 //the turret's health
var/locked = 1 //if the turret's behaviour control access is locked
var/controllock = 0 //if the turret responds to control panels
var/locked = TRUE //if the turret's behaviour control access is locked
var/controllock = FALSE //if the turret responds to control panels. TRUE = does NOT respond
var/installation = /obj/item/gun/energy/gun/turret //the type of weapon installed
var/gun_charge = 0 //the charge of the gun inserted
@@ -31,68 +31,49 @@
var/last_fired = 0 //1: if the turret is cooling down from a shot, 0: turret is ready to fire
var/shot_delay = 15 //1.5 seconds between each shot
var/check_arrest = 1 //checks if the perp is set to arrest
var/check_records = 1 //checks if a security record exists at all
var/check_weapons = 0 //checks if it can shoot people that have a weapon they aren't authorized to have
var/check_access = 1 //if this is active, the turret shoots everything that does not meet the access requirements
var/check_anomalies = 1 //checks if it can shoot at unidentified lifeforms (ie xenos)
var/check_synth = 0 //if active, will shoot at anything not an AI or cyborg
var/ailock = 0 // AI cannot use this
var/targetting_is_configurable = TRUE // if false, you cannot change who this turret attacks via its UI
var/check_arrest = TRUE //checks if the perp is set to arrest
var/check_records = TRUE //checks if a security record exists at all
var/check_weapons = FALSE //checks if it can shoot people that have a weapon they aren't authorized to have
var/check_access = TRUE //if this is active, the turret shoots everything that does not meet the access requirements
var/check_anomalies = TRUE //checks if it can shoot at unidentified lifeforms (ie xenos)
var/check_synth = FALSE //if active, will shoot at anything not an AI or cyborg
var/check_borgs = FALSE //if TRUE, target all cyborgs.
var/ailock = FALSE // if TRUE, AI cannot use this
var/attacked = 0 //if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!)
var/attacked = FALSE //if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!)
var/enabled = 1 //determines if the turret is on
var/lethal = 0 //whether in lethal or stun mode
var/disabled = 0
var/enabled = TRUE //determines if the turret is on
var/lethal = FALSE //whether in lethal or stun mode
var/lethal_is_configurable = TRUE // if false, its lethal setting cannot be changed
var/disabled = FALSE
var/shot_sound //what sound should play when the turret fires
var/eshot_sound //what sound should play when the emagged turret fires
var/datum/effect_system/spark_spread/spark_system //the spark system, used for generating... sparks?
var/wrenching = 0
var/wrenching = FALSE
var/last_target //last target fired at, prevents turrets from erratically firing at all valid targets in range
var/screen = 0 // Screen 0: main control, screen 1: access levels
var/one_access = 0 // Determines if access control is set to req_one_access or req_access
var/one_access = FALSE // Determines if access control is set to req_one_access or req_access
var/region_min = REGION_GENERAL
var/region_max = REGION_COMMAND
var/syndicate = 0 //is the turret a syndicate turret?
var/syndicate = FALSE //is the turret a syndicate turret?
var/faction = ""
var/emp_vulnerable = 1 // Can be empd
var/emp_vulnerable = TRUE // Can be empd
var/scan_range = 7
var/always_up = 0 //Will stay active
var/has_cover = 1 //Hides the cover
var/always_up = FALSE //Will stay active
var/has_cover = TRUE //Hides the cover
/obj/machinery/porta_turret/centcom
name = "Centcom Turret"
enabled = 0
ailock = 1
check_synth = 0
check_access = 1
check_arrest = 1
check_records = 1
check_weapons = 1
check_anomalies = 1
/obj/machinery/porta_turret/centcom/pulse
name = "Pulse Turret"
health = 200
enabled = 1
lethal = 1
req_access = list(ACCESS_CENT_COMMANDER)
installation = /obj/item/gun/energy/pulse/turret
/obj/machinery/porta_turret/stationary
ailock = 1
lethal = 1
installation = /obj/item/gun/energy/laser
/obj/machinery/porta_turret/Initialize(mapload)
. = ..()
if(req_access && req_access.len)
req_access.Cut()
req_one_access = list(ACCESS_SECURITY, ACCESS_HEADS)
one_access = 1
one_access = TRUE
//Sets up a spark system
spark_system = new /datum/effect_system/spark_spread
@@ -110,7 +91,7 @@
if(req_one_access && req_one_access.len)
req_one_access.Cut()
req_access = list(ACCESS_CENT_SPECOPS)
one_access = 0
one_access = FALSE
/obj/machinery/porta_turret/proc/setup()
var/obj/item/gun/energy/E = new installation //All energy-based weapons are applicable
@@ -185,152 +166,151 @@ GLOBAL_LIST_EMPTY(turret_icons)
else
icon_state = "turretCover"
/obj/machinery/porta_turret/proc/isLocked(mob/user)
if(ailock && (isrobot(user) || isAI(user)))
to_chat(user, "<span class='notice'>There seems to be a firewall preventing you from accessing this device.</span>")
return 1
if(locked && !(isrobot(user) || isAI(user) || isobserver(user)))
to_chat(user, "<span class='notice'>Access denied.</span>")
return 1
return 0
/obj/machinery/porta_turret/attack_ai(mob/user)
if(isLocked(user))
return
ui_interact(user)
/obj/machinery/porta_turret/attack_ghost(mob/user)
ui_interact(user)
/obj/machinery/porta_turret/attack_hand(mob/user)
if(isLocked(user))
return
ui_interact(user)
/obj/machinery/porta_turret/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 320)
ui.open()
ui.set_auto_update(1)
/obj/machinery/porta_turret/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
var/data[0]
data["access"] = !isLocked(user)
data["screen"] = screen
data["locked"] = locked
data["enabled"] = enabled
data["lethal_control"] = !syndicate ? 1 : 0
data["lethal"] = lethal
if(data["access"] && !syndicate)
var/settings[0]
settings[++settings.len] = list("category" = "Neutralize All Non-Synthetics", "setting" = "check_synth", "value" = check_synth)
settings[++settings.len] = list("category" = "Check Weapon Authorization", "setting" = "check_weapons", "value" = check_weapons)
settings[++settings.len] = list("category" = "Check Security Records", "setting" = "check_records", "value" = check_records)
settings[++settings.len] = list("category" = "Check Arrest Status", "setting" = "check_arrest", "value" = check_arrest)
settings[++settings.len] = list("category" = "Check Access Authorization", "setting" = "check_access", "value" = check_access)
settings[++settings.len] = list("category" = "Check Misc. Lifeforms", "setting" = "check_anomalies", "value" = check_anomalies)
data["settings"] = settings
if(!syndicate)
data["one_access"] = one_access
var/accesses[0]
var/list/access_list = get_all_accesses()
for(var/access in access_list)
var/name = get_access_desc(access)
var/active
if(one_access)
active = (access in req_one_access)
else
active = (access in req_access)
accesses[++accesses.len] = list("name" = name, "active" = active, "number" = access)
data["accesses"] = accesses
return data
/obj/machinery/porta_turret/proc/HasController()
var/area/A = get_area(src)
return A && A.turret_controls.len > 0
/obj/machinery/porta_turret/CanUseTopic(var/mob/user)
/obj/machinery/porta_turret/proc/access_is_configurable()
return targetting_is_configurable && !HasController()
/obj/machinery/porta_turret/proc/isLocked(mob/user)
if(HasController())
to_chat(user, "<span class='notice'>Turrets can only be controlled using the assigned turret controller.</span>")
return STATUS_CLOSE
return TRUE
if(isrobot(user) || isAI(user))
if(ailock)
to_chat(user, "<span class='notice'>There seems to be a firewall preventing you from accessing this device.</span>")
return TRUE
else
return FALSE
if(isobserver(user))
if(user.can_admin_interact())
return FALSE
else
return TRUE
if(locked)
return TRUE
return FALSE
if(isLocked(user))
return STATUS_CLOSE
/obj/machinery/porta_turret/attack_ai(mob/user)
tgui_interact(user)
if(!anchored)
to_chat(usr, "<span class='notice'>\The [src] has to be secured first!</span>")
return STATUS_CLOSE
/obj/machinery/porta_turret/attack_ghost(mob/user)
tgui_interact(user)
return ..()
/obj/machinery/porta_turret/attack_hand(mob/user)
tgui_interact(user)
/obj/machinery/porta_turret/Topic(href, href_list, var/nowindow = 0)
if(..())
return 1
if(href_list["command"] && href_list["value"])
var/value = text2num(href_list["value"])
if(href_list["command"] == "enable")
enabled = value
else if(syndicate)
return 1
else if(href_list["command"] == "screen")
screen = value
else if(href_list["command"] == "lethal")
lethal = value
else if(href_list["command"] == "check_synth")
check_synth = value
else if(href_list["command"] == "check_weapons")
check_weapons = value
else if(href_list["command"] == "check_records")
check_records = value
else if(href_list["command"] == "check_arrest")
check_arrest = value
else if(href_list["command"] == "check_access")
check_access = value
else if(href_list["command"] == "check_anomalies")
check_anomalies = value
if(!syndicate)
if(href_list["one_access"])
toggle_one_access(href_list["one_access"])
if(href_list["access"])
toggle_access(href_list["access"])
return 1
/obj/machinery/porta_turret/proc/toggle_one_access(var/access)
one_access = text2num(access)
if(one_access == 1)
req_one_access = req_access.Copy()
req_access.Cut()
else if(one_access == 0)
req_access = req_one_access.Copy()
req_one_access.Cut()
/obj/machinery/porta_turret/proc/toggle_access(var/access)
var/required = text2num(access)
if(!(required in get_all_accesses()))
/obj/machinery/porta_turret/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
if(HasController())
to_chat(user, "<span class='notice'>[src] can only be controlled using the assigned turret controller.</span>")
return
if(!anchored)
to_chat(user, "<span class='notice'>[src] has to be secured first!</span>")
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "PortableTurret", name, 500, access_is_configurable() ? 800 : 400)
ui.open()
if(one_access)
if((required in req_one_access))
req_one_access -= required
else
req_one_access += required
else
if((required in req_access))
req_access -= required
else
req_access += required
/obj/machinery/porta_turret/tgui_data(mob/user)
var/list/data = list(
"locked" = isLocked(user), // does the current user have access?
"on" = enabled,
"targetting_is_configurable" = targetting_is_configurable, // If false, targetting settings don't show up
"lethal" = lethal,
"lethal_is_configurable" = lethal_is_configurable,
"check_weapons" = check_weapons,
"neutralize_noaccess" = check_access,
"one_access" = one_access,
"selectedAccess" = one_access ? req_one_access : req_access,
"access_is_configurable" = access_is_configurable(),
"neutralize_norecord" = check_records,
"neutralize_criminals" = check_arrest,
"neutralize_all" = check_synth,
"neutralize_unidentified" = check_anomalies,
"neutralize_cyborgs" = check_borgs
)
return data
/obj/machinery/porta_turret/tgui_static_data(mob/user)
var/list/data = list()
data["regions"] = get_accesslist_static_data(region_min, region_max)
return data
/obj/machinery/porta_turret/tgui_act(action, params)
if (..())
return
if(isLocked(usr))
return
. = TRUE
switch(action)
if("power")
enabled = !enabled
if("lethal")
if(lethal_is_configurable)
lethal = !lethal
if(targetting_is_configurable)
switch(action)
if("authweapon")
check_weapons = !check_weapons
if("authaccess")
check_access = !check_access
if("authnorecord")
check_records = !check_records
if("autharrest")
check_arrest = !check_arrest
if("authxeno")
check_anomalies = !check_anomalies
if("authsynth")
check_synth = !check_synth
if("authborgs")
check_borgs = !check_borgs
if("set")
var/access = text2num(params["access"])
if(one_access)
if(!(access in req_one_access))
req_one_access += access
else
req_one_access -= access
else
if(!(access in req_access))
req_access += access
else
req_access -= access
if(access_is_configurable())
switch(action)
if("grant_region")
var/region = text2num(params["region"])
if(isnull(region))
return
if(one_access)
req_one_access |= get_region_accesses(region)
else
req_access |= get_region_accesses(region)
if("deny_region")
var/region = text2num(params["region"])
if(isnull(region))
return
if(one_access)
req_one_access -= get_region_accesses(region)
else
req_access -= get_region_accesses(region)
if("clear_all")
if(one_access)
req_one_access = list()
else
req_access = list()
if("grant_all")
if(one_access)
req_one_access = get_all_accesses()
else
req_access = get_all_accesses()
if("one_access")
if(one_access)
req_one_access = list()
else
req_access = list()
one_access = !one_access
/obj/machinery/porta_turret/power_change()
if(powered() || !use_power)
@@ -379,23 +359,25 @@ GLOBAL_LIST_EMPTY(turret_icons)
"<span class='notice'>You begin [anchored ? "un" : ""]securing the turret.</span>" \
)
wrenching = 1
wrenching = TRUE
if(do_after(user, 50 * I.toolspeed, target = src))
//This code handles moving the turret around. After all, it's a portable turret!
if(!anchored)
playsound(loc, I.usesound, 100, 1)
anchored = 1
anchored = TRUE
update_icon()
to_chat(user, "<span class='notice'>You secure the exterior bolts on the turret.</span>")
else if(anchored)
playsound(loc, I.usesound, 100, 1)
anchored = 0
anchored = FALSE
to_chat(user, "<span class='notice'>You unsecure the exterior bolts on the turret.</span>")
update_icon()
wrenching = 0
wrenching = FALSE
else if(istype(I, /obj/item/card/id) || istype(I, /obj/item/pda))
if(allowed(user))
if(HasController())
to_chat(user, "<span class='notice'>Turrets regulated by a nearby turret controller are not unlockable.</span>")
else if(allowed(user))
locked = !locked
to_chat(user, "<span class='notice'>Controls are now [locked ? "locked" : "unlocked"].</span>")
updateUsrDialog()
@@ -409,9 +391,9 @@ GLOBAL_LIST_EMPTY(turret_icons)
playsound(src.loc, 'sound/weapons/smash.ogg', 60, 1)
if(I.force * 0.5 > 1) //if the force of impact dealt at least 1 damage, the turret gets pissed off
if(!attacked && !emagged)
attacked = 1
attacked = TRUE
spawn(60)
attacked = 0
attacked = FALSE
..()
@@ -445,12 +427,12 @@ GLOBAL_LIST_EMPTY(turret_icons)
if(user)
to_chat(user, "<span class='warning'>You short out [src]'s threat assessment circuits.</span>")
visible_message("[src] hums oddly...")
emagged = 1
emagged = TRUE
iconholder = 1
controllock = 1
enabled = 0 //turns off the turret temporarily
controllock = TRUE
enabled = FALSE //turns off the turret temporarily
sleep(60) //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit
enabled = 1 //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here
enabled = TRUE //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here
/obj/machinery/porta_turret/take_damage(force)
if(!raised && !raising)
@@ -470,9 +452,9 @@ GLOBAL_LIST_EMPTY(turret_icons)
if(enabled)
if(!attacked && !emagged)
attacked = 1
attacked = TRUE
spawn(60)
attacked = 0
attacked = FALSE
..()
@@ -489,12 +471,12 @@ GLOBAL_LIST_EMPTY(turret_icons)
check_access = prob(20) // check_access is a pretty big deal, so it's least likely to get turned on
check_anomalies = prob(50)
if(prob(5))
emagged = 1
emagged = TRUE
enabled=0
spawn(rand(60,600))
spawn(rand(60, 600))
if(!enabled)
enabled=1
enabled = TRUE
..()
@@ -585,8 +567,8 @@ GLOBAL_LIST_EMPTY(turret_icons)
if(get_turf(L) == get_turf(src))
return TURRET_NOT_TARGET
if(!emagged && !syndicate && (issilicon(L) || isbot(L))) // Don't target silica
return TURRET_NOT_TARGET
if(!emagged && !syndicate && (issilicon(L) || isbot(L)))
return (check_borgs && isrobot(L)) ? TURRET_PRIORITY_TARGET : TURRET_NOT_TARGET
if(L.stat && !emagged) //if the perp is dead/dying, no need to bother really
return TURRET_NOT_TARGET //move onto next potential victim!
@@ -643,7 +625,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
return
if(stat & BROKEN)
return
set_raised_raising(raised, 1)
set_raised_raising(raised, TRUE)
playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1)
update_icon()
@@ -653,7 +635,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
sleep(10)
qdel(flick_holder)
set_raised_raising(1, 0)
set_raised_raising(TRUE, FALSE)
update_icon()
/obj/machinery/porta_turret/proc/popDown() //pops the turret down
@@ -664,7 +646,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
return
if(stat & BROKEN)
return
set_raised_raising(raised, 1)
set_raised_raising(raised, TRUE)
playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1)
update_icon()
@@ -674,7 +656,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
sleep(10)
qdel(flick_holder)
set_raised_raising(0, 0)
set_raised_raising(FALSE, FALSE)
update_icon()
/obj/machinery/porta_turret/on_assess_perp(mob/living/carbon/human/perp)
@@ -739,6 +721,27 @@ GLOBAL_LIST_EMPTY(turret_icons)
A.throw_at(target, scan_range, 1)
return A
/obj/machinery/porta_turret/centcom
name = "Centcom Turret"
enabled = FALSE
ailock = TRUE
check_synth = FALSE
check_access = TRUE
check_arrest = TRUE
check_records = TRUE
check_weapons = TRUE
check_anomalies = TRUE
region_max = REGION_CENTCOMM // Non-turretcontrolled turrets at CC can have their access customized to check for CC accesses.
/obj/machinery/porta_turret/centcom/pulse
name = "Pulse Turret"
health = 200
enabled = TRUE
lethal = TRUE
lethal_is_configurable = FALSE
req_access = list(ACCESS_CENT_COMMANDER)
installation = /obj/item/gun/energy/pulse/turret
/datum/turret_checks
var/enabled
var/lethal
@@ -748,6 +751,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
var/check_arrest
var/check_weapons
var/check_anomalies
var/check_borgs
var/ailock
/obj/machinery/porta_turret/proc/setState(var/datum/turret_checks/TC)
@@ -763,6 +767,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
check_arrest = TC.check_arrest
check_weapons = TC.check_weapons
check_anomalies = TC.check_anomalies
check_borgs = TC.check_borgs
ailock = TC.ailock
power_change()
@@ -791,7 +796,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
if(istype(I, /obj/item/wrench) && !anchored)
playsound(loc, I.usesound, 100, 1)
to_chat(user, "<span class='notice'>You secure the external bolts.</span>")
anchored = 1
anchored = TRUE
build_step = 1
return
@@ -816,7 +821,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
else if(istype(I, /obj/item/wrench))
playsound(loc, I.usesound, 75, 1)
to_chat(user, "<span class='notice'>You unfasten the external bolts.</span>")
anchored = 0
anchored = FALSE
build_step = 0
return
@@ -841,8 +846,10 @@ GLOBAL_LIST_EMPTY(turret_icons)
gun_charge = E.cell.charge //the gun's charge is stored in gun_charge
to_chat(user, "<span class='notice'>You add [I] to the turret.</span>")
if(istype(installation, /obj/item/gun/energy/laser/tag/blue) || istype(installation, /obj/item/gun/energy/laser/tag/red))
target_type = /obj/machinery/porta_turret/tag
if(istype(E, /obj/item/gun/energy/laser/tag/blue))
target_type = /obj/machinery/porta_turret/tag/blue
else if(istype(E, /obj/item/gun/energy/laser/tag/red))
target_type = /obj/machinery/porta_turret/tag/red
else
target_type = /obj/machinery/porta_turret
@@ -934,7 +941,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
Turret.name = finish_name
Turret.installation = installation
Turret.gun_charge = gun_charge
Turret.enabled = 0
Turret.enabled = FALSE
Turret.setup()
qdel(src)
@@ -981,25 +988,27 @@ GLOBAL_LIST_EMPTY(turret_icons)
var/icon_state_active = "syndieturret1"
var/icon_state_destroyed = "syndieturret2"
syndicate = 1
syndicate = TRUE
installation = null
always_up = 1
always_up = TRUE
use_power = NO_POWER_USE
has_cover = 0
raised = 1
has_cover = FALSE
raised = TRUE
scan_range = 9
faction = "syndicate"
emp_vulnerable = 0
emp_vulnerable = FALSE
lethal = 1
check_arrest = 0
check_records = 0
check_weapons = 0
check_access = 0
check_anomalies = 1
check_synth = 1
ailock = 1
lethal = TRUE
lethal_is_configurable = FALSE
targetting_is_configurable = FALSE
check_arrest = FALSE
check_records = FALSE
check_weapons = FALSE
check_access = FALSE
check_anomalies = TRUE
check_synth = TRUE
ailock = TRUE
var/area/syndicate_depot/core/depotarea
/obj/machinery/porta_turret/syndicate/die()
@@ -1018,7 +1027,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
if(req_one_access && req_one_access.len)
req_one_access.Cut()
req_access = list(ACCESS_SYNDICATE)
one_access = 0
one_access = FALSE
/obj/machinery/porta_turret/syndicate/update_icon()
if(stat & BROKEN)
+102 -102
View File
@@ -11,51 +11,56 @@
desc = "Used to control a room's automated defenses."
icon = 'icons/obj/machines/turret_control.dmi'
icon_state = "control_standby"
anchored = 1
density = 0
anchored = TRUE
density = FALSE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/enabled = 0
var/lethal = 0
var/locked = 1
var/enabled = FALSE
var/lethal = FALSE
var/lethal_is_configurable = TRUE
var/locked = TRUE
var/area/control_area //can be area name, path or nothing.
var/check_arrest = 1 //checks if the perp is set to arrest
var/check_records = 1 //checks if a security record exists at all
var/check_weapons = 0 //checks if it can shoot people that have a weapon they aren't authorized to have
var/check_access = 1 //if this is active, the turret shoots everything that does not meet the access requirements
var/check_anomalies = 1 //checks if it can shoot at unidentified lifeforms (ie xenos)
var/check_synth = 0 //if active, will shoot at anything not an AI or cyborg
var/ailock = 0 //Silicons cannot use this
var/targetting_is_configurable = TRUE // if false, you cannot change who this turret attacks via its UI
var/check_arrest = TRUE //checks if the perp is set to arrest
var/check_records = TRUE //checks if a security record exists at all
var/check_weapons = FALSE //checks if it can shoot people that have a weapon they aren't authorized to have
var/check_access = TRUE //if this is active, the turret shoots everything that does not meet the access requirements
var/check_anomalies = TRUE //checks if it can shoot at unidentified lifeforms (ie xenos)
var/check_synth = FALSE //if active, will shoot at anything not an AI or cyborg
var/check_borgs = FALSE //if TRUE, target all cyborgs.
var/ailock = FALSE //Silicons cannot use this
var/syndicate = 0
var/syndicate = FALSE
var/faction = "" // Turret controls can only access turrets that are in the same faction
req_access = list(ACCESS_AI_UPLOAD)
/obj/machinery/turretid/stun
enabled = 1
enabled = TRUE
icon_state = "control_stun"
/obj/machinery/turretid/lethal
enabled = 1
lethal = 1
enabled = TRUE
lethal = TRUE
icon_state = "control_kill"
/obj/machinery/turretid/syndicate
enabled = 1
lethal = 1
enabled = TRUE
lethal = TRUE
lethal_is_configurable = FALSE
targetting_is_configurable = FALSE
icon_state = "control_kill"
lethal = 1
check_arrest = 0
check_records = 0
check_weapons = 0
check_access = 0
check_anomalies = 1
check_synth = 1
ailock = 1
check_arrest = FALSE
check_records = FALSE
check_weapons = FALSE
check_access = FALSE
check_anomalies = TRUE
check_synth = TRUE
check_borgs = FALSE
ailock = TRUE
syndicate = 1
syndicate = TRUE
faction = "syndicate"
req_access = list(ACCESS_SYNDICATE_LEADER)
@@ -87,21 +92,23 @@
return
/obj/machinery/turretid/proc/isLocked(mob/user)
if(ailock && (isrobot(user) || isAI(user)))
to_chat(user, "<span class='notice'>There seems to be a firewall preventing you from accessing this device.</span>")
return 1
if(isrobot(user) || isAI(user))
if(ailock)
to_chat(user, "<span class='notice'>There seems to be a firewall preventing you from accessing this device.</span>")
return TRUE
else
return FALSE
if(locked && !(isrobot(user) || isAI(user) || isobserver(user)))
to_chat(user, "<span class='notice'>Access denied.</span>")
return 1
if(isobserver(user))
if(user.can_admin_interact())
return FALSE
else
return TRUE
return 0
if(locked)
return TRUE
/obj/machinery/turretid/CanUseTopic(mob/user)
if(isLocked(user))
return STATUS_CLOSE
return ..()
return FALSE
/obj/machinery/turretid/attackby(obj/item/W, mob/user)
if(stat & BROKEN)
@@ -120,89 +127,82 @@
/obj/machinery/turretid/emag_act(user as mob)
if(!emagged)
to_chat(user, "<span class='danger'>You short out the turret controls' access analysis module.</span>")
emagged = 1
locked = 0
ailock = 0
emagged = TRUE
locked = FALSE
ailock = FALSE
return
/obj/machinery/turretid/attack_ai(mob/user as mob)
if(isLocked(user))
return
ui_interact(user)
tgui_interact(user)
/obj/machinery/turretid/attack_ghost(mob/user as mob)
ui_interact(user)
tgui_interact(user)
/obj/machinery/turretid/attack_hand(mob/user as mob)
if(isLocked(user))
return
tgui_interact(user)
ui_interact(user)
/obj/machinery/turretid/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/turretid/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 350)
ui = new(user, src, ui_key, "PortableTurret", name, 500, 400)
ui.open()
ui.set_auto_update(1)
/obj/machinery/turretid/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
var/data[0]
data["access"] = !isLocked(user)
data["locked"] = locked
data["enabled"] = enabled
data["lethal_control"] = !syndicate ? 1 : 0
data["lethal"] = lethal
if(data["access"] && !syndicate)
var/settings[0]
settings[++settings.len] = list("category" = "Neutralize All Non-Synthetics", "setting" = "check_synth", "value" = check_synth)
settings[++settings.len] = list("category" = "Check Weapon Authorization", "setting" = "check_weapons", "value" = check_weapons)
settings[++settings.len] = list("category" = "Check Security Records", "setting" = "check_records", "value" = check_records)
settings[++settings.len] = list("category" = "Check Arrest Status", "setting" = "check_arrest", "value" = check_arrest)
settings[++settings.len] = list("category" = "Check Access Authorization", "setting" = "check_access", "value" = check_access)
settings[++settings.len] = list("category" = "Check Misc. Lifeforms", "setting" = "check_anomalies", "value" = check_anomalies)
data["settings"] = settings
/obj/machinery/turretid/tgui_data(mob/user)
var/list/data = list(
"locked" = isLocked(user), // does the current user have access?
"on" = enabled,
"targetting_is_configurable" = targetting_is_configurable, // If false, targetting settings don't show up
"lethal" = lethal,
"lethal_is_configurable" = lethal_is_configurable,
"check_weapons" = check_weapons,
"neutralize_noaccess" = check_access,
"one_access" = FALSE,
"selectedAccess" = list(),
"access_is_configurable" = FALSE,
"neutralize_norecord" = check_records,
"neutralize_criminals" = check_arrest,
"neutralize_all" = check_synth,
"neutralize_unidentified" = check_anomalies,
"neutralize_cyborgs" = check_borgs
)
return data
/obj/machinery/turretid/Topic(href, href_list, var/nowindow = 0)
if(..())
return 1
/obj/machinery/turretid/tgui_act(action, params)
if (..())
return
if(isLocked(usr))
return 1
if(href_list["command"] && href_list["value"])
var/value = text2num(href_list["value"])
if(href_list["command"] == "enable")
enabled = value
else if(syndicate)
return 1
else if(href_list["command"] == "lethal")
lethal = value
else if(href_list["command"] == "check_synth")
check_synth = value
else if(href_list["command"] == "check_weapons")
check_weapons = value
else if(href_list["command"] == "check_records")
check_records = value
else if(href_list["command"] == "check_arrest")
check_arrest = value
else if(href_list["command"] == "check_access")
check_access = value
else if(href_list["command"] == "check_anomalies")
check_anomalies = value
updateTurrets()
return 1
return
. = TRUE
switch(action)
if("power")
enabled = !enabled
if("lethal")
if(lethal_is_configurable)
lethal = !lethal
if(targetting_is_configurable)
switch(action)
if("authweapon")
check_weapons = !check_weapons
if("authaccess")
check_access = !check_access
if("authnorecord")
check_records = !check_records
if("autharrest")
check_arrest = !check_arrest
if("authxeno")
check_anomalies = !check_anomalies
if("authsynth")
check_synth = !check_synth
if("authborgs")
check_borgs = !check_borgs
updateTurrets()
/obj/machinery/turretid/proc/updateTurrets()
var/datum/turret_checks/TC = new
TC.enabled = enabled
TC.lethal = lethal
TC.check_synth = check_synth
TC.check_borgs = check_borgs
TC.check_access = check_access
TC.check_records = check_records
TC.check_arrest = check_arrest
-72
View File
@@ -1,72 +0,0 @@
<div class="item">
Behaviour controls are {{:data.locked ? "locked" : "unlocked"}}.
</div>
<br>
{{if data.access}}
{{if !data.screen}}
<div class="item">
<div class="itemLabelWide">
Turret Status:
</div>
<div class="itemContentNarrow">
{{:helper.link('Enabled', null, {'command' : 'enable', 'value' : 1}, data.enabled ?'redButton' : null)}}
{{:helper.link('Disabled',null, {'command' : 'enable', 'value' : 0}, !data.enabled ? 'selected' : null)}}
</div>
</div>
{{if data.accesses}}
<div class="item">
<div class="itemLabelWide">
Required Access:
</div>
<div class="itemContentNarrow">
{{:helper.link('Modify', null, {'command' : 'screen', 'value' : 1})}}
</div>
</div>
{{/if}}
{{if data.lethal_control}}
<div class="item">
<div class="itemLabelWide">
Lethal Mode:
</div>
<div class="itemContentNarrow">
{{:helper.link('On', null, {'command' : 'lethal', 'value' : 1}, data.lethal ?'redButton' : null)}}
{{:helper.link('Off',null, {'command' : 'lethal', 'value' : 0}, !data.lethal ? 'selected' : null)}}
</div>
</div>
{{/if}}
{{for data.settings}}
<div class="item">
<div class="itemLabelWide">
{{:value.category}}
</div>
<div class="itemContentNarrow">
{{:helper.link('On', null, {'command' : value.setting, 'value' : 1}, value.value ? 'selected' : null)}}
{{:helper.link('Off',null, {'command' : value.setting, 'value' : 0}, !value.value ? 'selected' : null)}}
</div>
</div>
{{/for}}
{{else}}
<div class="item">
<div class="itemLabelWide">
Turret Settings:
</div>
<div class="itemContentNarrow">
{{:helper.link('Modify', null, {'command' : 'screen', 'value' : 0})}}
</div>
</div>
<div class="item">
<div class="itemLabelWide">
Access Type:
</div>
<div class="itemContentNarrow">
{{:helper.link('All', null, {'one_access' : 0}, !data.one_access ? 'selected' : null)}}
{{:helper.link('One', null, {'one_access' : 1}, data.one_access ? 'selected' : null)}}
</div>
</div>
<h3>Select Access</h3>
{{for data.accesses}}
{{:helper.link(value.name, null, {'access' : value.number}, null, value.active ? 'selected' : null)}}
{{/for}}
{{/if}}
{{/if}}
@@ -0,0 +1,134 @@
import { Fragment } from 'inferno';
import { useBackend } from '../backend';
import { Button, LabeledList, NoticeBox, Section } from '../components';
import { Window } from '../layouts';
import { AccessList } from './common/AccessList';
export const PortableTurret = (props, context) => {
const { act, data } = useBackend(context);
const {
locked,
on,
lethal,
lethal_is_configurable,
targetting_is_configurable,
check_weapons,
neutralize_noaccess,
access_is_configurable,
regions,
selectedAccess,
one_access,
neutralize_norecord,
neutralize_criminals,
neutralize_all,
neutralize_unidentified,
neutralize_cyborgs,
} = data;
return (
<Window>
<Window.Content scrollable>
<NoticeBox>
Swipe an ID card to {locked ? 'unlock' : 'lock'} this interface.
</NoticeBox>
<Section>
<LabeledList>
<LabeledList.Item label="Status">
<Button
icon={on ? 'power-off' : 'times'}
content={on ? 'On' : 'Off'}
selected={on}
disabled={locked}
onClick={() => act('power')} />
</LabeledList.Item>
{!!lethal_is_configurable && (
<LabeledList.Item label="Lethals">
<Button
icon={lethal ? 'exclamation-triangle' : 'times'}
content={lethal ? 'On' : 'Off'}
color={lethal ? "bad" : ""}
disabled={locked}
onClick={() => act('lethal')} />
</LabeledList.Item>
)}
{!!access_is_configurable && (
<LabeledList.Item label="One Access Mode">
<Button
icon={one_access ? 'address-card' : 'exclamation-triangle'}
content={one_access ? 'On' : 'Off'}
selected={one_access}
disabled={locked}
onClick={() => act('one_access')} />
</LabeledList.Item>
)}
</LabeledList>
</Section>
{!!targetting_is_configurable && (
<Fragment>
<Section title="Humanoid Targets">
<Button.Checkbox
fluid
checked={neutralize_criminals}
content="Wanted Criminals"
disabled={locked}
onClick={() => act('autharrest')} />
<Button.Checkbox
fluid
checked={neutralize_norecord}
content="No Sec Record"
disabled={locked}
onClick={() => act('authnorecord')} />
<Button.Checkbox
fluid
checked={check_weapons}
content="Unauthorized Weapons"
disabled={locked}
onClick={() => act('authweapon')} />
<Button.Checkbox
fluid
checked={neutralize_noaccess}
content="Unauthorized Access"
disabled={locked}
onClick={() => act('authaccess')} />
</Section>
<Section title="Other Targets">
<Button.Checkbox
fluid
checked={neutralize_unidentified}
content="Unidentified Lifesigns (Xenos, Animals, Etc)"
disabled={locked}
onClick={() => act('authxeno')} />
<Button.Checkbox
fluid
checked={neutralize_cyborgs}
content="Cyborgs"
disabled={locked}
onClick={() => act('authborgs')} />
<Button.Checkbox
fluid
checked={neutralize_all}
content="All Non-Synthetics"
disabled={locked}
onClick={() => act('authsynth')} />
</Section>
</Fragment>
)}
{!!access_is_configurable && (
<AccessList
accesses={regions}
selectedList={selectedAccess}
accessMod={ref => act('set', {
access: ref,
})}
grantAll={() => act('grant_all')}
denyAll={() => act('clear_all')}
grantDep={ref => act('grant_region', {
region: ref,
})}
denyDep={ref => act('deny_region', {
region: ref,
})} />
)}
</Window.Content>
</Window>
);
};
@@ -0,0 +1,132 @@
import { sortBy } from 'common/collections';
import { Fragment } from 'inferno';
import { useLocalState } from '../../backend';
import { Button, Flex, Grid, Section, Tabs } from '../../components';
const diffMap = {
0: {
icon: 'times-circle',
color: 'bad',
},
1: {
icon: 'stop-circle',
color: null,
},
2: {
icon: 'check-circle',
color: 'good',
},
};
export const AccessList = (props, context) => {
const {
accesses = [],
selectedList = [],
accessMod,
grantAll,
denyAll,
grantDep,
denyDep,
} = props;
const [
selectedAccessName,
setSelectedAccessName,
] = useLocalState(context, 'accessName', accesses[0]?.name);
const selectedAccess = accesses
.find(access => access.name === selectedAccessName);
const selectedAccessEntries = sortBy(
entry => entry.desc,
)(selectedAccess?.accesses || []);
const checkAccessIcon = accesses => {
let oneAccess = false;
let oneInaccess = false;
for (let element of accesses) {
if (selectedList.includes(element.ref)) {
oneAccess = true;
}
else {
oneInaccess = true;
}
}
if (!oneAccess && oneInaccess) {
return 0;
}
else if (oneAccess && oneInaccess) {
return 1;
}
else {
return 2;
}
};
return (
<Section
title="Access"
buttons={(
<Fragment>
<Button
icon="check-double"
content="Select All"
color="good"
onClick={() => grantAll()} />
<Button
icon="undo"
content="Deselect All"
color="bad"
onClick={() => denyAll()} />
</Fragment>
)}>
<Flex>
<Flex.Item>
<Tabs vertical>
{accesses.map(access => {
const entries = access.accesses || [];
const icon = diffMap[checkAccessIcon(entries)].icon;
const color = diffMap[checkAccessIcon(entries)].color;
return (
<Tabs.Tab
key={access.name}
altSelection
color={color}
icon={icon}
selected={access.name === selectedAccessName}
onClick={() => setSelectedAccessName(access.name)}>
{access.name}
</Tabs.Tab>
);
})}
</Tabs>
</Flex.Item>
<Flex.Item grow={1}>
<Grid>
<Grid.Column mr={0}>
<Button
fluid
icon="check"
content="Select All In Region"
color="good"
onClick={() => grantDep(selectedAccess.regid)} />
</Grid.Column>
<Grid.Column ml={0}>
<Button
fluid
icon="times"
content="Deselect All In Region"
color="bad"
onClick={() => denyDep(selectedAccess.regid)} />
</Grid.Column>
</Grid>
{selectedAccessEntries.map(entry => (
<Button.Checkbox
fluid
key={entry.desc}
content={entry.desc}
checked={selectedList.includes(entry.ref)}
onClick={() => accessMod(entry.ref)} />
))}
</Flex.Item>
</Flex>
</Section>
);
};
File diff suppressed because one or more lines are too long