From b28f791f8f85e3f0677a36971f2ce2f1802f230f Mon Sep 17 00:00:00 2001 From: Markolie Date: Sun, 1 Mar 2015 02:10:32 +0100 Subject: [PATCH] (Porta) turret update, map area update --- code/__HELPERS/lists.dm | 6 - code/_onclick/ai.dm | 4 +- code/defines/procs/records.dm | 48 + code/game/area/Dynamic areas.dm | 5 +- code/game/jobs/access.dm | 9 + code/game/machinery/machinery.dm | 48 + code/game/machinery/portable_tag_turret.dm | 124 ++ code/game/machinery/portable_turret.dm | 1453 ++++++------- code/game/machinery/turret_control.dm | 220 ++ code/game/machinery/turrets.dm | 111 +- code/modules/mob/mob_helpers.dm | 7 + code/modules/nano/nanoui.dm | 5 +- code/modules/projectiles/gun.dm | 7 + .../projectiles/guns/energy/nuclear.dm | 35 + icons/obj/machines/turret_control.dmi | Bin 0 -> 700 bytes maps/cyberiad.dmm | 1877 +++++++++++------ nano/css/shared.css | 23 +- nano/templates/omni_filter.tmpl | 144 +- nano/templates/omni_mixer.tmpl | 8 +- nano/templates/turret_control.tmpl | 41 + paradise.dme | 3 + 21 files changed, 2466 insertions(+), 1712 deletions(-) create mode 100644 code/defines/procs/records.dm create mode 100644 code/game/machinery/portable_tag_turret.dm create mode 100644 code/game/machinery/turret_control.dm create mode 100644 icons/obj/machines/turret_control.dmi create mode 100644 nano/templates/turret_control.tmpl diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 8e6118f6f46..7cad8ab9d69 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -393,12 +393,6 @@ proc/listclearnulls(list/list) //world.log << " output: [out.len]" return reverselist(out) -/proc/find_record(field, value, list/L) - for(var/datum/data/record/R in L) - if(R.fields[field] == value) - return R - - /proc/dd_sortedObjectList(var/list/L, var/cache=list()) if(L.len < 2) return L diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index a7dcaff4fb1..96709e751f7 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -159,7 +159,7 @@ Topic("breaker=1", list("breaker"="1"), 0) // 0 meaning no window (consistency! wait...) /obj/machinery/turretid/AICtrlClick() //turns off/on Turrets - Topic("toggleOn", list("toggleOn" = 1), 1) // 1 meaning no window (consistency!) + Topic(src, list("src"= "\ref[src]", "command"="enable", "value"="[!enabled]"), 1) // 1 meaning no window (consistency!) /atom/proc/AIAltClick(var/atom/A) AltClick(A) @@ -178,7 +178,7 @@ return /obj/machinery/turretid/AIAltClick() //toggles lethal on turrets - Topic("toggleLethal", list("toggleLethal" = 1), 1) // 1 meaning no window (consistency!) + Topic(src, list("src"= "\ref[src]", "command"="lethal", "value"="[!lethal]"), 1) // 1 meaning no window (consistency!) /atom/proc/AIMiddleClick() return diff --git a/code/defines/procs/records.dm b/code/defines/procs/records.dm new file mode 100644 index 00000000000..4e9fbcc9afc --- /dev/null +++ b/code/defines/procs/records.dm @@ -0,0 +1,48 @@ +/proc/CreateGeneralRecord() + var/mob/living/carbon/human/dummy = new() + dummy.mind = new() + var/icon/front = new(get_id_photo(dummy), dir = SOUTH) + var/icon/side = new(get_id_photo(dummy), dir = WEST) + var/datum/data/record/G = new /datum/data/record() + G.fields["name"] = "New Record" + G.fields["id"] = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6)) + G.fields["rank"] = "Unassigned" + G.fields["real_rank"] = "Unassigned" + G.fields["sex"] = "Male" + G.fields["age"] = "Unknown" + G.fields["fingerprint"] = "Unknown" + G.fields["p_stat"] = "Active" + G.fields["m_stat"] = "Stable" + G.fields["species"] = "Human" + G.fields["home_system"] = "Unknown" + G.fields["citizenship"] = "Unknown" + G.fields["faction"] = "Unknown" + G.fields["religion"] = "Unknown" + G.fields["photo_front"] = front + G.fields["photo_side"] = side + data_core.general += G + + del(dummy) + return G + +/proc/CreateSecurityRecord(var/name as text, var/id as text) + var/datum/data/record/R = new /datum/data/record() + R.fields["name"] = name + R.fields["id"] = id + R.name = text("Security Record #[id]") + R.fields["criminal"] = "None" + R.fields["mi_crim"] = "None" + R.fields["mi_crim_d"] = "No minor crime convictions." + R.fields["ma_crim"] = "None" + R.fields["ma_crim_d"] = "No major crime convictions." + R.fields["notes"] = "No notes." + data_core.security += R + return R + +/proc/find_security_record(field, value) + return find_record(field, value, data_core.security) + +/proc/find_record(field, value, list/L) + for(var/datum/data/record/R in L) + if(R.fields[field] == value) + return R diff --git a/code/game/area/Dynamic areas.dm b/code/game/area/Dynamic areas.dm index 9d6010f29b4..7927b72e7ad 100644 --- a/code/game/area/Dynamic areas.dm +++ b/code/game/area/Dynamic areas.dm @@ -24,15 +24,18 @@ match_tag = "arrivals" match_width = 5 match_height = 4 + use_power = 0 /area/dynamic/source/lobby_russian name = "\improper Russian Lounge" match_tag = "arrivals" match_width = 5 match_height = 4 + use_power = 0 /area/dynamic/source/lobby_disco name = "\improper Disco Lounge" match_tag = "arrivals" match_width = 5 - match_height = 4 \ No newline at end of file + match_height = 4 + use_power = 0 \ No newline at end of file diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index f9219462ad2..f318b5311ae 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -508,6 +508,15 @@ return assignment return "Unknown" + +proc/GetIdCard(var/mob/living/carbon/human/H) + if(H.wear_id) + var/id = H.wear_id.GetID() + if(id) + return id + if(H.get_active_hand()) + var/obj/item/I = H.get_active_hand() + return I.GetID() proc/FindNameFromID(var/mob/living/carbon/human/H) ASSERT(istype(H)) diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index e30776ef6b4..519fb09b0cd 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -401,3 +401,51 @@ Class Procs: I.loc = loc del(src) return 1 + +/obj/machinery/proc/on_assess_perp(mob/living/carbon/human/perp) + return 0 + +/obj/machinery/proc/is_assess_emagged() + return emagged + +/obj/machinery/proc/assess_perp(mob/living/carbon/human/perp, var/auth_weapons, var/check_records, var/check_arrest) + var/threatcount = 0 //the integer returned + + if(is_assess_emagged()) + return 10 //if emagged, always return 10. + + threatcount += on_assess_perp(perp) + if(threatcount >= 10) + return threatcount + + //Agent cards lower threatlevel. + var/obj/item/weapon/card/id/id = GetIdCard(perp) + if(id && istype(id, /obj/item/weapon/card/id/syndicate)) + threatcount -= 2 + + if(auth_weapons && !src.allowed(perp)) + if(istype(perp.l_hand, /obj/item/weapon/gun) || istype(perp.l_hand, /obj/item/weapon/melee)) + threatcount += 4 + + if(istype(perp.r_hand, /obj/item/weapon/gun) || istype(perp.r_hand, /obj/item/weapon/melee)) + threatcount += 4 + + if(istype(perp.belt, /obj/item/weapon/gun) || istype(perp.belt, /obj/item/weapon/melee)) + threatcount += 2 + + if(perp.species.name != "Human") //beepsky so racist. + threatcount += 2 + + if(check_records || check_arrest) + var/perpname = perp.name + if(id) + perpname = id.registered_name + + var/datum/data/record/R = find_security_record("name", perpname) + if(check_records && !R) + threatcount += 4 + + if(check_arrest && R && (R.fields["criminal"] == "*Arrest*")) + threatcount += 4 + + return threatcount diff --git a/code/game/machinery/portable_tag_turret.dm b/code/game/machinery/portable_tag_turret.dm new file mode 100644 index 00000000000..c6da942645a --- /dev/null +++ b/code/game/machinery/portable_tag_turret.dm @@ -0,0 +1,124 @@ +#define TURRET_PRIORITY_TARGET 2 +#define TURRET_SECONDARY_TARGET 1 +#define TURRET_NOT_TARGET 0 + +/obj/machinery/porta_turret/tag + // 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/weapon/gun/energy/laser/redtag + +/obj/machinery/porta_turret/tag/red + +/obj/machinery/porta_turret/tag/blue + lasercolor = "b" + installation = /obj/item/weapon/gun/energy/laser/bluetag + +/obj/machinery/porta_turret/tag/New() + ..() + icon_state = "[lasercolor]grey_target_prism" + +/obj/machinery/porta_turret/tag/weapon_setup(var/obj/item/weapon/gun/energy/E) + switch(E.type) + if(/obj/item/weapon/gun/energy/laser/bluetag) + eprojectile = /obj/item/weapon/gun/energy/laser/bluetag + 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 + + if(/obj/item/weapon/gun/energy/laser/redtag) + eprojectile = /obj/item/weapon/gun/energy/laser/redtag + 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) + var/data[0] + data["access"] = !isLocked(user) + data["locked"] = locked + data["enabled"] = enabled + data["is_lethal"] = 0 + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 300) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) + +/obj/machinery/porta_turret/tag/update_icon() + if(!anchored) + icon_state = "turretCover" + return + if(stat & BROKEN) + icon_state = "[lasercolor]destroyed_target_prism" + else + if(powered()) + if(enabled) + if(iconholder) + //lasers have a orange icon + icon_state = "[lasercolor]orange_target_prism" + else + //almost everything has a blue icon + icon_state = "[lasercolor]target_prism" + else + icon_state = "[lasercolor]grey_target_prism" + else + icon_state = "[lasercolor]grey_target_prism" + +/obj/machinery/porta_turret/tag/bullet_act(obj/item/projectile/Proj) + ..() + + if(lasercolor == "b" && disabled == 0) + if(istype(Proj, /obj/item/weapon/gun/energy/laser/redtag)) + disabled = 1 + del(Proj) // qdel + sleep(100) + disabled = 0 + if(lasercolor == "r" && disabled == 0) + if(istype(Proj, /obj/item/weapon/gun/energy/laser/bluetag)) + disabled = 1 + del(Proj) // qdel + sleep(100) + disabled = 0 + +/obj/machinery/porta_turret/tag/assess_living(var/mob/living/L) + if(!L) + return TURRET_NOT_TARGET + + if(L.lying) + return TURRET_NOT_TARGET + + var/target_suit + var/target_weapon + switch(lasercolor) + if("b") + target_suit = /obj/item/clothing/suit/redtag + target_weapon = /obj/item/weapon/gun/energy/laser/redtag + if("r") + target_suit = /obj/item/clothing/suit/bluetag + target_weapon = /obj/item/weapon/gun/energy/laser/bluetag + + + if(target_suit)//Lasertag turrets target the opposing team, how great is that? -Sieve + if((istype(L.r_hand, target_weapon)) || (istype(L.l_hand, target_weapon))) + return TURRET_PRIORITY_TARGET + + if(istype(L, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = L + if(istype(H.wear_suit, target_suit)) + return TURRET_PRIORITY_TARGET + if(istype(H.belt, target_weapon)) + return TURRET_SECONDARY_TARGET + + return TURRET_NOT_TARGET \ No newline at end of file diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index fa36bcc23c5..13bdac7b536 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -1,635 +1,582 @@ -/* - Portable Turrets: - +/* Portable Turrets: Constructed from metal, a gun of choice, and a prox sensor. - Gun can be a taser or laser or energy gun. - This code is slightly more documented than normal, as requested by XSI on IRC. - */ - /obj/machinery/porta_turret name = "turret" icon = 'icons/obj/turrets.dmi' icon_state = "grey_target_prism" anchored = 1 layer = 3 - invisibility = INVISIBILITY_LEVEL_TWO // the turret is invisible if it's inside its cover + invisibility = INVISIBILITY_LEVEL_TWO //the turret is invisible if it's inside its cover density = 1 - use_power = 1 // 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 - req_access = list(access_security) - power_channel = EQUIP // drains power from the EQUIPMENT channel + use_power = 1 //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 + req_access = null + req_one_access = list(access_security, access_heads) + power_channel = EQUIP //drains power from the EQUIPMENT channel - var/lasercolor = "" // Something to do with lasertag turrets, blame Sieve for not adding a comment. - 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/health = 80 // the turret's health - var/locked = 1 // if the turret's behaviour control access is locked + 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/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/installation // the type of weapon installed - var/gun_charge = 0 // the charge of the gun inserted + var/installation = /obj/item/weapon/gun/energy/gun/turret //the type of weapon installed + var/gun_charge = 0 //the charge of the gun inserted var/projectile = null //holder for bullettype - var/eprojectile = null//holder for the shot when emagged - var/reqpower = 0 //holder for power needed - var/sound = null//So the taser can have sound - var/iconholder = null//holder for the icon_state - var/egun = null//holder to handle certain guns switching bullettypes + var/eprojectile = null //holder for the shot when emagged + var/reqpower = 500 //holder for power needed + var/iconholder = null //holder for the icon_state. 1 for orange sprite, null for blue. + var/egun = null //holder to handle certain guns switching bullettypes - var/obj/machinery/porta_turret_cover/cover = null // the cover that is covering this turret - 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/obj/machinery/porta_turret_cover/cover = null //the cover that is covering this turret + 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_records = 1 // checks if it can use the security records - var/criminals = 1 // checks if it can shoot people on arrest - var/auth_weapons = 0 // checks if it can shoot people that have a weapon they aren't authorized to have - var/stun_all = 0 // if this is active, the turret shoots everything that isn't security or head of staff - var/check_anomalies = 1 // checks if it can shoot at unidentified lifeforms (ie xenos) - var/ai = 0 // if active, will shoot at anything not an AI or cyborg + 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/attacked = 0 // if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!) + var/attacked = 0 //if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!) - //var/emagged = 0 // 1: emagged, 0: not emagged - var/on = 1 // determines if the turret is on + var/enabled = 1 //determines if the turret is on + var/lethal = 0 //whether in lethal or stun mode var/disabled = 0 - var/datum/effect/effect/system/spark_spread/spark_system // the spark system, used for generating... sparks? + var/shot_sound //what sound should play when the turret fires + var/eshot_sound //what sound should play when the emagged turret fires - New() - ..() - icon_state = "[lasercolor]grey_target_prism" - // Sets up a spark system - spark_system = new /datum/effect/effect/system/spark_spread - spark_system.set_up(5, 0, src) - spark_system.attach(src) - sleep(10) - if(!installation)// if for some reason the turret has no gun (ie, admin spawned) it resorts to basic taser shots - projectile = /obj/item/projectile/energy/electrode//holder for the projectile, here it is being set - eprojectile = /obj/item/projectile/beam//holder for the projectile when emagged, if it is different - reqpower = 200 - sound = 1 + var/datum/effect/effect/system/spark_spread/spark_system //the spark system, used for generating... sparks? + + var/wrenching = 0 + var/last_target //last target fired at, prevents turrets from erratically firing at all valid targets in range + +/obj/machinery/porta_turret/stationary + lethal = 1 + installation = /obj/item/weapon/gun/energy/laser + +/obj/machinery/porta_turret/New() + ..() + icon_state = "grey_target_prism" + //Sets up a spark system + spark_system = new /datum/effect/effect/system/spark_spread + spark_system.set_up(5, 0, src) + spark_system.attach(src) + + cover = new /obj/machinery/porta_turret_cover(loc) + cover.Parent_Turret = src + setup() + +/obj/machinery/porta_turret/proc/setup() + var/obj/item/weapon/gun/energy/E = installation //All energy-based weapons are applicable + //var/obj/item/ammo_casing/shottype = E.projectile_type + + projectile = initial(E.projectile_type) + eprojectile = projectile + shot_sound = initial(E.fire_sound) + eshot_sound = shot_sound + + weapon_setup(installation) + +/obj/machinery/porta_turret/proc/weapon_setup(var/guntype) + switch(guntype) + if(/obj/item/weapon/gun/energy/laser/practice) iconholder = 1 - else - var/obj/item/weapon/gun/energy/E=new installation - // All energy-based weapons are applicable - switch(E.type) - if(/obj/item/weapon/gun/energy/laser/bluetag) - projectile = /obj/item/projectile/lasertag/blue - eprojectile = /obj/item/projectile/lasertag/omni//This bolt will stun ERRYONE with a vest - iconholder = null - reqpower = 100 - lasercolor = "b" - req_access = list(access_maint_tunnels) - check_records = 0 - criminals = 0 - auth_weapons = 1 - stun_all = 0 - check_anomalies = 0 - shot_delay = 30 + eprojectile = /obj/item/projectile/beam - if(/obj/item/weapon/gun/energy/laser/redtag) - projectile = /obj/item/projectile/lasertag/red - eprojectile = /obj/item/projectile/lasertag/omni - iconholder = null - reqpower = 100 - lasercolor = "r" - req_access = list(access_maint_tunnels) - check_records = 0 - criminals = 0 - auth_weapons = 1 - stun_all = 0 - check_anomalies = 0 - shot_delay = 30 +// if(/obj/item/weapon/gun/energy/laser/practice/sc_laser) +// iconholder = 1 +// eprojectile = /obj/item/projectile/beam - if(/obj/item/weapon/gun/energy/laser/practice) - projectile = /obj/item/projectile/practice - eprojectile = /obj/item/projectile/beam - iconholder = null - reqpower = 100 + if(/obj/item/weapon/gun/energy/laser/retro) + iconholder = 1 - if(/obj/item/weapon/gun/energy/pulse_rifle) - projectile = /obj/item/projectile/beam/pulse - eprojectile = projectile - iconholder = null - reqpower = 700 +// if(/obj/item/weapon/gun/energy/retro/sc_retro) +// iconholder = 1 - if(/obj/item/weapon/gun/energy/staff) - projectile = /obj/item/projectile/change - eprojectile = projectile - iconholder = 1 - reqpower = 700 + if(/obj/item/weapon/gun/energy/laser/captain) + iconholder = 1 - if(/obj/item/weapon/gun/energy/ionrifle) - projectile = /obj/item/projectile/ion - eprojectile = projectile - iconholder = 1 - reqpower = 700 + if(/obj/item/weapon/gun/energy/lasercannon) + iconholder = 1 - if(/obj/item/weapon/gun/energy/advtaser) - projectile = /obj/item/projectile/energy/electrode - eprojectile = projectile - iconholder = 1 - reqpower = 200 + if(/obj/item/weapon/gun/energy/taser) + eprojectile = /obj/item/projectile/beam + eshot_sound = 'sound/weapons/Laser.ogg' - if(/obj/item/weapon/gun/energy/stunrevolver) - projectile = /obj/item/projectile/energy/electrode - eprojectile = projectile - iconholder = 1 - reqpower = 200 + if(/obj/item/weapon/gun/energy/stunrevolver) + eprojectile = /obj/item/projectile/beam + eshot_sound = 'sound/weapons/Laser.ogg' - if(/obj/item/weapon/gun/energy/lasercannon) - projectile = /obj/item/projectile/beam/heavylaser - eprojectile = projectile - iconholder = null - reqpower = 600 + if(/obj/item/weapon/gun/energy/gun) + eprojectile = /obj/item/projectile/beam //If it has, going to kill mode + eshot_sound = 'sound/weapons/Laser.ogg' + egun = 1 - if(/obj/item/weapon/gun/energy/decloner) - projectile = /obj/item/projectile/energy/declone - eprojectile = projectile - iconholder = null - reqpower = 600 - - if(/obj/item/weapon/gun/energy/kinetic_accelerator/crossbow/large) - projectile = /obj/item/projectile/energy/bolt/large - eprojectile = projectile - iconholder = null - reqpower = 125 - - if(/obj/item/weapon/gun/energy/kinetic_accelerator/crossbow) - projectile = /obj/item/projectile/energy/bolt - eprojectile = projectile - iconholder = null - reqpower = 50 - - if(/obj/item/weapon/gun/energy/laser) - projectile = /obj/item/projectile/beam - eprojectile = projectile - iconholder = null - reqpower = 500 - - else // Energy gun shots - projectile = /obj/item/projectile/energy/electrode// if it hasn't been emagged, it uses normal taser shots - eprojectile = /obj/item/projectile/beam//If it has, going to kill mode - iconholder = 1 - egun = 1 - reqpower = 200 - - Destroy() - // deletes its own cover with it - del(cover) - ..() - - -/obj/machinery/porta_turret/attack_ai(mob/user as mob) - return attack_hand(user) - -/obj/machinery/porta_turret/attack_hand(mob/user as mob) - . = ..() - if (.) - return - var/dat - - // The browse() text, similar to ED-209s and beepskies. - if(!(src.lasercolor))//Lasertag turrets have less options - dat += text({" -Automatic Portable Turret Installation

