diff --git a/baystation12.dme b/baystation12.dme index d6169d21a0b..ed72c127bf1 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -168,7 +168,14 @@ #include "code\datums\spells\turf_teleport.dm" #include "code\datums\spells\wizard.dm" #include "code\datums\wires\airlock.dm" +#include "code\datums\wires\alarm.dm" #include "code\datums\wires\apc.dm" +#include "code\datums\wires\camera.dm" +#include "code\datums\wires\explosive.dm" +#include "code\datums\wires\mulebot.dm" +#include "code\datums\wires\particle_accelerator.dm" +#include "code\datums\wires\radio.dm" +#include "code\datums\wires\robot.dm" #include "code\datums\wires\vending.dm" #include "code\datums\wires\wires.dm" #include "code\defines\obj.dm" @@ -357,7 +364,6 @@ #include "code\game\machinery\camera\motion.dm" #include "code\game\machinery\camera\presets.dm" #include "code\game\machinery\camera\tracking.dm" -#include "code\game\machinery\camera\wires.dm" #include "code\game\machinery\computer\ai_core.dm" #include "code\game\machinery\computer\aifixer.dm" #include "code\game\machinery\computer\arcade.dm" @@ -1070,7 +1076,6 @@ #include "code\modules\mob\living\silicon\robot\robot_items.dm" #include "code\modules\mob\living\silicon\robot\robot_modules.dm" #include "code\modules\mob\living\silicon\robot\robot_movement.dm" -#include "code\modules\mob\living\silicon\robot\wires.dm" #include "code\modules\mob\living\simple_animal\bees.dm" #include "code\modules\mob\living\simple_animal\borer.dm" #include "code\modules\mob\living\simple_animal\constructs.dm" diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index af1641f804d..4d8eca375e8 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -77,7 +77,6 @@ proc/age2agedescription(age) else return "unknown" - /* Proc for attack log creation, because really why not 1 argument is the actor @@ -95,4 +94,4 @@ proc/add_logs(mob/target, mob/user, what_done, var/object=null, var/addition=nul log_attack("[user.name][ismob(user) ? "([user.ckey])" : ""] [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition]") if(target.client) if(what_done != ("shaked" || "CPRed" || "grabbed")) - message_admins("[user.name][ismob(user) ? "([user.ckey])" : ""] [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition](JMP)") \ No newline at end of file + message_admins("[user.name][ismob(user) ? "([user.ckey])" : ""] [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition](JMP)") diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index ece685d28cc..e4a627088c7 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -551,6 +551,14 @@ Turf and target are seperate in case you want to teleport some distance from a t /proc/key_name_admin(var/whom, var/include_name = 1) return key_name(whom, 1, include_name) +// Returns the atom sitting on the turf. +// For example, using this on a disk, which is in a bag, on a mob, will return the mob because it's on the turf. +/proc/get_atom_on_turf(var/atom/movable/M) + var/atom/loc = M + while(loc && loc.loc && !istype(loc.loc, /turf/)) + loc = loc.loc + return loc + // Registers the on-close verb for a browse window (client/verb/.windowclose) // this will be called when the close-button of a window is pressed. diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index 436be01cbd4..51f3f3385ed 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -97,7 +97,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048 //Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. if(A.secondsElectrified != -1) A.shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])") - usr.attack_log += text("\[[time_stamp()]\] Electrified the [A.name] at [A.x] [A.y] [A.z]") + add_logs(usr, A, "electrified", admin=0, addition="at [A.x],[A.y],[A.z]") A.secondsElectrified = -1 else if(A.secondsElectrified == -1) @@ -163,7 +163,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048 //one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. if(A.secondsElectrified==0) A.shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])") - usr.attack_log += text("\[[time_stamp()]\] Electrified the [A.name] at [A.x] [A.y] [A.z]") + add_logs(usr, A, "electrified", admin=0, addition="at [A.x],[A.y],[A.z]") A.secondsElectrified = 30 spawn(10) if(A) diff --git a/code/datums/wires/alarm.dm b/code/datums/wires/alarm.dm index 2c826e6d527..c1c45096bbc 100644 --- a/code/datums/wires/alarm.dm +++ b/code/datums/wires/alarm.dm @@ -47,8 +47,8 @@ var/const/AALARM_WIRE_AALARM = 16 //world << "Syphon Wire Cut" if(AALARM_WIRE_AALARM) - if (A.alarm_area.atmosalert(2)) - A.post_alert(2) + //if (A.alarm_area.atmosalert(2)) + // A.post_alert(2) A.update_icon() /datum/wires/alarm/UpdatePulsed(var/index) @@ -89,6 +89,6 @@ var/const/AALARM_WIRE_AALARM = 16 if(AALARM_WIRE_AALARM) // world << "Aalarm wire pulsed" - if (A.alarm_area.atmosalert(0)) - A.post_alert(0) + //if (A.alarm_area.atmosalert(0)) + // A.post_alert(0) A.update_icon() diff --git a/code/datums/wires/apc.dm b/code/datums/wires/apc.dm index b6839a86204..96075d5941f 100644 --- a/code/datums/wires/apc.dm +++ b/code/datums/wires/apc.dm @@ -29,15 +29,16 @@ var/const/APC_WIRE_AI_CONTROL = 8 A.locked = 0 spawn(300) - A.locked = 1 - A.updateDialog() + if(A) + A.locked = 1 + A.updateDialog() if (APC_WIRE_MAIN_POWER1, APC_WIRE_MAIN_POWER2) if(A.shorted == 0) A.shorted = 1 spawn(1200) - if(!IsIndexCut(APC_WIRE_MAIN_POWER1) && !IsIndexCut(APC_WIRE_MAIN_POWER2)) + if(A && !IsIndexCut(APC_WIRE_MAIN_POWER1) && !IsIndexCut(APC_WIRE_MAIN_POWER2)) A.shorted = 0 A.updateDialog() @@ -46,7 +47,7 @@ var/const/APC_WIRE_AI_CONTROL = 8 A.aidisabled = 1 spawn(10) - if(!IsIndexCut(APC_WIRE_AI_CONTROL)) + if(A && !IsIndexCut(APC_WIRE_AI_CONTROL)) A.aidisabled = 0 A.updateDialog() diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm index 9dbbb9ff0a7..e05b543d420 100644 --- a/code/datums/wires/robot.dm +++ b/code/datums/wires/robot.dm @@ -3,11 +3,21 @@ holder_type = /mob/living/silicon/robot wire_count = 5 -var/const/BORG_WIRE_LAWCHECK = 1 -var/const/BORG_WIRE_MAIN_POWER = 2 // The power wires do nothing whyyyyyyyyyyyyy +/* /tg/ ordering doesn't work for us, we need lawsync at the end for MoMMIs. +var/const/BORG_WIRE_LAWCHECK = 1 +var/const/BORG_WIRE_MAIN_POWER = 2 // The power wires do nothing whyyyyyyyyyyyyy var/const/BORG_WIRE_LOCKED_DOWN = 4 -var/const/BORG_WIRE_AI_CONTROL = 8 -var/const/BORG_WIRE_CAMERA = 16 +var/const/BORG_WIRE_AI_CONTROL = 8 +var/const/BORG_WIRE_CAMERA = 16 +*/ + +// /vg/ ordering + +var/const/BORG_WIRE_MAIN_POWER = 1 // The power wires do nothing whyyyyyyyyyyyyy +var/const/BORG_WIRE_LOCKED_DOWN = 2 +var/const/BORG_WIRE_CAMERA = 4 +var/const/BORG_WIRE_AI_CONTROL = 8 // Not used on MoMMIs +var/const/BORG_WIRE_LAWCHECK = 16 // Not used on MoMMIs /datum/wires/robot/GetInteractWindow() @@ -76,4 +86,10 @@ var/const/BORG_WIRE_CAMERA = 16 return wires_status & BORG_WIRE_CAMERA /datum/wires/robot/proc/LockedCut() - return wires_status & BORG_WIRE_LOCKED_DOWN \ No newline at end of file + return wires_status & BORG_WIRE_LOCKED_DOWN + +/datum/wires/robot/proc/CanLawCheck() + return wires_status & BORG_WIRE_LAWCHECK + +/datum/wires/robot/proc/AIHasControl() + return wires_status & BORG_WIRE_AI_CONTROL \ No newline at end of file diff --git a/code/datums/wires/syndicatebomb.dm b/code/datums/wires/syndicatebomb.dm index 77700d9d028..8c60b0e4546 100644 --- a/code/datums/wires/syndicatebomb.dm +++ b/code/datums/wires/syndicatebomb.dm @@ -11,6 +11,8 @@ var/const/WIRE_ACTIVATE = 16 // Will start a bombs timer if pulsed, will hint if /datum/wires/syndicatebomb/UpdatePulsed(var/index) var/obj/machinery/syndicatebomb/P = holder + if(P.degutted) + return switch(index) if(WIRE_BOOM) if (P.active) @@ -47,6 +49,8 @@ var/const/WIRE_ACTIVATE = 16 // Will start a bombs timer if pulsed, will hint if /datum/wires/syndicatebomb/UpdateCut(var/index, var/mended) var/obj/machinery/syndicatebomb/P = holder + if(P.degutted) + return switch(index) if(WIRE_EXPLODE) if(!mended) diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index a897226a948..751542dc327 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -579,19 +579,6 @@ var/obj/machinery/machine -/obj/item/weapon/plastique - name = "plastic explosives" - desc = "Used to put holes in specific areas without too much extra hole." - gender = PLURAL - icon = 'icons/obj/assemblies.dmi' - icon_state = "plastic-explosive0" - item_state = "plasticx" - flags = FPRINT | TABLEPASS | NOBLUDGEON - w_class = 2.0 - origin_tech = "syndicate=2" - var/timer = 10 - var/atom/target = null - ///////////////////////////////////////Stock Parts ///////////////////////////////// /obj/item/weapon/stock_parts diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 3022049e587..428475ec7f7 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -2,32 +2,6 @@ //CONTAINS: Air Alarms and Fire Alarms// //////////////////////////////////////// -/proc/RandomAAlarmWires() - //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else). - var/list/AAlarmwires = list(0, 0, 0, 0, 0) - AAlarmIndexToFlag = list(0, 0, 0, 0, 0) - AAlarmIndexToWireColor = list(0, 0, 0, 0, 0) - AAlarmWireColorToIndex = list(0, 0, 0, 0, 0) - var/flagIndex = 1 - for (var/flag=1, flag<32, flag+=flag) - var/valid = 0 - while (!valid) - var/colorIndex = rand(1, 5) - if (AAlarmwires[colorIndex]==0) - valid = 1 - AAlarmwires[colorIndex] = flag - AAlarmIndexToFlag[flagIndex] = flag - AAlarmIndexToWireColor[flagIndex] = colorIndex - AAlarmWireColorToIndex[colorIndex] = flagIndex - flagIndex+=1 - return AAlarmwires - -#define AALARM_WIRE_IDSCAN 1 //Added wires -#define AALARM_WIRE_POWER 2 -#define AALARM_WIRE_SYPHON 3 -#define AALARM_WIRE_AI_CONTROL 4 -#define AALARM_WIRE_AALARM 5 - #define AALARM_MODE_SCRUBBING 1 #define AALARM_MODE_REPLACEMENT 2 //like scrubbing, but faster. #define AALARM_MODE_PANIC 3 //constantly sucks all air @@ -82,6 +56,7 @@ var/rcon_setting = 2 var/rcon_time = 0 var/locked = 1 + var/datum/wires/alarm/wires = null var/wiresexposed = 0 // If it's been screwdrivered open. var/aidisabled = 0 var/AAlarmwires = 31 @@ -153,6 +128,7 @@ /obj/machinery/alarm/New(var/loc, var/dir, var/building = 0) ..() + wires = new(src) if(building) if(loc) @@ -279,6 +255,8 @@ return /obj/machinery/alarm/proc/calculate_local_danger_level() + if(wires.IsIndexCut(AALARM_WIRE_AALARM)) + return 2 // MAXIMUM ALARM (With gravelly voice) - N3X var/turf/simulated/location = loc if(!istype(location)) return//returns if loc is not simulated @@ -542,118 +520,7 @@ E:air_locked = null E.update_icon()*/ -/////////// -//HACKING// -/////////// -/obj/machinery/alarm/proc/isWireColorCut(var/wireColor) - var/wireFlag = AAlarmWireColorToFlag[wireColor] - return ((AAlarmwires & wireFlag) == 0) -/obj/machinery/alarm/proc/isWireCut(var/wireIndex) - var/wireFlag = AAlarmIndexToFlag[wireIndex] - return ((AAlarmwires & wireFlag) == 0) - -/obj/machinery/alarm/proc/allWiresCut() - var/i = 1 - while(i<=5) - if(AAlarmwires & AAlarmIndexToFlag[i]) - return 0 - i++ - return 1 - -/obj/machinery/alarm/proc/cut(var/wireColor) - var/wireFlag = AAlarmWireColorToFlag[wireColor] - var/wireIndex = AAlarmWireColorToIndex[wireColor] - AAlarmwires &= ~wireFlag - switch(wireIndex) - if(AALARM_WIRE_IDSCAN) - locked = 1 - - if(AALARM_WIRE_POWER) - shock(usr, 50) - shorted = 1 - update_icon() - - if (AALARM_WIRE_AI_CONTROL) - if (aidisabled == 0) - aidisabled = 1 - - if(AALARM_WIRE_SYPHON) - mode = AALARM_MODE_PANIC - apply_mode() - - if(AALARM_WIRE_AALARM) - alarmActivated=1 - alarm_area.updateDangerLevel() - spawn(1) - updateUsrDialog() - update_icon() - - updateDialog() - - return - -/obj/machinery/alarm/proc/mend(var/wireColor) - var/wireFlag = AAlarmWireColorToFlag[wireColor] - var/wireIndex = AAlarmWireColorToIndex[wireColor] //not used in this function - AAlarmwires |= wireFlag - switch(wireIndex) - if(AALARM_WIRE_IDSCAN) - - if(AALARM_WIRE_POWER) - shorted = 0 - shock(usr, 50) - update_icon() - - if(AALARM_WIRE_AI_CONTROL) - if (aidisabled == 1) - aidisabled = 0 - - updateDialog() - return - -/obj/machinery/alarm/proc/pulse(var/wireColor) - //var/wireFlag = AAlarmWireColorToFlag[wireColor] //not used in this function - var/wireIndex = AAlarmWireColorToIndex[wireColor] - switch(wireIndex) - if(AALARM_WIRE_IDSCAN) //unlocks for 30 seconds, if you have a better way to hack I'm all ears - locked = 0 - spawn(300) - locked = 1 - - if (AALARM_WIRE_POWER) - if(shorted == 0) - shorted = 1 - update_icon() - - spawn(1200) - if(shorted == 1) - shorted = 0 - update_icon() - - - if (AALARM_WIRE_AI_CONTROL) - if (aidisabled == 0) - aidisabled = 1 - updateDialog() - spawn(10) - if (aidisabled == 1) - aidisabled = 0 - updateDialog() - - if(AALARM_WIRE_SYPHON) - mode = AALARM_MODE_REPLACEMENT - apply_mode() - - if(AALARM_WIRE_AALARM) - alarmActivated=0 - alarm_area.updateDangerLevel() - spawn(1) - updateUsrDialog() - update_icon() - - updateDialog() - return /obj/machinery/alarm/proc/shock(mob/user, prb) if((stat & (NOPOWER))) // unpowered, no shock @@ -848,35 +715,12 @@ user << browse(null, "window=air_alarm") return - if(wiresexposed && (!istype(user, /mob/living/silicon))) - var/t1 = text("[alarm_area.name] Air Alarm WiresAccess Panel
\n") - var/list/wirecolors = list( - "Orange" = 1, - "Dark red" = 2, - "White" = 3, - "Yellow" = 4, - "Black" = 5, - ) - for(var/wiredesc in wirecolors) - var/is_uncut = AAlarmwires & AAlarmWireColorToFlag[wirecolors[wiredesc]] - t1 += "[wiredesc] wire: " - if(!is_uncut) - t1 += "Mend" - else - t1 += "Cut " - t1 += "Pulse " - - t1 += "
" - t1 += text("
\n[(locked ? "The Air Alarm is locked." : "The Air Alarm is unlocked.")]
\n[((shorted || (stat & (NOPOWER|BROKEN))) ? "The Air Alarm is offline." : "The Air Alarm is working properly!")]
\n[(aidisabled ? "The 'AI control allowed' light is off." : "The 'AI control allowed' light is on.")]") - t1 += text("

