diff --git a/code/TriDimension/Movement.dm b/code/TriDimension/Movement.dm
deleted file mode 100644
index 3637184d31..0000000000
--- a/code/TriDimension/Movement.dm
+++ /dev/null
@@ -1,52 +0,0 @@
-/obj/item/weapon/tank/jetpack/verb/moveup()
- set name = "Move Upwards"
- set category = "Object"
- if(allow_thrust(0.01, usr))
- var/turf/controllerlocation = locate(1, 1, usr.z)
- var/legal = 0
- for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
- legal = controller.up
- if (controller.up)
- var/turf/T = locate(usr.x, usr.y, controller.up_target)
- if(T && (istype(T, /turf/space) || istype(T, /turf/simulated/floor/open)))
- var/blocked = 0
- for(var/atom/A in T.contents)
- if(A.density)
- blocked = 1
- usr << "You bump into \the [A]."
- break
- if(!blocked)
- usr.Move(T)
- usr << "You move upwards."
- else
- usr << "There is something in your way."
- if (legal == 0)
- usr << "There is nothing of interest in this direction."
- return 1
-
-/obj/item/weapon/tank/jetpack/verb/movedown()
- set name = "Move Downwards"
- set category = "Object"
- if(allow_thrust(0.01, usr))
- var/turf/controllerlocation = locate(1, 1, usr.z)
- var/legal = 0
- for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
- legal = controller.down
- if (controller.down == 1)
- var/turf/T = locate(usr.x, usr.y, controller.down_target)
- var/turf/S = locate(usr.x, usr.y, usr.z)
- if(T && (istype(S, /turf/space) || istype(S, /turf/simulated/floor/open)))
- var/blocked = 0
- for(var/atom/A in T.contents)
- if(A.density)
- blocked = 1
- usr << "You bump into \the [A]."
- break
- if(!blocked)
- usr.Move(T)
- usr << "You move downwards."
- else
- usr << "You cant move through the floor."
- if (legal == 0)
- usr << "There is nothing of interest in this direction."
- return 1
diff --git a/code/TriDimension/Structures.dm b/code/TriDimension/Structures.dm
deleted file mode 100644
index 99151936f5..0000000000
--- a/code/TriDimension/Structures.dm
+++ /dev/null
@@ -1,274 +0,0 @@
-///////////////////////////////////////
-//Contents: Ladders, Hatches, Stairs.//
-///////////////////////////////////////
-
-/obj/multiz
- icon = 'icons/obj/structures.dmi'
- density = 0
- opacity = 0
- anchored = 1
-
- CanPass(obj/mover, turf/source, height, airflow)
- return airflow || !density
-
-/obj/multiz/ladder
- icon_state = "ladderdown"
- name = "ladder"
- desc = "A ladder. You climb up and down it."
-
- var/d_state = 1
- var/obj/multiz/target
-
- New()
- . = ..()
-
- proc/connect()
- if(icon_state == "ladderdown") // the upper will connect to the lower
- d_state = 1
- var/turf/controllerlocation = locate(1, 1, z)
- for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
- if(controller.down)
- var/turf/below = locate(src.x, src.y, controller.down_target)
- for(var/obj/multiz/ladder/L in below)
- if(L.icon_state == "ladderup")
- target = L
- L.target = src
- d_state = 0
- break
- return
-
-/* ex_act(severity)
- switch(severity)
- if(1.0)
- if(icon_state == "ladderup" && prob(10))
- qdel(src)
- if(2.0)
- if(prob(50))
- qdel(src)
- if(3.0)
- qdel(src)
- return*/
-
- Destroy()
- spawn(1)
- if(target && icon_state == "ladderdown")
- qdel(target)
- return ..()
-
- attackby(obj/item/C as obj, mob/user as mob)
- (..)
-
-// construction commented out for balance concerns
-/* if (!target && istype(C, /obj/item/stack/rods))
- var/turf/controllerlocation = locate(1, 1, z)
- var/found = 0
- var/obj/item/stack/rods/S = C
- if(S.amount < 2)
- user << "You dont have enough rods to finish the ladder."
- return
- for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
- if(controller.down)
- found = 1
- var/turf/below = locate(src.x, src.y, controller.down_target)
- var/blocked = 0
- for(var/atom/A in below.contents)
- if(A.density)
- blocked = 1
- break
- if(!blocked && !istype(below, /turf/simulated/wall))
- var/obj/multiz/ladder/X = new /obj/multiz/ladder(below)
- S.amount = S.amount - 2
- if(S.amount == 0) qdel(S)
- X.icon_state = "ladderup"
- connect()
- user << "You finish the ladder."
- else
- user << "The area below is blocked."
- if(!found)
- user << "You cant build a ladder down there."
- return
-
- else if (icon_state == "ladderdown" && d_state == 0 && istype(C, /obj/item/weapon/wrench))
- user << "You start loosening the anchoring bolts which secure the ladder to the frame."
- playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
-
- sleep(30)
- if(!user || !C) return
-
- src.d_state = 1
- if(target)
- var/obj/item/stack/rods/R = PoolOrNew(/obj/item/stack/rods, target.loc)
- R.amount = 2
- qdel(Target)
-
- user << "You remove the bolts anchoring the ladder."
- return
-
- else if (icon_state == "ladderdown" && d_state == 1 && istype(C, /obj/item/weapon/weldingtool) )
- var/obj/item/weapon/weldingtool/WT = C
- if( WT.remove_fuel(0,user) )
-
- user << "You begin to remove the ladder."
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
-
- sleep(60)
- if(!user || !WT || !WT.isOn()) return
-
- var/obj/item/stack/material/steel/S = new /obj/item/stack/material/steel( src )
- S.amount = 2
- user << "You remove the ladder and close the hole."
- qdel(src)
- else
- user << "You need more welding fuel to complete this task."
- return
-
- else
- src.attack_hand(user)
- return*/
- src.attack_hand(user)
- return
-
- attack_hand(var/mob/M)
- if(!target || !istype(target.loc, /turf))
- M << "The ladder is incomplete and can't be climbed."
- else
- var/turf/T = target.loc
- var/blocked = 0
- for(var/atom/A in T.contents)
- if(A.density)
- blocked = 1
- break
- if(blocked || istype(T, /turf/simulated/wall))
- M << "Something is blocking the ladder."
- else
- M.visible_message("\The [M] climbs [src.icon_state == "ladderup" ? "up" : "down"] \the [src]!", "You climb [src.icon_state == "ladderup" ? "up" : "down"] \the [src]!", "You hear some grunting, and clanging of a metal ladder being used.")
- M.Move(target.loc)
-
-/* hatch
- icon_state = "hatchdown"
- name = "hatch"
- desc = "A hatch. You climb down it, and it will automatically seal against pressure loss behind you."
- top_icon_state = "hatchdown"
- var/top_icon_state_open = "hatchdown-open"
- var/top_icon_state_close = "hatchdown-close"
-
- bottom_icon_state = "ladderup"
-
- var/image/green_overlay
- var/image/red_overlay
-
- var/active = 0
-
- New()
- . = ..()
- red_overlay = image(icon, "red-ladderlight")
- green_overlay = image(icon, "green-ladderlight")
-
- attack_hand(var/mob/M)
-
- if(!target || !istype(target.loc, /turf))
- qdel(src)
-
- if(active)
- M << "That [src] is being used."
- return // It is a tiny airlock, only one at a time.
-
- active = 1
- var/obj/multiz/ladder/hatch/top_hatch = target
- var/obj/multiz/ladder/hatch/bottom_hatch = src
- if(icon_state == top_icon_state)
- top_hatch = src
- bottom_hatch = target
-
- flick(top_icon_state_open, top_hatch)
- bottom_hatch.overlays += green_overlay
-
- spawn(7)
- if(!target || !istype(target.loc, /turf))
- qdel(src)
- if(M.z == z && get_dist(src,M) <= 1)
- var/list/adjacent_to_me = global_adjacent_z_levels["[z]"]
- M.visible_message("\The [M] scurries [target.z == adjacent_to_me["up"] ? "up" : "down"] \the [src]!", "You scramble [target.z == adjacent_to_me["up"] ? "up" : "down"] \the [src]!", "You hear some grunting, and a hatch sealing.")
- M.Move(target.loc)
- flick(top_icon_state_close,top_hatch)
- bottom_hatch.overlays -= green_overlay
- bottom_hatch.overlays += red_overlay
-
- spawn(7)
- top_hatch.icon_state = top_icon_state
- bottom_hatch.overlays -= red_overlay
- active = 0*/
-
-/obj/multiz/stairs
- name = "Stairs"
- desc = "Stairs. You walk up and down them."
- icon_state = "rampbottom"
- var/obj/multiz/stairs/connected
- var/turf/target
- var/turf/target2
- var/suggest_dir // try this dir first when finding stairs; this is the direction to walk *down* the stairs
-
- New()
- ..()
- var/turf/cl= locate(1, 1, src.z)
- for(var/obj/effect/landmark/zcontroller/c in cl)
- if(c.up)
- var/turf/O = locate(src.x, src.y, c.up_target)
- if(istype(O, /turf/space))
- O.ChangeTurf(/turf/simulated/floor/open)
-
- spawn(1)
- var/turf/T
- if(suggest_dir)
- T = get_step(src.loc,suggest_dir)
- find_stair_connection(T, suggest_dir, 1)
- if(!target)
- for(var/dir in cardinal)
- T = get_step(src.loc,dir)
- find_stair_connection(T, dir)
- if(target)
- break
-
- Bumped(var/atom/movable/M)
- if(connected && target && istype(src, /obj/multiz/stairs) && locate(/obj/multiz/stairs) in M.loc)
- var/obj/multiz/stairs/Con = locate(/obj/multiz/stairs) in M.loc
- if(Con == src.connected) //make sure the atom enters from the approriate lower stairs tile
- M.Move(target)
- return
-
- proc/find_stair_connection(var/turf/T, var/dir, var/suggested=0)
- for(var/obj/multiz/stairs/S in T)
- if(S && S.icon_state == "rampbottom" && !S.connected)
- if(!S.suggest_dir || S.suggest_dir == dir) // it doesn't have a suggested direction, or it's the same direction as we're trying, so we connect to it
- initialise_stair_connection(src, S, dir)
- else if(!suggested) // we're trying directions, so it could be a reverse stair (i.e. we're the bottom stair rather than the top)
- var/inv_dir = 0
- switch(dir)
- if(1)
- inv_dir = 2
- if(2)
- inv_dir = 1
- if(4)
- inv_dir = 8
- if(8)
- inv_dir = 4
- if(S.suggest_dir == inv_dir)
- initialise_stair_connection(S, src, inv_dir)
-
- proc/initialise_stair_connection(var/obj/multiz/stairs/top, var/obj/multiz/stairs/bottom, var/dir)
- top.set_dir(dir)
- bottom.set_dir(dir)
- top.connected = bottom
- bottom.connected = top
- top.icon_state = "ramptop"
- top.density = 1
- var/turf/controllerlocation = locate(1, 1, top.z)
- for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
- if(controller.up)
- var/turf/above = locate(top.x, top.y, controller.up_target)
- if(istype(above,/turf/space) || istype(above,/turf/simulated/floor/open))
- top.target = above
- var/turf/above2 = locate(bottom.x, bottom.y, controller.up_target)
- if(istype(above2, /turf/space) || istype(above,/turf/simulated/floor/open))
- top.target2 = above2
- return
diff --git a/code/TriDimension/Structures_presets.dm b/code/TriDimension/Structures_presets.dm
deleted file mode 100644
index 7a28efe211..0000000000
--- a/code/TriDimension/Structures_presets.dm
+++ /dev/null
@@ -1,11 +0,0 @@
-/obj/multiz/stairs/north_up
- suggest_dir = SOUTH
-
-/obj/multiz/stairs/south_up
- suggest_dir = NORTH
-
-/obj/multiz/stairs/east_up
- suggest_dir = WEST
-
-/obj/multiz/stairs/west_up
- suggest_dir = EAST
\ No newline at end of file
diff --git a/code/TriDimension/Turfs.dm b/code/TriDimension/Turfs.dm
deleted file mode 100644
index c601e36b99..0000000000
--- a/code/TriDimension/Turfs.dm
+++ /dev/null
@@ -1,128 +0,0 @@
-/turf/simulated/floor/open
- name = "open space"
- density = 0
- icon_state = "black"
- pathweight = 100000 //Seriously, don't try and path over this one numbnuts
- var/icon/darkoverlays = null
- var/turf/floorbelow
- var/list/overlay_references
-
- New()
- ..()
- getbelow()
- return
-
- Enter(var/atom/movable/AM)
- if (..()) //TODO make this check if gravity is active (future use) - Sukasa
- spawn(1)
- // only fall down in defined areas (read: areas with artificial gravitiy)
- if(!floorbelow) //make sure that there is actually something below
- if(!getbelow())
- return
- if(AM)
- var/area/areacheck = get_area(src)
- var/blocked = 0
- var/soft = 0
- for(var/atom/A in floorbelow.contents)
- if(A.density)
- if(istype(A, /obj/structure/window))
- var/obj/structure/window/W = A
- blocked = W.is_fulltile()
- if(blocked)
- break
- else
- blocked = 1
- break
- if(istype(A, /obj/machinery/atmospherics/pipe/zpipe/up) && istype(AM,/obj/item/pipe))
- blocked = 1
- break
- if(istype(A, /obj/structure/disposalpipe/up) && istype(AM,/obj/item/pipe))
- blocked = 1
- break
- if(istype(A, /obj/multiz/stairs))
- soft = 1
- //dont break here, since we still need to be sure that it isnt blocked
-
- if (soft || (!blocked && !(areacheck.name == "Space")))
- AM.Move(floorbelow)
- if (!soft && istype(AM, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = AM
- var/damage = 5
- H.apply_damage(min(rand(-damage,damage),0), BRUTE, "head")
- H.apply_damage(min(rand(-damage,damage),0), BRUTE, "chest")
- H.apply_damage(min(rand(-damage,damage),0), BRUTE, "l_leg")
- H.apply_damage(min(rand(-damage,damage),0), BRUTE, "r_leg")
- H.apply_damage(min(rand(-damage,damage),0), BRUTE, "l_arm")
- H.apply_damage(min(rand(-damage,damage),0), BRUTE, "r_arm")
- H:weakened = max(H:weakened,2)
- H:updatehealth()
- return ..()
-
-/turf/proc/hasbelow()
- var/turf/controllerlocation = locate(1, 1, z)
- for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
- if(controller.down)
- return 1
- return 0
-
-/turf/simulated/floor/open/proc/getbelow()
- var/turf/controllerlocation = locate(1, 1, z)
- for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
- // check if there is something to draw below
- if(!controller.down)
- src.ChangeTurf(get_base_turf(src.z))
- return 0
- else
- floorbelow = locate(src.x, src.y, controller.down_target)
- return 1
- return 1
-
-// override to make sure nothing is hidden
-/turf/simulated/floor/open/levelupdate()
- for(var/obj/O in src)
- O.hide(0)
-
-//overwrite the attackby of space to transform it to openspace if necessary
-/turf/space/attackby(obj/item/C as obj, mob/user as mob)
- if (istype(C, /obj/item/stack/cable_coil) && src.hasbelow())
- var/turf/simulated/floor/open/W = src.ChangeTurf(/turf/simulated/floor/open)
- W.attackby(C, user)
- return
- ..()
-
-/turf/simulated/floor/open/ex_act(severity)
- // cant destroy empty space with an ordinary bomb
- return
-
-/turf/simulated/floor/open/attackby(obj/item/C as obj, mob/user as mob)
- (..)
- if (istype(C, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/cable = C
- cable.turf_place(src, user)
- return
-
- if (istype(C, /obj/item/stack/rods))
- var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
- if(L)
- return
- var/obj/item/stack/rods/R = C
- if (R.use(1))
- user << "Constructing support lattice..."
- playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1)
- ReplaceWithLattice()
- return
-
- if (istype(C, /obj/item/stack/tile/floor))
- var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
- if(L)
- var/obj/item/stack/tile/floor/S = C
- if (S.get_amount() < 1)
- return
- qdel(L)
- playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1)
- S.use(1)
- ChangeTurf(/turf/simulated/floor/airless)
- return
- else
- user << "The plating is going to need some support."
- return
diff --git a/code/TriDimension/controller.dm b/code/TriDimension/controller.dm
deleted file mode 100644
index c8b81d0d49..0000000000
--- a/code/TriDimension/controller.dm
+++ /dev/null
@@ -1,189 +0,0 @@
-/obj/effect/landmark/zcontroller
- name = "Z-Level Controller"
- var/initialized = 0 // when set to 1, turfs will report to the controller
- var/up = 0 // 1 allows up movement
- var/up_target = 0 // the Z-level that is above the current one
- var/down = 0 // 1 allows down movement
- var/down_target = 0 // the Z-level that is below the current one
-
- var/list/slow = list()
- var/list/normal = list()
- var/list/fast = list()
-
- var/slow_time
- var/normal_time
- var/fast_time
-
-/obj/effect/landmark/zcontroller/New()
- ..()
- for (var/turf/T in world)
- if (T.z == z)
- fast += T
- slow_time = world.time + 3000
- normal_time = world.time + 600
- fast_time = world.time + 10
-
- processing_objects.Add(src)
-
- initialized = 1
- return 1
-
-/obj/effect/landmark/zcontroller/Destroy()
- processing_objects.Remove(src)
- return ..()
-
-/obj/effect/landmark/zcontroller/process()
- if (world.time > fast_time)
- calc(fast)
- fast_time = world.time + 10
-
- if (world.time > normal_time)
- calc(normal)
- normal_time = world.time + 600
-
-/* if (world.time > slow_time)
- calc(slow)
- slow_time = world.time + 3000 */
- return
-
-/obj/effect/landmark/zcontroller/proc/add(var/list/L, var/I, var/transfer)
- while (L.len)
- var/turf/T = pick(L)
-
- L -= T
- slow -= T
- normal -= T
- fast -= T
-
- if(!T || !istype(T, /turf))
- continue
-
- switch (I)
- if(1) slow += T
- if(2) normal += T
- if(3) fast += T
-
- if(transfer > 0)
- if(up)
- var/turf/controller_up = locate(1, 1, up_target)
- for(var/obj/effect/landmark/zcontroller/c_up in controller_up)
- var/list/temp = list()
- temp += locate(T.x, T.y, up_target)
- c_up.add(temp, I, transfer-1)
-
- if(down)
- var/turf/controller_down = locate(1, 1, down_target)
- for(var/obj/effect/landmark/zcontroller/c_down in controller_down)
- var/list/temp = list()
- temp += locate(T.x, T.y, down_target)
- c_down.add(temp, I, transfer-1)
- return
-
-/turf
- var/list/z_overlays = list()
-
-/turf/New()
- ..()
-
- var/turf/controller = locate(1, 1, z)
- for(var/obj/effect/landmark/zcontroller/c in controller)
- if(c.initialized)
- var/list/turf = list()
- turf += src
- c.add(turf,3,1)
-
-atom/movable/Move() //Hackish
- . = ..()
-
- var/turf/controllerlocation = locate(1, 1, src.z)
- for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
- if(controller.up || controller.down)
- var/list/temp = list()
- temp += locate(src.x, src.y, src.z)
- controller.add(temp,3,1)
-
-/obj/effect/landmark/zcontroller/proc/calc(var/list/L)
- var/list/slowholder = list()
- var/list/normalholder = list()
- var/list/fastholder = list()
- var/new_list
-
- while(L.len)
- var/turf/T = pick(L)
- new_list = 0
-
- if(!T || !istype(T, /turf))
- L -= T
- continue
-
- T.overlays -= T.z_overlays
- T.z_overlays -= T.z_overlays
-
- if(down && (istype(T, /turf/space) || istype(T, /turf/simulated/floor/open)))
- var/turf/below = locate(T.x, T.y, down_target)
- if(below)
- if(!(istype(below, /turf/space) || istype(below, /turf/simulated/floor/open)))
- var/image/t_img = list()
- new_list = 1
-
- var/image/temp = image(below, dir=below.dir, layer = TURF_LAYER + 0.04)
-
- temp.color = rgb(127,127,127)
- temp.overlays += below.overlays
- t_img += temp
- T.overlays += t_img
- T.z_overlays += t_img
-
- // get objects
- var/image/o_img = list()
- for(var/obj/o in below)
- // ingore objects that have any form of invisibility
- if(o.invisibility) continue
- new_list = 2
- var/image/temp2 = image(o, dir=o.dir, layer = TURF_LAYER+0.05*o.layer)
- temp2.color = rgb(127,127,127)
- temp2.overlays += o.overlays
- o_img += temp2
- // you need to add a list to .overlays or it will not display any because space
- T.overlays += o_img
- T.z_overlays += o_img
-
- // get mobs
- var/image/m_img = list()
- for(var/mob/m in below)
- // ingore mobs that have any form of invisibility
- if(m.invisibility) continue
- // only add this tile to fastprocessing if there is a living mob, not a dead one
- if(istype(m, /mob/living)) new_list = 3
- var/image/temp2 = image(m, dir=m.dir, layer = TURF_LAYER+0.05*m.layer)
- temp2.color = rgb(127,127,127)
- temp2.overlays += m.overlays
- m_img += temp2
- // you need to add a list to .overlays or it will not display any because space
- T.overlays += m_img
- T.z_overlays += m_img
-
- T.overlays -= below.z_overlays
- T.z_overlays -= below.z_overlays
-
- L -= T
-
- if(new_list == 1)
- slowholder += T
- if(new_list == 2)
- normalholder += T
- if(new_list == 3)
- fastholder += T
- for(var/d in cardinal)
- var/turf/mT = get_step(T,d)
- if(!(mT in fastholder))
- fastholder += mT
- for(var/f in cardinal)
- var/turf/nT = get_step(mT,f)
- if(!(nT in fastholder))
- fastholder += nT
-
- add(slowholder,1, 0)
- add(normalholder, 2, 0)
- add(fastholder, 3, 0)
- return
diff --git a/code/TriDimension/controller_presets.dm b/code/TriDimension/controller_presets.dm
deleted file mode 100644
index f775b94e93..0000000000
--- a/code/TriDimension/controller_presets.dm
+++ /dev/null
@@ -1,37 +0,0 @@
-/obj/effect/landmark/zcontroller/level_1_bottom
- up = 1
- up_target = 2
-
-/obj/effect/landmark/zcontroller/level_2_mid
- up = 1
- up_target = 3
- down = 1
- down_target = 1
-
-/obj/effect/landmark/zcontroller/level_3_mid
- up = 1
- up_target = 4
- down = 1
- down_target = 2
-
-/obj/effect/landmark/zcontroller/level_4_mid
- up = 1
- up_target = 5
- down = 1
- down_target = 3
-
-/obj/effect/landmark/zcontroller/level_2_top
- down = 1
- down_target = 1
-
-/obj/effect/landmark/zcontroller/level_3_top
- down = 1
- down_target = 2
-
-/obj/effect/landmark/zcontroller/level_4_top
- down = 1
- down_target = 3
-
-/obj/effect/landmark/zcontroller/level_5_top
- down = 1
- down_target = 4
\ No newline at end of file
diff --git a/code/ZAS/Atom.dm b/code/ZAS/Atom.dm
index e655295f78..ce69ad7162 100644
--- a/code/ZAS/Atom.dm
+++ b/code/ZAS/Atom.dm
@@ -64,9 +64,9 @@ turf/c_airblock(turf/other)
#ifdef ZLEVELS
if(other.z != src.z)
if(other.z < src.z)
- if(!istype(src, /turf/simulated/floor/open)) return BLOCKED
+ if(!istype(src, /turf/simulated/open)) return BLOCKED
else
- if(!istype(other, /turf/simulated/floor/open)) return BLOCKED
+ if(!istype(other, /turf/simulated/open)) return BLOCKED
#endif
var/result = 0
diff --git a/code/ZAS/Controller.dm b/code/ZAS/Controller.dm
index 922275bcc9..f6d2481468 100644
--- a/code/ZAS/Controller.dm
+++ b/code/ZAS/Controller.dm
@@ -281,8 +281,8 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
var/direct = !(block & ZONE_BLOCKED)
var/space = !istype(B)
- if(direct && !space)
- if(min(A.zone.contents.len, B.zone.contents.len) <= ZONE_MIN_SIZE || equivalent_pressure(A.zone,B.zone) || current_cycle == 0)
+ if(!space)
+ if(min(A.zone.contents.len, B.zone.contents.len) < ZONE_MIN_SIZE || (direct && (equivalent_pressure(A.zone,B.zone) || current_cycle == 0)))
merge(A.zone,B.zone)
return
diff --git a/code/__defines/atmos.dm b/code/__defines/atmos.dm
index ef41eb97f5..e93bf45085 100644
--- a/code/__defines/atmos.dm
+++ b/code/__defines/atmos.dm
@@ -86,3 +86,10 @@
//Flags for zone sleeping
#define ZONE_ACTIVE 1
#define ZONE_SLEEPING 0
+
+// Defines how much of certain gas do the Atmospherics tanks start with. Values are in kpa per tile (assuming 20C)
+#define ATMOSTANK_NITROGEN 90000 // A lot of N2 is needed to produce air mix, that's why we keep 90MPa of it
+#define ATMOSTANK_OXYGEN 40000 // O2 is also important for airmix, but not as much as N2 as it's only 21% of it.
+#define ATMOSTANK_CO2 25000 // CO2 and PH are not critically important for station, only for toxins and alternative coolants, no need to store a lot of those.
+#define ATMOSTANK_PHORON 25000
+#define ATMOSTANK_NITROUSOXIDE 10000 // N2O doesn't have a real useful use, i guess it's on station just to allow refilling of sec's riot control canisters?
\ No newline at end of file
diff --git a/code/__defines/gamemode.dm b/code/__defines/gamemode.dm
index db75adbbd2..827737cf92 100644
--- a/code/__defines/gamemode.dm
+++ b/code/__defines/gamemode.dm
@@ -24,6 +24,7 @@
#define BE_PLANT 0x1000
#define BE_MUTINEER 0x2000
#define BE_PAI 0x4000
+#define BE_LOYALIST 0x8000
var/list/be_special_flags = list(
"Traitor" = BE_TRAITOR,
@@ -32,6 +33,7 @@ var/list/be_special_flags = list(
"Wizard" = BE_WIZARD,
"Malf AI" = BE_MALF,
"Revolutionary" = BE_REV,
+ "Loyalist" = BE_LOYALIST,
"Xenomorph" = BE_ALIEN,
"Positronic Brain" = BE_AI,
"Cultist" = BE_CULTIST,
@@ -77,6 +79,7 @@ var/list/be_special_flags = list(
#define MODE_MONKEY "monkey"
#define MODE_RENEGADE "renegade"
#define MODE_REVOLUTIONARY "revolutionary"
+#define MODE_LOYALIST "loyalist"
#define MODE_MALFUNCTION "malf"
#define MODE_TRAITOR "traitor"
diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm
index 21a8f83c83..4dff787114 100644
--- a/code/__defines/machinery.dm
+++ b/code/__defines/machinery.dm
@@ -46,8 +46,8 @@ var/list/restricted_camera_networks = list("thunder","ERT","NUKE","Secret")
#define NETWORK_MINE "MINE"
#define NETWORK_RESEARCH "Research"
#define NETWORK_RESEARCH_OUTPOST "Research Outpost"
-#define NETWORK_PRISON "Prison"
#define NETWORK_ROBOTS "Robots"
+#define NETWORK_PRISON "Prison"
#define NETWORK_SECURITY "Security"
#define NETWORK_TELECOM "Tcomsat"
#define NETWORK_THUNDER "thunder"
diff --git a/code/__defines/research.dm b/code/__defines/research.dm
index 0cfc2aded6..d40722d0cf 100644
--- a/code/__defines/research.dm
+++ b/code/__defines/research.dm
@@ -14,5 +14,5 @@
#define IMPRINTER 0x1 //For circuits. Uses glass/chemicals.
#define PROTOLATHE 0x2 //New stuff. Uses glass/metal/chemicals
-#define MECHFAB 0x4 //Remember, objects utilising this flag should have construction_time and construction_cost vars.
+#define MECHFAB 0x4 //Mechfab
#define CHASSIS 0x8 //For protolathe, but differently
diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm
index 27dae81e72..fccfbaa2ef 100644
--- a/code/__defines/species_languages.dm
+++ b/code/__defines/species_languages.dm
@@ -20,6 +20,7 @@
#define HAS_LIPS 0x4 // Lips are drawn onto the mob icon. (lipstick)
#define HAS_UNDERWEAR 0x8 // Underwear is drawn onto the mob icon.
#define HAS_EYE_COLOR 0x10 // Eye colour selectable in chargen. (RGB)
+#define HAS_HAIR_COLOR 0x20 // Hair colour selectable in chargen. (RGB)
// Languages.
#define LANGUAGE_SOL_COMMON "Sol Common"
diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm
index 7690e73e09..863f33177e 100644
--- a/code/_helpers/global_lists.dm
+++ b/code/_helpers/global_lists.dm
@@ -64,6 +64,8 @@ var/global/list/rune_list = new()
var/global/list/escape_list = list()
var/global/list/endgame_exits = list()
var/global/list/endgame_safespawns = list()
+
+var/global/list/syndicate_access = list(access_maint_tunnels, access_syndicate, access_external_airlocks)
//////////////////////////
/////Initial Building/////
//////////////////////////
@@ -118,9 +120,7 @@ var/global/list/endgame_safespawns = list()
for (var/language_name in all_languages)
var/datum/language/L = all_languages[language_name]
if(!(L.flags & NONGLOBAL))
- language_keys[":[lowertext(L.key)]"] = L
- language_keys[".[lowertext(L.key)]"] = L
- language_keys["#[lowertext(L.key)]"] = L
+ language_keys[lowertext(L.key)] = L
var/rkey = 0
paths = typesof(/datum/species)-/datum/species
diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm
index 5aa80299c7..549060b0af 100644
--- a/code/_helpers/text.dm
+++ b/code/_helpers/text.dm
@@ -314,3 +314,19 @@ proc/TextPreview(var/string,var/len=40)
if(C && (C.prefs.toggles & CHAT_NOICONS))
return tagdesc
return "
"
+
+/proc/contains_az09(var/input)
+ for(var/i=1, i<=length(input), i++)
+ var/ascii_char = text2ascii(input,i)
+ switch(ascii_char)
+ // A .. Z
+ if(65 to 90) //Uppercase Letters
+ return 1
+ // a .. z
+ if(97 to 122) //Lowercase Letters
+ return 1
+
+ // 0 .. 9
+ if(48 to 57) //Numbers
+ return 1
+ return 0
diff --git a/code/_helpers/time.dm b/code/_helpers/time.dm
index 707d399c76..336d72fc13 100644
--- a/code/_helpers/time.dm
+++ b/code/_helpers/time.dm
@@ -36,9 +36,12 @@ proc/round_duration()
var/mills = world.time // 1/10 of a second, not real milliseconds but whatever
//var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something
- var/mins = (mills % 36000) / 600
- var/hours = mills / 36000
+ var/mins = round((mills % 36000) / 600)
+ var/hours = round(mills / 36000)
- last_round_duration = "[round(hours)]h [round(mins)]m"
+ mins = mins < 10 ? add_zero(mins, 1) : mins
+ hours = hours < 10 ? add_zero(hours, 1) : hours
+
+ last_round_duration = "[hours]:[mins]"
next_duration_update = world.time + 1 MINUTES
return last_round_duration
diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm
index 366fcbbbc1..c56a5d1e68 100644
--- a/code/_helpers/unsorted.dm
+++ b/code/_helpers/unsorted.dm
@@ -243,10 +243,10 @@ Turf and target are seperate in case you want to teleport some distance from a t
return 1
//Ensure the frequency is within bounds of what it should be sending/recieving at
-/proc/sanitize_frequency(var/f)
+/proc/sanitize_frequency(var/f, var/low = PUBLIC_LOW_FREQ, var/high = PUBLIC_HIGH_FREQ)
f = round(f)
- f = max(1441, f) // 144.1
- f = min(1489, f) // 148.9
+ f = max(low, f)
+ f = min(high, f)
if ((f % 2) == 0) //Ensure the last digit is an odd number
f += 1
return f
@@ -569,7 +569,7 @@ proc/GaussRandRound(var/sigma,var/roundto)
var/turf/current = get_turf(source)
var/turf/target_turf = get_turf(target)
var/steps = 0
-
+
if(!current || !target_turf)
return 0
@@ -1053,12 +1053,10 @@ proc/get_mob_with_client_list()
//gets the turf the atom is located in (or itself, if it is a turf).
//returns null if the atom is not in a turf.
-/proc/get_turf(atom/location)
- while(location)
- if(isturf(location))
- return location
- location = location.loc
- return null
+/proc/get_turf(atom/A)
+ if(!istype(A)) return
+ for(A, A && !isturf(A), A=A.loc);
+ return A
/proc/get(atom/loc, type)
while(loc)
diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm
index 4dee15388d..dfb6de5e91 100644
--- a/code/_onclick/ai.dm
+++ b/code/_onclick/ai.dm
@@ -31,7 +31,7 @@
build_click(src, client.buildmode, params, A)
return
- if(control_disabled || stat)
+ if(stat)
return
var/list/modifiers = params2list(params)
@@ -51,7 +51,7 @@
CtrlClickOn(A)
return
- if(!canClick())
+ if(control_disabled || !canClick())
return
if(aiCamera.in_camera_mode)
@@ -89,13 +89,24 @@
*/
/mob/living/silicon/ai/ShiftClickOn(var/atom/A)
- A.AIShiftClick(src)
+ if(!control_disabled && A.AIShiftClick(src))
+ return
+ ..()
+
/mob/living/silicon/ai/CtrlClickOn(var/atom/A)
- A.AICtrlClick(src)
+ if(!control_disabled && A.AICtrlClick(src))
+ return
+ ..()
+
/mob/living/silicon/ai/AltClickOn(var/atom/A)
- A.AIAltClick(src)
+ if(!control_disabled && A.AIAltClick(src))
+ return
+ ..()
+
/mob/living/silicon/ai/MiddleClickOn(var/atom/A)
- A.AIMiddleClick(src)
+ if(!control_disabled && A.AIMiddleClick(src))
+ return
+ ..()
/*
The following criminally helpful code is just the previous code cleaned up;
@@ -105,11 +116,6 @@
/atom/proc/AICtrlShiftClick()
return
-/obj/machinery/door/airlock/AICtrlShiftClick()
- if(emagged)
- return
- return
-
/atom/proc/AIShiftClick()
return
@@ -118,7 +124,7 @@
Topic(src, list("src"= "\ref[src]", "command"="open", "activate" = "1"), 1) // 1 meaning no window (consistency!)
else
Topic(src, list("src"= "\ref[src]", "command"="open", "activate" = "0"), 1)
- return
+ return 1
/atom/proc/AICtrlClick()
return
@@ -128,15 +134,18 @@
Topic(src, list("src"= "\ref[src]", "command"="bolts", "activate" = "0"), 1)// 1 meaning no window (consistency!)
else
Topic(src, list("src"= "\ref[src]", "command"="bolts", "activate" = "1"), 1)
+ return 1
/obj/machinery/power/apc/AICtrlClick() // turns off/on APCs.
Topic(src, list("src"= "\ref[src]", "breaker"="1"), 1) // 1 meaning no window (consistency!)
+ return 1
/obj/machinery/turretid/AICtrlClick() //turns off/on Turrets
Topic(src, list("src"= "\ref[src]", "command"="enable", "value"="[!enabled]"), 1) // 1 meaning no window (consistency!)
+ return 1
/atom/proc/AIAltClick(var/atom/A)
- AltClick(A)
+ return AltClick(A)
/obj/machinery/door/airlock/AIAltClick() // Electrifies doors.
if(!electrified_until)
@@ -145,20 +154,25 @@
else
// disable/6 is not in Topic; disable/5 disables both temporary and permanent shock
Topic(src, list("src"= "\ref[src]", "command"="electrify_permanently", "activate" = "0"), 1)
- return
+ return 1
/obj/machinery/turretid/AIAltClick() //toggles lethal on turrets
Topic(src, list("src"= "\ref[src]", "command"="lethal", "value"="[!lethal]"), 1) // 1 meaning no window (consistency!)
+ return 1
-/atom/proc/AIMiddleClick()
- return
+/atom/proc/AIMiddleClick(var/mob/living/silicon/user)
+ return 0
/obj/machinery/door/airlock/AIMiddleClick() // Toggles door bolt lights.
+
+ if(..())
+ return
+
if(!src.lights)
Topic(src, list("src"= "\ref[src]", "command"="lights", "activate" = "1"), 1) // 1 meaning no window (consistency!)
else
Topic(src, list("src"= "\ref[src]", "command"="lights", "activate" = "0"), 1)
- return
+ return 1
//
// Override AdjacentQuick for AltClicking
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 5a4ce2bb8e..2261ceb368 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -108,7 +108,7 @@
// faster access to objects already on you
if(A.loc != src)
setMoveCooldown(10) //getting something out of a backpack
-
+
if(W)
var/resolved = W.resolve_attackby(A, src)
if(!resolved && A && W)
@@ -128,7 +128,7 @@
if(isturf(A) || isturf(A.loc) || (sdepth != -1 && sdepth <= 1))
if(A.Adjacent(src)) // see adjacent.dm
setMoveCooldown(5)
-
+
if(W)
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
var/resolved = W.resolve_attackby(A,src)
@@ -224,10 +224,8 @@
Only used for swapping hands
*/
/mob/proc/MiddleClickOn(var/atom/A)
- return
-
-/mob/living/carbon/MiddleClickOn(var/atom/A)
swap_hand()
+ return
// In case of use break glass
/*
@@ -278,7 +276,7 @@
else
user.listed_turf = T
user.client.statpanel = T.name
- return
+ return 1
/mob/proc/TurfAdjacent(var/turf/T)
return T.AdjacentQuick(src)
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index 324dcc234d..55fe373301 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -26,7 +26,7 @@
// Otherwise jump
else
following = null
- loc = get_turf(A)
+ forceMove(get_turf(A))
/mob/dead/observer/ClickOn(var/atom/A, var/params)
if(client.buildmode)
diff --git a/code/_onclick/rig.dm b/code/_onclick/rig.dm
index 600d8c5619..436e7353ec 100644
--- a/code/_onclick/rig.dm
+++ b/code/_onclick/rig.dm
@@ -29,34 +29,53 @@
src << "Somehow you bugged the system. Setting your hardsuit mode to middle-click."
hardsuit_click_mode = MIDDLE_CLICK
-/mob/living/carbon/human/MiddleClickOn(atom/A)
+/mob/living/MiddleClickOn(atom/A)
if(client && client.hardsuit_click_mode == MIDDLE_CLICK)
if(HardsuitClickOn(A))
return
..()
-/mob/living/carbon/human/AltClickOn(atom/A)
+/mob/living/AltClickOn(atom/A)
if(client && client.hardsuit_click_mode == ALT_CLICK)
if(HardsuitClickOn(A))
return
..()
-/mob/living/carbon/human/CtrlClickOn(atom/A)
+/mob/living/CtrlClickOn(atom/A)
if(client && client.hardsuit_click_mode == CTRL_CLICK)
if(HardsuitClickOn(A))
return
..()
-/mob/living/carbon/human/proc/HardsuitClickOn(atom/A)
- if(!canClick())
- return
- if(back)
- var/obj/item/weapon/rig/rig = back
- if(istype(rig) && rig.selected_module)
- rig.selected_module.engage(A)
- if(ismob(A)) // No instant mob attacking - though modules have their own cooldowns
- setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
- return 1
+/mob/living/proc/can_use_rig()
+ return 0
+
+/mob/living/carbon/human/can_use_rig()
+ return 1
+
+/mob/living/carbon/brain/can_use_rig()
+ return istype(loc, /obj/item/device/mmi)
+
+/mob/living/silicon/ai/can_use_rig()
+ return carded
+
+/mob/living/silicon/pai/can_use_rig()
+ return loc == card
+
+/mob/living/proc/HardsuitClickOn(var/atom/A, var/alert_ai = 0)
+ if(!can_use_rig() || !canClick())
+ return 0
+ var/obj/item/weapon/rig/rig = get_rig()
+ if(istype(rig) && !rig.offline && rig.selected_module)
+ if(src != rig.wearer)
+ if(rig.ai_can_move_suit(src, check_user_module = 1))
+ message_admins("[key_name_admin(src, include_name = 1)] is trying to force \the [key_name_admin(rig.wearer, include_name = 1)] to use a hardsuit module.")
+ else
+ return 0
+ rig.selected_module.engage(A, alert_ai)
+ if(ismob(A)) // No instant mob attacking - though modules have their own cooldowns
+ setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ return 1
return 0
#undef MIDDLE_CLICK
diff --git a/code/controllers/Processes/machinery.dm b/code/controllers/Processes/machinery.dm
index b84dfaf943..7959ee4fa7 100644
--- a/code/controllers/Processes/machinery.dm
+++ b/code/controllers/Processes/machinery.dm
@@ -6,6 +6,7 @@
/datum/controller/process/machinery/doWork()
internal_sort()
+ internal_process_pipenets()
internal_process_machinery()
internal_process_power()
internal_process_power_drain()
@@ -57,6 +58,14 @@
processing_power_items.Remove(I)
scheck()
+/datum/controller/process/machinery/proc/internal_process_pipenets()
+ for(var/datum/pipe_network/pipeNetwork in pipe_networks)
+ if(istype(pipeNetwork) && !pipeNetwork.disposed)
+ pipeNetwork.process()
+ scheck()
+ continue
+
+ pipe_networks.Remove(pipeNetwork)
/datum/controller/process/machinery/getStatName()
- return ..()+"([machines.len])"
+ return ..()+"(MCH:[machines.len] PWR:[powernets.len] PIP:[pipe_networks.len])"
diff --git a/code/controllers/Processes/pipenet.dm b/code/controllers/Processes/pipenet.dm
deleted file mode 100644
index 8a5d6a22ca..0000000000
--- a/code/controllers/Processes/pipenet.dm
+++ /dev/null
@@ -1,15 +0,0 @@
-/datum/controller/process/pipenet/setup()
- name = "pipenet"
- schedule_interval = 20 // every 2 seconds
-
-/datum/controller/process/pipenet/doWork()
- for(var/datum/pipe_network/pipeNetwork in pipe_networks)
- if(istype(pipeNetwork) && !pipeNetwork.disposed)
- pipeNetwork.process()
- scheck()
- continue
-
- pipe_networks.Remove(pipeNetwork)
-
-/datum/controller/process/pipenet/getStatName()
- return ..()+"([pipe_networks.len])"
\ No newline at end of file
diff --git a/code/controllers/communications.dm b/code/controllers/communications.dm
index c1594665a1..f9e7b67c74 100644
--- a/code/controllers/communications.dm
+++ b/code/controllers/communications.dm
@@ -97,11 +97,16 @@ On the map:
1455 for AI access
*/
-var/const/BOT_FREQ = 1447
+var/const/RADIO_LOW_FREQ = 1200
+var/const/PUBLIC_LOW_FREQ = 1441
+var/const/PUBLIC_HIGH_FREQ = 1489
+var/const/RADIO_HIGH_FREQ = 1600
+
+var/const/BOT_FREQ = 1447
var/const/COMM_FREQ = 1353
-var/const/ERT_FREQ = 1345
-var/const/AI_FREQ = 1343
-var/const/DTH_FREQ = 1341
+var/const/ERT_FREQ = 1345
+var/const/AI_FREQ = 1343
+var/const/DTH_FREQ = 1341
var/const/SYND_FREQ = 1213
// department channels
@@ -113,6 +118,10 @@ var/const/SCI_FREQ = 1351
var/const/SRV_FREQ = 1349
var/const/SUP_FREQ = 1347
+// internal department channels
+var/const/MED_I_FREQ = 1485
+var/const/SEC_I_FREQ = 1475
+
var/list/radiochannels = list(
"Common" = PUB_FREQ,
"Science" = SCI_FREQ,
@@ -125,7 +134,9 @@ var/list/radiochannels = list(
"Mercenary" = SYND_FREQ,
"Supply" = SUP_FREQ,
"Service" = SRV_FREQ,
- "AI Private" = AI_FREQ
+ "AI Private" = AI_FREQ,
+ "Medical(I)" = MED_I_FREQ,
+ "Security(I)" = SEC_I_FREQ
)
// central command channels, i.e deathsquid & response teams
@@ -134,8 +145,8 @@ var/list/CENT_FREQS = list(ERT_FREQ, DTH_FREQ)
// Antag channels, i.e. Syndicate
var/list/ANTAG_FREQS = list(SYND_FREQ)
-//depenging helpers
-var/list/DEPT_FREQS = list(SCI_FREQ, MED_FREQ, ENG_FREQ, SEC_FREQ, SUP_FREQ, SRV_FREQ, ERT_FREQ, SYND_FREQ, DTH_FREQ)
+//Department channels, arranged lexically
+var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, MED_FREQ, SEC_FREQ, SCI_FREQ, SRV_FREQ, SUP_FREQ)
#define TRANSMISSION_WIRE 0
#define TRANSMISSION_RADIO 1
@@ -145,29 +156,28 @@ var/list/DEPT_FREQS = list(SCI_FREQ, MED_FREQ, ENG_FREQ, SEC_FREQ, SUP_FREQ, SRV
if (frequency in ANTAG_FREQS)
return "syndradio"
// centcomm channels (deathsquid and ert)
- else if(frequency in CENT_FREQS)
+ if(frequency in CENT_FREQS)
return "centradio"
// command channel
- else if(frequency == COMM_FREQ)
+ if(frequency == COMM_FREQ)
return "comradio"
// AI private channel
- else if(frequency == AI_FREQ)
+ if(frequency == AI_FREQ)
return "airadio"
// department radio formatting (poorly optimized, ugh)
- else if(frequency == SEC_FREQ)
+ if(frequency == SEC_FREQ)
return "secradio"
- else if (frequency == ENG_FREQ)
+ if (frequency == ENG_FREQ)
return "engradio"
- else if(frequency == SCI_FREQ)
+ if(frequency == SCI_FREQ)
return "sciradio"
- else if(frequency == MED_FREQ)
+ if(frequency == MED_FREQ)
return "medradio"
- else if(frequency == SUP_FREQ) // cargo
+ if(frequency == SUP_FREQ) // cargo
return "supradio"
- else if(frequency == SRV_FREQ) // service
+ if(frequency == SRV_FREQ) // service
return "srvradio"
- // If all else fails and it's a dept_freq, color me purple!
- else if(frequency in DEPT_FREQS)
+ if(frequency in DEPT_FREQS)
return "deptradio"
return "radio"
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index a96dd682ba..aba57b47a2 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -74,9 +74,6 @@ var/list/gamemode_cache = list()
var/automute_on = 0 //enables automuting/spam prevention
var/jobs_have_minimal_access = 0 //determines whether jobs use minimal access or expanded access.
- var/rp_rev = 0 // Changes between conversion methods in rev.
- var/announce_revheads = 0 // Determines if revheads are announced in revolution mode.
-
var/cult_ghostwriter = 1 //Allows ghosts to write in blood in cult rounds...
var/cult_ghostwriter_req_cultists = 10 //...so long as this many cultists are active.
@@ -216,6 +213,8 @@ var/list/gamemode_cache = list()
var/aggressive_changelog = 0
+ var/list/language_prefixes = list(",","#","-")//Default language prefixes
+
/datum/configuration/New()
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
for (var/T in L)
@@ -648,12 +647,6 @@ var/list/gamemode_cache = list()
if("disable_welder_vision")
config.welder_vision = 0
- if("rp_rev")
- config.rp_rev = 1
-
- if("announce_revheads")
- config.announce_revheads = 1
-
if("allow_extra_antags")
config.allow_extra_antags = 1
@@ -696,6 +689,11 @@ var/list/gamemode_cache = list()
if("aggressive_changelog")
config.aggressive_changelog = 1
+ if("default_language_prefixes")
+ var/list/values = text2list(value, " ")
+ if(values.len > 0)
+ language_prefixes = values
+
else
log_misc("Unknown setting in configuration: '[name]'")
@@ -853,21 +851,15 @@ var/list/gamemode_cache = list()
for (var/game_mode in gamemode_cache)
var/datum/game_mode/M = gamemode_cache[game_mode]
if (M.config_tag && M.config_tag == mode_name)
- M.create_antagonists()
return M
return gamemode_cache["extended"]
/datum/configuration/proc/get_runnable_modes()
- var/list/datum/game_mode/runnable_modes = new
- for (var/game_mode in gamemode_cache)
+ var/list/runnable_modes = list()
+ for(var/game_mode in gamemode_cache)
var/datum/game_mode/M = gamemode_cache[game_mode]
- if (!(M.config_tag in modes))
- continue
- if (probabilities[M.config_tag]<=0)
- continue
- if (M.can_start())
- runnable_modes[M] = probabilities[M.config_tag]
- //world << "DEBUG: runnable_mode\[[runnable_modes.len]\] = [M.config_tag]"
+ if(M && M.can_start() && !isnull(config.probabilities[M.config_tag]) && config.probabilities[M.config_tag] > 0)
+ runnable_modes |= M
return runnable_modes
/datum/configuration/proc/post_load()
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index ab79808cf3..ac5ebee68c 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -17,6 +17,7 @@
var/list/eng = new()
var/list/med = new()
var/list/sci = new()
+ var/list/car = new()
var/list/civ = new()
var/list/bot = new()
var/list/misc = new()
@@ -67,6 +68,9 @@
if(real_rank in science_positions)
sci[name] = rank
department = 1
+ if(real_rank in cargo_positions)
+ car[name] = rank
+ department = 1
if(real_rank in civilian_positions)
civ[name] = rank
department = 1
@@ -100,6 +104,11 @@
for(name in sci)
dat += "
| [name] | [sci[name]] | [isactive[name]] |
"
even = !even
+ if(car.len > 0)
+ dat += "| Cargo |
"
+ for(name in car)
+ dat += "| [name] | [car[name]] | [isactive[name]] |
"
+ even = !even
if(civ.len > 0)
dat += "| Civilian |
"
for(name in civ)
diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm
index a0f1f9c7f1..3c247d6c7f 100644
--- a/code/datums/wires/airlock.dm
+++ b/code/datums/wires/airlock.dm
@@ -161,7 +161,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
if(A.emagged) return
if(!A.requiresID() || A.check_access(null))
if(A.density) A.open()
- else A.close()
+ else A.close()
if(AIRLOCK_WIRE_SAFETY)
A.safe = !A.safe
if(!A.density)
diff --git a/code/defines/obj.dm b/code/defines/obj.dm
index c3082d188f..602008ccd7 100644
--- a/code/defines/obj.dm
+++ b/code/defines/obj.dm
@@ -72,6 +72,7 @@ var/global/ManifestJSON
var/eng[0]
var/med[0]
var/sci[0]
+ var/car[0]
var/civ[0]
var/bot[0]
var/misc[0]
@@ -113,6 +114,12 @@ var/global/ManifestJSON
department = 1
if(depthead && sci.len != 1)
sci.Swap(1,sci.len)
+
+ if(real_rank in cargo_positions)
+ car[++car.len] = list("name" = name, "rank" = rank, "active" = isactive)
+ department = 1
+ if(depthead && car.len != 1)
+ car.Swap(1,car.len)
if(real_rank in civilian_positions)
civ[++civ.len] = list("name" = name, "rank" = rank, "active" = isactive)
@@ -134,6 +141,7 @@ var/global/ManifestJSON
"eng" = eng,\
"med" = med,\
"sci" = sci,\
+ "car" = car,\
"civ" = civ,\
"bot" = bot,\
"misc" = misc\
diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm
index d4633e3f07..54ca78aa39 100644
--- a/code/defines/obj/weapon.dm
+++ b/code/defines/obj/weapon.dm
@@ -174,6 +174,7 @@
w_class = 3.0
origin_tech = list(TECH_MATERIAL = 1)
var/breakouttime = 300 //Deciseconds = 30s = 0.5 minute
+ sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/handcuffs.dmi')
/obj/item/weapon/caution
desc = "Caution! Wet Floor!"
diff --git a/code/game/antagonist/alien/borer.dm b/code/game/antagonist/alien/borer.dm
index bd436ceaf8..07ebf3d189 100644
--- a/code/game/antagonist/alien/borer.dm
+++ b/code/game/antagonist/alien/borer.dm
@@ -7,7 +7,14 @@ var/datum/antagonist/xenos/borer/borers
mob_path = /mob/living/simple_animal/borer
bantype = "Borer"
welcome_text = "Use your Infest power to crawl into the ear of a host and fuse with their brain. You can only take control temporarily, and at risk of hurting your host, so be clever and careful; your host is encouraged to help you however they can. Talk to your fellow borers with :x."
- var/list/hosts = list()
+ antag_indicator = "brainworm"
+
+ faction_role_text = "Borer Thrall"
+ faction_descriptor = "Unity"
+ faction_welcome = "You are now a thrall to a cortical borer. Please listen to what they have to say; they're in your head."
+
+ initial_spawn_req = 3
+ initial_spawn_target = 5
/datum/antagonist/xenos/borer/New()
..(1)
@@ -23,32 +30,24 @@ var/datum/antagonist/xenos/borer/borers
player.objectives += new /datum/objective/borer_reproduce()
player.objectives += new /datum/objective/escape()
-/datum/antagonist/xenos/borer/proc/place_in_host(var/mob/living/simple_animal/borer/borer, var/mob/living/carbon/human/host)
- borer.host = host
- borer.host_brain.name = host.name
- borer.host_brain.real_name = host.real_name
- var/obj/item/organ/external/head = host.get_organ("head")
- if(head) head.implants += borer
-
-/datum/antagonist/xenos/borer/proc/get_hosts()
- var/list/possible_hosts = list()
- for(var/mob/living/carbon/human/H in mob_list)
- var/obj/item/organ/external/head/head = H.get_organ("head")
- if(head.status & ORGAN_ROBOT)
- continue
- if(H.stat != DEAD && !H.has_brain_worms())
- possible_hosts |= H
- return possible_hosts
-
-/datum/antagonist/xenos/borer/place_all_mobs()
- var/list/possible_hosts = get_hosts()
- for(var/datum/mind/player in current_antagonists)
- if(!possible_hosts.len)
- return
- var/mob/host = pick(possible_hosts)
- possible_hosts -= host
- place_in_host(player, host)
-
/datum/antagonist/xenos/borer/place_mob(var/mob/living/mob)
- var/list/possible_hosts = get_hosts()
- if(possible_hosts.len) place_in_host(mob, pick(possible_hosts))
+ var/mob/living/simple_animal/borer/borer = mob
+ if(istype(borer))
+ var/mob/living/carbon/human/host
+ for(var/mob/living/carbon/human/H in mob_list)
+ if(H.stat != DEAD && !H.has_brain_worms())
+ var/obj/item/organ/external/head = H.get_organ("head")
+ if(head && !(head.status & ORGAN_ROBOT))
+ host = H
+ break
+ if(istype(host))
+ var/obj/item/organ/external/head = host.get_organ("head")
+ borer.host = host
+ head.implants += borer
+ borer.loc = head
+ if(!borer.host_brain)
+ borer.host_brain = new(borer)
+ borer.host_brain.name = host.name
+ borer.host_brain.real_name = host.real_name
+ return
+ ..() // Place them at a vent if they can't get a host.
diff --git a/code/game/antagonist/alien/xenomorph.dm b/code/game/antagonist/alien/xenomorph.dm
index f93409a820..f6a8bc5cb1 100644
--- a/code/game/antagonist/alien/xenomorph.dm
+++ b/code/game/antagonist/alien/xenomorph.dm
@@ -10,27 +10,21 @@ var/datum/antagonist/xenos/xenomorphs
flags = ANTAG_OVERRIDE_MOB | ANTAG_RANDSPAWN | ANTAG_OVERRIDE_JOB | ANTAG_VOTABLE
welcome_text = "Hiss! You are a larval alien. Hide and bide your time until you are ready to evolve."
- max_antags = 5
- max_antags_round = 8
+ hard_cap = 5
+ hard_cap_round = 8
+ initial_spawn_req = 4
+ initial_spawn_target = 6
spawn_announcement = "Unidentified lifesigns detected coming aboard the station. Secure any exterior access, including ducting and ventilation."
spawn_announcement_title = "Lifesign Alert"
spawn_announcement_sound = 'sound/AI/aliens.ogg'
- spawn_announcement_delay = 400
+ spawn_announcement_delay = 5000
/datum/antagonist/xenos/New(var/no_reference)
..()
if(!no_reference)
xenomorphs = src
-/datum/antagonist/xenos/Topic(href, href_list)
- if (..())
- return
- if(href_list["move_to_spawn"]) place_mob(locate(href_list["move_to_spawn"]))
-
-/datum/antagonist/xenos/get_extra_panel_options(var/datum/mind/player)
- return "\[move to vent\]"
-
/datum/antagonist/xenos/attempt_random_spawn()
if(config.aliens_allowed) ..()
@@ -48,12 +42,5 @@ var/datum/antagonist/xenos/xenomorphs
player.objectives += new /datum/objective/survive()
player.objectives += new /datum/objective/escape()
-/datum/antagonist/xenos/place_all_mobs()
- var/list/vents = get_vents()
- for(var/datum/mind/player in current_antagonists)
- var/obj/machinery/atmospherics/unary/vent_pump/temp_vent = pick(vents)
- vents -= temp_vent
- player.current.loc = get_turf(temp_vent)
-
/datum/antagonist/xenos/place_mob(var/mob/living/player)
player.loc = get_turf(pick(get_vents()))
diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm
index 6e98ce6c35..3be89beba1 100644
--- a/code/game/antagonist/antagonist.dm
+++ b/code/game/antagonist/antagonist.dm
@@ -1,53 +1,76 @@
/datum/antagonist
- var/role_type = BE_TRAITOR
- var/role_text = "Traitor"
- var/role_text_plural = "Traitors"
+ // Text shown when becoming this antagonist.
+ var/list/restricted_jobs = list() // Jobs that cannot be this antagonist (depending on config)
+ var/list/protected_jobs = list() // As above.
+
+ // Strings.
var/welcome_text = "Cry havoc and let slip the dogs of war!"
- var/leader_welcome_text
- var/victory_text
- var/loss_text
- var/victory_feedback_tag
- var/loss_feedback_tag
- var/max_antags = 3
- var/max_antags_round = 5
+ var/leader_welcome_text // Text shown to the leader, if any.
+ var/victory_text // World output at roundend for victory.
+ var/loss_text // As above for loss.
+ var/victory_feedback_tag // Used by the database for end of round loss.
+ var/loss_feedback_tag // Used by the database for end of round loss.
- // Random spawn values.
- var/spawn_announcement
- var/spawn_announcement_title
- var/spawn_announcement_sound
- var/spawn_announcement_delay
+ // Role data.
+ var/id = "traitor" // Unique datum identifier.
+ var/role_type = BE_TRAITOR // Preferences option for this role.
+ var/role_text = "Traitor" // special_role text.
+ var/role_text_plural = "Traitors" // As above but plural.
- var/id = "traitor"
- var/landmark_id
- var/antag_indicator
- var/mob_path = /mob/living/carbon/human
- var/feedback_tag = "traitor_objective"
- var/bantype = "Syndicate"
- var/suspicion_chance = 50
- var/flags = 0
- var/cur_max = 0
+ // Visual references.
+ var/antag_indicator // icon_state for icons/mob/mob.dm visual indicator.
+ var/faction_indicator // See antag_indicator, but for factionalized people only.
+ var/faction_invisible // Can members of the faction identify other antagonists?
- var/datum/mind/leader
- var/spawned_nuke
- var/nuke_spawn_loc
+ // Faction data.
+ var/faction_role_text // Role for sub-antags. Mandatory for faction role.
+ var/faction_descriptor // Description of the cause. Mandatory for faction role.
+ var/faction_verb // Verb added when becoming a member of the faction, if any.
+ var/faction_welcome // Message shown to faction members.
- var/list/valid_species = list("Unathi","Tajara","Skrell","Human") // Used for setting appearance.
- var/list/current_antagonists = list()
- var/list/pending_antagonists = list()
- var/list/starting_locations = list()
- var/list/global_objectives = list()
- var/list/restricted_jobs = list()
- var/list/protected_jobs = list()
- var/list/candidates = list()
+ // Spawn values (autotraitor and game mode)
+ var/hard_cap = 3 // Autotraitor var. Won't spawn more than this many antags.
+ var/hard_cap_round = 5 // As above but 'core' round antags ie. roundstart.
+ var/initial_spawn_req = 1 // Gamemode using this template won't start without this # candidates.
+ var/initial_spawn_target = 3 // Gamemode will attempt to spawn this many antags.
+ var/announced // Has an announcement been sent?
+ var/spawn_announcement // When the datum spawn proc is called, does it announce to the world? (ie. xenos)
+ var/spawn_announcement_title // Report title.
+ var/spawn_announcement_sound // Report sound clip.
+ var/spawn_announcement_delay // Time between initial spawn and round announcement.
+ // Misc.
+ var/landmark_id // Spawn point identifier.
+ var/mob_path = /mob/living/carbon/human // Mobtype this antag will use if none is provided.
+ var/feedback_tag = "traitor_objective" // End of round
+ var/bantype = "Syndicate" // Ban to check when spawning this antag.
+ var/suspicion_chance = 50 // Prob of being on the initial Command report
+ var/flags = 0 // Various runtime options.
+
+ // Used for setting appearance.
+ var/list/valid_species = list("Unathi","Tajara","Skrell","Human")
+
+ // Runtime vars.
+ var/datum/mind/leader // Current leader, if any.
+ var/cur_max = 0 // Autotraitor current effective maximum.
+ var/spawned_nuke // Has a bomb been spawned?
+ var/nuke_spawn_loc // If so, where should it be placed?
+ var/list/current_antagonists = list() // All marked antagonists for this type.
+ var/list/pending_antagonists = list() // Candidates that are awaiting finalized antag status.
+ var/list/starting_locations = list() // Spawn points.
+ var/list/global_objectives = list() // Universal objectives if any.
+ var/list/candidates = list() // Potential candidates.
+ var/list/faction_members = list() // Semi-antags (in-round revs, borer thralls)
+
+ // ID card stuff.
var/default_access = list()
var/id_type = /obj/item/weapon/card/id
- var/announced
+
/datum/antagonist/New()
..()
- cur_max = max_antags
+ cur_max = hard_cap
get_starting_locations()
if(!role_text_plural)
role_text_plural = role_text
@@ -59,7 +82,7 @@
/datum/antagonist/proc/get_candidates(var/ghosts_only)
candidates = list() // Clear.
-
+
// Prune restricted status. Broke it up for readability.
// Note that this is done before jobs are handed out.
for(var/datum/mind/player in ticker.mode.get_players_for_role(role_type, id))
@@ -85,14 +108,21 @@
/datum/antagonist/proc/attempt_late_spawn(var/datum/mind/player)
if(!can_late_spawn())
- return
- if(!istype(player)) player = get_candidates(is_latejoin_template())
+ return 0
+ if(!istype(player))
+ var/list/players = get_candidates(is_latejoin_template())
+ if(players && players.len)
+ player = pick(players)
+ if(!istype(player))
+ message_admins("AUTO[uppertext(ticker.mode.name)]: Failed to find a candidate for [role_text].")
+ return 0
player.current << "You have been selected this round as an antagonist!"
+ message_admins("AUTO[uppertext(ticker.mode.name)]: Selected [player] as a [role_text].")
if(istype(player.current, /mob/dead))
create_default(player.current)
else
- add_antagonist(player,0,1,0,1,1)
- return
+ add_antagonist(player,0,0,0,1,1)
+ return 1
/datum/antagonist/proc/build_candidate_list(var/ghosts_only)
// Get the raw list of potential players.
@@ -111,8 +141,7 @@
return 0
//Grab candidates randomly until we have enough.
- candidates = shuffle(candidates)
- while(candidates.len && pending_antagonists.len < cur_max)
+ while(candidates.len && pending_antagonists.len < initial_spawn_target)
var/datum/mind/player = pick(candidates)
candidates -= player
draft_antagonist(player)
@@ -121,19 +150,26 @@
/datum/antagonist/proc/draft_antagonist(var/datum/mind/player)
//Check if the player can join in this antag role, or if the player has already been given an antag role.
- if(!can_become_antag(player) || player.special_role)
+ if(!can_become_antag(player))
log_debug("[player.key] was selected for [role_text] by lottery, but is not allowed to be that role.")
return 0
+ if(player.special_role)
+ log_debug("[player.key] was selected for [role_text] by lottery, but they already have a special role.")
+ return 0
+ if(!(flags & ANTAG_OVERRIDE_JOB) && (!player.current || istype(player.current, /mob/new_player)))
+ log_debug("[player.key] was selected for [role_text] by lottery, but they have not joined the game.")
+ return 0
pending_antagonists |= player
-
+ log_debug("[player.key] has been selected for [role_text] by lottery.")
+
//Ensure that antags with ANTAG_OVERRIDE_JOB do not occupy job slots.
if(flags & ANTAG_OVERRIDE_JOB)
player.assigned_role = role_text
-
+
//Ensure that a player cannot be drafted for multiple antag roles, taking up slots for antag roles that they will not fill.
player.special_role = role_text
-
+
return 1
//Spawns all pending_antagonists. This is done separately from attempt_spawn in case the game mode setup fails.
diff --git a/code/game/antagonist/antagonist_add.dm b/code/game/antagonist/antagonist_add.dm
index 7815167d6f..5ca66731c4 100644
--- a/code/game/antagonist/antagonist_add.dm
+++ b/code/game/antagonist/antagonist_add.dm
@@ -1,15 +1,8 @@
/datum/antagonist/proc/add_antagonist(var/datum/mind/player, var/ignore_role, var/do_not_equip, var/move_to_spawn, var/do_not_announce, var/preserve_appearance)
- if(!istype(player))
- return 0
- if(!player.current)
- return 0
- if(player in current_antagonists)
- return 0
- if(!can_become_antag(player, ignore_role))
- return 0
- current_antagonists |= player
-
+ if(!add_antagonist_mind(player, ignore_role))
+ return
+
//do this again, just in case
if(flags & ANTAG_OVERRIDE_JOB)
player.assigned_role = role_text
@@ -23,10 +16,37 @@
equip(player.current)
return 1
+/datum/antagonist/proc/add_antagonist_mind(var/datum/mind/player, var/ignore_role, var/nonstandard_role_type, var/nonstandard_role_msg)
+ if(!istype(player))
+ return 0
+ if(!player.current)
+ return 0
+ if(player in current_antagonists)
+ return 0
+ if(!can_become_antag(player, ignore_role))
+ return 0
+ current_antagonists |= player
+
+ if(faction_verb && player.current)
+ player.current.verbs |= faction_verb
+
+ // Handle only adding a mind and not bothering with gear etc.
+ if(nonstandard_role_type)
+ faction_members |= player
+ player.current << "You are \a [nonstandard_role_type]!"
+ player.special_role = nonstandard_role_type
+ if(nonstandard_role_msg)
+ player.current << "[nonstandard_role_msg]"
+ update_icons_added(player)
+ return 1
+
/datum/antagonist/proc/remove_antagonist(var/datum/mind/player, var/show_message, var/implanted)
+ if(player.current && faction_verb)
+ player.current.verbs -= faction_verb
if(player in current_antagonists)
player.current << "You are no longer a [role_text]!"
current_antagonists -= player
+ faction_members -= player
player.special_role = null
update_icons_removed(player)
BITSET(player.current.hud_updateflag, SPECIALROLE_HUD)
diff --git a/code/game/antagonist/antagonist_create.dm b/code/game/antagonist/antagonist_create.dm
index 69b7f8e9d0..072dd88bee 100644
--- a/code/game/antagonist/antagonist_create.dm
+++ b/code/game/antagonist/antagonist_create.dm
@@ -36,7 +36,7 @@
if(!W) return
W.access |= default_access
W.assignment = "[assignment]"
- W.set_owner_info(player)
+ player.set_id_info(W)
if(equip) player.equip_to_slot_or_del(W, slot_wear_id)
return W
diff --git a/code/game/antagonist/antagonist_factions.dm b/code/game/antagonist/antagonist_factions.dm
new file mode 100644
index 0000000000..83c9957be2
--- /dev/null
+++ b/code/game/antagonist/antagonist_factions.dm
@@ -0,0 +1,50 @@
+/mob/living/proc/convert_to_rev(mob/M as mob in oview(src))
+ set name = "Convert Bourgeoise"
+ set category = "Abilities"
+ if(!M.mind)
+ return
+ convert_to_faction(M.mind, revs)
+
+/mob/living/proc/convert_to_faction(var/datum/mind/player, var/datum/antagonist/faction)
+
+ if(!player || !faction || !player.current)
+ return
+
+ if(!faction.faction_verb || !faction.faction_descriptor || !faction.faction_verb)
+ return
+
+ if(faction.is_antagonist(player))
+ src << "\The [player.current] already serves the [faction.faction_descriptor]."
+ return
+
+ if(player_is_antag(player))
+ src << "\The [player.current]'s loyalties seem to be elsewhere..."
+ return
+
+ if(!faction.can_become_antag(player))
+ src << "\The [player.current] cannot be \a [faction.faction_role_text]!"
+ return
+
+ if(world.time < player.rev_cooldown)
+ src << "You must wait five seconds between attempts."
+ return
+
+ src << "You are attempting to convert \the [player.current]..."
+ log_admin("[src]([src.ckey]) attempted to convert [player.current].")
+ message_admins("[src]([src.ckey]) attempted to convert [player.current].")
+
+ player.rev_cooldown = world.time+100
+ var/choice = alert(player.current,"Asked by [src]: Do you want to join the [faction.faction_descriptor]?","Join the [faction.faction_descriptor]?","No!","Yes!")
+ if(choice == "Yes!" && faction.add_antagonist_mind(player, 0, faction.faction_role_text, faction.faction_welcome))
+ src << "\The [player.current] joins the [faction.faction_descriptor]!"
+ return
+ if(choice == "No!")
+ player << "You reject this traitorous cause!"
+ src << "\The [player.current] does not support the [faction.faction_descriptor]!"
+
+/mob/living/proc/convert_to_loyalist(mob/M as mob in oview(src))
+ set name = "Convert Recidivist"
+ set category = "Abilities"
+ if(!M.mind)
+ return
+ convert_to_faction(M.mind, loyalists)
\ No newline at end of file
diff --git a/code/game/antagonist/antagonist_place.dm b/code/game/antagonist/antagonist_place.dm
index 1d69aaa96f..db8c74a14f 100644
--- a/code/game/antagonist/antagonist_place.dm
+++ b/code/game/antagonist/antagonist_place.dm
@@ -5,23 +5,20 @@
if(L.name == landmark_id)
starting_locations |= get_turf(L)
-/datum/antagonist/proc/place_all_mobs()
- if(!starting_locations || !starting_locations.len || !current_antagonists || !current_antagonists.len)
- return
- for(var/datum/mind/player in current_antagonists)
- player.current.loc = pick(starting_locations)
-
/datum/antagonist/proc/announce_antagonist_spawn()
+
if(spawn_announcement)
if(announced)
return
announced = 1
- if(spawn_announcement_delay)
- sleep(spawn_announcement_delay)
- if(spawn_announcement_sound)
- command_announcement.Announce("[spawn_announcement]", "[spawn_announcement_title ? spawn_announcement_title : "Priority Alert"]", new_sound = spawn_announcement_sound)
- else
- command_announcement.Announce("[spawn_announcement]", "[spawn_announcement_title ? spawn_announcement_title : "Priority Alert"]")
+ spawn(0)
+ if(spawn_announcement_delay)
+ sleep(spawn_announcement_delay)
+ if(spawn_announcement_sound)
+ command_announcement.Announce("[spawn_announcement]", "[spawn_announcement_title ? spawn_announcement_title : "Priority Alert"]", new_sound = spawn_announcement_sound)
+ else
+ command_announcement.Announce("[spawn_announcement]", "[spawn_announcement_title ? spawn_announcement_title : "Priority Alert"]")
+ return
/datum/antagonist/proc/place_mob(var/mob/living/mob)
if(!starting_locations || !starting_locations.len)
diff --git a/code/game/antagonist/antagonist_update.dm b/code/game/antagonist/antagonist_update.dm
index 0fd5fb2a93..d6be8c9441 100644
--- a/code/game/antagonist/antagonist_update.dm
+++ b/code/game/antagonist/antagonist_update.dm
@@ -19,53 +19,65 @@
/datum/antagonist/proc/update_access(var/mob/living/player)
for(var/obj/item/weapon/card/id/id in player.contents)
- id.name = "[player.real_name]'s ID Card"
- id.registered_name = player.real_name
+ player.set_id_info(id)
+
+/datum/antagonist/proc/clear_indicators(var/datum/mind/recipient)
+ if(!recipient.current || !recipient.current.client)
+ return
+ for(var/image/I in recipient.current.client.images)
+ if(I.icon_state == antag_indicator || (faction_indicator && I.icon_state == faction_indicator))
+ qdel(I)
+
+/datum/antagonist/proc/get_indicator(var/datum/mind/recipient, var/datum/mind/other)
+ if(!antag_indicator || !other.current || !recipient.current)
+ return
+ var/indicator = (faction_indicator && (other in faction_members)) ? faction_indicator : antag_indicator
+ return image('icons/mob/mob.dmi', loc = other.current, icon_state = indicator)
/datum/antagonist/proc/update_all_icons()
if(!antag_indicator)
return
for(var/datum/mind/antag in current_antagonists)
- if(antag.current && antag.current.client)
- for(var/image/I in antag.current.client.images)
- if(I.icon_state == antag_indicator)
- qdel(I)
- for(var/datum/mind/other_antag in current_antagonists)
- if(other_antag.current)
- antag.current.client.images |= image('icons/mob/mob.dmi', loc = other_antag.current, icon_state = antag_indicator)
+ clear_indicators(antag)
+ if(faction_invisible && (antag in faction_members))
+ continue
+ for(var/datum/mind/other_antag in current_antagonists)
+ if(antag.current && antag.current.client)
+ antag.current.client.images |= get_indicator(antag, other_antag)
/datum/antagonist/proc/update_icons_added(var/datum/mind/player)
if(!antag_indicator || !player.current)
return
spawn(0)
+
+ var/give_to_player = (!faction_invisible || !(player in faction_members))
for(var/datum/mind/antag in current_antagonists)
if(!antag.current)
continue
if(antag.current.client)
- antag.current.client.images |= image('icons/mob/mob.dmi', loc = player.current, icon_state = antag_indicator)
+ antag.current.client.images |= get_indicator(antag, player)
+ if(!give_to_player)
+ continue
if(player.current.client)
- player.current.client.images |= image('icons/mob/mob.dmi', loc = antag.current, icon_state = antag_indicator)
+ player.current.client.images |= get_indicator(player, antag)
/datum/antagonist/proc/update_icons_removed(var/datum/mind/player)
if(!antag_indicator || !player.current)
return
spawn(0)
- for(var/datum/mind/antag in current_antagonists)
- if(antag.current)
- if(antag.current.client)
- for(var/image/I in antag.current.client.images)
- if(I.icon_state == antag_indicator && I.loc == player.current)
- qdel(I)
+ clear_indicators(player)
if(player.current && player.current.client)
- for(var/image/I in player.current.client.images)
- if(I.icon_state == antag_indicator)
- qdel(I)
+ for(var/datum/mind/antag in current_antagonists)
+ if(antag.current && antag.current.client)
+ for(var/image/I in antag.current.client.images)
+ if(I.loc == player.current)
+ qdel(I)
/datum/antagonist/proc/update_current_antag_max()
var/main_type
if(ticker && ticker.mode)
- if(ticker.mode.antag_tag && ticker.mode.antag_tag == id)
+ if(ticker.mode.antag_tags && (id in ticker.mode.antag_tags))
main_type = 1
- cur_max = (main_type ? max_antags_round : max_antags)
+ cur_max = (main_type ? hard_cap_round : hard_cap)
if(ticker.mode.antag_scaling_coeff)
cur_max = Clamp((ticker.mode.num_players()/ticker.mode.antag_scaling_coeff), 1, cur_max)
diff --git a/code/game/antagonist/outsider/commando.dm b/code/game/antagonist/outsider/commando.dm
index 560878a3be..135a586b2e 100644
--- a/code/game/antagonist/outsider/commando.dm
+++ b/code/game/antagonist/outsider/commando.dm
@@ -8,6 +8,12 @@ var/datum/antagonist/deathsquad/mercenary/commandos
welcome_text = "You are in the employ of a criminal syndicate hostile to corporate interests."
id_type = /obj/item/weapon/card/id/centcom/ERT
+ hard_cap = 4
+ hard_cap_round = 8
+ initial_spawn_req = 4
+ initial_spawn_target = 6
+
+
/datum/antagonist/deathsquad/mercenary/New()
..(1)
commandos = src
diff --git a/code/game/antagonist/outsider/deathsquad.dm b/code/game/antagonist/outsider/deathsquad.dm
index e01b2a8f3f..052533340b 100644
--- a/code/game/antagonist/outsider/deathsquad.dm
+++ b/code/game/antagonist/outsider/deathsquad.dm
@@ -8,9 +8,13 @@ var/datum/antagonist/deathsquad/deathsquad
welcome_text = "You work in the service of corporate Asset Protection, answering directly to the Board of Directors."
landmark_id = "Commando"
flags = ANTAG_OVERRIDE_JOB | ANTAG_OVERRIDE_MOB | ANTAG_HAS_NUKE | ANTAG_HAS_LEADER
- max_antags = 4
- max_antags_round = 6
default_access = list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage)
+
+ hard_cap = 4
+ hard_cap_round = 8
+ initial_spawn_req = 4
+ initial_spawn_target = 6
+
var/deployed = 0
/datum/antagonist/deathsquad/New(var/no_reference)
diff --git a/code/game/antagonist/outsider/ert.dm b/code/game/antagonist/outsider/ert.dm
index 7675a3cbf8..71278c344a 100644
--- a/code/game/antagonist/outsider/ert.dm
+++ b/code/game/antagonist/outsider/ert.dm
@@ -8,13 +8,16 @@ var/datum/antagonist/ert/ert
role_text_plural = "Emergency Responders"
welcome_text = "As member of the Emergency Response Team, you answer only to your leader and company officials."
leader_welcome_text = "As leader of the Emergency Response Team, you answer only to the Company, and have authority to override the Captain where it is necessary to achieve your mission goals. It is recommended that you attempt to cooperate with the captain where possible, however."
- max_antags = 5
- max_antags_round = 5 // ERT mode?
landmark_id = "Response Team"
id_type = /obj/item/weapon/card/id/centcom/ERT
flags = ANTAG_OVERRIDE_JOB | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER | ANTAG_CHOOSE_NAME
+ hard_cap = 5
+ hard_cap_round = 7
+ initial_spawn_req = 5
+ initial_spawn_target = 7
+
/datum/antagonist/ert/create_default(var/mob/source)
var/mob/living/carbon/human/M = ..()
if(istype(M)) M.age = rand(25,45)
diff --git a/code/game/antagonist/outsider/mercenary.dm b/code/game/antagonist/outsider/mercenary.dm
index 66aab758e0..3c2a276932 100644
--- a/code/game/antagonist/outsider/mercenary.dm
+++ b/code/game/antagonist/outsider/mercenary.dm
@@ -5,15 +5,19 @@ var/datum/antagonist/mercenary/mercs
role_type = BE_OPERATIVE
role_text = "Mercenary"
bantype = "operative"
+ antag_indicator = "synd"
role_text_plural = "Mercenaries"
landmark_id = "Syndicate-Spawn"
leader_welcome_text = "You are the leader of the mercenary strikeforce; hail to the chief. Use :t to speak to your underlings."
welcome_text = "To speak on the strike team's private channel use :t."
flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_HAS_NUKE | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER
- max_antags = 4
- max_antags_round = 6
id_type = /obj/item/weapon/card/id/syndicate
+ hard_cap = 4
+ hard_cap_round = 8
+ initial_spawn_req = 4
+ initial_spawn_target = 6
+
/datum/antagonist/mercenary/New()
..()
mercs = src
@@ -44,14 +48,6 @@ var/datum/antagonist/mercenary/mercs
create_radio(SYND_FREQ, player)
return 1
-/datum/antagonist/mercenary/place_all_mobs()
- var/spawnpos = 1
- for(var/datum/mind/player in current_antagonists)
- player.current.loc = starting_locations[spawnpos]
- spawnpos++
- if(spawnpos > starting_locations.len)
- spawnpos = 1
-
/datum/antagonist/mercenary/create_nuke()
..()
// Create the radio.
diff --git a/code/game/antagonist/outsider/ninja.dm b/code/game/antagonist/outsider/ninja.dm
index f5d8392571..b091e9a55e 100644
--- a/code/game/antagonist/outsider/ninja.dm
+++ b/code/game/antagonist/outsider/ninja.dm
@@ -9,8 +9,12 @@ var/datum/antagonist/ninja/ninjas
landmark_id = "ninjastart"
welcome_text = "You are an elite mercenary assassin of the Spider Clan. You have a variety of abilities at your disposal, thanks to your nano-enhanced cyber armor."
flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_RANDSPAWN | ANTAG_VOTABLE | ANTAG_SET_APPEARANCE
- max_antags = 1
- max_antags_round = 1
+
+ initial_spawn_req = 1
+ initial_spawn_target = 1
+ hard_cap = 1
+ hard_cap_round = 3
+
id_type = /obj/item/weapon/card/id/syndicate
/datum/antagonist/ninja/New()
diff --git a/code/game/antagonist/outsider/raider.dm b/code/game/antagonist/outsider/raider.dm
index 8ac7530e92..f377480a4d 100644
--- a/code/game/antagonist/outsider/raider.dm
+++ b/code/game/antagonist/outsider/raider.dm
@@ -6,11 +6,16 @@ var/datum/antagonist/raider/raiders
role_text = "Raider"
role_text_plural = "Raiders"
bantype = "raider"
+ antag_indicator = "mutineer"
landmark_id = "voxstart"
welcome_text = "Use :H to talk on your encrypted channel."
flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_VOTABLE | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER
- max_antags = 6
- max_antags_round = 10
+
+ hard_cap = 6
+ hard_cap_round = 10
+ initial_spawn_req = 4
+ initial_spawn_target = 6
+
id_type = /obj/item/weapon/card/id/syndicate
// Heist overrides check_victory() and doesn't need victory or loss strings/tags.
diff --git a/code/game/antagonist/outsider/wizard.dm b/code/game/antagonist/outsider/wizard.dm
index 57a00adfdd..af1fc09e8e 100644
--- a/code/game/antagonist/outsider/wizard.dm
+++ b/code/game/antagonist/outsider/wizard.dm
@@ -9,8 +9,12 @@ var/datum/antagonist/wizard/wizards
landmark_id = "wizard"
welcome_text = "You will find a list of available spells in your spell book. Choose your magic arsenal carefully.
In your pockets you will find a teleport scroll. Use it as needed."
flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_VOTABLE | ANTAG_SET_APPEARANCE
- max_antags = 1
- max_antags_round = 1
+
+ hard_cap = 1
+ hard_cap_round = 3
+ initial_spawn_req = 1
+ initial_spawn_target = 1
+
/datum/antagonist/wizard/New()
..()
diff --git a/code/game/antagonist/station/changeling.dm b/code/game/antagonist/station/changeling.dm
index f6307b8ae8..ded3361cd2 100644
--- a/code/game/antagonist/station/changeling.dm
+++ b/code/game/antagonist/station/changeling.dm
@@ -7,7 +7,7 @@
feedback_tag = "changeling_objective"
restricted_jobs = list("AI", "Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain")
- welcome_text = "Use say \":g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them."
+ welcome_text = "Use say \"#g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them."
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
/datum/antagonist/changeling/get_special_objective_text(var/datum/mind/player)
diff --git a/code/game/antagonist/station/cultist.dm b/code/game/antagonist/station/cultist.dm
index f3999535af..20c2bd428d 100644
--- a/code/game/antagonist/station/cultist.dm
+++ b/code/game/antagonist/station/cultist.dm
@@ -22,10 +22,12 @@ var/datum/antagonist/cultist/cult
victory_feedback_tag = "win - cult win"
loss_feedback_tag = "loss - staff stopped the cult"
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
- max_antags = 200 // No upper limit.
- max_antags_round = 200
- var/allow_narsie = 1
+ hard_cap = 5
+ hard_cap_round = 6
+ initial_spawn_req = 4
+ initial_spawn_target = 6
+ var/allow_narsie = 1
var/datum/mind/sacrifice_target
var/list/startwords = list("blood","join","self","hell")
var/list/allwords = list("travel","self","see","hell","blood","join","tech","destroy", "other", "hide")
@@ -104,9 +106,9 @@ var/datum/antagonist/cultist/cult
player.current.visible_message("[player.current] looks like they just reverted to their old faith!")
/datum/antagonist/cultist/add_antagonist(var/datum/mind/player)
- if(!..())
- return
- player << "You catch a glimpse of the Realm of Nar-Sie, the Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of That Which Waits. Assist your new compatriots in their dark dealings. Their goals are yours, and yours are theirs. You serve the Dark One above all else. Bring It back."
+ . = ..()
+ if(.)
+ player << "You catch a glimpse of the Realm of Nar-Sie, the Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of That Which Waits. Assist your new compatriots in their dark dealings. Their goals are yours, and yours are theirs. You serve the Dark One above all else. Bring It back."
/datum/antagonist/cultist/can_become_antag(var/datum/mind/player)
if(!..())
diff --git a/code/game/antagonist/station/highlander.dm b/code/game/antagonist/station/highlander.dm
index 1fd573bf1a..23d816bd97 100644
--- a/code/game/antagonist/station/highlander.dm
+++ b/code/game/antagonist/station/highlander.dm
@@ -6,8 +6,11 @@ var/datum/antagonist/highlander/highlanders
welcome_text = "There can be only one."
id = MODE_HIGHLANDER
flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE //| ANTAG_RANDSPAWN | ANTAG_VOTABLE // Someday...
- max_antags = 5
- max_antags_round = 7
+
+ hard_cap = 5
+ hard_cap_round = 7
+ initial_spawn_req = 3
+ initial_spawn_target = 5
/datum/antagonist/highlander/New()
..()
diff --git a/code/game/antagonist/station/loyalist.dm b/code/game/antagonist/station/loyalist.dm
new file mode 100644
index 0000000000..4b95467691
--- /dev/null
+++ b/code/game/antagonist/station/loyalist.dm
@@ -0,0 +1,46 @@
+var/datum/antagonist/loyalists/loyalists
+
+/datum/antagonist/loyalists
+ id = MODE_LOYALIST
+ role_type = BE_LOYALIST
+ role_text = "Head Loyalist"
+ role_text_plural = "Loyalists"
+ bantype = "loyalist"
+ feedback_tag = "loyalist_objective"
+ antag_indicator = "loyal_head"
+ welcome_text = "You belong to the Company, body and soul. Preserve its interests against the conspirators amongst the crew."
+ victory_text = "The heads of staff remained at their posts! The loyalists win!"
+ loss_text = "The heads of staff did not stop the revolution!"
+ victory_feedback_tag = "win - rev heads killed"
+ loss_feedback_tag = "loss - heads killed"
+ flags = 0
+
+ hard_cap = 2
+ hard_cap_round = 4
+ initial_spawn_req = 2
+ initial_spawn_target = 4
+
+ // Inround loyalists.
+ faction_role_text = "Loyalist"
+ faction_descriptor = "Company"
+ faction_verb = /mob/living/proc/convert_to_loyalist
+ faction_welcome = "Preserve NanoTrasen's interests against the traitorous recidivists amongst the crew. Protect the heads of staff with your life."
+ faction_indicator = "loyal"
+ faction_invisible = 1
+ restricted_jobs = list("AI", "Cyborg")
+
+/datum/antagonist/loyalists/New()
+ ..()
+ loyalists = src
+
+/datum/antagonist/loyalists/create_global_objectives()
+ if(!..())
+ return
+ global_objectives = list()
+ for(var/mob/living/carbon/human/player in mob_list)
+ if(!player.mind || player.stat==2 || !(player.mind.assigned_role in command_positions))
+ continue
+ var/datum/objective/protect/loyal_obj = new
+ loyal_obj.target = player.mind
+ loyal_obj.explanation_text = "Protect [player.real_name], the [player.mind.assigned_role]."
+ global_objectives += loyal_obj
diff --git a/code/game/antagonist/station/renegade.dm b/code/game/antagonist/station/renegade.dm
index 9b275776f8..cd9dd9b83b 100644
--- a/code/game/antagonist/station/renegade.dm
+++ b/code/game/antagonist/station/renegade.dm
@@ -6,30 +6,28 @@ var/datum/antagonist/renegade/renegades
welcome_text = "Your own safety matters above all else, trust no one and kill anyone who gets in your way. However, armed as you are, now would be the perfect time to settle that score or grab that pair of yellow gloves you've been eyeing..."
id = MODE_RENEGADE
flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE
- max_antags = 5
- max_antags_round = 7
+ hard_cap = 5
+ hard_cap_round = 7
+
+ hard_cap = 8
+ hard_cap_round = 12
+ initial_spawn_req = 3
+ initial_spawn_target = 6
var/list/spawn_guns = list(
- /obj/item/weapon/gun/energy/taser,
/obj/item/weapon/gun/energy/gun,
/obj/item/weapon/gun/energy/laser,
/obj/item/weapon/gun/projectile,
/obj/item/weapon/gun/projectile/revolver/detective,
/obj/item/weapon/gun/projectile/automatic/c20r,
- /obj/item/weapon/gun/energy/gun/nuclear,
/obj/item/weapon/gun/projectile/deagle/camo,
/obj/item/weapon/gun/projectile/pistol,
/obj/item/weapon/silencer,
- /obj/item/weapon/gun/energy/lasercannon,
/obj/item/weapon/gun/projectile/shotgun/pump,
/obj/item/weapon/gun/projectile/shotgun/pump/combat,
/obj/item/weapon/gun/projectile/automatic,
/obj/item/weapon/gun/projectile/automatic/mini_uzi,
/obj/item/weapon/gun/energy/crossbow
- //obj/item/weapon/gun/projectile/gyropistol,
- //obj/item/weapon/gun/energy/pulse_rifle,
- //obj/item/weapon/gun/projectile/revolver/mateba,
- //obj/item/weapon/gun/projectile/automatic/l6_saw,
)
/datum/antagonist/renegade/New()
diff --git a/code/game/antagonist/station/revolutionary.dm b/code/game/antagonist/station/revolutionary.dm
index 06819c96ce..f3454cf756 100644
--- a/code/game/antagonist/station/revolutionary.dm
+++ b/code/game/antagonist/station/revolutionary.dm
@@ -3,196 +3,46 @@ var/datum/antagonist/revolutionary/revs
/datum/antagonist/revolutionary
id = MODE_REVOLUTIONARY
role_type = BE_REV
- role_text = "Revolutionary"
+ role_text = "Head Revolutionary"
role_text_plural = "Revolutionaries"
bantype = "revolutionary"
feedback_tag = "rev_objective"
- restricted_jobs = list("Internal Affairs Agent", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
- protected_jobs = list("Security Officer", "Warden", "Detective")
- antag_indicator = "rev"
- welcome_text = "The flash in your possession will help you to persuade the crew to join your cause."
+ antag_indicator = "rev_head"
+ welcome_text = "Down with the capitalists! Down with the Bourgeoise!"
victory_text = "The heads of staff were relieved of their posts! The revolutionaries win!"
loss_text = "The heads of staff managed to stop the revolution!"
victory_feedback_tag = "win - heads killed"
loss_feedback_tag = "loss - rev heads killed"
flags = ANTAG_SUSPICIOUS | ANTAG_VOTABLE
- max_antags = 200 // No upper limit.
- max_antags_round = 200
- var/list/head_revolutionaries = list()
+ hard_cap = 2
+ hard_cap_round = 4
+ initial_spawn_req = 2
+ initial_spawn_target = 4
+
+ //Inround revs.
+ faction_role_text = "Revolutionary"
+ faction_descriptor = "Revolution"
+ faction_verb = /mob/living/proc/convert_to_rev
+ faction_welcome = "Help the cause overturn the ruling class. Do not harm your fellow freedom fighters."
+ faction_indicator = "rev"
+ faction_invisible = 1
+
+ restricted_jobs = list("Internal Affairs Agent", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
+ protected_jobs = list("Security Officer", "Warden", "Detective")
/datum/antagonist/revolutionary/New()
..()
revs = src
-/datum/antagonist/revolutionary/is_antagonist(var/datum/mind/player)
- if(..() || (player in head_revolutionaries))
- return 1
- return 0
-
-/datum/antagonist/revolutionary/equip(mob/living/carbon/human/mob)
-
- if(!..())
- return 0
-
- if(!config.rp_rev)
- mob.verbs |= /mob/living/carbon/human/proc/convert_to_rev
- return
-
- var/obj/item/device/flash/T = new(mob)
-
- var/list/slots = list (
- "backpack" = slot_in_backpack,
- "left pocket" = slot_l_store,
- "right pocket" = slot_r_store,
- "left hand" = slot_l_hand,
- "right hand" = slot_r_hand,
- )
- mob.equip_in_one_of_slots(T, slots)
-
-/*
-datum/antagonist/revolutionary/finalize(var/datum/mind/target)
- if(target)
- return ..(target)
- current_antagonists |= head_revolutionaries
- create_global_objectives()
- ..()
-
-/datum/antagonist/revolutionary/get_additional_check_antag_output(var/datum/admins/caller)
- return ..() //Todo
-
- Rev extras:
- dat += "
| Revolutionaries | |
"
- for(var/datum/mind/N in ticker.mode.head_revolutionaries)
- var/mob/M = N.current
- if(!M)
- dat += "| Head Revolutionary not found! |
"
- else
- dat += "| [M.real_name] (Leader)[M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""] | "
- dat += "PM |
"
- for(var/datum/mind/N in ticker.mode.revolutionaries)
- var/mob/M = N.current
- if(M)
- dat += "| [M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""] | "
- dat += "PM |
"
- dat += "
| Target(s) | | Location |
"
- for(var/datum/mind/N in ticker.mode.get_living_heads())
- var/mob/M = N.current
- if(M)
- dat += "| [M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""] | "
- dat += "PM | "
- var/turf/mob_loc = get_turf(M)
- dat += "[mob_loc.loc] |
"
- else
- dat += "| Head not found! |
"
-*/
-
/datum/antagonist/revolutionary/create_global_objectives()
if(!..())
return
-
global_objectives = list()
-
- for(var/datum/mind/head_mind in get_living_heads())
- var/datum/objective/mutiny/rev_obj = new
- rev_obj.target = head_mind
- rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]."
+ for(var/mob/living/carbon/human/player in mob_list)
+ if(!player.mind || player.stat==2 || !(player.mind.assigned_role in command_positions))
+ continue
+ var/datum/objective/rev/rev_obj = new
+ rev_obj.target = player.mind
+ rev_obj.explanation_text = "Assassinate, capture or convert [player.real_name], the [player.mind.assigned_role]."
global_objectives += rev_obj
-
-/datum/antagonist/revolutionary/print_player_summary()
-
- current_antagonists |= head_revolutionaries
- if(!current_antagonists.len)
- return
-
- var/text = "
The [head_revolutionaries.len == 1 ? "Head Revolutionary was" : "Head Revolutionaries were"]:"
- for(var/datum/mind/ply in head_revolutionaries)
- text += "
[ply.name]"
- world << text
-
- ..()
-
- var/list/heads = list()
- for(var/mob/player in mob_list)
- if(player.mind && (player.mind.assigned_role in command_positions))
- heads += player.mind
-
- text = "The heads of staff were:"
- for(var/datum/mind/head in heads)
- text += "
[head.key] was [head.name] ("
- if(head.current)
- if(head.current.stat == DEAD)
- text += "died"
- else if(isNotStationLevel(head.current.z))
- text += "fled the station"
- else
- text += "survived the revolution"
- if(head.current.real_name != head.name)
- text += " as [head.current.real_name]"
- else
- text += "body destroyed"
- text += ")"
- world << text
-
-// This is a total redefine because headrevs are greeted differently to subrevs.
-/datum/antagonist/revolutionary/add_antagonist(var/datum/mind/player, var/ignore_role)
- if((player in current_antagonists) || (player in head_revolutionaries))
- return 0
- if(!can_become_antag(player, ignore_role))
- return 0
- current_antagonists |= player
- player.current << "You are a Revolutionary!"
- player.current << "Help the cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them overturn the ruling class!"
- player.special_role = "Revolutionary"
- create_objectives(player)
- show_objectives(player)
- update_icons_added(player)
- return 1
-
-/datum/antagonist/revolutionary/remove_antagonist(datum/mind/player, var/show_message, var/implanted)
- if(!..())
- return
-
- if(player in head_revolutionaries)
- return
-
- if(istype(player.current, /mob/living/carbon/brain))
- player.current << "The frame's firmware detects and deletes your neural reprogramming! You remember nothing from the moment you were flashed until now."
- if(show_message)
- player.current.visible_message("The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.")
- else
- if(implanted)
- player.current << "The nanobots in the loyalty implant remove all thoughts about being a revolutionary. Get back to work!"
- else
- player.current << "You have been brainwashed! You are no longer a revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you..."
- if(show_message)
- player.current.visible_message("[player.current] looks like they just remembered their real allegiance!")
-
-// Used by RP-rev.
-/mob/living/carbon/human/proc/convert_to_rev(mob/M as mob in oview(src))
- set name = "Convert Bourgeoise"
- set category = "Abilities"
-
- if(revs.is_antagonist(M.mind))
- src << "\The [M] already serves the revolution."
- return
- if(!revs.can_become_antag(M.mind))
- src << "\The [M] cannot be a revolutionary!"
-
- if(world.time < M.mind.rev_cooldown)
- src << "You must wait five seconds between attempts."
- return
-
- src << "You are attempting to convert \the [M]..."
- log_admin("[src]([src.ckey]) attempted to convert [M].")
- message_admins("[src]([src.ckey]) attempted to convert [M].")
-
- var/choice = alert(M,"Asked by [src]: Do you want to join the revolution?","Join the revolution?","No!","Yes!")
- if(choice == "Yes!")
- M << "You join the revolution!"
- src << "[M] joins the revolution!"
- revs.add_antagonist(M.mind, 0, 0, 1)
- else if(choice == "No!")
- M << "You reject this traitorous cause!"
- src << "\The [M] does not support the revolution!"
- M.mind.rev_cooldown = world.time+50
\ No newline at end of file
diff --git a/code/game/antagonist/station/rogue_ai.dm b/code/game/antagonist/station/rogue_ai.dm
index f19edb2807..a3e609e55d 100644
--- a/code/game/antagonist/station/rogue_ai.dm
+++ b/code/game/antagonist/station/rogue_ai.dm
@@ -11,8 +11,10 @@ var/datum/antagonist/rogue_ai/malf
victory_text = "The AI has taken control of all of the station's systems."
loss_text = "The AI has been shut down!"
flags = ANTAG_VOTABLE | ANTAG_OVERRIDE_MOB | ANTAG_OVERRIDE_JOB | ANTAG_CHOOSE_NAME
- max_antags = 1
- max_antags_round = 1
+ hard_cap = 1
+ hard_cap_round = 1
+ initial_spawn_req = 1
+ initial_spawn_target = 1
/datum/antagonist/rogue_ai/New()
diff --git a/code/game/antagonist/station/traitor.dm b/code/game/antagonist/station/traitor.dm
index a4f14dccf8..6e9ed32b9a 100644
--- a/code/game/antagonist/station/traitor.dm
+++ b/code/game/antagonist/station/traitor.dm
@@ -1,12 +1,10 @@
var/datum/antagonist/traitor/traitors
+// Inherits most of its vars from the base datum.
/datum/antagonist/traitor
id = MODE_TRAITOR
- restricted_jobs = list("Cyborg")//They are part of the AI if he is traitor so are they, they use to get double chances
- protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Captain")//AI", Currently out of the list as malf does not work for shit
+ protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Captain")
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
- max_antags = 200 // No upper limit.
- max_antags_round = 200
/datum/antagonist/traitor/New()
..()
@@ -139,9 +137,9 @@ var/datum/antagonist/traitor/traitors
if(istype(R,/obj/item/device/radio))
// generate list of radio freqs
var/obj/item/device/radio/target_radio = R
- var/freq = 1441
+ var/freq = PUBLIC_LOW_FREQ
var/list/freqlist = list()
- while (freq <= 1489)
+ while (freq <= PUBLIC_HIGH_FREQ)
if (freq < 1451 || freq > PUB_FREQ)
freqlist += freq
freq += 2
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index 50f6c1ccf7..912dd86797 100755
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -98,6 +98,7 @@ var/list/ghostteleportlocs = list()
icon_state = "space"
requires_power = 1
always_unpowered = 1
+ lighting_use_dynamic = 1
power_light = 0
power_equip = 0
power_environ = 0
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 527b4dea61..07b3dcacc5 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -18,6 +18,11 @@
power_equip = 0
power_environ = 0
+ if(lighting_use_dynamic)
+ luminosity = 0
+ else
+ luminosity = 1
+
..()
/area/proc/initialize()
@@ -266,8 +271,8 @@ var/list/mob/living/forced_ambiance_list = new
for(var/mob/M in A)
if(has_gravity)
- thunk(M)
- M.update_floating( M.Check_Dense_Object() )
+ thunk(M)
+ M.update_floating( M.Check_Dense_Object() )
/area/proc/thunk(mob)
if(istype(get_turf(mob), /turf/space)) // Can't fall onto nothing.
diff --git a/code/game/gamemodes/calamity/calamity.dm b/code/game/gamemodes/calamity/calamity.dm
index d8872bbbff..4f7b9ab49d 100644
--- a/code/game/gamemodes/calamity/calamity.dm
+++ b/code/game/gamemodes/calamity/calamity.dm
@@ -18,7 +18,7 @@
for(var/antag_id in all_antag_types)
if(i > grab_antags)
break
- additional_antag_types |= antag_id
+ antag_tags |= antag_id
i++
..()
diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm
index 02545bf8c7..ba82a064f6 100644
--- a/code/game/gamemodes/changeling/changeling.dm
+++ b/code/game/gamemodes/changeling/changeling.dm
@@ -1,5 +1,4 @@
/datum/game_mode/changeling
- antag_tag = MODE_CHANGELING
name = "changeling"
round_description = "There are alien changelings on the station. Do not let the changelings succeed!"
extended_round_description = "Life always finds a way. However, life can sometimes take a more disturbing route. \
@@ -17,3 +16,4 @@
required_enemies = 1
end_on_antag_death = 0
antag_scaling_coeff = 10
+ antag_tags = list(MODE_CHANGELING)
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index 4f03fd0b90..c3ffef61bb 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -7,4 +7,4 @@
required_players_secret = 15
required_enemies = 3
end_on_antag_death = 0
- antag_tag = MODE_CULTIST
+ antag_tags = list(MODE_CULTIST)
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 00f90f336c..c4eea26004 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -1,25 +1,5 @@
var/global/antag_add_failed // Used in antag type voting.
var/global/list/additional_antag_types = list()
-///////////////////////////////////
-//Keeps track of all living heads//
-///////////////////////////////////
-/proc/get_living_heads()
- var/list/heads = list()
- for(var/mob/living/carbon/human/player in mob_list)
- if(player.stat!=2 && player.mind && (player.mind.assigned_role in command_positions))
- heads += player.mind
- return heads
-
-/*
- * GAMEMODES (by Rastaf0)
- *
- * In the new mode system all special roles are fully supported.
- * You can have proper wizards/traitors/changelings/cultists during any mode.
- * Only two things really depends on gamemode:
- * 1. Starting roles, equipment and preparations
- * 2. Conditions of finishing the round.
- *
- */
/datum/game_mode
var/name = "invalid"
@@ -40,11 +20,12 @@ var/global/list/additional_antag_types = list()
var/shuttle_delay = 1 // Shuttle transit time is multiplied by this.
var/auto_recall_shuttle = 0 // Will the shuttle automatically be recalled?
- var/antag_tag // First (main) antag template to spawn.
+ var/list/antag_tags = list() // Core antag templates to spawn.
var/list/antag_templates // Extra antagonist types to include.
var/list/latejoin_templates = list()
var/round_autoantag = 0 // Will this round attempt to periodically spawn more antagonists?
var/antag_scaling_coeff = 5 // Coefficient for scaling max antagonists to player count.
+ var/require_all_templates = 0 // Will only start if all templates are checked and can spawn.
var/station_was_nuked = 0 // See nuclearbomb.dm and malfunction.dm.
var/explosion_in_progress = 0 // Sit back and relax
@@ -54,6 +35,13 @@ var/global/list/additional_antag_types = list()
var/event_delay_mod_moderate // Modifies the timing of random events.
var/event_delay_mod_major // As above.
+/datum/game_mode/New()
+ ..()
+ // Enforce some formatting.
+ // This will probably break something.
+ name = capitalize(lowertext(name))
+ config_tag = lowertext(config_tag)
+
/datum/game_mode/Topic(href, href_list[])
if(..())
return
@@ -79,18 +67,18 @@ var/global/list/additional_antag_types = list()
shuttle_delay = choice
if("antag_scaling")
choice = input("Enter a new antagonist cap scaling coefficient.") as num
- if(!choice || choice < 0 || choice > 100)
+ if(isnull(choice) || choice < 0 || choice > 100)
return
antag_scaling_coeff = choice
if("event_modifier_moderate")
choice = input("Enter a new moderate event time modifier.") as num
- if(!choice || choice < 0 || choice > 100)
+ if(isnull(choice) || choice < 0 || choice > 100)
return
event_delay_mod_moderate = choice
refresh_event_modifiers()
if("event_modifier_severe")
choice = input("Enter a new moderate event time modifier.") as num
- if(!choice || choice < 0 || choice > 100)
+ if(isnull(choice) || choice < 0 || choice > 100)
return
event_delay_mod_major = choice
refresh_event_modifiers()
@@ -104,7 +92,7 @@ var/global/list/additional_antag_types = list()
usr.client.debug_variables(antag)
message_admins("Admin [key_name_admin(usr)] is debugging the [antag.role_text] template.")
else if(href_list["remove_antag_type"])
- if(antag_tag && href_list["remove_antag_type"] == antag_tag)
+ if(antag_tags && (href_list["remove_antag_type"] in antag_tags))
usr << "Cannot remove core mode antag type."
return
var/datum/antagonist/antag = all_antag_types[href_list["remove_antag_type"]]
@@ -118,14 +106,15 @@ var/global/list/additional_antag_types = list()
return
var/datum/antagonist/antag = all_antag_types[choice]
if(antag)
- additional_antag_types |= antag
+ ticker.mode.antag_templates |= antag
message_admins("Admin [key_name_admin(usr)] added [antag.role_text] template to game mode.")
// I am very sure there's a better way to do this, but I'm not sure what it might be. ~Z
- for(var/datum/admins/admin in world)
- if(usr.client == admin.owner)
- admin.show_game_mode(usr)
- return
+ spawn(1)
+ for(var/datum/admins/admin in world)
+ if(usr.client == admin.owner)
+ admin.show_game_mode(usr)
+ return
/datum/game_mode/proc/announce() //to be called when round starts
world << "The current game mode is [capitalize(name)]!"
@@ -166,15 +155,23 @@ var/global/list/additional_antag_types = list()
if(!(antag_templates && antag_templates.len))
return 1
- var/datum/antagonist/main_antags = antag_templates[1]
- var/list/potential
- if(main_antags.flags & ANTAG_OVERRIDE_JOB)
- potential = main_antags.pending_antagonists
- else
- potential = main_antags.candidates
-
- if(potential.len >= required_enemies)
- return 1
+ var/enemy_count = 0
+ if(antag_tags && antag_tags.len)
+ for(var/antag_tag in antag_tags)
+ var/datum/antagonist/antag = all_antag_types[antag_tag]
+ if(!antag)
+ continue
+ var/list/potential = list()
+ if(antag.flags & ANTAG_OVERRIDE_JOB)
+ potential = antag.pending_antagonists
+ else
+ potential = antag.candidates
+ if(islist(potential))
+ if(require_all_templates && potential.len < antag.initial_spawn_req)
+ return 0
+ enemy_count += potential.len
+ if(enemy_count >= required_enemies)
+ return 1
return 0
/datum/game_mode/proc/refresh_event_modifiers()
@@ -471,11 +468,13 @@ var/global/list/additional_antag_types = list()
if(!config.traitor_scaling)
antag_scaling_coeff = 0
- if(antag_tag)
+ if(antag_tags && antag_tags.len)
antag_templates = list()
- var/datum/antagonist/antag = all_antag_types[antag_tag]
- if(antag)
- antag_templates |= antag
+ for(var/antag_tag in antag_tags)
+ var/datum/antagonist/antag = all_antag_types[antag_tag]
+ if(antag)
+ antag_templates |= antag
+
if(additional_antag_types && additional_antag_types.len)
if(!antag_templates)
antag_templates = list()
@@ -484,15 +483,6 @@ var/global/list/additional_antag_types = list()
if(antag)
antag_templates |= antag
- /*
- if(antag_templates && antag_templates.len)
- for(var/datum/antagonist/antag in antag_templates)
- if(antag.flags & (ANTAG_OVERRIDE_JOB|ANTAG_RANDSPAWN))
- continue
- antag_templates -= antag
- world << "[antag.role_text_plural] are invalid for additional roundtype antags!"
- */
-
newscaster_announcements = pick(newscaster_standard_feeds)
/datum/game_mode/proc/check_victory()
diff --git a/code/game/gamemodes/game_mode_latespawn.dm b/code/game/gamemodes/game_mode_latespawn.dm
index 9af3524144..f849f7133d 100644
--- a/code/game/gamemodes/game_mode_latespawn.dm
+++ b/code/game/gamemodes/game_mode_latespawn.dm
@@ -1,7 +1,12 @@
+/datum/game_mode/var/next_spawn = 0
+/datum/game_mode/var/min_autotraitor_delay = 4200 // Approx 7 minutes.
+/datum/game_mode/var/max_autotraitor_delay = 12000 // Approx 20 minutes.
+
/datum/game_mode/proc/get_usable_templates(var/list/supplied_templates)
var/list/usable_templates = list()
for(var/datum/antagonist/A in supplied_templates)
if(A.can_late_spawn())
+ message_admins("AUTO[uppertext(name)]: [A.id] selected for spawn attempt.")
usable_templates |= A
return usable_templates
@@ -21,23 +26,27 @@
if(emergency_shuttle.departed || !round_autoantag)
return
- if(!prob(get_antag_prob()))
+ if(world.time < next_spawn)
return
+ message_admins("AUTO[uppertext(name)]: Attempting spawn.")
+
var/list/usable_templates
if(latejoin_only && latejoin_templates.len)
usable_templates = get_usable_templates(latejoin_templates)
- else if (antag_templates.len)
+ else if (antag_templates && antag_templates.len)
usable_templates = get_usable_templates(antag_templates)
else
+ message_admins("AUTO[uppertext(name)]: Failed to find configured mode spawn templates, please disable auto-antagonists until one is added.")
+ round_autoantag = 0
return
- if(usable_templates.len)
- var/datum/antagonist/spawn_antag = pick(usable_templates)
- spawn_antag.attempt_late_spawn(player)
-/datum/game_mode/proc/get_antag_prob()
- var/player_count = 0
- for(var/mob/living/M in mob_list)
- if(M.client)
- player_count += 1
- return min(100,max(0,(player_count - 5 * 10) * 5))
\ No newline at end of file
+ while(usable_templates.len)
+ var/datum/antagonist/spawn_antag = pick(usable_templates)
+ usable_templates -= spawn_antag
+ if(spawn_antag.attempt_late_spawn(player))
+ message_admins("AUTO[uppertext(name)]: Attempting to latespawn [spawn_antag.id]. ([spawn_antag.get_antag_count()]/[spawn_antag.cur_max])")
+ next_spawn = world.time + rand(min_autotraitor_delay, max_autotraitor_delay)
+ return
+ message_admins("AUTO[uppertext(name)]: Failed to proc a viable spawn template.")
+ next_spawn = world.time + rand(min_autotraitor_delay, max_autotraitor_delay)
diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
index 614d181795..bb8abe6757 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/game/gamemodes/gameticker.dm
@@ -69,33 +69,34 @@ var/global/datum/controller/gameticker/ticker
//Create and announce mode
if(master_mode=="secret")
src.hide_mode = 1
- var/list/datum/game_mode/runnable_modes
- var/mode_started
+
+ var/list/runnable_modes = config.get_runnable_modes()
if((master_mode=="random") || (master_mode=="secret"))
- runnable_modes = config.get_runnable_modes()
- if (runnable_modes.len==0)
+ if(!runnable_modes.len)
current_state = GAME_STATE_PREGAME
world << "Unable to choose playable game mode. Reverting to pre-game lobby."
return 0
if(secret_force_mode != "secret")
- var/datum/game_mode/M = config.pick_mode(secret_force_mode)
- if(M.can_start())
- mode_started = 1
- src.mode = config.pick_mode(secret_force_mode)
- job_master.ResetOccupations()
+ src.mode = config.pick_mode(secret_force_mode)
if(!src.mode)
- src.mode = pickweight(runnable_modes)
- if(src.mode)
- var/mtype = src.mode.type
- src.mode = new mtype
+ var/list/weighted_modes = list()
+ for(var/datum/game_mode/GM in runnable_modes)
+ weighted_modes[GM.config_tag] = config.probabilities[GM.config_tag]
+ src.mode = gamemode_cache[pickweight(weighted_modes)]
else
src.mode = config.pick_mode(master_mode)
- src.mode.pre_setup()
+ if(!src.mode)
+ current_state = GAME_STATE_PREGAME
+ world << "Serious error in mode setup! Reverting to pre-game lobby."
+ return 0
+ job_master.ResetOccupations()
+ src.mode.create_antagonists()
+ src.mode.pre_setup()
job_master.DivideOccupations() // Apparently important for new antagonist system to register specific job antags properly.
- if(!mode_started && !src.mode.can_start())
+ if(!src.mode.can_start())
world << "Unable to start [mode.name]. Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby."
current_state = GAME_STATE_PREGAME
mode.fail_setup()
@@ -104,12 +105,14 @@ var/global/datum/controller/gameticker/ticker
return 0
if(hide_mode)
- var/list/modes = new
- for (var/datum/game_mode/M in runnable_modes)
- modes+=M.name
- modes = sortList(modes)
world << "The current game mode is - Secret!"
- world << "Possibilities: [english_list(modes)]"
+ if(runnable_modes.len)
+ var/list/tmpmodes = new
+ for (var/datum/game_mode/M in runnable_modes)
+ tmpmodes+=M.name
+ tmpmodes = sortList(tmpmodes)
+ if(tmpmodes.len)
+ world << "Possibilities: [english_list(tmpmodes)]"
else
src.mode.announce()
@@ -153,8 +156,6 @@ var/global/datum/controller/gameticker/ticker
processScheduler.start()
- for(var/obj/multiz/ladder/L in world) L.connect() //Lazy hackfix for ladders. TODO: move this to an actual controller. ~ Z
-
if(config.sql_enabled)
statistic_cycle() // Polls population totals regularly and stores them in an SQL DB -- TLE
diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm
index 032d96d6fd..f0a6ece909 100644
--- a/code/game/gamemodes/heist/heist.dm
+++ b/code/game/gamemodes/heist/heist.dm
@@ -5,14 +5,18 @@ VOX HEIST ROUNDTYPE
var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' objective. Clumsy, rewrite sometime.
/datum/game_mode/heist
- antag_tag = MODE_RAIDER
name = "heist"
config_tag = "heist"
required_players = 15
required_players_secret = 25
required_enemies = 4
round_description = "An unidentified bluespace signature has slipped past the Icarus and is approaching the station!"
+<<<<<<< HEAD
end_on_antag_death = 0
+=======
+ end_on_antag_death = 1
+ antag_tags = list(MODE_RAIDER)
+>>>>>>> 25638218325f612b029a8c37cc802b9abbab6d92
/datum/game_mode/heist/check_finished()
if(!..())
diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm
index b528016898..ea98f32558 100644
--- a/code/game/gamemodes/malfunction/malfunction.dm
+++ b/code/game/gamemodes/malfunction/malfunction.dm
@@ -8,4 +8,4 @@
required_enemies = 1
end_on_antag_death = 0
auto_recall_shuttle = 0
- antag_tag = MODE_MALFUNCTION
+ antag_tags = list(MODE_MALFUNCTION)
diff --git a/code/game/gamemodes/mixed/bughunt.dm b/code/game/gamemodes/mixed/bughunt.dm
new file mode 100644
index 0000000000..cfdb25c9a5
--- /dev/null
+++ b/code/game/gamemodes/mixed/bughunt.dm
@@ -0,0 +1,13 @@
+/datum/game_mode/bughunt
+ name = "Bughunt"
+ round_description = "A mercenary strike force is approaching the station to eradicate a xenomorph infestation!"
+ config_tag = "bughunt"
+ required_players = 15
+ required_players_secret = 25
+ required_enemies = 1
+ end_on_antag_death = 1
+ antag_tags = list(MODE_XENOMORPH, MODE_DEATHSQUAD)
+ auto_recall_shuttle = 1
+ ert_disabled = 1
+ require_all_templates = 1
+ votable = 0
\ No newline at end of file
diff --git a/code/game/gamemodes/mixed/conflux.dm b/code/game/gamemodes/mixed/conflux.dm
new file mode 100644
index 0000000000..2d8753ce1a
--- /dev/null
+++ b/code/game/gamemodes/mixed/conflux.dm
@@ -0,0 +1,12 @@
+/datum/game_mode/conflux
+ name = "conflux"
+ round_description = "A space wizard and a cult have invaded the station!"
+ extended_round_description = "Cultists and wizards spawn during this round."
+ config_tag = "conflux"
+ required_players = 15
+ required_players_secret = 15
+ required_enemies = 5
+ end_on_antag_death = 1
+ antag_tags = list(MODE_WIZARD, MODE_CULTIST)
+ require_all_templates = 1
+ votable = 0
\ No newline at end of file
diff --git a/code/game/gamemodes/mixed/infestation.dm b/code/game/gamemodes/mixed/infestation.dm
new file mode 100644
index 0000000000..71e9ebe180
--- /dev/null
+++ b/code/game/gamemodes/mixed/infestation.dm
@@ -0,0 +1,16 @@
+/datum/game_mode/infestation
+ name = "infestation"
+ round_description = "There's something in the walls!"
+ extended_round_description = "Two alien antagonists (Xenomorphs, Cortical Borers or Changelings) may spawn during this round."
+ config_tag = "infestation"
+ required_players = 15
+ required_enemies = 5
+ end_on_antag_death = 1
+ antag_tags = list(MODE_BORER, MODE_XENOMORPH, MODE_CHANGELING)
+ require_all_templates = 1
+ votable = 0
+
+/datum/game_mode/infestation/create_antagonists()
+ // Two of the three.
+ antag_tags -= pick(antag_tags)
+ ..()
\ No newline at end of file
diff --git a/code/game/gamemodes/mixed/paranoia.dm b/code/game/gamemodes/mixed/paranoia.dm
new file mode 100644
index 0000000000..7c3e903b14
--- /dev/null
+++ b/code/game/gamemodes/mixed/paranoia.dm
@@ -0,0 +1,12 @@
+/datum/game_mode/paranoia
+ name = "paranoia"
+ round_description = "The AI has malfunctioned, and subversive elements infest the crew..."
+ extended_round_description = "Rampant AIs, renegades and changelings spawn in this mode."
+ config_tag = "paranoia"
+ required_players = 2
+ required_players_secret = 7
+ required_enemies = 1
+ end_on_antag_death = 1
+ require_all_templates = 1
+ votable = 0
+ antag_tags = list(MODE_MALFUNCTION, MODE_RENEGADE, MODE_CHANGELING)
diff --git a/code/game/gamemodes/mixed/traitorling.dm b/code/game/gamemodes/mixed/traitorling.dm
new file mode 100644
index 0000000000..12527f0877
--- /dev/null
+++ b/code/game/gamemodes/mixed/traitorling.dm
@@ -0,0 +1,11 @@
+/datum/game_mode/traitorling
+ name = "traitorling"
+ round_description = "There are traitors and alien changelings on the station. Do not let the changelings succeed!"
+ extended_round_description = "Traitors and changelings both spawn during this mode."
+ config_tag = "traitorling"
+ required_players = 10
+ required_players_secret = 15
+ required_enemies = 5
+ end_on_antag_death = 1
+ require_all_templates = 1
+ antag_tags = list(MODE_CHANGELING, MODE_TRAITOR)
diff --git a/code/game/gamemodes/mixed/uprising.dm b/code/game/gamemodes/mixed/uprising.dm
new file mode 100644
index 0000000000..005d9dce91
--- /dev/null
+++ b/code/game/gamemodes/mixed/uprising.dm
@@ -0,0 +1,12 @@
+/datum/game_mode/uprising
+ name = "uprising"
+ config_tag = "uprising"
+ round_description = "Some crewmembers are attempting to start a revolution while a cult plots in the shadows!"
+ extended_round_description = "Cultists and revolutionaries spawn in this round."
+ required_players = 15
+ required_players_secret = 15
+ required_enemies = 3
+ end_on_antag_death = 1
+ antag_tags = list(MODE_REVOLUTIONARY, MODE_LOYALIST, MODE_CULTIST)
+ require_all_templates = 1
+ votable = 0
\ No newline at end of file
diff --git a/code/game/gamemodes/ninja/ninja.dm b/code/game/gamemodes/ninja/ninja.dm
index c6a0ce5b2f..7a4981c0fa 100644
--- a/code/game/gamemodes/ninja/ninja.dm
+++ b/code/game/gamemodes/ninja/ninja.dm
@@ -8,9 +8,9 @@
through the defenses of the station with technological capabilities eons ahead of your time. They can avoid \
the omniscience of the AI and rival the most hardened weapons your station is capable of. Tread lightly and \
only hope this unknown assassin isn't here for you."
- antag_tag = MODE_NINJA
config_tag = "ninja"
required_players = 1
required_players_secret = 10
required_enemies = 1
end_on_antag_death = 0
+ antag_tags = list(MODE_NINJA)
\ No newline at end of file
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index b45eab261c..e3ab6b151b 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -12,10 +12,9 @@ var/list/nuke_disks = list()
required_players_secret = 25 // 25 players - 5 players to be the nuke ops = 20 players remaining
required_enemies = 1
end_on_antag_death = 0
- antag_tag = MODE_MERCENARY
-
var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station
var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level
+ antag_tags = list(MODE_MERCENARY)
//delete all nuke disks not on a station zlevel
/datum/game_mode/nuclear/proc/check_nuke_disks()
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index 51937d6f95..ed7c6ac871 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -64,69 +64,6 @@ datum/objective/assassinate
return 1
-
-datum/objective/mutiny
- find_target()
- ..()
- if(target && target.current)
- explanation_text = "Assassinate [target.current.real_name], the [target.assigned_role]."
- else
- explanation_text = "Free Objective"
- return target
-
-
- find_target_by_role(role, role_type=0)
- ..(role, role_type)
- if(target && target.current)
- explanation_text = "Assassinate [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]."
- else
- explanation_text = "Free Objective"
- return target
-
- check_completion()
- if(target && target.current)
- if(target.current.stat == DEAD || !ishuman(target.current) || !target.current.ckey)
- return 1
- var/turf/T = get_turf(target.current)
- if(T && isNotStationLevel(T.z)) //If they leave the station they count as dead for this
- return 2
- return 0
- return 1
-
-datum/objective/mutiny/rp
- find_target()
- ..()
- if(target && target.current)
- explanation_text = "Assassinate, capture or convert [target.current.real_name], the [target.assigned_role]."
- else
- explanation_text = "Free Objective"
- return target
-
-
- find_target_by_role(role, role_type=0)
- ..(role, role_type)
- if(target && target.current)
- explanation_text = "Assassinate, capture or convert [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]."
- else
- explanation_text = "Free Objective"
- return target
-
- // less violent rev objectives
- check_completion()
- var/rval = 1
- if(target && target.current)
- //assume that only carbon mobs can become rev heads for now
- if(target.current.stat == DEAD || target.current:handcuffed || !ishuman(target.current))
- return 1
- // Check if they're converted
- if(target in revs.head_revolutionaries)
- return 1
- var/turf/T = get_turf(target.current)
- if(T && isNotStationLevel(T.z)) //If they leave the station they count as dead for this
- rval = 2
- return 0
- return rval
-
datum/objective/anti_revolution/execute
find_target()
..()
@@ -933,3 +870,38 @@ datum/objective/heist/salvage
/datum/objective/cult/sacrifice/check_completion()
return (target && cult && !cult.sacrificed.Find(target))
+
+/datum/objective/rev/find_target()
+ ..()
+ if(target && target.current)
+ explanation_text = "Assassinate, capture or convert [target.current.real_name], the [target.assigned_role]."
+ else
+ explanation_text = "Free Objective"
+ return target
+
+
+/datum/objective/rev/find_target_by_role(role, role_type=0)
+ ..(role, role_type)
+ if(target && target.current)
+ explanation_text = "Assassinate, capture or convert [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]."
+ else
+ explanation_text = "Free Objective"
+ return target
+
+/datum/objective/rev/check_completion()
+ var/rval = 1
+ if(target && target.current)
+ var/mob/living/carbon/human/H = target.current
+ if(!istype(H))
+ return 1
+ if(H.stat == DEAD || H.restrained())
+ return 1
+ // Check if they're converted
+ if(target in revs.current_antagonists)
+ return 1
+ var/turf/T = get_turf(H)
+ if(T && isNotStationLevel(T.z)) //If they leave the station they count as dead for this
+ rval = 2
+ return 0
+ return rval
+
diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm
index a370bc1480..b7a38fd8d5 100644
--- a/code/game/gamemodes/revolution/revolution.dm
+++ b/code/game/gamemodes/revolution/revolution.dm
@@ -2,47 +2,12 @@
name = "Revolution"
config_tag = "revolution"
round_description = "Some crewmembers are attempting to start a revolution!"
- extended_round_description = "Revolutionaries - Kill the Captain, HoP, HoS, CE, RD and CMO. Convert other crewmembers (excluding the heads of staff, and security officers) to your cause by flashing them. Protect your leaders.
\nPersonnel - Protect the heads of staff. Kill the leaders of the revolution, and brainwash the other revolutionaries (by beating them in the head)."
+ extended_round_description = "Revolutionaries - Remove the heads of staff from power. Convert other crewmembers to your cause using the 'Convert Bourgeoise' verb. Protect your leaders."
required_players = 4
required_players_secret = 15
required_enemies = 3
auto_recall_shuttle = 0 //NO THANKS
end_on_antag_death = 0
shuttle_delay = 3
- antag_tag = MODE_REVOLUTIONARY
-
-/datum/game_mode/revolution/New()
- if(config && config.rp_rev)
- extended_round_description = "Revolutionaries - Remove the heads of staff from power. Convert other crewmembers to your cause using the 'Convert Bourgeoise' verb. Protect your leaders."
-
-/datum/game_mode/revolution/send_intercept()
-
- ..()
-
- if(config.announce_revheads)
- spawn(54000)
- var/intercepttext = ""
- command_announcement.Announce("Summary downloaded and printed out at all communications consoles.", "Local agitators have been determined.")
- intercepttext = "Cent. Com. Update Requested status information:
"
- intercepttext += "We have determined several members of your staff to be political activists. They are:"
- for(var/datum/mind/revmind in revs.head_revolutionaries)
- intercepttext += "
[revmind.current.real_name]"
- intercepttext += "
Please arrest them at once."
- for (var/obj/machinery/computer/communications/comm in world)
- if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept)
- var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc )
- intercept.name = "Cent. Com. Status Summary"
- intercept.info = intercepttext
- comm.messagetitle.Add("Cent. Com. Status Summary")
- comm.messagetext.Add(intercepttext)
- spawn(12000)
- command_announcement.Announce("Repeating the previous message over intercoms due to urgency. The station has political agitators onboard by the names of [reveal_rev_heads()], please arrest them at once.", "Local agitators have been determined.")
-
-/datum/game_mode/revolution/proc/reveal_rev_heads()
- . = ""
- for(var/i = 1, i <= revs.head_revolutionaries.len,i++)
- var/datum/mind/revmind = revs.head_revolutionaries[i]
- if(i < revs.head_revolutionaries.len)
- . += "[revmind.current.real_name],"
- else
- . += "and [revmind.current.real_name]"
+ antag_tags = list(MODE_REVOLUTIONARY, MODE_LOYALIST)
+ require_all_templates = 1
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index e5e6a29e6d..a4ae776bbf 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -14,5 +14,11 @@
required_players = 0
required_enemies = 1
end_on_antag_death = 0
+ antag_tags = list(MODE_TRAITOR)
antag_scaling_coeff = 10
- antag_tag = MODE_TRAITOR
+
+/datum/game_mode/traitor/auto
+ name = "autotraitor"
+ config_tag = "autotraitor"
+ round_autoantag = 1
+ antag_scaling_coeff = 5
diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm
index 3034de4d76..7926fd22be 100644
--- a/code/game/gamemodes/wizard/wizard.dm
+++ b/code/game/gamemodes/wizard/wizard.dm
@@ -7,4 +7,4 @@
required_players_secret = 10
required_enemies = 1
end_on_antag_death = 0
- antag_tag = MODE_WIZARD
+ antag_tags = list(MODE_WIZARD)
diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm
index fbc92f4bc4..55f603f362 100644
--- a/code/game/jobs/access.dm
+++ b/code/game/jobs/access.dm
@@ -8,14 +8,10 @@
//check if it doesn't require any access at all
if(src.check_access(null))
return 1
- if(istype(M, /mob/living/silicon))
- //AI can do whatever he wants
- return 1
- else if(istype(M, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
- //if they are holding or wearing a card that has access, that works
- if(src.check_access(H.get_active_hand()) || src.check_access(H.wear_id))
- return 1
+
+ var/id = M.GetIdCard()
+ if(id)
+ return check_access(id)
return 0
/obj/item/proc/GetAccess()
@@ -32,12 +28,15 @@
if(!req_one_access) req_one_access = list()
if(!L) return 0
if(!istype(L, /list)) return 0
- for(var/req in src.req_access)
- if(!(req in L)) //doesn't have this access
+ return has_access(req_access, req_one_access, L)
+
+/proc/has_access(var/list/req_access, var/list/req_one_access, var/list/accesses)
+ for(var/req in req_access)
+ if(!(req in accesses)) //doesn't have this access
return 0
- if(src.req_one_access.len)
- for(var/req in src.req_one_access)
- if(req in L) //has an access from the single access list
+ if(req_one_access.len)
+ for(var/req in req_one_access)
+ if(req in accesses) //has an access from the single access list
return 1
return 0
return 1
@@ -191,18 +190,27 @@
"Emergency Response Team",
"Emergency Response Team Leader")
-proc/GetIdCard(var/mob/living/carbon/human/H)
- if(H.wear_id)
- var/id = H.wear_id.GetID()
+/mob/proc/GetIdCard()
+ return null
+
+/mob/living/bot/GetIdCard()
+ return botcard
+
+/mob/living/carbon/human/GetIdCard()
+ if(wear_id)
+ var/id = wear_id.GetID()
if(id)
return id
- if(H.get_active_hand())
- var/obj/item/I = H.get_active_hand()
+ if(get_active_hand())
+ var/obj/item/I = get_active_hand()
return I.GetID()
+/mob/living/silicon/GetIdCard()
+ return idcard
+
proc/FindNameFromID(var/mob/living/carbon/human/H)
ASSERT(istype(H))
- var/obj/item/weapon/card/id/C = GetIdCard(H)
+ var/obj/item/weapon/card/id/C = H.GetIdCard()
if(C)
return C.registered_name
@@ -214,13 +222,12 @@ proc/get_all_job_icons() //For all existing HUD icons
if(I)
var/job_icons = get_all_job_icons()
- var/centcom = get_all_centcom_jobs()
-
if(I.assignment in job_icons) //Check if the job has a hud icon
return I.assignment
if(I.rank in job_icons)
return I.rank
+ var/centcom = get_all_centcom_jobs()
if(I.assignment in centcom) //Return with the NT logo if it is a Centcom job
return "Centcom"
if(I.rank in centcom)
diff --git a/code/game/jobs/access_datum.dm b/code/game/jobs/access_datum.dm
index ca8e95276c..718026450c 100644
--- a/code/game/jobs/access_datum.dm
+++ b/code/game/jobs/access_datum.dm
@@ -447,6 +447,12 @@
/*******
* Misc *
*******/
+/var/const/access_synth = 199
+/datum/access/synthetic
+ id = access_synth
+ desc = "Synthetic"
+ access_type = ACCESS_TYPE_NONE
+
/var/const/access_crate_cash = 200
/datum/access/crate_cash
id = access_crate_cash
diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm
index f7243244bd..ffbc7c0fc3 100644
--- a/code/game/jobs/job/civilian.dm
+++ b/code/game/jobs/job/civilian.dm
@@ -64,9 +64,8 @@
spawn_positions = 1
supervisors = "the head of personnel"
selection_color = "#dddddd"
- access = list(access_hydroponics, access_bar, access_kitchen) // Removed tox and chem access because STOP PISSING OFF THE CHEMIST GUYS // //Removed medical access because WHAT THE FUCK YOU AREN'T A DOCTOR YOU GROW WHEAT //Given Morgue access because they have a viable means of cloning.
- minimal_access = list(access_hydroponics) // Removed tox and chem access because STOP PISSING OFF THE CHEMIST GUYS // //Removed medical access because WHAT THE FUCK YOU AREN'T A DOCTOR YOU GROW WHEAT //Given Morgue access because they have a viable means of cloning.
- alt_titles = list("Hydroponicist")
+ access = list(access_hydroponics, access_bar, access_kitchen)
+ minimal_access = list(access_hydroponics) alt_titles = list("Hydroponicist")
equip(var/mob/living/carbon/human/H)
diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm
index 434c2cf7f3..efa670d858 100644
--- a/code/game/jobs/job/medical.dm
+++ b/code/game/jobs/job/medical.dm
@@ -46,6 +46,8 @@
supervisors = "the chief medical officer"
selection_color = "#ffeef0"
economic_modifier = 7
+ access = list(access_medical, access_medical_equip, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics)
+ minimal_access = list(access_medical, access_medical_equip, access_morgue, access_surgery, access_virology)
alt_titles = list("Surgeon","Emergency Physician","Nurse","Virologist")
equip(var/mob/living/carbon/human/H)
@@ -107,6 +109,8 @@
supervisors = "the chief medical officer"
selection_color = "#ffeef0"
economic_modifier = 5
+ access = list(access_medical, access_medical_equip, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics)
+ minimal_access = list(access_medical, access_medical_equip, access_chemistry)
alt_titles = list("Pharmacist")
@@ -136,6 +140,8 @@
supervisors = "the chief medical officer and research director"
selection_color = "#ffeef0"
economic_modifier = 7
+ access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics, access_research)
+ minimal_access = list(access_medical, access_morgue, access_genetics, access_research)
equip(var/mob/living/carbon/human/H)
if(!H) return 0
@@ -197,6 +203,7 @@
supervisors = "the chief medical officer"
selection_color = "#ffeef0"
economic_modifier = 4
+ access = list(access_medical, access_medical_equip, access_morgue, access_surgery, access_chemistry, access_virology, access_eva, access_maint_tunnels, access_external_airlocks, access_psychiatrist)
minimal_access = list(access_medical, access_medical_equip, access_eva, access_maint_tunnels, access_external_airlocks)
alt_titles = list("Emergency Medical Technician")
diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm
index 2e3d53b3cc..04bd9093ce 100644
--- a/code/game/jobs/job/security.dm
+++ b/code/game/jobs/job/security.dm
@@ -96,7 +96,9 @@
access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_eva, access_external_airlocks)
minimal_access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_eva, access_external_airlocks)
economic_modifier = 5
- minimal_player_age = 3
+ access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels)
+ minimal_access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels)
+ alt_titles = list("Forensic Technician") minimal_player_age = 3
equip(var/mob/living/carbon/human/H)
if(!H) return 0
H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(H), slot_l_ear)
@@ -105,7 +107,7 @@
if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back)
if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back)
H.equip_to_slot_or_del(new /obj/item/clothing/under/det(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes)
+ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/device/pda/detective(H), slot_belt)
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves)
H.equip_to_slot_or_del(new /obj/item/weapon/flame/lighter/zippo(H), slot_l_store)
@@ -118,8 +120,8 @@
if(H.mind.role_alt_title && H.mind.role_alt_title == "Forensic Technician")
H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/forensics/blue(H), slot_wear_suit)
else
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/det_suit(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/det_hat(H), slot_head)
+ H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/det_trench(H), slot_wear_suit)
+ H.equip_to_slot_or_del(new /obj/item/clothing/head/det(H), slot_head)
return 1
@@ -134,10 +136,10 @@
spawn_positions = 4
supervisors = "the head of security"
selection_color = "#ffeeee"
+ alt_titles = list("Junior Officer")
economic_modifier = 4
access = list(access_security, access_eva, access_sec_doors, access_brig, access_maint_tunnels, access_morgue, access_external_airlocks)
minimal_access = list(access_security, access_eva, access_sec_doors, access_brig, access_maint_tunnels, access_external_airlocks)
- alt_titles = list("Security Cadet")
minimal_player_age = 3
equip(var/mob/living/carbon/human/H)
if(!H) return 0
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index ff994e8cd3..f375755982 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -528,7 +528,7 @@ var/global/datum/controller/occupations/job_master
if(C)
C.rank = rank
C.assignment = title ? title : rank
- C.set_owner_info(H)
+ H.set_id_info(C)
//put the player's account number onto the ID
if(H.mind && H.mind.initial_account)
diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm
index 135da6bb60..35026659dd 100644
--- a/code/game/jobs/jobs.dm
+++ b/code/game/jobs/jobs.dm
@@ -86,6 +86,12 @@ var/list/science_positions = list(
)
//BS12 EDIT
+var/list/cargo_positions = list(
+ "Quartermaster",
+ "Cargo Technician",
+ "Shaft Miner"
+)
+
var/list/civilian_positions = list(
"Head of Personnel",
"Bartender",
@@ -93,9 +99,6 @@ var/list/civilian_positions = list(
"Chef",
"Janitor",
"Librarian",
- "Quartermaster",
- "Cargo Technician",
- "Shaft Miner",
"Lawyer",
"Chaplain",
"Assistant"
diff --git a/code/game/machinery/CableLayer.dm b/code/game/machinery/CableLayer.dm
index b50e605825..277742a22b 100644
--- a/code/game/machinery/CableLayer.dm
+++ b/code/game/machinery/CableLayer.dm
@@ -20,10 +20,10 @@
/obj/machinery/cablelayer/attack_hand(mob/user as mob)
if(!cable&&!on)
- user << "\The [src] don't work with no cable."
+ user << "\The [src] doesn't have any cable loaded."
return
on=!on
- user.visible_message("\The [src] [!on?"dea":"a"]ctivated.", "[user] [!on?"dea":"a"]ctivated \the [src].")
+ user.visible_message("\The [user] [!on?"dea":"a"]ctivates \the [src].", "You switch [src] [on? "on" : "off"]")
return
/obj/machinery/cablelayer/attackby(var/obj/item/O as obj, var/mob/user as mob)
@@ -31,26 +31,27 @@
var/result = load_cable(O)
if(!result)
- user << "Reel is full."
+ user << "\The [src]'s cable reel is full."
else
- user << "[result] meters of cable successfully loaded."
+ user << "You load [result] lengths of cable into [src]."
return
- if(istype(O, /obj/item/weapon/screwdriver))
+ if(istype(O, /obj/item/weapon/wirecutters))
if(cable && cable.amount)
var/m = round(input(usr,"Please specify the length of cable to cut","Cut cable",min(cable.amount,30)) as num, 1)
m = min(m, cable.amount)
m = min(m, 30)
if(m)
+ playsound(loc, 'sound/items/Wirecutter.ogg', 50, 1)
use_cable(m)
var/obj/item/stack/cable_coil/CC = new (get_turf(src))
CC.amount = m
else
- usr << "There's no more cable on the reel."
+ usr << "There's no more cable on the reel."
/obj/machinery/cablelayer/examine(mob/user)
..()
- user << "\The [src] has [cable.amount] meter\s."
+ user << "\The [src]'s cable reel has [cable.amount] length\s left."
/obj/machinery/cablelayer/proc/load_cable(var/obj/item/stack/cable_coil/CC)
if(istype(CC) && CC.amount)
@@ -70,12 +71,11 @@
/obj/machinery/cablelayer/proc/use_cable(amount)
if(!cable || cable.amount<1)
- visible_message("Cable depleted, [src] deactivated.")
+ visible_message("A red light flashes on \the [src].")
return
-/* if(cable.amount < amount)
- visible_message("No enough cable to finish the task.")
- return*/
cable.use(amount)
+ if(deleted(cable))
+ cable = null
return 1
/obj/machinery/cablelayer/proc/reset()
diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm
index 65324f5555..739583ede8 100644
--- a/code/game/machinery/camera/tracking.dm
+++ b/code/game/machinery/camera/tracking.dm
@@ -223,6 +223,9 @@ mob/living/proc/near_camera()
/mob/living/proc/tracking_status()
// Easy checks first.
// Don't detect mobs on Centcom. Since the wizard den is on Centcomm, we only need this.
+ var/obj/item/weapon/card/id/id = GetIdCard()
+ if(id && id.prevent_tracking())
+ return TRACKING_TERMINATE
if(InvalidPlayerTurf(get_turf(src)))
return TRACKING_TERMINATE
if(invisibility >= INVISIBILITY_LEVEL_ONE) //cloaked
@@ -240,14 +243,8 @@ mob/living/proc/near_camera()
if(. == TRACKING_NO_COVERAGE)
return camera && camera.can_use() ? TRACKING_POSSIBLE : TRACKING_NO_COVERAGE
-/mob/living/silicon/robot/syndicate/tracking_status()
- return TRACKING_TERMINATE
-
/mob/living/carbon/human/tracking_status()
//Cameras can't track people wearing an agent card or a ninja hood.
- var/obj/item/weapon/card/id/id = GetIdCard(src)
- if(id && id.prevent_tracking())
- return TRACKING_TERMINATE
if(istype(head, /obj/item/clothing/head/helmet/space/rig))
var/obj/item/clothing/head/helmet/space/rig/helmet = head
if(helmet.prevent_track())
diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm
index 1fcf6e8625..009c12403d 100644
--- a/code/game/machinery/computer/ai_core.dm
+++ b/code/game/machinery/computer/ai_core.dm
@@ -137,8 +137,7 @@
return
if(M.brainmob.mind)
- cult.remove_antagonist(M.brainmob.mind, 1)
- revs.remove_antagonist(M.brainmob.mind, 1)
+ clear_antag_roles(M.brainmob.mind, 1)
user.drop_item()
P.loc = src
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index 9ead672048..24c79ff972 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -18,7 +18,7 @@
/obj/item/toy/blink = 2,
/obj/item/clothing/under/syndicate/tacticool = 2,
/obj/item/toy/sword = 2,
- /obj/item/toy/gun = 2,
+ /obj/item/weapon/gun/projectile/revolver/capgun = 2,
/obj/item/toy/crossbow = 2,
/obj/item/clothing/suit/syndicatefake = 2,
/obj/item/weapon/storage/fancy/crayons = 2,
@@ -168,8 +168,8 @@
var/prizeselect = pickweight(prizes)
new prizeselect(src.loc)
- if(istype(prizeselect, /obj/item/toy/gun)) //Ammo comes with the gun
- new /obj/item/toy/ammo/gun(src.loc)
+ if(istype(prizeselect, /obj/item/weapon/gun/projectile/revolver/capgun)) //Ammo comes with the gun
+ new /obj/item/projectile/bullet/pistol/cap(src.loc)
else if(istype(prizeselect, /obj/item/clothing/suit/syndicatefake)) //Helmet is part of the suit
new /obj/item/clothing/head/syndicatefake(src.loc)
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index 8d85a63224..4b8b9a9acf 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -257,3 +257,7 @@
icon_state = "syndicam"
network = list("NUKE")
circuit = null
+
+/obj/machinery/computer/security/nuclear/New()
+ ..()
+ req_access = list(150)
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index d8f13f57b7..b949e284b8 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -59,12 +59,10 @@
if(!istype(id_card))
return ..()
- if(!scan && access_change_ids in id_card.access)
- user.drop_item()
+ if(!scan && (access_change_ids in id_card.access) && user.unEquip(id_card))
id_card.loc = src
scan = id_card
else if(!modify)
- user.drop_item()
id_card.loc = src
modify = id_card
@@ -157,8 +155,7 @@
modify = null
else
var/obj/item/I = usr.get_active_hand()
- if (istype(I, /obj/item/weapon/card/id))
- usr.drop_item()
+ if (istype(I, /obj/item/weapon/card/id) && usr.unEquip(I))
I.loc = src
modify = I
diff --git a/code/game/machinery/computer/guestpass.dm b/code/game/machinery/computer/guestpass.dm
index 7258fc543b..ccbce91b61 100644
--- a/code/game/machinery/computer/guestpass.dm
+++ b/code/game/machinery/computer/guestpass.dm
@@ -62,13 +62,14 @@
/obj/machinery/computer/guestpass/attackby(obj/O, mob/user)
if(istype(O, /obj/item/weapon/card/id))
- if(!giver)
- user.drop_item()
+ if(!giver && user.unEquip(O))
O.loc = src
giver = O
updateUsrDialog()
- else
+ else if(giver)
user << "There is already ID card inside."
+ return
+ ..()
/obj/machinery/computer/guestpass/attack_ai(var/mob/user as mob)
return attack_hand(user)
@@ -151,8 +152,7 @@
accesses.Cut()
else
var/obj/item/I = usr.get_active_hand()
- if (istype(I, /obj/item/weapon/card/id))
- usr.drop_item()
+ if (istype(I, /obj/item/weapon/card/id) && usr.unEquip(I))
I.loc = src
giver = I
updateUsrDialog()
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index 30d7de6d6c..15c504800a 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -35,13 +35,13 @@
usr << "There is nothing to remove from the console."
return
-/obj/machinery/computer/med_data/attackby(obj/item/O as obj, user as mob)
- if(istype(O, /obj/item/weapon/card/id) && !scan)
- usr.drop_item()
+/obj/machinery/computer/med_data/attackby(var/obj/item/O, var/mob/user)
+ if(istype(O, /obj/item/weapon/card/id) && !scan && user.unEquip(O))
O.loc = src
scan = O
- user << "You insert [O]."
- ..()
+ user << "You insert \the [O]."
+ else
+ ..()
/obj/machinery/computer/med_data/attack_ai(user as mob)
return src.attack_hand(user)
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 090e02c908..eba129df26 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -248,8 +248,7 @@ What a mess.*/
scan = null
else
var/obj/item/I = usr.get_active_hand()
- if (istype(I, /obj/item/weapon/card/id))
- usr.drop_item()
+ if (istype(I, /obj/item/weapon/card/id) && usr.unEquip(I))
I.loc = src
scan = I
diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm
index fb2d4ef095..8e57548d6e 100644
--- a/code/game/machinery/computer/skills.dm
+++ b/code/game/machinery/computer/skills.dm
@@ -24,13 +24,13 @@
var/sortBy = "name"
var/order = 1 // -1 = Descending - 1 = Ascending
-/obj/machinery/computer/skills/attackby(obj/item/O as obj, user as mob)
- if(istype(O, /obj/item/weapon/card/id) && !scan)
- usr.drop_item()
+/obj/machinery/computer/skills/attackby(obj/item/O as obj, var/mob/user)
+ if(istype(O, /obj/item/weapon/card/id) && !scan && user.unEquip(O))
O.loc = src
scan = O
user << "You insert [O]."
- ..()
+ else
+ ..()
/obj/machinery/computer/skills/attack_ai(mob/user as mob)
return attack_hand(user)
@@ -185,8 +185,7 @@ What a mess.*/
scan = null
else
var/obj/item/I = usr.get_active_hand()
- if (istype(I, /obj/item/weapon/card/id))
- usr.drop_item()
+ if (istype(I, /obj/item/weapon/card/id) && usr.unEquip(I))
I.loc = src
scan = I
@@ -278,7 +277,11 @@ What a mess.*/
else
P.info += "General Record Lost!
"
P.info += ""
- P.name = "Employment Record ([active1.fields["name"]])"
+ if(active1)
+ P.name = "Employment Record ([active1.fields["name"]])"
+ else
+ P.name = "Employment Record (Unknown/Invald Entry)"
+ log_debug("[usr] ([usr.ckey]) attempted to print a null employee record, this should be investigated.")
printing = null
//RECORD DELETE
if ("Delete All Records")
diff --git a/code/game/machinery/computer3/computers/arcade.dm b/code/game/machinery/computer3/computers/arcade.dm
index 1f8edfa0a9..7447363661 100644
--- a/code/game/machinery/computer3/computers/arcade.dm
+++ b/code/game/machinery/computer3/computers/arcade.dm
@@ -7,7 +7,7 @@
/obj/item/toy/blink = 2,
/obj/item/clothing/under/syndicate/tacticool = 2,
/obj/item/toy/sword = 2,
- /obj/item/toy/gun = 2,
+ /obj/item/weapon/gun/projectile/revolver/capgun = 2,
/obj/item/toy/crossbow = 2,
/obj/item/clothing/suit/syndicatefake = 2,
/obj/item/weapon/storage/fancy/crayons = 2,
@@ -28,8 +28,8 @@
if(computer && !computer.stat)
var/prizeselect = pickweight(prizes)
new prizeselect(computer.loc)
- if(istype(prizeselect, /obj/item/toy/gun)) //Ammo comes with the gun
- new /obj/item/toy/ammo/gun(computer.loc)
+ if(istype(prizeselect, /obj/item/weapon/gun/projectile/revolver/capgun)) //Ammo comes with the gun
+ new /obj/item/projectile/bullet/pistol/cap(src.loc)
else if(istype(prizeselect, /obj/item/clothing/suit/syndicatefake)) //Helmet is part of the suit
new /obj/item/clothing/head/syndicatefake(computer.loc)
feedback_inc("arcade_win_normal")
diff --git a/code/game/machinery/computer3/computers/medical.dm b/code/game/machinery/computer3/computers/medical.dm
index f39dd54de8..7cf89a3fce 100644
--- a/code/game/machinery/computer3/computers/medical.dm
+++ b/code/game/machinery/computer3/computers/medical.dm
@@ -181,7 +181,7 @@
scan = null
else
var/obj/item/I = usr.get_active_hand()
- if (istype(I, /obj/item/weapon/card/id))
+ if (istype(I, /obj/item/weapon/card/id) && usr.drop_item(I))
computer.cardslot.insert(I, 1)
scan = I
@@ -194,7 +194,7 @@
scan2 = null
else
var/obj/item/I = usr.get_active_hand()
- if (istype(I, /obj/item/weapon/card/id))
+ if (istype(I, /obj/item/weapon/card/id) && usr.drop_item(I))
computer.cardslot.insert(I, 2)
scan2 = I
diff --git a/code/game/machinery/computer3/computers/security.dm b/code/game/machinery/computer3/computers/security.dm
index a346c12fac..1ba0c08cf7 100644
--- a/code/game/machinery/computer3/computers/security.dm
+++ b/code/game/machinery/computer3/computers/security.dm
@@ -254,7 +254,7 @@ What a mess.*/
scan = null
else
var/obj/item/I = usr.get_active_hand()
- if (istype(I, /obj/item/weapon/card/id))
+ if (istype(I, /obj/item/weapon/card/id) && usr.drop_item(I))
computer.cardslot.insert(I, 1)
scan = I
@@ -267,7 +267,7 @@ What a mess.*/
scan2 = null
else
var/obj/item/I = usr.get_active_hand()
- if (istype(I, /obj/item/weapon/card/id))
+ if (istype(I, /obj/item/weapon/card/id) && usr.drop_item(I))
computer.cardslot.insert(I, 2)
scan2 = I
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index d1cd2fe748..1546ed4c4b 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -419,20 +419,10 @@
for(var/datum/objective/O in all_objectives)
// We don't want revs to get objectives that aren't for heads of staff. Letting
// them win or lose based on cryo is silly so we remove the objective.
- if(istype(O,/datum/objective/mutiny) && O.target == occupant.mind)
+ if(O.target == occupant.mind)
+ if(O.owner && O.owner.current)
+ O.owner.current << "You get the feeling your target is no longer within your reach..."
qdel(O)
- else if(O.target && istype(O.target,/datum/mind))
- if(O.target == occupant.mind)
- if(O.owner && O.owner.current)
- O.owner.current << "You get the feeling your target is no longer within your reach. Time for Plan [pick(list("A","B","C","D","X","Y","Z"))]..."
- O.target = null
- spawn(1) //This should ideally fire after the occupant is deleted.
- if(!O) return
- O.find_target()
- if(!(O.target))
- all_objectives -= O
- O.owner.objectives -= O
- qdel(O)
//Handle job slot/tater cleanup.
var/job = occupant.mind.assigned_role
diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm
index 8916beb413..6662b20b67 100644
--- a/code/game/machinery/door_control.dm
+++ b/code/game/machinery/door_control.dm
@@ -65,7 +65,7 @@
use_power(5)
icon_state = "doorctrl1"
desiredstate = !desiredstate
- trigger()
+ trigger(user)
spawn(15)
update_icon()
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 2def8f8086..33f61fb1ec 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -254,6 +254,7 @@
health = between(health, health + repairing.amount*DOOR_REPAIR_AMOUNT, maxhealth)
update_icon()
qdel(repairing)
+ repairing = null
return
if(repairing && istype(I, /obj/item/weapon/crowbar))
diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm
index 5393de59cc..e6fb41193c 100644
--- a/code/game/machinery/flasher.dm
+++ b/code/game/machinery/flasher.dm
@@ -67,25 +67,22 @@
if (get_dist(src, O) > src.range)
continue
+ var/flash_time = strength
if (istype(O, /mob/living/carbon/human))
var/mob/living/carbon/human/H = O
if(!H.eyecheck() <= 0)
continue
-
- if (istype(O, /mob/living/carbon/alien))//So aliens don't get flashed (they have no external eyes)/N
- continue
-
- O.Weaken(strength)
- if (istype(O, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = O
+ flash_time *= H.species.flash_mod
var/obj/item/organ/eyes/E = H.internal_organs_by_name["eyes"]
- if (E && (E.damage > E.min_bruised_damage && prob(E.damage + 50)))
+ if(!E)
+ return
+ if(E.is_bruised() && prob(E.damage + 50))
flick("e_flash", O:flash)
E.damage += rand(1, 5)
else
if(!O.blinded)
flick("flash", O:flash)
-
+ O.Weaken(flash_time)
/obj/machinery/flasher/emp_act(severity)
if(stat & (BROKEN|NOPOWER))
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index 2fa0281ecd..94f9bc70df 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -623,7 +623,6 @@ var/list/turret_icons
else
A = new projectile(loc)
playsound(loc, shot_sound, 75, 1)
- A.original = target
// Lethal/emagged turrets use twice the power due to higher energy beams
// Emagged turrets again use twice as much power due to higher firing rates
@@ -631,19 +630,15 @@ var/list/turret_icons
//Turrets aim for the center of mass by default.
//If the target is grabbing someone then the turret smartly aims for extremities
+ var/def_zone
var/obj/item/weapon/grab/G = locate() in target
if(G && G.state >= GRAB_NECK) //works because mobs are currently not allowed to upgrade to NECK if they are grabbing two people.
- A.def_zone = pick("head", "l_hand", "r_hand", "l_foot", "r_foot", "l_arm", "r_arm", "l_leg", "r_leg")
+ def_zone = pick("head", "l_hand", "r_hand", "l_foot", "r_foot", "l_arm", "r_arm", "l_leg", "r_leg")
else
- A.def_zone = pick("chest", "groin")
+ def_zone = pick("chest", "groin")
//Shooting Code:
- A.current = T
- A.starting = T
- A.yo = U.y - T.y
- A.xo = U.x - T.x
- spawn(1)
- A.process()
+ A.launch(target, def_zone)
/datum/turret_checks
var/enabled
diff --git a/code/game/machinery/supplybeacon.dm b/code/game/machinery/supplybeacon.dm
new file mode 100644
index 0000000000..cab45d6898
--- /dev/null
+++ b/code/game/machinery/supplybeacon.dm
@@ -0,0 +1,117 @@
+// Used to deploy the bacon.
+/obj/item/supply_beacon
+ name = "inactive supply beacon"
+ icon = 'icons/obj/supplybeacon.dmi'
+ desc = "An inactive, hacked supply beacon stamped with the Nyx Rapid Fabrication logo. Good for one (1) ballistic supply pod shipment."
+ icon_state = "beacon"
+ var/deploy_path = /obj/machinery/power/supply_beacon
+ var/deploy_time = 30
+
+/obj/item/supply_beacon/supermatter
+ name = "inactive supermatter supply beacon"
+ deploy_path = /obj/machinery/power/supply_beacon/supermatter
+
+/obj/item/supply_beacon/attack_self(var/mob/user)
+ user.visible_message("\The [user] begins setting up \the [src].")
+ if(!do_after(user, deploy_time))
+ return
+ var/obj/S = new deploy_path(get_turf(user))
+ user.visible_message("\The [user] deploys \the [S].")
+ user.unEquip(src)
+ qdel(src)
+
+/obj/machinery/power/supply_beacon
+ name = "supply beacon"
+ desc = "A bulky moonshot supply beacon. Someone has been messing with the wiring."
+ icon = 'icons/obj/supplybeacon.dmi'
+ icon_state = "beacon"
+
+ anchored = 0
+ density = 1
+ layer = MOB_LAYER - 0.1
+ stat = 0
+
+ var/target_drop_time
+ var/drop_delay = 450
+ var/expended
+ var/drop_type
+
+/obj/machinery/power/supply_beacon/New()
+ ..()
+ if(!drop_type) drop_type = pick(supply_drop_random_loot_types())
+
+/obj/machinery/power/supply_beacon/supermatter
+ name = "supermatter supply beacon"
+ drop_type = "supermatter"
+
+/obj/machinery/power/supply_beacon/attackby(var/obj/item/weapon/W, var/mob/user)
+ if(!use_power && istype(W, /obj/item/weapon/wrench))
+ if(!anchored && !connect_to_network())
+ user << "This device must be placed over an exposed cable."
+ return
+ anchored = !anchored
+ user.visible_message("\The [user] [anchored ? "secures" : "unsecures"] \the [src].")
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
+ return
+ return ..()
+
+/obj/machinery/power/supply_beacon/attack_hand(var/mob/user)
+
+ if(expended)
+ use_power = 0
+ user << "\The [src] has used up its charge."
+ return
+
+ if(anchored)
+ return use_power ? deactivate(user) : activate(user)
+ else
+ user << "You need to secure the beacon with a wrench first!"
+ return
+
+/obj/machinery/power/supply_beacon/attack_ai(var/mob/user)
+ if(user.Adjacent(src))
+ attack_hand(user)
+
+/obj/machinery/power/supply_beacon/proc/activate(var/mob/user)
+ if(expended)
+ return
+ if(surplus() < 500)
+ if(user) user << "The connected wire doesn't have enough current."
+ return
+ set_light(3, 3, "#00CCAA")
+ icon_state = "beacon_active"
+ use_power = 1
+ if(user) user << "You activate the beacon. The supply drop will be dispatched soon."
+
+/obj/machinery/power/supply_beacon/proc/deactivate(var/mob/user, var/permanent)
+ if(permanent)
+ expended = 1
+ icon_state = "beacon_depleted"
+ else
+ icon_state = "beacon"
+ set_light(0)
+ use_power = 0
+ target_drop_time = null
+ if(user) user << "You deactivate the beacon."
+
+/obj/machinery/power/supply_beacon/Destroy()
+ if(use_power)
+ deactivate()
+ ..()
+
+/obj/machinery/power/supply_beacon/process()
+ if(!use_power || expended)
+ return PROCESS_KILL
+ if(draw_power(500) < 500)
+ deactivate()
+ return
+ if(!target_drop_time)
+ target_drop_time = world.time + drop_delay
+ else if(world.time >= target_drop_time)
+ deactivate(permanent = 1)
+ var/drop_x = src.x-2
+ var/drop_y = src.y-2
+ var/drop_z = src.z
+ command_announcement.Announce("Nyx Rapid Fabrication priority supply request #[rand(1000,9999)]-[rand(100,999)] recieved. Shipment dispatched via ballistic supply pod for immediate delivery. Have a nice day.", "Thank You For Your Patronage")
+ spawn(rand(100,300))
+ new /datum/random_map/droppod/supply(null, drop_x, drop_y, drop_z, supplied_drop = drop_type) // Splat.
diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm
index 820d09045b..6a61a082b9 100644
--- a/code/game/machinery/telecomms/broadcaster.dm
+++ b/code/game/machinery/telecomms/broadcaster.dm
@@ -287,14 +287,18 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/* --- Loop through the receivers and categorize them --- */
- if (R.client && !(R.client.prefs.toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
- continue
+ if (R.client)
+ if(R.client.prefs)
+ if(!(R.client.prefs.toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
+ continue
+ else
+ log_debug("Client prefs found to be null in /proc/Broadcast_Message() for mob [R] and client [R.ckey], this should be investigated.")
if(istype(R, /mob/new_player)) // we don't want new players to hear messages. rare but generates runtimes.
continue
// Ghosts hearing all radio chat don't want to hear syndicate intercepts, they're duplicates
- if(data == 3 && istype(R, /mob/dead/observer) && R.client && (R.client.prefs.toggles & CHAT_GHOSTRADIO))
+ if(data == 3 && istype(R, /mob/dead/observer) && R.client && R.client.prefs && (R.client.prefs.toggles & CHAT_GHOSTRADIO))
continue
// --- Check for compression ---
@@ -353,7 +357,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- This following recording is intended for research and feedback in the use of department radio channels ---
var/part_blackbox_b = " \[[freq_text]\] " // Tweaked for security headsets -- TLE
- var/blackbox_msg = "[part_a][name][part_blackbox_b][quotedmsg][part_c]"
+ var/blackbox_msg = "[part_a][name][part_blackbox_b][quotedmsg][part_c]"
//var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]"
//BR.messages_admin += blackbox_admin_msg
@@ -490,8 +494,12 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/* --- Loop through the receivers and categorize them --- */
- if (R.client && !(R.client.prefs.toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
- continue
+ if (R.client)
+ if(R.client.prefs)
+ if(!(R.client.prefs.toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
+ continue
+ else
+ log_debug("Client prefs found to be null in /proc/Broadcast_SimpleMessage() for mob [R] and client [R.ckey], this should be investigated.")
// --- Check for compression ---
@@ -518,7 +526,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
if (length(heard_normal) || length(heard_garbled) || length(heard_gibberish))
/* --- Some miscellaneous variables to format the string output --- */
- var/part_a = "" // goes in the actual output
+ var/part_a = "" // goes in the actual output
var/freq_text = get_frequency_name(display_freq)
// --- Some more pre-message formatting ---
@@ -531,23 +539,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
var/obj/item/device/radio/headset/radio = new
var/part_b = " \icon[radio]\[[freq_text]\][part_b_extra] " // Tweaked for security headsets -- TLE
+ var/part_blackbox_b = " \[[freq_text]\] " // Tweaked for security headsets -- TLE
var/part_c = ""
- part_a = ""
-
- // --- This following recording is intended for research and feedback in the use of department radio channels ---
-
- var/part_blackbox_b = " \[[freq_text]\] " // Tweaked for security headsets -- TLE
var/blackbox_msg = "[part_a][source][part_blackbox_b]\"[text]\"[part_c]"
- //var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]"
//BR.messages_admin += blackbox_admin_msg
if(istype(blackbox))
diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm
index dcb555b755..ca35f59236 100644
--- a/code/game/machinery/telecomms/presets.dm
+++ b/code/game/machinery/telecomms/presets.dm
@@ -60,7 +60,7 @@
//Common and other radio frequencies for people to freely use
New()
- for(var/i = 1441, i < 1489, i += 2)
+ for(var/i = PUBLIC_LOW_FREQ, i < PUBLIC_HIGH_FREQ, i += 2)
freq_listening |= i
..()
@@ -87,7 +87,7 @@
autolinkers = list("processor2", "supply", "service", "unused")
/obj/machinery/telecomms/bus/preset_two/New()
- for(var/i = 1441, i < 1489, i += 2)
+ for(var/i = PUBLIC_LOW_FREQ, i < PUBLIC_HIGH_FREQ, i += 2)
if(i == PUB_FREQ)
continue
freq_listening |= i
@@ -178,7 +178,7 @@
autolinkers = list("unused")
/obj/machinery/telecomms/server/presets/unused/New()
- for(var/i = 1441, i < 1489, i += 2)
+ for(var/i = PUBLIC_LOW_FREQ, i < PUBLIC_HIGH_FREQ, i += 2)
if(i == AI_FREQ || i == PUB_FREQ)
continue
freq_listening |= i
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index d80c57336e..7229875a71 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -235,26 +235,25 @@
nanomanager.update_uis(src)
return
else if(istype(W, /obj/item/weapon/wrench))
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
+ if(anchored)
+ user.visible_message("[user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.")
+ else
+ user.visible_message("[user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.")
+
if(do_after(user, 20))
if(!src) return
- playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
- switch (anchored)
- if (0)
- anchored = 1
- user.visible_message("\The [user] tightens the bolts securing \the [src] to the floor.", "You tighten the bolts securing \the [src] to the floor.")
- if (1)
- user.visible_message("\The [user] unfastens the bolts securing \the [src] to the floor.", "You unfasten the bolts securing \the [src] to the floor.")
- anchored = 0
+ user << "You [anchored? "un" : ""]secured \the [src]!"
+ anchored = !anchored
return
- else if(src.panel_open)
+ else
for(var/datum/data/vending_product/R in product_records)
if(istype(W, R.product_path))
stock(R, user)
qdel(W)
-
- else
+ return
..()
/**
@@ -560,7 +559,7 @@
/obj/machinery/vending/proc/stock(var/datum/data/vending_product/R, var/mob/user)
if(src.panel_open)
- user << "You stock \the [src] with \a [R.product_name]"
+ user << "You insert \the [src] in the product receptor."
R.amount++
nanomanager.update_uis(src)
@@ -692,7 +691,8 @@
/obj/item/weapon/reagent_containers/food/drinks/bottle/small/ale = 6,/obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice = 4,
/obj/item/weapon/reagent_containers/food/drinks/bottle/tomatojuice = 4,/obj/item/weapon/reagent_containers/food/drinks/bottle/limejuice = 4,
/obj/item/weapon/reagent_containers/food/drinks/bottle/cream = 4,/obj/item/weapon/reagent_containers/food/drinks/cans/tonic = 8,
- /obj/item/weapon/reagent_containers/food/drinks/cans/cola = 8, /obj/item/weapon/reagent_containers/food/drinks/cans/sodawater = 15,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/cola = 5, /obj/item/weapon/reagent_containers/food/drinks/bottle/space_up = 5,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/space_mountain_wind = 5, /obj/item/weapon/reagent_containers/food/drinks/cans/sodawater = 15,
/obj/item/weapon/reagent_containers/food/drinks/flask/barflask = 2, /obj/item/weapon/reagent_containers/food/drinks/flask/vacuumflask = 2,
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 30,/obj/item/weapon/reagent_containers/food/drinks/ice = 9,
/obj/item/weapon/reagent_containers/food/drinks/bottle/melonliquor = 2,/obj/item/weapon/reagent_containers/food/drinks/bottle/bluecuracao = 2,
diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm
index 607e8f445c..db1cb3d004 100644
--- a/code/game/mecha/equipment/mecha_equipment.dm
+++ b/code/game/mecha/equipment/mecha_equipment.dm
@@ -7,8 +7,6 @@
icon_state = "mecha_equip"
force = 5
origin_tech = list(TECH_MATERIAL = 2)
- construction_time = 100
- construction_cost = list(DEFAULT_WALL_MATERIAL=10000)
var/equip_cooldown = 0
var/equip_ready = 1
var/energy_drain = 0
diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm
index 498a9dfff6..98a49af28a 100644
--- a/code/game/mecha/equipment/tools/medical_tools.dm
+++ b/code/game/mecha/equipment/tools/medical_tools.dm
@@ -6,7 +6,6 @@
origin_tech = list(TECH_DATA = 2, TECH_BIO = 3)
energy_drain = 20
range = MELEE
- construction_cost = list(DEFAULT_WALL_MATERIAL=5000,"glass"=10000)
equip_cooldown = 20
var/mob/living/carbon/occupant = null
var/datum/global_iterator/pr_mech_sleeper
@@ -384,8 +383,6 @@
range = MELEE|RANGED
equip_cooldown = 10
origin_tech = list(TECH_MATERIAL = 3, TECH_BIO = 4, TECH_MAGNET = 4, TECH_DATA = 3)
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=3000,"glass"=2000)
required_type = /obj/mecha/medical
New()
diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm
index 4b9a17483f..ca51d1e1b3 100644
--- a/code/game/mecha/equipment/tools/tools.dm
+++ b/code/game/mecha/equipment/tools/tools.dm
@@ -126,9 +126,8 @@
/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill
name = "diamond drill"
desc = "This is an upgraded version of the drill that'll pierce the heavens! (Can be attached to: Combat and Engineering Exosuits)"
- icon_state = "mecha_diamond_drill"
- origin_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3)
- construction_cost = list(DEFAULT_WALL_MATERIAL=10000,"diamond"=6500)
+ icon_state = "mecha_diamond_drill"
+ origin_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3)
equip_cooldown = 20
force = 15
@@ -255,8 +254,6 @@
equip_cooldown = 10
energy_drain = 250
range = MELEE|RANGED
- construction_time = 1200
- construction_cost = list(DEFAULT_WALL_MATERIAL=30000,"phoron"=25000,"silver"=20000,"gold"=20000)
var/mode = 0 //0 - deconstruct, 1 - wall or floor, 2 - airlock.
var/disabled = 0 //malf
@@ -506,7 +503,6 @@
equip_cooldown = 10
energy_drain = 50
range = 0
- construction_cost = list(DEFAULT_WALL_MATERIAL=20000,"silver"=5000)
var/deflect_coeff = 1.15
var/damage_coeff = 0.8
@@ -556,7 +552,6 @@
equip_cooldown = 10
energy_drain = 50
range = 0
- construction_cost = list(DEFAULT_WALL_MATERIAL=20000,"gold"=5000)
var/deflect_coeff = 1.15
var/damage_coeff = 0.8
@@ -627,7 +622,6 @@
equip_cooldown = 20
energy_drain = 100
range = 0
- construction_cost = list(DEFAULT_WALL_MATERIAL=10000,"gold"=1000,"silver"=2000,"glass"=5000)
var/health_boost = 2
var/datum/global_iterator/pr_repair_droid
var/icon/droid_overlay
@@ -722,7 +716,6 @@
equip_cooldown = 10
energy_drain = 0
range = 0
- construction_cost = list(DEFAULT_WALL_MATERIAL=10000,"gold"=2000,"silver"=3000,"glass"=2000)
var/datum/global_iterator/pr_energy_relay
var/coeff = 100
var/list/use_channels = list(EQUIP,ENVIRON,LIGHT)
@@ -839,7 +832,6 @@
equip_cooldown = 10
energy_drain = 0
range = MELEE
- construction_cost = list(DEFAULT_WALL_MATERIAL=10000,"silver"=500,"glass"=1000)
var/datum/global_iterator/pr_mech_generator
var/coeff = 100
var/obj/item/stack/material/fuel
@@ -972,9 +964,8 @@
/obj/item/mecha_parts/mecha_equipment/generator/nuclear
name = "\improper ExoNuclear reactor"
desc = "Generates power using uranium. Pollutes the environment."
- icon_state = "tesla"
- origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3)
- construction_cost = list(DEFAULT_WALL_MATERIAL=10000,"silver"=500,"glass"=1000)
+ icon_state = "tesla"
+ origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3)
max_fuel = 50000
fuel_per_cycle_idle = 10
fuel_per_cycle_active = 30
@@ -1072,7 +1063,6 @@
origin_tech = list(TECH_ENGINEERING = 1, TECH_BIO = 1)
energy_drain = 10
range = MELEE
- construction_cost = list(DEFAULT_WALL_MATERIAL=5000,"glass"=5000)
equip_cooldown = 20
var/mob/living/carbon/occupant = null
var/door_locked = 1
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index f034f27550..913f9acb72 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -274,7 +274,6 @@
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang//Because I am a heartless bastard -Sieve
name = "\improper SOP-6 grenade launcher"
projectile = /obj/item/weapon/grenade/flashbang/clusterbang
- construction_cost = list(DEFAULT_WALL_MATERIAL=20000,"gold"=6000,"uranium"=6000)
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang/limited/get_equip_info()//Limited version of the clusterbang launcher that can't reload
return "* [chassis.selected==src?"":""][src.name][chassis.selected==src?"":""]\[[src.projectiles]\]"
diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index 3fb9ed8bf4..7fc5f17e86 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -1,126 +1,29 @@
-/////////////////////////////
-///// Part Fabricator ///////
-/////////////////////////////
-
/obj/machinery/mecha_part_fabricator
icon = 'icons/obj/robotics.dmi'
icon_state = "fab-idle"
name = "Exosuit Fabricator"
- desc = "Nothing is being built."
+ desc = "A machine used for construction of robotcs and mechas."
density = 1
anchored = 1
use_power = 1
idle_power_usage = 20
active_power_usage = 5000
req_access = list(access_robotics)
- var/current_manufacturer
- var/time_coeff = 1.5 //can be upgraded with research
- var/resource_coeff = 1.5 //can be upgraded with research
- var/list/resources = list(
- DEFAULT_WALL_MATERIAL=0,
- "glass"=0,
- "gold"=0,
- "silver"=0,
- "diamond"=0,
- "phoron"=0,
- "uranium"=0,
- )
+
+ var/speed = 1
+ var/mat_efficiency = 1
+ var/list/materials = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0, "gold" = 0, "silver" = 0, "diamond" = 0, "phoron" = 0, "uranium" = 0)
var/res_max_amount = 200000
+
var/datum/research/files
- var/id
- var/sync = 0
- var/part_set
- var/obj/being_built
- var/list/queue = list()
- var/processing_queue = 0
- var/screen = "main"
- var/opened = 0
- var/temp
- var/output_dir = SOUTH //the direction relative to the fabber at which completed parts appear.
- var/list/part_sets = list( //set names must be unique
- "Robot"=list(
- /obj/item/robot_parts/robot_suit,
- /obj/item/robot_parts/chest,
- /obj/item/robot_parts/head,
- /obj/item/robot_parts/l_arm,
- /obj/item/robot_parts/r_arm,
- /obj/item/robot_parts/l_leg,
- /obj/item/robot_parts/r_leg,
- /obj/item/robot_parts/robot_component/binary_communication_device,
- /obj/item/robot_parts/robot_component/radio,
- /obj/item/robot_parts/robot_component/actuator,
- /obj/item/robot_parts/robot_component/diagnosis_unit,
- /obj/item/robot_parts/robot_component/camera,
- /obj/item/robot_parts/robot_component/armour
- ),
- "Ripley"=list(
- /obj/item/mecha_parts/chassis/ripley,
- /obj/item/mecha_parts/part/ripley_torso,
- /obj/item/mecha_parts/part/ripley_left_arm,
- /obj/item/mecha_parts/part/ripley_right_arm,
- /obj/item/mecha_parts/part/ripley_left_leg,
- /obj/item/mecha_parts/part/ripley_right_leg
- ),
-// "Hoverpod"=list(
-// /obj/structure/largecrate/hoverpod // Doesn't work, even with required vars. Why? - Gamerofthegame
-// ),
- "Odysseus"=list(
- /obj/item/mecha_parts/chassis/odysseus,
- /obj/item/mecha_parts/part/odysseus_torso,
- /obj/item/mecha_parts/part/odysseus_head,
- /obj/item/mecha_parts/part/odysseus_left_arm,
- /obj/item/mecha_parts/part/odysseus_right_arm,
- /obj/item/mecha_parts/part/odysseus_left_leg,
- /obj/item/mecha_parts/part/odysseus_right_leg
- ),
+ var/list/datum/design/queue = list()
+ var/progress = 0
+ var/busy = 0
- "Gygax"=list(
- /obj/item/mecha_parts/chassis/gygax,
- /obj/item/mecha_parts/part/gygax_torso,
- /obj/item/mecha_parts/part/gygax_head,
- /obj/item/mecha_parts/part/gygax_left_arm,
- /obj/item/mecha_parts/part/gygax_right_arm,
- /obj/item/mecha_parts/part/gygax_left_leg,
- /obj/item/mecha_parts/part/gygax_right_leg,
- /obj/item/mecha_parts/part/gygax_armour
- ),
- "Durand"=list(
- /obj/item/mecha_parts/chassis/durand,
- /obj/item/mecha_parts/part/durand_torso,
- /obj/item/mecha_parts/part/durand_head,
- /obj/item/mecha_parts/part/durand_left_arm,
- /obj/item/mecha_parts/part/durand_right_arm,
- /obj/item/mecha_parts/part/durand_left_leg,
- /obj/item/mecha_parts/part/durand_right_leg,
- /obj/item/mecha_parts/part/durand_armour
- ),
- "Exosuit Equipment"=list(
- /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp,
- /obj/item/mecha_parts/mecha_equipment/tool/drill,
- /obj/item/mecha_parts/mecha_equipment/tool/extinguisher,
- /obj/item/mecha_parts/mecha_equipment/tool/cable_layer,
- /obj/item/mecha_parts/mecha_equipment/tool/sleeper,
- /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun,
- /obj/item/mecha_parts/mecha_equipment/tool/passenger,
- /obj/item/mecha_parts/chassis/firefighter,
- ///obj/item/mecha_parts/mecha_equipment/repair_droid,
- /obj/item/mecha_parts/mecha_equipment/generator,
- ///obj/item/mecha_parts/mecha_equipment/jetpack, //TODO MECHA JETPACK SPRITE MISSING
- /obj/item/mecha_parts/mecha_equipment/weapon/energy/taser,
- /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg
- ),
-
- "Robotic Upgrade Modules" = list(
- /obj/item/borg/upgrade/reset,
- /obj/item/borg/upgrade/rename,
- /obj/item/borg/upgrade/restart,
- /obj/item/borg/upgrade/vtec,
- /obj/item/borg/upgrade/tasercooler,
- /obj/item/borg/upgrade/jetpack
- ),
-
- "Misc"=list(/obj/item/mecha_parts/mecha_tracking)
- )
+ var/list/categories = list()
+ var/category = null
+ var/manufacturer = null
+ var/sync_message = ""
/obj/machinery/mecha_part_fabricator/New()
..()
@@ -134,643 +37,129 @@
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
RefreshParts()
- // part_sets["Cyborg Upgrade Modules"] = typesof(/obj/item/borg/upgrade/) - /obj/item/borg/upgrade/ // Eh. This does it dymaically, but to support having the items referenced otherwhere in the code but not being constructable, going to do it manaully.
-
- for(var/part_set in part_sets)
- convert_part_set(part_set)
files = new /datum/research(src) //Setup the research data holder.
- /*
- if(!id)
- for(var/obj/machinery/r_n_d/server/centcom/S in world)
- S.initialize()
- break
- */
return
/obj/machinery/mecha_part_fabricator/initialize()
- current_manufacturer = basic_robolimb.company
+ manufacturer = basic_robolimb.company
+ update_categories()
+
+/obj/machinery/mecha_part_fabricator/process()
+ ..()
+ if(stat)
+ return
+ if(busy)
+ use_power = 2
+ progress += speed
+ check_build()
+ else
+ use_power = 1
+ update_icon()
+
+/obj/machinery/mecha_part_fabricator/update_icon()
+ overlays.Cut()
+ if(panel_open)
+ icon_state = "fab-o"
+ else
+ icon_state = "fab-idle"
+ if(busy)
+ overlays += "fab-active"
+
+/obj/machinery/mecha_part_fabricator/dismantle()
+ for(var/f in materials)
+ eject_materials(f, -1)
+ ..()
/obj/machinery/mecha_part_fabricator/RefreshParts()
- var/T = 0
+ res_max_amount = 0
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
+ res_max_amount += M.rating * 100000 // 200k -> 600k
+ var/T = 0
+ for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
T += M.rating
- res_max_amount = (187500+(T * 37500))
- T = 0
- for(var/obj/item/weapon/stock_parts/micro_laser/Ma in component_parts)
- T += Ma.rating
- if(T >= 1)
- T -= 1
- var/diff
- diff = round(initial(resource_coeff) - (initial(resource_coeff)*(T))/25,0.01)
- if(resource_coeff!=diff)
- resource_coeff = diff
- T = 0
- for(var/obj/item/weapon/stock_parts/manipulator/Ml in component_parts)
- T += Ml.rating
- if(T>= 1)
- T -= 1
- diff = round(initial(time_coeff) - (initial(time_coeff)*(T))/25,0.01)
- if(time_coeff!=diff)
- time_coeff = diff
+ mat_efficiency = 1 - (T - 1) / 4 // 1 -> 0.5
+ for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts) // Not resetting T is intended; speed is affected by both
+ T += M.rating
+ speed = T / 2 // 1 -> 3
-/obj/machinery/mecha_part_fabricator/Destroy()
- for(var/atom/A in src)
- qdel(A)
- ..()
- return
-
-/obj/machinery/mecha_part_fabricator/proc/operation_allowed(mob/M)
- if(isrobot(M) || isAI(M))
- return 1
- if(!istype(req_access) || !req_access.len)
- return 1
- else if(istype(M, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
- for(var/ID in list(H.get_active_hand(), H.wear_id, H.belt))
- if(src.check_access(ID))
- return 1
- M << "You don't have required permissions to use [src]"
- return 0
-
-/obj/machinery/mecha_part_fabricator/proc/convert_part_set(set_name as text)
- var/list/parts = part_sets[set_name]
- if(istype(parts, /list))
- for(var/i=1;i<=parts.len;i++)
- var/path = parts[i]
- var/part = new path(src)
- if(part)
- parts[i] = part
- //debug below
- if(!istype(parts[i],/obj/item)) return 0
- return
-
-
-/obj/machinery/mecha_part_fabricator/proc/add_part_set(set_name as text,parts=null)
- if(set_name in part_sets)//attempt to create duplicate set
- return 0
- if(isnull(parts))
- part_sets[set_name] = list()
- else
- part_sets[set_name] = parts
- convert_part_set(set_name)
- return 1
-
-/obj/machinery/mecha_part_fabricator/proc/add_part_to_set(set_name as text,part)
- if(!part) return 0
- src.add_part_set(set_name)//if no "set_name" set exists, create
- var/list/part_set = part_sets[set_name]
- var/atom/apart
- if(ispath(part))
- apart = new part(src)
- else
- apart = part
- if(!istype(apart)) return 0
- for(var/obj/O in part_set)
- if(O.type == apart.type)
- qdel(apart)
- return 0
- part_set[++part_set.len] = apart
- return 1
-
-/obj/machinery/mecha_part_fabricator/proc/remove_part_set(set_name as text)
- for(var/i=1,i<=part_sets.len,i++)
- if(part_sets[i]==set_name)
- part_sets.Cut(i,++i)
- return
-/*
- proc/sanity_check()
- for(var/p in resources)
- var/index = resources.Find(p)
- index = resources.Find(p, ++index)
- if(index) //duplicate resource
- world << "Duplicate resource definition for [src](\ref[src])"
- return 0
- for(var/set_name in part_sets)
- var/index = part_sets.Find(set_name)
- index = part_sets.Find(set_name, ++index)
- if(index) //duplicate part set
- world << "Duplicate part set definition for [src](\ref[src])"
- return 0
- return 1
-*/
-
-/obj/machinery/mecha_part_fabricator/proc/output_parts_list(set_name)
- var/output = ""
- var/list/part_set = listgetindex(part_sets, set_name)
- if(istype(part_set))
- for(var/obj/item/part in part_set)
- var/resources_available = check_resources(part)
- output += ""
- return output
-
-/obj/machinery/mecha_part_fabricator/proc/output_part_info(var/obj/item/part)
- var/output = "[part.name] (Cost: [output_part_cost(part)]) [get_construction_time_w_coeff(part)/10]sec"
- return output
-
-/obj/machinery/mecha_part_fabricator/proc/output_part_cost(var/obj/item/part)
- var/i = 0
- var/output
- if(part.vars.Find("construction_time") && part.vars.Find("construction_cost"))//The most efficient way to go about this. Not all objects have these vars, but if they don't then they CANNOT be made by the mech fab. Doing it this way reduces a major amount of typecasting and switches, while cutting down maintenece for them as well -Sieve
- for(var/c in part:construction_cost)//The check should ensure that anything without the var doesn't make it to this point
- if(c in resources)
- output += "[i?" | ":null][get_resource_cost_w_coeff(part,c)] [c]"
- i++
- return output
- else
- return 0
-
-/obj/machinery/mecha_part_fabricator/proc/output_available_resources()
- var/output
- for(var/resource in resources)
- var/amount = min(res_max_amount, resources[resource])
- output += "[resource]: [amount] cm³"
- if(amount>0)
- output += " - Remove \[1\] | \[10\] | \[All\]"
- output += "
"
- return output
-
-/obj/machinery/mecha_part_fabricator/proc/remove_resources(var/obj/item/part)
-//Be SURE to add any new equipment to this switch, but don't be suprised if it spits out children objects
- if(part.vars.Find("construction_time") && part.vars.Find("construction_cost"))
- for(var/resource in part:construction_cost)
- if(resource in src.resources)
- src.resources[resource] -= get_resource_cost_w_coeff(part,resource)
- else
+/obj/machinery/mecha_part_fabricator/attack_hand(var/mob/user)
+ if(..())
return
-
-/obj/machinery/mecha_part_fabricator/proc/check_resources(var/obj/item/part)
-// if(istype(part, /obj/item/robot_parts) || istype(part, /obj/item/mecha_parts) || istype(part,/obj/item/borg/upgrade))
-//Be SURE to add any new equipment to this switch, but don't be suprised if it spits out children objects
- if(part.vars.Find("construction_time") && part.vars.Find("construction_cost"))
- for(var/resource in part:construction_cost)
- if(resource in src.resources)
- if(src.resources[resource] < get_resource_cost_w_coeff(part,resource))
- return 0
- return 1
- else
- return 0
-
-/obj/machinery/mecha_part_fabricator/proc/build_part(var/obj/item/part)
- if(!part) return
-
- // critical exploit prevention, do not remove unless you replace it -walter0o
- if( !(locate(part, src.contents)) || !(part.vars.Find("construction_time")) || !(part.vars.Find("construction_cost")) ) // these 3 are the current requirements for an object being buildable by the mech_fabricator
+ if(!allowed(user))
return
+ ui_interact(user)
- if(current_manufacturer)
- src.being_built = new part.type(src, current_manufacturer)
- else
- src.being_built = new part.type(src, basic_robolimb.company)
+/obj/machinery/mecha_part_fabricator/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ var/data[0]
- src.desc = "It's building [src.being_built]."
- src.remove_resources(part)
- src.overlays += "fab-active"
- src.use_power = 2
- src.updateUsrDialog()
- sleep(get_construction_time_w_coeff(part))
- src.use_power = 1
- src.overlays -= "fab-active"
- src.desc = initial(src.desc)
- if(being_built)
- src.being_built.Move(get_step(src,output_dir))
- src.visible_message("\icon[src] [src] beeps, \"The following has been completed: [src.being_built] is built\".")
- src.being_built = null
- src.updateUsrDialog()
- return 1
+ var/datum/design/current = queue.len ? queue[1] : null
+ if(current)
+ data["current"] = current.name
+ data["queue"] = get_queue_names()
+ data["buildable"] = get_build_options()
+ data["category"] = category
+ data["categories"] = categories
+ if(all_robolimbs)
+ var/list/T = list()
+ for(var/A in all_robolimbs)
+ var/datum/robolimb/R = all_robolimbs[A]
+ T += list(list("id" = A, "company" = R.company))
+ data["manufacturers"] = T
+ data["manufacturer"] = manufacturer
+ data["materials"] = get_materials()
+ data["maxres"] = res_max_amount
+ data["sync"] = sync_message
+ if(current)
+ data["builtperc"] = round((progress / current.time) * 100)
-/obj/machinery/mecha_part_fabricator/proc/update_queue_on_page()
- send_byjax(usr,"mecha_fabricator.browser","queue",src.list_queue())
- return
-
-/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(set_name)
- if(set_name in part_sets)
- var/list/part_set = part_sets[set_name]
- if(islist(part_set))
- for(var/obj/item/part in part_set)
- add_to_queue(part)
- return
-
-/obj/machinery/mecha_part_fabricator/proc/add_to_queue(part)
- if(!istype(queue))
- queue = list()
- if(part)
- queue[++queue.len] = part
- return queue.len
-
-/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index)
- if(!isnum(index) || !istype(queue) || (index<1 || index>queue.len))
- return 0
- queue.Cut(index,++index)
- return 1
-
-/obj/machinery/mecha_part_fabricator/proc/process_queue()
- var/obj/item/part = listgetindex(src.queue, 1)
- if(!part)
- remove_from_queue(1)
- if(src.queue.len)
- return process_queue()
- else
- return
- if(!(part.vars.Find("construction_time")) || !(part.vars.Find("construction_cost")))//If it shouldn't be printed
- remove_from_queue(1)//Take it out of the quene
- return process_queue()//Then reprocess it
- temp = null
- while(part)
- if(stat&(NOPOWER|BROKEN))
- return 0
- if(!check_resources(part))
- src.visible_message("\icon[src] [src] beeps, \"Not enough resources. Queue processing stopped\".")
- temp = {"Not enough resources to build next part.
- Try again | Return"}
- return 0
- remove_from_queue(1)
- build_part(part)
- part = listgetindex(src.queue, 1)
- src.visible_message("\icon[src] [src] beeps, \"Queue processing finished successfully\".")
- return 1
-
-/obj/machinery/mecha_part_fabricator/proc/list_queue()
- var/output = "Queue contains:"
- if(!istype(queue) || !queue.len)
- output += "
Nothing"
- else
- output += ""
- for(var/i=1;i<=queue.len;i++)
- var/obj/item/part = listgetindex(src.queue, i)
- if(istype(part))
- if(part.vars.Find("construction_time") && part.vars.Find("construction_cost"))
- output += "- [part.name] - [i>1?"↑":null] [i↓
":null] Remove"
- else//Prevents junk items from even appearing in the list, and they will be silently removed when the fab processes
- remove_from_queue(i)//Trash it
- return list_queue()//Rebuild it
- output += ""
- output += "\[Process queue | Clear queue\]"
- return output
-
-/obj/machinery/mecha_part_fabricator/proc/convert_designs()
- if(!files) return
- var/i = 0
- for(var/datum/design/D in files.known_designs)
- if(D.build_type&16)
- if(D.category in part_sets)//Checks if it's a valid category
- if(add_part_to_set(D.category, D.build_path))//Adds it to said category
- i++
- else
- if(add_part_to_set("Misc", D.build_path))//If in doubt, chunk it into the Misc
- i++
- return i
-
-/obj/machinery/mecha_part_fabricator/proc/update_tech()
- if(!files) return
- var/output
- for(var/datum/tech/T in files.known_tech)
- if(T && T.level > 1)
- var/diff
- switch(T.id) //bad, bad formulas
- if("materials")
- var/pmat = 0//Calculations to make up for the fact that these parts and tech modify the same thing
- for(var/obj/item/weapon/stock_parts/micro_laser/Ml in component_parts)
- pmat += Ml.rating
- if(pmat >= 1)
- pmat -= 1//So the equations don't have to be reworked, upgrading a single part from T1 to T2 is == to 1 tech level
- diff = round(initial(resource_coeff) - (initial(resource_coeff)*(T.level+pmat))/25,0.01)
- if(resource_coeff!=diff)
- resource_coeff = diff
- output+="Production efficiency increased.
"
- if("programming")
- var/ptime = 0
- for(var/obj/item/weapon/stock_parts/manipulator/Ma in component_parts)
- ptime += Ma.rating
- if(ptime >= 2)
- ptime -= 2
- diff = round(initial(time_coeff) - (initial(time_coeff)*(T.level+ptime))/25,0.1)
- if(time_coeff!=diff)
- time_coeff = diff
- output+="Production routines updated.
"
- return output
-
-
-/obj/machinery/mecha_part_fabricator/proc/sync(silent=null)
-/* if(queue.len)
- if(!silent)
- temp = "Error. Please clear processing queue before updating!"
- src.updateUsrDialog()
- return
-*/
- if(!silent)
- temp = "Updating local R&D database..."
- src.updateUsrDialog()
- sleep(30) //only sleep if called by user
- var/found = 0
- for(var/obj/machinery/computer/rdconsole/RDC in get_area_all_atoms(get_area(src)))
- if(!RDC.sync)
- continue
- found++
- for(var/datum/tech/T in RDC.files.known_tech)
- files.AddTech2Known(T)
- for(var/datum/design/D in RDC.files.known_designs)
- files.AddDesign2Known(D)
- files.RefreshResearch()
- var/i = src.convert_designs()
- var/tech_output = update_tech()
- if(!silent)
- temp = "Processed [i] equipment designs.
"
- temp += tech_output
- temp += "Return"
- src.updateUsrDialog()
- if(i || tech_output)
- src.visible_message("\icon[src] [src] beeps, \"Successfully synchronized with R&D server. New data processed.\"")
- if(found == 0)
- temp = "Couldn't contact R&D server.
"
- temp += "Return"
- src.updateUsrDialog()
- src.visible_message("\icon[src] [src] beeps, \"Error! Couldn't connect to R&D server.\"")
- return
-
-/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(var/obj/item/part as obj,var/resource as text, var/roundto=1)
-//Be SURE to add any new equipment to this switch, but don't be suprised if it spits out children objects
- if(part.vars.Find("construction_time") && part.vars.Find("construction_cost"))
- return round(part:construction_cost[resource]*resource_coeff, roundto)
- else
- return 0
-
-/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(var/obj/item/part as obj, var/roundto=1)
-//Be SURE to add any new equipment to this switch, but don't be suprised if it spits out children objects
- if(part.vars.Find("construction_time") && part.vars.Find("construction_cost"))
- return round(part:construction_time*time_coeff, roundto)
- else
- return 0
-
-
-/obj/machinery/mecha_part_fabricator/attack_hand(mob/user as mob)
- var/dat, left_part
- if (..())
- return
- if(!operation_allowed(user))
- return
- user.set_machine(src)
- var/turf/exit = get_step(src,SOUTH)
- if(exit.density)
- src.visible_message("\icon[src] [src] beeps, \"Error! Part outlet is obstructed\".")
- return
- if(temp)
- left_part = temp
- else if(src.being_built)
- left_part = {"Building [src.being_built.name].
- Please wait until completion..."}
- else
- switch(screen)
- if("main")
- left_part = output_available_resources()+"
"
- left_part += "Sync with R&D servers | Set manufacturer ([current_manufacturer])
"
- for(var/part_set in part_sets)
- left_part += "[part_set] - \[Add all parts to queue\]
"
- if("parts")
- left_part += output_parts_list(part_set)
- left_part += "
Return"
- dat = {"
-
- [src.name]
-
-
-
-
-
-
- |
- [left_part]
- |
-
- [list_queue()]
- |
-
-
-
- "}
- user << browse(dat, "window=mecha_fabricator;size=1000x400")
- onclose(user, "mecha_fabricator")
- return
-
-/obj/machinery/mecha_part_fabricator/proc/exploit_prevention(var/obj/Part, mob/user as mob, var/desc_exploit)
-// critical exploit prevention, feel free to improve or replace this, but do not remove it -walter0o
-
- if(!Part || !user || !istype(Part) || !istype(user)) // sanity
- return 1
-
- if( !(locate(Part, src.contents)) || !(Part.vars.Find("construction_time")) || !(Part.vars.Find("construction_cost")) ) // these 3 are the current requirements for an object being buildable by the mech_fabricator
-
- var/turf/LOC = get_turf(user)
- message_admins("[key_name_admin(user)] tried to exploit an Exosuit Fabricator to [desc_exploit ? "get the desc of" : "duplicate"] [Part] ! ([LOC ? "JMP" : "null"])", 0)
- log_admin("EXPLOIT : [key_name(user)] tried to exploit an Exosuit Fabricator to [desc_exploit ? "get the desc of" : "duplicate"] [Part] !")
- return 1
-
- return null
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "mechfab.tmpl", "Exosuit Fabricator UI", 800, 600)
+ ui.set_initial_data(data)
+ ui.open()
+ ui.set_auto_update(1)
/obj/machinery/mecha_part_fabricator/Topic(href, href_list)
-
- if(..()) // critical exploit prevention, do not remove unless you replace it -walter0o
+ if(..())
return
- var/datum/topic_input/filter = new /datum/topic_input(href,href_list)
- if(href_list["set_manufacturer"])
- var/choice = input(usr, "Which manufacturer do you wish to use for this fabricator?") as null|anything in all_robolimbs
- if(choice) current_manufacturer = choice
- if(href_list["part_set"])
- var/tpart_set = filter.getStr("part_set")
- if(tpart_set)
- if(tpart_set=="clear")
- src.part_set = null
- else
- src.part_set = tpart_set
- screen = "parts"
- if(href_list["part"])
- var/obj/part = filter.getObj("part")
+ if(href_list["build"])
+ add_to_queue(text2num(href_list["build"]))
- // critical exploit prevention, do not remove unless you replace it -walter0o
- if(src.exploit_prevention(part, usr))
- return
+ if(href_list["remove"])
+ remove_from_queue(text2num(href_list["remove"]))
- if(!processing_queue)
- build_part(part)
- else
- add_to_queue(part)
- if(href_list["add_to_queue"])
- var/obj/part = filter.getObj("add_to_queue")
+ if(href_list["category"])
+ if(href_list["category"] in categories)
+ category = href_list["category"]
- // critical exploit prevention, do not remove unless you replace it -walter0o
- if(src.exploit_prevention(part, usr))
- return
+ if(href_list["manufacturer"])
+ if(href_list["manufacturer"] in all_robolimbs)
+ manufacturer = href_list["manufacturer"]
- add_to_queue(part)
+ if(href_list["eject"])
+ eject_materials(href_list["eject"], text2num(href_list["amount"]))
- return update_queue_on_page()
- if(href_list["remove_from_queue"])
- remove_from_queue(filter.getNum("remove_from_queue"))
- return update_queue_on_page()
- if(href_list["partset_to_queue"])
- add_part_set_to_queue(filter.get("partset_to_queue"))
- return update_queue_on_page()
- if(href_list["process_queue"])
- spawn(-1)
- if(processing_queue || being_built)
- return 0
- processing_queue = 1
- process_queue()
- processing_queue = 0
-/*
- if(href_list["list_queue"])
- list_queue()
-*/
- if(href_list["clear_temp"])
- temp = null
- if(href_list["screen"])
- src.screen = href_list["screen"]
- if(href_list["queue_move"] && href_list["index"])
- var/index = filter.getNum("index")
- var/new_index = index + filter.getNum("queue_move")
- if(isnum(index) && isnum(new_index))
- if(InRange(new_index,1,queue.len))
- queue.Swap(index,new_index)
- return update_queue_on_page()
- if(href_list["clear_queue"])
- queue = list()
- return update_queue_on_page()
if(href_list["sync"])
- queue = list()
- src.sync()
- return update_queue_on_page()
- if(href_list["part_desc"])
- var/obj/part = filter.getObj("part_desc")
-
- // critical exploit prevention, do not remove unless you replace it -walter0o
- if(src.exploit_prevention(part, usr, 1))
- return
-
- if(part)
- temp = {"[part] description:
- [part.desc]
- Return
- "}
- if(href_list["remove_mat"] && href_list["material"])
- temp = "Ejected [remove_material(href_list["material"],text2num(href_list["remove_mat"]))] of [href_list["material"]]
Return"
- src.updateUsrDialog()
- return
-
-/obj/machinery/mecha_part_fabricator/proc/remove_material(var/mat_string, var/amount)
- var/type
- switch(mat_string)
- if(DEFAULT_WALL_MATERIAL)
- type = /obj/item/stack/material/steel
- if("glass")
- type = /obj/item/stack/material/glass
- if("gold")
- type = /obj/item/stack/material/gold
- if("silver")
- type = /obj/item/stack/material/silver
- if("diamond")
- type = /obj/item/stack/material/diamond
- if("phoron")
- type = /obj/item/stack/material/phoron
- if("uranium")
- type = /obj/item/stack/material/uranium
- else
- return 0
- var/result = 0
- var/obj/item/stack/material/res = new type(src)
-
- // amount available to take out
- var/total_amount = round(resources[mat_string]/res.perunit)
-
- // number of stacks we're going to take out
- res.amount = round(min(total_amount,amount))
-
- if(res.amount>0)
- resources[mat_string] -= res.amount*res.perunit
- res.Move(src.loc)
- result = res.amount
+ sync()
else
- qdel(res)
- return result
+ sync_message = ""
+
+ return 1
-/obj/machinery/mecha_part_fabricator/emag_act(var/remaining_charges, var/mob/user)
- sleep()
- switch(emagged)
- if(0)
- emagged = 0.5
- src.visible_message("\icon[src] [src] beeps: \"DB error \[Code 0x00F1\]\"")
- sleep(10)
- src.visible_message("\icon[src] [src] beeps: \"Attempting auto-repair\"")
- sleep(15)
- src.visible_message("\icon[src] [src] beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"")
- sleep(30)
- src.visible_message("\icon[src] [src] beeps: \"User DB truncated. Please contact your [company_name] system operator for future assistance.\"")
- req_access = null
- emagged = 1
- return 1
- if(0.5)
- src.visible_message("\icon[src] [src] beeps: \"DB not responding \[Code 0x0003\]...\"")
- if(1)
- src.visible_message("\icon[src] [src] beeps: \"No records in User DB\"")
-
-/obj/machinery/mecha_part_fabricator/attackby(obj/W as obj, mob/user as mob)
- if(istype(W,/obj/item/weapon/screwdriver))
- if (!opened)
- opened = 1
- icon_state = "fab-o"
- user << "You open the maintenance hatch of [src]."
- else
- opened = 0
- icon_state = "fab-idle"
- user << "You close the maintenance hatch of [src]."
+/obj/machinery/mecha_part_fabricator/attackby(var/obj/item/I, var/mob/user)
+ if(busy)
+ user << "\The [src] is busy. Please wait for completion of previous operation."
+ return 1
+ if(default_deconstruction_screwdriver(user, I))
+ return
+ if(default_deconstruction_crowbar(user, I))
+ return
+ if(default_part_replacement(user, I))
return
- if (opened)
- if(istype(W, /obj/item/weapon/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)
- I.loc = src.loc
- if(src.resources[DEFAULT_WALL_MATERIAL] >= 3750)
- var/obj/item/stack/material/steel/G = new /obj/item/stack/material/steel(src.loc)
- G.amount = round(src.resources[DEFAULT_WALL_MATERIAL] / G.perunit)
- if(src.resources["glass"] >= 3750)
- var/obj/item/stack/material/glass/G = new /obj/item/stack/material/glass(src.loc)
- G.amount = round(src.resources["glass"] / G.perunit)
- if(src.resources["phoron"] >= 2000)
- var/obj/item/stack/material/phoron/G = new /obj/item/stack/material/phoron(src.loc)
- G.amount = round(src.resources["phoron"] / G.perunit)
- if(src.resources["silver"] >= 2000)
- var/obj/item/stack/material/silver/G = new /obj/item/stack/material/silver(src.loc)
- G.amount = round(src.resources["silver"] / G.perunit)
- if(src.resources["gold"] >= 2000)
- var/obj/item/stack/material/gold/G = new /obj/item/stack/material/gold(src.loc)
- G.amount = round(src.resources["gold"] / G.perunit)
- if(src.resources["uranium"] >= 2000)
- var/obj/item/stack/material/uranium/G = new /obj/item/stack/material/uranium(src.loc)
- G.amount = round(src.resources["uranium"] / G.perunit)
- if(src.resources["diamond"] >= 2000)
- var/obj/item/stack/material/diamond/G = new /obj/item/stack/material/diamond(src.loc)
- G.amount = round(src.resources["diamond"] / G.perunit)
- qdel(src)
- return 1
- else
- user << "You can't load the [src.name] while it's opened."
- return 1
var/material
- switch(W.type)
+ switch(I.type)
if(/obj/item/stack/material/gold)
material = "gold"
if(/obj/item/stack/material/silver)
@@ -788,30 +177,171 @@
else
return ..()
- if(src.being_built)
- user << "The fabricator is currently processing. Please wait until completion."
- return
-
- var/obj/item/stack/material/stack = W
-
+ var/obj/item/stack/material/stack = I
var/sname = "[stack.name]"
var/amnt = stack.perunit
- if(src.resources[material] < res_max_amount)
+
+ if(materials[material] + amnt <= res_max_amount)
if(stack && stack.amount >= 1)
var/count = 0
- src.overlays += "fab-load-[material]"//loading animation is now an overlay based on material type. No more spontaneous conversion of all ores to metal. -vey
- sleep(10)
-
- while(src.resources[material] < res_max_amount && stack.amount >= 1)
- src.resources[material] += amnt
+ overlays += "fab-load-metal"
+ spawn(10)
+ overlays -= "fab-load-metal"
+ while(materials[material] + amnt <= res_max_amount && stack.amount >= 1)
+ materials[material] += amnt
stack.use(1)
count++
- src.overlays -= "fab-load-[material]"
user << "You insert [count] [sname] into the fabricator."
- src.updateUsrDialog()
- else
- user << "The fabricator can only accept full sheets of [sname]."
- return
+ update_busy()
else
user << "The fabricator cannot hold more [sname]."
- return
+
+/obj/machinery/mecha_part_fabricator/emag_act(var/remaining_charges, var/mob/user)
+ switch(emagged)
+ if(0)
+ emagged = 0.5
+ visible_message("\icon[src] [src] beeps: \"DB error \[Code 0x00F1\]\"")
+ sleep(10)
+ visible_message("\icon[src] [src] beeps: \"Attempting auto-repair\"")
+ sleep(15)
+ visible_message("\icon[src] [src] beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"")
+ sleep(30)
+ visible_message("\icon[src] [src] beeps: \"User DB truncated. Please contact your [company_name] system operator for future assistance.\"")
+ req_access = null
+ emagged = 1
+ return 1
+ if(0.5)
+ visible_message("\icon[src] [src] beeps: \"DB not responding \[Code 0x0003\]...\"")
+ if(1)
+ visible_message("\icon[src] [src] beeps: \"No records in User DB\"")
+
+/obj/machinery/mecha_part_fabricator/proc/update_busy()
+ if(queue.len)
+ if(can_build(queue[1]))
+ busy = 1
+ else
+ busy = 0
+ else
+ busy = 0
+
+/obj/machinery/mecha_part_fabricator/proc/add_to_queue(var/index)
+ var/datum/design/D = files.known_designs[index]
+ queue += D
+ update_busy()
+
+/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(var/index)
+ if(index == 1)
+ progress = 0
+ queue.Cut(index, index + 1)
+ update_busy()
+
+/obj/machinery/mecha_part_fabricator/proc/can_build(var/datum/design/D)
+ for(var/M in D.materials)
+ if(materials[M] < D.materials[M])
+ return 0
+ return 1
+
+/obj/machinery/mecha_part_fabricator/proc/check_build()
+ if(!queue.len)
+ progress = 0
+ return
+ var/datum/design/D = queue[1]
+ if(!can_build(D))
+ progress = 0
+ return
+ if(D.time > progress)
+ return
+ for(var/M in D.materials)
+ materials[M] = max(0, materials[M] - D.materials[M] * mat_efficiency)
+ if(D.build_path)
+ var/obj/new_item = new D.build_path(loc, manufacturer)
+ visible_message("\The [src] pings, indicating that \the [D] is complete.", "You hear a ping.")
+ if(mat_efficiency != 1)
+ if(new_item.matter && new_item.matter.len > 0)
+ for(var/i in new_item.matter)
+ new_item.matter[i] = new_item.matter[i] * mat_efficiency
+ remove_from_queue(1)
+
+/obj/machinery/mecha_part_fabricator/proc/get_queue_names()
+ . = list()
+ for(var/i = 2 to queue.len)
+ var/datum/design/D = queue[i]
+ . += D.name
+
+/obj/machinery/mecha_part_fabricator/proc/get_build_options()
+ . = list()
+ for(var/i = 1 to files.known_designs.len)
+ var/datum/design/D = files.known_designs[i]
+ if(!D.build_path || !(D.build_type & MECHFAB))
+ continue
+ . += list(list("name" = D.name, "id" = i, "category" = D.category, "resourses" = get_design_resourses(D), "time" = get_design_time(D)))
+
+/obj/machinery/mecha_part_fabricator/proc/get_design_resourses(var/datum/design/D)
+ var/list/F = list()
+ for(var/T in D.materials)
+ F += "[capitalize(T)]: [D.materials[T] * mat_efficiency]"
+ return english_list(F, and_text = ", ")
+
+/obj/machinery/mecha_part_fabricator/proc/get_design_time(var/datum/design/D)
+ return time2text(round(10 * D.time / speed), "mm:ss")
+
+/obj/machinery/mecha_part_fabricator/proc/update_categories()
+ categories = list()
+ for(var/datum/design/D in files.known_designs)
+ if(!D.build_path || !(D.build_type & MECHFAB))
+ continue
+ categories |= D.category
+ if(!category || !(category in categories))
+ category = categories[1]
+
+/obj/machinery/mecha_part_fabricator/proc/get_materials()
+ . = list()
+ for(var/T in materials)
+ . += list(list("mat" = capitalize(T), "amt" = materials[T]))
+
+/obj/machinery/mecha_part_fabricator/proc/eject_materials(var/material, var/amount) // 0 amount = 0 means ejecting a full stack; -1 means eject everything
+ var/recursive = amount == -1 ? 1 : 0
+ material = lowertext(material)
+ var/mattype
+ switch(material)
+ if(DEFAULT_WALL_MATERIAL)
+ mattype = /obj/item/stack/material/steel
+ if("glass")
+ mattype = /obj/item/stack/material/glass
+ if("gold")
+ mattype = /obj/item/stack/material/gold
+ if("silver")
+ mattype = /obj/item/stack/material/silver
+ if("diamond")
+ mattype = /obj/item/stack/material/diamond
+ if("phoron")
+ mattype = /obj/item/stack/material/phoron
+ if("uranium")
+ mattype = /obj/item/stack/material/uranium
+ else
+ return
+ var/obj/item/stack/material/S = new mattype(loc)
+ if(amount <= 0)
+ amount = S.max_amount
+ var/ejected = min(round(materials[material] / S.perunit), amount)
+ S.amount = min(ejected, amount)
+ if(S.amount <= 0)
+ qdel(S)
+ return
+ materials[material] -= ejected * S.perunit
+ if(recursive && materials[material] >= S.perunit)
+ eject_materials(material, -1)
+ update_busy()
+
+/obj/machinery/mecha_part_fabricator/proc/sync()
+ sync_message = "Error: no console found."
+ for(var/obj/machinery/computer/rdconsole/RDC in get_area_all_atoms(get_area(src)))
+ if(!RDC.sync)
+ continue
+ for(var/datum/tech/T in RDC.files.known_tech)
+ files.AddTech2Known(T)
+ for(var/datum/design/D in RDC.files.known_designs)
+ files.AddDesign2Known(D)
+ files.RefreshResearch()
+ sync_message = "Sync complete."
+ update_categories()
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 573ede3fb0..270227a2fc 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -1455,7 +1455,7 @@
if(href_list["rfreq"])
if(usr != src.occupant) return
var/new_frequency = (radio.frequency + filter.getNum("rfreq"))
- if (!radio.freerange || (radio.frequency < 1200 || radio.frequency > 1600))
+ if ((radio.frequency < PUBLIC_LOW_FREQ || radio.frequency > PUBLIC_HIGH_FREQ))
new_frequency = sanitize_frequency(new_frequency)
radio.set_frequency(new_frequency)
send_byjax(src.occupant,"exosuit.browser","rfreq","[format_frequency(radio.frequency)]")
diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm
index e3bee7a816..e9dbd93edf 100644
--- a/code/game/mecha/mecha_control_console.dm
+++ b/code/game/mecha/mecha_control_console.dm
@@ -70,8 +70,6 @@
icon = 'icons/obj/device.dmi'
icon_state = "motion2"
origin_tech = list(TECH_DATA = 2, TECH_MAGNET = 2)
- construction_time = 50
- construction_cost = list(DEFAULT_WALL_MATERIAL=500)
proc/get_mecha_info()
if(!in_mecha())
diff --git a/code/game/mecha/mecha_parts.dm b/code/game/mecha/mecha_parts.dm
index fbc6a1d7aa..876e6c3f6b 100644
--- a/code/game/mecha/mecha_parts.dm
+++ b/code/game/mecha/mecha_parts.dm
@@ -11,15 +11,12 @@
w_class = 5
flags = CONDUCT
origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2)
- var/construction_time = 100
- var/list/construction_cost = list(DEFAULT_WALL_MATERIAL=20000,"glass"=5000)
/obj/item/mecha_parts/chassis
name="Mecha Chassis"
icon_state = "backbone"
var/datum/construction/construct
- construction_cost = list(DEFAULT_WALL_MATERIAL=20000)
flags = CONDUCT
attackby(obj/item/W as obj, mob/user as mob)
@@ -42,48 +39,37 @@
/obj/item/mecha_parts/part/ripley_torso
name="Ripley Torso"
desc="A torso part of Ripley APLU. Contains power unit, processing core and life support systems."
- icon_state = "ripley_harness"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_ENGINEERING = 2)
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=40000,"glass"=15000)
+ icon_state = "ripley_harness"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_ENGINEERING = 2)
/obj/item/mecha_parts/part/ripley_left_arm
name="Ripley Left Arm"
desc="A Ripley APLU left arm. Data and power sockets are compatible with most exosuit tools."
- icon_state = "ripley_l_arm"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
- construction_time = 150
- construction_cost = list(DEFAULT_WALL_MATERIAL=25000)
+ icon_state = "ripley_l_arm"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
/obj/item/mecha_parts/part/ripley_right_arm
name="Ripley Right Arm"
desc="A Ripley APLU right arm. Data and power sockets are compatible with most exosuit tools."
- icon_state = "ripley_r_arm"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
- construction_time = 150
- construction_cost = list(DEFAULT_WALL_MATERIAL=25000)
+ icon_state = "ripley_r_arm"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
/obj/item/mecha_parts/part/ripley_left_leg
name="Ripley Left Leg"
desc="A Ripley APLU left leg. Contains somewhat complex servodrives and balance maintaining systems."
- icon_state = "ripley_l_leg"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
- construction_time = 150
- construction_cost = list(DEFAULT_WALL_MATERIAL=30000)
+ icon_state = "ripley_l_leg"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
/obj/item/mecha_parts/part/ripley_right_leg
name="Ripley Right Leg"
desc="A Ripley APLU right leg. Contains somewhat complex servodrives and balance maintaining systems."
- icon_state = "ripley_r_leg"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
- construction_time = 150
- construction_cost = list(DEFAULT_WALL_MATERIAL=30000)
+ icon_state = "ripley_r_leg"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
///////// Gygax
/obj/item/mecha_parts/chassis/gygax
name = "Gygax Chassis"
- construction_cost = list(DEFAULT_WALL_MATERIAL=25000)
New()
..()
@@ -92,62 +78,47 @@
/obj/item/mecha_parts/part/gygax_torso
name="Gygax Torso"
desc="A torso part of Gygax. Contains power unit, processing core and life support systems. Has an additional equipment slot."
- icon_state = "gygax_harness"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_BIO = 3, TECH_ENGINEERING = 3)
- construction_time = 300
- construction_cost = list(DEFAULT_WALL_MATERIAL=50000,"glass"=20000)
+ icon_state = "gygax_harness"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_BIO = 3, TECH_ENGINEERING = 3)
/obj/item/mecha_parts/part/gygax_head
name="Gygax Head"
desc="A Gygax head. Houses advanced surveilance and targeting sensors."
- icon_state = "gygax_head"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_MAGNET = 3, TECH_ENGINEERING = 3)
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=20000,"glass"=10000)
+ icon_state = "gygax_head"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_MAGNET = 3, TECH_ENGINEERING = 3)
/obj/item/mecha_parts/part/gygax_left_arm
name="Gygax Left Arm"
desc="A Gygax left arm. Data and power sockets are compatible with most exosuit tools and weapons."
- icon_state = "gygax_l_arm"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 3)
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=30000)
+ icon_state = "gygax_l_arm"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 3)
/obj/item/mecha_parts/part/gygax_right_arm
name="Gygax Right Arm"
desc="A Gygax right arm. Data and power sockets are compatible with most exosuit tools and weapons."
- icon_state = "gygax_r_arm"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 3)
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=30000)
+ icon_state = "gygax_r_arm"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 3)
/obj/item/mecha_parts/part/gygax_left_leg
name="Gygax Left Leg"
- icon_state = "gygax_l_leg"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 3)
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=35000)
+ icon_state = "gygax_l_leg"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 3)
/obj/item/mecha_parts/part/gygax_right_leg
name="Gygax Right Leg"
- icon_state = "gygax_r_leg"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 3)
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=35000)
+ icon_state = "gygax_r_leg"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 3)
/obj/item/mecha_parts/part/gygax_armour
name="Gygax Armour Plates"
- icon_state = "gygax_armour"
- origin_tech = list(TECH_MATERIAL = 6, TECH_COMBAT = 4, TECH_ENGINEERING = 5)
- construction_time = 600
- construction_cost = list(DEFAULT_WALL_MATERIAL=50000,"diamond"=10000)
+ icon_state = "gygax_armour"
+ origin_tech = list(TECH_MATERIAL = 6, TECH_COMBAT = 4, TECH_ENGINEERING = 5)
//////////// Durand
/obj/item/mecha_parts/chassis/durand
name = "Durand Chassis"
- construction_cost = list(DEFAULT_WALL_MATERIAL=25000)
New()
..()
@@ -155,52 +126,38 @@
/obj/item/mecha_parts/part/durand_torso
name="Durand Torso"
- icon_state = "durand_harness"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 3, TECH_BIO = 3, TECH_ENGINEERING = 3)
- construction_time = 300
- construction_cost = list(DEFAULT_WALL_MATERIAL=55000,"glass"=20000,"silver"=10000)
+ icon_state = "durand_harness"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 3, TECH_BIO = 3, TECH_ENGINEERING = 3)
/obj/item/mecha_parts/part/durand_head
name="Durand Head"
- icon_state = "durand_head"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 3, TECH_MAGNET = 3, TECH_ENGINEERING = 3)
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=25000,"glass"=10000,"silver"=3000)
+ icon_state = "durand_head"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 3, TECH_MAGNET = 3, TECH_ENGINEERING = 3)
/obj/item/mecha_parts/part/durand_left_arm
name="Durand Left Arm"
- icon_state = "durand_l_arm"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 3, TECH_ENGINEERING = 3)
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=35000,"silver"=3000)
+ icon_state = "durand_l_arm"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 3, TECH_ENGINEERING = 3)
/obj/item/mecha_parts/part/durand_right_arm
name="Durand Right Arm"
- icon_state = "durand_r_arm"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 3, TECH_ENGINEERING = 3)
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=35000,"silver"=3000)
+ icon_state = "durand_r_arm"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 3, TECH_ENGINEERING = 3)
/obj/item/mecha_parts/part/durand_left_leg
name="Durand Left Leg"
- icon_state = "durand_l_leg"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 3, TECH_ENGINEERING = 3)
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=40000,"silver"=3000)
+ icon_state = "durand_l_leg"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 3, TECH_ENGINEERING = 3)
/obj/item/mecha_parts/part/durand_right_leg
name="Durand Right Leg"
- icon_state = "durand_r_leg"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 3, TECH_ENGINEERING = 3)
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=40000,"silver"=3000)
+ icon_state = "durand_r_leg"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 3, TECH_ENGINEERING = 3)
/obj/item/mecha_parts/part/durand_armour
name="Durand Armour Plates"
- icon_state = "durand_armour"
- origin_tech = list(TECH_MATERIAL = 5, TECH_COMBAT = 4, TECH_ENGINEERING = 5)
- construction_time = 600
- construction_cost = list(DEFAULT_WALL_MATERIAL=50000,"uranium"=10000)
+ icon_state = "durand_armour"
+ origin_tech = list(TECH_MATERIAL = 5, TECH_COMBAT = 4, TECH_ENGINEERING = 5)
@@ -247,43 +204,43 @@
/obj/item/mecha_parts/part/phazon_torso
name="Phazon Torso"
icon_state = "phazon_harness"
- construction_time = 300
- construction_cost = list(DEFAULT_WALL_MATERIAL=35000,"glass"=10000,"phoron"=20000)
+ //construction_time = 300
+ //construction_cost = list(DEFAULT_WALL_MATERIAL=35000,"glass"=10000,"phoron"=20000)
origin_tech = list(TECH_DATA = 5, TECH_MATERIAL = 7, TECH_BLUESPACE = 6, TECH_POWER = 6)
/obj/item/mecha_parts/part/phazon_head
name="Phazon Head"
icon_state = "phazon_head"
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=15000,"glass"=5000,"phoron"=10000)
+ //construction_time = 200
+ //construction_cost = list(DEFAULT_WALL_MATERIAL=15000,"glass"=5000,"phoron"=10000)
origin_tech = list(TECH_DATA = 4, TECH_MATERIAL = 5, TECH_MAGNET = 6)
/obj/item/mecha_parts/part/phazon_left_arm
name="Phazon Left Arm"
icon_state = "phazon_l_arm"
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=20000,"phoron"=10000)
+ //construction_time = 200
+ //construction_cost = list(DEFAULT_WALL_MATERIAL=20000,"phoron"=10000)
origin_tech = list(TECH_MATERIAL = 5, TECH_BLUESPACE = 2, TECH_MAGNET = 2)
/obj/item/mecha_parts/part/phazon_right_arm
name="Phazon Right Arm"
icon_state = "phazon_r_arm"
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=20000,"phoron"=10000)
+ //construction_time = 200
+ //construction_cost = list(DEFAULT_WALL_MATERIAL=20000,"phoron"=10000)
origin_tech = list(TECH_MATERIAL = 5, TECH_BLUESPACE = 2, TECH_MAGNET = 2)
/obj/item/mecha_parts/part/phazon_left_leg
name="Phazon Left Leg"
icon_state = "phazon_l_leg"
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=20000,"phoron"=10000)
+ //construction_time = 200
+ //construction_cost = list(DEFAULT_WALL_MATERIAL=20000,"phoron"=10000)
origin_tech = list(TECH_MATERIAL = 5, TECH_BLUESPACE = 3, TECH_MAGNET = 3)
/obj/item/mecha_parts/part/phazon_right_leg
name="Phazon Right Leg"
icon_state = "phazon_r_leg"
- construction_time = 200
- construction_cost = list(DEFAULT_WALL_MATERIAL=20000,"phoron"=10000)
+ //construction_time = 200
+ //construction_cost = list(DEFAULT_WALL_MATERIAL=20000,"phoron"=10000)
origin_tech = list(TECH_MATERIAL = 5, TECH_BLUESPACE = 3, TECH_MAGNET = 3)
///////// Odysseus
@@ -299,49 +256,37 @@
/obj/item/mecha_parts/part/odysseus_head
name="Odysseus Head"
icon_state = "odysseus_head"
- construction_time = 100
- construction_cost = list(DEFAULT_WALL_MATERIAL=2000,"glass"=10000)
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 2)
/obj/item/mecha_parts/part/odysseus_torso
name="Odysseus Torso"
desc="A torso part of Odysseus. Contains power unit, processing core and life support systems."
- icon_state = "odysseus_torso"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_ENGINEERING = 2)
- construction_time = 180
- construction_cost = list(DEFAULT_WALL_MATERIAL=25000)
+ icon_state = "odysseus_torso"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_ENGINEERING = 2)
/obj/item/mecha_parts/part/odysseus_left_arm
name="Odysseus Left Arm"
desc="An Odysseus left arm. Data and power sockets are compatible with most exosuit tools."
- icon_state = "odysseus_l_arm"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
- construction_time = 120
- construction_cost = list(DEFAULT_WALL_MATERIAL=10000)
+ icon_state = "odysseus_l_arm"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
/obj/item/mecha_parts/part/odysseus_right_arm
name="Odysseus Right Arm"
desc="An Odysseus right arm. Data and power sockets are compatible with most exosuit tools."
- icon_state = "odysseus_r_arm"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
- construction_time = 120
- construction_cost = list(DEFAULT_WALL_MATERIAL=10000)
+ icon_state = "odysseus_r_arm"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
/obj/item/mecha_parts/part/odysseus_left_leg
name="Odysseus Left Leg"
desc="An Odysseus left leg. Contains somewhat complex servodrives and balance maintaining systems."
- icon_state = "odysseus_l_leg"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
- construction_time = 130
- construction_cost = list(DEFAULT_WALL_MATERIAL=15000)
+ icon_state = "odysseus_l_leg"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
/obj/item/mecha_parts/part/odysseus_right_leg
name="Odysseus Right Leg"
desc="A Odysseus right leg. Contains somewhat complex servodrives and balance maintaining systems."
- icon_state = "odysseus_r_leg"
- origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
- construction_time = 130
- construction_cost = list(DEFAULT_WALL_MATERIAL=15000)
+ icon_state = "odysseus_r_leg"
+ origin_tech = list(TECH_DATA = 2, TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
/*/obj/item/mecha_parts/part/odysseus_armour
name="Odysseus Carapace"
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index e5f769858f..9dfe1c3b19 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -4,6 +4,7 @@
icon_state = "x2"
anchored = 1.0
unacidable = 1
+ simulated = 0
/obj/effect/landmark/New()
..()
diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm
index 1b32185ace..b081530e10 100644
--- a/code/game/objects/explosion.dm
+++ b/code/game/objects/explosion.dm
@@ -1,8 +1,6 @@
//TODO: Flash range does nothing currently
-///// Z-Level Stuff
-proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = 1)
-///// Z-Level Stuff
+proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = UP|DOWN)
src = null //so we don't abort once src is deleted
spawn(0)
if(config.use_recursive_explosions)
@@ -14,23 +12,19 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
epicenter = get_turf(epicenter)
if(!epicenter) return
-///// Z-Level Stuff
- if(z_transfer && (devastation_range > 0 || heavy_impact_range > 0))
- //transfer the explosion in both directions
- explosion_z_transfer(epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range)
-///// Z-Level Stuff
+ // Handles recursive propagation of explosions.
+ if(devastation_range > 2 || heavy_impact_range > 2)
+ if(HasAbove(epicenter.z) && z_transfer & UP)
+ explosion(GetAbove(epicenter), max(0, devastation_range - 2), max(0, heavy_impact_range - 2), max(0, light_impact_range - 2), max(0, flash_range - 2), 0, UP)
+ if(HasBelow(epicenter.z) && z_transfer & DOWN)
+ explosion(GetAbove(epicenter), max(0, devastation_range - 2), max(0, heavy_impact_range - 2), max(0, light_impact_range - 2), max(0, flash_range - 2), 0, DOWN)
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flash_range)
- //playsound(epicenter, 'sound/effects/explosionfar.ogg', 100, 1, round(devastation_range*2,1) )
- //playsound(epicenter, "explosion", 100, 1, round(devastation_range,1) )
-// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
-
-// Stereo users will also hear the direction of the explosion!
-
-// Calculate far explosion sound range. Only allow the sound effect for heavy/devastating explosions.
-
-// 3/7/14 will calculate to 80 + 35
+ // Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
+ // Stereo users will also hear the direction of the explosion!
+ // Calculate far explosion sound range. Only allow the sound effect for heavy/devastating explosions.
+ // 3/7/14 will calculate to 80 + 35
var/far_dist = 0
far_dist += heavy_impact_range * 5
far_dist += devastation_range * 20
@@ -62,10 +56,6 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (JMP)")
log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ")
-// var/lighting_controller_was_processing = lighting_controller.processing //Pause the lighting updates for a bit
-// lighting_controller.processing = 0
-
-
var/approximate_intensity = (devastation_range * 3) + (heavy_impact_range * 2) + light_impact_range
var/powernet_rebuild_was_deferred_already = defer_powernet_rebuild
// Large enough explosion. For performance reasons, powernets will be rebuilt manually
@@ -107,7 +97,6 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
sleep(8)
-// if(!lighting_controller.processing) lighting_controller.processing = lighting_controller_was_processing
if(!powernet_rebuild_was_deferred_already && defer_powernet_rebuild)
makepowernets()
defer_powernet_rebuild = 0
@@ -119,20 +108,3 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
proc/secondaryexplosion(turf/epicenter, range)
for(var/turf/tile in range(range, epicenter))
tile.ex_act(2)
-
-///// Z-Level Stuff
-proc/explosion_z_transfer(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, up = 1, down = 1)
- var/turf/controllerlocation = locate(1, 1, epicenter.z)
- for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
- if(controller.down)
- //start the child explosion, no admin log and no additional transfers
- explosion(locate(epicenter.x, epicenter.y, controller.down_target), max(devastation_range - 2, 0), max(heavy_impact_range - 2, 0), max(light_impact_range - 2, 0), max(flash_range - 2, 0), 0, 0)
- if(devastation_range - 2 > 0 || heavy_impact_range - 2 > 0) //only transfer further if the explosion is still big enough
- explosion(locate(epicenter.x, epicenter.y, controller.down_target), max(devastation_range - 2, 0), max(heavy_impact_range - 2, 0), max(light_impact_range - 2, 0), max(flash_range - 2, 0), 0, 1)
-
- if(controller.up)
- //start the child explosion, no admin log and no additional transfers
- explosion(locate(epicenter.x, epicenter.y, controller.up_target), max(devastation_range - 2, 0), max(heavy_impact_range - 2, 0), max(light_impact_range - 2, 0), max(flash_range - 2, 0), 0, 0)
- if(devastation_range - 2 > 0 || heavy_impact_range - 2 > 0) //only transfer further if the explosion is still big enough
- explosion(locate(epicenter.x, epicenter.y, controller.up_target), max(devastation_range - 2, 0), max(heavy_impact_range - 2, 0), max(light_impact_range - 2, 0), max(flash_range - 2, 0), 1, 0)
-///// Z-Level Stuff
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 8f36b1d007..ff7cecf169 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -409,7 +409,12 @@ var/list/global/slot_flags_enumeration = list(
/obj/item/proc/ui_action_click()
attack_self(usr)
-/obj/item/proc/IsShield()
+//RETURN VALUES
+//handle_shield should return a positive value to indicate that the attack is blocked and should be prevented.
+//If a negative value is returned, it should be treated as a special return value for bullet_act() and handled appropriately.
+//For non-projectile attacks this usually means the attack is blocked.
+//Otherwise should return 0 to indicate that the attack is not affected in any way.
+/obj/item/proc/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
return 0
/obj/item/proc/get_loc_turf()
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index a01dc224c3..7400b3bcca 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -11,6 +11,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
item_state = "electronic"
w_class = 2.0
slot_flags = SLOT_ID | SLOT_BELT
+ sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/id.dmi')
//Main variables
var/owner = null
@@ -1142,21 +1143,22 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(choice == 1)
if (id)
remove_id()
+ return 1
else
var/obj/item/I = user.get_active_hand()
- if (istype(I, /obj/item/weapon/card/id))
- user.drop_item()
+ if (istype(I, /obj/item/weapon/card/id) && user.unEquip(I))
I.loc = src
id = I
+ return 1
else
var/obj/item/weapon/card/I = user.get_active_hand()
- if (istype(I, /obj/item/weapon/card/id) && I:registered_name)
+ if (istype(I, /obj/item/weapon/card/id) && I:registered_name && user.unEquip(I))
var/obj/old_id = id
- user.drop_item()
I.loc = src
id = I
user.put_in_hands(old_id)
- return
+ return 1
+ return 0
// access to status display signals
/obj/item/device/pda/attackby(obj/item/C as obj, mob/user as mob)
@@ -1184,9 +1186,9 @@ var/global/list/obj/item/device/pda/PDAs = list()
else
//Basic safety check. If either both objects are held by user or PDA is on ground and card is in hand.
if(((src in user.contents) && (C in user.contents)) || (istype(loc, /turf) && in_range(src, user) && (C in user.contents)) )
- id_check(user, 2)
- user << "You put the ID into \the [src]'s slot."
- updateSelfDialog()//Update self dialog on success.
+ if(id_check(user, 2))
+ user << "You put the ID into \the [src]'s slot."
+ updateSelfDialog()//Update self dialog on success.
return //Return in case of failed check or when successful.
updateSelfDialog()//For the non-input related code.
else if(istype(C, /obj/item/device/paicard) && !src.pai)
diff --git a/code/game/objects/items/devices/PDA/radio.dm b/code/game/objects/items/devices/PDA/radio.dm
index 94fb81fc77..7ad2b00200 100644
--- a/code/game/objects/items/devices/PDA/radio.dm
+++ b/code/game/objects/items/devices/PDA/radio.dm
@@ -221,7 +221,7 @@
if(!radio_controller)
return
- if (src.frequency < 1441 || src.frequency > 1489)
+ if (src.frequency < PUBLIC_LOW_FREQ || src.frequency > PUBLIC_HIGH_FREQ)
src.frequency = sanitize_frequency(src.frequency)
set_frequency(frequency)
diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm
index 577ee1010b..356ee87f60 100644
--- a/code/game/objects/items/devices/aicard.dm
+++ b/code/game/objects/items/devices/aicard.dm
@@ -105,12 +105,13 @@
if(istype(ai.loc, /turf/))
new /obj/structure/AIcore/deactivated(get_turf(ai))
+ ai.carded = 1
admin_attack_log(user, ai, "Carded with [src.name]", "Was carded with [src.name]", "used the [src.name] to card")
src.name = "[initial(name)] - [ai.name]"
ai.loc = src
- ai.cancel_camera()
ai.destroy_eyeobj(src)
+ ai.cancel_camera()
ai.control_disabled = 1
ai.aiRestorePowerRoutine = 0
carded_ai = ai
@@ -120,10 +121,14 @@
if(user.client)
user << "Transfer successful: [ai.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory."
+ ai.canmove = 1
update_icon()
return 1
/obj/item/device/aicard/proc/clear()
+ if(carded_ai && istype(carded_ai.loc, /turf))
+ carded_ai.canmove = 0
+ carded_ai.carded = 0
name = initial(name)
carded_ai = null
update_icon()
@@ -140,10 +145,9 @@
carded_ai.show_message(rendered, type)
..()
-/*
/obj/item/device/aicard/relaymove(var/mob/user, var/direction)
- if(src.loc && istype(src.loc.loc, /obj/item/rig_module))
- var/obj/item/rig_module/module = src.loc.loc
- if(!module.holder || !direction)
- return
- module.holder.forced_move(direction)*/
+ if(user.stat || user.stunned)
+ return
+ var/obj/item/weapon/rig/rig = src.get_rig()
+ if(istype(rig))
+ rig.forced_move(direction, user)
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index 8f9fa27093..cfbe33e5fd 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -64,30 +64,18 @@
var/flashfail = 0
if(iscarbon(M))
- var/safety = M:eyecheck()
- if(safety <= 0)
- M.Weaken(10)
- flick("e_flash", M.flash)
-
- if(ishuman(M) && ishuman(user) && M.stat!=DEAD)
- if(user.mind && user.mind in revs.head_revolutionaries)
- var/revsafe = 0
- for(var/obj/item/weapon/implant/loyalty/L in M)
- if(L && L.implanted)
- revsafe = 1
- break
- M.mind_initialize() //give them a mind datum if they don't have one.
- if(M.mind.has_been_rev)
- revsafe = 2
- if(!revsafe)
- M.mind.has_been_rev = 1
- revs.add_antagonist(M.mind)
- else if(revsafe == 1)
- user << "Something seems to be blocking the flash!"
- else
- user << "This mind seems resistant to the flash!"
- else
- flashfail = 1
+ if(M.stat!=DEAD)
+ var/safety = M:eyecheck()
+ if(safety <= 0)
+ var/flash_strength = 10
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ flash_strength *= H.species.flash_mod
+ if(flash_strength > 0)
+ M.Weaken(flash_strength)
+ flick("e_flash", M.flash)
+ else
+ flashfail = 1
else if(issilicon(M))
M.Weaken(rand(5,10))
@@ -194,8 +182,6 @@
desc = "When a problem arises, SCIENCE is the solution."
icon_state = "sflash"
origin_tech = list(TECH_MAGNET = 2, TECH_COMBAT = 1)
- var/construction_cost = list(DEFAULT_WALL_MATERIAL=750,"glass"=750)
- var/construction_time=100
/obj/item/device/flash/synthetic/attack(mob/living/M as mob, mob/user as mob)
..()
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index ab5ede0bce..e729fa3b09 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -16,14 +16,9 @@
/obj/item/device/flashlight/initialize()
..()
- if(on)
- icon_state = "[initial(icon_state)]-on"
- set_light(brightness_on)
- else
- icon_state = initial(icon_state)
- set_light(0)
+ update_icon()
-/obj/item/device/flashlight/proc/update_brightness(var/mob/user = null)
+/obj/item/device/flashlight/update_icon()
if(on)
icon_state = "[initial(icon_state)]-on"
set_light(brightness_on)
@@ -36,7 +31,7 @@
user << "You cannot turn the light on while in this [user.loc]." //To prevent some lighting anomalities.
return 0
on = !on
- update_brightness(user)
+ update_icon()
user.update_action_buttons()
return 1
@@ -171,11 +166,7 @@
on = 0
src.force = initial(src.force)
src.damtype = initial(src.damtype)
- if(ismob(loc))
- var/mob/U = loc
- update_brightness(U)
- else
- update_brightness(null)
+ update_icon()
/obj/item/device/flashlight/flare/attack_self(mob/user)
@@ -206,10 +197,11 @@
on = 1 //Bio-luminesence has one setting, on.
/obj/item/device/flashlight/slime/New()
+ ..()
set_light(brightness_on)
- spawn(1) //Might be sloppy, but seems to be necessary to prevent further runtimes and make these work as intended... don't judge me!
- update_brightness()
- icon_state = initial(icon_state)
+
+/obj/item/device/flashlight/slime/update_icon()
+ return
/obj/item/device/flashlight/slime/attack_self(mob/user)
return //Bio-luminescence does not toggle.
diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm
index f7fa46678b..685f2a9043 100644
--- a/code/game/objects/items/devices/paicard.dm
+++ b/code/game/objects/items/devices/paicard.dm
@@ -10,12 +10,12 @@
var/looking_for_personality = 0
var/mob/living/silicon/pai/pai
-/*/obj/item/device/paicard/relaymove(var/mob/user, var/direction)
- if(src.loc && istype(src.loc.loc, /obj/item/rig_module))
- var/obj/item/rig_module/module = src.loc.loc
- if(!module.holder || !direction)
- return
- module.holder.forced_move(direction)*/
+/obj/item/device/paicard/relaymove(var/mob/user, var/direction)
+ if(user.stat || user.stunned)
+ return
+ var/obj/item/weapon/rig/rig = src.get_rig()
+ if(istype(rig))
+ rig.forced_move(direction, user)
/obj/item/device/paicard/New()
..()
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 43a4c5bf56..7b9f046443 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -13,13 +13,15 @@
var/translate_hive = 0
var/obj/item/device/encryptionkey/keyslot1 = null
var/obj/item/device/encryptionkey/keyslot2 = null
- maxf = 1489
var/ks1type = /obj/item/device/encryptionkey
var/ks2type = null
+ sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/ears.dmi')
+
/obj/item/device/radio/headset/New()
..()
+ internal_channels.Cut()
if(ks1type)
keyslot1 = new ks1type(src)
if(ks2type)
@@ -33,11 +35,14 @@
keyslot2 = null
..()
+/obj/item/device/radio/headset/list_channels(var/mob/user)
+ return list_secure_channels()
+
/obj/item/device/radio/headset/examine(mob/user)
if(!(..(user, 1) && radio_desc))
return
- user << "The following channels are built-in:"
+ user << "The following channels are available:"
user << radio_desc
/obj/item/device/radio/headset/handle_message_mode(mob/living/M as mob, message, channel)
@@ -175,21 +180,7 @@
icon_state = "com_headset"
item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/hop
-/*
-/obj/item/device/radio/headset/headset_mine
- name = "mining radio headset"
- desc = "Headset used by miners. How useless. To access the mining channel, use :d."
- icon_state = "mine_headset"
- item_state = "headset"
- keyslot2 = new /obj/item/device/encryptionkey/headset_mine
-/obj/item/device/radio/headset/heads/qm
- name = "quartermaster's headset"
- desc = "The headset of the man who control your toiletpaper supply. To access the cargo channel, use :q. For mining, use :d."
- icon_state = "cargo_headset"
- item_state = "headset"
- keyslot2 = new /obj/item/device/encryptionkey/heads/qm
-*/
/obj/item/device/radio/headset/headset_cargo
name = "supply radio headset"
desc = "A headset used by the QM and their slaves."
@@ -209,7 +200,6 @@
desc = "The headset of the boss's boss."
icon_state = "com_headset"
item_state = "headset"
- freerange = 1
ks2type = /obj/item/device/encryptionkey/ert
/obj/item/device/radio/headset/ia
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 1abccb5e77..2a0341a77e 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -1,5 +1,5 @@
/obj/item/device/radio/intercom
- name = "station intercom"
+ name = "station intercom (General)"
desc = "Talk through this."
icon_state = "intercom"
anchored = 1
@@ -7,14 +7,64 @@
canhear_range = 2
flags = CONDUCT | NOBLOODY
var/number = 0
- var/anyai = 1
- var/mob/living/silicon/ai/ai = list()
var/last_tick //used to delay the powercheck
+/obj/item/device/radio/intercom/custom
+ name = "station intercom (Custom)"
+ broadcasting = 0
+ listening = 0
+
+/obj/item/device/radio/intercom/interrogation
+ name = "station intercom (Interrogation)"
+ frequency = 1449
+
+/obj/item/device/radio/intercom/private
+ name = "station intercom (Private)"
+ frequency = AI_FREQ
+
+/obj/item/device/radio/intercom/specops
+ name = "\improper Spec Ops intercom"
+ frequency = ERT_FREQ
+
+/obj/item/device/radio/intercom/department
+ canhear_range = 5
+ broadcasting = 0
+ listening = 1
+
+/obj/item/device/radio/intercom/department/medbay
+ name = "station intercom (Medbay)"
+ frequency = MED_I_FREQ
+
+/obj/item/device/radio/intercom/department/security
+ name = "station intercom (Security)"
+ frequency = SEC_I_FREQ
+
/obj/item/device/radio/intercom/New()
..()
processing_objects += src
+/obj/item/device/radio/intercom/department/medbay/New()
+ ..()
+ internal_channels = default_medbay_channels.Copy()
+
+/obj/item/device/radio/intercom/department/security/New()
+ ..()
+ internal_channels = list(
+ num2text(PUB_FREQ) = list(),
+ num2text(SEC_I_FREQ) = list(access_security)
+ )
+
+/obj/item/device/radio/intercom/syndicate
+ name = "illicit intercom"
+ desc = "Talk through this. Evilly"
+ frequency = SYND_FREQ
+ subspace_transmission = 1
+ syndie = 1
+
+/obj/item/device/radio/intercom/syndicate/New()
+ ..()
+ internal_channels[num2text(SYND_FREQ)] = list(access_syndicate)
+
/obj/item/device/radio/intercom/Destroy()
processing_objects -= src
..()
@@ -44,12 +94,6 @@
return canhear_range
-
-/obj/item/device/radio/intercom/hear_talk(mob/M as mob, msg)
- if(!src.anyai && !(M in src.ai))
- return
- ..()
-
/obj/item/device/radio/intercom/process()
if(((world.timeofday - last_tick) > 30) || ((world.timeofday - last_tick) < 0))
last_tick = world.timeofday
@@ -57,8 +101,8 @@
if(!src.loc)
on = 0
else
- var/area/A = src.loc.loc
- if(!A || !isarea(A))
+ var/area/A = get_area(src)
+ if(!A)
on = 0
else
on = A.powered(EQUIP) // set "on" to the power status
@@ -69,8 +113,19 @@
icon_state = "intercom"
/obj/item/device/radio/intercom/locked
- freerange = 1
var/locked_frequency
-
-/obj/item/device/radio/intercom/locked/set_frequency()
- ..(locked_frequency)
+
+/obj/item/device/radio/intercom/locked/set_frequency(var/frequency)
+ if(frequency == locked_frequency)
+ ..(locked_frequency)
+
+/obj/item/device/radio/intercom/locked/list_channels()
+ return ""
+
+/obj/item/device/radio/intercom/locked/ai_private
+ name = "\improper AI intercom"
+ frequency = AI_FREQ
+
+/obj/item/device/radio/intercom/locked/confessional
+ name = "confessional intercom"
+ frequency = 1480
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 0353c25f59..54ebfa85af 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -1,9 +1,32 @@
+// Access check is of the type requires one. These have been carefully selected to avoid allowing the janitor to see channels he shouldn't
+var/global/list/default_internal_channels = list(
+ num2text(PUB_FREQ) = list(),
+ num2text(AI_FREQ) = list(access_synth),
+ num2text(ERT_FREQ) = list(access_cent_specops),
+ num2text(COMM_FREQ)= list(access_heads),
+ num2text(ENG_FREQ) = list(access_engine_equip, access_atmospherics),
+ num2text(MED_FREQ) = list(access_medical_equip),
+ num2text(MED_I_FREQ)=list(access_medical_equip),
+ num2text(SEC_FREQ) = list(access_security),
+ num2text(SEC_I_FREQ)=list(access_security),
+ num2text(SCI_FREQ) = list(access_tox,access_robotics,access_xenobiology),
+ num2text(SUP_FREQ) = list(access_cargo),
+ num2text(SRV_FREQ) = list(access_janitor, access_hydroponics)
+)
+
+var/global/list/default_medbay_channels = list(
+ num2text(PUB_FREQ) = list(),
+ num2text(MED_FREQ) = list(access_medical_equip),
+ num2text(MED_I_FREQ) = list(access_medical_equip)
+)
+
/obj/item/device/radio
icon = 'icons/obj/radio.dmi'
name = "station bounced radio"
suffix = "\[3\]"
icon_state = "walkietalkie"
item_state = "walkietalkie"
+
var/on = 1 // 0 for off
var/last_transmission
var/frequency = PUB_FREQ //common chat
@@ -14,12 +37,9 @@
var/b_stat = 0
var/broadcasting = 0
var/listening = 1
- var/freerange = 0 // 0 - Sanitize frequencies, 1 - Full range
- var/list/channels = list() //see communications.dm for full list. First channes is a "default" for :h
+ var/list/channels = list() //see communications.dm for full list. First channel is a "default" for :h
var/subspace_transmission = 0
- var/syndie = 0//Holder to see if it's a syndicate encrpyed radio
- var/maxf = 1499
-// "Example" = FREQ_LISTENING|FREQ_BROADCASTING
+ var/syndie = 0//Holder to see if it's a syndicate encrypted radio
flags = CONDUCT
slot_flags = SLOT_BELT
throw_speed = 2
@@ -28,7 +48,7 @@
matter = list("glass" = 25,DEFAULT_WALL_MATERIAL = 75)
var/const/FREQ_LISTENING = 1
-
+ var/list/internal_channels
/obj/item/device/radio
var/datum/radio_frequency/radio_connection
@@ -42,6 +62,7 @@
/obj/item/device/radio/New()
..()
wires = new(src)
+ internal_channels = default_internal_channels.Copy()
/obj/item/device/radio/Destroy()
qdel(wires)
@@ -55,19 +76,15 @@
/obj/item/device/radio/initialize()
- if(freerange)
- if(frequency < 1200 || frequency > 1600)
- frequency = sanitize_frequency(frequency, maxf)
- // The max freq is higher than a regular headset to decrease the chance of people listening in, if you use the higher channels.
- else if (frequency < 1441 || frequency > maxf)
- //world.log << "[src] ([type]) has a frequency of [frequency], sanitizing."
- frequency = sanitize_frequency(frequency, maxf)
-
+ if(frequency < RADIO_LOW_FREQ || frequency > RADIO_HIGH_FREQ)
+ frequency = sanitize_frequency(frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ)
set_frequency(frequency)
for (var/ch_name in channels)
secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
+/obj/item/device/radio/attack_ghost(mob/user)
+ interact(user)
/obj/item/device/radio/attack_self(mob/user as mob)
user.set_machine(src)
@@ -95,13 +112,48 @@
+
"}
- for (var/ch_name in channels)
- dat+=text_sec_channel(ch_name, channels[ch_name])
+ dat+=list_channels(user)
+
dat+={"[text_wires()]