-Status: []
-Behaviour controls are [src.locked ? "locked" : "unlocked"]"}, - -"[src.on ? "On" : "Off"]" ) - - if(!src.locked) - dat += text({"
-Check for Weapon Authorization: []
-Check Security Records: []
-Neutralize Identified Criminals: []
-Neutralize All Non-Security and Non-Command Personnel: []
-Neutralize All Unidentified Life Signs: []
"}, - -"[src.auth_weapons ? "Yes" : "No"]", -"[src.check_records ? "Yes" : "No"]", -"[src.criminals ? "Yes" : "No"]", -"[stun_all ? "Yes" : "No"]", -"[check_anomalies ? "Yes" : "No"]" ) - else - if(istype(user,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - if(((src.lasercolor) == "b") && (istype(H.wear_suit, /obj/item/clothing/suit/redtag))) - return - if(((src.lasercolor) == "r") && (istype(H.wear_suit, /obj/item/clothing/suit/bluetag))) - return - dat += text({" -Automatic Portable Turret Installation

-Status: []
"}, - -"[src.on ? "On" : "Off"]" ) - - - user << browse("Automatic Portable Turret Installation[dat]", "window=autosec") - onclose(user, "autosec") - return - -/obj/machinery/porta_turret/Topic(href, href_list) - if (..()) - return 1 - usr.set_machine(src) - src.add_fingerprint(usr) - if ((href_list["power"]) && (src.allowed(usr))) - if(anchored) // you can't turn a turret on/off if it's not anchored/secured - on = !on // toggle on/off - else - usr << "\red It has to be secured first!" - - updateUsrDialog() - return - - switch(href_list["operation"]) - // toggles customizable behavioural protocols - - if ("authweapon") - src.auth_weapons = !src.auth_weapons - if ("checkrecords") - src.check_records = !src.check_records - if ("shootcrooks") - src.criminals = !src.criminals - if("shootall") - stun_all = !stun_all - updateUsrDialog() - - -/obj/machinery/porta_turret/power_change() + if(/obj/item/weapon/gun/energy/gun/nuclear) + eprojectile = /obj/item/projectile/beam //If it has, going to kill mode + eshot_sound = 'sound/weapons/Laser.ogg' + egun = 1 + + if(/obj/item/weapon/gun/energy/gun/turret) + eprojectile = /obj/item/projectile/beam //If it has, going to copypaste mode + eshot_sound = 'sound/weapons/Laser.ogg' + egun = 1 +/obj/machinery/porta_turret/update_icon() if(!anchored) icon_state = "turretCover" return if(stat & BROKEN) - icon_state = "[lasercolor]destroyed_target_prism" + icon_state = "destroyed_target_prism" else - if( powered() ) - if (on) - if (installation == /obj/item/weapon/gun/energy/laser || installation == /obj/item/weapon/gun/energy/pulse_rifle) - // laser guns and pulse rifles have an orange icon - icon_state = "[lasercolor]orange_target_prism" + if(powered()) + if(enabled) + if(iconholder) + //lasers have a orange icon + icon_state = "orange_target_prism" else - // anything else has a blue icon - icon_state = "[lasercolor]target_prism" + //almost everything has a blue icon + icon_state = "target_prism" else - icon_state = "[lasercolor]grey_target_prism" - stat &= ~NOPOWER + icon_state = "grey_target_prism" else - spawn(rand(0, 15)) - src.icon_state = "[lasercolor]grey_target_prism" - stat |= NOPOWER + icon_state = "grey_target_prism" + +/obj/machinery/porta_turret/Destroy() + //deletes its own cover with it + qdel(cover) // qdel + ..() + +/obj/machinery/porta_turret/proc/isLocked(mob/user) + if(ailock && (isrobot(user) || isAI(user))) + user << "There seems to be a firewall preventing you from accessing this device." + return 1 + + if(locked && !(isrobot(user) || isAI(user))) + user << "Access denied." + return 1 + + return 0 + +/obj/machinery/porta_turret/attack_ai(mob/user) + if(isLocked(user)) + return + + 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) + var/data[0] + data["access"] = !isLocked(user) + data["locked"] = locked + data["enabled"] = enabled + data["is_lethal"] = 1 + data["lethal"] = lethal + + if(data["access"]) + 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 + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 300) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) + +/obj/machinery/porta_turret/proc/HasController() + var/area/A = get_area(src) + return A && A.turret_controls.len > 0 + +/obj/machinery/porta_turret/Topic(href, href_list, var/nowindow = 0) + if(..()) + return 1 + + if(HasController()) + usr << "Turrets can only be controlled using the assigned turret controller." + return 1 + + if(isLocked(usr)) + return 1 + + if(!anchored) + usr << "\The [src] has to be secured first!" + return 1 + + if(href_list["command"] && href_list["value"]) + var/value = text2num(href_list["value"]) + if(href_list["command"] == "enable") + enabled = 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 + + return 1 + +/obj/machinery/porta_turret/power_change() + if(powered()) + stat &= ~NOPOWER + update_icon() + else + spawn(rand(0, 15)) + stat |= NOPOWER + update_icon() - -/obj/machinery/porta_turret/attackby(obj/item/W as obj, mob/user as mob, params) +/obj/machinery/porta_turret/attackby(obj/item/I, mob/user) if(stat & BROKEN) - if(istype(W, /obj/item/weapon/crowbar)) + if(istype(I, /obj/item/weapon/crowbar)) + //If the turret is destroyed, you can remove it with a crowbar to + //try and salvage its components + user << "You begin prying the metal coverings off." + if(do_after(user, 20)) + if(prob(70)) + user << "You remove the turret and salvage some components." + if(installation) + var/obj/item/weapon/gun/energy/Gun = new installation(loc) + Gun.power_supply.charge = gun_charge + Gun.update_icon() + if(prob(50)) + new /obj/item/stack/sheet/metal(loc, rand(1,4)) + if(prob(50)) + new /obj/item/device/assembly/prox_sensor(loc) + else + user << "You remove the turret but did not manage to salvage anything." + qdel(src) // qdel - // If the turret is destroyed, you can remove it with a crowbar to - // try and salvage its components - user << "You begin prying the metal coverings off." - sleep(20) - if(prob(70)) - user << "You remove the turret and salvage some components." - if(installation) - var/obj/item/weapon/gun/energy/Gun = new installation(src.loc) - Gun.power_supply.charge=gun_charge - Gun.update_icon() - lasercolor = null - if(prob(50)) new /obj/item/stack/sheet/metal( loc, rand(1,4)) - if(prob(50)) new /obj/item/device/assembly/prox_sensor(locate(x,y,z)) - else - user << "You remove the turret but did not manage to salvage anything." - del(src) + if(istype(I, /obj/item/weapon/card/emag) && !emagged) + //Emagging the turret makes it go bonkers and stun everyone. It also makes + //the turret shoot much, much faster. + user << "You short out [src]'s threat assessment circuits." + visible_message("[src] hums oddly...") + emagged = 1 + iconholder = 1 + controllock = 1 + enabled = 0 //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 + else if((istype(I, /obj/item/weapon/wrench))) + if(enabled || raised) + user << "You cannot unsecure an active turret!" + return + if(wrenching) + user << "Someone is already [anchored ? "un" : ""]securing the turret!" + return + if(!anchored && isinspace()) + user << "Cannot secure turrets in space!" + return - if((istype(W, /obj/item/weapon/wrench)) && (!on)) - if(raised) return - // This code handles moving the turret around. After all, it's a portable turret! + user.visible_message( \ + "[user] begins [anchored ? "un" : ""]securing the turret.", \ + "You begin [anchored ? "un" : ""]securing the turret." \ + ) - if(!anchored) - anchored = 1 - invisibility = INVISIBILITY_LEVEL_TWO - icon_state = "[lasercolor]grey_target_prism" - user << "You secure the exterior bolts on the turret." - cover=new/obj/machinery/porta_turret_cover(src.loc) // create a new turret. While this is handled in process(), this is to workaround a bug where the turret becomes invisible for a split second - cover.Parent_Turret = src // make the cover's parent src + wrenching = 1 + if(do_after(user, 50)) + //This code handles moving the turret around. After all, it's a portable turret! + if(!anchored) + playsound(loc, 'sound/items/Ratchet.ogg', 100, 1) + anchored = 1 + invisibility = INVISIBILITY_LEVEL_TWO + update_icon() + user << "You secure the exterior bolts on the turret." + create_cover() + else if(anchored) + playsound(loc, 'sound/items/Ratchet.ogg', 100, 1) + anchored = 0 + user << "You unsecure the exterior bolts on the turret." + invisibility = 0 + update_icon() + qdel(cover) //deletes the cover, and the turret instance itself becomes its own cover. - qdel + wrenching = 0 + + else if(istype(I, /obj/item/weapon/card/id)||istype(I, /obj/item/device/pda)) + //Behavior lock/unlock mangement + if(allowed(user)) + locked = !locked + user << "Controls are now [locked ? "locked" : "unlocked"]." + updateUsrDialog() else - anchored = 0 - user << "You unsecure the exterior bolts on the turret." - icon_state = "turretCover" - invisibility = 0 - del(cover) // deletes the cover, and the turret instance itself becomes its own cover. - - else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - // Behavior lock/unlock mangement - if (allowed(user)) - locked = !src.locked - user << "Controls are now [locked ? "locked." : "unlocked."]" - else - user << "\red Access denied." + user << "Access denied." else - // if the turret was attacked with the intention of harming it: - src.health -= W.force * 0.5 - if (src.health <= 0) - src.die() - if ((W.force * 0.5) > 1) // if the force of impact dealt at least 1 damage, the turret gets pissed off + //if the turret was attacked with the intention of harming it: + user.changeNext_move(CLICK_CD_MELEE) + take_damage(I.force * 0.5) + 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 spawn() sleep(60) attacked = 0 + ..() -/obj/machinery/porta_turret/emag_act(user as mob) - if(!src.emagged) - // Emagging the turret makes it go bonkers and stun everyone. It also makes - // the turret shoot much, much faster. +/obj/machinery/porta_turret/proc/take_damage(var/force) + health -= force + if (force > 5 && prob(45)) + spark_system.start() + if(health <= 0) + die() //the death process :( - user << "\red You short out [src]'s threat assessment circuits." - spawn(0) - for(var/mob/O in hearers(src, null)) - O.show_message("\red [src] hums oddly...", 1) - emagged = 1 - src.on = 0 // 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 - on = 1 // turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here +/obj/machinery/porta_turret/bullet_act(obj/item/projectile/Proj) -/obj/machinery/porta_turret/bullet_act(var/obj/item/projectile/Proj) - if(on) + if(Proj.damage_type == HALLOSS) + return + + if(enabled) if(!attacked && !emagged) attacked = 1 spawn() sleep(60) attacked = 0 - if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) - health -= Proj.damage - ..() - if(prob(45) && Proj.damage > 0) src.spark_system.start() - if (src.health <= 0) - src.die() // the death process :( - if((src.lasercolor == "b") && (src.disabled == 0)) - if(istype(Proj, /obj/item/projectile/lasertag/red)) - src.disabled = 1 - del (Proj) - sleep(100) - src.disabled = 0 - if((src.lasercolor == "r") && (src.disabled == 0)) - if(istype(Proj, /obj/item/projectile/lasertag/blue)) - src.disabled = 1 - del (Proj) - sleep(100) - src.disabled = 0 - return + if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) + take_damage(Proj.damage) /obj/machinery/porta_turret/emp_act(severity) - if(on) - // if the turret is on, the EMP no matter how severe disables the turret for a while - // and scrambles its settings, with a slight chance of having an emag effect - check_records=pick(0,1) - criminals=pick(0,1) - auth_weapons=pick(0,1) - stun_all=pick(0,0,0,0,1) // stun_all is a pretty big deal, so it's least likely to get turned on - if(prob(5)) emagged=1 - on=0 + if(enabled) + //if the turret is on, the EMP no matter how severe disables the turret for a while + //and scrambles its settings, with a slight chance of having an emag effect + check_arrest = prob(50) + check_records = prob(50) + check_weapons = prob(50) + 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 + + enabled=0 sleep(rand(60,600)) - if(!on) - on=1 + if(!enabled) + enabled=1 ..() /obj/machinery/porta_turret/ex_act(severity) - if(severity >= 3) // turret dies if an explosion touches it! - qdel(src) - else - src.die() - -/obj/machinery/porta_turret/proc/die() // called when the turret dies, ie, health <= 0 - src.health = 0 - src.density = 0 - src.stat |= BROKEN // enables the BROKEN bit - src.icon_state = "[lasercolor]destroyed_target_prism" - invisibility=0 - src.spark_system.start() // creates some sparks because they look cool - src.density=1 - qdel(cover) // deletes the cover - no need on keeping it there! + switch (severity) + if (1) + qdel(src) + if (2) + if (prob(25)) + qdel(src) + else + take_damage(150) //should instakill most turrets + if (3) + take_damage(50) +/obj/machinery/porta_turret/proc/die() //called when the turret dies, ie, health <= 0 + health = 0 + density = 0 + stat |= BROKEN //enables the BROKEN bit + invisibility = 0 + spark_system.start() //creates some sparks because they look cool + density = 1 + update_icon() + del(cover) //deletes the cover - no need on keeping it there! - del +/obj/machinery/porta_turret/proc/create_cover() + if(cover == null && anchored) + cover = new /obj/machinery/porta_turret_cover(loc) //if the turret has no cover and is anchored, give it a cover + cover.Parent_Turret = src //assign the cover its Parent_Turret, which would be this (src) /obj/machinery/porta_turret/process() - // the main machinery process + //the main machinery process - //set background = 1 + set background = BACKGROUND_ENABLED - if(src.cover==null && anchored) // if it has no cover and is anchored - if (stat & BROKEN) // if the turret is borked - del(cover) // delete its cover, assuming it has one. Workaround for a pesky little bug + if(cover == null && anchored) //if it has no cover and is anchored + if(stat & BROKEN) //if the turret is borked + qdel(cover) //delete its cover, assuming it has one. Workaround for a pesky little bug - qdel else - - src.cover = new /obj/machinery/porta_turret_cover(src.loc) // if the turret has no cover and is anchored, give it a cover - src.cover.Parent_Turret = src // assign the cover its Parent_Turret, which would be this (src) + create_cover() if(stat & (NOPOWER|BROKEN)) - // if the turret has no power or is broken, make the turret pop down if it hasn't already + //if the turret has no power or is broken, make the turret pop down if it hasn't already popDown() return - if(!on) - // if the turret is off, make it pop down + if(!enabled) + //if the turret is off, make it pop down popDown() return - var/list/targets = list() // list of primary targets - var/list/secondarytargets = list() // targets that are least important + var/list/targets = list() //list of primary targets + var/list/secondarytargets = list() //targets that are least important - if(src.check_anomalies) // if its set to check for xenos/carps, check for non-mob "crittersssss"(And simple_animals) - for(var/mob/living/simple_animal/C in view(7,src)) - if(C.stat) - continue - // Ignore lazarus-injected mobs. - if(C.faction == "lazarus") - continue - targets += C + for(var/obj/mecha/ME in view(7,src)) + assess_and_assign(ME.occupant, targets, secondarytargets) - for (var/mob/living/carbon/C in view(7,src)) // loops through all living carbon-based lifeforms in view(12) - if(istype(C, /mob/living/carbon/alien) && src.check_anomalies) // git those fukken xenos - if(!C.stat) // if it's dead/dying, there's no need to keep shooting at it. - targets += C + for(var/obj/spacepod/SP in view(7,src)) + assess_and_assign(SP.occupant, targets, secondarytargets) + + for(var/obj/vehicle/train/T in view(7,src)) + assess_and_assign(T.load, targets, secondarytargets) - else - if(emagged) // if emagged, HOLY SHIT EVERYONE IS DANGEROUS beep boop beep - targets += C - else - if (C.stat || C.handcuffed) // if the perp is handcuffed or dead/dying, no need to bother really - continue // move onto next potential victim! + for(var/mob/living/C in view(7,src)) //loops through all living lifeforms in view + assess_and_assign(C, targets, secondarytargets) - var/dst = get_dist(src, C) // if it's too far away, why bother? - if (dst > 7) - continue + if(!tryToShootAt(targets)) + if(!tryToShootAt(secondarytargets)) // if no valid targets, go for secondary targets + spawn() + popDown() // no valid targets, close the cover - if(ai) // If it's set to attack all nonsilicons, target them! - if(C.lying) - if(lasercolor) - continue - else - secondarytargets += C - continue - else - targets += C - continue +/obj/machinery/porta_turret/proc/assess_and_assign(var/mob/living/L, var/list/targets, var/list/secondarytargets) + switch(assess_living(L)) + if(TURRET_PRIORITY_TARGET) + targets += L + if(TURRET_SECONDARY_TARGET) + secondarytargets += L - if (istype(C, /mob/living/carbon/human)) // if the target is a human, analyze threat level - if(src.assess_perp(C)<4) - continue // if threat level < 4, keep going +/obj/machinery/porta_turret/proc/assess_living(var/mob/living/L) + if(!istype(L)) + return TURRET_NOT_TARGET - else if (istype(C, /mob/living/carbon/monkey)) - continue // Don't target monkeys or borgs/AIs you dumb shit + if(L.invisibility >= INVISIBILITY_LEVEL_ONE) // Cannot see him. see_invisible is a mob-var + return TURRET_NOT_TARGET - if (C.lying) // if the perp is lying down, it's still a target but a less-important target - secondarytargets += C - continue + if(!L) + return TURRET_NOT_TARGET - targets += C // if the perp has passed all previous tests, congrats, it is now a "shoot-me!" nominee + // If emagged not even the dead get a rest + if(emagged) + return L.stat ? TURRET_SECONDARY_TARGET : TURRET_PRIORITY_TARGET - if (targets.len>0) // if there are targets to shoot + if(issilicon(L)) // Don't target silica + return TURRET_NOT_TARGET - var/atom/t = pick(targets) // pick a perp from the list of targets. Targets go first because they are the most important + if(L.stat) //if the perp is dead/dying, no need to bother really + return TURRET_NOT_TARGET //move onto next potential victim! - if (istype(t, /mob/living)) // if a mob - var/mob/living/M = t // simple typecasting - if (M.stat!=2) // if the target is not dead - spawn() popUp() // pop the turret up if it's not already up. - dir=get_dir(src,M) // even if you can't shoot, follow the target - spawn() shootAt(M) // shoot the target, finally + var/dst = get_dist(src, L) //if it's too far away, why bother? + if(dst > 7) + return 0 - else - if(secondarytargets.len>0) // if there are no primary targets, go for secondary targets - var/mob/t = pick(secondarytargets) - if (istype(t, /mob/living)) - if (t.stat!=2) - spawn() popUp() - dir=get_dir(src,t) - shootAt(t) - else - spawn() popDown() + if(check_synth) //If it's set to attack all non-silicons, target them! + if(L.lying) + return lethal ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET + return TURRET_PRIORITY_TARGET -/obj/machinery/porta_turret/proc - popUp() // pops the turret up - if(disabled) - return - if(raising || raised) return - if(stat & BROKEN) return - invisibility=0 - raising=1 - flick("popup",cover) - sleep(5) - sleep(5) - raising=0 - cover.icon_state="openTurretCover" - raised=1 - layer=4 + if(iscuffed(L)) // If the target is handcuffed, leave it alone + return TURRET_NOT_TARGET - popDown() // pops the turret down - if(disabled) - return - if(raising || !raised) return - if(stat & BROKEN) return - layer=3 - raising=1 - flick("popdown",cover) - sleep(10) - raising=0 - cover.icon_state="turretCover" - raised=0 - invisibility=2 - icon_state="[lasercolor]grey_target_prism" + if(isanimal(L) || ismonkey(L)) // Animals are not so dangerous + return check_anomalies ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET + if(isalien(L)) // Xenos are dangerous + return check_anomalies ? TURRET_PRIORITY_TARGET : TURRET_NOT_TARGET + if(ishuman(L)) //if the target is a human, analyze threat level + if(assess_perp(L, check_weapons, check_records, check_arrest) < 4) + return TURRET_NOT_TARGET //if threat level < 4, keep going -/obj/machinery/porta_turret/proc/assess_perp(mob/living/carbon/human/perp as mob) - var/threatcount = 0 // the integer returned + if(L.lying) //if the perp is lying down, it's still a target but a less-important target + return lethal ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET - if(src.emagged) return 10 // if emagged, always return 10. + return TURRET_PRIORITY_TARGET //if the perp has passed all previous tests, congrats, it is now a "shoot-me!" nominee - if((stun_all && !src.allowed(perp)) || attacked && !src.allowed(perp)) - // if the turret has been attacked or is angry, target all non-sec people - if(!src.allowed(perp)) - return 10 +/obj/machinery/porta_turret/proc/tryToShootAt(var/list/mob/living/targets) + if(targets.len && last_target && (last_target in targets) && target(last_target)) + return 1 - if(auth_weapons) // check for weapon authorization - if((isnull(perp.wear_id)) || (istype(perp.wear_id.GetID(), /obj/item/weapon/card/id/syndicate))) - - if((src.allowed(perp)) && !(src.lasercolor)) // if the perp has security access, return 0 - return 0 - - if((istype(perp.l_hand, /obj/item/weapon/gun) && !istype(perp.l_hand, /obj/item/weapon/gun/projectile/shotgun)) || istype(perp.l_hand, /obj/item/weapon/melee/baton)) - threatcount += 4 - - if((istype(perp.r_hand, /obj/item/weapon/gun) && !istype(perp.r_hand, /obj/item/weapon/gun/projectile/shotgun)) || istype(perp.r_hand, /obj/item/weapon/melee/baton)) - threatcount += 4 - - if(istype(perp.belt, /obj/item/weapon/gun) || istype(perp.belt, /obj/item/weapon/melee/baton)) - threatcount += 2 - - if((src.lasercolor) == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve - threatcount = 0//But does not target anyone else - if(istype(perp.wear_suit, /obj/item/clothing/suit/redtag)) - threatcount += 4 - if((istype(perp.r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(perp.l_hand,/obj/item/weapon/gun/energy/laser/redtag))) - threatcount += 4 - if(istype(perp.belt, /obj/item/weapon/gun/energy/laser/redtag)) - threatcount += 2 - - if((src.lasercolor) == "r") - threatcount = 0 - if(istype(perp.wear_suit, /obj/item/clothing/suit/bluetag)) - threatcount += 4 - if((istype(perp.r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(perp.l_hand,/obj/item/weapon/gun/energy/laser/bluetag))) - threatcount += 4 - if(istype(perp.belt, /obj/item/weapon/gun/energy/laser/bluetag)) - threatcount += 2 - - if (src.check_records) // if the turret can check the records, check if they are set to *Arrest* on records - for (var/datum/data/record/E in data_core.general) - - var/perpname = perp.name - if (perp.wear_id) - var/obj/item/weapon/card/id/id = perp.wear_id.GetID() - if (id) - perpname = id.registered_name - - if (E.fields["name"] == perpname) - for (var/datum/data/record/R in data_core.security) - if ((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "*Arrest*")) - threatcount = 4 - break - - - - return threatcount - - - - - -/obj/machinery/porta_turret/proc/shootAt(var/atom/movable/target) // shoots at a target + while(targets.len > 0) + var/mob/living/M = pick(targets) + targets -= M + if(target(M)) + return 1 + +/obj/machinery/porta_turret/proc/popUp() //pops the turret up if(disabled) return + if(raising || raised) + return + if(stat & BROKEN) + return + invisibility = 0 + raising = 1 + flick("popup", cover) + sleep(10) + raising = 0 + cover.icon_state = "openTurretCover" + raised = 1 + layer = 4 + update_icon() - if(lasercolor && (istype(target,/mob/living/carbon/human))) - var/mob/living/carbon/human/H = target - if(H.lying) +/obj/machinery/porta_turret/proc/popDown() //pops the turret down + last_target = null + if(disabled) + return + if(raising || !raised) + return + if(stat & BROKEN) + return + layer = 3 + raising = 1 + flick("popdown", cover) + sleep(10) + raising = 0 + cover.icon_state = "turretCover" + raised = 0 + invisibility = INVISIBILITY_LEVEL_TWO + update_icon() + +/obj/machinery/porta_turret/on_assess_perp(mob/living/carbon/human/perp) + if((check_access || attacked) && !allowed(perp)) + //if the turret has been attacked or is angry, target all non-authorized personnel, see req_access + return 10 + + return ..() + +/obj/machinery/porta_turret/proc/target(var/mob/living/target) + if(disabled) + return + if(target) + last_target = target + spawn() + popUp() //pop the turret up if it's not already up. + dir = get_dir(src, target) //even if you can't shoot, follow the target + spawn() + shootAt(target) + return 1 + return + +/obj/machinery/porta_turret/proc/shootAt(var/mob/living/target) + //any emagged turrets will shoot extremely fast! This not only is deadly, but drains a lot power! + if(!emagged) //if it hasn't been emagged, it has to obey a cooldown rate + if(last_fired || !raised) //prevents rapid-fire shooting, unless it's been emagged return - - if(!emagged) // if it hasn't been emagged, it has to obey a cooldown rate - if(last_fired || !raised) return // prevents rapid-fire shooting, unless it's been emagged last_fired = 1 spawn() sleep(shot_delay) @@ -637,47 +584,65 @@ Status: []
"}, var/turf/T = get_turf(src) var/turf/U = get_turf(target) - if (!istype(T) || !istype(U)) + if(!istype(T) || !istype(U)) return - if (!raised) // the turret has to be raised in order to fire - makes sense, right? + if(!raised) //the turret has to be raised in order to fire - makes sense, right? return - // any emagged turrets will shoot extremely fast! This not only is deadly, but drains a lot power! - - if(iconholder) - icon_state = "[lasercolor]target_prism" - else - icon_state = "[lasercolor]orange_target_prism" - if(sound) - playsound(src.loc, 'sound/weapons/Taser.ogg', 75, 1) + update_icon() var/obj/item/projectile/A - if(emagged) - A = new eprojectile( loc ) + if(emagged || lethal) + A = new eprojectile(loc) + playsound(loc, eshot_sound, 75, 1) else - A = new projectile( loc ) - A.original = target.loc - if(!emagged) - use_power(reqpower) - else - use_power((reqpower*2)) - // Shooting Code: + A = new projectile(loc) + playsound(loc, shot_sound, 75, 1) + A.original = target + + // Lethal/emagged turrets use twice the power due to higher energy beams + // Emagged turrets again use twice as much power due to higher firing rates + use_power(reqpower * (2 * (emagged || lethal)) * (2 * emagged)) + + //Shooting Code: A.current = T A.yo = U.y - T.y A.xo = U.x - T.x - spawn( 1 ) + spawn(1) A.process() - return +/datum/turret_checks + var/enabled + var/lethal + var/check_synth + var/check_access + var/check_records + var/check_arrest + var/check_weapons + var/check_anomalies + var/ailock +/obj/machinery/porta_turret/proc/setState(var/datum/turret_checks/TC) + if(controllock) + return + src.enabled = TC.enabled + src.lethal = TC.lethal + src.iconholder = TC.lethal + + check_synth = TC.check_synth + check_access = TC.check_access + check_records = TC.check_records + check_arrest = TC.check_arrest + check_weapons = TC.check_weapons + check_anomalies = TC.check_anomalies + ailock = TC.ailock + + src.power_change() /* - Portable turret constructions - Known as "turret frame"s - */ /obj/machinery/porta_turret_construct @@ -685,68 +650,66 @@ Status: []
"}, icon = 'icons/obj/turrets.dmi' icon_state = "turret_frame" density=1 - var/build_step = 0 // the current step in the building process - var/finish_name="turret" // the name applied to the product turret - var/installation = null // the gun type installed - var/gun_charge = 0 // the gun charge of the gun type installed + var/target_type = /obj/machinery/porta_turret // The type we intend to build + var/build_step = 0 //the current step in the building process + var/finish_name="turret" //the name applied to the product turret + var/installation = null //the gun type installed + var/gun_charge = 0 //the gun charge of the gun type installed - -/obj/machinery/porta_turret_construct/attackby(obj/item/W as obj, mob/user as mob, params) - - // this is a bit unweildy but self-explanitory +/obj/machinery/porta_turret_construct/attackby(obj/item/I, mob/user) + //this is a bit unwieldy but self-explanatory switch(build_step) - if(0) // first step - if(istype(W, /obj/item/weapon/wrench) && !anchored) - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - user << "\blue You secure the external bolts." + if(0) //first step + if(istype(I, /obj/item/weapon/wrench) && !anchored) + playsound(loc, 'sound/items/Ratchet.ogg', 100, 1) + user << "You secure the external bolts." anchored = 1 build_step = 1 return - else if(istype(W, /obj/item/weapon/crowbar) && !anchored) - playsound(src.loc, 'sound/items/Crowbar.ogg', 75, 1) - user << "You dismantle the turret construction." + else if(istype(I, /obj/item/weapon/crowbar) && !anchored) + playsound(loc, 'sound/items/Crowbar.ogg', 75, 1) + user << "You dismantle the turret construction." new /obj/item/stack/sheet/metal( loc, 5) - del(src) + qdel(src) // qdel return if(1) - if(istype(W, /obj/item/stack/sheet/metal)) - var/obj/item/stack/sheet/metal/M = W - if(M.amount>=2) // requires 2 metal sheets - user << "\blue You add some metal armor to the interior frame." + if(istype(I, /obj/item/stack/sheet/metal)) + var/obj/item/stack/sheet/metal/M = I + if(M.use(2)) + user << "You add some metal armor to the interior frame." build_step = 2 - M.amount -= 2 icon_state = "turret_frame2" - if(M.amount <= 0) - user.unEquip(M, 1) //We're deleting it anyway, so no point in having NODROP fuck shit up. - del(M) - return + else + user << "You need two sheets of metal to continue construction." + return - else if(istype(W, /obj/item/weapon/wrench)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) - user << "You unfasten the external bolts." + else if(istype(I, /obj/item/weapon/wrench)) + playsound(loc, 'sound/items/Ratchet.ogg', 75, 1) + user << "You unfasten the external bolts." anchored = 0 build_step = 0 return if(2) - if(istype(W, /obj/item/weapon/wrench)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - user << "\blue You bolt the metal armor into place." + if(istype(I, /obj/item/weapon/wrench)) + playsound(loc, 'sound/items/Ratchet.ogg', 100, 1) + user << "You bolt the metal armor into place." build_step = 3 return - else if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(!WT.isOn()) return - if (WT.get_fuel() < 5) // uses up 5 fuel. - user << "\red You need more fuel to complete this task." + else if(istype(I, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = I + if(!WT.isOn()) + return + if(WT.get_fuel() < 5) //uses up 5 fuel. + user << "You need more fuel to complete this task." return - playsound(src.loc, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) + playsound(loc, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) if(do_after(user, 20)) if(!src || !WT.remove_fuel(5, user)) return build_step = 1 @@ -756,138 +719,143 @@ Status: []
"}, if(3) - if(istype(W, /obj/item/weapon/gun/energy)) // the gun installation part + if(istype(I, /obj/item/weapon/gun/energy)) //the gun installation part - var/obj/item/weapon/gun/energy/E = W // typecasts the item to an energy gun - if(!user.unEquip(W)) - user << "\the [W] is stuck to your hand, you cannot put it in \the [src]" + if(isrobot(user)) return - installation = W.type // installation becomes W.type - gun_charge = E.power_supply.charge // the gun's charge is stored in src.gun_charge - user << "\blue You add \the [W] to the turret." + var/obj/item/weapon/gun/energy/E = I //typecasts the item to an energy gun + if(!user.unEquip(I)) + user << "\the [I] is stuck to your hand, you cannot put it in \the [src]" + return + installation = I.type //installation becomes I.type + gun_charge = E.power_supply.charge //the gun's charge is stored in gun_charge + user << "You add [I] to the turret." + + if(istype(installation, /obj/item/weapon/gun/energy/laser/bluetag) || istype(installation, /obj/item/weapon/gun/energy/laser/redtag)) + target_type = /obj/machinery/porta_turret/tag + else + target_type = /obj/machinery/porta_turret + build_step = 4 - del(W) // delete the gun :( + qdel(I) //delete the gun :( qdel return - else if(istype(W, /obj/item/weapon/wrench)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - user << "You remove the turret's metal armor bolts." + else if(istype(I, /obj/item/weapon/wrench)) + playsound(loc, 'sound/items/Ratchet.ogg', 100, 1) + user << "You remove the turret's metal armor bolts." build_step = 2 return if(4) - if(isprox(W)) - if(!user.unEquip(W)) - user << "\the [W] is stuck to your hand, you cannot put it in \the [src]" - return + if(isprox(I)) build_step = 5 - user << "\blue You add the prox sensor to the turret." - del(W) + if(!user.unEquip(I)) + user << "\the [I] is stuck to your hand, you cannot put it in \the [src]" + return + user << "You add the prox sensor to the turret." + qdel(I) // qdel return - // attack_hand() removes the gun + //attack_hand() removes the gun if(5) - if(istype(W, /obj/item/weapon/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) + if(istype(I, /obj/item/weapon/screwdriver)) + playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1) build_step = 6 - user << "\blue You close the internal access hatch." + user << "You close the internal access hatch." return - // attack_hand() removes the prox sensor + //attack_hand() removes the prox sensor if(6) - if(istype(W, /obj/item/stack/sheet/metal)) - var/obj/item/stack/sheet/metal/M = W - if(M.amount>=2) - user << "\blue You add some metal armor to the exterior frame." + if(istype(I, /obj/item/stack/sheet/metal)) + var/obj/item/stack/sheet/metal/M = I + if(M.use(2)) + user << "You add some metal armor to the exterior frame." build_step = 7 - M.amount -= 2 - if(M.amount <= 0) - user.unEquip(M, 1) //If we don't force-unequip, bugs happen because the item was deleted without updating the neccesary stuff - del(M) - return + else + user << "You need two sheets of metal to continue construction." + return - else if(istype(W, /obj/item/weapon/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) + else if(istype(I, /obj/item/weapon/screwdriver)) + playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1) build_step = 5 - user << "You open the internal access hatch." + user << "You open the internal access hatch." return if(7) - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W + if(istype(I, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = I if(!WT.isOn()) return - if (WT.get_fuel() < 5) - user << "\red You need more fuel to complete this task." + if(WT.get_fuel() < 5) + user << "You need more fuel to complete this task." - playsound(src.loc, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) + playsound(loc, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) if(do_after(user, 30)) - if(!src || !WT.remove_fuel(5, user)) return + if(!src || !WT.remove_fuel(5, user)) + return build_step = 8 - user << "\blue You weld the turret's armor down." + user << "You weld the turret's armor down." - // The final step: create a full turret - var/obj/machinery/porta_turret/Turret = new/obj/machinery/porta_turret(locate(x,y,z)) + //The final step: create a full turret + var/obj/machinery/porta_turret/Turret = new target_type(loc) Turret.name = finish_name - Turret.installation = src.installation - Turret.gun_charge = src.gun_charge + Turret.installation = installation + Turret.gun_charge = gun_charge + Turret.enabled = 0 + Turret.setup() -// Turret.cover=new/obj/machinery/porta_turret_cover(src.loc) +// Turret.cover=new/obj/machinery/porta_turret_cover(loc) // Turret.cover.Parent_Turret=Turret // Turret.cover.name = finish_name - Turret.New() - del(src) + qdel(src) // qdel - else if(istype(W, /obj/item/weapon/crowbar)) - playsound(src.loc, 'sound/items/Crowbar.ogg', 75, 1) - user << "You pry off the turret's exterior armor." - new /obj/item/stack/sheet/metal( loc, 2) + else if(istype(I, /obj/item/weapon/crowbar)) + playsound(loc, 'sound/items/Crowbar.ogg', 75, 1) + user << "You pry off the turret's exterior armor." + new /obj/item/stack/sheet/metal(loc, 2) build_step = 6 return - if (istype(W, /obj/item/weapon/pen)) // you can rename turrets like bots! - var/t = input(user, "Enter new turret name", src.name, src.finish_name) as text + if(istype(I, /obj/item/weapon/pen)) //you can rename turrets like bots! + var/t = input(user, "Enter new turret name", name, finish_name) as text t = sanitize(copytext(t, 1, MAX_MESSAGE_LEN)) - if (!t) + if(!t) return - if (!in_range(src, usr) && src.loc != usr) + if(!in_range(src, usr) && loc != usr) return - src.finish_name = t + finish_name = t return ..() - -/obj/machinery/porta_turret_construct/attack_hand(mob/user as mob) +/obj/machinery/porta_turret_construct/attack_hand(mob/user) switch(build_step) if(4) - if(!installation) return + if(!installation) + return build_step = 3 - var/obj/item/weapon/gun/energy/Gun = new installation(src.loc) - Gun.power_supply.charge=gun_charge + var/obj/item/weapon/gun/energy/Gun = new installation(loc) + Gun.power_supply.charge = gun_charge Gun.update_icon() installation = null gun_charge = 0 - user << "You remove \the [Gun] from the turret frame." + user << "You remove [Gun] from the turret frame." if(5) - user << "You remove the prox sensor from the turret frame." - new/obj/item/device/assembly/prox_sensor(locate(x,y,z)) + user << "You remove the prox sensor from the turret frame." + new /obj/item/device/assembly/prox_sensor(loc) build_step = 4 +/obj/machinery/porta_turret_construct/attack_ai() + return - - - - - - - - +/************************ +* PORTABLE TURRET COVER * +************************/ /obj/machinery/porta_turret_cover name = "turret" @@ -898,179 +866,14 @@ Status: []
"}, density = 0 var/obj/machinery/porta_turret/Parent_Turret = null +/obj/machinery/porta_turret_cover/attack_ai(mob/user) + return attack_hand(user) - -// The below code is pretty much just recoded from the initial turret object. It's necessary but uncommented because it's exactly the same! - -/obj/machinery/porta_turret_cover/attack_ai(mob/user as mob) - . = ..() - if (.) - return - var/dat - if(!(Parent_Turret.lasercolor)) - dat += text({" -Automatic Portable Turret Installation