Close

") - user << browse(t1, "window=AAlarmwires") - onclose(user, "AAlarmwires") + if(wiresexposed && !istype(user, /mob/living/silicon)) + wires.Interact(user) if(!shorted) ui_interact(user) - return - /obj/machinery/alarm/Topic(href, href_list) var/changed=0 @@ -1022,34 +866,6 @@ target_temperature = input_temperature + T0C ui_interact(usr) return 1 - - if (href_list["AAlarmwires"]) - var/t1 = text2num(href_list["AAlarmwires"]) - if (!( istype(usr.equipped(), /obj/item/weapon/wirecutters) )) - usr << "You need wirecutters!" - return - if (isWireColorCut(t1)) - mend(t1) - changed=1 - else - cut(t1) - if (AAlarmwires == 0) - usr << "You cut last of wires inside [src]" - update_icon() - buildstage = 1 - return - - else if (href_list["pulse"]) - var/t1 = text2num(href_list["pulse"]) - if (!istype(usr.equipped(), /obj/item/device/multitool)) - usr << "You need a multitool!" - return - if (isWireColorCut(t1)) - usr << "You can't pulse a cut wire." - return - else - pulse(t1) - changed=1 if(changed) updateUsrDialog() @@ -1082,7 +898,7 @@ user << "It does nothing" return else - if(allowed(usr) && !isWireCut(AALARM_WIRE_IDSCAN)) + if(allowed(usr) && !wires.IsIndexCut(AALARM_WIRE_IDSCAN)) locked = !locked user << "\blue You [ locked ? "lock" : "unlock"] the Air Alarm interface." updateUsrDialog() diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm index 3e392a5c4d9..1d548de3bd1 100644 --- a/code/game/machinery/bots/mulebot.dm +++ b/code/game/machinery/bots/mulebot.dm @@ -4,9 +4,10 @@ // Navigates via floor navbeacons // Remote Controlled from QM's PDA +var/global/mulebot_count = 0 /obj/machinery/bot/mulebot - name = "Mulebot" + name = "\improper MULEbot" desc = "A Multiple Utility Load Effector bot." icon_state = "mulebot0" layer = MOB_LAYER @@ -48,30 +49,24 @@ var/auto_pickup = 1 // true if auto-pickup at beacon var/obj/item/weapon/cell/cell + var/datum/wires/mulebot/wires = null // the installed power cell // constants for internal wiring bitflags - var/const/wire_power1 = 1 // power connections - var/const/wire_power2 = 2 - var/const/wire_mobavoid = 4 // mob avoidance - var/const/wire_loadcheck = 8 // load checking (non-crate) - var/const/wire_motor1 = 16 // motor wires - var/const/wire_motor2 = 32 // - var/const/wire_remote_rx = 64 // remote recv functions - var/const/wire_remote_tx = 128 // remote trans status - var/const/wire_beacon_rx = 256 // beacon ping recv - var/const/wire_beacon_tx = 512 // beacon ping trans + /* var/wires = 1023 // all flags on var/list/wire_text // list of wire colours var/list/wire_order // order of wire indices + */ var/bloodiness = 0 // count of bloodiness /obj/machinery/bot/mulebot/New() ..() + wires = new(src) botcard = new(src) var/datum/job/cargo_tech/J = new/datum/job/cargo_tech botcard.access = J.get_access() @@ -79,41 +74,21 @@ cell = new(src) cell.charge = 2000 cell.maxcharge = 2000 - setup_wires() spawn(5) // must wait for map loading to finish if(radio_controller) radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT) radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) - var/count = 0 - for(var/obj/machinery/bot/mulebot/other in world) - count++ + mulebot_count += 1 if(!suffix) - suffix = "#[count]" - name = "Mulebot ([suffix])" + suffix = "#[mulebot_count]" + name = "\improper Mulebot ([suffix])" + verbs -= /atom/movable/verb/pull -// set up the wire colours in random order -// and the random wire display order -// needs 10 wire colours -/obj/machinery/bot/mulebot/proc/setup_wires() - var/list/colours = list("Red", "Green", "Blue", "Magenta", "Cyan", "Yellow", "Black", "White", "Orange", "Grey") - var/list/orders = list("0","1","2","3","4","5","6","7","8","9") - wire_text = list() - wire_order = list() - while(colours.len > 0) - var/colour = colours[ rand(1,colours.len) ] - wire_text += colour - colours -= colour - - var/order = orders[ rand(1,orders.len) ] - wire_order += text2num(order) - orders -= order - - // attack by item // emag : lock/unlock, @@ -126,6 +101,10 @@ user << "\blue You [locked ? "lock" : "unlock"] the mulebot's controls!" flick("mulebot-emagged", src) playsound(src.loc, 'sound/effects/sparks1.ogg', 100, 0) + else if(istype(I, /obj/item/weapon/card/id)) + if(toggle_lock(user)) + user << "\blue Controls [(locked ? "locked" : "unlocked")]." + else if(istype(I,/obj/item/weapon/cell) && open && !cell) var/obj/item/weapon/cell/C = I user.drop_item() @@ -171,11 +150,10 @@ unload(0) switch(severity) if(2) - wires &= ~(1 << rand(0,9)) - wires &= ~(1 << rand(0,9)) - wires &= ~(1 << rand(0,9)) + for(var/i = 1; i < 3; i++) + wires.RandomCut() if(3) - wires &= ~(1 << rand(0,9)) + wires.RandomCut() ..() return @@ -184,11 +162,7 @@ unload(0) if(prob(25)) src.visible_message("\red Something shorts out inside [src]!") - var/index = 1<< (rand(0,9)) - if(wires & index) - wires &= ~index - else - wires |= index + wires.RandomCut() ..() @@ -282,18 +256,7 @@ // returns the wire panel text /obj/machinery/bot/mulebot/proc/wires() - var/t = "" - for(var/i = 0 to 9) - var/index = 1<0 && (wires & wire_power1) && (wires & wire_power2) + return !open && cell && cell.charge > 0 && wires.HasPower() + +/obj/machinery/bot/mulebot/proc/toggle_lock(var/mob/user) + if(src.allowed(user)) + locked = !locked + updateDialog() + return 1 + else + user << "\red Access denied." + return 0 // mousedrop a crate to load the bot // can load anything if emagged @@ -469,7 +405,7 @@ // called to load a crate /obj/machinery/bot/mulebot/proc/load(var/atom/movable/C) - if((wires & wire_loadcheck) && !istype(C,/obj/structure/closet/crate)) + if(wires.LoadCheck() && !istype(C,/obj/structure/closet/crate)) src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) return // if not emagged, only allow crates to be loaded @@ -567,7 +503,7 @@ on = 0 return if(on) - var/speed = ((wires & wire_motor1) ? 1:0) + ((wires & wire_motor2) ? 2:0) + var/speed = (wires.Motor1() ? 1 : 0) + (wires.Motor2() ? 2 : 0) //world << "speed: [speed]" switch(speed) if(0) @@ -658,7 +594,7 @@ blockcount++ mode = 4 if(blockcount == 3) - src.visible_message("[src] makes an annoyed buzzing sound", "You hear an electronic buzzing sound.") + src.visible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.") playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0) if(blockcount > 5) // attempt 5 times before recomputing @@ -676,7 +612,7 @@ return return else - src.visible_message("[src] makes an annoyed buzzing sound", "You hear an electronic buzzing sound.") + src.visible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.") playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0) //world << "Bad turf." mode = 5 @@ -714,7 +650,7 @@ // calculates a path to the current destination // given an optional turf to avoid /obj/machinery/bot/mulebot/proc/calc_path(var/turf/avoid = null) - src.path = AStar(src.loc, src.target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 250, id=botcard, exclude=avoid) + src.path = AStar(src.loc, src.target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_cardinal, 0, 250, id=botcard, exclude=avoid) if(!src.path) src.path = list() @@ -734,7 +670,7 @@ mode = 3 else mode = 2 - icon_state = "mulebot[(wires & wire_mobavoid) == wire_mobavoid]" + icon_state = "mulebot[(wires.MobAvoid() != 0)]" // starts bot moving to home // sends a beacon query to find @@ -742,7 +678,7 @@ spawn(0) set_destination(home_destination) mode = 4 - icon_state = "mulebot[(wires & wire_mobavoid) == wire_mobavoid]" + icon_state = "mulebot[(wires.MobAvoid() != 0)]" // called when bot reaches current target /obj/machinery/bot/mulebot/proc/at_target() @@ -757,7 +693,7 @@ // not loaded if(auto_pickup) // find a crate var/atom/movable/AM - if(!(wires & wire_loadcheck)) // if emagged, load first unanchored thing we find + if(!wires.LoadCheck()) // if emagged, load first unanchored thing we find for(var/atom/movable/A in get_step(loc, loaddir)) if(!A.anchored) AM = A @@ -781,7 +717,7 @@ // called when bot bumps into anything /obj/machinery/bot/mulebot/Bump(var/atom/obs) - if(!(wires & wire_mobavoid)) //usually just bumps, but if avoidance disabled knock over mobs + if(!wires.MobAvoid()) //usually just bumps, but if avoidance disabled knock over mobs var/mob/M = obs if(ismob(M)) if(istype(M,/mob/living/silicon/robot)) @@ -841,12 +777,12 @@ */ var/recv = signal.data["command"] // process all-bot input - if(recv=="bot_status" && (wires & wire_remote_rx)) + if(recv=="bot_status" && wires.RemoteRX()) send_status() recv = signal.data["command [suffix]"] - if(wires & wire_remote_rx) + if(wires.RemoteRX()) // process control input switch(recv) if("stop") @@ -886,7 +822,7 @@ // receive response from beacon recv = signal.data["beacon"] - if(wires & wire_beacon_rx) + if(wires.BeaconRX()) if(recv == new_destination) // if the recvd beacon location matches the set destination // the we will navigate there destination = new_destination @@ -896,7 +832,7 @@ loaddir = text2num(direction) else loaddir = 0 - icon_state = "mulebot[(wires & wire_mobavoid) == wire_mobavoid]" + icon_state = "mulebot[(wires.MobAvoid() != null)]" calc_path() updateDialog() @@ -907,9 +843,9 @@ // send a radio signal with multiple data key/values /obj/machinery/bot/mulebot/proc/post_signal_multiple(var/freq, var/list/keyval) - if(freq == beacon_freq && !(wires & wire_beacon_tx)) + if(freq == beacon_freq && !(wires.BeaconRX())) return - if(freq == control_freq && !(wires & wire_remote_tx)) + if(freq == control_freq && !(wires.RemoteTX())) return var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 9a99e5898f5..23a398ca8c8 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -8,25 +8,18 @@ active_power_usage = 10 layer = 5 + var/datum/wires/camera/wires = null // Wires datum var/list/network = list("SS13") var/c_tag = null var/c_tag_order = 999 var/status = 1.0 anchored = 1.0 - var/panel_open = 0 // 0 = Closed / 1 = Open var/invuln = null var/bugged = 0 var/obj/item/weapon/camera_assembly/assembly = null var/watcherslist = list() var/obj/item/device/camera_bug/hasbug = null - // WIRES - var/wires = 63 // 0b111111 - var/list/IndexToFlag = list() - var/list/IndexToWireColor = list() - var/list/WireColorToIndex = list() - var/list/WireColorToFlag = list() - //OTHER var/view_range = 7 @@ -37,7 +30,8 @@ var/busy = 0 /obj/machinery/camera/New() - WireColorToFlag = randomCameraWires() + wires = new(src) + assembly = new(src) assembly.state = 4 /* // Use this to look for cameras that have the same c_tag. @@ -113,7 +107,7 @@ /obj/machinery/camera/attackby(W as obj, mob/living/user as mob) // DECONSTRUCTION - if(isscrewdriver(W)) + if(istype(W, /obj/item/weapon/screwdriver)) //user << "You start to [panel_open ? "close" : "open"] the camera's panel." //if(toggle_panel(user)) // No delay because no one likes screwdrivers trying to be hip and have a duration cooldown panel_open = !panel_open @@ -121,10 +115,10 @@ "You screw the camera's panel [panel_open ? "open" : "closed"].") playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - else if((iswirecutter(W) || ismultitool(W)) && panel_open) - interact(user) + else if((istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/multitool)) && panel_open) + wires.Interact(user) - else if(iswelder(W) && canDeconstruct()) + else if(istype(W, /obj/item/weapon/weldingtool) && wires.CanDeconstruct()) if(weld(W, user)) if(assembly) assembly.loc = src.loc @@ -207,12 +201,20 @@ if(choice==1) status = !( src.status ) if (!(src.status)) - visible_message("\red [user] has deactivated [src]!") + if(user) + visible_message("\red [user] has deactivated [src]!") + add_hiddenprint(user) + else + visible_message("\red \The [src] deactivates!") playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) icon_state = "[initial(icon_state)]1" add_hiddenprint(user) else - visible_message("\red [user] has reactivated [src]!") + if(user) + visible_message("\red [user] has reactivated [src]!") + add_hiddenprint(user) + else + visible_message("\red \the [src] reactivates!") playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) icon_state = initial(icon_state) add_hiddenprint(user) @@ -306,4 +308,4 @@ return 0 return 1 busy = 0 - return 0 \ No newline at end of file + return 0 diff --git a/code/game/machinery/camera/wires.dm b/code/game/machinery/camera/wires.dm deleted file mode 100644 index 13f0a858616..00000000000 --- a/code/game/machinery/camera/wires.dm +++ /dev/null @@ -1,170 +0,0 @@ -#define CAMERA_WIRE_FOCUS 1 -#define CAMERA_WIRE_POWER 2 -#define CAMERA_WIRE_LIGHT 3 -#define CAMERA_WIRE_ALARM 4 -#define CAMERA_WIRE_NOTHING1 5 -#define CAMERA_WIRE_NOTHING2 6 - -/obj/machinery/camera/proc/randomCameraWires() - //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else). - var/list/wires = list(0, 0, 0, 0, 0, 0) - IndexToFlag = list(0, 0, 0, 0, 0, 0) - IndexToWireColor = list(0, 0, 0, 0, 0, 0) - WireColorToIndex = list(0, 0, 0, 0, 0, 0) - var/flagIndex = 1 - //I think it's easier to read this way, also doesn't rely on the random number generator to land on a new wire. - var/list/colorIndexList = list(CAMERA_WIRE_FOCUS, CAMERA_WIRE_POWER, CAMERA_WIRE_LIGHT, CAMERA_WIRE_ALARM, CAMERA_WIRE_NOTHING1, CAMERA_WIRE_NOTHING2) - for (var/flag=1, flag<=32, flag+=flag) - var/colorIndex = pick(colorIndexList) - if (wires[colorIndex]==0) - wires[colorIndex] = flag - IndexToFlag[flagIndex] = flag - IndexToWireColor[flagIndex] = colorIndex - WireColorToIndex[colorIndex] = flagIndex - colorIndexList -= colorIndex // Shortens the list. - //world.log << "Flag: [flag], CIndex: [colorIndex], FIndex: [flagIndex]" - flagIndex+=1 - return wires - -/obj/machinery/camera/proc/isWireColorCut(var/wireColor) - var/wireFlag = WireColorToFlag[wireColor] - return ((src.wires & wireFlag) == 0) - -/obj/machinery/camera/proc/isWireCut(var/wireIndex) - var/wireFlag = IndexToFlag[wireIndex] - return ((src.wires & wireFlag) == 0) - -/obj/machinery/camera/proc/canDeconstruct() - if(isWireCut(CAMERA_WIRE_POWER) && isWireCut(CAMERA_WIRE_FOCUS) && isWireCut(CAMERA_WIRE_LIGHT) && isWireCut(CAMERA_WIRE_NOTHING1) && isWireCut(CAMERA_WIRE_NOTHING2)) - return 1 - else - return 0 - -/obj/machinery/camera/proc/cut(var/wireColor) - var/wireFlag = WireColorToFlag[wireColor] - var/wireIndex = WireColorToIndex[wireColor] - wires &= ~wireFlag - switch(wireIndex) - if(CAMERA_WIRE_FOCUS) - setViewRange(short_range) - - if(CAMERA_WIRE_POWER) - deactivate(usr, 1) - //shock(usr) - - if(CAMERA_WIRE_LIGHT) - light_disabled = 1 - - if(CAMERA_WIRE_ALARM) - triggerCameraAlarm() - - src.interact(usr) - -/obj/machinery/camera/proc/mend(var/wireColor) - var/wireFlag = WireColorToFlag[wireColor] - var/wireIndex = WireColorToIndex[wireColor] - wires |= wireFlag - switch(wireIndex) - if(CAMERA_WIRE_FOCUS) - setViewRange(initial(view_range)) - - if(CAMERA_WIRE_POWER) - deactivate(usr, 1) - - if(CAMERA_WIRE_LIGHT) - light_disabled = 0 - - if(CAMERA_WIRE_ALARM) - cancelCameraAlarm() - - src.interact(usr) - - -/obj/machinery/camera/proc/pulse(var/wireColor) - var/wireIndex = WireColorToIndex[wireColor] - switch(wireIndex) - if(CAMERA_WIRE_FOCUS) - var/new_range = (view_range == initial(view_range) ? short_range : initial(view_range)) - setViewRange(new_range) - - if(CAMERA_WIRE_POWER) - deactivate(usr, 0) // Kicks anyone watching the camera - - if(CAMERA_WIRE_LIGHT) - light_disabled = !light_disabled - - if(CAMERA_WIRE_ALARM) - src.visible_message("\icon[src] *beep*", "\icon[src] *beep*") - - src.interact(usr) - -/obj/machinery/camera/interact(mob/living/user as mob) - if(!panel_open) - return - - user.set_machine(src) - var/t1 = text("Access Panel
\n") - var/list/wires = list( - "Orange" = 1, - "Dark red" = 2, - "White" = 3, - "Yellow" = 4, - "Blue" = 5, - "Pink" = 6 - ) - for(var/wiredesc in wires) - var/is_uncut = src.wires & WireColorToFlag[wires[wiredesc]] - t1 += "[wiredesc] wire: " - if(!is_uncut) - t1 += "Mend" - else - t1 += "Cut " - t1 += "Pulse " - t1 += "
" - - t1 += "
\n[(src.view_range == initial(view_range) ? "The focus light is on." : "The focus light is off.")]" - t1 += "
\n[(src.can_use() ? "The power link light is on." : "The power link light is off.")]" - t1 += "
\n[(light_disabled ? "The camera light is off." : "The camera light is on.")]" - t1 += "
\n[(alarm_on ? "The alarm light is on." : "The alarm light is off.")]" - - t1 += "

