diff --git a/main-src/Code/!atoms.dm b/main-src/Code/!atoms.dm index 52e7c8e..c0bfc5b 100644 --- a/main-src/Code/!atoms.dm +++ b/main-src/Code/!atoms.dm @@ -2387,51 +2387,8 @@ Total SMES charging rate should not exceed total power generation rate, or an ov var/locked = 0.0 var/mob/occupant = null anchored = 1.0 -/obj/machinery/door - name = "door" - icon = 'doors.dmi' - icon_state = "door1" - opacity = 1 - density = 1 - var/visible = 1.0 - var/access = "0000" - var/allowed = null - //var/r_access - //var/r_lab - //var/r_engine - //var/r_air - var/p_open = 0.0 - var/operating = null - anchored = 1.0 -/obj/machinery/door/airlock - name = "airlock" - icon = 'Door1.dmi' - var/blocked = null - var/powered = 1.0 - var/locked = 0.0 - var/wires = 511.0 -/obj/machinery/door/false_wall - name = "wall" - icon = 'Doorf.dmi' -/obj/machinery/door/firedoor - name = "firedoor" - icon = 'Door1.dmi' - icon_state = "door0" - var/blocked = null - opacity = 0 - density = 0 -/obj/machinery/door/poddoor - name = "poddoor" - icon = 'Door1.dmi' - icon_state = "pdoor1" - var/id = 1.0 -/obj/machinery/door/window - name = "interior door" - icon = 'windoor.dmi' - visible = 0.0 - flags = 512.0 - opacity = 0 + /obj/machinery/freezer name = "freezer" @@ -2469,13 +2426,7 @@ Total SMES charging rate should not exceed total power generation rate, or an ov var/code = 1.0 var/id = 1.0 anchored = 1.0 -/obj/machinery/meter - name = "meter" - icon = 'pipes.dmi' - icon_state = "meterX" - var/obj/machinery/pipes/target = null - anchored = 1.0 - var/average = 0 + /obj/machinery/nuclearbomb desc = "Uh oh." name = "Nuclear Fission Explosive" diff --git a/main-src/Code/Machinery/Door/_door.dm b/main-src/Code/Machinery/Door/_door.dm new file mode 100644 index 0000000..dbf2ef5 --- /dev/null +++ b/main-src/Code/Machinery/Door/_door.dm @@ -0,0 +1,146 @@ +/* + * Door -- the base door type. + * All other doors (airlocks, false walls, poddoors, firedoors and windowdoors) descend from this. + * + */ + +obj/machinery/door + name = "door" + icon = 'doors.dmi' + icon_state = "door1" + opacity = 1 + density = 1 + anchored = 1 + + var + visible = 1.0 // True for all except windowdoors; controls whether door becomes opaque when closed. + + access = "0000" // ID card access levels + allowed = null // ID card job assignment access + + p_open = 0.0 // True if the wiring panel is open; currently only used for airlocks + operating = null // True if door is currently opening/closing + + + // Create a new door. Ensure that turf links are updated. + + New() + ..() + var/turf/T = src.loc + if (istype(T, /turf)) + if (src.density) + T.updatecell = 0 + T.buildlinks() + + + // Called to open a door + // Plays opening animation, updates icon state, ensures turf links are updated + + proc/open() + if (src.operating) + return + src.operating = 1 + flick(text("[]doorc0", (src.p_open ? "o_" : null)), src) + src.icon_state = text("[]door0", (src.p_open ? "o_" : null)) + sleep(15) + src.density = 0 + src.opacity = 0 + var/turf/T = src.loc + if (istype(T, /turf)) + T.updatecell = 1 + T.buildlinks() + src.operating = 0 + + + // Called to close a door. + // Plays closing animation, updates icon state, ensures turf links are updated + + proc/close() + if (src.operating) + return + src.operating = 1 + flick(text("[]doorc1", (src.p_open ? "o_" : null)), src) + src.icon_state = text("[]door1", (src.p_open ? "o_" : null)) + src.density = 1 + if (src.visible) + src.opacity = 1 + var/turf/T = src.loc + if (istype(T, /turf)) + T.updatecell = 0 + T.buildlinks() + sleep(15) + src.operating = 0 + + // Monkey attack same as human + + attack_paw(mob/user) + return src.attack_hand(user) + + + // Attack with hand. If human and wearing an ID, same as attacking with the ID + + attack_hand(mob/user as mob) + if(istype(user, /mob/human)) + var/mob/human/H = user + if(H.wear_id) + attackby(H.wear_id, user) + + + // Attack with an item + // If an emag card, open the door if closed. Note: Door cannot be reclosed with an emag. + // If anything else, check to see if user is wearing an ID (or the ID was used) + // then check the ID access and open or close the door + + attackby(obj/item/I, mob/user) + + if (src.operating) + return + src.add_fingerprint(user) + if ((src.density && istype(I, /obj/item/weapon/card/emag))) + src.operating = 1 + flick("door_spark", src) + sleep(6) + src.operating = null + open() + return 1 + var/obj/item/weapon/card/id/card + if (istype(user, /mob/human)) + var/mob/human/H = user + card = H.wear_id + if (istype(I, /obj/item/weapon/card/id)) + card = I + else + if (!( istype(card, /obj/item/weapon/card/id) )) + return 0 + if (card.check_access(access, allowed)) + if (src.density) + open() + else + close() + else + if (src.density) + flick("door_deny", src) + + + // If hit by a meteor, open the door + + meteorhit(obj/M) + src.open() + return + + // Attack by blob, chance to destroy the door. + + blob_act() + if(prob(20)) + del(src) + +// Built-in proc called when the door moves location + // Since doors do not move, this seems to be redundent + + Move() + ..() + if (src.density) + var/turf/location = src.loc + if (istype(location, /turf)) + location.updatecell = 0 + buildlinks() diff --git a/main-src/Code/Machinery/Door/airlock.dm b/main-src/Code/Machinery/Door/airlock.dm new file mode 100644 index 0000000..18bf713 --- /dev/null +++ b/main-src/Code/Machinery/Door/airlock.dm @@ -0,0 +1,209 @@ +/* + * Airlock -- an airlock door. + * + * TODO: Make the interaction between the "test light" and the new power system more logical. + * TODO: Make it possible to crowbar an airlock open if the area power is out (but bolts still up) + */ + +obj/machinery/door/airlock + name = "airlock" + icon = 'Door1.dmi' + var + blocked = null // true if door is welded shut + powered = 1.0 // true if the test light is on + locked = 0.0 // true if the door bolts are down (locked) + wires = 511 // bitmask representing the 9 internal wires. Defaults to all connected + // The wire conditions effect the "powered" and "locked" variables. + + + // Called to open door. + // Door must be unwelded, not locked, test light on, and area power present to open + + open() + if ((src.blocked || src.locked || !( src.powered )) || stat & NOPOWER) + return + use_power(50) + ..() + + + // Called to close door + // If test light is off or no area power, do not close + + close() + if (!( src.powered || stat & NOPOWER)) + return + use_power(50) + ..() + var/turf/T = src.loc + if (T) + T.firelevel = 0 + + + // Set the icon state and other variables, depending on the wires bitfield. + + proc/update() + if (((!( src.wires & 2 ) || !( src.wires & 8 ) || !( src.wires & 32 ) || !( src.wires & 64 ) || !( src.wires & 128 ) || !( src.wires & 256 )) && src.powered)) + src.locked = 1 // Door is locked if grey, blue, yellow, white, dk red or orange wires are cut and test light is on + // Note bolts are not automatically raised - you must use a wrench to reset + if ((!( src.wires & 1 ) && !( src.wires & 4 ) && !( src.wires & 16 ))) + src.powered = 0 // Test light goes off if black, green and red wires are cut + else + src.powered = 1 // Otherwise test light is on + var/d = src.density + if (src.blocked) // true if welded shut + d = "l" + src.icon_state = text("[]door[]", (src.p_open ? "o_" : null), d) + return + + + // Monkey interact same a human + + attack_paw(mob/user) + return src.attack_hand(user) + + + // Human interact. If the door panel is open, show the wire interaction window. Otherwise, do standard door interaction. + + attack_hand(mob/user) + if (src.p_open) + user.machine = src + var/t1 = {"Access Panel
+Orange Wire: [(src.wires & 256 ? "Cut Wire" : "Mend Wire")]
+Dark Red Wire: [(src.wires & 128 ? "Cut Wire" : "Mend Wire")]
+White Wire: [(src.wires & 64 ? "Cut Wire" : "Mend Wire")]
+Yellow Wire: [(src.wires & 32 ? "Cut Wire" : "Mend Wire")]
+Red Wire: [(src.wires & 16 ? "Cut Wire" : "Mend Wire")]
+Blue Wire: [(src.wires & 8 ? "Cut Wire" : "Mend Wire")]
+Green Wire: [(src.wires & 4 ? "Cut Wire" : "Mend Wire")]
+Grey Wire: [(src.wires & 2 ? "Cut Wire" : "Mend Wire")]
+Black Wire: [(src.wires & 1 ? "Cut Wire" : "Mend Wire")]
+
+[(src.locked ? "The door bolts have fallen!" : "The door bolts look up.")]
+[(src.powered ? "The test light is on." : "The test light is off!")]"} + + + user << browse(t1, "window=airlock") + else + ..(user) + return + + + // Handle topic links from interaction window. Cut/join wires if clicking with wirecutters + + Topic(href, href_list) + ..() + if (usr.stat || usr.restrained() ) + return + if ((get_dist(src, usr) <= 1 && istype(src.loc, /turf))) + usr.machine = src + if (href_list["wires"]) + var/t1 = text2num(href_list["wires"]) + if (!( istype(usr.equipped(), /obj/item/weapon/wirecutters) )) + return + if (!( src.p_open )) + return + if (t1 & 1) + if (src.wires & 1) + src.wires &= ~1 + else + src.wires |= 1 + else if (t1 & 2) + if (src.wires & 2) + src.wires &= ~2 + else + src.wires |= 2 + else if (t1 & 4) + if (src.wires & 4) + src.wires &= ~4 + else + src.wires |= 4 + else if (t1 & 8) + if (src.wires & 8) + src.wires &= ~8 + else + src.wires |= 8 + else if (t1 & 16) + if (src.wires & 16) + src.wires &= ~16 + else + src.wires |= 16 + else if (t1 & 32) + if (src.wires & 32) + src.wires &= ~32 + else + src.wires |= 32 + else if (t1 & 64) + if (src.wires & 64) + src.wires &= ~64 + else + src.wires |= 64 + else if (t1 & 128) + if (src.wires & 128) + src.wires &= ~128 + else + src.wires |= 128 + else if (t1 & 256) + if (src.wires & 256) + src.wires &= ~256 + else + src.wires |= 256 + src.update() + add_fingerprint(usr) + for(var/mob/M in viewers(1, src)) + if ((M.client && M.machine == src)) + src.attack_hand(M) + return + + + // Attack with item. + // If weldingtool (and door is closed), weld/unweld the door + // If wrench, and door has test light on, unlock the door (raise bolts) + // If screwdriver, toggle door panel open/closed + // If crowbar, and door is closed, not welded, test light off and not locked, open the door + // Otherwise, do standard door attackby() + + attackby(obj/item/weapon/C, mob/user) + src.add_fingerprint(user) + if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) + var/obj/item/weapon/weldingtool/W = C + if(W.welding) + if (W.weldfuel > 2) + W.weldfuel -= 2 + else + user << "Need more welding fuel!" + return + if (!( src.blocked )) + src.blocked = 1 + else + src.blocked = null + src.update() + return + else if (istype(C, /obj/item/weapon/wrench)) + if (src.p_open) + if (src.powered) + src.locked = null + else + user << alert("You need power assist!", null, null, null, null, null) + src.update() + else if (istype(C, /obj/item/weapon/screwdriver)) + src.p_open = !( src.p_open ) + update() + else if (istype(C, /obj/item/weapon/crowbar)) + if ((src.density && !( src.blocked ) && !( src.operating ) && !( src.powered ) && !( src.locked ))) + spawn( 0 ) + src.operating = 1 + flick(text("[]doorc0", (src.p_open ? "o_" : null)), src) + src.icon_state = text("[]door0", (src.p_open ? "o_" : null)) + sleep(15) + src.density = 0 + src.opacity = 0 + var/turf/T = src.loc + if (istype(T, /turf)) + T.updatecell = 1 + T.buildlinks() + src.operating = 0 + return + else + ..() + return + diff --git a/main-src/Code/Machinery/Door/false_wall.dm b/main-src/Code/Machinery/Door/false_wall.dm new file mode 100644 index 0000000..a531d3a --- /dev/null +++ b/main-src/Code/Machinery/Door/false_wall.dm @@ -0,0 +1,57 @@ +/* + * False_wall -- A fake wall that can be opened like a door. + * + * + */ + +obj/machinery/door/false_wall + name = "wall" + icon = 'Doorf.dmi' + + + // Create a false-wall door. Remove the pull verb as this gives away the doors position. + + New() + ..() + src.verbs -= /atom/movable/verb/pull + + // Examine verb. Same result as a standard wall. + + examine() + set src in oview(1) + + usr << "It looks like a regular wall" + + // Monkey interact - if in monkey mode, same as human + + attack_paw(mob/user) + if ((ticker && ticker.mode == "monkey")) + return src.attack_hand(user) + + + // Human interact - 25% chance to open the door + + attack_hand(mob/user) + + src.add_fingerprint(user) + if (src.density) + if (prob(25)) + open() + else + user << "\blue You push the wall but nothing happens!" + else + close() + + // Attack by item + // If a screwdriver, disassembly the false wall into components + + attackby(obj/item/weapon/screwdriver/S, mob/user) + + src.add_fingerprint(user) + if (istype(S, /obj/item/weapon/screwdriver)) + new /obj/item/weapon/sheet/metal( src.loc ) + new /obj/d_girders( src.loc ) + del(src) + return + else + ..() diff --git a/main-src/Code/Machinery/Door/firedoor.dm b/main-src/Code/Machinery/Door/firedoor.dm new file mode 100644 index 0000000..41cae72 --- /dev/null +++ b/main-src/Code/Machinery/Door/firedoor.dm @@ -0,0 +1,120 @@ +/* + * Firedoor - a door automatically closed by the firealarm system + * + */ + +obj/machinery/door/firedoor + name = "firedoor" + icon = 'Door1.dmi' + icon_state = "door0" + opacity = 0 // Firedoors start open + density = 0 // + var + blocked = null // true if the door has been welded shut (can't be opened) + + + // Standard open and close procs do not work with firedoors + + open() + usr << "This is a remote firedoor!" + + + close() + usr << "This is a remote firedoor!" + + + + // Called when area power status changes. Firedoors use the ENVIRON channel. + + power_change() + if( powered(ENVIRON) ) + stat &= ~NOPOWER + else + stat |= NOPOWER + + + // Attack by an item + // If a welding tool, weld the door shut (or unweld) + // If a crowbar. open the door. + + attackby(obj/item/weapon/C, mob/user) + + src.add_fingerprint(user) + if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) + var/obj/item/weapon/weldingtool/W = C + if(W.welding) + if (W.weldfuel > 2) + W.weldfuel -= 2 + if (!( src.blocked )) + src.blocked = 1 + src.icon_state = "doorl" + else + src.blocked = 0 + src.icon_state = "door1" + return + else + if (!( istype(C, /obj/item/weapon/crowbar) )) + return + if ((src.density && !( src.blocked ) && !( src.operating ))) + spawn( 0 ) + src.operating = 1 + flick("doorc0", src) + src.icon_state = "door0" + sleep(15) + src.density = 0 + src.opacity = 0 + var/turf/T = src.loc + if (istype(T, /turf)) + T.updatecell = 1 + T.buildlinks() + src.operating = 0 + + + // Called to open a firedoor + // Play opening animation, update icon state, and update turf links + + proc/openfire() + set src in oview(1) + + if (stat & NOPOWER) return + + if ((src.operating || src.blocked)) + return + use_power(50, ENVIRON) + src.operating = 1 + flick("doorc0", src) + src.icon_state = "door0" + sleep(15) + src.density = 0 + src.opacity = 0 + var/turf/T = src.loc + if (istype(T, /turf)) + T.updatecell = 1 + T.buildlinks() + src.operating = 0 + + + // Called to close a firedoor. + // Play closing animation, update icon state, and update turf links. + + proc/closefire() + set src in oview(1) + + if (stat & NOPOWER) return + + if (src.operating) + return + use_power(50, ENVIRON) + src.operating = 1 + flick("doorc1", src) + src.icon_state = "door1" + src.density = 1 + src.opacity = 1 + var/turf/T = src.loc + if (istype(T, /turf)) + T.updatecell = 0 + T.buildlinks() + T.firelevel = 0 + sleep(15) + src.operating = 0 + diff --git a/main-src/Code/Machinery/Door/poddoor.dm b/main-src/Code/Machinery/Door/poddoor.dm new file mode 100644 index 0000000..1c62e23 --- /dev/null +++ b/main-src/Code/Machinery/Door/poddoor.dm @@ -0,0 +1,90 @@ +/* + * Poddoor -- A remotely controlled door. Operable from pod computers and remote door controls. + * + */ + + +obj/machinery/door/poddoor + name = "poddoor" + icon = 'Door1.dmi' + icon_state = "pdoor1" + var + id = 1.0 // ID that must match that of the controlling device + + + // Standard open() and close() procs do not work + + open() + usr << "This is a remote controlled door!" + + close() + usr << "This is a remote controlled door!" + + + + // Attack by item. + // If crowbar (and door unpowered), open the door + + attackby(obj/item/weapon/C as obj, mob/user as mob) + src.add_fingerprint(user) + if (!( istype(C, /obj/item/weapon/crowbar) )) + return + if ((src.density && (stat & NOPOWER) && !( src.operating ))) + spawn( 0 ) + src.operating = 1 + flick("pdoorc0", src) + src.icon_state = "pdoor0" + sleep(15) + src.density = 0 + src.opacity = 0 + var/turf/T = src.loc + if (istype(T, /turf)) + T.updatecell = 1 + T.buildlinks() + src.operating = 0 + return + + // Called to open a poddoor + + proc/openpod() + set src in oview(1) + + if(stat & NOPOWER) return + + if (src.operating || !src.density) + return + src.operating = 1 + use_power(50) + flick("pdoorc0", src) + src.icon_state = "pdoor0" + sleep(15) + src.density = 0 + src.opacity = 0 + var/turf/T = src.loc + if (istype(T, /turf)) + T.updatecell = 1 + T.buildlinks() + src.operating = 0 + + + // Called to close a poddoor + + proc/closepod() + set src in oview(1) + + if(stat & NOPOWER) return + + if (src.operating || src.density) + return + use_power(50) + src.operating = 1 + flick("pdoorc1", src) + src.icon_state = "pdoor1" + src.density = 1 + src.opacity = 1 + var/turf/T = src.loc + if (istype(T, /turf)) + T.updatecell = 0 + T.buildlinks() + sleep(15) + src.operating = 0 diff --git a/main-src/Code/Machinery/Door/window.dm b/main-src/Code/Machinery/Door/window.dm new file mode 100644 index 0000000..03fd050 --- /dev/null +++ b/main-src/Code/Machinery/Door/window.dm @@ -0,0 +1,136 @@ +/* + * Window door -- A non-opaque door covering either the south or east edges of a turf + * + * If the door has an access requirement, the security door icon is substituted + */ + + +obj/machinery/door/window + name = "interior door" + icon = 'windoor.dmi' + visible = 0.0 // Door is not opaque when closed + flags = WINDOW + opacity = 0 + + // Note dir var sets the 4 possible states - "door handle" points in the dir direction, slides in opposite dirn to open + // dir=1 : Door on east edge, slides to south + // dir=2: Door on east edge, slides to north + // dir=4: Door on south edge, slides to west + // dir=8: Door on south edge, slides to east + + + // Create a new windowdoor. If access controls are set, use the alternate icon for security doors + + New() + ..() + var/turf/T = src.loc + if (T) + T.updatecell = 1 + T.buildlinks() + if ( (access && access!="0000") || allowed) + src.icon = 'security.dmi' + + + // Override close() proc since windowdoors still update their turf when closed, unlike other doors. + + close() + ..() // call standard door/close() proc + var/turf/T = src.loc + if (T) + T.updatecell = 1 // turf still runs gas simulation + T.buildlinks() + return + + + // If a mob bumps into the door, cycle the door (open then close) + + Bumped(atom/movable/AM) + if (!( ismob(AM) )) + return + src.cycle(AM,1) + return + + + // Attack by monkey same as human + + attack_paw(mob/user) + return src.attack_hand(user) + + + // Human attack hand - cycle the door + + attack_hand(mob/user) + src.cycle(user,0) + + + // Called to cycle a windowdoor + // If an unsecured door, open for 5 seconds, then close again + // Otherwise, check ID access levels and toggle open/closed state + // arg bumped is true if called from the Bump proc (will not check ID in this case) + + proc/cycle(mob/user, bumped=0) + if (!( ticker )) // doors won't open until round has started + return + if (src.operating) + return + if (access && access=="0000" && !allowed) // unsecure door + if (src.density) + open() // open then close 5 seconds later + sleep(50) + close() + return + + if(bumped) // if called from Bump(), return now - you can't bump open a secure door + return + + var/obj/item/weapon/card/id/card // check if user is human and wearing ID + if (istype(user, /mob/human)) + var/mob/human/H = user + card = H.wear_id + if (!( istype(card, /obj/item/weapon/card/id) )) + return + else + return + if (card.check_access(access, allowed)) // check access levels of worn ID + if (src.density) // and toggle door open/closed depending on current state + open() + else + close() + else + if (src.density) + flick("door_deny", src) + + + // Note attackby item (ID) handled by standard door proc + + + // Called in turf/Enter() to see if windowdoor is passable, when turf being entered contains a windowdoor + // O is the moving object + // target is the turf it wants to move into + + CheckPass(atom/movable/O, target) + if (src.density) // only check if door is closed + var/direct = get_dir(O, target) + if ((direct == NORTH && src.dir & 12)) // moving north, and door is on south edge of target + return 0 // can't pass + else + if ((direct == WEST && src.dir & 3)) // moving west, and door is on east edge of target + return 0 + return 1 + + + // Called in turf/Enter() to see if windowdoor is passable, when turf entering from contains a windowdoor + // O is the moving object + // target is the turf it wants to move into + + CheckExit(atom/movable/O, target) + + if (src.density) // only check if door is closed + var/direct = get_dir(O, target) + if ((direct == SOUTH && src.dir & 12)) // moving south, and door is on south edge + return 0 + else + if ((direct == EAST && src.dir & 3)) // moving east, and door is on east edge + return 0 + return 1 + diff --git a/main-src/Code/Machinery/Power/solar.dm b/main-src/Code/Machinery/Power/solar.dm index 75d4622..fd63858 100644 --- a/main-src/Code/Machinery/Power/solar.dm +++ b/main-src/Code/Machinery/Power/solar.dm @@ -14,12 +14,13 @@ obj/machinery/power/solar anchored = 1 density = 1 directwired = 1 + dir = SOUTH // the current direction of the solar panel var id = 1 // solar_control must have matching id (and be on same powernet) to control this machine obscured = 0 // true if the panel is in shadow (thus does not generate power) sunfrac = 0 // fraction (0.0-1.0) of the maximum exposure of the solar panel to the sun // calculated from the relative angle of the sun and the panel - adir = SOUTH // the current direction of the solar panel + ndir = SOUTH // the new set direction of the panel turn_angle = 0 // the angle to turn through to get to the set angle; -45 or +45 obj/machinery/power/solar_control/control // the controller for this panel @@ -42,13 +43,14 @@ obj/machinery/power/solar // Updates the icon for the solar panel // The object icon is just the base, with the panel itself being an 8-direction overlay + // As the object direction is changed, the overlay direction will echo it proc/updateicon() src.overlays = null if(stat & BROKEN) overlays += image('power.dmi', "solar_panel-b", FLY_LAYER) else - overlays += image('power.dmi', "solar_panel", FLY_LAYER, adir) + overlays += image('power.dmi', "solar_panel", FLY_LAYER) // Calculate the fraction of power produced by the panel @@ -61,7 +63,7 @@ obj/machinery/power/solar sunfrac = 0 return - var/p_angle = dir2angle(adir) - sun.angle + var/p_angle = dir2angle(dir) - sun.angle if(abs(p_angle) > 90) // if facing more than 90deg from sun, zero output sunfrac = 0 @@ -85,11 +87,11 @@ obj/machinery/power/solar control.gen += sgen // notify the controller of how much was generated - if(adir == ndir) // if current angle == set angle, stop turning + if(dir == ndir) // if current angle == set angle, stop turning turn_angle = 0 else // otherwise turn spawn(rand(0,10)) // slight random delay is to stop all panels turning in lockstep - adir = turn(adir, turn_angle) + dir = turn(dir, turn_angle) updateicon() updatefrac() // update the panel icon and the fractional power production for the new angle diff --git a/main-src/Code/Machinery/Power/solar_control.dm b/main-src/Code/Machinery/Power/solar_control.dm index e41c487..e008ae7 100644 --- a/main-src/Code/Machinery/Power/solar_control.dm +++ b/main-src/Code/Machinery/Power/solar_control.dm @@ -34,7 +34,7 @@ obj/machinery/power/solar_control if(powernet) for(var/obj/machinery/power/solar/S in powernet.nodes) if(S.id == id) - cdir = S.adir // find the contorlled solar panels and set the current direction to match + cdir = S.dir // find the contorlled solar panels and set the current direction to match updateicon() // also update the icon overlay @@ -222,7 +222,7 @@ obj/machinery/power/solar_control if(S.id == id) S.control = src - var/delta = dir2angle(S.adir) - dir2angle(cdir) + var/delta = dir2angle(S.dir) - dir2angle(cdir) delta = (delta+360)%360 diff --git a/main-src/Code/Machinery/meter.dm b/main-src/Code/Machinery/meter.dm new file mode 100644 index 0000000..34d961d --- /dev/null +++ b/main-src/Code/Machinery/meter.dm @@ -0,0 +1,88 @@ +/* + * Meter -- a machine that shows the flow rate of gas in a pipe on the same turf + * + * The meter actually reads a moving average of the flow var of the pipeline object associated with the pipe. + * Note that the value can be negative if the flow is going through the pipe "backwards" + * + * TODO: Add an icon overlay showing the actual movement direction of the gas. + */ + +obj/machinery/meter + name = "meter" + icon = 'pipes.dmi' + icon_state = "meterX" + anchored = 1 + var + obj/machinery/pipes/target = null // the pipe object to monitor + average = 0 // the exponential moving average of the flow rate + + + + // Create a new meter. Find the target pipe in the same location as the meter + + New() + ..() + src.target = locate(/obj/machinery/pipes, src.loc) + average = 0 + return + + + // Timed process. + // Read flow rate from the pipeline object of the target pipe + // Calculate exponentially weighted moving average of flow rate + // Update icon state of flow rate bargraph + + process() + + if(!target) + icon_state = "meterX" + return + if(stat & NOPOWER) + icon_state = "meter0" + return + + use_power(5) + + average = 0.5 * average + 0.5 * target.pl.flow + + var/val = min(18, round( 18.99 * ((abs(average) / 2500000)**0.25)) ) + icon_state = "meter[val]" + + + // If the meter is clicked on, report the flow rate and temperature of the gas + + Click() + + if (get_dist(usr, src) <= 3) + if (src.target) + usr << text("\blue Results:\nMass flow []%\nTemperature [] K", round(100*abs(average)/6e6, 0.1), round(target.pl.gas.temperature,0.1)) + else + usr << "\blue Results: Connection Error!" + else + usr << "\blue You are too far away." + return + +// Disabled routines + +/* +/obj/machinery/meter/proc/pressure() + + if(src.target && src.target.gas) + return (average * target.gas.temperature)/100000.0 + else + return 0 +*/ + +/* +/obj/machinery/meter/examine() + set src in oview(1) + + var/t = "A gas flow meter. " + if (src.target) + t += text("Results:\nMass flow []%\nPressure [] kPa", round(100*average/src.target.gas.maximum, 0.1), round(pressure(), 0.1) ) + else + t += "It is not functioning." + + usr << t + +*/ diff --git a/main-src/Code/atmo_control.dm b/main-src/Code/atmo_control.dm index ee6d816..785b2f7 100644 --- a/main-src/Code/atmo_control.dm +++ b/main-src/Code/atmo_control.dm @@ -1,63 +1,4 @@ - -/obj/machinery/meter/New() - - ..() - src.target = locate(/obj/machinery/pipes, src.loc) - average = 0 - return - -/obj/machinery/meter/process() - - if(!target) - icon_state = "meterX" - return - if(stat & NOPOWER) - icon_state = "meter0" - return - - use_power(5) - - average = 0.5 * average + 0.5 * target.pl.flow - - var/val = min(18, round( 18.99 * ((abs(average) / 2500000)**0.25)) ) - icon_state = "meter[val]" - -/* -/obj/machinery/meter/examine() - set src in oview(1) - - var/t = "A gas flow meter. " - if (src.target) - t += text("Results:\nMass flow []%\nPressure [] kPa", round(100*average/src.target.gas.maximum, 0.1), round(pressure(), 0.1) ) - else - t += "It is not functioning." - - usr << t - -*/ - -/obj/machinery/meter/Click() - - if (get_dist(usr, src) <= 3) - if (src.target) - usr << text("\blue Results:\nMass flow []%\nTemperature [] K", round(100*abs(average)/6e6, 0.1), round(target.pl.gas.temperature,0.1)) - else - usr << "\blue Results: Connection Error!" - else - usr << "\blue You are too far away." - return - -/* -/obj/machinery/meter/proc/pressure() - - if(src.target && src.target.gas) - return (average * target.gas.temperature)/100000.0 - else - return 0 -*/ - - /obj/machinery/mass_driver/proc/drive(amount) if(stat & NOPOWER) diff --git a/main-src/Code/computer.dm b/main-src/Code/computer.dm index 987540c..a7e582c 100644 --- a/main-src/Code/computer.dm +++ b/main-src/Code/computer.dm @@ -580,79 +580,6 @@ //Foreach goto(394) return -/obj/machinery/door/poddoor/open() - - usr << "This is a remote controlled door!" - return - -/obj/machinery/door/poddoor/close() - - usr << "This is a remote controlled door!" - return - -/obj/machinery/door/poddoor/attackby(obj/item/weapon/C as obj, mob/user as mob) - - src.add_fingerprint(user) - if (!( istype(C, /obj/item/weapon/crowbar) )) - return - if ((src.density && (stat & NOPOWER) && !( src.operating ))) - spawn( 0 ) - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - sleep(15) - src.density = 0 - src.opacity = 0 - var/turf/T = src.loc - if (istype(T, /turf)) - T.updatecell = 1 - T.buildlinks() - src.operating = 0 - return - return - -/obj/machinery/door/poddoor/proc/openpod() - set src in oview(1) - - if(stat & NOPOWER) return - - if (src.operating || !src.density) - return - src.operating = 1 - use_power(50) - flick("pdoorc0", src) - src.icon_state = "pdoor0" - sleep(15) - src.density = 0 - src.opacity = 0 - var/turf/T = src.loc - if (istype(T, /turf)) - T.updatecell = 1 - T.buildlinks() - src.operating = 0 - return - -/obj/machinery/door/poddoor/proc/closepod() - set src in oview(1) - - if(stat & NOPOWER) return - - if (src.operating || src.density) - return - use_power(50) - src.operating = 1 - flick("pdoorc1", src) - src.icon_state = "pdoor1" - src.density = 1 - src.opacity = 1 - var/turf/T = src.loc - if (istype(T, /turf)) - T.updatecell = 0 - T.buildlinks() - sleep(15) - src.operating = 0 - return - /obj/machinery/pod/meteorhit(var/obj/O as obj) if (O.icon_state == "flaming") diff --git a/main-src/Code/demo.dm b/main-src/Code/demo.dm index a028cae..e5e68fc 100644 --- a/main-src/Code/demo.dm +++ b/main-src/Code/demo.dm @@ -1,507 +1,4 @@ -/obj/machinery/door/meteorhit(obj/M as obj) - - src.open() - return - -/obj/machinery/door/Move() - - ..() - if (src.density) - var/turf/location = src.loc - if (istype(location, /turf)) - location.updatecell = 0 - buildlinks() - return - - -//*****RM -/obj/machinery/door/attack_paw(mob/user as mob) - - return src.attack_hand(user) - -/obj/machinery/door/attack_hand(mob/user as mob) - if(istype(user, /mob/human)) - var/mob/human/H = user - if(H.wear_id) - attackby(H.wear_id, user) - return -//***** - -/obj/machinery/door/attackby(obj/item/I as obj, mob/user as mob) - - if (src.operating) - return - src.add_fingerprint(user) - if ((src.density && istype(I, /obj/item/weapon/card/emag))) - src.operating = 1 - flick("door_spark", src) - sleep(6) - src.operating = null - open() - return 1 - var/obj/item/weapon/card/id/card - if (istype(user, /mob/human)) - var/mob/human/H = user - card = H.wear_id - if (istype(I, /obj/item/weapon/card/id)) - card = I - else - if (!( istype(card, /obj/item/weapon/card/id) )) - return 0 - if (card.check_access(access, allowed)) - if (src.density) - open() - else - close() - else - if (src.density) - flick("door_deny", src) - return - -/obj/machinery/door/window/close() - - ..() - var/turf/T = src.loc - if (T) - T.updatecell = 1 - T.buildlinks() - return - -/obj/machinery/door/window/New() - - ..() - var/turf/T = src.loc - if (T) - T.updatecell = 1 - T.buildlinks() - if ( (access && access!="0000") || allowed) - src.icon = 'security.dmi' - return - - -/obj/machinery/door/window/Bumped(atom/movable/AM as mob|obj) - - if (!( ismob(AM) )) - return - src.cycle(AM,1) - return - -//*****RM -/obj/machinery/door/window/attack_paw(mob/user as mob) - - return src.attack_hand(user) - -/obj/machinery/door/window/attack_hand(mob/user as mob) - src.cycle(user,0) - return - -/obj/machinery/door/window/proc/cycle(mob/user, bumped=0) - if (!( ticker )) - return - if (src.operating) - return - if (access && access=="0000" && !allowed) - if (src.density) - open() - sleep(50) - close() - return - - if(bumped) - return - - var/obj/item/weapon/card/id/card - if (istype(user, /mob/human)) - var/mob/human/H = user - card = H.wear_id - if (!( istype(card, /obj/item/weapon/card/id) )) - return - else - return - if (card.check_access(access, allowed)) - if (src.density) - open() - else - close() - else - if (src.density) - flick("door_deny", src) - return -//***** - -/obj/machinery/door/window/CheckPass(atom/movable/O as mob|obj, target as turf) - - if (src.density) - var/direct = get_dir(O, target) - if ((direct == NORTH && src.dir & 12)) - return 0 - else - if ((direct == WEST && src.dir & 3)) - return 0 - return 1 - return - -/obj/machinery/door/window/CheckExit(atom/movable/O as mob|obj, target as turf) - - if (src.density) - var/direct = get_dir(O, target) - if ((direct == SOUTH && src.dir & 12)) - return 0 - else - if ((direct == EAST && src.dir & 3)) - return 0 - return 1 - return - -/obj/machinery/door/false_wall/New() - ..() - src.verbs -= /atom/movable/verb/pull - return - -/obj/machinery/door/false_wall/examine() - set src in oview(1) - - usr << "It looks like a regular wall" - return - -/obj/machinery/door/false_wall/attack_paw(mob/user as mob) - - if ((ticker && ticker.mode == "monkey")) - return src.attack_hand(user) - return - -/obj/machinery/door/false_wall/attack_hand(mob/user as mob) - - src.add_fingerprint(user) - if (src.density) - if (prob(25)) - open() - else - user << "\blue You push the wall but nothing happens!" - else - close() - return - -/obj/machinery/door/false_wall/attackby(obj/item/weapon/screwdriver/S as obj, mob/user as mob) - - src.add_fingerprint(user) - if (istype(S, /obj/item/weapon/screwdriver)) - new /obj/item/weapon/sheet/metal( src.loc ) - new /obj/d_girders( src.loc ) - //SN src = null - del(src) - return - else - ..() - return - -/obj/machinery/door/airlock/proc/update() - - if (((!( src.wires & 2 ) || !( src.wires & 8 ) || !( src.wires & 32 ) || !( src.wires & 64 ) || !( src.wires & 128 ) || !( src.wires & 256 )) && src.powered)) - src.locked = 1 - if ((!( src.wires & 1 ) && !( src.wires & 4 ) && !( src.wires & 16 ))) - src.powered = 0 - else - src.powered = 1 - var/d = src.density - if (src.blocked) - d = "l" - src.icon_state = text("[]door[]", (src.p_open ? "o_" : null), d) - return - -/obj/machinery/door/airlock/attack_paw(mob/user as mob) - - return src.attack_hand(user) - return - -/obj/machinery/door/airlock/attack_hand(mob/user as mob) - - if (src.p_open) - user.machine = src - var/t1 = text("Access Panel
\nOrange Wire: []
\nDark Red Wire: []
\nWhite Wire: []
\nYellow Wire: []
\nRed Wire: []
\nBlue Wire: []
\nGreen Wire: []
\nGrey Wire: []
\nBlack Wire: []
\n
\n[]
\n[]", (src.wires & 256 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.wires & 128 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.wires & 64 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.wires & 32 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.wires & 16 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.wires & 8 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.wires & 4 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.wires & 2 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.wires & 1 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.locked ? "The door bolts have fallen!" : "The door bolts look up."), (src.powered ? "The test light is on." : "The test light is off!")) - user << browse(t1, "window=airlock") - else - ..(user) - return - -/obj/machinery/door/airlock/Topic(href, href_list) - ..() - if (usr.stat || usr.restrained() ) - return - if ((get_dist(src, usr) <= 1 && istype(src.loc, /turf))) - usr.machine = src - if (href_list["wires"]) - var/t1 = text2num(href_list["wires"]) - if (!( istype(usr.equipped(), /obj/item/weapon/wirecutters) )) - return - if (!( src.p_open )) - return - if (t1 & 1) - if (src.wires & 1) - src.wires &= ~1 - else - src.wires |= 1 - else if (t1 & 2) - if (src.wires & 2) - src.wires &= ~2 - else - src.wires |= 2 - else if (t1 & 4) - if (src.wires & 4) - src.wires &= ~4 - else - src.wires |= 4 - else if (t1 & 8) - if (src.wires & 8) - src.wires &= ~8 - else - src.wires |= 8 - else if (t1 & 16) - if (src.wires & 16) - src.wires &= ~16 - else - src.wires |= 16 - else if (t1 & 32) - if (src.wires & 32) - src.wires &= ~32 - else - src.wires |= 32 - else if (t1 & 64) - if (src.wires & 64) - src.wires &= ~64 - else - src.wires |= 64 - else if (t1 & 128) - if (src.wires & 128) - src.wires &= ~128 - else - src.wires |= 128 - else if (t1 & 256) - if (src.wires & 256) - src.wires &= ~256 - else - src.wires |= 256 - src.update() - add_fingerprint(usr) - for(var/mob/M in viewers(1, src)) - if ((M.client && M.machine == src)) - src.attack_hand(M) - //Foreach goto(477) - return - -/obj/machinery/door/airlock/attackby(C as obj, mob/user as mob) - - src.add_fingerprint(user) - if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) - var/obj/item/weapon/weldingtool/W = C - if(W.welding) - if (W.weldfuel > 2) - W.weldfuel -= 2 - else - user << "Need more welding fuel!" - return - if (!( src.blocked )) - src.blocked = 1 - else - src.blocked = null - src.update() - return - else - if (istype(C, /obj/item/weapon/wrench)) - if (src.p_open) - if (src.powered) - src.locked = null - else - user << alert("You need power assist!", null, null, null, null, null) - src.update() - else - if (istype(C, /obj/item/weapon/screwdriver)) - src.p_open = !( src.p_open ) - update() - else - if (istype(C, /obj/item/weapon/crowbar)) - if ((src.density && !( src.blocked ) && !( src.operating ) && !( src.powered ) && !( src.locked ))) - spawn( 0 ) - src.operating = 1 - flick(text("[]doorc0", (src.p_open ? "o_" : null)), src) - src.icon_state = text("[]door0", (src.p_open ? "o_" : null)) - sleep(15) - src.density = 0 - src.opacity = 0 - var/turf/T = src.loc - if (istype(T, /turf)) - T.updatecell = 1 - T.buildlinks() - src.operating = 0 - return - else - ..() - return - -/obj/machinery/door/airlock/open() - - if ((src.blocked || src.locked || !( src.powered )) || stat & NOPOWER) - return - use_power(50) - ..() - return - -/obj/machinery/door/airlock/close() - - if (!( src.powered || stat & NOPOWER)) - return - use_power(50) - ..() - var/turf/T = src.loc - if (T) - T.firelevel = 0 - return - -/obj/machinery/door/firedoor/open() - - usr << "This is a remote firedoor!" - return - -/obj/machinery/door/firedoor/close() - - usr << "This is a remote firedoor!" - return - -/obj/machinery/door/blob_act() - if(prob(20)) - del(src) - -/obj/machinery/door/firedoor/power_change() - if( powered(ENVIRON) ) - stat &= ~NOPOWER - else - stat |= NOPOWER - -/obj/machinery/door/firedoor/attackby(obj/item/weapon/C as obj, mob/user as mob) - - src.add_fingerprint(user) - if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) - var/obj/item/weapon/weldingtool/W = C - if(W.welding) - if (W.weldfuel > 2) - W.weldfuel -= 2 - if (!( src.blocked )) - src.blocked = 1 - src.icon_state = "doorl" - else - src.blocked = 0 - src.icon_state = "door1" - return - else - if (!( istype(C, /obj/item/weapon/crowbar) )) - return - if ((src.density && !( src.blocked ) && !( src.operating ))) - spawn( 0 ) - src.operating = 1 - flick("doorc0", src) - src.icon_state = "door0" - sleep(15) - src.density = 0 - src.opacity = 0 - var/turf/T = src.loc - if (istype(T, /turf)) - T.updatecell = 1 - T.buildlinks() - src.operating = 0 - return - return - -/obj/machinery/door/firedoor/proc/openfire() - set src in oview(1) - - if (stat & NOPOWER) return - - if ((src.operating || src.blocked)) - return - use_power(50, ENVIRON) - src.operating = 1 - flick("doorc0", src) - src.icon_state = "door0" - sleep(15) - src.density = 0 - src.opacity = 0 - var/turf/T = src.loc - if (istype(T, /turf)) - T.updatecell = 1 - T.buildlinks() - src.operating = 0 - return - -/obj/machinery/door/firedoor/proc/closefire() - set src in oview(1) - - if (stat & NOPOWER) return - - if (src.operating) - return - use_power(50, ENVIRON) - src.operating = 1 - flick("doorc1", src) - src.icon_state = "door1" - src.density = 1 - src.opacity = 1 - var/turf/T = src.loc - if (istype(T, /turf)) - T.updatecell = 0 - T.buildlinks() - T.firelevel = 0 - sleep(15) - src.operating = 0 - return - -/obj/machinery/door/New() - - ..() - var/turf/T = src.loc - if (istype(T, /turf)) - if (src.density) - T.updatecell = 0 - T.buildlinks() - return - -/obj/machinery/door/proc/open() - - if (src.operating) - return - src.operating = 1 - flick(text("[]doorc0", (src.p_open ? "o_" : null)), src) - src.icon_state = text("[]door0", (src.p_open ? "o_" : null)) - sleep(15) - src.density = 0 - src.opacity = 0 - var/turf/T = src.loc - if (istype(T, /turf)) - T.updatecell = 1 - T.buildlinks() - src.operating = 0 - return - -/obj/machinery/door/proc/close() - - if (src.operating) - return - src.operating = 1 - flick(text("[]doorc1", (src.p_open ? "o_" : null)), src) - src.icon_state = text("[]door1", (src.p_open ? "o_" : null)) - src.density = 1 - if (src.visible) - src.opacity = 1 - var/turf/T = src.loc - if (istype(T, /turf)) - T.updatecell = 0 - T.buildlinks() - sleep(15) - src.operating = 0 - return - - - diff --git a/main-src/Code/globals.dm b/main-src/Code/globals.dm index 1b6839e..55a9c3c 100644 --- a/main-src/Code/globals.dm +++ b/main-src/Code/globals.dm @@ -1,4 +1,23 @@ -/* Most recent changes (Since H9.5) +/* Most recent changes (Since H9.6) + + Contining reorg of obj/machinery code + Changed how solar panel directions are displayed, to fix the rotation display bug. + + + + + + + + + + + + + + + + (Since H9.5) Started pipelaying system, /obj/item/weapon/pipe. diff --git a/main-src/Code/mob.dm b/main-src/Code/mob.dm index cfc6bd2..d99ca31 100644 --- a/main-src/Code/mob.dm +++ b/main-src/Code/mob.dm @@ -3596,6 +3596,10 @@ //stat(null, "([x], [y], [z])") +#ifdef SDEBUG + stat("CPU",world.cpu) +#endif + stat(null, text("Intent: []", src.a_intent)) stat(null, text("Move Mode: []", src.m_intent)) diff --git a/main-src/Icons/power.dmi b/main-src/Icons/power.dmi index a49e0a7..563fbd1 100644 Binary files a/main-src/Icons/power.dmi and b/main-src/Icons/power.dmi differ diff --git a/main-src/spacestation13.dme b/main-src/spacestation13.dme index d5e7437..c64e112 100644 --- a/main-src/spacestation13.dme +++ b/main-src/spacestation13.dme @@ -5,7 +5,7 @@ // BEGIN_INTERNALS /* FILE: Code\!atoms.dm -DIR: Code Code\Machinery Code\Machinery\Atmoalter Code\Machinery\Power +DIR: Code Code\Machinery Code\Machinery\Atmoalter Code\Machinery\Door Code\Machinery\Power MAP_ICON_TYPE: 0 AUTO_FILE_DIR: ON */ @@ -15,6 +15,7 @@ AUTO_FILE_DIR: ON #define FILE_DIR "Code" #define FILE_DIR "Code/Machinery" #define FILE_DIR "Code/Machinery/Atmoalter" +#define FILE_DIR "Code/Machinery/Door" #define FILE_DIR "Code/Machinery/Power" #define FILE_DIR "Icons" #define FILE_DIR "Interface" @@ -82,6 +83,7 @@ AUTO_FILE_DIR: ON #include "Code\Machinery\junction.dm" #include "Code\Machinery\light_switch.dm" #include "Code\Machinery\manifold.dm" +#include "Code\Machinery\meter.dm" #include "Code\Machinery\pipeline.dm" #include "Code\Machinery\pipes.dm" #include "Code\Machinery\recharger.dm" @@ -92,6 +94,12 @@ AUTO_FILE_DIR: ON #include "Code\Machinery\Atmoalter\canister.dm" #include "Code\Machinery\Atmoalter\heater.dm" #include "Code\Machinery\Atmoalter\siphs.dm" +#include "Code\Machinery\Door\_door.dm" +#include "Code\Machinery\Door\airlock.dm" +#include "Code\Machinery\Door\false_wall.dm" +#include "Code\Machinery\Door\firedoor.dm" +#include "Code\Machinery\Door\poddoor.dm" +#include "Code\Machinery\Door\window.dm" #include "Code\Machinery\Power\_power.dm" #include "Code\Machinery\Power\apc.dm" #include "Code\Machinery\Power\generator.dm" diff --git a/main-src/ss13h.dmp b/main-src/ss13h.dmp index a9db3d1..7955d70 100644 --- a/main-src/ss13h.dmp +++ b/main-src/ss13h.dmp @@ -1,7 +1,7 @@ "aa" = (/turf/space,/area) "ab" = (/obj/grille,/turf/station/floor,/area) "ac" = (/obj/item/weapon/tank/oxygentank,/turf/space,/area) -"ad" = (/obj/machinery/power/solar{id = 2; adir = 1},/turf/station/floor,/area) +"ad" = (/obj/machinery/power/solar{id = 2},/turf/station/floor,/area) "ae" = (/obj/cable{icon_state = "1-2"; d1 = 1; d2 = 2},/turf/station/floor{icon_state = "Floor1"; intact = 0},/area) "af" = (/obj/cable{icon_state = "1-4"; d1 = 1; d2 = 4},/turf/station/floor{icon_state = "Floor1"; intact = 0},/area) "ag" = (/obj/cable,/obj/cable{icon_state = "0-8"; d2 = 8},/obj/cable{icon_state = "0-4"; d2 = 4},/turf/station/floor{icon_state = "Floor1"; intact = 0},/area)