-Status: []
-Behaviour controls are [Parent_Turret.locked ? "locked" : "unlocked"]"}, - -"[Parent_Turret.on ? "On" : "Off"]" ) - - - dat += text({"
-Check for Weapon Authorization: []
-Check Security Records: []
-Neutralize Identified Criminals: []
-Neutralize All Non-Security and Non-Command Personnel: []
-Neutralize All Unidentified Life Signs: []
"}, - -"[Parent_Turret.auth_weapons ? "Yes" : "No"]", -"[Parent_Turret.check_records ? "Yes" : "No"]", -"[Parent_Turret.criminals ? "Yes" : "No"]", -"[Parent_Turret.stun_all ? "Yes" : "No"]" , -"[Parent_Turret.check_anomalies ? "Yes" : "No"]" ) - else - dat += text({" -Automatic Portable Turret Installation

-Status: []
"}, - -"[Parent_Turret.on ? "On" : "Off"]" ) - - user << browse("Automatic Portable Turret Installation[dat]", "window=autosec") - onclose(user, "autosec") - return - -/obj/machinery/porta_turret_cover/attack_hand(mob/user as mob) - . = ..() - if (.) - return - var/dat - if(!(Parent_Turret.lasercolor)) - dat += text({" -Automatic Portable Turret Installation