Close

\n" - user << browse(t1, "window=wires") - onclose(user, "wires") - - - -/obj/machinery/camera/Topic(href, href_list) - ..() - if (in_range(src, usr) && istype(src.loc, /turf)) - usr.set_machine(src) - if (href_list["wires"]) - var/t1 = text2num(href_list["wires"]) - if (!( istype(usr.get_active_hand(), /obj/item/weapon/wirecutters) )) - usr << "You need wirecutters!" - return - if (src.isWireColorCut(t1)) - src.mend(t1) - else - src.cut(t1) - else if (href_list["pulse"]) - var/t1 = text2num(href_list["pulse"]) - if (!istype(usr.get_active_hand(), /obj/item/device/multitool)) - usr << "You need a multitool!" - return - if (src.isWireColorCut(t1)) - usr << "You can't pulse a cut wire." - return - else - src.pulse(t1) - else if (href_list["close2"]) - usr << browse(null, "window=wires") - usr.unset_machine() - return - - -#undef CAMERA_WIRE_FOCUS -#undef CAMERA_WIRE_POWER -#undef CAMERA_WIRE_LIGHT -#undef CAMERA_WIRE_ALARM -#undef CAMERA_WIRE_NOTHING1 -#undef CAMERA_WIRE_NOTHING2 \ No newline at end of file diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 5e6b66be525..06bd4ad92ea 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1,23 +1,8 @@ -#define AIRLOCK_WIRE_IDSCAN 1 -#define AIRLOCK_WIRE_MAIN_POWER1 2 -#define AIRLOCK_WIRE_MAIN_POWER2 3 -#define AIRLOCK_WIRE_DOOR_BOLTS 4 -#define AIRLOCK_WIRE_BACKUP_POWER1 5 -#define AIRLOCK_WIRE_BACKUP_POWER2 6 -#define AIRLOCK_WIRE_OPEN_DOOR 7 -#define AIRLOCK_WIRE_AI_CONTROL 8 -#define AIRLOCK_WIRE_ELECTRIFY 9 -#define AIRLOCK_WIRE_SAFETY 10 -#define AIRLOCK_WIRE_SPEED 11 -#define AIRLOCK_WIRE_LIGHT 12 - /* New methods: pulse - sends a pulse into a wire for hacking purposes cut - cuts a wire and makes any necessary state changes mend - mends a wire and makes any necessary state changes - isWireColorCut - returns 1 if that color wire is cut, or 0 if not - isWireCut - returns 1 if that wire (e.g. AIRLOCK_WIRE_DOOR_BOLTS) is cut, or 0 if not canAIControl - 1 if the AI can control the airlock, 0 if not (then check canAIHack to see if it can hack in) canAIHack - 1 if the AI can hack into the airlock to recover control, 0 if not. Also returns 0 if the AI does not *need* to hack it. arePowerSystemsOn - 1 if the main or backup power are functioning, 0 if not. Does not check whether the power grid is charged or an APC has equipment on or anything like that. (Check (stat & NOPOWER) for that) @@ -30,8 +15,12 @@ shock - has a chance of electrocuting its target. */ + +// Wires for the airlock are located in the datum folder, inside the wires datum folder. + + /obj/machinery/door/airlock - name = "Airlock" + name = "airlock" icon = 'icons/obj/doors/Doorint.dmi' icon_state = "door_closed" power_channel = ENVIRON @@ -50,9 +39,7 @@ var/aiHacking = 0 var/obj/machinery/door/airlock/closeOther = null var/closeOtherId = null - var/list/signalers[12] var/lockdownbyai = 0 - autoclose = 1 var/assembly_type = /obj/structure/door_assembly var/mineral = null var/justzap = 0 @@ -61,6 +48,7 @@ var/obj/item/weapon/airlock_electronics/electronics = null var/hasShocked = 0 //Prevents multiple shocks from happening var/frozen = 0 //special condition for airlocks that are frozen shut, this will look weird on not normal airlocks because of a lack of special overlays. + autoclose = 1 /obj/machinery/door/airlock/command name = "Airlock" @@ -311,7 +299,7 @@ About the new airlock wires panel: * one wire for controling door safetys. When active, door does not close on someone. When cut, door will ruin someone's shit. When pulsed, door will immedately ruin someone's shit. * one wire for controlling door speed. When active, dor closes at normal rate. When cut, door does not close manually. When pulsed, door attempts to close every tick. */ - +// You can find code for the airlock wires in the wire datum folder. /obj/machinery/door/airlock/bumpopen(mob/living/user as mob) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite @@ -336,8 +324,6 @@ About the new airlock wires panel: ..(user) - - /obj/machinery/door/airlock/proc/isElectrified() if(src.secondsElectrified != 0) return 1 @@ -347,7 +333,6 @@ About the new airlock wires panel: // You can find the wires in the datum folder. return wires.IsIndexCut(wireIndex) - /obj/machinery/door/airlock/proc/canAIControl() return ((src.aiControlDisabled!=1) && (!src.isAllPowerCut())); @@ -420,8 +405,8 @@ About the new airlock wires panel: s.start() //sparks always. if(electrocute_mob(user, get_area(src), src)) hasShocked = 1 - sleep(10) - hasShocked = 0 + spawn(10) + hasShocked = 0 return 1 else return 0 @@ -645,13 +630,11 @@ About the new airlock wires panel: return src.attack_hand(user) /obj/machinery/door/airlock/attack_hand(mob/user as mob) - if(!istype(usr, /mob/living/silicon)) + if(!istype(user, /mob/living/silicon)) if(src.isElectrified()) if(src.shock(user, 100)) return - // No. -- cib - /** if(ishuman(user) && prob(40) && src.density) var/mob/living/carbon/human/H = user if(H.getBrainLoss() >= 60) @@ -666,7 +649,6 @@ About the new airlock wires panel: else visible_message("\red [user] headbutts the airlock. Good thing they're wearing a helmet.") return - **/ if(src.p_open) wires.Interact(user) @@ -676,6 +658,8 @@ About the new airlock wires panel: /obj/machinery/door/airlock/Topic(href, href_list, var/nowindow = 0) + // If you add an if(..()) check you must first remove the var/nowindow parameter. + // Otherwise it will runtime with this kind of error: null.Topic() if(!nowindow) ..() if(usr.stat || usr.restrained()|| usr.small) @@ -690,6 +674,46 @@ About the new airlock wires panel: if((in_range(src, usr) && istype(src.loc, /turf)) && src.p_open) usr.set_machine(src) + if(!p_open) + if(!issilicon(usr)) + if(!istype(usr.get_active_hand(), /obj/item/device/multitool)) + testing("Not silicon, not using a multitool.") + return + + var/obj/item/device/multitool/P = get_multitool(usr) + + if("set_tag" in href_list) + if(!(href_list["set_tag"] in vars)) + usr << "\red Something went wrong: Unable to find [href_list["set_tag"]] in vars!" + return 1 + var/current_tag = src.vars[href_list["set_tag"]] + var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag", src, current_tag) as null|text),1,MAX_MESSAGE_LEN) + if(newid) + vars[href_list["set_tag"]] = newid + initialize() + + if("set_freq" in href_list) + var/newfreq=frequency + if(href_list["set_freq"]!="-1") + newfreq=text2num(href_list["set_freq"]) + else + newfreq = input(usr, "Specify a new frequency (GHz). Decimals assigned automatically.", src, frequency) as null|num + if(newfreq) + if(findtext(num2text(newfreq), ".")) + newfreq *= 10 // shift the decimal one place + if(newfreq < 10000) + frequency = newfreq + initialize() + + if(href_list["unlink"]) + P.visible_message("\The [P] buzzes in an annoying tone.","You hear a buzz.") + + if(href_list["link"]) + P.visible_message("\The [P] buzzes in an annoying tone.","You hear a buzz.") + + if(href_list["buffer"]) + P.buffer = src + if(istype(usr, /mob/living/silicon) && src.canAIControl()) @@ -890,7 +914,7 @@ About the new airlock wires panel: return src.add_fingerprint(user) - if((istype(C, /obj/item/weapon/weldingtool) && !( src.operating > 0 ) && src.density)) + if((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) var/obj/item/weapon/weldingtool/W = C if(W.remove_fuel(0,user)) if(frozen) @@ -921,7 +945,7 @@ About the new airlock wires panel: beingcrowbarred = 1 //derp, Agouri else beingcrowbarred = 0 - if( beingcrowbarred && (operating == -1 || density && welded && operating != 1 && src.p_open && (!src.arePowerSystemsOn() || stat & NOPOWER) && !src.locked) ) + if( beingcrowbarred && (density && welded && !operating && src.p_open && (!src.arePowerSystemsOn() || stat & NOPOWER) && !src.locked) ) playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics from the airlock assembly.") if(do_after(user,40)) @@ -979,7 +1003,6 @@ About the new airlock wires panel: user << "\red You need to be wielding the Fire axe to do that." else spawn(0) close(1) - else ..() return @@ -1004,6 +1027,14 @@ About the new airlock wires panel: playsound(src.loc, 'sound/machines/airlock.ogg', 30, 1) if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density) src.closeOther.close() + // This worries me - N3X + if(autoclose && normalspeed) + spawn(150) + autoclose() + else if(autoclose && !normalspeed) + spawn(5) + autoclose() + // return ..() /obj/machinery/door/airlock/close(var/forced=0) diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 1bacef1500e..89a380f1cb3 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -108,6 +108,8 @@ Class Procs: var/uid var/manual = 0 var/global/gl_uid = 1 + var/custom_aghost_alerts=0 + var/panel_open = 0 /obj/machinery/New() ..() @@ -238,3 +240,23 @@ Class Procs: uid = gl_uid gl_uid++ +/obj/machinery/proc/default_deconstruction_crowbar() + playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) + var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(src.loc) + M.state = 2 + M.icon_state = "box_1" + for(var/obj/I in component_parts) + if(I.reliability != 100 && crit_fail) + I.crit_fail = 1 + I.loc = src.loc + del(src) + +/obj/machinery/proc/default_deconstruction_screwdriver(var/mob/user, var/icon_state_open, var/icon_state_closed) + if (!panel_open) + panel_open = 1 + icon_state = icon_state_open + user << "You open the maintenance hatch of [src]." + else + panel_open = 0 + icon_state = icon_state_closed + user << "You close the maintenance hatch of [src]." diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 9ba92674e39..a6f6810b021 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -7,7 +7,6 @@ var/display_color = "blue" - /obj/machinery/vending name = "Vendomat" desc = "A generic vending machine." @@ -16,44 +15,39 @@ layer = 2.9 anchored = 1 density = 1 - var/active = 1 //No sales pitches if off! - var/vend_ready = 1 //Are we ready to vend?? Is it time?? - var/vend_delay = 10 //How long does it take to vend? + var/active = 1 //No sales pitches if off! + var/vend_ready = 1 //Are we ready to vend?? Is it time?? + var/vend_delay = 10 //How long does it take to vend? var/datum/data/vending_product/currently_vending = null // A /datum/data/vending_product instance of what we're paying for right now. // To be filled out at compile time - var/list/products = list() // For each, use the following pattern: - var/list/contraband = list() // list(/type/path = amount,/type/path2 = amount2) - var/list/premium = list() // No specified amount = only one in stock - var/list/prices = list() // Prices for each item, list(/type/path = price), items not in the list don't have a price. + var/list/products = list() // For each, use the following pattern: + var/list/contraband = list() // list(/type/path = amount,/type/path2 = amount2) + var/list/premium = list() // No specified amount = only one in stock + var/list/prices = list() // Prices for each item, list(/type/path = price), items not in the list don't have a price. - var/product_slogans = "" //String of slogans separated by semicolons, optional - var/product_ads = "" //String of small ad messages in the vending screen - random chance + var/product_slogans = "" //String of slogans separated by semicolons, optional + var/product_ads = "" //String of small ad messages in the vending screen - random chance var/list/product_records = list() var/list/hidden_records = list() var/list/coin_records = list() var/list/slogan_list = list() - var/list/small_ads = list() // small ad messages in the vending screen - random chance of popping up whenever you open it - var/vend_reply //Thank you for shopping! + var/list/small_ads = list() //Small ad messages in the vending screen - random chance of popping up whenever you open it + var/vend_reply //Thank you for shopping! var/last_reply = 0 - var/last_slogan = 0 //When did we last pitch? - var/slogan_delay = 6000 //How long until we can pitch again? - var/icon_vend //Icon_state when vending! - var/icon_deny //Icon_state when vending! - //var/emagged = 0 //Ignores if somebody doesn't have card access to that machine. - var/seconds_electrified = 0 //Shock customers like an airlock. - var/shoot_inventory = 0 //Fire items at customers! We're broken! - var/shut_up = 1 //Stop spouting those godawful pitches! - var/extended_inventory = 0 //can we access the hidden inventory? - var/panel_open = 0 //Hacking that vending machine. Gonna get a free candy bar. - var/obj/item/weapon/coin/coin - var/const/WIRE_EXTEND = 1 - var/const/WIRE_SCANID = 2 - var/const/WIRE_SHOCK = 3 - var/const/WIRE_SHOOTINV = 4 - var/datum/wires/vending/wires = null - var/scan_id = 1 var/obj/item/weapon/vending_refill/refill_canister = null //The type of refill canisters used by this machine. + var/last_slogan = 0 //When did we last pitch? + var/slogan_delay = 6000 //How long until we can pitch again? + var/icon_vend //Icon_state when vending! + var/icon_deny //Icon_state when vending! + //var/emagged = 0 //Ignores if somebody doesn't have card access to that machine. + var/seconds_electrified = 0 //Shock customers like an airlock. + var/shoot_inventory = 0 //Fire items at customers! We're broken! + var/shut_up = 0 //Stop spouting those godawful pitches! + var/extended_inventory = 0 //can we access the hidden inventory? + var/scan_id = 1 + var/obj/item/weapon/coin/coin + var/datum/wires/vending/wires = null /obj/machinery/vending/New() @@ -91,22 +85,16 @@ del(src) return if(3.0) - if (prob(25)) - spawn(0) - src.malfunction() - return - return - else - return + if(prob(25)) + malfunction() + /obj/machinery/vending/blob_act() - if (prob(50)) - spawn(0) - src.malfunction() - del(src) - return + if(prob(75)) + malfunction() + else + del(src) - return /obj/machinery/vending/proc/build_inventory(var/list/productlist,hidden=0,req_coin=0) for(var/typepath in productlist) @@ -130,7 +118,7 @@ else product_records += R // world << "Added: [R.product_name]] - [R.amount] - [R.product_path]" - return + /obj/machinery/vending/proc/refill_inventory(obj/item/weapon/vending_refill/refill, datum/data/vending_product/machine, mob/user) var/total = 0 @@ -162,28 +150,28 @@ return total -/obj/machinery/vending/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/card/emag)) - src.emagged = 1 +/obj/machinery/vending/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/card/emag)) + emagged = 1 user << "You short out the product lock on [src]" return else if(istype(W, /obj/item/weapon/screwdriver)) - src.panel_open = !src.panel_open - user << "You [src.panel_open ? "open" : "close"] the maintenance panel." - src.overlays.Cut() - if(src.panel_open) - src.overlays += image(src.icon, "[initial(icon_state)]-panel") - src.updateUsrDialog() + panel_open = !panel_open + user << "You [panel_open ? "open" : "close"] the maintenance panel." + overlays.Cut() + if(panel_open) + overlays += image(icon, "[initial(icon_state)]-panel") + updateUsrDialog() return else if(istype(W, /obj/item/device/multitool)||istype(W, /obj/item/weapon/wirecutters)) - if(src.panel_open) + if(panel_open) attack_hand(user) return else if(istype(W, /obj/item/weapon/coin) && premium.len > 0) user.drop_item() W.loc = src coin = W - user << "\blue You insert the [W] into the [src]" + user << "You insert [W] into [src]." return else if(src.panel_open) @@ -268,75 +256,93 @@ /obj/machinery/vending/attack_ai(mob/user as mob) return attack_hand(user) -/obj/machinery/vending/attack_hand(var/mob/user as mob) - if(stat & BROKEN) +/obj/machinery/vending/attack_hand(mob/user as mob) + if(stat & (BROKEN|NOPOWER)) return + user.set_machine(src) - if(src.seconds_electrified != 0) - if(src.shock(user, 100)) + if(seconds_electrified != 0) + if(shock(user, 100)) return + var/vendorname = (src.name) //import the machine's name - if(panel_open) //NanoUI does not feature thoes wire() procs, and I don't feel like rewriting it, so this is the best option. - var/dat - dat += wires() + if(src.currently_vending) + var/dat = "
[vendorname]


" //display the name, and added a horizontal rule - if (product_slogans != "") - dat += "The speaker switch is [src.shut_up ? "off" : "on"]. Toggle" - - var/datum/browser/popup = new(user, "vending", (name)) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - ui_interact(user) - -/obj/machinery/vending/ui_interact(mob/user, ui_key = "vending_machine") - if(stat & (BROKEN|NOPOWER)) return - if(user.stat || user.restrained()) return - var/list/productData[0] - var/list/premiumData[0] - var/list/contrabandData[0] - var/list/display_records = product_records - for(var/datum/data/vending_product/R in display_records) - productData.Add(list(list("amount" = R.amount, "name" = R.product_name, "price" = R.price, "displayColor" = R.display_color, "itself" = "\ref[R]", "path" = R.product_path))) - for(var/datum/data/vending_product/R in coin_records) - premiumData.Add(list(list("amount" = R.amount, "name" = R.product_name, "price" = R.price, "displayColor" = R.display_color, "itself" = "\ref[R]", "path" = R.product_path))) - for(var/datum/data/vending_product/R in hidden_records) - contrabandData.Add(list(list("amount" = R.amount, "name" = R.product_name, "price" = R.price, "displayColor" = R.display_color, "itself" = "\ref[R]", "path" = R.product_path))) - - var/data[0] - data["premiumItems"] = premium - data["contraband"] = contraband - data["products"] = products - data["coin"] = coin - data["extendedInventory"] = extended_inventory - data["panelOpen"] = panel_open - data["productData"] = productData - data["premiumData"] = premiumData - data["contrabandData"] = contrabandData - var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, ui_key) - if (!ui) - ui = new(user, src, ui_key, "vending.tmpl", "Vending Machine", 600, 500) - ui.set_initial_data(data) - ui.set_auto_update(1) - ui.open() - else - ui.push_data(data) + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\Documents\Projects\vgstation13\code\game\machinery\vending.dm:260: dat += "You have selected [currently_vending.product_name].
Please ensure your ID is in your ID holder or hand.

" + dat += {"You have selected [currently_vending.product_name].
Please ensure your ID is in your ID holder or hand.

+ Pay | + Cancel"} + // END AUTOFIX + user << browse(dat, "window=vending") + onclose(user, "") return + var/dat = "
[vendorname]


" //display the name, and added a horizontal rule + dat += "Select an item:

" //the rest is just general spacing and bolding + + if (premium.len > 0) + dat += "Coin slot: [coin ? coin : "No coin inserted"] (Remove)