-Status: []
-Behaviour controls are [Parent_Turret.locked ? "locked" : "unlocked"]"}, - -"[Parent_Turret.on ? "On" : "Off"]" ) - - if(!Parent_Turret.locked) - dat += text({"
-Check for Weapon Authorization: []
-Check Security Records: []
-Neutralize Identified Criminals: []
-Neutralize All Non-Security and Non-Command Personnel: []
-Neutralize All Unidentified Life Signs: []
"}, - -"[Parent_Turret.auth_weapons ? "Yes" : "No"]", -"[Parent_Turret.check_records ? "Yes" : "No"]", -"[Parent_Turret.criminals ? "Yes" : "No"]", -"[Parent_Turret.stun_all ? "Yes" : "No"]" , -"[Parent_Turret.check_anomalies ? "Yes" : "No"]" ) - else - if(istype(user,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - if(((Parent_Turret.lasercolor) == "b") && (istype(H.wear_suit, /obj/item/clothing/suit/redtag))) - return - if(((Parent_Turret.lasercolor) == "r") && (istype(H.wear_suit, /obj/item/clothing/suit/bluetag))) - return - dat += text({" -Automatic Portable Turret Installation

-Status: []
"}, - -"[Parent_Turret.on ? "On" : "Off"]" ) - - - - user << browse("Automatic Portable Turret Installation[dat]", "window=autosec") - onclose(user, "autosec") - return +/obj/machinery/porta_turret_cover/attack_hand(mob/user) + return Parent_Turret.attack_hand(user) /obj/machinery/porta_turret_cover/Topic(href, href_list) - if (..()) - return - usr.set_machine(src) - Parent_Turret.add_fingerprint(usr) - src.add_fingerprint(usr) - if ((href_list["power"]) && (Parent_Turret.allowed(usr))) - if(Parent_Turret.anchored) - if (Parent_Turret.on) - Parent_Turret.on=0 - else - Parent_Turret.on=1 - else - usr << "\red It has to be secured first!" + Parent_Turret.Topic(href, href_list, 1) // Calling another object's Topic requires that we claim to not have a window, otherwise BYOND's base proc will runtime. - updateUsrDialog() - return - - switch(href_list["operation"]) - if ("authweapon") - Parent_Turret.auth_weapons = !Parent_Turret.auth_weapons - if ("checkrecords") - Parent_Turret.check_records = !Parent_Turret.check_records - if ("shootcrooks") - Parent_Turret.criminals = !Parent_Turret.criminals - if("shootall") - Parent_Turret.stun_all = !Parent_Turret.stun_all - if("checkxenos") - Parent_Turret.check_anomalies = !Parent_Turret.check_anomalies - - updateUsrDialog() - - - -/obj/machinery/porta_turret_cover/attackby(obj/item/W as obj, mob/user as mob, params) - - if ((istype(W, /obj/item/weapon/card/emag)) && (!Parent_Turret.emagged)) - user << "\red You short out [Parent_Turret]'s threat assessment circuits." - spawn(0) - for(var/mob/O in hearers(Parent_Turret, null)) - O.show_message("\red [Parent_Turret] hums oddly...", 1) - Parent_Turret.emagged = 1 - Parent_Turret.on = 0 - sleep(40) - Parent_Turret.on = 1 - - else if((istype(W, /obj/item/weapon/wrench)) && (!Parent_Turret.on)) - if(Parent_Turret.raised) return - - if(!Parent_Turret.anchored) - Parent_Turret.anchored = 1 - Parent_Turret.invisibility = INVISIBILITY_LEVEL_TWO - Parent_Turret.icon_state = "grey_target_prism" - user << "You secure the exterior bolts on the turret." - else - Parent_Turret.anchored = 0 - user << "You unsecure the exterior bolts on the turret." - Parent_Turret.icon_state = "turretCover" - Parent_Turret.invisibility = 0 - del(src) - - else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - if (Parent_Turret.allowed(user)) - Parent_Turret.locked = !Parent_Turret.locked - user << "Controls are now [Parent_Turret.locked ? "locked." : "unlocked."]" - updateUsrDialog() - else - user << "\red Access denied." - - else - Parent_Turret.health -= W.force * 0.5 - if (Parent_Turret.health <= 0) - Parent_Turret.die() - if ((W.force * 0.5) > 2) - if(!Parent_Turret.attacked && !Parent_Turret.emagged) - Parent_Turret.attacked = 1 - spawn() - sleep(30) - Parent_Turret.attacked = 0 - ..() - - - - -/obj/machinery/porta_turret/stationary - emagged = 1 - - New() - installation = new/obj/item/weapon/gun/energy/laser(src.loc) - ..() +/obj/machinery/porta_turret_cover/attackby(obj/item/I, mob/user) + Parent_Turret.attackby(I, user) diff --git a/code/game/machinery/turret_control.dm b/code/game/machinery/turret_control.dm new file mode 100644 index 00000000000..3b7b48b48d1 --- /dev/null +++ b/code/game/machinery/turret_control.dm @@ -0,0 +1,220 @@ +//////////////////////// +//Turret Control Panel// +//////////////////////// + +/area + // Turrets use this list to see if individual power/lethal settings are allowed + var/list/turret_controls = list() + +/obj/machinery/turretid + name = "turret control panel" + desc = "Used to control a room's automated defenses." + icon = 'icons/obj/machines/turret_control.dmi' + icon_state = "control_standby" + anchored = 1 + density = 0 + var/enabled = 0 + var/lethal = 0 + var/locked = 1 + 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 + + req_access = list(access_ai_upload) + +/obj/machinery/turretid/stun + enabled = 1 + icon_state = "control_stun" + +/obj/machinery/turretid/lethal + enabled = 1 + lethal = 1 + icon_state = "control_kill" + +/obj/machinery/turretid/Del() + if(control_area) + var/area/A = control_area + if(A && istype(A)) + A.turret_controls -= src + ..() + +/obj/machinery/turretid/initialize() + if(!control_area) + var/area/CA = get_area(src) + control_area = CA.master + else if(istext(control_area)) + for(var/area/A in world) + if(A.name && A.name==control_area) + control_area = A.master + break + + if(control_area) + var/area/A = control_area + if(istype(A)) + A.turret_controls += src + else + control_area = null + + power_change() //Checks power and initial settings + return + +/obj/machinery/turretid/proc/isLocked(mob/user) + if(ailock && (isrobot(user) || isAI(user))) + user << "There seems to be a firewall preventing you from accessing this device." + return 1 + + if(locked && !(isrobot(user) || isAI(user))) + user << "Access denied." + return 1 + + return 0 + +/obj/machinery/turretid/attackby(obj/item/weapon/W, mob/user) + if(stat & BROKEN) + return + + if(!emagged && istype(W, /obj/item/weapon/card/emag)) + user << "You short out the turret controls' access analysis module." + emagged = 1 + locked = 0 + ailock = 0 + return + + if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) + if(src.allowed(usr)) + if(emagged) + user << "The turret control is unresponsive." + else + locked = !locked + user << "You [ locked ? "lock" : "unlock"] the panel." + return + return ..() + +/obj/machinery/turretid/attack_ai(mob/user as mob) + if(isLocked(user)) + return + + ui_interact(user) + +/obj/machinery/turretid/attack_hand(mob/user as mob) + if(isLocked(user)) + return + + ui_interact(user) + +/obj/machinery/turretid/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + var/data[0] + data["access"] = !isLocked(user) + data["locked"] = locked + data["enabled"] = enabled + data["is_lethal"] = 1 + data["lethal"] = lethal + + if(data["access"]) + 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 + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 300) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) + +/obj/machinery/turretid/Topic(href, href_list, var/nowindow = 0) + if(..()) + return 1 + + 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(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 + +/obj/machinery/turretid/proc/updateTurrets() + var/datum/turret_checks/TC = new + TC.enabled = enabled + TC.lethal = lethal + TC.check_synth = check_synth + TC.check_access = check_access + TC.check_records = check_records + TC.check_arrest = check_arrest + TC.check_weapons = check_weapons + TC.check_anomalies = check_anomalies + TC.ailock = ailock + + if(istype(control_area)) + for(var/area/sub_area in control_area.related) + for (var/obj/machinery/porta_turret/aTurret in sub_area) + aTurret.setState(TC) + + update_icon() + +/obj/machinery/turretid/power_change() + ..() + updateTurrets() + update_icon() + +/obj/machinery/turretid/update_icon() + ..() + if(stat & NOPOWER) + icon_state = "control_off" + else if (enabled) + if (lethal) + icon_state = "control_kill" + else + icon_state = "control_stun" + else + icon_state = "control_standby" + +/obj/machinery/turretid/emp_act(severity) + if(enabled) + //if the turret is on, the EMP no matter how severe disables the turret for a while + //and scrambles its settings, with a slight chance of having an emag effect + + check_arrest = pick(0, 1) + check_records = pick(0, 1) + check_weapons = pick(0, 1) + check_access = pick(0, 0, 0, 0, 1) // check_access is a pretty big deal, so it's least likely to get turned on + check_anomalies = pick(0, 1) + + enabled=0 + updateTurrets() + + sleep(rand(60,600)) + if(!enabled) + enabled=1 + updateTurrets() + + ..() diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index 0f31d45c124..171586d255a 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -331,110 +331,7 @@ spawn(13) qdel(src) -/obj/machinery/turretid - name = "turret deactivation control" - icon = 'icons/obj/device.dmi' - icon_state = "control_stun" - anchored = 1 - density = 0 - var/enabled = 1 - var/lethal = 0 - var/locked = 1 - var/control_area //can be area name, path or nothing. - var/ailock = 0 // AI cannot use this - req_access = list(access_ai_upload) - -/obj/machinery/turretid/New() - ..() - if(!control_area) - var/area/CA = get_area(src) - if(CA.master && CA.master != CA) - control_area = CA.master - else - control_area = CA - else if(istext(control_area)) - for(var/area/A in world) - if(A.name && A.name==control_area) - control_area = A - break - //don't have to check if control_area is path, since get_area_all_atoms can take path. - return - -/obj/machinery/turretid/attackby(obj/item/weapon/W, mob/user, params) - if(stat & BROKEN) return - if (istype(user, /mob/living/silicon)) - return src.attack_hand(user) - - else if( get_dist(src, user) == 0 ) // trying to unlock the interface - if (src.allowed(usr)) - if(emagged) - user << "The turret control is unresponsive." - return - - locked = !locked - user << "You [ locked ? "lock" : "unlock"] the panel." - if (locked) - if (user.machine==src) - user.unset_machine() - user << browse(null, "window=turretid") - else - if (user.machine==src) - src.attack_hand(user) - else - user << "Access denied." - -/obj/machinery/turretid/emag_act(user as mob) - if (!emagged) - if(!ishuman(user)) - return - var/mob/living/carbon/human/H = user - user << "\red You short out the turret controls' access analysis module." - emagged = 1 - locked = 0 - if(H.machine==src) - src.attack_hand(user) - -/obj/machinery/turretid/attack_ai(mob/user as mob) - if(!ailock) - return attack_hand(user) - else - user << "There seems to be a firewall preventing you from accessing this device." - -/obj/machinery/turretid/attack_hand(mob/user as mob) - if ( get_dist(src, user) > 0 ) - if ( !issilicon(user) ) - user << "You are too far away." - user.unset_machine() - user << browse(null, "window=turretid;size=500x250") - return - - user.set_machine(src) - var/loc = src.loc - if (istype(loc, /turf)) - loc = loc:loc - if (!istype(loc, /area)) - user << text("Turret badly positioned - loc.loc is [].", loc) - return - var/area/area = loc - var/t = "" - - if(src.locked && (!istype(user, /mob/living/silicon))) - t += "
Swipe ID card to unlock interface
" - else - if (!istype(user, /mob/living/silicon)) - t += "
Swipe ID card to lock interface
" - t += text("Turrets [] - []?
\n", src.enabled?"activated":"deactivated", src, src.enabled?"Disable":"Enable") - t += text("Currently set for [] - Change to []?
\n", src.lethal?"lethal":"stun repeatedly", src, src.lethal?"Stun repeatedly":"Lethal") - - //user << browse(t, "window=turretid;size=500x250") - //onclose(user, "turretid") - var/datum/browser/popup = new(user, "turretid", "Turret Control Panel ([area.name])", 500, 250) - popup.set_content(t) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - - - + /obj/machinery/turret/attack_animal(mob/living/simple_animal/M as mob) M.changeNext_move(CLICK_CD_MELEE) M.do_attack_animation(src) @@ -484,12 +381,6 @@ if(!nowindow) src.attack_hand(usr) -/obj/machinery/turretid/proc/updateTurrets() - if(control_area) - for (var/obj/machinery/turret/aTurret in get_area_all_atoms(control_area)) - aTurret.setState(enabled, lethal) - src.update_icons() - /obj/machinery/turretid/proc/update_icons() if (src.enabled) if (src.lethal) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index cf334f54def..cf801fc4311 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -158,6 +158,13 @@ proc/isnewplayer(A) proc/hasorgans(A) return ishuman(A) + +proc/iscuffed(A) + if(istype(A, /mob/living/carbon)) + var/mob/living/carbon/C = A + if(C.handcuffed) + return 1 + return 0 proc/isdeaf(A) if(istype(A, /mob)) diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm index 096c5f0f9c2..884fee74982 100644 --- a/code/modules/nano/nanoui.dm +++ b/code/modules/nano/nanoui.dm @@ -144,10 +144,9 @@ nanoui is used to open and update nano browser uis return var/status = user.can_interact_with_interface(host.nano_host()) + set_status(status, push_update) if(status == STATUS_CLOSE) close() - else - set_status(status, push_update) /* Procs called by update_status() @@ -501,6 +500,8 @@ nanoui is used to open and update nano browser uis if (width && height) window_size = "size=[width]x[height];" update_status(0) + if(status == STATUS_CLOSE) + return var/html=get_html() if(src.writeDebug) var/f = file("nano/debug.html") diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index bd72edb6955..21146c38573 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -36,6 +36,7 @@ var/last_fired = 0 var/obj/item/device/flashlight/F = null var/can_flashlight = 0 + var/heavy_weapon = 0 proc/ready_to_fire() if(world.time >= last_fired + fire_delay) @@ -122,6 +123,12 @@ if(!in_chamber) return + + if(heavy_weapon) + if(user.get_inactive_hand()) + recoil = 4 //one-handed kick + else + recoil = initial(recoil) in_chamber.firer = user in_chamber.def_zone = user.zone_sel.selecting diff --git a/code/modules/projectiles/guns/energy/nuclear.dm b/code/modules/projectiles/guns/energy/nuclear.dm index 3a278424dc1..d744525ee17 100644 --- a/code/modules/projectiles/guns/energy/nuclear.dm +++ b/code/modules/projectiles/guns/energy/nuclear.dm @@ -130,3 +130,38 @@ update_charge() update_reactor() update_mode() + + +/obj/item/weapon/gun/energy/gun/turret + name = "hybrid turret gun" + desc = "A heavy hybrid energy cannon with two settings: Stun and kill." + icon_state = "turretlaser" + slot_flags = null + w_class = 5 + heavy_weapon = 1 + can_flashlight = 0 + +/obj/item/weapon/gun/energy/gun/turret/update_icon() + icon_state = initial(icon_state) + +/obj/item/weapon/gun/energy/gun/turret/attack_self(mob/living/user as mob) + switch(mode) + if(0) + mode = 1 + charge_cost = 1000 + fire_sound = 'sound/weapons/Laser.ogg' + user << "\red [src.name] is now set to kill." + projectile_type = "/obj/item/projectile/beam" + modifystate = "energykill" + if(1) + mode = 0 + charge_cost = 500 + fire_sound = 'sound/weapons/Taser2.ogg' + user << "\red [src.name] is now set to disable." + projectile_type = "/obj/item/projectile/beam/disabler" + modifystate = "energystun" + update_icon() + if(user.l_hand == src) + user.update_inv_l_hand() + else + user.update_inv_r_hand() \ No newline at end of file diff --git a/icons/obj/machines/turret_control.dmi b/icons/obj/machines/turret_control.dmi new file mode 100644 index 0000000000000000000000000000000000000000..b7c81cd923e5a7e75a96cc982625d81cc07cd8c9 GIT binary patch literal 700 zcmV;t0z>_YP)C0000pP)t-sz`(#7 z8X7k@H!UqKB_$;l6%_!P003qH05bq)009300GR*)|Nj90%mDwH0L%aYz`(%qpyECN z0004WQchCV=-0C=2JR&a84_w-Y6@%7{?OD!tS z%+FJ>RWQ*r;NmRLOex6#a*U0*I5Sc+(=$pSoZ^zil2jm5DLFr{q$ocpK0hr@iHkEO zv#1y-YRJWzR+N~V3S}3imS^UrfY})OfC70bNtM|3ngB&pa}p~-!a86`$gt8p>X?+B znUh17Ny-YYelFmU1ORc7U-56+F%tj)0g*{WK~#90?V90kgD?<-A%PXh3h)26yJkoc z+T{WY2Bi7>i7mwnDXI^eh7dxCLMz;=JHc?^buV;T2TE_-b!WuT_kRs=-MMvVbOT=Z zo$$G?8sy^FYZxs3B?e0$#E{ju0mi-`tpK{70_b`Qpy=Z0B5{i}16to4l2Nb@5k!x8 z7Y$PglWIWgzXsQ?dv(43aX9CVMo&xB43ZUr6`u!rDtsm<5kV6>R+3&MIvs#_=frj$| zLI@#*5VG?4`GE1a`V_s`@AEGnYxD!v3iE3BK)+YZYqjoY>CaZbpOz4;`o4(4(t{ZC zukSYj^nRZL=mApzT~7h@TYRA3tGB39zkf&-LHGZ&<^$OWRjtnX03n1BLI`;brTz|I zztG>|>lgYxY~4MdUL)5p^mqLFK1hEyKEJ;*K)$^q6BPS9Ji(s+j;7e(F9~4wcYK0U ie}^Yve