" + + if (src.product_records.len == 0) + dat += "No product loaded!" + else + var/list/display_records = src.product_records + if(src.extended_inventory) + display_records = src.product_records + src.hidden_records + if(src.coin) + display_records = src.product_records + src.coin_records + if(src.coin && src.extended_inventory) + display_records = src.product_records + src.hidden_records + src.coin_records + + for (var/datum/data/vending_product/R in display_records) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\Documents\Projects\vgstation13\code\game\machinery\vending.dm:285: dat += "[R.product_name]:" + dat += {"[R.product_name]: + [R.amount] "} + // END AUTOFIX + if(R.price) + dat += " (Price: [R.price])" + if (R.amount > 0) + dat += " (Vend)" + else + dat += " SOLD OUT" + dat += "
" + + dat += "
" + + if(panel_open) + dat += wires() + + if(product_slogans != "") + dat += "The speaker switch is [shut_up ? "off" : "on"]. Toggle" + + user << browse(dat, "window=vending") + onclose(user, "") + return // returns the wire panel text /obj/machinery/vending/proc/wires() - return wires.GetInteractWindow() - + return wires.GetInteractWindow() /obj/machinery/vending/Topic(href, href_list) - if(stat & (BROKEN|NOPOWER)) - return - if(usr.stat || usr.restrained()) + if(..()) return - if(href_list["remove_coin"] && !istype(usr,/mob/living/silicon)) + if(istype(usr,/mob/living/silicon)) + if(istype(usr,/mob/living/silicon/robot)) + var/mob/living/silicon/robot/R = usr + if(!(R.module && istype(R.module,/obj/item/weapon/robot_module/butler) ) ) + usr << "\red The vending machine refuses to interface with you, as you are not in its target demographic!" + return + else + usr << "\red The vending machine refuses to interface with you, as you are not in its target demographic!" + return + + if(href_list["remove_coin"]) if(!coin) usr << "There is no coin in this machine." return @@ -346,23 +352,13 @@ usr.put_in_hands(coin) usr << "\blue You remove the [coin] from the [src]" coin = null + usr.set_machine(src) if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) - usr.set_machine(src) if ((href_list["vend"]) && (src.vend_ready) && (!currently_vending)) - if(istype(usr,/mob/living/silicon)) - if(istype(usr,/mob/living/silicon/robot)) - var/mob/living/silicon/robot/R = usr - if(!(R.module && istype(R.module,/obj/item/weapon/robot_module/butler) )) - usr << "\red The vending machine refuses to interface with you, as you are not in its target demographic!" - return - else - usr << "\red The vending machine refuses to interface with you, as you are not in its target demographic!" - return - - if ((!src.allowed(usr)) && (!src.emagged) && (src.wires & WIRE_SCANID)) //For SECURE VENDING MACHINES YEAH + if (!allowed(usr) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH usr << "\red Access denied." //Unless emagged of course flick(src.icon_deny,src) return @@ -384,6 +380,18 @@ src.updateUsrDialog() return + else if (href_list["buy"]) + if(istype(usr, /mob/living/carbon/human)) + var/mob/living/carbon/human/H=usr + var/obj/item/weapon/card/card = null + if(istype(H.wear_id,/obj/item/weapon/card)) + card=H.wear_id + else if(istype(H.get_active_hand(),/obj/item/weapon/card)) + card=H.get_active_hand() + if(card) + scan_card(card) + return + else if ((href_list["togglevoice"]) && (src.panel_open)) src.shut_up = !src.shut_up @@ -395,7 +403,7 @@ return /obj/machinery/vending/proc/vend(datum/data/vending_product/R, mob/user) - if ((!src.allowed(user)) && (!src.emagged) && (src.wires & WIRE_SCANID)) //For SECURE VENDING MACHINES YEAH + if (!allowed(user) && !emagged && wires.IsIndexCut(VENDING_WIRE_IDSCAN)) //For SECURE VENDING MACHINES YEAH user << "\red Access denied." //Unless emagged of course flick(src.icon_deny,src) return @@ -526,7 +534,6 @@ return 1 - /obj/machinery/vending/proc/shock(mob/user, prb) if(stat & (BROKEN|NOPOWER)) // unpowered, no shock return 0 @@ -535,7 +542,7 @@ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(5, 1, src) s.start() - if (electrocute_mob(user, get_area(src), src, 0.7)) + if(electrocute_mob(user, get_area(src), src, 0.7)) return 1 else return 0 diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index c096e834178..4da17c25991 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -37,9 +37,8 @@ dat += "

Device Settings


" if(radio) dat += "Radio Uplink
" - dat += "Transmit: [(radio.wires & 4) ? "Enabled" : "Disabled"]
" - dat += "Receive: [(radio.wires & 2) ? "Enabled" : "Disabled"]
" - dat += "Signal Pulser: [(radio.wires & 1) ? "Enabled" : "Disabled"]
" + dat += "Transmit: [(radio.wires.IsIndexCut(WIRE_TRANSMIT)) ? "Disabled" : "Enabled"]
" + dat += "Receive: [(radio.wires.IsIndexCut(WIRE_RECEIVE)) ? "Disabled" : "Enabled"]
" else dat += "Radio Uplink
" dat += "Radio firmware not loaded. Please install a pAI personality to load firmware.
" @@ -87,10 +86,8 @@ removePersonality() if(href_list["wires"]) var/t1 = text2num(href_list["wires"]) - if (radio.wires & t1) - radio.wires &= ~t1 - else - radio.wires |= t1 + if(radio) + radio.wires.CutWireIndex(t1) if(href_list["setlaws"]) var/newlaws = copytext(sanitize(input("Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", pai.pai_laws) as message),1,MAX_MESSAGE_LEN) if(newlaws) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 0883ab4b080..5f062d62abc 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -15,7 +15,8 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use var/traitor_frequency = 0 //tune to frequency to unlock traitor supplies var/canhear_range = 3 // the range which mobs can hear this radio from var/obj/item/device/radio/patch_link = null - var/wires = WIRE_SIGNAL | WIRE_RECEIVE | WIRE_TRANSMIT + var/datum/wires/radio/wires = null + var/prison_radio = 0 var/b_stat = 0 var/broadcasting = 0 var/listening = 1 @@ -32,16 +33,14 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use w_class = 2 g_amt = 25 m_amt = 75 - var/const/WIRE_SIGNAL = 1 //sends a signal, like to set off a bomb or electrocute someone - var/const/WIRE_RECEIVE = 2 - var/const/WIRE_TRANSMIT = 4 + var/const/TRANSMISSION_DELAY = 5 // only 2/second/radio var/const/FREQ_LISTENING = 1 //FREQ_BROADCASTING = 2 /obj/item/device/radio var/datum/radio_frequency/radio_connection - var/list/datum/radio_frequency/secure_radio_connections = new + var/list/datum/radio_frequency/secure_radio_connections proc/set_frequency(new_frequency) radio_controller.remove_object(src, frequency) @@ -49,6 +48,10 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT) /obj/item/device/radio/New() + wires = new(src) + if(prison_radio) + wires.CutWireIndex(WIRE_TRANSMIT) + secure_radio_connections = new ..() if(radio_controller) initialize() @@ -104,21 +107,15 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use return /obj/item/device/radio/proc/text_wires() - if (!b_stat) - return "" - return {" -
- Green Wire: [(wires & 4) ? "Cut" : "Mend"] Wire
- Red Wire: [(wires & 2) ? "Cut" : "Mend"] Wire
- Blue Wire: [(wires & 1) ? "Cut" : "Mend"] Wire
- "} + if (b_stat) + return wires.GetInteractWindow() + return /obj/item/device/radio/proc/text_sec_channel(var/chan_name, var/chan_stat) var/list = !!(chan_stat&FREQ_LISTENING)!=0 return {" - [chan_name]
- Speaker: [list ? "Engaged" : "Disengaged"]
+ [chan_name]: [list ? "Engaged" : "Disengaged"]
"} /obj/item/device/radio/Topic(href, href_list) @@ -182,14 +179,6 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use channels[chan_name] &= ~FREQ_LISTENING else channels[chan_name] |= FREQ_LISTENING - else if (href_list["wires"]) - var/t1 = text2num(href_list["wires"]) - if (!( istype(usr.get_active_hand(), /obj/item/weapon/wirecutters) )) - return - if (wires & t1) - wires &= ~t1 - else - wires |= t1 if (!( master )) if (istype(loc, /mob)) interact(loc) @@ -202,6 +191,9 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use updateDialog() add_fingerprint(usr) +/obj/item/device/radio/proc/isWireCut(var/index) + return wires.IsIndexCut(index) + /obj/item/device/radio/proc/autosay(var/message, var/from, var/channel) //BS12 EDIT var/datum/radio_frequency/connection = null if(channel && channels && channels.len > 0) @@ -232,7 +224,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use // Uncommenting this. To the above comment: // The permacell radios aren't suppose to be able to transmit, this isn't a bug and this "fix" is just making radio wires useless. -Giacom - if(!(src.wires & WIRE_TRANSMIT)) // The device has to have all its wires and shit intact + if(isWireCut(WIRE_TRANSMIT)) // The device has to have all its wires and shit intact return @@ -256,6 +248,8 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use //world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\"" channel = channels[1] connection = secure_radio_connections[channel] + if (!channels[channel]) // if the channel is turned off, don't broadcast + return else connection = radio_connection channel = null @@ -459,7 +453,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use else eqjobname = "Unknown" - if (!(wires & WIRE_TRANSMIT)) + if (isWireCut(WIRE_TRANSMIT)) return var/list/receive = list() @@ -619,7 +613,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use // what the range is in which mobs will hear the radio // returns: -1 if can't receive, range otherwise - if (!(wires & WIRE_RECEIVE)) + if (isWireCut(WIRE_RECEIVE)) return -1 if(!listening) return -1 diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index 664bce55ef1..4eedb37125a 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -1,6 +1,54 @@ + + +/obj/item/weapon/plastique + name = "plastic explosives" + desc = "Used to put holes in specific areas without too much extra hole." + gender = PLURAL + icon = 'icons/obj/assemblies.dmi' + icon_state = "plastic-explosive0" + item_state = "plasticx" + flags = FPRINT | TABLEPASS | USEDELAY + w_class = 2.0 + origin_tech = "syndicate=2" + var/datum/wires/explosive/plastic/wires = null + var/timer = 10 + var/atom/target = null + var/open_panel = 0 + +/obj/item/weapon/plastique/New() + wires = new(src) + ..() + +/obj/item/weapon/plastique/suicide_act(var/mob/user) + . = (BRUTELOSS) + viewers(user) << "\red [user] activates the C4 and holds it above his head! It looks like \he's going out with a bang!" + var/message_say = "FOR NO RAISIN!" + if(user.mind) + if(user.mind.special_role) + var/role = lowertext(user.mind.special_role) + if(role == "traitor" || role == "syndicate") + message_say = "FOR THE SYNDICATE!" + else if(role == "changeling") + message_say = "FOR THE HIVE!" + else if(role == "cultist") + message_say = "FOR NARSIE!" + user.say(message_say) + target = user + explode(get_turf(user)) + return . + +/obj/item/weapon/plastique/attackby(var/obj/item/I, var/mob/user) + if(istype(I, /obj/item/weapon/screwdriver)) + open_panel = !open_panel + user << "You [open_panel ? "open" : "close"] the wire panel." + else if(istype(I, /obj/item/weapon/wirecutters) || istype(I, /obj/item/device/multitool) || istype(I, /obj/item/device/assembly/signaler )) + wires.Interact(user) + else + ..() + /obj/item/weapon/plastique/attack_self(mob/user as mob) var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num - if(newtime > 60000) + if(newtime < 60000) newtime = 60000 timer = newtime user << "Timer set for [timer] seconds." @@ -20,11 +68,8 @@ if(do_after(user, 50) && in_range(user, target)) user.drop_item() - target = target + src.target = target loc = null - var/location - if (isturf(target)) location = target - if (isobj(target)) location = target.loc if (ismob(target)) var/mob/M = target target:attack_log += "\[[time_stamp()]\] Had the [name] planted on them by [user.real_name] ([user.ckey])" @@ -36,15 +81,26 @@ target.overlays += image('icons/obj/assemblies.dmi', "plastic-explosive2") user << "Bomb has been planted. Timer counting down from [timer]." spawn(timer*10) - if(target) - explosion(location, -1, -1, 2, 3) - if (istype(target, /turf/simulated/wall)) target:dismantle_wall(1) - else target.ex_act(1) - if (isobj(target)) - if (target) - del(target) - if (src) - del(src) + explode(get_turf(target)) + +/obj/item/weapon/plastique/proc/explode(var/location) + + if(!target) + target = get_atom_on_turf(src) + if(!target) + target = src + if(location) + explosion(location, -1, -1, 2, 3) + + if(target) + if (istype(target, /turf/simulated/wall)) + target:dismantle_wall(1) + else + target.ex_act(1) + if (isobj(target)) + if (target) + del(target) + del(src) /obj/item/weapon/plastique/attack(mob/M as mob, mob/user as mob, def_zone) return \ No newline at end of file diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 881744f547b..cc9f12b51f9 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -335,4 +335,11 @@ if(!t.density) if(!LinkBlocked(src, t) && !TurfBlockedNonWindow(t)) L.Add(t) - return L \ No newline at end of file + return L + +// This Distance proc assumes that only cardinal movement is +// possible. It results in more efficient (CPU-wise) pathing +// for bots and anything else that only moves in cardinal dirs. +/turf/proc/Distance_cardinal(turf/t) + if(!src || !t) return 0 + return abs(src.x - t.x) + abs(src.y - t.y) diff --git a/code/global.dm b/code/global.dm index 5e9105f3c83..1188996a3f9 100644 --- a/code/global.dm +++ b/code/global.dm @@ -172,27 +172,6 @@ var/forceblob = 0 // nanomanager, the manager for Nano UIs var/datum/nanomanager/nanomanager = new() - //airlockWireColorToIndex takes a number representing the wire color, e.g. the orange wire is always 1, the dark red wire is always 2, etc. It returns the index for whatever that wire does. - //airlockIndexToWireColor does the opposite thing - it takes the index for what the wire does, for example AIRLOCK_WIRE_IDSCAN is 1, AIRLOCK_WIRE_POWER1 is 2, etc. It returns the wire color number. - //airlockWireColorToFlag takes the wire color number and returns the flag for it (1, 2, 4, 8, 16, etc) - -//var/list/airlockWireColorToFlag = RandomAirlockWires() -//var/list/airlockIndexToFlag -//var/list/airlockIndexToWireColor -//var/list/airlockWireColorToIndex -//var/list/APCWireColorToFlag = RandomAPCWires() -//var/list/APCIndexToFlag -//var/list/APCIndexToWireColor -//var/list/APCWireColorToIndex -var/list/BorgWireColorToFlag = RandomBorgWires() -var/list/BorgIndexToFlag -var/list/BorgIndexToWireColor -var/list/BorgWireColorToIndex -var/list/AAlarmWireColorToFlag = RandomAAlarmWires() -var/list/AAlarmIndexToFlag -var/list/AAlarmIndexToWireColor -var/list/AAlarmWireColorToIndex - #define SPEED_OF_LIGHT 3e8 //not exact but hey! #define SPEED_OF_LIGHT_SQ 9e+16 #define FIRE_DAMAGE_MODIFIER 0.0215 //Higher values result in more external fire damage to the skin (default 0.0215) @@ -286,4 +265,4 @@ var/score_richestkey = null var/score_dmgestname = null // who had the most damage on the shuttle (but was still alive) var/score_dmgestjob = null var/score_dmgestdamage = 0 -var/score_dmgestkey = null \ No newline at end of file +var/score_dmgestkey = null diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index 8fe819d2fe7..7f2d7c8f731 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -121,17 +121,14 @@ return -/* + pulse(var/radio = 0) - if(istype(src.loc, /obj/machinery/door/airlock) && src.airlock_wire && src.wires) - var/obj/machinery/door/airlock/A = src.loc - A.pulse(src.airlock_wire) - else if(holder) - holder.process_activation(src, 1, 0) + if(src.connected && src.wires) + connected.Pulse(src) else - ..(radio) - return 1 -*/ + return ..(radio) + + receive_signal(datum/signal/signal) if( !receiving || !signal ) return 0 @@ -169,4 +166,4 @@ A.anomalyNeutralize() /obj/item/device/assembly/signaler/anomaly/attack_self() - return \ No newline at end of file + return diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 88362f33ecb..1011238609e 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -16,6 +16,10 @@ if(hand) return r_hand else return l_hand +// Because there's several different places it's stored. +/mob/proc/get_multitool(var/if_active=0) + return null + //Puts the item into your l_hand if possible and calls all necessary triggers/updates. returns 1 on success. /mob/proc/put_in_l_hand(var/obj/item/W) if(lying) return 0 diff --git a/code/modules/mob/living/silicon/mommi/life.dm b/code/modules/mob/living/silicon/mommi/life.dm new file mode 100644 index 00000000000..5b9f8bd98c1 --- /dev/null +++ b/code/modules/mob/living/silicon/mommi/life.dm @@ -0,0 +1,280 @@ +/mob/living/silicon/robot/mommi/Life() + set invisibility = 0 + set background = 1 + + if (src.monkeyizing) + return + + + src.blinded = null + + //Status updates, death etc. + clamp_values() + handle_regular_status_updates() + + if(client) + handle_regular_hud_updates() + update_items() + if (src.stat != DEAD) //still using power + use_power() + process_killswitch() + process_locks() + update_canmove() + + + + +/mob/living/silicon/robot/mommi/clamp_values() + +// SetStunned(min(stunned, 30)) + SetParalysis(min(paralysis, 30)) +// SetWeakened(min(weakened, 20)) + sleeping = 0 + adjustBruteLoss(0) + adjustToxLoss(0) + adjustOxyLoss(0) + adjustFireLoss(0) + + +/mob/living/silicon/robot/mommi/use_power() + + if (src.cell) + if(src.cell.charge <= 0) + uneq_all() + src.stat = 1 + else if (src.cell.charge <= 100) + src.module_active = null + src.sight_state = null + src.tool_state = null + src.sight_mode = 0 + src.cell.use(1) + else + if(src.sight_state) + src.cell.use(5) + if(src.tool_state) + src.cell.use(5) + src.cell.use(1) + src.blinded = 0 + src.stat = 0 + else + uneq_all() + src.stat = 1 + + +/mob/living/silicon/robot/mommi/handle_regular_status_updates() + + if(src.camera && !scrambledcodes) + if(src.stat == 2 || wires.IsCameraCut()) + src.camera.status = 0 + else + src.camera.status = 1 + + health = maxHealth - (getOxyLoss() + getFireLoss() + getBruteLoss()) + + if(getOxyLoss() > 50) Paralyse(3) + + if(src.sleeping) + Paralyse(3) + src.sleeping-- + + if(src.resting) + Weaken(5) + + if(health <= 0 && src.stat != 2) //die only once + gib() + + if (src.stat != 2) //Alive. + if (src.paralysis || src.stunned || src.weakened) //Stunned etc. + src.stat = 1 + if (src.stunned > 0) + AdjustStunned(-1) + if (src.weakened > 0) + AdjustWeakened(-1) + if (src.paralysis > 0) + AdjustParalysis(-1) + src.blinded = 1 + else + src.blinded = 0 + + else //Not stunned. + src.stat = 0 + + else //Dead. + src.blinded = 1 + src.stat = 2 + + if (src.stuttering) src.stuttering-- + + if (src.eye_blind) + src.eye_blind-- + src.blinded = 1 + + if (src.ear_deaf > 0) src.ear_deaf-- + if (src.ear_damage < 25) + src.ear_damage -= 0.05 + src.ear_damage = max(src.ear_damage, 0) + + src.density = !( src.lying ) + + if ((src.sdisabilities & BLIND)) + src.blinded = 1 + if ((src.sdisabilities & DEAF)) + src.ear_deaf = 1 + + if (src.eye_blurry > 0) + src.eye_blurry-- + src.eye_blurry = max(0, src.eye_blurry) + + if (src.druggy > 0) + src.druggy-- + src.druggy = max(0, src.druggy) + + return 1 +/ +/mob/living/silicon/robot/mommi/handle_regular_hud_updates() + + if (src.stat == 2 || XRAY in mutations || src.sight_mode & BORGXRAY) + src.sight |= SEE_TURFS + src.sight |= SEE_MOBS + src.sight |= SEE_OBJS + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + else if (src.sight_mode & BORGMESON && src.sight_mode & BORGTHERM) + src.sight |= SEE_TURFS + src.sight |= SEE_MOBS + src.see_in_dark = 8 + see_invisible = SEE_INVISIBLE_MINIMUM + else if (src.sight_mode & BORGMESON) + src.sight |= SEE_TURFS + src.see_in_dark = 8 + see_invisible = SEE_INVISIBLE_MINIMUM + else if (src.sight_mode & BORGTHERM) + src.sight |= SEE_MOBS + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + else if (src.stat != 2) + src.sight &= ~SEE_MOBS + src.sight &= ~SEE_TURFS + src.sight &= ~SEE_OBJS + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + + var/obj/item/borg/sight/hud/hud = (locate(/obj/item/borg/sight/hud) in src) + if(hud && hud.hud) hud.hud.process_hud(src) + + if (src.healths) + if (src.stat != 2) + switch(health) + if(60 to INFINITY) + src.healths.icon_state = "health0" + if(40 to 60) + src.healths.icon_state = "health1" + if(30 to 40) + src.healths.icon_state = "health2" + if(10 to 20) + src.healths.icon_state = "health3" + if(0 to 10) + src.healths.icon_state = "health4" + if(config.health_threshold_dead to 0) + src.healths.icon_state = "health5" + else + src.healths.icon_state = "health6" + else + src.healths.icon_state = "health7" + + if (src.syndicate && src.client) + if(ticker.mode.name == "traitor") + for(var/datum/mind/tra in ticker.mode.traitors) + if(tra.current) + var/I = image('icons/mob/mob.dmi', loc = tra.current, icon_state = "traitor") + src.client.images += I + if(src.connected_ai) + src.connected_ai.connected_robots -= src + src.connected_ai = null + if(src.mind) + if(!src.mind.special_role) + src.mind.special_role = "traitor" + ticker.mode.traitors += src.mind + + if (src.cells) + if (src.cell) + var/cellcharge = src.cell.charge/src.cell.maxcharge + switch(cellcharge) + if(0.75 to INFINITY) + src.cells.icon_state = "charge4" + if(0.5 to 0.75) + src.cells.icon_state = "charge3" + if(0.25 to 0.5) + src.cells.icon_state = "charge2" + if(0 to 0.25) + src.cells.icon_state = "charge1" + else + src.cells.icon_state = "charge0" + else + src.cells.icon_state = "charge-empty" + + if(bodytemp) + switch(src.bodytemperature) //310.055 optimal body temp + if(335 to INFINITY) + src.bodytemp.icon_state = "temp2" + if(320 to 335) + src.bodytemp.icon_state = "temp1" + if(300 to 320) + src.bodytemp.icon_state = "temp0" + if(260 to 300) + src.bodytemp.icon_state = "temp-1" + else + src.bodytemp.icon_state = "temp-2" + + + if(src.pullin) src.pullin.icon_state = "pull[src.pulling ? 1 : 0]" +//Oxygen and fire does nothing yet!! +// if (src.oxygen) src.oxygen.icon_state = "oxy[src.oxygen_alert ? 1 : 0]" +// if (src.fire) src.fire.icon_state = "fire[src.fire_alert ? 1 : 0]" + + client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired) + + if ((src.blind && src.stat != 2)) + if(src.blinded) + src.blind.layer = 18 + else + src.blind.layer = 0 + if (src.disabilities & NEARSIGHTED) + src.client.screen += global_hud.vimpaired + + if (src.eye_blurry) + src.client.screen += global_hud.blurry + + if (src.druggy) + src.client.screen += global_hud.druggy + + if (src.stat != 2) + if (src.machine) + if (!( src.machine.check_eye(src) )) + src.reset_view(null) + else + if(!client.adminobs) + reset_view(null) + + return 1 + + +// MoMMIs only have one hand. +/mob/living/silicon/robot/mommi/update_items() + if (src.client) + src.client.screen -= src.contents + for(var/obj/I in src.contents) + //if(I && !(istype(I,/obj/item/weapon/cell) || istype(I,/obj/item/device/radio) || istype(I,/obj/machinery/camera) || istype(I,/obj/item/device/mmi))) + if(I) + // Make sure we're not showing any of our internal components, as that would be lewd. + // This way of doing it ensures that shit we pick up will be visible, wheras shit inside of us isn't. + if(I!=src.cell && I!=src.radio && I!=src.camera && I!=src.mmi) + src.client.screen += I + if(src.sight_state) + src.sight_state:screen_loc = ui_inv1 + if(src.tool_state) + src.tool_state:screen_loc = ui_inv2 + +/mob/living/silicon/robot/mommi/update_canmove() + canmove = !(paralysis || stunned || weakened || buckled || lockcharge || anchored) + return canmove \ No newline at end of file diff --git a/code/modules/mob/living/silicon/mommi/mommi.dm b/code/modules/mob/living/silicon/mommi/mommi.dm new file mode 100644 index 00000000000..79034c8782c --- /dev/null +++ b/code/modules/mob/living/silicon/mommi/mommi.dm @@ -0,0 +1,539 @@ +/* Basically, the concept is this: +You have an MMI. It can't do squat on its own. +Now you put some robot legs and arms on the thing, and POOF! You have a Mobile MMI, or MoMMI. +Why? MoMMIs can do all sorts of shit, like ventcrawl, do shit with their hands, etc. +They can only use one tool at a time, they can't choose modules, and they have 1/6th the HP of a borg. +*/ +/mob/living/silicon/robot/mommi + name = "Mobile MMI" + real_name = "Mobile MMI" + icon = 'icons/mob/robots.dmi'// + icon_state = "mommi" + maxHealth = 60 + health = 60 + pass_flags = PASSTABLE + var/keeper=0 // 0 = No, 1 = Yes (Disables speech and common radio.) + var/picked = 0 + var/subtype="keeper" + var/obj/screen/inv_tool = null + var/obj/screen/inv_sight = null + +//one tool and one sightmod can be activated at any one time. + var/tool_state = null + var/sight_state = null + + modtype = "robot" // Not sure what this is, but might be cool to have seperate loadouts for MoMMIs (e.g. paintjobs and tools) + //Cyborgs will sync their laws with their AI by default, but we may want MoMMIs to be mute independents at some point, kinda like the Keepers in Ass Effect. + lawupdate = 1 + +/mob/living/carbon/can_use_hands() + return 1 + +/mob/living/silicon/robot/mommi/New(loc) + spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, src) + spark_system.attach(src) + + + ident = rand(1, 999) + updatename() + updateicon() + + if(!cell) + cell = new /obj/item/weapon/cell(src) + cell.maxcharge = 7500 + cell.charge = 7500 + ..() + module = new /obj/item/weapon/robot_module/mommi(src) + laws = new mommi_base_law_type + // Don't sync if we're a KEEPER. + if(!istype(laws,/datum/ai_laws/keeper)) + connected_ai = select_active_ai_with_fewest_borgs() + else + // Enforce silence. + keeper=1 + connected_ai = null // Enforce no AI parent + scrambledcodes = 1 // Hide from console because people are fucking idiots + + if(connected_ai) + connected_ai.connected_robots += src + lawsync() + lawupdate = 1 + else + lawupdate = 0 + + radio = new /obj/item/device/radio/borg(src) + if(!scrambledcodes && !camera) + camera = new /obj/machinery/camera(src) + camera.c_tag = real_name + camera.network = list("SS13") + if(wires.IsCameraCut()) // 5 = BORG CAMERA + camera.status = 0 + + // Sanity check + if(connected_ai && keeper) + world << "\red ASSERT FAILURE: connected_ai && keeper in mommi.dm" + + //playsound(loc, 'sound/voice/liveagain.ogg', 75, 1) + playsound(loc, 'sound/misc/interference.ogg', 75, 1) + + +/mob/living/silicon/robot/mommi/choose_icon() + var/icontype = input("Select an icon!", "Mobile MMI", null) in list("Basic", "Keeper") + switch(icontype) + if("Basic") subtype = "mommi" + else subtype = "keeper" + updateicon() + var/answer = input("Is this what you want?", "Mobile MMI", null) in list("Yes", "No") + switch(answer) + if("No") + choose_icon() + return + picked = 1 + +/mob/living/silicon/robot/mommi/pick_module() + + if(module) + return + var/list/modules = list("MoMMI") + if(modules.len) + modtype = input("Please, select a module!", "Robot", null, null) in modules + else: + modtype=modules[0] + + var/module_sprites[0] //Used to store the associations between sprite names and sprite index. + var/channels = list() + + if(module) + return + + switch(modtype) + if("MoMMI") + module = new /obj/item/weapon/robot_module/standard(src) + module_sprites["Basic"] = "mommi" + module_sprites["Keeper"] = "keeper" + + //Custom_sprite check and entry + if (custom_sprite == 1) + module_sprites["Custom"] = "[src.ckey]-[modtype]" + + hands.icon_state = lowertext(modtype) + feedback_inc("mommi_[lowertext(modtype)]",1) + updatename() + + choose_icon(6,module_sprites) + radio.config(channels) + base_icon = icon_state + +//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO +//Improved /N +/mob/living/silicon/robot/mommi/Del() + if(mmi)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside. + var/obj/item/device/mmi/nmmi = mmi + var/turf/T = get_turf(loc)//To hopefully prevent run time errors. + if(T) nmmi.loc = T + if(mind) mind.transfer_to(nmmi.brainmob) + mmi = null + nmmi.icon = 'icons/obj/assemblies.dmi' + nmmi.invisibility = 0 + ..() + +/mob/living/silicon/robot/mommi/updatename(var/prefix as text) + + var/changed_name = "" + if(custom_name) + changed_name = custom_name + else + changed_name = "Mobile MMI [num2text(ident)]" + real_name = changed_name + name = real_name + +/mob/living/silicon/robot/attackby(obj/item/weapon/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/handcuffs)) // fuck i don't even know why isrobot() in handcuff code isn't working so this will have to do + return + + if (istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if (WT.remove_fuel(0)) + adjustBruteLoss(-30) + updatehealth() + add_fingerprint(user) + for(var/mob/O in viewers(user, null)) + O.show_message(text("\red [user] has fixed some of the dents on [src]!"), 1) + else + user << "Need more welding fuel!" + return + + else if(istype(W, /obj/item/weapon/cable_coil) && wiresexposed) + var/obj/item/weapon/cable_coil/coil = W + adjustFireLoss(-30) + updatehealth() + coil.use(1) + for(var/mob/O in viewers(user, null)) + O.show_message(text("\red [user] has fixed some of the burnt wires on [src]!"), 1) + + else if (istype(W, /obj/item/weapon/crowbar)) // crowbar means open or close the cover + if(stat == DEAD) + user << "You pop the MMI off the base." + spawn(0) + del(src) + return + if(opened) + user << "You close the cover." + opened = 0 + updateicon() + else + if(locked) + user << "The cover is locked and cannot be opened." + else + user << "You open the cover." + opened = 1 + updateicon() + + else if (istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside + if(wiresexposed) + user << "Close the panel first." + else if(cell) + user << "There is a power cell already installed." + else + user.drop_item() + W.loc = src + cell = W + user << "You insert the power cell." +// chargecount = 0 + updateicon() + + else if (istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/multitool)) + if (wiresexposed) + wires.Interact() + else + user << "You can't reach the wiring." + + else if(istype(W, /obj/item/weapon/screwdriver) && opened && !cell) // haxing + wiresexposed = !wiresexposed + user << "The wires have been [wiresexposed ? "exposed" : "unexposed"]" + updateicon() + + else if(istype(W, /obj/item/weapon/screwdriver) && opened && cell) // radio + if(radio) + radio.attackby(W,user)//Push it to the radio to let it handle everything + else + user << "Unable to locate a radio." + updateicon() + + else if(istype(W, /obj/item/device/encryptionkey/) && opened) + if(radio)//sanityyyyyy + radio.attackby(W,user)//GTFO, you have your own procs + else + user << "Unable to locate a radio." + + else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card + if(emagged)//still allow them to open the cover + user << "The interface seems slightly damaged" + if(opened) + user << "You must close the cover to swipe an ID card." + else + if(allowed(usr)) + locked = !locked + user << "You [ locked ? "lock" : "unlock"] [src]'s interface." + updateicon() + else + user << "\red Access denied." + + else if(istype(W, /obj/item/weapon/card/emag)) // trying to unlock with an emag card + if(!opened)//Cover is closed + if(locked) + if(prob(90)) + user << "You emag the cover lock." + locked = 0 + else + user << "You fail to emag the cover lock." + if(prob(25)) + src << "Hack attempt detected." + else + user << "The cover is already unlocked." + return + + if(opened)//Cover is open + if(emagged) return//Prevents the X has hit Y with Z message also you cant emag them twice + if(wiresexposed) + user << "You must close the panel first" + return + else + sleep(6) + if(prob(50)) + emagged = 1 + lawupdate = 0 + connected_ai = null + user << "You emag [src]'s interface." +// message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.") + log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.") + clear_supplied_laws() + clear_inherent_laws() + laws = new /datum/ai_laws/syndicate_override + var/time = time2text(world.realtime,"hh:mm:ss") + lawchanges.Add("[time] : [user.name]([user.key]) emagged [name]([key])") + set_zeroth_law("Only [user.real_name] and people he designates as being such are Syndicate Agents.") + src << "\red ALERT: Foreign software detected." + sleep(5) + src << "\red Initiating diagnostics..." + sleep(20) + src << "\red SynBorg v1.7 loaded." + sleep(5) + src << "\red LAW SYNCHRONISATION ERROR" + sleep(5) + src << "\red Would you like to send a report to NanoTraSoft? Y/N" + sleep(10) + src << "\red > N" + sleep(20) + src << "\red ERRORERRORERROR" + src << "Obey these laws:" + laws.show_laws(src) + src << "\red \b ALERT: [user.real_name] is your new master. Obey your new laws and his commands." + if(src.module && istype(src.module, /obj/item/weapon/robot_module/miner)) + for(var/obj/item/weapon/pickaxe/borgdrill/D in src.module.modules) + del(D) + src.module.modules += new /obj/item/weapon/pickaxe/diamonddrill(src.module) + src.module.rebuild() + updateicon() + else + user << "You fail to [ locked ? "unlock" : "lock"] [src]'s interface." + if(prob(25)) + src << "Hack attempt detected." + return + + else if(istype(W, /obj/item/borg/upgrade/)) + var/obj/item/borg/upgrade/U = W + if(!opened) + usr << "You must access the borgs internals!" + else if(!src.module && U.require_module) + usr << "The borg must choose a module before he can be upgraded!" + else if(U.locked) + usr << "The upgrade is locked and cannot be used yet!" + else + if(U.action(src)) + usr << "You apply the upgrade to [src]!" + usr.drop_item() + U.loc = src + else + usr << "Upgrade error!" + + + else + spark_system.start() + return ..() + +/mob/living/silicon/robot/mommi/attack_hand(mob/user) + add_fingerprint(user) + + if(opened && !wiresexposed && (!istype(user, /mob/living/silicon))) + if(cell) + cell.updateicon() + cell.add_fingerprint(user) + user.put_in_active_hand(cell) + user << "You remove \the [cell]." + cell = null + updateicon() + return + + + if(ishuman(user)) + if(istype(user:gloves, /obj/item/clothing/gloves/space_ninja)&&user:gloves:candrain&&!user:gloves:draining) + call(/obj/item/clothing/gloves/space_ninja/proc/drain)("CYBORG",src,user:wear_suit) + return + if(user.a_intent == "help") + user.visible_message("\blue [user.name] pats [src.name] on the head.") + return + + + + if(!istype(user, /mob/living/silicon)) + switch(user.a_intent) + if("disarm") + user.attack_log += text("\[[time_stamp()]\] Disarmed [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] Has been disarmed by [user.name] ([user.ckey])") + log_admin("ATTACK: [user.name] ([user.ckey]) disarmed [src.name] ([src.ckey])") + log_attack("[user.name] ([user.ckey]) disarmed [src.name] ([src.ckey])") + var/randn = rand(1,100) + //var/talked = 0; + if (randn <= 25) + weakened = 3 + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + visible_message("\red [user] has pushed [src]!") + var/obj/item/found = locate(tool_state) in src.module.modules + if(!found) + var/obj/item/TS = tool_state + drop_item() + if(TS && TS.loc) + TS.loc = src.loc + visible_message("\red [src]'s robotic arm loses grip on what it was holding") + return + if(randn <= 50)//MoMMI's robot arm is stronger than a human's, but not by much + var/obj/item/found = locate(tool_state) in src.module.modules + if(!found) + var/obj/item/TS = tool_state + drop_item() + if(TS && TS.loc) + TS.loc = src.loc + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + visible_message("\red [user] has disarmed [src]!") + else + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("\red [user] attempted to disarm [src]!") + return + + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("\red [user] attempted to disarm [src]!") + +/mob/living/silicon/robot/mommi/updateicon() + icon_state=subtype + // Clear all overlays. + overlays.Cut() + if(opened) // TODO: Open the front "head" panel + if(wiresexposed) + overlays += "ov-openpanel +w" + else if(cell) + overlays += "ov-openpanel +c" + else + overlays += "ov-openpanel -c" + // Put our eyes just on top of the lighting, so it looks emissive in maint tunnels. + if(layer==MOB_LAYER) + overlays+=image(icon,"eyes-[subtype][emagged?"-emagged":""]",LIGHTING_LAYER+1) + if(anchored) + overlays+=image(icon,"[subtype]-park", LIGHTING_LAYER+1) + else + overlays+=image(icon,"eyes-[subtype][emagged?"-emagged":""]",TURF_LAYER+0.2) // Fixes floating eyes + if(anchored) + overlays+=image(icon,"[subtype]-park", TURF_LAYER+0.2) + return + + + +/mob/living/silicon/robot/mommi/installed_modules() + if(weapon_lock) + src << "\red Weapon lock active, unable to use modules! Count:[weaponlock_time]" + return + + if(!module) + pick_module() + return + if(!picked) + choose_icon() + return + var/dat = "Modules\n" + dat += {"
+
+ Activated Modules +
+ Sight Mode: [sight_state ? "[sight_state]" : "No module selected"]
+ Utility Module: [tool_state ? "[tool_state]" : "No module selected"]
+
+ Installed Modules

"} + + + for (var/obj in module.modules) + if (!obj) + dat += text("Resource depleted
") + else if(activated(obj)) + dat += text("[obj]: Activated
") + else + dat += text("[obj]: Activate
") + if (emagged) + if(activated(module.emag)) + dat += text("[module.emag]: Activated
") + else + dat += text("[module.emag]: Activate
") + src << browse(dat, "window=robotmod") + onclose(src,"robotmod") // Register on-close shit, which unsets machinery. + + +/mob/living/silicon/robot/mommi/Topic(href, href_list) + ..() + if(usr && (src != usr)) + return + + if (href_list["mach_close"]) + var/t1 = text("window=[href_list["mach_close"]]") + unset_machine() + src << browse(null, t1) + return + + if (href_list["showalerts"]) + robot_alerts() + return + + if (href_list["mod"]) + var/obj/item/O = locate(href_list["mod"]) + if (O) + O.attack_self(src) + + if (href_list["act"]) + var/obj/item/O = locate(href_list["act"]) + var/obj/item/TS + if(!(locate(O) in src.module.modules) && O != src.module.emag) + return + if(istype(O,/obj/item/borg/sight)) + TS = sight_state + if(sight_state) + contents -= sight_state + sight_mode &= ~sight_state:sight_mode + if (client) + client.screen -= sight_state + sight_state = O + O.layer = 20 + contents += O + sight_mode |= sight_state:sight_mode + + inv_sight.icon_state = "sight+a" + inv_tool.icon_state = "inv1" + module_active=sight_state + else + TS = tool_state + if(tool_state) + contents -= tool_state + if (client) + client.screen -= tool_state + tool_state = O + O.layer = 20 + contents += O + + inv_sight.icon_state = "sight" + inv_tool.icon_state = "inv1 +a" + module_active=tool_state + if(TS && istype(TS)) + if(src.is_in_modules(TS)) + TS.loc = src.module + else + TS.layer=initial(TS.layer) + TS.loc = src.loc + + installed_modules() + return + +/mob/living/silicon/robot/mommi/radio_menu() + radio.interact(src)//Just use the radio's Topic() instead of bullshit special-snowflake code + + +/mob/living/silicon/robot/mommi/Move(a, b, flag) + + ..() + +/mob/living/silicon/robot/mommi/proc/ActivateKeeper() + set category = "Robot Commands" + set name = "Activate KEEPER" + set desc = "Performs a full purge of your laws and disconnects you from AIs and cyborg consoles. However, you lose the ability to speak and must remain neutral, only being permitted to perform station upkeep. You can still be emagged in this state." + + if(keeper) + return + + var/mob/living/silicon/robot/R = src + + if(R) + R.UnlinkSelf() + var/obj/item/weapon/aiModule/keeper/mdl = new + + mdl.transmitInstructions(src, src) + src << "These are your laws now:" + src.show_laws() + + src.verbs -= /mob/living/silicon/robot/mommi/proc/ActivateKeeper \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 81db811de8e..21fcd4f873d 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -62,7 +62,7 @@ /mob/living/silicon/robot/proc/handle_regular_status_updates() if(src.camera && !scrambledcodes) - if(src.stat == 2 || isWireCut(5)) + if(src.stat == 2 || wires.IsCameraCut()) src.camera.status = 0 else src.camera.status = 1 diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index a1a33e875ef..03a01ce5a47 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -40,6 +40,8 @@ var/obj/item/device/pda/ai/rbPDA = null + var/datum/wires/robot/wires = null + var/opened = 0 var/emagged = 0 var/wiresexposed = 0 @@ -55,7 +57,7 @@ var/datum/effect/effect/system/ion_trail_follow/ion_trail = null var/datum/effect/effect/system/spark_spread/spark_system//So they can initialize sparks whenever/N var/jeton = 0 - var/borgwires = 31 // 0b11111 + var/killswitch = 0 var/killswitch_time = 60 var/weapon_lock = 0 @@ -74,13 +76,12 @@ spark_system.set_up(5, 0, src) spark_system.attach(src) - -// wires = new(src) - robot_modules_background = new() robot_modules_background.icon_state = "block" robot_modules_background.layer = 19 //Objects that appear on screen are on layer 20, UI should be just below it. + wires = new(src) + ident = rand(1, 999) updatename("Default") updateicon() @@ -119,7 +120,7 @@ camera = new /obj/machinery/camera(src) camera.c_tag = real_name camera.network = list("SS13","Robots") - if(isWireCut(5)) // 5 = BORG CAMERA + if(wires.IsCameraCut()) // 5 = BORG CAMERA camera.status = 0 initialize_components() @@ -594,7 +595,7 @@ user << "You close the cover." opened = 0 updateicon() - else if(mmi && wiresexposed && isWireCut(1) && isWireCut(2) && isWireCut(3) && isWireCut(4) && isWireCut(5)) + else if(mmi && wiresexposed && wires.IsAllCut()) //Cell is out, wires are exposed, remove MMI, produce damaged chassis, baleet original mob. user << "You jam the crowbar into the robot and begin levering [mmi]." sleep(30) @@ -654,7 +655,7 @@ else if (istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/multitool)) if (wiresexposed) - interact(user) + wires.Interact(user) else user << "You can't reach the wiring." @@ -774,6 +775,17 @@ spark_system.start() return ..() +/mob/living/silicon/robot/verb/unlock_own_cover() + set category = "Robot Commands" + set name = "Unlock Cover" + set desc = "Unlocks your own cover if it is locked. You can not lock it again. A human will have to lock it for you." + if(locked) + switch(alert("You can not lock your cover again, are you sure?\n (You can still ask for a human to lock it)", "Unlock Own Cover", "Yes", "No")) + if("Yes") + locked = 0 + updateicon() + usr << "You unlock your cover." + /mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M as mob) if (!ticker) M << "You cannot attack people before the game has started." @@ -1188,6 +1200,13 @@ return +/mob/living/silicon/robot/proc/SetLockdown(var/state = 1) + // They stay locked down if their wire is cut. + if(wires.LockedCut()) + state = 1 + lockcharge = state + update_canmove() + /mob/living/silicon/robot/verb/pose() set name = "Set Pose" set desc = "Sets a description which will be shown when someone examines you." diff --git a/code/modules/mob/living/silicon/robot/wires.dm b/code/modules/mob/living/silicon/robot/wires.dm deleted file mode 100644 index 10b6832fe4b..00000000000 --- a/code/modules/mob/living/silicon/robot/wires.dm +++ /dev/null @@ -1,148 +0,0 @@ -#define BORG_WIRE_LAWCHECK 1 -#define BORG_WIRE_MAIN_POWER1 2 -#define BORG_WIRE_MAIN_POWER2 3 -#define BORG_WIRE_AI_CONTROL 4 -#define BORG_WIRE_CAMERA 5 - -/proc/RandomBorgWires() - //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else). - var/list/Borgwires = list(0, 0, 0, 0, 0) - BorgIndexToFlag = list(0, 0, 0, 0, 0) - BorgIndexToWireColor = list(0, 0, 0, 0, 0) - BorgWireColorToIndex = list(0, 0, 0, 0, 0) - var/flagIndex = 1 - //I think it's easier to read this way, also doesn't rely on the random number generator to land on a new wire. - var/list/colorIndexList = list(BORG_WIRE_LAWCHECK, BORG_WIRE_MAIN_POWER1, BORG_WIRE_MAIN_POWER2, BORG_WIRE_AI_CONTROL, BORG_WIRE_CAMERA) - for (var/flag=1, flag<=16, flag+=flag) - var/colorIndex = pick(colorIndexList) - if (Borgwires[colorIndex]==0) - Borgwires[colorIndex] = flag - BorgIndexToFlag[flagIndex] = flag - BorgIndexToWireColor[flagIndex] = colorIndex - BorgWireColorToIndex[colorIndex] = flagIndex - colorIndexList -= colorIndex // Shortens the list. - //world.log << "Flag: [flag], CIndex: [colorIndex], FIndex: [flagIndex]" - flagIndex+=1 - return Borgwires - -/mob/living/silicon/robot/proc/isWireColorCut(var/wireColor) - var/wireFlag = BorgWireColorToFlag[wireColor] - return ((src.borgwires & wireFlag) == 0) - -/mob/living/silicon/robot/proc/isWireCut(var/wireIndex) - var/wireFlag = BorgIndexToFlag[wireIndex] - return ((src.borgwires & wireFlag) == 0) - -/mob/living/silicon/robot/proc/cut(var/wireColor) - var/wireFlag = BorgWireColorToFlag[wireColor] - var/wireIndex = BorgWireColorToIndex[wireColor] - borgwires &= ~wireFlag - switch(wireIndex) - if(BORG_WIRE_LAWCHECK) //Cut the law wire, and the borg will no longer receive law updates from its AI - if (src.lawupdate == 1) - src << "LawSync protocol engaged." - src.show_laws() - if (BORG_WIRE_AI_CONTROL) //Cut the AI wire to reset AI control - if (src.connected_ai) - src.connected_ai = null - if (BORG_WIRE_CAMERA) - if(!isnull(src.camera) && !scrambledcodes) - src.camera.status = 0 - src.camera.deactivate(usr, 0) // Will kick anyone who is watching the Cyborg's camera. - - src.interact(usr) - -/mob/living/silicon/robot/proc/mend(var/wireColor) - var/wireFlag = BorgWireColorToFlag[wireColor] - var/wireIndex = BorgWireColorToIndex[wireColor] - borgwires |= wireFlag - switch(wireIndex) - if(BORG_WIRE_LAWCHECK) //turns law updates back on assuming the borg hasn't been emagged - if (src.lawupdate == 0 && !src.emagged) - src.lawupdate = 1 - if(BORG_WIRE_CAMERA) - if (!isnull(src.camera) && !scrambledcodes) - src.camera.status = 1 - src.camera.deactivate(usr, 0) // Will kick anyone who is watching the Cyborg's camera. - - src.interact(usr) - - -/mob/living/silicon/robot/proc/pulse(var/wireColor) - var/wireIndex = BorgWireColorToIndex[wireColor] - switch(wireIndex) - if(BORG_WIRE_LAWCHECK) //Forces a law update if the borg is set to receive them. Since an update would happen when the borg checks its laws anyway, not much use, but eh - if (src.lawupdate) - src.lawsync() - - if (BORG_WIRE_AI_CONTROL) //pulse the AI wire to make the borg reselect an AI - if(!src.emagged) - src.connected_ai = select_active_ai() - - if (BORG_WIRE_CAMERA) - if(!isnull(src.camera) && src.camera.status && !scrambledcodes) - src.camera.deactivate(usr, 0) // Kick anyone watching the Cyborg's camera, doesn't display you disconnecting the camera. - usr << "[src]'s camera lens focuses loudly." - src << "Your camera lens focuses loudly." - - src.interact(usr) - -/mob/living/silicon/robot/proc/interact(mob/user) - if(wiresexposed && (!istype(user, /mob/living/silicon))) - user.set_machine(src) - var/t1 = text("Access Panel
\n") - var/list/Borgwires = list( - "Orange" = 1, - "Dark red" = 2, - "White" = 3, - "Yellow" = 4, - "Blue" = 5, - ) - for(var/wiredesc in Borgwires) - var/is_uncut = src.borgwires & BorgWireColorToFlag[Borgwires[wiredesc]] - t1 += "[wiredesc] wire: " - if(!is_uncut) - t1 += "Mend" - else - t1 += "Cut " - t1 += "Pulse " - t1 += "
" - t1 += text("
\n[(src.lawupdate ? "The LawSync light is on." : "The LawSync light is off.")]
\n[(src.connected_ai ? "The AI link light is on." : "The AI link light is off.")]") - t1 += text("
\n[((!isnull(src.camera) && src.camera.status == 1) ? "The Camera light is on." : "The Camera light is off.")]
\n") - t1 += text("

Close

\n") - user << browse(t1, "window=borgwires") - onclose(user, "borgwires") - -/mob/living/silicon/robot/Topic(href, href_list) - ..() - if (((in_range(src, usr) && istype(src.loc, /turf))) && !istype(usr, /mob/living/silicon)) - usr.set_machine(src) - if (href_list["borgwires"]) - var/t1 = text2num(href_list["borgwires"]) - if (!( istype(usr.get_active_hand(), /obj/item/weapon/wirecutters) )) - usr << "You need wirecutters!" - return - if (src.isWireColorCut(t1)) - src.mend(t1) - else - src.cut(t1) - else if (href_list["pulse"]) - var/t1 = text2num(href_list["pulse"]) - if (!istype(usr.get_active_hand(), /obj/item/device/multitool)) - usr << "You need a multitool!" - return - if (src.isWireColorCut(t1)) - usr << "You can't pulse a cut wire." - return - else - src.pulse(t1) - else if (href_list["close2"]) - usr << browse(null, "window=borgwires") - usr.unset_machine() - return - -#undef BORG_WIRE_LAWCHECK -#undef BORG_WIRE_MAIN_POWER1 -#undef BORG_WIRE_MAIN_POWER2 -#undef BORG_WIRE_AI_CONTROL -#undef BORG_WIRE_CAMERA \ No newline at end of file diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 58bf31d55d7..05dfc79f107 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -431,4 +431,16 @@ var/list/intents = list("help","disarm","grab","hurt") set category = "IC" resting = !resting - src << "\blue You are now [resting ? "resting" : "getting up"]" \ No newline at end of file + src << "\blue You are now [resting ? "resting" : "getting up"]" + +/proc/get_multitool(mob/user as mob) + // Check distance for those that need it. + if(!isAI(user)) + if(!in_range(user, src)) + return null + + // Get tool + var/obj/item/device/multitool/P = user.get_multitool() + if(!istype(P)) + return null + return P \ No newline at end of file diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm index 04163d48594..a7aeffe9508 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_control.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm @@ -14,11 +14,15 @@ construction_state = 0 active = 0 dir = 1 + var/strength_upper_limit = 2 + var/interface_control = 1 var/list/obj/structure/particle_accelerator/connected_parts var/assembled = 0 var/parts = null + var/datum/wires/particle_acc/control_box/wires = null /obj/machinery/particle_accelerator/control_box/New() + wires = new(src) connected_parts = list() ..() @@ -26,6 +30,8 @@ /obj/machinery/particle_accelerator/control_box/attack_hand(mob/user as mob) if(construction_state >= 3) interact(user) + else if(construction_state == 2) // Wires exposed + wires.Interact(user) /obj/machinery/particle_accelerator/control_box/update_state() if(construction_state < 3) @@ -67,11 +73,11 @@ return /obj/machinery/particle_accelerator/control_box/Topic(href, href_list) - ..() - //Ignore input if we are broken, !silicon guy cant touch us, or nonai controlling from super far away - if(stat & (BROKEN|NOPOWER) || (get_dist(src, usr) > 1 && !istype(usr, /mob/living/silicon)) || (get_dist(src, usr) > 8 && !istype(usr, /mob/living/silicon/ai))) - usr.unset_machine() - usr << browse(null, "window=pacontrol") + if(..()) + return + + if(!interface_control) + usr << "ERROR: Request timed out. Check wire contacts." return if( href_list["close"] ) @@ -79,45 +85,54 @@ usr.unset_machine() return if(href_list["togglep"]) - src.toggle_power() - investigate_log("turned [active?"ON":"OFF"] by [usr.key]","singulo") - if (active) - message_admins("PA Control Computer turned ON by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1) - log_game("PA Control Computer turned ON by [usr.ckey]([usr]) in ([x],[y],[z])") + if(!wires.IsIndexCut(PARTICLE_TOGGLE_WIRE)) + src.toggle_power() else if(href_list["scan"]) src.part_scan() else if(href_list["strengthup"]) + if(!wires.IsIndexCut(PARTICLE_STRENGTH_WIRE)) + add_strength() + + else if(href_list["strengthdown"]) + if(!wires.IsIndexCut(PARTICLE_STRENGTH_WIRE)) + remove_strength() + + src.updateDialog() + src.update_icon() + return + + +/obj/machinery/particle_accelerator/control_box/proc/strength_change() + for(var/obj/structure/particle_accelerator/part in connected_parts) + part.strength = strength + part.update_icon() + +/obj/machinery/particle_accelerator/control_box/proc/add_strength(var/s) + if(assembled) strength++ - if(strength > 2) - strength = 2 + if(strength > strength_upper_limit) + strength = strength_upper_limit else message_admins("PA Control Computer increased to [strength] by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1) log_game("PA Control Computer increased to [strength] by [usr.ckey]([usr]) in ([x],[y],[z])") investigate_log("increased to [strength] by [usr.key]","singulo") - for(var/obj/structure/particle_accelerator/part in connected_parts) - part.strength = strength - part.update_icon() + strength_change() - else if(href_list["strengthdown"]) +/obj/machinery/particle_accelerator/control_box/proc/remove_strength(var/s) + if(assembled) strength-- if(strength < 0) strength = 0 else investigate_log("decreased to [strength] by [usr.key]","singulo") - for(var/obj/structure/particle_accelerator/part in connected_parts) - part.strength = strength - part.update_icon() - src.updateDialog() - src.update_icon() - return - + strength_change() /obj/machinery/particle_accelerator/control_box/power_change() ..() if(stat & NOPOWER) active = 0 use_power = 0 - else if(!stat && construction_state == 3) + else if(!stat && construction_state <= 3) use_power = 1 return @@ -187,6 +202,10 @@ /obj/machinery/particle_accelerator/control_box/proc/toggle_power() src.active = !src.active + investigate_log("turned [active?"ON":"OFF"] by [usr ? usr.key : "outside forces"]","singulo") + if (active) + message_admins("PA Control Computer turned ON by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1) + log_game("PA Control Computer turned ON by [usr.ckey]([usr]) in ([x],[y],[z])") if(src.active) src.use_power = 2 for(var/obj/structure/particle_accelerator/part in connected_parts)