Merge remote-tracking branch 'Citadel-Station-13/master' into Garlic

This commit is contained in:
Artur
2020-03-24 12:36:21 +02:00
1739 changed files with 401053 additions and 234616 deletions
+6
View File
@@ -48,6 +48,8 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "space_near"
dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT
/area/space/station_ruins //Paint this area where you want station ruins to be allowed to spawn
/area/start
name = "start area"
icon_state = "start"
@@ -849,6 +851,10 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Medbay Treatment Center"
icon_state = "exam_room"
/area/medical/paramedic
name = "Paramedic Station"
icon_state = "paramedic"
//Security
+11 -34
View File
@@ -63,6 +63,9 @@
var/xenobiology_compatible = FALSE //Can the Xenobio management console transverse this area by default?
var/list/canSmoothWithAreas //typecache to limit the areas that atoms in this area can smooth with
/// Color on minimaps, if it's null (which is default) it makes one at random.
var/minimap_color
/**
* These two vars allow for multiple unique areas to be linked to a master area
* and share some functionalities such as APC powernet nodes, fire alarms etc, without sacrificing
@@ -96,7 +99,14 @@ GLOBAL_LIST_EMPTY(teleportlocs)
// ===
/area/New()
// This interacts with the map loader, so it needs to be set immediately
if(!minimap_color) // goes in New() because otherwise it doesn't fucking work
// generate one using the icon_state
if(icon_state && icon_state != "unknown")
var/icon/I = new(icon, icon_state, dir)
I.Scale(1,1)
minimap_color = I.GetPixel(1,1)
else // no icon state? use random.
minimap_color = rgb(rand(50,70),rand(50,70),rand(50,70)) // This interacts with the map loader, so it needs to be set immediately
// rather than waiting for atoms to initialize.
if (unique)
GLOB.areas_by_type[type] = src
@@ -514,39 +524,6 @@ GLOBAL_LIST_EMPTY(teleportlocs)
/client/proc/ResetAmbiencePlayed()
played = FALSE
/atom/proc/has_gravity(turf/T)
if(!T || !isturf(T))
T = get_turf(src)
if(!T)
return 0
var/list/forced_gravity = list()
SEND_SIGNAL(src, COMSIG_ATOM_HAS_GRAVITY, T, forced_gravity)
if(!forced_gravity.len)
SEND_SIGNAL(T, COMSIG_TURF_HAS_GRAVITY, src, forced_gravity)
if(forced_gravity.len)
var/max_grav
for(var/i in forced_gravity)
max_grav = max(max_grav, i)
if(max_grav)
return max_grav
if(isspaceturf(T)) // Turf never has gravity
return 0
var/area/A = get_area(T)
if(A.has_gravity) // Areas which always has gravity
return A.has_gravity
else
// There's a gravity generator on our z level
if(GLOB.gravity_generators["[T.z]"])
var/max_grav = 0
for(var/obj/machinery/gravity_generator/main/G in GLOB.gravity_generators["[T.z]"])
max_grav = max(G.setting,max_grav)
return max_grav
return SSmapping.level_trait(T.z, ZTRAIT_GRAVITY)
/area/proc/setup(a_name)
name = a_name
power_equip = FALSE
+2
View File
@@ -3,6 +3,8 @@
/area/ruin/space
has_gravity = FALSE
blob_allowed = FALSE //Nope, no winning in space as a blob. Gotta eat the station.
outdoors = TRUE
ambientsounds = SPACE
/area/ruin/space/has_grav
has_gravity = STANDARD_GRAVITY
+59 -8
View File
@@ -28,7 +28,6 @@
var/list/managed_overlays
var/datum/proximity_monitor/proximity_monitor
var/buckle_message_cooldown = 0
var/fingerprintslast
var/list/filter_data //For handling persistent filters
@@ -98,7 +97,7 @@
var/temp_list = list()
for(var/i in custom_materials)
temp_list[getmaterialref(i)] = custom_materials[i] //Get the proper instanced version
temp_list[SSmaterials.GetMaterialRef(i)] = custom_materials[i] //Get the proper instanced version
custom_materials = null //Null the list to prepare for applying the materials properly
set_custom_materials(temp_list)
@@ -334,9 +333,11 @@
/atom/proc/update_icon()
// I expect we're going to need more return flags and options in this proc
var/signalOut = SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_ICON)
. = FALSE
if(!(signalOut & COMSIG_ATOM_NO_UPDATE_ICON_STATE))
update_icon_state()
. = TRUE
if(!(signalOut & COMSIG_ATOM_NO_UPDATE_OVERLAYS))
var/list/new_overlays = update_overlays()
@@ -346,6 +347,9 @@
if(length(new_overlays))
managed_overlays = new_overlays
add_overlay(new_overlays)
. = TRUE
SEND_SIGNAL(src, COMSIG_ATOM_UPDATED_ICON, signalOut, .)
/// Updates the icon state of the atom
/atom/proc/update_icon_state()
@@ -356,11 +360,12 @@
. = list()
SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_OVERLAYS, .)
/atom/proc/relaymove(mob/user)
if(buckle_message_cooldown <= world.time)
buckle_message_cooldown = world.time + 50
/atom/proc/relaymove(mob/living/user)
if(!istype(user))
return //why are you buckling nonliving mobs to atoms?
if(user.buckle_message_cooldown <= world.time)
user.buckle_message_cooldown = world.time + 50
to_chat(user, "<span class='warning'>You can't move while buckled to [src]!</span>")
return
/atom/proc/contents_explosion(severity, target)
return //For handling the effects of explosions on contents that would not normally be effected
@@ -899,7 +904,7 @@ Proc for attack log creation, because really why not
if(custom_materials) //Only runs if custom materials existed at first. Should usually be the case but check anyways
for(var/i in custom_materials)
var/datum/material/custom_material = getmaterialref(i)
var/datum/material/custom_material = SSmaterials.GetMaterialRef(i)
custom_material.on_removed(src, material_flags) //Remove the current materials
if(!length(materials))
@@ -908,8 +913,54 @@ Proc for attack log creation, because really why not
custom_materials = list() //Reset the list
for(var/x in materials)
var/datum/material/custom_material = getmaterialref(x)
var/datum/material/custom_material = SSmaterials.GetMaterialRef(x)
if(!(material_flags & MATERIAL_NO_EFFECTS))
custom_material.on_applied(src, materials[custom_material] * multiplier * material_modifier, material_flags)
custom_materials[custom_material] += materials[x] * multiplier
/**
* Returns true if this atom has gravity for the passed in turf
*
* Sends signals COMSIG_ATOM_HAS_GRAVITY and COMSIG_TURF_HAS_GRAVITY, both can force gravity with
* the forced gravity var
*
* Gravity situations:
* * No gravity if you're not in a turf
* * No gravity if this atom is in is a space turf
* * Gravity if the area it's in always has gravity
* * Gravity if there's a gravity generator on the z level
* * Gravity if the Z level has an SSMappingTrait for ZTRAIT_GRAVITY
* * otherwise no gravity
*/
/atom/proc/has_gravity(turf/T)
if(!T || !isturf(T))
T = get_turf(src)
if(!T)
return 0
var/list/forced_gravity = list()
SEND_SIGNAL(src, COMSIG_ATOM_HAS_GRAVITY, T, forced_gravity)
if(!forced_gravity.len)
SEND_SIGNAL(T, COMSIG_TURF_HAS_GRAVITY, src, forced_gravity)
if(forced_gravity.len)
var/max_grav
for(var/i in forced_gravity)
max_grav = max(max_grav, i)
return max_grav
if(isspaceturf(T)) // Turf never has gravity
return 0
var/area/A = get_area(T)
if(A.has_gravity) // Areas which always has gravity
return A.has_gravity
else
// There's a gravity generator on our z level
if(GLOB.gravity_generators["[T.z]"])
var/max_grav = 0
for(var/obj/machinery/gravity_generator/main/G in GLOB.gravity_generators["[T.z]"])
max_grav = max(G.setting,max_grav)
return max_grav
return SSmapping.level_trait(T.z, ZTRAIT_GRAVITY)
+10 -307
View File
@@ -131,7 +131,7 @@
return FALSE
// Are we trying to pull something we are already pulling? Then enter grab cycle and end.
if(AM == pulling)
grab_state = state
setGrabState(state)
if(istype(AM,/mob/living))
var/mob/living/AMob = AM
AMob.grabbedby(src)
@@ -142,7 +142,7 @@
AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once.
pulling = AM
AM.pulledby = src
grab_state = state
setGrabState(state)
if(ismob(AM))
var/mob/M = AM
log_combat(src, M, "grabbed", addition="passive grab")
@@ -155,10 +155,10 @@
pulling.pulledby = null
var/mob/living/ex_pulled = pulling
pulling = null
grab_state = 0
setGrabState(0)
if(isliving(ex_pulled))
var/mob/living/L = ex_pulled
L.update_canmove()// mob gets up if it was lyng down in a chokehold
L.update_mobility()// mob gets up if it was lyng down in a chokehold
/atom/movable/proc/Move_Pulled(atom/A)
if(!pulling)
@@ -194,160 +194,6 @@
stop_pulling()
return
////////////////////////////////////////
// Here's where we rewrite how byond handles movement except slightly different
// To be removed on step_ conversion
// All this work to prevent a second bump
/atom/movable/Move(atom/newloc, direct=0)
. = FALSE
if(!newloc || newloc == loc)
return
if(!direct)
direct = get_dir(src, newloc)
setDir(direct)
if(!loc.Exit(src, newloc))
return
if(!newloc.Enter(src, src.loc))
return
// Past this is the point of no return
var/atom/oldloc = loc
var/area/oldarea = get_area(oldloc)
var/area/newarea = get_area(newloc)
loc = newloc
. = TRUE
oldloc.Exited(src, newloc)
if(oldarea != newarea)
oldarea.Exited(src, newloc)
for(var/i in oldloc)
if(i == src) // Multi tile objects
continue
var/atom/movable/thing = i
thing.Uncrossed(src)
newloc.Entered(src, oldloc)
if(oldarea != newarea)
newarea.Entered(src, oldloc)
for(var/i in loc)
if(i == src) // Multi tile objects
continue
var/atom/movable/thing = i
thing.Crossed(src)
//
////////////////////////////////////////
/atom/movable/Move(atom/newloc, direct)
var/atom/movable/pullee = pulling
var/turf/T = loc
if(pulling)
if(pullee && get_dist(src, pullee) > 1)
stop_pulling()
if(pullee && pullee.loc != loc && !isturf(pullee.loc) ) //to be removed once all code that changes an object's loc uses forceMove().
log_game("DEBUG:[src]'s pull on [pullee] wasn't broken despite [pullee] being in [pullee.loc]. Pull stopped manually.")
stop_pulling()
if(!loc || !newloc)
return FALSE
var/atom/oldloc = loc
if(loc != newloc)
if (!(direct & (direct - 1))) //Cardinal move
. = ..()
else //Diagonal move, split it into cardinal moves
moving_diagonally = FIRST_DIAG_STEP
var/first_step_dir
// The `&& moving_diagonally` checks are so that a forceMove taking
// place due to a Crossed, Bumped, etc. call will interrupt
// the second half of the diagonal movement, or the second attempt
// at a first half if step() fails because we hit something.
if (direct & NORTH)
if (direct & EAST)
if (step(src, NORTH) && moving_diagonally)
first_step_dir = NORTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, EAST)
else if (moving_diagonally && step(src, EAST))
first_step_dir = EAST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, NORTH)
else if (direct & WEST)
if (step(src, NORTH) && moving_diagonally)
first_step_dir = NORTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, WEST)
else if (moving_diagonally && step(src, WEST))
first_step_dir = WEST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, NORTH)
else if (direct & SOUTH)
if (direct & EAST)
if (step(src, SOUTH) && moving_diagonally)
first_step_dir = SOUTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, EAST)
else if (moving_diagonally && step(src, EAST))
first_step_dir = EAST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, SOUTH)
else if (direct & WEST)
if (step(src, SOUTH) && moving_diagonally)
first_step_dir = SOUTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, WEST)
else if (moving_diagonally && step(src, WEST))
first_step_dir = WEST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, SOUTH)
if(moving_diagonally == SECOND_DIAG_STEP)
if(!.)
setDir(first_step_dir)
else if (!inertia_moving)
inertia_next_move = world.time + inertia_move_delay
newtonian_move(direct)
moving_diagonally = 0
return
if(!loc || (loc == oldloc && oldloc != newloc))
last_move = 0
return
if(.)
Moved(oldloc, direct)
if(. && pulling && pulling == pullee) //we were pulling a thing and didn't lose it during our move.
if(pulling.anchored)
stop_pulling()
else
var/pull_dir = get_dir(src, pulling)
//puller and pullee more than one tile away or in diagonal position
if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir)))
pulling.Move(T, get_dir(pulling, T)) //the pullee tries to reach our previous position
if(pulling && get_dist(src, pulling) > 1) //the pullee couldn't keep up
stop_pulling()
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1)//separated from our puller and not in the middle of a diagonal move.
pulledby.stop_pulling()
last_move = direct
setDir(direct)
if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc,direct)) //movement failed due to buckled mob(s)
return FALSE
//Called after a successful Move(). By this point, we've already moved
/atom/movable/proc/Moved(atom/OldLoc, Dir, Forced = FALSE)
SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, OldLoc, Dir, Forced)
if (!inertia_moving)
inertia_next_move = world.time + inertia_move_delay
newtonian_move(Dir)
if (length(client_mobs_in_contents))
update_parallax_contents()
return TRUE
/atom/movable/Destroy(force)
QDEL_NULL(proximity_monitor)
QDEL_NULL(language_holder)
@@ -372,143 +218,6 @@
orbiting.end_orbit(src)
orbiting = null
// Make sure you know what you're doing if you call this, this is intended to only be called by byond directly.
// You probably want CanPass()
/atom/movable/Cross(atom/movable/AM)
. = TRUE
SEND_SIGNAL(src, COMSIG_MOVABLE_CROSS, AM)
return CanPass(AM, AM.loc, TRUE)
//oldloc = old location on atom, inserted when forceMove is called and ONLY when forceMove is called!
/atom/movable/Crossed(atom/movable/AM, oldloc)
SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM)
/atom/movable/Uncross(atom/movable/AM, atom/newloc)
. = ..()
if(SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSS, AM) & COMPONENT_MOVABLE_BLOCK_UNCROSS)
return FALSE
if(isturf(newloc) && !CheckExit(AM, newloc))
return FALSE
/atom/movable/Uncrossed(atom/movable/AM)
SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSSED, AM)
/atom/movable/Bump(atom/A)
if(!A)
CRASH("Bump was called with no argument.")
SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A)
. = ..()
if(!QDELETED(throwing))
throwing.hit_atom(A)
. = TRUE
if(QDELETED(A))
return
A.Bumped(src)
/atom/movable/proc/forceMove(atom/destination)
. = FALSE
if(destination)
. = doMove(destination)
else
CRASH("No valid destination passed into forceMove")
/atom/movable/proc/moveToNullspace()
return doMove(null)
/atom/movable/proc/doMove(atom/destination)
. = FALSE
if(destination)
if(pulledby)
pulledby.stop_pulling()
var/atom/oldloc = loc
var/same_loc = oldloc == destination
var/area/old_area = get_area(oldloc)
var/area/destarea = get_area(destination)
loc = destination
moving_diagonally = 0
if(!same_loc)
if(oldloc)
oldloc.Exited(src, destination)
if(old_area && old_area != destarea)
old_area.Exited(src, destination)
for(var/atom/movable/AM in oldloc)
AM.Uncrossed(src)
var/turf/oldturf = get_turf(oldloc)
var/turf/destturf = get_turf(destination)
var/old_z = (oldturf ? oldturf.z : null)
var/dest_z = (destturf ? destturf.z : null)
if (old_z != dest_z)
onTransitZ(old_z, dest_z)
destination.Entered(src, oldloc)
if(destarea && old_area != destarea)
destarea.Entered(src, oldloc)
for(var/atom/movable/AM in destination)
if(AM == src)
continue
AM.Crossed(src, oldloc)
Moved(oldloc, NONE, TRUE)
. = TRUE
//If no destination, move the atom into nullspace (don't do this unless you know what you're doing)
else
. = TRUE
if (loc)
var/atom/oldloc = loc
var/area/old_area = get_area(oldloc)
oldloc.Exited(src, null)
if(old_area)
old_area.Exited(src, null)
loc = null
/atom/movable/proc/onTransitZ(old_z,new_z)
SEND_SIGNAL(src, COMSIG_MOVABLE_Z_CHANGED, old_z, new_z)
for (var/item in src) // Notify contents of Z-transition. This can be overridden IF we know the items contents do not care.
var/atom/movable/AM = item
AM.onTransitZ(old_z,new_z)
/atom/movable/proc/setMovetype(newval)
movement_type = newval
//Called whenever an object moves and by mobs when they attempt to move themselves through space
//And when an object or action applies a force on src, see newtonian_move() below
//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting
//Mobs should return 1 if they should be able to move of their own volition, see client/Move() in mob_movement.dm
//movement_dir == 0 when stopping or any dir when trying to move
/atom/movable/proc/Process_Spacemove(movement_dir = 0)
if(has_gravity(src))
return 1
if(pulledby)
return 1
if(throwing)
return 1
if(!isturf(loc))
return 1
if(locate(/obj/structure/lattice) in range(1, get_turf(src))) //Not realistic but makes pushing things in space easier
return 1
return 0
/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity
if(!loc || Process_Spacemove(0))
inertia_dir = 0
return 0
inertia_dir = direction
if(!direction)
return 1
inertia_last_loc = loc
SSspacedrift.processing[src] = src
return 1
/atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
set waitfor = 0
SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
@@ -610,17 +319,6 @@
SSthrowing.currentrun[src] = TT
TT.tick()
/atom/movable/proc/handle_buckled_mob_movement(newloc,direct)
for(var/m in buckled_mobs)
var/mob/living/buckled_mob = m
if(!buckled_mob.Move(newloc, direct))
forceMove(buckled_mob.loc)
last_move = buckled_mob.last_move
inertia_dir = last_move
buckled_mob.inertia_dir = last_move
return 0
return 1
/atom/movable/proc/force_pushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction)
return FALSE
@@ -639,7 +337,7 @@
/atom/movable/CanPass(atom/movable/mover, turf/target)
if(mover in buckled_mobs)
return 1
return TRUE
return ..()
// called when this atom is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called.
@@ -865,6 +563,11 @@
return FALSE
return TRUE
/// Updates the grab state of the movable
/// This exists to act as a hook for behaviour
/atom/movable/proc/setGrabState(newstate)
grab_state = newstate
/obj/item/proc/do_pickup_animation(atom/target)
set waitfor = FALSE
if(!istype(loc, /turf))
+307
View File
@@ -0,0 +1,307 @@
// File for movement procs for atom/movable
////////////////////////////////////////
// Here's where we rewrite how byond handles movement except slightly different
// To be removed on step_ conversion
// All this work to prevent a second bump
/atom/movable/Move(atom/newloc, direct=0)
. = FALSE
if(!newloc || newloc == loc)
return
if(!direct)
direct = get_dir(src, newloc)
setDir(direct)
if(!loc.Exit(src, newloc))
return
if(!newloc.Enter(src, src.loc))
return
// Past this is the point of no return
var/atom/oldloc = loc
var/area/oldarea = get_area(oldloc)
var/area/newarea = get_area(newloc)
loc = newloc
. = TRUE
oldloc.Exited(src, newloc)
if(oldarea != newarea)
oldarea.Exited(src, newloc)
for(var/i in oldloc)
if(i == src) // Multi tile objects
continue
var/atom/movable/thing = i
thing.Uncrossed(src)
newloc.Entered(src, oldloc)
if(oldarea != newarea)
newarea.Entered(src, oldloc)
for(var/i in loc)
if(i == src) // Multi tile objects
continue
var/atom/movable/thing = i
thing.Crossed(src)
//
////////////////////////////////////////
/atom/movable/Move(atom/newloc, direct)
var/atom/movable/pullee = pulling
var/turf/T = loc
if(pulling)
if(pullee && get_dist(src, pullee) > 1)
stop_pulling()
if(pullee && pullee.loc != loc && !isturf(pullee.loc) ) //to be removed once all code that changes an object's loc uses forceMove().
log_game("DEBUG:[src]'s pull on [pullee] wasn't broken despite [pullee] being in [pullee.loc]. Pull stopped manually.")
stop_pulling()
if(!loc || !newloc)
return FALSE
var/atom/oldloc = loc
if(loc != newloc)
if (!(direct & (direct - 1))) //Cardinal move
. = ..()
else //Diagonal move, split it into cardinal moves
moving_diagonally = FIRST_DIAG_STEP
var/first_step_dir
// The `&& moving_diagonally` checks are so that a forceMove taking
// place due to a Crossed, Bumped, etc. call will interrupt
// the second half of the diagonal movement, or the second attempt
// at a first half if step() fails because we hit something.
if (direct & NORTH)
if (direct & EAST)
if (step(src, NORTH) && moving_diagonally)
first_step_dir = NORTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, EAST)
else if (moving_diagonally && step(src, EAST))
first_step_dir = EAST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, NORTH)
else if (direct & WEST)
if (step(src, NORTH) && moving_diagonally)
first_step_dir = NORTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, WEST)
else if (moving_diagonally && step(src, WEST))
first_step_dir = WEST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, NORTH)
else if (direct & SOUTH)
if (direct & EAST)
if (step(src, SOUTH) && moving_diagonally)
first_step_dir = SOUTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, EAST)
else if (moving_diagonally && step(src, EAST))
first_step_dir = EAST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, SOUTH)
else if (direct & WEST)
if (step(src, SOUTH) && moving_diagonally)
first_step_dir = SOUTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, WEST)
else if (moving_diagonally && step(src, WEST))
first_step_dir = WEST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, SOUTH)
if(moving_diagonally == SECOND_DIAG_STEP)
if(!.)
setDir(first_step_dir)
else if (!inertia_moving)
inertia_next_move = world.time + inertia_move_delay
newtonian_move(direct)
moving_diagonally = 0
return
if(!loc || (loc == oldloc && oldloc != newloc))
last_move = NONE
return
if(.)
last_move = direct
setDir(direct)
if(has_buckled_mobs() && !handle_buckled_mob_movement(loc,direct)) //movement failed due to buckled mob(s)
return FALSE
if(pulling && pulling == pullee) //we were pulling a thing and didn't lose it during our move.
if(pulling.anchored)
stop_pulling()
else
var/pull_dir = get_dir(src, pulling)
//puller and pullee more than one tile away or in diagonal position
if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir)))
pulling.Move(T, get_dir(pulling, T)) //the pullee tries to reach our previous position
if(pulling && get_dist(src, pulling) > 1) //the pullee couldn't keep up
stop_pulling()
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1)//separated from our puller and not in the middle of a diagonal move.
pulledby.stop_pulling()
Moved(oldloc, direct)
/atom/movable/proc/handle_buckled_mob_movement(newloc,direct)
for(var/m in buckled_mobs)
var/mob/living/buckled_mob = m
if(!buckled_mob.Move(newloc, direct))
forceMove(buckled_mob.loc)
last_move = buckled_mob.last_move
inertia_dir = last_move
buckled_mob.inertia_dir = last_move
return FALSE
return TRUE
//Called after a successful Move(). By this point, we've already moved
/atom/movable/proc/Moved(atom/OldLoc, Dir, Forced = FALSE)
SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, OldLoc, Dir, Forced)
if (!inertia_moving)
inertia_next_move = world.time + inertia_move_delay
newtonian_move(Dir)
if (length(client_mobs_in_contents))
update_parallax_contents()
return TRUE
// Make sure you know what you're doing if you call this, this is intended to only be called by byond directly.
// You probably want CanPass()
/atom/movable/Cross(atom/movable/AM)
. = TRUE
SEND_SIGNAL(src, COMSIG_MOVABLE_CROSS, AM)
return CanPass(AM, AM.loc, TRUE)
//oldloc = old location on atom, inserted when forceMove is called and ONLY when forceMove is called!
/atom/movable/Crossed(atom/movable/AM, oldloc)
SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM)
/atom/movable/Uncross(atom/movable/AM, atom/newloc)
. = ..()
if(SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSS, AM) & COMPONENT_MOVABLE_BLOCK_UNCROSS)
return FALSE
if(isturf(newloc) && !CheckExit(AM, newloc))
return FALSE
/atom/movable/Uncrossed(atom/movable/AM)
SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSSED, AM)
/atom/movable/Bump(atom/A)
if(!A)
CRASH("Bump was called with no argument.")
SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A)
. = ..()
if(!QDELETED(throwing))
throwing.hit_atom(A)
. = TRUE
if(QDELETED(A))
return
A.Bumped(src)
/atom/movable/proc/onTransitZ(old_z,new_z)
SEND_SIGNAL(src, COMSIG_MOVABLE_Z_CHANGED, old_z, new_z)
for (var/item in src) // Notify contents of Z-transition. This can be overridden IF we know the items contents do not care.
var/atom/movable/AM = item
AM.onTransitZ(old_z,new_z)
/atom/movable/proc/setMovetype(newval)
movement_type = newval
///////////// FORCED MOVEMENT /////////////
/atom/movable/proc/forceMove(atom/destination)
. = FALSE
if(destination)
. = doMove(destination)
else
CRASH("No valid destination passed into forceMove")
/atom/movable/proc/moveToNullspace()
return doMove(null)
/atom/movable/proc/doMove(atom/destination)
. = FALSE
if(destination)
if(pulledby)
pulledby.stop_pulling()
var/atom/oldloc = loc
var/same_loc = oldloc == destination
var/area/old_area = get_area(oldloc)
var/area/destarea = get_area(destination)
loc = destination
moving_diagonally = 0
if(!same_loc)
if(oldloc)
oldloc.Exited(src, destination)
if(old_area && old_area != destarea)
old_area.Exited(src, destination)
for(var/atom/movable/AM in oldloc)
AM.Uncrossed(src)
var/turf/oldturf = get_turf(oldloc)
var/turf/destturf = get_turf(destination)
var/old_z = (oldturf ? oldturf.z : null)
var/dest_z = (destturf ? destturf.z : null)
if (old_z != dest_z)
onTransitZ(old_z, dest_z)
destination.Entered(src, oldloc)
if(destarea && old_area != destarea)
destarea.Entered(src, oldloc)
for(var/atom/movable/AM in destination)
if(AM == src)
continue
AM.Crossed(src, oldloc)
Moved(oldloc, NONE, TRUE)
. = TRUE
//If no destination, move the atom into nullspace (don't do this unless you know what you're doing)
else
. = TRUE
if (loc)
var/atom/oldloc = loc
var/area/old_area = get_area(oldloc)
oldloc.Exited(src, null)
if(old_area)
old_area.Exited(src, null)
loc = null
//Called whenever an object moves and by mobs when they attempt to move themselves through space
//And when an object or action applies a force on src, see newtonian_move() below
//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting
//Mobs should return 1 if they should be able to move of their own volition, see client/Move() in mob_movement.dm
//movement_dir == 0 when stopping or any dir when trying to move
/atom/movable/proc/Process_Spacemove(movement_dir = 0)
if(has_gravity(src))
return 1
if(pulledby)
return 1
if(throwing)
return 1
if(!isturf(loc))
return 1
if(locate(/obj/structure/lattice) in range(1, get_turf(src))) //Not realistic but makes pushing things in space easier
return 1
return 0
/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity
if(!loc || Process_Spacemove(0))
inertia_dir = 0
return 0
inertia_dir = direction
if(!direction)
return 1
inertia_last_loc = loc
SSspacedrift.processing[src] = src
return 1
+1 -1
View File
@@ -269,7 +269,7 @@ Credit where due:
//Servant of Ratvar outfit
/datum/outfit/servant_of_ratvar
name = "Servant of Ratvar"
uniform = /obj/item/clothing/under/rank/engineer //no more chameleon suit for them, as requested
uniform = /obj/item/clothing/under/rank/engineering/engineer //no more chameleon suit for them, as requested
shoes = /obj/item/clothing/shoes/sneakers/black
back = /obj/item/storage/backpack
ears = /obj/item/radio/headset
+11 -17
View File
@@ -4,23 +4,17 @@
icon = 'icons/obj/machines/nuke.dmi'
icon_state = "bananiumbomb_base"
/obj/machinery/nuclearbomb/syndicate/bananium/update_icon()
if(deconstruction_state == NUKESTATE_INTACT)
switch(get_nuke_state())
if(NUKE_OFF_LOCKED, NUKE_OFF_UNLOCKED)
icon_state = "bananiumbomb_base"
update_icon_interior()
update_icon_lights()
if(NUKE_ON_TIMING)
cut_overlays()
icon_state = "bananiumbomb_timing"
if(NUKE_ON_EXPLODING)
cut_overlays()
icon_state = "bananiumbomb_exploding"
else
/obj/machinery/nuclearbomb/syndicate/bananium/update_icon_state()
if(deconstruction_state != NUKESTATE_INTACT)
icon_state = "bananiumbomb_base"
update_icon_interior()
update_icon_lights()
return
switch(get_nuke_state())
if(NUKE_OFF_LOCKED, NUKE_OFF_UNLOCKED)
icon_state = "bananiumbomb_base"
if(NUKE_ON_TIMING)
icon_state = "bananiumbomb_timing"
if(NUKE_ON_EXPLODING)
icon_state = "bananiumbomb_exploding"
/obj/machinery/nuclearbomb/syndicate/bananium/get_cinematic_type(off_station)
switch(off_station)
@@ -41,7 +35,7 @@
H.Stun(10)
var/obj/item/clothing/C
if(!H.w_uniform || H.dropItemToGround(H.w_uniform))
C = new /obj/item/clothing/under/rank/clown(H)
C = new /obj/item/clothing/under/rank/civilian/clown(H)
ADD_TRAIT(C, TRAIT_NODROP, CLOWN_NUKE_TRAIT)
H.equip_to_slot_or_del(C, SLOT_W_UNIFORM)
@@ -2,6 +2,7 @@
ruletype = "Event"
var/typepath // typepath of the event
var/triggering
var/earliest_start = 20 MINUTES
/datum/dynamic_ruleset/event/get_blackbox_info()
var/list/ruleset_data = list()
@@ -25,8 +26,10 @@
return E
/datum/dynamic_ruleset/event/ready(forced = FALSE) // same as midround cause we're still using enemy system
/datum/dynamic_ruleset/event/ready(forced = FALSE)
if (!forced)
if(earliest_start >= world.time-SSticker.round_start_time)
return FALSE
var/job_check = 0
if (enemy_roles.len > 0)
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
@@ -56,6 +59,7 @@
required_enemies = list(2,2,1,1,0,0,0,0,0,0)
weight = 5
cost = 10
earliest_start = 30 MINUTES
blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear)
requirements = list(70,60,50,50,40,40,40,30,20,15)
property_weights = list("story_potential" = 1, "trust" = 1, "chaos" = 1)
@@ -157,17 +161,18 @@
required_enemies = list(3,3,3,3,3,3,3,3,3,3)
cost = 15
weight = 3
earliest_start = 25 MINUTES
repeatable_weight_decrease = 2
requirements = list(60,50,40,30,30,30,30,30,30,30)
high_population_requirement = 30
property_weights = list("extended" = -2)
/datum/dynamic_ruleset/event/meteor_wave/ready()
if(mode.threat_level > 40 && mode.threat >= 25 && prob(20))
if(world.time-SSticker.round_start_time > 35 MINUTES && mode.threat_level > 40 && mode.threat >= 25 && prob(30))
name = "Meteor Wave: Threatening"
cost = 25
typepath = /datum/round_event/meteor_wave/threatening
else if(mode.threat_level > 50 && mode.threat >= 40 && prob(30))
else if(world.time-SSticker.round_start_time > 45 MINUTES && mode.threat_level > 50 && mode.threat >= 40 && prob(30))
name = "Meteor Wave: Catastrophic"
cost = 40
typepath = /datum/round_event/meteor_wave/catastrophic
@@ -280,6 +285,7 @@
cost = 4
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
earliest_start = 10 MINUTES
repeatable = TRUE
property_weights = list("extended" = 1)
@@ -324,6 +330,7 @@
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
earliest_start = 0 MINUTES
property_weights = list("extended" = 1)
always_max_weight = TRUE
@@ -381,3 +388,67 @@
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
property_weights = list("extended" = 1,"chaos" = 1)
/datum/dynamic_ruleset/event/portal_storm_syndicate
name = "Portal Storm"
config_tag = "portal_storm"
typepath = /datum/round_event/portal_storm/syndicate_shocktroop
cost = 10
weight = 1
enemy_roles = list("Head of Security","Security Officer","AI","Captain","Shaft Miner")
required_enemies = list(2,2,2,2,2,2,2,2,2,2)
requirements = list(101,101,101,30,30,30,30,30,30,30)
high_population_requirement = 30
earliest_start = 30 MINUTES
property_weights = list("teamwork" = 1,"chaos" = 1, "extended" = -1)
/datum/dynamic_ruleset/event/wormholes
name = "Wormholes"
config_tag = "wormhole"
typepath = /datum/round_event/wormholes
cost = 3
weight = 4
enemy_roles = list("AI","Medical Doctor","Station Engineer","Head of Personnel","Captain")
required_enemies = list(2,2,2,2,2,2,2,2,2,2)
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
property_weights = list("extended" = 1)
/datum/dynamic_ruleset/event/swarmers
name = "Swarmers"
config_tag = "swarmer"
typepath = /datum/round_event/spawn_swarmer
cost = 10
weight = 1
earliest_start = 30 MINUTES
enemy_roles = list("AI","Security Officer","Head of Security","Captain","Station Engineer","Atmos Technician","Chief Engineer")
required_enemies = list(4,4,4,4,3,3,2,2,1,1)
requirements = list(101,101,101,101,101,101,101,101,101,101)
high_population_requirement = 5
property_weights = list("extended" = -2)
/datum/dynamic_ruleset/event/sentient_disease
name = "Sentient Disease"
config_tag = "sentient_disease"
typepath = /datum/round_event/ghost_role/sentient_disease
enemy_roles = list("Virologist","Chief Medical Officer","Captain","Chemist")
required_enemies = list(2,1,1,1,0,0,0,0,0,0)
required_candidates = 1
weight = 4
cost = 5
requirements = list(30,30,20,20,15,10,10,10,10,5) // yes, it can even happen in "extended"!
property_weights = list("story_potential" = 1, "extended" = 1, "valid" = -2)
high_population_requirement = 5
/datum/dynamic_ruleset/event/revenant
name = "Revenant"
config_tag = "revenant"
typepath = /datum/round_event/ghost_role/revenant
enemy_roles = list("Chief Engineer","Station Engineer","Captain","Chaplain","AI")
required_enemies = list(2,1,1,1,0,0,0,0,0,0)
required_candidates = 1
weight = 4
cost = 5
requirements = list(30,30,30,30,20,15,15,15,15,15)
high_population_requirement = 15
property_weights = list("story_potential" = -2, "extended" = -1)
@@ -34,7 +34,7 @@
living_players = trim_list(mode.current_players[CURRENT_LIVING_PLAYERS])
living_antags = trim_list(mode.current_players[CURRENT_LIVING_ANTAGS])
list_observers = trim_list(mode.current_players[CURRENT_OBSERVERS])
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(/datum/element/ghost_role_eligibility)
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
ghost_eligible = trim_list(eligibility.get_all_ghost_role_eligible())
/datum/dynamic_ruleset/midround/proc/trim_list(list/L = list())
@@ -43,7 +43,7 @@
if (!istype(M, required_type))
trimmed_list.Remove(M)
continue
if (M.GetComponent(/datum/component/virtual_reality))
if (HAS_TRAIT(M, TRAIT_NO_MIDROUND_ANTAG))
trimmed_list.Remove(M)
continue
if (!M.client) // Are they connected?
@@ -273,10 +273,14 @@
var/ion_announce = 33
var/removeDontImproveChance = 10
/datum/dynamic_ruleset/midround/malf/ready()
if(!candidates || !candidates.len)
return FALSE
return ..()
/datum/dynamic_ruleset/midround/malf/trim_candidates()
..()
living_players = candidates[CURRENT_LIVING_PLAYERS]
for(var/mob/living/player in candidates)
for(var/mob/living/player in living_players)
if(!isAI(player))
candidates -= player
continue
@@ -287,8 +291,6 @@
candidates -= player
/datum/dynamic_ruleset/midround/malf/execute()
if(!candidates || !candidates.len)
return FALSE
var/mob/living/silicon/ai/M = pick_n_take(candidates)
assigned += M.mind
var/datum/antagonist/traitor/AI = new
@@ -337,6 +339,7 @@
/datum/dynamic_ruleset/midround/from_ghosts/wizard/finish_setup(mob/new_character, index)
..()
new_character.forceMove(pick(GLOB.wizardstart))
wizard = new_character.mind
/datum/dynamic_ruleset/midround/from_ghosts/wizard/rule_process() // i can literally copy this from are_special_antags_dead it's great
if(isliving(wizard.current) && wizard.current.stat!=DEAD)
@@ -447,9 +450,7 @@
property_weights = list("story_potential" = -1, "trust" = 1, "chaos" = 2, "extended" = -2, "valid" = 2)
var/list/vents = list()
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/execute()
// 50% chance of being incremented by one
required_candidates += prob(50)
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/ready()
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in GLOB.machines)
if(QDELETED(temp_vent))
continue
@@ -463,6 +464,12 @@
vents += temp_vent
if(!vents.len)
return FALSE
return ..()
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/execute()
// 50% chance of being incremented by one
required_candidates += prob(50)
. = ..()
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/generate_ruleset_body(mob/applicant)
@@ -497,7 +504,7 @@
property_weights = list("story_potential" = 1, "trust" = 1, "extended" = 1, "valid" = 2, "integrity" = 1)
var/list/spawn_locs = list()
/datum/dynamic_ruleset/midround/from_ghosts/nightmare/execute()
/datum/dynamic_ruleset/midround/from_ghosts/nightmare/ready()
for(var/X in GLOB.xeno_spawn)
var/turf/T = X
var/light_amount = T.get_lumcount()
@@ -505,7 +512,7 @@
spawn_locs += T
if(!spawn_locs.len)
return FALSE
. = ..()
return ..()
/datum/dynamic_ruleset/midround/from_ghosts/nightmare/generate_ruleset_body(mob/applicant)
var/datum/mind/player_mind = new /datum/mind(applicant.key)
@@ -523,88 +530,6 @@
log_game("DYNAMIC: [key_name(S)] was spawned as a Nightmare by the midround ruleset.")
return S
//////////////////////////////////////////////
// //
// SENTIENT DISEASE //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/midround/from_ghosts/sentient_disease
name = "Sentient Disease"
config_tag = "sentient_disease"
antag_flag = ROLE_ALIEN
enemy_roles = list("Virologist","Chief Medical Officer","Captain","Chemist")
required_enemies = list(2,1,1,1,0,0,0,0,0,0)
required_candidates = 1
weight = 4
cost = 5
requirements = list(30,30,20,20,15,10,10,10,10,5) // yes, it can even happen in "extended"!
property_weights = list("story_potential" = 1, "extended" = 1, "valid" = -2)
high_population_requirement = 5
/datum/dynamic_ruleset/midround/from_ghosts/sentient_disease/generate_ruleset_body(mob/applicant)
var/mob/camera/disease/virus = new /mob/camera/disease(SSmapping.get_station_center())
applicant.transfer_ckey(virus, FALSE)
INVOKE_ASYNC(virus, /mob/camera/disease/proc/pick_name)
message_admins("[ADMIN_LOOKUPFLW(virus)] has been made into a sentient disease by the midround ruleset.")
log_game("[key_name(virus)] was spawned as a sentient disease by the midround ruleset.")
return virus
//////////////////////////////////////////////
// //
// REVENANT //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/midround/from_ghosts/revenant
name = "Revenant"
config_tag = "revenant"
antag_flag = ROLE_REVENANT
enemy_roles = list("Chief Engineer","Station Engineer","Captain","Chaplain","AI")
required_enemies = list(2,1,1,1,0,0,0,0,0,0)
required_candidates = 1
weight = 4
cost = 5
requirements = list(30,30,30,30,20,15,15,15,15,15)
high_population_requirement = 15
property_weights = list("story_potential" = -2, "extended" = -1)
var/list/spawn_locs = list()
/datum/dynamic_ruleset/midround/from_ghosts/revenant/acceptable(population = 0,threat = 0)
var/deadMobs = 0
for(var/mob/M in GLOB.dead_mob_list)
deadMobs++
if(deadMobs < REVENANT_SPAWN_THRESHOLD)
return FALSE
return ..()
/datum/dynamic_ruleset/midround/from_ghosts/revenant/ready(forced = FALSE)
for(var/mob/living/L in GLOB.dead_mob_list) //look for any dead bodies
var/turf/T = get_turf(L)
if(T && is_station_level(T.z))
spawn_locs += T
if(!spawn_locs.len || spawn_locs.len < 15) //look for any morgue trays, crematoriums, ect if there weren't alot of dead bodies on the station to pick from
for(var/obj/structure/bodycontainer/bc in GLOB.bodycontainers)
var/turf/T = get_turf(bc)
if(T && is_station_level(T.z))
spawn_locs += T
if(!spawn_locs.len) //If we can't find any valid spawnpoints, try the carp spawns
for(var/obj/effect/landmark/carpspawn/L in GLOB.landmarks_list)
if(isturf(L.loc))
spawn_locs += L.loc
if(!spawn_locs.len) //If we can't find THAT, then just give up and cry
return FALSE
return ..()
/datum/dynamic_ruleset/midround/from_ghosts/revenant/generate_ruleset_body(mob/applicant)
var/mob/living/simple_animal/revenant/revvie = new(pick(spawn_locs))
applicant.transfer_ckey(revvie, FALSE)
message_admins("[ADMIN_LOOKUPFLW(revvie)] has been made into a revenant by the midround ruleset.")
log_game("[key_name(revvie)] was spawned as a revenant by the midround ruleset.")
return revvie
//////////////////////////////////////////////
// //
// SLAUGHTER DEMON //
@@ -668,11 +593,11 @@
required_candidates = 2
weight = 8
cost = 10
requirements = list(101,101,70,50,40,30,30,20,15,15)
requirements = list(101,101,70,50,40,30,30,30,30,30)
blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear)
high_population_requirement = 15
var/datum/team/abductor_team/team
property_weights = list("story_potential" = 1, "extended" = -2, "valid" = 1, "trust" = -1, "chaos" = 2)
property_weights = list("extended" = -2, "valid" = 1, "trust" = -1, "chaos" = 2)
repeatable_weight_decrease = 4
repeatable = TRUE
@@ -742,15 +667,19 @@
var/datum/antagonist/ninja/ninjadatum = new
ninjadatum.helping_station = pick(TRUE,FALSE)
if(ninjadatum.helping_station)
mode.refund_threat(5)
mode.refund_threat(cost+5)
mode.log_threat("Ninja was helping station; [cost+5] cost refunded.")
Mind.add_antag_datum(ninjadatum)
if(Ninja.mind != Mind) //something has gone wrong!
throw EXCEPTION("Ninja created with incorrect mind")
stack_trace("Ninja created with incorrect mind")
message_admins("[ADMIN_LOOKUPFLW(Ninja)] has been made into a ninja by dynamic.")
log_game("[key_name(Ninja)] was spawned as a ninja by dynamic.")
return Ninja
/datum/dynamic_ruleset/midround/from_ghosts/ninja/finish_setup(mob/new_character, index)
return
#undef ABDUCTOR_MAX_TEAMS
#undef REVENANT_SPAWN_THRESHOLD
@@ -623,8 +623,7 @@
config_tag = "clownops"
antag_datum = /datum/antagonist/nukeop/clownop
antag_leader_datum = /datum/antagonist/nukeop/leader/clownop
requirements = list(101,101,101,101,101,101,101,101,101,101)
high_population_requirement = 101
weight = 1
property_weights = list("trust" = 2, "chaos" = 2, "extended" = -2, "story_potential" = 2, "valid" = 2)
@@ -1,16 +1,22 @@
/datum/dynamic_storyteller
var/name = "none"
var/config_tag = null
var/desc = "A coder's idiocy."
var/list/property_weights = list()
var/curve_centre = 0
var/curve_width = 1.8
var/name = "none" // Name for voting.
var/config_tag = null // Config tag for config weights.
var/desc = "A coder's idiocy." // Description for voting.
var/list/property_weights = list() // See below.
var/curve_centre = 0 // As GLOB.dynamic_curve_centre.
var/curve_width = 1.8 // As GLOB.dynamic_curve_width.
var/forced_threat_level = -1
/*
NO_ASSASSIN: Will not have permanent assassination targets.
WAROPS_ALWAYS_ALLOWED: Can always do warops, regardless of threat level.
USE_PREF_WEIGHTS: Will use peoples' preferences to change the threat centre.
*/
var/flags = 0
var/weight = 3 // how many rounds need to have been recently played for this storyteller to be left out of the vote
var/event_frequency_lower = 6 MINUTES
var/event_frequency_upper = 20 MINUTES
var/datum/game_mode/dynamic/mode = null
var/weight = 3 // Weights for randomly picking storyteller. Multiplied by score after voting.
var/event_frequency_lower = 6 MINUTES // How rare events will be, at least.
var/event_frequency_upper = 20 MINUTES // How rare events will be, at most.
var/pop_antag_ratio = 5 // How many non-antags there should be vs antags.
var/datum/game_mode/dynamic/mode = null // Cached as soon as it's made, by dynamic.
/**
Property weights are:
@@ -80,7 +86,7 @@ Property weights are:
var/chance = 0
// If the high pop override is in effect, we reduce the impact of population on the antag injection chance
var/high_pop_factor = (mode.current_players[CURRENT_LIVING_PLAYERS].len >= GLOB.dynamic_high_pop_limit)
var/max_pop_per_antag = max(5,15 - round(mode.threat_level/10) - round(mode.current_players[CURRENT_LIVING_PLAYERS].len/(high_pop_factor ? 10 : 5)))
var/max_pop_per_antag = max(pop_antag_ratio,15 - round(mode.threat_level/10) - round(mode.current_players[CURRENT_LIVING_PLAYERS].len/(high_pop_factor ? 10 : 5)))
if (!mode.current_players[CURRENT_LIVING_ANTAGS].len)
chance += 80 // No antags at all? let's boost those odds!
else
@@ -173,12 +179,13 @@ Property weights are:
name = "Chaotic"
config_tag = "chaotic"
curve_centre = 10
desc = "Chaos: high. Variation: high. Likely antags: clock cult, revs, wizard."
desc = "High chaos modes. Revs, wizard, clock cult. Multiple antags at once. Chaos is kept up all round."
property_weights = list("extended" = -1, "chaos" = 10)
weight = 1
event_frequency_lower = 2 MINUTES
event_frequency_upper = 10 MINUTES
flags = WAROPS_ALWAYS_ALLOWED
pop_antag_ratio = 4
var/refund_cooldown = 0
/datum/dynamic_storyteller/cowabunga/get_midround_cooldown()
@@ -189,14 +196,14 @@ Property weights are:
/datum/dynamic_storyteller/cowabunga/do_process()
if(refund_cooldown < world.time)
mode.refund_threat(20)
mode.log_threat("Cowabunga it is. Refunded 20 threat. Threat is now [mode.threat].")
refund_cooldown = world.time + 600 SECONDS
mode.refund_threat(40)
mode.log_threat("Chaotic storyteller refunded 40 threat. Threat is now [mode.threat].")
refund_cooldown = world.time + 1200 SECONDS
/datum/dynamic_storyteller/team
name = "Teamwork"
config_tag = "teamwork"
desc = "Chaos: high. Variation: low. Likely antags: nukies, clockwork cult, wizard, blob, xenomorph."
desc = "Modes where the crew must band together. Nukies, xenos, blob. Only one antag threat at once."
curve_centre = 2
curve_width = 1.5
weight = 2
@@ -209,56 +216,71 @@ Property weights are:
/datum/dynamic_storyteller/conversion
name = "Conversion"
config_tag = "conversion"
desc = "Chaos: high. Variation: medium. Likely antags: cults, bloodsuckers, revs."
desc = "Conversion antags. Cults, revs."
curve_centre = 3
curve_width = 1
weight = 2
weight = 0
flags = WAROPS_ALWAYS_ALLOWED
property_weights = list("valid" = 1, "conversion" = 20)
/datum/dynamic_storyteller/classic
name = "Random"
config_tag = "random"
desc = "Chaos: varies. Variation: highest. No special weights attached."
weight = 6
flags = USE_PREF_WEIGHTS
desc = "No special weights attached. Anything goes."
weight = 4
curve_width = 4
pop_antag_ratio = 7
flags = USE_PREF_WEIGHTS
/datum/dynamic_storyteller/memes
/datum/dynamic_storyteller/story
name = "Story"
config_tag = "story"
desc = "Chaos: varies. Variation: high. Likely antags: abductors, nukies, wizard, traitor."
weight = 4
flags = USE_PREF_WEIGHTS
curve_width = 4
desc = "Antags with options for loadouts and gimmicks. Traitor, wizard, nukies."
weight = 2
curve_width = 2
pop_antag_ratio = 7
property_weights = list("story_potential" = 10)
/datum/dynamic_storyteller/suspicion
name = "Intrigue"
config_tag = "intrigue"
desc = "Chaos: low. Variation: high. Likely antags: traitor, bloodsucker. Rare: revs, blood cult."
weight = 4
flags = USE_PREF_WEIGHTS
curve_width = 4
desc = "Antags that instill distrust in the crew. Traitors, bloodsuckers."
weight = 2
curve_width = 2
pop_antag_ratio = 7
property_weights = list("trust" = -5)
/datum/dynamic_storyteller/liteextended
name = "Calm"
config_tag = "calm"
desc = "Chaos: low. Variation: medium. Likely antags: bloodsuckers, traitors, sentient disease, revenant."
desc = "Low-chaos round. Few antags. No conversion."
curve_centre = -3
curve_width = 0.5
flags = NO_ASSASSIN
weight = 1
pop_antag_ratio = 10
property_weights = list("extended" = 1, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10)
/datum/dynamic_storyteller/no_antag
name = "Extended"
config_tag = "semiextended"
desc = "No standard antags. Threatening events may still spawn."
curve_centre = -5
curve_width = 0.5
flags = NO_ASSASSIN
weight = 2
property_weights = list("extended" = 1, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10)
weight = 1
property_weights = list("extended" = 2)
/datum/dynamic_storyteller/liteextended/get_injection_chance(dry_run = FALSE)
return ..()/2
/datum/dynamic_storyteller/no_antag/roundstart_draft()
return list()
/datum/dynamic_storyteller/no_antag/get_injection_chance(dry_run)
return 0
/datum/dynamic_storyteller/extended
name = "Extended"
name = "Super Extended"
config_tag = "extended"
desc = "Chaos: none. Variation: none. Likely antags: none."
desc = "No antags. No dangerous events."
curve_centre = -20
weight = 0
curve_width = 0.5
+6 -6
View File
@@ -21,7 +21,7 @@
/datum/team/gang/zerog
name = "Zero-G"
color = "#C0C0C0"
inner_outfits = list(/obj/item/clothing/under/suit_jacket/white)
inner_outfits = list(/obj/item/clothing/under/suit/white)
outer_outfits = list(/obj/item/clothing/suit/hooded/wintercoat)
/datum/team/gang/max
@@ -33,13 +33,13 @@
/datum/team/gang/blasto
name = "Blasto"
color = "#000080"
inner_outfits = list(/obj/item/clothing/under/suit_jacket/navy)
inner_outfits = list(/obj/item/clothing/under/suit/navy)
outer_outfits = list(/obj/item/clothing/suit/jacket/miljacket)
/datum/team/gang/waffle
name = "Waffle"
color = "#808000" //shared color with cyber, but they can keep brown cause waffles.
inner_outfits = list(/obj/item/clothing/under/suit_jacket/green)
inner_outfits = list(/obj/item/clothing/under/suit/green)
outer_outfits = list(/obj/item/clothing/suit/poncho)
/datum/team/gang/north
@@ -87,7 +87,7 @@
/datum/team/gang/tunnel
name = "Tunnel"
color = "#FF00FF" //Gave the leather jacket to the tunnel gang over diablo.
inner_outfits = list(/obj/item/clothing/under/villain)
inner_outfits = list(/obj/item/clothing/under/costume/villain)
outer_outfits = list(/obj/item/clothing/suit/jacket/leather)
/datum/team/gang/diablo
@@ -123,13 +123,13 @@
/datum/team/gang/h
name = "H"
color = "#993333"
inner_outfits = list(/obj/item/clothing/under/jabroni) //Why not?
inner_outfits = list(/obj/item/clothing/under/costume/jabroni) //Why not?
outer_outfits = list(/obj/item/clothing/suit/toggle/owlwings)
/datum/team/gang/rigatonifamily
name = "Rigatoni family"
color = "#cc9900" // p a s t a colored
inner_outfits = list(/obj/item/clothing/under/rank/chef)
inner_outfits = list(/obj/item/clothing/under/rank/civilian/chef)
outer_outfits = list(/obj/item/clothing/suit/apron/chef)
/datum/team/gang/weed
+3 -3
View File
@@ -220,11 +220,11 @@ datum/gang_item/clothing/shades //Addition: Why not have cool shades on a gang m
cost = 15
item_path = /obj/item/ammo_box/magazine/sniper_rounds
/datum/gang_item/weapon/ammo/sleeper_ammo
/*/datum/gang_item/weapon/ammo/sleeper_ammo //no. absolutely no.
name = "Illicit Soporific Cartridges"
id = "sniper_ammo"
cost = 15
item_path = /obj/item/ammo_box/magazine/sniper_rounds/soporific
cost = 15 //who the fuck thought a ONE-HIT K.O. for 15 gbp IN AN ENVIRONMENT WHERE WE'RE GETTING RID OF HARDSTUNS is a GOOD IDEA
item_path = /obj/item/ammo_box/magazine/sniper_rounds/soporific*/
/datum/gang_item/weapon/machinegun
name = "Mounted Machine Gun"
+1 -1
View File
@@ -54,6 +54,6 @@
return
var/mob/living/carbon/human/H = gangster_mind.current // we are sure the dude's human cause it's checked in attack()
H.silent = max(H.silent, 5)
H.Knockdown(100)
H.DefaultCombatKnockdown(100)
gangster_mind.add_antag_datum(/datum/antagonist/gang, gang)
return TRUE
+2 -2
View File
@@ -165,7 +165,7 @@
/datum/outfit/syndicate/full
name = "Syndicate Operative - Full Kit"
glasses = /obj/item/clothing/glasses/night
glasses = /obj/item/clothing/glasses/night/syndicate
mask = /obj/item/clothing/mask/gas/syndicate
suit = /obj/item/clothing/suit/space/hardsuit/syndi
r_pocket = /obj/item/tank/internals/emergency_oxygen/engi
@@ -180,7 +180,7 @@
/datum/outfit/syndicate/lone
name = "Syndicate Operative - Lone"
glasses = /obj/item/clothing/glasses/night
glasses = /obj/item/clothing/glasses/night/syndicate
mask = /obj/item/clothing/mask/gas/syndicate
suit = /obj/item/clothing/suit/space/syndicate/black/red
head = /obj/item/clothing/head/helmet/space/syndicate/black/red
+30 -4
View File
@@ -86,8 +86,10 @@ GLOBAL_LIST_EMPTY(objectives)
if(M)
. += M
/datum/objective/proc/find_target()
/datum/objective/proc/find_target(dupe_search_range, blacklist)
var/list/datum/mind/owners = get_owners()
if(!dupe_search_range)
dupe_search_range = get_owners()
var/list/possible_targets = list()
var/try_target_late_joiners = FALSE
for(var/I in owners)
@@ -96,7 +98,8 @@ GLOBAL_LIST_EMPTY(objectives)
try_target_late_joiners = TRUE
for(var/datum/mind/possible_target in get_crewmember_minds())
if(!(possible_target in owners) && ishuman(possible_target.current) && (possible_target.current.stat != DEAD) && is_unique_objective(possible_target))
possible_targets += possible_target
if(!(possible_target in blacklist))
possible_targets += possible_target
if(try_target_late_joiners)
var/list/all_possible_targets = possible_targets.Copy()
for(var/I in all_possible_targets)
@@ -1075,7 +1078,7 @@ GLOBAL_LIST_EMPTY(cult_contraband)
var/mob/living/carbon/human/H = owner
H.equip_in_one_of_slots(I, list("backpack" = SLOT_IN_BACKPACK))
hoarded_item = I
GLOBAL_LIST_EMPTY(possible_sabotages)
@@ -1092,7 +1095,7 @@ GLOBAL_LIST_EMPTY(possible_sabotages)
if(!GLOB.possible_sabotages.len)//Only need to fill the list when it's needed.
for(var/I in subtypesof(/datum/sabotage_objective))
new I
/datum/objective/sabotage/find_target()
var/list/datum/mind/owners = get_owners()
var/approved_targets = list()
@@ -1155,3 +1158,26 @@ GLOBAL_LIST_EMPTY(possible_sabotages)
/datum/objective/flavor/wizard
flavor_file = "strings/flavor_objectives/wizard.txt"
/datum/objective/contract
var/payout = 0
var/payout_bonus = 0
var/area/dropoff = null
var/static/list/blacklisted_areas = typecacheof(list(/area/ai_monitored/turret_protected,
/area/solar/,
/area/ruin/, //thank you station space ruins
/area/science/test_area/,
/area/shuttle/))
/datum/objective/contract/proc/generate_dropoff() // Generate a random valid area on the station that the dropoff will happen.
var/found = FALSE
while(!found)
var/area/dropoff_area = pick(GLOB.sortedAreas)
if(dropoff_area && is_station_level(dropoff_area.z) && !dropoff_area.outdoors && !is_type_in_typecache(dropoff_area, blacklisted_areas))
dropoff = dropoff_area
found = TRUE
/datum/objective/contract/proc/dropoff_check(mob/user, mob/target) // Check if both the contractor and contract target are at the dropoff point.
var/area/user_area = get_area(user)
var/area/target_area = get_area(target)
return (istype(user_area, dropoff) && istype(target_area, dropoff))
+9 -4
View File
@@ -205,13 +205,18 @@
difficulty = 10
/datum/objective_item/special/boh
name = "a bag of holding."
name = "a type of bag of holding."
targetitem = /obj/item/storage/backpack/holding
difficulty = 10
/datum/objective_item/special/hypercell
name = "a hyper-capacity power cell."
targetitem = /obj/item/stock_parts/cell/hyper
/datum/objective_item/special/adv_surgical_drapes
name = "a set of smart surgical drapes."
targetitem = /obj/item/surgical_drapes/advanced
difficulty = 10 //would be 15 but cmo rarely have it on themselfs and leave it in their lockers...
/datum/objective_item/special/bluespace
name = "a bluespace power cell."
targetitem = /obj/item/stock_parts/cell/bluespace
difficulty = 5
/datum/objective_item/special/laserpointer
+7 -14
View File
@@ -23,34 +23,27 @@
START_PROCESSING(SSprocessing, src)
/datum/sabotage_objective/processing/proc/check_condition_processing()
return 100
return 1
/datum/sabotage_objective/processing/process()
check_condition_processing()
if(won >= 100)
if(won >= 1)
STOP_PROCESSING(SSprocessing,src)
/datum/sabotage_objective/processing/check_conditions()
return won
/datum/sabotage_objective/processing/power_sink
name = "Drain at least 1 gigajoule of power using a power sink."
name = "Drain at least 100 megajoules of power using a power sink."
sabotage_type = "powersink"
special_equipment = list(/obj/item/powersink)
special_equipment = list(/obj/item/sbeacondrop/powersink)
var/sink_found = FALSE
var/count = 0
/datum/sabotage_objective/processing/power_sink/check_condition_processing()
count += 1
if(count==10 || sink_found) // doesn't need to fire that often unless a sink exists
var/sink_found_this_time = FALSE
for(var/datum/powernet/PN in GLOB.powernets)
for(var/obj/item/powersink/sink in PN.nodes)
sink_found_this_time = TRUE
won = max(won,sink.power_drained/1e9)
sink_found = sink_found_this_time
count = 0
return FALSE
for(var/s in GLOB.power_sinks)
var/obj/item/powersink/sink = s
won = max(won,sink.power_drained/1e8)
/obj/item/paper/guides/antag/supermatter_sabotage
info = "Ways to sabotage a supermatter:<br>\
+1 -1
View File
@@ -28,7 +28,7 @@
update_icon()
// update the icon_state
/obj/machinery/bluespace_beacon/update_icon()
/obj/machinery/bluespace_beacon/update_icon_state()
var/state="floor_beacon"
if(invisibility)
+10 -5
View File
@@ -9,16 +9,12 @@
var/list/colorlist = list()
/obj/machinery/pdapainter/update_icon()
cut_overlays()
/obj/machinery/pdapainter/update_icon_state()
if(stat & BROKEN)
icon_state = "[initial(icon_state)]-broken"
return
if(storedpda)
add_overlay("[initial(icon_state)]-closed")
if(powered())
icon_state = initial(icon_state)
else
@@ -26,6 +22,15 @@
return
/obj/machinery/pdapainter/update_overlays()
. = ..()
if(stat & BROKEN)
return
if(storedpda)
. += "[initial(icon_state)]-closed"
/obj/machinery/pdapainter/Initialize()
. = ..()
var/list/blocked = list(
+1 -1
View File
@@ -71,7 +71,7 @@
reagents.maximum_volume = (500*E)
/obj/machinery/sleeper/update_icon()
/obj/machinery/sleeper/update_icon_state()
icon_state = initial(icon_state)
if(state_open)
icon_state += "-open"
+1 -1
View File
@@ -185,7 +185,7 @@ Class Procs:
A.forceMove(T)
if(isliving(A))
var/mob/living/L = A
L.update_canmove()
L.update_mobility()
if(occupant)
SEND_SIGNAL(src, COMSIG_MACHINE_EJECT_OCCUPANT, occupant)
occupant = null
+1 -1
View File
@@ -113,7 +113,7 @@
id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_SENSOR
master_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_CONTROLLER
/obj/machinery/airlock_sensor/update_icon()
/obj/machinery/airlock_sensor/update_icon_state()
if(on)
if(alert)
icon_state = "airlock_sensor_alert"
+6 -6
View File
@@ -32,22 +32,22 @@ GLOBAL_LIST_EMPTY(announcement_systems)
radio = new /obj/item/radio/headset/silicon/ai(src)
update_icon()
/obj/machinery/announcement_system/update_icon()
/obj/machinery/announcement_system/update_icon_state()
if(is_operational())
icon_state = (panel_open ? "AAS_On_Open" : "AAS_On")
else
icon_state = (panel_open ? "AAS_Off_Open" : "AAS_Off")
cut_overlays()
/obj/machinery/announcement_system/update_overlays()
. =..()
if(arrivalToggle)
add_overlay(greenlight)
. += greenlight
if(newheadToggle)
add_overlay(pinklight)
. += pinklight
if(stat & BROKEN)
add_overlay(errorlight)
. += errorlight
/obj/machinery/announcement_system/Destroy()
QDEL_NULL(radio)
+6 -6
View File
@@ -19,21 +19,21 @@
initial_icon_state = initial(icon_state)
return ..()
/obj/machinery/aug_manipulator/update_icon()
cut_overlays()
/obj/machinery/aug_manipulator/update_icon_state()
if(stat & BROKEN)
icon_state = "[initial_icon_state]-broken"
return
if(storedpart)
add_overlay("[initial_icon_state]-closed")
if(powered())
icon_state = initial_icon_state
else
icon_state = "[initial_icon_state]-off"
/obj/machinery/aug_manipulator/update_overlays()
. = ..()
if(storedpart)
. += "[initial_icon_state]-closed"
/obj/machinery/aug_manipulator/Destroy()
QDEL_NULL(storedpart)
return ..()
+5 -6
View File
@@ -47,8 +47,8 @@
)
/obj/machinery/autolathe/Initialize()
AddComponent(/datum/component/material_container,
list(/datum/material/iron,
var/static/list/allowed_types = list(
/datum/material/iron,
/datum/material/glass,
/datum/material/gold,
/datum/material/silver,
@@ -62,10 +62,9 @@
/datum/material/plastic,
/datum/material/adamantine,
/datum/material/mythril
),
0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
)
AddComponent(/datum/component/material_container, allowed_types, _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert))
. = ..()
wires = new /datum/wires/autolathe(src)
stored_research = new /datum/techweb/specialized/autounlocking/autolathe
matching_designs = list()
@@ -140,7 +139,7 @@
/obj/machinery/autolathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal))
use_power(MINERAL_MATERIAL_AMOUNT / 10)
else if(item_inserted.custom_materials?.len && item_inserted.custom_materials[getmaterialref(/datum/material/glass)])
else if(item_inserted.custom_materials?.len && item_inserted.custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
flick("autolathe_r",src)//plays glass insertion animation by default otherwise
else
flick("autolathe_o",src)//plays metal insertion animation
+11 -11
View File
@@ -54,16 +54,17 @@
efficiency = E
productivity = P
/obj/machinery/bloodbankgen/update_icon()
cut_overlays()
/obj/machinery/bloodbankgen/update_icon_state()
if(is_operational())
icon_state = "bloodbank-on"
icon_state = "bloodbank-[is_operational() ? "on" : "off"]"
/obj/machinery/bloodbankgen/update_overlays()
. = ..()
if(panel_open)
add_overlay("bloodbank-panel")
. += "bloodbank-panel"
if(src.bag)
add_overlay("bloodbag-input")
if(bag)
. += "bloodbag-input"
if(bag.reagents.total_volume)
var/mutable_appearance/filling_overlay = mutable_appearance(icon, "input-reagent")
@@ -85,10 +86,10 @@
filling_overlay.icon_state = "input-reagent100"
filling_overlay.color = list(mix_color_from_reagents(bag.reagents.reagent_list))
add_overlay(filling_overlay)
. += filling_overlay
if(src.outbag)
add_overlay("bloodbag-output")
if(outbag)
. += "bloodbag-output"
if(outbag.reagents.total_volume)
var/mutable_appearance/filling_overlay = mutable_appearance(icon, "output-reagent")
@@ -110,8 +111,7 @@
filling_overlay.icon_state = "output-reagent100"
filling_overlay.color = list(mix_color_from_reagents(outbag.reagents.reagent_list))
add_overlay(filling_overlay)
return
. += filling_overlay
/obj/machinery/bloodbankgen/process()
if(!is_operational())
+11 -12
View File
@@ -10,18 +10,19 @@
circuit = /obj/item/circuitboard/machine/cell_charger
pass_flags = PASSTABLE
var/obj/item/stock_parts/cell/charging = null
var/chargelevel = -1
var/charge_rate = 500
/obj/machinery/cell_charger/update_icon()
cut_overlays()
if(charging)
add_overlay(image(charging.icon, charging.icon_state))
add_overlay("ccharger-on")
if(!(stat & (BROKEN|NOPOWER)))
var/newlevel = round(charging.percent() * 4 / 100)
chargelevel = newlevel
add_overlay("ccharger-o[newlevel]")
/obj/machinery/cell_charger/update_overlays()
. += ..()
if(!charging)
return
. += mutable_appearance(charging.icon, charging.icon_state)
. += "ccharger-on"
if(!(stat & (BROKEN|NOPOWER)))
var/newlevel = round(charging.percent() * 4 / 100)
. += "ccharger-o[newlevel]"
/obj/machinery/cell_charger/examine(mob/user)
. = ..()
@@ -54,7 +55,6 @@
charging = W
user.visible_message("[user] inserts a cell into [src].", "<span class='notice'>You insert a cell into [src].</span>")
chargelevel = -1
update_icon()
else
if(!charging && default_deconstruction_screwdriver(user, icon_state, icon_state, W))
@@ -77,7 +77,6 @@
/obj/machinery/cell_charger/proc/removecell()
charging.update_icon()
charging = null
chargelevel = -1
update_icon()
/obj/machinery/cell_charger/attack_hand(mob/user)
+46 -43
View File
@@ -77,6 +77,8 @@
name = "cloning data disk"
icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
var/list/fields = list()
var/list/mutations = list()
var/max_mutations = 6
var/read_only = 0 //Well,it's still a floppy disk
//Disk stuff.
@@ -129,7 +131,7 @@
return examine(user)
//Start growing a human clone in the pod!
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, se, mindref, datum/species/mrace, list/features, factions, list/quirks)
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, datum/species/mrace, list/features, factions, list/quirks)
if(panel_open)
return FALSE
if(mess || attempting)
@@ -165,8 +167,9 @@
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
H.hardset_dna(ui, se, H.real_name, null, mrace, features)
H.randmutb() //100% bad mutation. Can be cured with mutadone.
H.hardset_dna(ui, mutation_index, H.real_name, null, mrace, features)
H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) //100% bad mutation. Can be cured with mutadone.
H.silent = 20 //Prevents an extreme edge case where clones could speak if they said something at exactly the right moment.
occupant = H
@@ -216,7 +219,7 @@
if(!is_operational()) //Autoeject if power is lost
if(mob_occupant)
go_out()
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
connected_message("Clone Ejected: Loss of power.")
else if(mob_occupant && (mob_occupant.loc == src))
@@ -226,7 +229,7 @@
SPEAK("The cloning has been \
aborted due to unrecoverable tissue failure.")
go_out()
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
else if(mob_occupant.cloneloss > (100 - heal_level))
mob_occupant.Unconscious(80)
@@ -272,7 +275,7 @@
BP.attach_limb(mob_occupant)
go_out()
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
else if (!mob_occupant || mob_occupant.loc != src)
occupant = null
@@ -320,7 +323,7 @@
SPEAK("An emergency ejection of the current clone has occurred. Survival not guaranteed.")
to_chat(user, "<span class='notice'>You force an emergency ejection. </span>")
go_out()
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
else
return ..()
@@ -418,7 +421,7 @@
if(mob_occupant && prob(100/(severity*efficiency)))
connected_message(Gibberish("EMP-caused Accidental Ejection", 0))
SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of, ERROR: John Doe, prematurely." ,0))
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
go_out()
/obj/machinery/clonepod/ex_act(severity, target)
@@ -477,51 +480,51 @@
flesh_number = unattached_flesh.len
/obj/machinery/clonepod/update_icon()
cut_overlays()
/obj/machinery/clonepod/update_icon_state()
if(mess)
icon_state = "pod_g"
var/image/gib1 = image(CRYOMOBS, "gibup")
var/image/gib2 = image(CRYOMOBS, "gibdown")
gib1.pixel_y = 27 + round(sin(world.time) * 3)
gib1.pixel_x = round(sin(world.time * 3))
gib2.pixel_y = 27 + round(cos(world.time) * 3)
gib2.pixel_x = round(cos(world.time * 3))
add_overlay(gib2)
add_overlay(gib1)
add_overlay("cover-on")
else if(occupant)
icon_state = "pod_1"
var/image/occupant_overlay
var/completion = (flesh_number - unattached_flesh.len) / flesh_number
if(unattached_flesh.len <= 0)
occupant_overlay = image(occupant.icon, occupant.icon_state)
occupant_overlay.copy_overlays(occupant)
else
occupant_overlay = image(CRYOMOBS, "clone_meat")
var/matrix/tform = matrix()
tform.Scale(completion)
tform.Turn(cos(world.time * 2) * 3)
occupant_overlay.transform = tform
occupant_overlay.appearance_flags = 0
occupant_overlay.dir = SOUTH
occupant_overlay.pixel_y = 27 + round(sin(world.time) * 3)
occupant_overlay.pixel_x = round(sin(world.time * 3))
add_overlay(occupant_overlay)
add_overlay("cover-on")
else
icon_state = "pod_0"
if(panel_open)
icon_state = "pod_0_maintenance"
add_overlay("panel")
/obj/machinery/clonepod/update_overlays()
. = ..()
if(mess)
var/mutable_appearance/gib1 = mutable_appearance(CRYOMOBS, "gibup")
var/mutable_appearance/gib2 = mutable_appearance(CRYOMOBS, "gibdown")
gib1.pixel_y = 27 + round(sin(world.time) * 3)
gib1.pixel_x = round(sin(world.time * 3))
gib2.pixel_y = 27 + round(cos(world.time) * 3)
gib2.pixel_x = round(cos(world.time * 3))
. += gib2
. += gib1
else if(occupant)
var/mutable_appearance/occupant_overlay
var/completion = (flesh_number - unattached_flesh.len) / flesh_number
if(unattached_flesh.len <= 0)
occupant_overlay = mutable_appearance(occupant.icon, occupant.icon_state)
occupant_overlay.copy_overlays(occupant)
. += "cover-on"
else
occupant_overlay = mutable_appearance(CRYOMOBS, "clone_meat")
var/matrix/tform = matrix()
tform.Scale(completion)
tform.Turn(cos(world.time * 2) * 3)
occupant_overlay.transform = tform
occupant_overlay.appearance_flags = NONE
occupant_overlay.dir = SOUTH
occupant_overlay.pixel_y = 27 + round(sin(world.time) * 3)
occupant_overlay.pixel_x = round(sin(world.time * 3))
. += occupant_overlay
. += "cover-on"
. += "panel"
/*
* Manual -- A big ol' manual.
+4 -4
View File
@@ -48,13 +48,13 @@
icon_state = initial(icon_state)
update_icon()
/obj/machinery/computer/update_icon()
cut_overlays()
/obj/machinery/computer/update_overlays()
. = ..()
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
if(stat & NOPOWER)
add_overlay("[icon_keyboard]_off")
. += "[icon_keyboard]_off"
return
add_overlay(icon_keyboard)
. += icon_keyboard
// This whole block lets screens ignore lighting and be visible even in the darkest room
// We can't do this for many things that emit light unfortunately because it layers over things that would be on top of it
+11 -12
View File
@@ -103,21 +103,20 @@
add_fingerprint(usr)
updateUsrDialog()
/obj/machinery/computer/aifixer/update_icon()
..()
/obj/machinery/computer/aifixer/update_overlays()
. = ..()
if(stat & (NOPOWER|BROKEN))
return
if(active)
. += "ai-fixer-on"
if (occupier)
switch (occupier.stat)
if (0)
. += "ai-fixer-full"
if (2)
. += "ai-fixer-404"
else
if(active)
add_overlay("ai-fixer-on")
if (occupier)
switch (occupier.stat)
if (0)
add_overlay("ai-fixer-full")
if (2)
add_overlay("ai-fixer-404")
else
add_overlay("ai-fixer-empty")
. += "ai-fixer-empty"
/obj/machinery/computer/aifixer/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
if(!..())
@@ -217,7 +217,7 @@
M.vomit(10, distance = 5)
if(ORION_TRAIL_FLUX)
if(prob(75))
M.Knockdown(60)
M.DefaultCombatKnockdown(60)
say("A sudden gust of powerful wind slams [M] into the floor!")
M.take_bodypart_damage(25)
playsound(loc, 'sound/weapons/genhit.ogg', 100, 1)
+5 -8
View File
@@ -78,23 +78,20 @@
update_icon()
return
/obj/machinery/computer/atmos_alert/update_icon()
..()
cut_overlays()
/obj/machinery/computer/atmos_alert/update_overlays()
. = ..()
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
var/overlay_state = icon_screen
if(stat & (NOPOWER|BROKEN))
add_overlay("[icon_keyboard]_off")
. |= "[icon_keyboard]_off"
return
add_overlay(icon_keyboard)
. |= icon_keyboard
if(priority_alarms.len)
overlay_state = "alert:2"
add_overlay("alert:2")
else if(minor_alarms.len)
overlay_state = "alert:1"
add_overlay("alert:1")
else
overlay_state = "alert:0"
add_overlay("alert:0")
. |= overlay_state
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
@@ -41,7 +41,7 @@
name = "incinerator chamber gas sensor"
id_tag = ATMOS_GAS_MONITOR_SENSOR_INCINERATOR
/obj/machinery/air_sensor/update_icon()
/obj/machinery/air_sensor/update_icon_state()
icon_state = "gsensor[on]"
/obj/machinery/air_sensor/process_atmos()
+1 -2
View File
@@ -175,11 +175,10 @@
clockwork = TRUE //it'd look very weird
light_power = 0
/obj/machinery/computer/security/telescreen/update_icon()
/obj/machinery/computer/security/telescreen/update_icon_state()
icon_state = initial(icon_state)
if(stat & BROKEN)
icon_state += "b"
return
/obj/machinery/computer/security/telescreen/entertainment
name = "entertainment monitor"
+1 -1
View File
@@ -485,7 +485,7 @@
R.fields["id"] = copytext_char(md5(mob_occupant.real_name), 2, 6)
R.fields["UE"] = dna.unique_enzymes
R.fields["UI"] = dna.uni_identity
R.fields["SE"] = dna.struc_enzymes
R.fields["SE"] = dna.mutation_index
R.fields["blood_type"] = dna.blood_type
R.fields["features"] = dna.features
R.fields["factions"] = mob_occupant.faction
+10 -5
View File
@@ -15,6 +15,7 @@
var/message_cooldown = 0
var/ai_message_cooldown = 0
var/tmp_alertlevel = 0
var/static/security_level_cd // used to stop mass spam.
var/const/STATE_DEFAULT = 1
var/const/STATE_CALLSHUTTLE = 2
var/const/STATE_CANCELSHUTTLE = 3
@@ -94,16 +95,18 @@
I = pda.id
if (I && istype(I))
if(ACCESS_CAPTAIN in I.access)
if(security_level_cd > world.time)
to_chat(usr, "<span class='warning'>Security level protocols are currently on cooldown. Please stand by.</span>")
return
var/old_level = GLOB.security_level
if(!tmp_alertlevel)
tmp_alertlevel = SEC_LEVEL_GREEN
if(tmp_alertlevel < SEC_LEVEL_GREEN)
tmp_alertlevel = SEC_LEVEL_GREEN
if(tmp_alertlevel == SEC_LEVEL_BLUE)
tmp_alertlevel = SEC_LEVEL_BLUE
if(tmp_alertlevel > SEC_LEVEL_AMBER)
tmp_alertlevel = SEC_LEVEL_AMBER //Cannot engage delta with this
set_security_level(tmp_alertlevel)
security_level_cd = world.time + 15 SECONDS
if(GLOB.security_level != old_level)
to_chat(usr, "<span class='notice'>Authorization confirmed. Modifying security level.</span>")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
@@ -376,19 +379,21 @@
if("ai-announce")
make_announcement(usr, 1)
if("ai-securitylevel")
if(security_level_cd > world.time)
to_chat(usr, "<span class='warning'>Security level protocols are currently on cooldown. Please stand by.</span>")
return
tmp_alertlevel = text2num( href_list["newalertlevel"] )
if(!tmp_alertlevel)
tmp_alertlevel = 0
tmp_alertlevel = SEC_LEVEL_GREEN
var/old_level = GLOB.security_level
if(!tmp_alertlevel)
tmp_alertlevel = SEC_LEVEL_GREEN
if(tmp_alertlevel < SEC_LEVEL_GREEN)
tmp_alertlevel = SEC_LEVEL_GREEN
if(tmp_alertlevel == SEC_LEVEL_BLUE)
tmp_alertlevel = SEC_LEVEL_BLUE
if(tmp_alertlevel > SEC_LEVEL_AMBER)
tmp_alertlevel = SEC_LEVEL_AMBER //Cannot engage delta with this
set_security_level(tmp_alertlevel)
security_level_cd = world.time + 15 SECONDS
if(GLOB.security_level != old_level)
//Only notify people if an actual change happened
var/security_level = get_security_level()
+594 -144
View File
@@ -1,14 +1,16 @@
#define INJECTOR_TIMEOUT 100
#define REJUVENATORS_INJECT 15
#define REJUVENATORS_MAX 90
#define NUMBER_OF_BUFFERS 3
#define SCRAMBLE_TIMEOUT 600
#define JOKER_TIMEOUT 12000 //20 minutes
#define JOKER_UPGRADE 1800
#define RADIATION_STRENGTH_MAX 15
#define RADIATION_STRENGTH_MULTIPLIER 1 //larger has a more range
#define RADIATION_STRENGTH_MULTIPLIER 1 //larger has more range
#define RADIATION_DURATION_MAX 30
#define RADIATION_ACCURACY_MULTIPLIER 3 //larger is less accurate
#define RADIATION_IRRADIATION_MULTIPLIER 1 //multiplier for how much radiation a test subject receives
#define SCANNER_ACTION_SE 1
@@ -23,22 +25,44 @@
icon_keyboard = "med_key"
density = TRUE
circuit = /obj/item/circuitboard/computer/scan_consolenew
var/radduration = 2
var/radstrength = 1
var/list/buffer[NUMBER_OF_BUFFERS]
var/injectorready = 0 //world timer cooldown var
var/current_screen = "mainmenu"
var/obj/machinery/dna_scannernew/connected = null
var/obj/item/disk/data/diskette = null
var/list/delayed_action = null
use_power = IDLE_POWER_USE
idle_power_usage = 10
active_power_usage = 400
light_color = LIGHT_COLOR_BLUE
var/datum/techweb/stored_research
var/max_storage = 6
var/combine
var/radduration = 2
var/radstrength = 1
var/max_chromosomes = 6
///Amount of mutations we can store
var/list/buffer[NUMBER_OF_BUFFERS]
///mutations we have stored
var/list/stored_mutations = list()
///chromosomes we have stored
var/list/stored_chromosomes = list()
///combinations of injectors for the 'injector selection'. format is list("Elsa" = list(Cryokinesis, Geladikinesis), "The Hulk" = list(Hulk, Gigantism), etc) Glowy and the gang being an initialized datum
var/list/injector_selection = list()
///max amount of selections you can make
var/max_injector_selections = 2
///hard-cap on the advanced dna injector
var/max_injector_mutations = 10
///the max instability of the advanced injector.
var/max_injector_instability = 50
var/injectorready = 0 //world timer cooldown var
var/jokerready = 0
var/scrambleready = 0
var/current_screen = "mainmenu"
var/current_mutation //what block are we inspecting? only used when screen = "info"
var/current_storage //what storage block are we looking at?
var/obj/machinery/dna_scannernew/connected = null
var/obj/item/disk/data/diskette = null
var/list/delayed_action = null
/obj/machinery/computer/scan_consolenew/attackby(obj/item/I, mob/user, params)
if (istype(I, /obj/item/disk/data)) //INSERT SOME DISKETTES
if (!src.diskette)
@@ -48,6 +72,28 @@
to_chat(user, "<span class='notice'>You insert [I].</span>")
src.updateUsrDialog()
return
if (istype(I, /obj/item/chromosome))
if(LAZYLEN(stored_chromosomes) < max_chromosomes)
I.forceMove(src)
stored_chromosomes += I
to_chat(user, "<span class='notice'>You insert [I].</span>")
else
to_chat(user, "<span class='warning'>You cannot store any more chromosomes!</span>")
return
if(istype(I, /obj/item/dnainjector/activator))
var/obj/item/dnainjector/activator/A = I
if(A.used)
to_chat(user,"<span class='notice'>Recycled [I].</span>")
if(A.research)
var/c_typepath = generate_chromosome()
var/obj/item/chromosome/CM = new c_typepath (drop_location())
to_chat(user,"<span class='notice'>Recycled [I].</span>")
if((LAZYLEN(stored_chromosomes) < max_chromosomes) && prob(60))
CM.forceMove(src)
stored_chromosomes += CM
to_chat(user,"<span class='notice'>[capitalize(CM.name)] added to storage.</span>")
qdel(I)
return
else
return ..()
@@ -58,12 +104,26 @@
if(!isnull(connected))
break
injectorready = world.time + INJECTOR_TIMEOUT
scrambleready = world.time + SCRAMBLE_TIMEOUT
jokerready = world.time + JOKER_TIMEOUT
stored_research = SSresearch.science_tech
/obj/machinery/computer/scan_consolenew/examine(mob/user)
. = ..()
if(jokerready < world.time)
. += "<span class='notice'>JOKER algorithm available.</span>"
else
. += "<span class='notice'>JOKER algorithm available in about [round(0.00166666667 * (jokerready - world.time))] minutes."
/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, last_change)
. = ..()
if(!user)
return
var/datum/browser/popup = new(user, "scannernew", "DNA Modifier Console", 800, 630) // Set up the popup browser window
if(user.client)
var/datum/asset/simple/assets = get_asset_datum(/datum/asset/simple/genetics)
assets.send(user.client)
if(!(in_range(src, user) || hasSiliconAccessInArea(user)))
popup.close()
return
@@ -76,7 +136,7 @@
if(connected && connected.is_operational())
if(connected.occupant) //set occupant_status message
viable_occupant = connected.occupant
if(viable_occupant.has_dna() && !HAS_TRAIT(viable_occupant, TRAIT_RADIMMUNE) && !HAS_TRAIT(viable_occupant, TRAIT_NOCLONE) || (connected.scan_level == 3)) //occupant is viable for dna modification
if(viable_occupant.has_dna() && !HAS_TRAIT_NOT_FROM(viable_occupant, TRAIT_RADIMMUNE,BLOODSUCKER_TRAIT) && !HAS_TRAIT(viable_occupant, TRAIT_NOCLONE) || (connected.scan_level == 3)) //occupant is viable for dna modification
occupant_status += "[viable_occupant.name] => "
switch(viable_occupant.stat)
if(CONSCIOUS)
@@ -88,8 +148,6 @@
occupant_status += "</div></div>"
occupant_status += "<div class='line'><div class='statusLabel'>Health:</div><div class='progressBar'><div style='width: [viable_occupant.health]%;' class='progressFill good'></div></div><div class='statusValue'>[viable_occupant.health] %</div></div>"
occupant_status += "<div class='line'><div class='statusLabel'>Radiation Level:</div><div class='progressBar'><div style='width: [viable_occupant.radiation/(RAD_MOB_SAFE/100)]%;' class='progressFill bad'></div></div><div class='statusValue'>[viable_occupant.radiation/(RAD_MOB_SAFE/100)] %</div></div>"
var/rejuvenators = viable_occupant.reagents.get_reagent_amount(/datum/reagent/medicine/potass_iodide)
occupant_status += "<div class='line'><div class='statusLabel'>Rejuvenators:</div><div class='progressBar'><div style='width: [round((rejuvenators / REJUVENATORS_MAX) * 100)]%;' class='progressFill highlight'></div></div><div class='statusValue'>[rejuvenators] units</div></div>"
occupant_status += "<div class='line'><div class='statusLabel'>Unique Enzymes :</div><div class='statusValue'><span class='highlight'>[viable_occupant.dna.unique_enzymes]</span></div></div>"
occupant_status += "<div class='line'><div class='statusLabel'>Last Operation:</div><div class='statusValue'>[last_change ? last_change : "----"]</div></div>"
else
@@ -147,28 +205,61 @@
buttons += "<a href='?src=[REF(src)];task=togglelock;'>[connected.locked ? "Unlock" : "Lock"] Scanner</a>"
else
buttons += "<span class='linkOff'>Open Scanner</span> <span class='linkOff'>Lock Scanner</span>"
if(viable_occupant)
buttons += "<a href='?src=[REF(src)];task=rejuv'>Inject Rejuvenators</a>"
if(viable_occupant && (scrambleready < world.time))
buttons += "<a href='?src=[REF(src)];task=scramble'>Scramble DNA</a>"
else
buttons += "<span class='linkOff'>Inject Rejuvenators</span>"
buttons += "<span class='linkOff'>Scramble DNA</span>"
if(diskette)
buttons += "<a href='?src=[REF(src)];task=ejectdisk'>Eject Disk</a>"
buttons += "<a href='?src=[REF(src)];task=screen;text=disk;'>Disk</a>"
else
buttons += "<span class='linkOff'>Eject Disk</span>"
if(current_screen == "buffer")
buttons += "<a href='?src=[REF(src)];task=screen;text=mainmenu;'>Radiation Emitter Menu</a>"
buttons += "<span class='linkOff'>Disk</span>"
if(current_screen == "mutations")
buttons += "<span class='linkOff'>Mutations</span>"
else
buttons += "<a href='?src=[REF(src)];task=screen;text=buffer;'>Buffer Menu</a>"
buttons += "<a href='?src=[REF(src)];task=screen;text=mutations;'>Mutations</a>"
if((current_screen == "mainmenu") || !current_screen)
buttons += "<span class='linkOff'>Genetic Sequencer</span>"
else
buttons += "<a href='?src=[REF(src)];task=screen;text=mainmenu;'>Genetic Sequencer</a>"
if(current_screen == "ui")
buttons += "<span class='linkOff'>Unique Identifiers</span>"
else
buttons += "<a href='?src=[REF(src)];task=screen;text=ui;'>Unique Identifiers</a>"
if(current_screen == "advinjector")
buttons += "<span class='linkOff'>Adv. Injectors</span>"
else
buttons += "<a href='?src=[REF(src)];task=screen;text=advinjector;'>Adv. Injectors</a>"
switch(current_screen)
if("working")
temp_html += status
temp_html += "<h1>System Busy</h1>"
temp_html += "Working ... Please wait ([DisplayTimeText(radduration*10)])"
if("buffer")
if("ui")
temp_html += status
temp_html += buttons
temp_html += "<h1>Buffer Menu</h1>"
temp_html += "<h1>Unique Identifiers</h1>"
temp_html += "<a href='?src=[REF(src)];task=setstrength;num=[radstrength-1];'>--</a> <a href='?src=[REF(src)];task=setstrength;'>Output Level</a> <a href='?src=[REF(src)];task=setstrength;num=[radstrength+1];'>++</a>"
temp_html += "<br><a href='?src=[REF(src)];task=setduration;num=[radduration-1];'>--</a> <a href='?src=[REF(src)];task=setduration;'>Pulse Duration</a> <a href='?src=[REF(src)];task=setduration;num=[radduration+1];'>++</a>"
temp_html += "<h3>Irradiate Subject</h3>"
temp_html += "<div class='line'><div class='statusLabel'>Unique Identifier:</div><div class='statusValue'><div class='clearBoth'>"
var/max_line_len = 7*DNA_BLOCK_SIZE
if(viable_occupant)
temp_html += "<div class='dnaBlockNumber'>1</div>"
var/char = ""
var/ui_text = viable_occupant.dna.uni_identity
var/len_byte = length(ui_text)
var/char_it = 0
for(var/byte_it = 1, byte_it <= len_byte, byte_it += length(char))
char_it++
char = ui_text[byte_it]
temp_html += "<a class='dnaBlock' href='?src=[REF(src)];task=pulseui;num=[char_it];'>[char]</a>"
if((char_it % max_line_len) == 0)
temp_html += "</div><div class='clearBoth'>"
if((char_it % DNA_BLOCK_SIZE) == 0 && byte_it < len_byte)
temp_html += "<div class='dnaBlockNumber'>[(char_it / DNA_BLOCK_SIZE) + 1]</div>"
else
temp_html += "---------"
temp_html += "</div></div><br><h1>Buffer Menu</h1>"
if(istype(buffer))
for(var/i=1, i<=buffer.len, i++)
@@ -188,7 +279,6 @@
temp_html += "<span class='linkOff'>Save to Disk</span>"
else
var/ui = buffer_slot["UI"]
var/se = buffer_slot["SE"]
var/ue = buffer_slot["UE"]
var/name = buffer_slot["name"]
var/label = buffer_slot["label"]
@@ -234,19 +324,6 @@
temp_html += "<a href='?src=[REF(src)];task=injector;num=[i];text=mixed'>UI+UE Injector</a>"
else
temp_html += "<span class='linkOff'>UI+UE Injector</span>"
if(se)
temp_html += "<br>\tSE: [se] "
if(viable_occupant)
temp_html += "<a href='?src=[REF(src)];task=transferbuffer;num=[i];text=se'>Occupant</a>"
else
temp_html += "<span class='linkOff'>Occupant</span>"
temp_html += "<a href='?src=[REF(src)];task=setdelayed;num=[i];delayaction=[SCANNER_ACTION_SE]'>Occupant:Delayed</a>"
if(injectorready < world.time )
temp_html += "<a href='?src=[REF(src)];task=injector;num=[i];text=se'>Injector</a>"
else
temp_html += "<span class='linkOff'>Injector</span>"
else
temp_html += "<br>\tSE: No Data"
if(viable_occupant)
temp_html += "<br><a href='?src=[REF(src)];task=setbuffer;num=[i];'>Save to Buffer</a>"
else
@@ -260,58 +337,225 @@
temp_html += "<a href='?src=[REF(src)];task=savedisk;num=[i];'>Save to Disk</a>"
else
temp_html += "<span class='linkOff'>Save to Disk</span>"
if("disk")
temp_html += status
temp_html += buttons
if(diskette)
temp_html += "<h3>[diskette.name]</h3><br>"
temp_html += "<a href='?src=[REF(src)];task=ejectdisk'>Eject Disk</a><br>"
if(LAZYLEN(diskette.mutations))
temp_html += "<table>"
for(var/datum/mutation/human/A in diskette.mutations)
temp_html += "<tr><td><span class='linkOff'>[A.name]</span></td>"
temp_html += "<td><a href='?src=[REF(src)];task=deletediskmut;num=[diskette.mutations.Find(A)];'>Delete</a></td>"
if(LAZYLEN(stored_mutations) < max_storage)
temp_html += "<td><a href='?src=[REF(src)];task=importdiskmut;num=[diskette.mutations.Find(A)];'>Import</a></td>"
else
temp_html += "<td><td><span class='linkOff'>Import</span></td>"
temp_html += "</tr>"
temp_html += "</table>"
else
temp_html += "<br>Load diskette to start ----------"
if("info")
if(LAZYLEN(stored_mutations))
if(LAZYLEN(stored_mutations) >= current_storage)
var/datum/mutation/human/HM = stored_mutations[current_storage]
if(HM)
temp_html += display_sequence(HM.type, current_storage)
else
current_screen = "mainmenu"
if("mutations")
temp_html += status
temp_html += buttons
temp_html += "<h3>Mutation Storage:<br></h3>"
temp_html += "<table>"
for(var/datum/mutation/human/HM in stored_mutations)
var/i = stored_mutations.Find(HM)
temp_html += "<tr><td><a href='?src=[REF(src)];task=inspectstorage;num=[i]'>[HM.name]</a></td>"
temp_html += "<td><a href='?src=[REF(src)];task=exportdiskmut;path=[HM.type]'>Export</a></td>"
temp_html += "<td><a href='?src=[REF(src)];task=deletemut;num=[i]'>Delete</a></td>"
if(combine == HM.type)
temp_html += "<td><span class='linkOff'>Combine</span></td></tr>"
else
temp_html += "<td><a href='?src=[REF(src)];task=combine;num=[i]'>Combine</a></td></tr>"
temp_html += "</table><br>"
temp_html += "<h3>Chromosome Storage:<br></h3>"
temp_html += "<table>"
for(var/i in 1 to stored_chromosomes.len)
var/obj/item/chromosome/CM = stored_chromosomes[i]
temp_html += "<td><a href='?src=[REF(src)];task=ejectchromosome;num=[i]'>[CM.name]</a></td><br>"
temp_html += "</table>"
if("advinjector")
temp_html += status
temp_html += buttons
temp_html += "<div class='line'><div class='statusLabel'><b>Advanced Injectors:</b></div></div><br>"
temp_html += "<div class='statusLine'><a href='?src=[REF(src)];task=add_advinjector;'>New Selection</a></div>"
for(var/A in injector_selection)
temp_html += "<div class='statusDisplay'><b>[A]</b>"
var/list/true_selection = injector_selection[A]
temp_html += "<br>"
for(var/B in true_selection)
var/datum/mutation/human/HM = B
var/mutcolor
switch(HM.quality)
if(POSITIVE)
mutcolor = "good"
if(MINOR_NEGATIVE)
mutcolor = "average"
if(NEGATIVE)
mutcolor = "bad"
temp_html += "<div class='statusLine'><span class='[mutcolor]'>[HM.name] </span>"
temp_html += "<a href='?src=[REF(src)];task=remove_from_advinjector;injector=[A];path=[HM.type];'>Remove</a></div>"
if (injectorready < world.time)
temp_html += "<div class='statusLine'> <a href='?src=[REF(src)];task=advinjector;injector=[A];'>Print Advanced Injector</a>"
else
temp_html += "<div class='statusLine'> <span class='linkOff'>Print Advanced Injector</span>"
temp_html += "<a href='?src=[REF(src)];task=remove_advinjector;injector=[A];'>Remove Injector</a></div>"
temp_html += "<br></div>"
else
temp_html += status
temp_html += buttons
temp_html += "<h1>Radiation Emitter Menu</h1>"
temp_html += "<a href='?src=[REF(src)];task=setstrength;num=[radstrength-1];'>--</a> <a href='?src=[REF(src)];task=setstrength;'>Output Level</a> <a href='?src=[REF(src)];task=setstrength;num=[radstrength+1];'>++</a>"
temp_html += "<br><a href='?src=[REF(src)];task=setduration;num=[radduration-1];'>--</a> <a href='?src=[REF(src)];task=setduration;'>Pulse Duration</a> <a href='?src=[REF(src)];task=setduration;num=[radduration+1];'>++</a>"
temp_html += "<h3>Irradiate Subject</h3>"
temp_html += "<div class='line'><div class='statusLabel'>Unique Identifier:</div><div class='statusValue'><div class='clearBoth'>"
var/max_line_len = 7*DNA_BLOCK_SIZE
temp_html += "<div class='line'><div class='statusLabel'>Genetic Sequence:</div><br>"
if(viable_occupant)
temp_html += "<div class='dnaBlockNumber'>1</div>"
var/char = ""
var/ui_text = viable_occupant.dna.uni_identity
var/len_byte = length(ui_text)
var/char_it = 0
for(var/byte_it = 1, byte_it <= len_byte, byte_it += length(char))
char_it++
char = ui_text[byte_it]
temp_html += "<a class='dnaBlock' href='?src=[REF(src)];task=pulseui;num=[char_it];'>[char]</a>"
if((char_it % max_line_len) == 0)
temp_html += "</div><div class='clearBoth'>"
if((char_it % DNA_BLOCK_SIZE) == 0 && byte_it < len_byte)
temp_html += "<div class='dnaBlockNumber'>[(char_it / DNA_BLOCK_SIZE) + 1]</div>"
if(viable_occupant)
for(var/A in get_mutation_list())
temp_html += display_inactive_sequence(A)
temp_html += "<br>"
else
temp_html += "----"
if(viable_occupant && (current_mutation in get_mutation_list(viable_occupant)))
temp_html += display_sequence(current_mutation)
temp_html += "</div><br>"
else
temp_html += "----"
temp_html += "</div></div></div><br>"
temp_html += "<br><div class='line'><div class='statusLabel'>Structural Enzymes:</div><div class='statusValue'><div class='clearBoth'>"
if(viable_occupant)
temp_html += "<div class='dnaBlockNumber'>1</div>"
var/char = ""
var/se_text = viable_occupant.dna.struc_enzymes
var/len_byte = length(se_text)
var/char_it = 0
for(var/byte_it = 1, byte_it <= len_byte, byte_it += length(char))
char_it++
char = se_text[byte_it]
temp_html += "<a class='dnaBlock' href='?src=[REF(src)];task=pulsese;num=[char_it];'>[char]</a>"
if((char_it % max_line_len) == 0)
temp_html += "</div><div class='clearBoth'>"
if((char_it % DNA_BLOCK_SIZE) == 0 && byte_it < len_byte)
temp_html += "<div class='dnaBlockNumber'>[(char_it / DNA_BLOCK_SIZE) + 1]</div>"
else
temp_html += "----"
temp_html += "</div></div></div>"
temp_html += "----------"
popup.set_content(temp_html.Join())
popup.open()
/obj/machinery/computer/scan_consolenew/proc/display_inactive_sequence(mutation)
var/temp_html = ""
var/class = "unselected"
var/mob/living/carbon/viable_occupant = get_viable_occupant()
if(!viable_occupant)
return
var/location = viable_occupant.dna.mutation_index.Find(mutation) //We do this because we dont want people using sysexp or similair tools to just read the mutations.
if(!location) //Do this only when needed, dont make a list with mutations for every iteration if you dont need to
var/list/mutations = get_mutation_list(TRUE)
if(mutation in mutations)
location = mutations.Find(mutation)
if(mutation == current_mutation)
class = "selected"
if(location > DNA_MUTATION_BLOCKS)
temp_html += "<a class='clean' href='?src=[REF(src)];task=inspect;num=[location];'><img class='[class]' src='dna_extra.gif' width = '65' alt='Extra Mutation'></a>"
else if(mutation in stored_research.discovered_mutations)
temp_html += "<a class='clean' href='?src=[REF(src)];task=inspect;num=[location];'><img class='[class]' src='dna_discovered.gif' width = '65' alt='Discovered Mutation'></a>"
else
temp_html += "<a class='clean' clean href='?src=[REF(src)];task=inspect;num=[location];'><img class='[class]' src='dna_undiscovered.gif' width = '65' alt=Undiscovered Mutation'></a>"
return temp_html
/obj/machinery/computer/scan_consolenew/proc/display_sequence(mutation, storage_slot) //Storage slot is for when viewing from the stored mutations
var/temp_html = ""
if(!mutation)
temp_html += "ERR-"
return
var/mut_name = "Unknown gene"
var/mut_desc = "No information available."
var/alias
var/discovered = FALSE
var/active = FALSE
var/scrambled = FALSE
var/instability
var/mob/living/carbon/viable_occupant = get_viable_occupant()
var/datum/mutation/human/HM = get_valid_mutation(mutation)
if(viable_occupant)
var/datum/mutation/human/M = viable_occupant.dna.get_mutation(mutation)
if(M)
scrambled = M.scrambled
active = TRUE
var/datum/mutation/human/A = GET_INITIALIZED_MUTATION(mutation)
alias = A.alias
if(active && !scrambled)
discover(mutation)
if(stored_research && (mutation in stored_research.discovered_mutations))
mut_name = A.name
mut_desc = A.desc
discovered = TRUE
instability = A.instability
var/extra
if(viable_occupant && !(storage_slot || viable_occupant.dna.mutation_in_sequence(mutation)))
extra = TRUE
if(discovered && !scrambled)
var/mutcolor
switch(A.quality)
if(POSITIVE)
mutcolor = "good"
if(MINOR_NEGATIVE)
mutcolor = "average"
if(NEGATIVE)
mutcolor = "bad"
if(HM)
instability *= GET_MUTATION_STABILIZER(HM)
temp_html += "<div class='statusDisplay'><div class='statusLine'><span class='[mutcolor]'><b>[mut_name]</b></span><small> ([alias])</small><br>"
temp_html += "<div class='statusLine'>Instability : [round(instability)]</span><br>"
else
temp_html += "<div class='statusDisplay'><div class='statusLine'><b>[alias]</b><br>"
temp_html += "<div class='statusLine'>[mut_desc]<br></div>"
if(active && !storage_slot)
if(HM?.can_chromosome && (HM in viable_occupant.dna.mutations))
var/i = viable_occupant.dna.mutations.Find(HM)
var/chromosome_name = "<a href='?src=[REF(src)];task=applychromosome;path=[mutation];num=[i];'>----</a>"
if(HM.chromosome_name)
chromosome_name = HM.chromosome_name
temp_html += "<div class='statusLine'>Chromosome status: [chromosome_name]<br></div>"
temp_html += "<div class='statusLine'>Sequence:<br><br></div>"
if(!scrambled)
for(var/block in 1 to A.blocks)
var/whole_sequence = get_valid_gene_string(mutation)
var/sequence = copytext(whole_sequence, 1+(block-1)*(DNA_SEQUENCE_LENGTH*2),(DNA_SEQUENCE_LENGTH*2*block+1))
temp_html += "<div class='statusLine'><table class='statusDisplay'><tr>"
for(var/i in 1 to DNA_SEQUENCE_LENGTH)
var/num = 1+(i-1)*2
var/genenum = num+(DNA_SEQUENCE_LENGTH*2*(block-1))
temp_html += "<td><div class='statusLine'><span class='dnaBlockNumber'><a href='?src=[REF(src)];task=pulsegene;num=[genenum];path=[mutation];'>[sequence[num]]</span></a></div></td>"
temp_html += "</tr><tr>"
for(var/i in 1 to DNA_SEQUENCE_LENGTH)
temp_html += "<td><div class='statusLine'>|</div></td>"
temp_html += "</tr><tr>"
for(var/i in 1 to DNA_SEQUENCE_LENGTH)
var/num = i*2
var/genenum = num+(DNA_SEQUENCE_LENGTH*2*(block-1))
temp_html += "<td><div class='statusLine'><span class='dnaBlockNumber'><a href='?src=[REF(src)];task=pulsegene;num=[genenum];path=[mutation];'>[sequence[num]]</span></a></div></td>"
temp_html += "</tr></table></div>"
temp_html += "<br><br><br><br><br>"
else
temp_html = "<div class='statusLine'>Sequence unreadable due to unpredictable mutation.</div>"
if((active || storage_slot) && (injectorready < world.time) && !scrambled)
temp_html += "<a href='?src=[REF(src)];task=activator;path=[mutation];slot=[storage_slot];'>Print Activator</a>"
temp_html += "<a href='?src=[REF(src)];task=mutator;path=[mutation];slot;=[storage_slot];'>Print Mutator</a>"
else
temp_html += "<span class='linkOff'>Print Activator</span>"
temp_html += "<span class='linkOff'>Print Mutator</span>"
temp_html += "<br><div class='statusLine'>"
if(storage_slot)
temp_html += "<a href='?src=[REF(src)];task=deletemut;num=[storage_slot];'>Delete</a>"
if((LAZYLEN(stored_mutations) < max_storage) && diskette && !diskette.read_only)
temp_html += "<a href='?src=[REF(src)];task=exportdiskmut;path=[mutation];'>Export</a>"
else
temp_html += "<span class='linkOff'>Export</span>"
temp_html += "<a href='?src=[REF(src)];task=screen;text=mutations;'>Back</a>"
else if(active && !scrambled)
temp_html += "<a href='?src=[REF(src)];task=savemut;path=[mutation];'>Store</a>"
temp_html += "<a href='?src=[REF(src)];task=expand_advinjector;path=[mutation];'>Adv. Injector</a>"
if(extra || scrambled)
temp_html += "<a href='?src=[REF(src)];task=nullify;'>Nullify</a>"
else
temp_html += "<span class='linkOff'>Nullify</span>"
temp_html += "</div></div>"
return temp_html
/obj/machinery/computer/scan_consolenew/Topic(href, href_list)
if(..())
@@ -350,13 +594,15 @@
radstrength = WRAP(num, 1, RADIATION_STRENGTH_MAX+1)
if("screen")
current_screen = href_list["text"]
if("rejuv")
if(viable_occupant && viable_occupant.reagents)
var/potassiodide_amount = viable_occupant.reagents.get_reagent_amount(/datum/reagent/medicine/potass_iodide)
var/can_add = max(min(REJUVENATORS_MAX - potassiodide_amount, REJUVENATORS_INJECT), 0)
viable_occupant.reagents.add_reagent(/datum/reagent/medicine/potass_iodide, can_add)
if("scramble")
if(viable_occupant && (scrambleready < world.time))
viable_occupant.dna.remove_all_mutations(list(MUT_NORMAL, MUT_EXTRA))
viable_occupant.dna.generate_dna_blocks()
scrambleready = world.time + SCRAMBLE_TIMEOUT
to_chat(usr,"<span class'notice'>DNA scrambled.</span>")
viable_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER*50/(connected.damage_coeff ** 2)
if("setbufferlabel")
var/text = sanitize(input(usr, "Input a new label:", "Input an Text", null) as text|null)
var/text = sanitize(input(usr, "Input a new label:", "Input a Text", null) as text|null)
if(num && text)
num = CLAMP(num, 1, NUMBER_OF_BUFFERS)
var/list/buffer_slot = buffer[num]
@@ -368,7 +614,6 @@
buffer[num] = list(
"label"="Buffer[num]:[viable_occupant.real_name]",
"UI"=viable_occupant.dna.uni_identity,
"SE"=viable_occupant.dna.struc_enzymes,
"UE"=viable_occupant.dna.unique_enzymes,
"name"=viable_occupant.real_name,
"blood_type"=viable_occupant.dna.blood_type
@@ -382,8 +627,6 @@
if("transferbuffer")
if(num && viable_occupant)
switch(href_list["text"]) //Numbers are this high because other way upgrading laser is just not worth the hassle, and i cant think of anything better to inmrove
if("se")
apply_buffer(SCANNER_ACTION_SE,num)
if("ui")
apply_buffer(SCANNER_ACTION_UI,num)
if("ue")
@@ -397,28 +640,6 @@
if(istype(buffer_slot))
var/obj/item/dnainjector/timed/I
switch(href_list["text"])
if("se")
if(buffer_slot["SE"])
I = new /obj/item/dnainjector/timed(loc)
var/powers = 0
for(var/datum/mutation/human/HM in GLOB.good_mutations + GLOB.bad_mutations + GLOB.not_good_mutations)
if(HM.check_block_string(buffer_slot["SE"]))
I.add_mutations.Add(HM)
if(HM in GLOB.good_mutations)
powers += 1
if(HM in GLOB.bad_mutations + GLOB.not_good_mutations)
powers -= 1 //To prevent just unlocking everything to get all powers to a syringe for max tech
else
I.remove_mutations.Add(HM)
var/time_coeff
for(var/datum/mutation/human/HM in I.add_mutations)
if(!time_coeff)
time_coeff = HM.time_coeff
continue
time_coeff = min(time_coeff,HM.time_coeff)
if(connected)
I.duration = I.duration * time_coeff * connected.damage_coeff
I.damage_coeff = connected.damage_coeff
if("ui")
if(buffer_slot["UI"])
I = new /obj/item/dnainjector/timed(loc)
@@ -457,7 +678,7 @@
if("setdelayed")
if(num)
delayed_action = list("action"=text2num(href_list["delayaction"]),"buffer"=num)
if("pulseui","pulsese")
if("pulseui")
if(num && viable_occupant && connected)
radduration = WRAP(radduration, 1, RADIATION_DURATION_MAX+1)
radstrength = WRAP(radstrength, 1, RADIATION_STRENGTH_MAX+1)
@@ -469,7 +690,7 @@
ui_interact(usr)
sleep(radduration*10)
current_screen = "mainmenu"
current_screen = "ui"
if(viable_occupant && connected && connected.occupant==viable_occupant)
viable_occupant.radiation += (RADIATION_IRRADIATION_MULTIPLIER*radduration*radstrength)/(connected.damage_coeff ** 2) //Read comment in "transferbuffer" section above for explanation
@@ -478,7 +699,7 @@
var/len = length_char(viable_occupant.dna.uni_identity)
num = WRAP(num, 1, len+1)
num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len) //Each manipulator level above 1 makes randomization as accurate as selected time + manipulator lvl^2
//Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low
//Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low
var/block = round((num-1)/DNA_BLOCK_SIZE)+1
var/subblock = num - block*DNA_BLOCK_SIZE
last_change = "UI #[block]-[subblock]; "
@@ -490,35 +711,229 @@
viable_occupant.dna.uni_identity = copytext_char(viable_occupant.dna.uni_identity, 1, num) + hex + copytext_char(viable_occupant.dna.uni_identity, num + 1)
viable_occupant.updateappearance(mutations_overlay_update=1)
if("pulsese")
var/len = length(viable_occupant.dna.struc_enzymes)
num = WRAP(num, 1, len+1)
num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len)
var/block = round((num-1)/DNA_BLOCK_SIZE)+1
var/subblock = num - block*DNA_BLOCK_SIZE
last_change = "SE #[block]-[subblock]; "
var/hex = copytext_char(viable_occupant.dna.struc_enzymes, num, num+1)
last_change += "[hex]"
hex = scramble(hex, radstrength, radduration)
last_change += "->[hex]"
viable_occupant.dna.struc_enzymes = copytext_char(viable_occupant.dna.struc_enzymes, 1, num) + hex + copytext_char(viable_occupant.dna.struc_enzymes, num + 1)
viable_occupant.domutcheck()
else
current_screen = "mainmenu"
if(connected)
connected.locked = locked_state
if("inspect")
if(viable_occupant)
var/list/mutations = get_mutation_list(TRUE)
if(current_mutation == mutations[num])
current_mutation = null
else
current_mutation = mutations[num]
if("inspectstorage")
current_storage = num
current_screen = "info"
if("savemut")
if(viable_occupant)
var/succes
if(LAZYLEN(stored_mutations) < max_storage)
var/mutation = text2path(href_list["path"])
if(ispath(mutation, /datum/mutation/human)) //sanity checks
var/datum/mutation/human/HM = viable_occupant.dna.get_mutation(mutation)
if(HM)
var/datum/mutation/human/A = new HM.type()
A.copy_mutation(HM)
succes = TRUE
stored_mutations += A
to_chat(usr,"<span class='notice'>Mutation succesfully stored.</span>")
if(!succes) //we can exactly return here
to_chat(usr,"<span class='warning'>Mutation storage is full.</span>")
if("deletemut")
var/datum/mutation/human/HM = stored_mutations[num]
if(HM)
stored_mutations.Remove(HM)
qdel(HM)
current_screen = "mutations"
if("activator")
if(injectorready < world.time)
var/mutation = text2path(href_list["path"])
if(ispath(mutation, /datum/mutation/human))
var/datum/mutation/human/HM = get_valid_mutation(mutation)
if(HM)
var/obj/item/dnainjector/activator/I = new /obj/item/dnainjector/activator(loc)
I.add_mutations += new HM.type (copymut = HM)
I.name = "[HM.name] activator"
I.research = TRUE
if(connected)
I.damage_coeff = connected.damage_coeff*4
injectorready = world.time + INJECTOR_TIMEOUT * (1 - 0.1 * connected.precision_coeff) //precision_coeff being the matter bin rating
else
injectorready = world.time + INJECTOR_TIMEOUT
if("mutator")
if(injectorready < world.time)
var/mutation = text2path(href_list["path"])
if(ispath(mutation, /datum/mutation/human))
var/datum/mutation/human/HM = get_valid_mutation(mutation)
if(HM)
var/obj/item/dnainjector/activator/I = new /obj/item/dnainjector/activator(loc)
I.add_mutations += new HM.type (copymut = HM)
I.doitanyway = TRUE
I.name = "[HM.name] injector"
if(connected)
I.damage_coeff = connected.damage_coeff
injectorready = world.time + INJECTOR_TIMEOUT * 5 * (1 - 0.1 * connected.precision_coeff)
else
injectorready = world.time + INJECTOR_TIMEOUT * 5
if("advinjector")
var/selection = href_list["injector"]
if(injectorready < world.time)
if(injector_selection.Find(selection))
var/list/true_selection = injector_selection[selection]
if(LAZYLEN(injector_selection))
var/obj/item/dnainjector/activator/I = new /obj/item/dnainjector/activator(loc)
for(var/A in true_selection)
var/datum/mutation/human/HM = A
I.add_mutations += new HM.type (copymut = HM)
I.doitanyway = TRUE
I.name = "Advanced [selection] injector"
if(connected)
I.damage_coeff = connected.damage_coeff
injectorready = world.time + INJECTOR_TIMEOUT * 8 * (1 - 0.1 * connected.precision_coeff)
else
injectorready = world.time + INJECTOR_TIMEOUT * 8
if("nullify")
if(viable_occupant)
var/datum/mutation/human/A = viable_occupant.dna.get_mutation(current_mutation)
if(A && (!viable_occupant.dna.mutation_in_sequence(current_mutation) || A.scrambled))
viable_occupant.dna.remove_mutation(current_mutation)
current_screen = "mainmenu"
current_mutation = null
if("pulsegene")
if(current_screen != "info")
var/path = text2path(href_list["path"])
if(viable_occupant && num && (path in viable_occupant.dna.mutation_index))
var/list/genes = list("A","T","G","C","X")
if(jokerready < world.time)
genes += "JOKER"
var/sequence = GET_GENE_STRING(path, viable_occupant.dna)
var/original = sequence[num]
var/new_gene = input("From [original] to-", "New block", original) as null|anything in genes
if(!new_gene)
new_gene = original
if(viable_occupant == get_viable_occupant()) //No cheesing
if((new_gene == "JOKER") && (jokerready < world.time))
var/true_genes = GET_SEQUENCE(current_mutation)
new_gene = true_genes[num]
jokerready = world.time + JOKER_TIMEOUT - (JOKER_UPGRADE * (connected.precision_coeff-1))
sequence = copytext(sequence, 1, num) + new_gene + copytext(sequence, num+1, length(sequence)+1)
viable_occupant.dna.mutation_index[path] = sequence
viable_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER/connected.damage_coeff
viable_occupant.domutcheck()
if("exportdiskmut")
if(diskette && !diskette.read_only)
var/path = text2path(href_list["path"])
if(ispath(path, /datum/mutation/human))
var/datum/mutation/human/A = get_valid_mutation(path)
if(A && diskette && (LAZYLEN(diskette.mutations) < diskette.max_mutations))
var/datum/mutation/human/HM = new A.type()
diskette.mutations += HM
HM.copy_mutation(A)
to_chat(usr, "<span class='notice'>Succesfully written [A.name] to [diskette.name].</span>")
if("deletediskmut")
if(diskette && !diskette.read_only)
if(num && (LAZYLEN(diskette.mutations) >= num))
var/datum/mutation/human/A = diskette.mutations[num]
diskette.mutations.Remove(A)
qdel(A)
if("importdiskmut")
if(diskette && (LAZYLEN(diskette.mutations) >= num))
if(LAZYLEN(stored_mutations) < max_storage)
var/datum/mutation/human/A = diskette.mutations[num]
var/datum/mutation/human/HM = new A.type()
HM.copy_mutation(A)
stored_mutations += HM
to_chat(usr,"<span class='notice'>Succesfully written [A.name] to storage.")
if("combine")
if(num && (LAZYLEN(stored_mutations) >= num))
if(LAZYLEN(stored_mutations) < max_storage)
var/datum/mutation/human/A = stored_mutations[num]
var/path = A.type
if(combine)
var/result_path = get_mixed_mutation(combine, path)
if(result_path)
stored_mutations += new result_path()
to_chat(usr, "<span class='boldnotice'>Succes! New mutation has been added to storage</span>")
discover(result_path)
combine = null
else
to_chat(usr, "<span class='warning'>Failed. No mutation could be created.</span>")
combine = null
else
combine = path
to_chat(usr,"<span class='notice'>Selected [A.name] for combining</span>")
else
to_chat(usr, "<span class='warning'>Not enough space to store potential mutation.</span>")
if("ejectchromosome")
if(LAZYLEN(stored_chromosomes) <= num)
var/obj/item/chromosome/CM = stored_chromosomes[num]
CM.forceMove(drop_location())
adjust_item_drop_location(CM)
stored_chromosomes -= CM
if("applychromosome")
if(viable_occupant && (LAZYLEN(viable_occupant.dna.mutations) <= num))
var/datum/mutation/human/HM = viable_occupant.dna.mutations[num]
var/list/chromosomes = list()
for(var/obj/item/chromosome/CM in stored_chromosomes)
if(CM.can_apply(HM))
chromosomes += CM
if(chromosomes.len)
var/obj/item/chromosome/CM = input("Select a chromosome to apply", "Apply Chromosome") as null|anything in sortNames(chromosomes)
if(CM)
to_chat(usr, "<span class='notice'>You apply [CM] to [HM.name].</span>")
stored_chromosomes -= CM
CM.apply(HM)
if("expand_advinjector")
var/mutation = text2path(href_list["path"])
var/datum/mutation/human/HM = get_valid_mutation(mutation)
if(HM && LAZYLEN(injector_selection))
var/which_injector = input(usr, "Select Adv. Injector", "Advanced Injectors") as null|anything in injector_selection
if(injector_selection.Find(which_injector))
var/list/true_selection = injector_selection[which_injector]
var/total_instability
for(var/B in true_selection)
var/datum/mutation/human/mootacion = B
total_instability += mootacion.instability
total_instability += HM.instability
if((total_instability > max_injector_instability) || (true_selection.len + 1) > max_injector_mutations)
to_chat(usr, "<span class='warning'>Adding more mutations would make the advanced injector too unstable!</span>")
else
true_selection += HM //reminder that this works. because I keep forgetting this works
if("remove_from_advinjector")
var/mutation = text2path(href_list["path"])
var/selection = href_list["injector"]
if(injector_selection.Find(selection))
var/list/true_selection = injector_selection[selection]
for(var/B in true_selection)
var/datum/mutation/human/HM = B
if(HM.type == mutation)
true_selection -= HM
break
if("remove_advinjector")
var/selection = href_list["injector"]
for(selection in injector_selection)
if(selection == selection)
injector_selection.Remove(selection)
if("add_advinjector")
if(LAZYLEN(injector_selection) < max_injector_selections)
var/new_selection = input(usr, "Enter Adv. Injector name", "Advanced Injectors") as text|null
if(new_selection && !(new_selection in injector_selection))
injector_selection[new_selection] = list()
ui_interact(usr,last_change)
/obj/machinery/computer/scan_consolenew/proc/scramble(input,rs,rd)
/obj/machinery/computer/scan_consolenew/proc/scramble(input,rs,rd) //hexadecimal genetics. dont confuse with scramble button
var/length = length(input)
var/ran = gaussian(0, rs*RADIATION_STRENGTH_MULTIPLIER)
if(ran == 0)
ran = pick(-1,1) //hacky, statistically should almost never happen. 0-change makes people mad though
ran = pick(-1,1) //hacky, statistically should almost never happen. 0-chance makes people mad though
else if(ran < 0)
ran = round(ran) //negative, so floor it
else
@@ -533,7 +948,7 @@
var/mob/living/carbon/viable_occupant = null
if(connected)
viable_occupant = connected.occupant
if(!istype(viable_occupant) || !viable_occupant.dna || HAS_TRAIT(viable_occupant, TRAIT_RADIMMUNE) || HAS_TRAIT(viable_occupant, TRAIT_NOCLONE))
if(!istype(viable_occupant) || !viable_occupant.dna || HAS_TRAIT_NOT_FROM(viable_occupant, TRAIT_RADIMMUNE,BLOODSUCKER_TRAIT) || HAS_TRAIT(viable_occupant, TRAIT_NOCLONE))
viable_occupant = null
return viable_occupant
@@ -547,10 +962,6 @@
//Each laser level reduces damage by lvl^2, so no effect on 1 lvl, 4 times less damage on 2 and 9 times less damage on 3
//Numbers are this high because other way upgrading laser is just not worth the hassle, and i cant think of anything better to inmrove
switch(action)
if(SCANNER_ACTION_SE)
if(buffer_slot["SE"])
viable_occupant.dna.struc_enzymes = buffer_slot["SE"]
viable_occupant.domutcheck()
if(SCANNER_ACTION_UI)
if(buffer_slot["UI"])
viable_occupant.dna.uni_identity = buffer_slot["UI"]
@@ -572,15 +983,54 @@
viable_occupant.dna.blood_type = buffer_slot["blood_type"]
/obj/machinery/computer/scan_consolenew/proc/on_scanner_close()
if(delayed_action && connected)
if(delayed_action && get_viable_occupant())
to_chat(connected.occupant, "<span class='notice'>[src] activates!</span>")
apply_buffer(delayed_action["action"],delayed_action["buffer"])
delayed_action = null //or make it stick + reset button ?
/obj/machinery/computer/scan_consolenew/proc/get_valid_mutation(mutation)
var/mob/living/carbon/C = get_viable_occupant()
if(C)
var/datum/mutation/human/HM = C.dna.get_mutation(mutation)
if(HM)
return HM
for(var/datum/mutation/human/A in stored_mutations)
if(A.type == mutation)
return A
/obj/machinery/computer/scan_consolenew/proc/get_mutation_list(include_storage) //Returns a list of the mutation index types and any extra mutations
var/mob/living/carbon/viable_occupant = get_viable_occupant()
var/list/paths = list()
if(viable_occupant)
for(var/A in viable_occupant.dna.mutation_index)
paths += A
for(var/datum/mutation/human/A in viable_occupant.dna.mutations)
if(A.class == MUT_EXTRA)
paths += A.type
if(include_storage)
for(var/datum/mutation/human/A in stored_mutations)
paths += A.type
return paths
/obj/machinery/computer/scan_consolenew/proc/get_valid_gene_string(mutation)
var/mob/living/carbon/C = get_viable_occupant()
if(C && (mutation in C.dna.mutation_index))
return GET_GENE_STRING(mutation, C.dna)
else if(C && (LAZYLEN(C.dna.mutations)))
for(var/datum/mutation/human/A in C.dna.mutations)
if(A.type == mutation)
return GET_SEQUENCE(mutation)
for(var/datum/mutation/human/A in stored_mutations)
if(A.type == mutation)
return GET_SEQUENCE(mutation)
/obj/machinery/computer/scan_consolenew/proc/discover(mutation)
if(stored_research && !(mutation in stored_research.discovered_mutations))
stored_research.discovered_mutations += mutation
return TRUE
/////////////////////////// DNA MACHINES
#undef INJECTOR_TIMEOUT
#undef REJUVENATORS_INJECT
#undef REJUVENATORS_MAX
#undef NUMBER_OF_BUFFERS
#undef RADIATION_STRENGTH_MAX
+2 -2
View File
@@ -145,7 +145,7 @@
if(5)
dat += "<CENTER><B>Virus Database</B></CENTER>"
for(var/Dt in typesof(/datum/disease/))
var/datum/disease/Dis = new Dt(0)
var/datum/disease/Dis = new Dt(FALSE)
if(istype(Dis, /datum/disease/advance))
continue // TODO (tm): Add advance diseases to the virus database which no one uses.
if(!Dis.desc)
@@ -248,7 +248,7 @@
else if(href_list["vir"])
var/type = href_list["vir"]
var/datum/disease/Dis = new type(0)
var/datum/disease/Dis = new type(FALSE)
var/AfS = ""
for(var/mob/M in Dis.viable_mobtypes)
AfS += " [initial(M.name)];"
+9 -10
View File
@@ -37,12 +37,11 @@
dat += "[R.name] |"
if(R.stat)
dat += " Not Responding |"
else if (!R.canmove)
else if(R.locked_down)
dat += " Locked Down |"
else
dat += " Operating Normally |"
if (!R.canmove)
else if(R.cell)
if(R.cell)
dat += " Battery Installed ([R.cell.charge]/[R.cell.maxcharge]) |"
else
dat += " No Cell Installed |"
@@ -62,7 +61,7 @@
dat += "<A href='?src=[REF(src)];magbot=[REF(R)]'>(<font color=blue><i>Hack</i></font>)</A> "
else if(IsAdminGhost(user) && !R.emagged)
dat += "<A href='?src=[REF(src)];magbot=[REF(R)]'>(<font color=blue><i>Hack</i></font>)</A> "
dat += "<A href='?src=[REF(src)];stopbot=[REF(R)]'>(<font color=green><i>[R.canmove ? "Lockdown" : "Release"]</i></font>)</A> "
dat += "<A href='?src=[REF(src)];stopbot=[REF(R)]'>(<font color=green><i>[R.locked_down? "Lockdown" : "Release"]</i></font>)</A> "
dat += "<A href='?src=[REF(src)];killbot=[REF(R)]'>(<font color=red><i>Destroy</i></font>)</A>"
dat += "<BR>"
@@ -116,14 +115,14 @@
if(src.allowed(usr))
var/mob/living/silicon/robot/R = locate(href_list["stopbot"]) in GLOB.silicon_mobs
if(can_control(usr, R))
var/choice = input("Are you certain you wish to [R.canmove ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
var/choice = input("Are you certain you wish to [!R.locked_down ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
if(choice == "Confirm" && can_control(usr, R) && !..())
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [R.canmove ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [key_name(R)]!")
R.SetLockdown(!R.lockcharge)
to_chat(R, "[!R.lockcharge ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [!R.locked_down ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
log_game("[key_name(usr)] [!R.locked_down ? "locked down" : "released"] [key_name(R)]!")
R.SetLockdown(!R.locked_down)
to_chat(R, "[!R.locked_down ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
if(R.connected_ai)
to_chat(R.connected_ai, "[!R.lockcharge ? "<span class='notice'>NOTICE - Cyborg lockdown lifted" : "<span class='alert'>ALERT - Cyborg lockdown detected"]: <a href='?src=[REF(R.connected_ai)];track=[html_encode(R.name)]'>[R.name]</a></span><br>")
to_chat(R.connected_ai, "[!R.locked_down ? "<span class='notice'>NOTICE - Cyborg lockdown lifted" : "<span class='alert'>ALERT - Cyborg lockdown detected"]: <a href='?src=[REF(R.connected_ai)];track=[html_encode(R.name)]'>[R.name]</a></span><br>")
else
to_chat(usr, "<span class='danger'>Access Denied.</span>")
+8 -10
View File
@@ -75,25 +75,23 @@
L -= I
return !cleared
/obj/machinery/computer/station_alert/update_icon()
..()
cut_overlays()
/obj/machinery/computer/station_alert/update_overlays()
. = ..()
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
var/overlay_state = icon_screen
if(stat & (NOPOWER|BROKEN))
add_overlay("[icon_keyboard]_off")
. |= "[icon_keyboard]_off"
return
add_overlay(icon_keyboard)
. |= icon_keyboard
var/active_alarms = FALSE
for(var/cat in alarms)
var/list/L = alarms[cat]
if(L.len)
if(length(alarms[cat]))
active_alarms = TRUE
break
if(active_alarms)
overlay_state = "alert:2"
add_overlay("alert:2")
else
overlay_state = "alert:0"
add_overlay("alert:0")
. |= overlay_state
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
@@ -44,8 +44,8 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
else
to_chat(user, "<span class='notice'>[I] doesn't appear to be an uplink...</span>")
/obj/machinery/computer/telecrystals/uplinker/update_icon()
..()
/obj/machinery/computer/telecrystals/uplinker/update_overlays()
. = ..()
if(uplinkholder)
add_overlay("[initial(icon_state)]-closed")
+21 -13
View File
@@ -287,6 +287,7 @@
#define CRYO_PRESERVE 1
#define CRYO_OBJECTIVE 2
#define CRYO_IGNORE 3
#define CRYO_DESTROY_LATER 4
/obj/machinery/cryopod/proc/should_preserve_item(obj/item/I)
for(var/datum/objective_item/steal/T in control_computer.theft_cache)
@@ -308,8 +309,8 @@
if(iscyborg(mob_occupant))
var/mob/living/silicon/robot/R = mob_occupant
if(R.mmi?.brain)
cryo_items[R.mmi] = CRYO_IGNORE
cryo_items[R.mmi.brain] = CRYO_IGNORE
cryo_items[R.mmi] = CRYO_DESTROY_LATER
cryo_items[R.mmi.brain] = CRYO_DESTROY_LATER
for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc
for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags
cryo_items[O] = should_preserve_item(O)
@@ -318,7 +319,7 @@
//Drop all items into the pod.
for(var/obj/item/I in mob_occupant)
if(cryo_items[I] == CRYO_IGNORE)
if(cryo_items[I] == CRYO_IGNORE || cryo_items[I] ==CRYO_DESTROY_LATER)
continue
cryo_items[I] = should_preserve_item(I)
mob_occupant.transferItemToLoc(I, src, TRUE)
@@ -334,17 +335,19 @@
if(QDELETED(I)) //edge cases and DROPDEL.
continue
var/preserve = cryo_items[I]
if(preserve == CRYO_IGNORE)
if(preserve == CRYO_DESTROY_LATER)
continue
else if(preserve == CRYO_DESTROY)
qdel(I)
else if(control_computer?.allow_items)
control_computer.frozen_items += I
if(preserve == CRYO_OBJECTIVE)
control_computer.objective_items += I
I.moveToNullspace()
else
I.forceMove(loc)
if(preserve != CRYO_IGNORE)
if(preserve == CRYO_DESTROY)
qdel(I)
else if(control_computer?.allow_items)
control_computer.frozen_items += I
if(preserve == CRYO_OBJECTIVE)
control_computer.objective_items += I
I.moveToNullspace()
else
I.forceMove(loc)
cryo_items -= I
//Update any existing objectives involving this mob.
for(var/datum/objective/O in GLOB.objectives)
@@ -405,6 +408,10 @@
mob_occupant.ghostize(FALSE, penalize = TRUE)
QDEL_NULL(occupant)
for(var/I in cryo_items) //only "CRYO_DESTROY_LATER" atoms are left)
var/atom/A = I
if(!QDELETED(A))
qdel(A)
open_machine()
name = initial(name)
@@ -412,6 +419,7 @@
#undef CRYO_PRESERVE
#undef CRYO_OBJECTIVE
#undef CRYO_IGNORE
#undef CRYO_DESTROY_LATER
/obj/machinery/cryopod/MouseDrop_T(mob/living/target, mob/user)
if(!istype(target) || user.incapacitated() || !target.Adjacent(user) || !Adjacent(user) || !ismob(target) || (!ishuman(user) && !iscyborg(user)) || !istype(user.loc, /turf) || target.buckled)
+2 -2
View File
@@ -45,7 +45,7 @@
return
return ..()
/obj/machinery/jukebox/update_icon()
/obj/machinery/jukebox/update_icon_state()
if(active)
icon_state = "[initial(icon_state)]-active"
else
@@ -433,5 +433,5 @@
. = ..()
if(active)
for(var/mob/living/M in rangers)
if(prob(5+(allowed(M)*4)) && M.canmove)
if(prob(5+(allowed(M)*4)) && CHECK_MOBILITY(M, MOBILITY_MOVE))
dance(M)
+2 -2
View File
@@ -22,7 +22,7 @@
precision_coeff = 0
for(var/obj/item/stock_parts/scanning_module/P in component_parts)
scan_level += P.rating
for(var/obj/item/stock_parts/manipulator/P in component_parts)
for(var/obj/item/stock_parts/matter_bin/P in component_parts)
precision_coeff = P.rating
for(var/obj/item/stock_parts/micro_laser/P in component_parts)
damage_coeff = P.rating
@@ -34,7 +34,7 @@
if(scan_level >= 3)
. += "<span class='notice'>Scanner has been upgraded to support autoprocessing.<span>"
/obj/machinery/dna_scannernew/update_icon()
/obj/machinery/dna_scannernew/update_icon_state()
//no power or maintenance
if(stat & (NOPOWER|BROKEN))
+2 -2
View File
@@ -769,7 +769,7 @@
if(!istype(H.head, /obj/item/clothing/head/helmet))
H.visible_message("<span class='danger'>[user] headbutts the airlock.</span>", \
"<span class='userdanger'>You headbutt the airlock!</span>")
H.Knockdown(100)
H.DefaultCombatKnockdown(100)
H.apply_damage(10, BRUTE, BODY_ZONE_HEAD)
else
visible_message("<span class='danger'>[user] headbutts the airlock. Good thing [user.p_theyre()] wearing a helmet.</span>")
@@ -1033,7 +1033,7 @@
if(!I.use_tool(src, user, 150, volume=50))
to_chat(user, "<span class='warning'>You slip and [charge] detonates!</span>")
charge.ex_act(EXPLODE_DEVASTATE)
user.Knockdown(60)
user.DefaultCombatKnockdown(60)
return
user.visible_message("<span class='notice'>[user] removes [charge] from [src].</span>", \
"<span class='notice'>You gently pry out [charge] from [src] and unhook its wires.</span>")
+1 -1
View File
@@ -508,7 +508,7 @@
throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src)))
SEND_SOUND(L, sound(pick('sound/hallucinations/turn_around1.ogg','sound/hallucinations/turn_around2.ogg'),0,1,50))
flash_color(L, flash_color="#960000", flash_time=20)
L.Knockdown(40)
L.DefaultCombatKnockdown(40)
L.throw_at(throwtarget, 5, 1)
return 0
+3 -3
View File
@@ -230,7 +230,7 @@
/obj/machinery/door/proc/unelectrify()
secondsElectrified = 0
/obj/machinery/door/update_icon()
/obj/machinery/door/update_icon_state()
if(density)
icon_state = "door1"
else
@@ -319,10 +319,10 @@
else if(ishuman(L)) //For humans
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
L.emote("scream")
L.Knockdown(100)
L.DefaultCombatKnockdown(100)
else if(ismonkey(L)) //For monkeys
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
L.Knockdown(100)
L.DefaultCombatKnockdown(100)
else //for simple_animals & borgs
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
var/turf/location = get_turf(src)
+11 -8
View File
@@ -171,16 +171,20 @@
if("closing")
flick("door_closing", src)
/obj/machinery/door/firedoor/update_icon()
cut_overlays()
/obj/machinery/door/firedoor/update_icon_state()
if(density)
icon_state = "door_closed"
if(welded)
add_overlay("welded")
else
icon_state = "door_open"
if(welded)
add_overlay("welded_open")
/obj/machinery/door/firedoor/update_overlays()
. = ..()
if(!welded)
return
if(density)
. += "welded"
else
. += "welded_open"
/obj/machinery/door/firedoor/open()
. = ..()
@@ -283,8 +287,7 @@
if(CONSTRUCTION_NOCIRCUIT)
. += "<span class='notice'>There are no <i>firelock electronics</i> in the frame. The frame could be <b>cut</b> apart.</span>"
/obj/structure/firelock_frame/update_icon()
..()
/obj/structure/firelock_frame/update_icon_state()
icon_state = "frame[constructionStep]"
/obj/structure/firelock_frame/attackby(obj/item/C, mob/user)
+1 -1
View File
@@ -42,7 +42,7 @@
else
do_animate("deny")
/obj/machinery/door/password/update_icon()
/obj/machinery/door/password/update_icon_state()
if(density)
icon_state = "closed"
else
+1 -1
View File
@@ -77,7 +77,7 @@
flick("closing", src)
playsound(src, 'sound/machines/blastdoor.ogg', 30, 1)
/obj/machinery/door/poddoor/update_icon()
/obj/machinery/door/poddoor/update_icon_state()
if(density)
icon_state = "closed"
else
+1 -1
View File
@@ -48,7 +48,7 @@
electronics = null
return ..()
/obj/machinery/door/window/update_icon()
/obj/machinery/door/window/update_icon_state()
if(density)
icon_state = base_state
else
+1 -1
View File
@@ -199,7 +199,7 @@
if(istype(a, dispense_type))
.++
/obj/machinery/droneDispenser/update_icon()
/obj/machinery/droneDispenser/update_icon_state()
if(stat & (BROKEN|NOPOWER))
icon_state = icon_off
else if(mode == DRONE_RECHARGING)
@@ -84,7 +84,7 @@
busy = FALSE
update_icon()
/obj/machinery/doorButtons/access_button/update_icon()
/obj/machinery/doorButtons/access_button/update_icon_state()
if(stat & NOPOWER)
icon_state = "access_button_off"
else
@@ -249,7 +249,7 @@
else if(A.id_tag == idExterior)
exteriorAirlock = A
/obj/machinery/doorButtons/airlock_controller/update_icon()
/obj/machinery/doorButtons/airlock_controller/update_icon_state()
if(stat & NOPOWER)
icon_state = "access_control_off"
return
@@ -255,7 +255,7 @@
new_prog.master = src
program = new_prog
/obj/machinery/embedded_controller/radio/airlock_controller/update_icon()
/obj/machinery/embedded_controller/radio/airlock_controller/update_icon_state()
if(on && program)
if(program.memory["processing"])
icon_state = "airlock_control_process"
@@ -33,8 +33,6 @@
popup.set_content(return_text())
popup.open()
/obj/machinery/embedded_controller/update_icon()
/obj/machinery/embedded_controller/proc/return_text()
/obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line)
@@ -54,7 +54,7 @@
new_prog.master = src
program = new_prog
/obj/machinery/embedded_controller/radio/simple_vent_controller/update_icon()
/obj/machinery/embedded_controller/radio/simple_vent_controller/update_icon_state()
if(on && program)
icon_state = "airlock_control_standby"
else
+14 -14
View File
@@ -9,7 +9,7 @@
internal_radio = FALSE
//Start growing a human clone in the pod!
/obj/machinery/clonepod/experimental/growclone(ckey, clonename, ui, se, datum/species/mrace, list/features, factions)
/obj/machinery/clonepod/experimental/growclone(clonename, ui, mutation_index, mindref, last_death, blood_type, datum/species/mrace, list/features, factions, list/quirks)
if(panel_open)
return FALSE
if(mess || attempting)
@@ -20,15 +20,15 @@
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
H.hardset_dna(ui, se, H.real_name, null, mrace, features)
H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features)
if(efficiency > 2)
var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations)
H.dna.remove_mutation_group(unclean_mutations)
if(efficiency > 5 && prob(20))
H.randmutvg()
H.easy_randmut(POSITIVE)
if(efficiency < 3 && prob(50))
var/mob/M = H.randmutb()
var/mob/M = H.easy_randmut(NEGATIVE+MINOR_NEGATIVE)
if(ismob(M))
H = M
@@ -42,18 +42,17 @@
icon_state = "pod_1"
//Get the clone body ready
maim_clone(H)
ADD_TRAIT(H, TRAIT_STABLEHEART, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_STABLELIVER, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_MUTE, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_NOBREATH, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning")
ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning")
ADD_TRAIT(H, TRAIT_MUTE, "cloning")
ADD_TRAIT(H, TRAIT_NOBREATH, "cloning")
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning")
H.Unconscious(80)
var/list/candidates = pollCandidatesForMob("Do you want and agree to play as a [clonename]'s defective clone, respect their character and not engage in ERP without permission from the original?", null, null, null, 100, H, POLL_IGNORE_CLONE)
var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone?", null, null, null, 100, H)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
C.transfer_ckey(H)
var/mob/C = pick(candidates)
H.key = C.key
if(grab_ghost_when == CLONER_FRESH_CLONE)
H.grab_ghost()
@@ -293,6 +292,7 @@
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else
pod.growclone(null, mob_occupant.real_name, dna.uni_identity, dna.struc_enzymes, clone_species, dna.features, mob_occupant.faction)
pod.growclone(mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
temp = "[mob_occupant.real_name] => <font class='good'>Cloning data sent to pod.</font>"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+11 -10
View File
@@ -55,10 +55,7 @@
..()
update_icon()
/obj/machinery/firealarm/update_icon()
cut_overlays()
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
/obj/machinery/firealarm/update_icon_state()
if(panel_open)
icon_state = "fire_b[buildstage]"
return
@@ -72,26 +69,30 @@
if(stat & NOPOWER)
return
add_overlay("fire_overlay")
/obj/machinery/firealarm/update_overlays()
. = ..()
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
. += "fire_overlay"
if(is_station_level(z))
add_overlay("fire_[GLOB.security_level]")
. += "fire_[GLOB.security_level]"
SSvis_overlays.add_vis_overlay(src, icon, "fire_[GLOB.security_level]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
else
add_overlay("fire_[SEC_LEVEL_GREEN]")
. += "fire_[SEC_LEVEL_GREEN]"
SSvis_overlays.add_vis_overlay(src, icon, "fire_[SEC_LEVEL_GREEN]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
var/area/A = src.loc
A = A.loc
if(!detecting || !A.fire)
add_overlay("fire_off")
. += "fire_off"
SSvis_overlays.add_vis_overlay(src, icon, "fire_off", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
else if(obj_flags & EMAGGED)
add_overlay("fire_emagged")
. += "fire_emagged"
SSvis_overlays.add_vis_overlay(src, icon, "fire_emagged", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
else
add_overlay("fire_on")
. += "fire_on"
SSvis_overlays.add_vis_overlay(src, icon, "fire_on", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
/obj/machinery/firealarm/emp_act(severity)
+1 -1
View File
@@ -115,7 +115,7 @@
continue
if(L.flash_act(affect_silicon = 1))
L.Knockdown(strength)
L.DefaultCombatKnockdown(strength)
flashed = TRUE
if(flashed)
+1 -1
View File
@@ -68,7 +68,7 @@ The console is located at computer/gulag_teleporter.dm
return ..()
/obj/machinery/gulag_teleporter/update_icon()
/obj/machinery/gulag_teleporter/update_icon_state()
icon_state = initial(icon_state) + (state_open ? "_open" : "")
//no power or maintenance
if(stat & (NOPOWER|BROKEN))
+9 -5
View File
@@ -11,6 +11,7 @@
light_color = LIGHT_COLOR_BLUE
var/interval = 20
var/harvesting = FALSE
var/warming_up = FALSE
var/list/operation_order = list() //Order of wich we harvest limbs.
var/allow_clothing = FALSE
var/allow_living = FALSE
@@ -27,12 +28,11 @@
max_time -= L.rating
interval = max(max_time,1)
/obj/machinery/harvester/update_icon(warming_up)
if(warming_up)
icon_state = initial(icon_state)+"-charging"
return
/obj/machinery/harvester/update_icon_state()
if(state_open)
icon_state = initial(icon_state)+"-open"
else if(warming_up)
icon_state = initial(icon_state)+"-charging"
else if(harvesting)
icon_state = initial(icon_state)+"-active"
else
@@ -43,6 +43,7 @@
return
. = ..()
harvesting = FALSE
warming_up = FALSE
/obj/machinery/harvester/attack_hand(mob/user)
if(state_open)
@@ -86,13 +87,15 @@
return
var/mob/living/carbon/C = occupant
operation_order = reverseList(C.bodyparts) //Chest and head are first in bodyparts, so we invert it to make them suffer more
warming_up = TRUE
harvesting = TRUE
visible_message("<span class='notice'>The [name] begins warming up!</span>")
say("Initializing harvest protocol.")
update_icon(TRUE)
update_icon()
addtimer(CALLBACK(src, .proc/harvest), interval)
/obj/machinery/harvester/proc/harvest()
warming_up = FALSE
update_icon()
if(!harvesting || state_open || !powered(EQUIP) || !occupant || !iscarbon(occupant))
return
@@ -127,6 +130,7 @@
addtimer(CALLBACK(src, .proc/harvest), interval)
/obj/machinery/harvester/proc/end_harvesting()
warming_up = FALSE
harvesting = FALSE
open_machine()
say("Subject has been successfully harvested.")
+1 -1
View File
@@ -441,7 +441,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
set_light(0)
update_icon()
/obj/machinery/holopad/update_icon()
/obj/machinery/holopad/update_icon_state()
var/total_users = LAZYLEN(masters) + LAZYLEN(holo_calls)
if(ringing)
icon_state = "holopad_ringing"
+8 -7
View File
@@ -24,7 +24,7 @@
QDEL_NULL(beaker)
return ..()
/obj/machinery/iv_drip/update_icon()
/obj/machinery/iv_drip/update_icon_state()
if(attached)
if(mode)
icon_state = "injecting"
@@ -36,13 +36,14 @@
else
icon_state = "donateidle"
cut_overlays()
/obj/machinery/iv_drip/update_overlays()
. = ..()
if(beaker)
if(attached)
add_overlay("beakeractive")
. += "beakeractive"
else
add_overlay("beakeridle")
. += "beakeridle"
if(beaker.reagents.total_volume)
var/mutable_appearance/filling_overlay = mutable_appearance('icons/obj/iv_drip.dmi', "reagent")
@@ -64,7 +65,7 @@
filling_overlay.icon_state = "reagent100"
filling_overlay.color = mix_color_from_reagents(beaker.reagents.reagent_list)
add_overlay(filling_overlay)
. += filling_overlay
/obj/machinery/iv_drip/MouseDrop(mob/living/target)
. = ..()
@@ -227,9 +228,9 @@
desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate. This one is telescopic, and can be picked up and put down."
icon_state = "iv_drip"
/obj/machinery/iv_drip/telescopic/update_icon()
/obj/machinery/iv_drip/telescopic/update_icon_state()
..()
icon_state = icon_state + "_tele"
icon_state += "_tele"
/obj/machinery/iv_drip/telescopic/AltClick(mob/user)
if (attached || beaker || !user.canUseTopic(src, BE_CLOSE))
+1 -1
View File
@@ -23,7 +23,7 @@
on = area.lightswitch
update_icon()
/obj/machinery/light_switch/update_icon()
/obj/machinery/light_switch/update_icon_state()
if(stat & NOPOWER)
icon_state = "light-p"
else
+2 -1
View File
@@ -138,7 +138,8 @@
limb = new buildpath(loc)
if(selected_category=="human" || selected_category=="lizard") //Species with greyscale parts should be included here
limb.icon = 'icons/mob/human_parts_greyscale.dmi'
limb.should_draw_greyscale = TRUE
limb.base_bp_icon = DEFAULT_BODYPART_ICON_ORGANIC
limb.color_src = MUTCOLORS
else
limb.icon = 'icons/mob/human_parts.dmi'
// Set this limb up using the specias name and body zone
+3 -3
View File
@@ -49,7 +49,7 @@
update_icon()
// update the icon_state
/obj/machinery/magnetic_module/update_icon()
/obj/machinery/magnetic_module/update_icon_state()
var/state="floor_magnet"
var/onstate=""
if(!on)
@@ -316,7 +316,7 @@
if("togglemoving")
moving = !moving
if(moving)
spawn() MagnetMove()
INVOKE_ASYNC(src, .proc/MagnetMove)
updateUsrDialog()
@@ -325,7 +325,7 @@
if(looping)
return
while(moving && rpath.len >= 1)
while(moving && length(rpath) >= 1)
if(stat & (BROKEN|NOPOWER))
break
+1 -1
View File
@@ -75,7 +75,7 @@
update_icon()
// update the icon_state
/obj/machinery/navbeacon/update_icon()
/obj/machinery/navbeacon/update_icon_state()
var/state="navbeacon[open]"
if(invisibility)
+5 -4
View File
@@ -17,7 +17,7 @@ Buildable meters
icon = 'icons/obj/atmospherics/pipes/pipe_item.dmi'
icon_state = "simple"
item_state = "buildpipe"
w_class = WEIGHT_CLASS_NORMAL
w_class = WEIGHT_CLASS_SMALL
level = 2
var/piping_layer = PIPING_LAYER_DEFAULT
var/RPD_type
@@ -63,7 +63,7 @@ Buildable meters
if(make_from.flipped)
do_a_flip()
/obj/item/pipe/dropped()
/obj/item/pipe/dropped(mob/user)
if(loc)
setPipingLayer(piping_layer)
return ..()
@@ -90,7 +90,8 @@ Buildable meters
set name = "Flip Pipe"
set src in view(1)
if ( usr.stat || usr.restrained() || !usr.canmove )
var/mob/living/L = usr
if(!istype(L) || !CHECK_MOBILITY(L, MOBILITY_USE))
return
do_a_flip()
@@ -224,7 +225,7 @@ Buildable meters
to_chat(user, "<span class='notice'>You fasten the meter to the [loc.name].</span>")
qdel(src)
/obj/item/pipe_meter/dropped()
/obj/item/pipe_meter/dropped(mob/user)
. = ..()
if(loc)
setAttachLayer(piping_layer)
+5 -4
View File
@@ -34,7 +34,8 @@
/obj/machinery/pipedispenser/Topic(href, href_list)
if(..())
return 1
if(!anchored|| !usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
var/mob/living/L = usr
if(!anchored || !istype(L) || !CHECK_MOBILITY(L, MOBILITY_USE))
usr << browse(null, "window=pipedispenser")
return 1
usr.set_machine(src)
@@ -93,14 +94,14 @@
//Allow you to drag-drop disposal pipes and transit tubes into it
/obj/machinery/pipedispenser/disposal/MouseDrop_T(obj/structure/pipe, mob/usr)
if(!usr.canmove || usr.stat || usr.restrained())
/obj/machinery/pipedispenser/disposal/MouseDrop_T(obj/structure/pipe, mob/living/user)
if(!istype(user) || !CHECK_MOBILITY(user, MOBILITY_USE))
return
if (!istype(pipe, /obj/structure/disposalconstruct) && !istype(pipe, /obj/structure/c_transit_tube) && !istype(pipe, /obj/structure/c_transit_tube_pod))
return
if (get_dist(usr, src) > 1 || get_dist(src,pipe) > 1 )
if (get_dist(user, src) > 1 || get_dist(src,pipe) > 1 )
return
if (pipe.anchored)
@@ -99,8 +99,7 @@
if(!has_cover)
INVOKE_ASYNC(src, .proc/popUp)
/obj/machinery/porta_turret/update_icon()
cut_overlays()
/obj/machinery/porta_turret/update_icon_state()
if(!anchored)
icon_state = "turretCover"
return
@@ -248,6 +247,7 @@
if(prob(70))
if(stored_gun)
stored_gun.forceMove(loc)
stored_gun = null
to_chat(user, "<span class='notice'>You remove the turret and salvage some components.</span>")
if(prob(50))
new /obj/item/stack/sheet/metal(loc, rand(1,4))
@@ -409,7 +409,7 @@
if(iscarbon(A))
var/mob/living/carbon/C = A
//If not emagged, only target non downed carbons
if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || C.recoveringstam))//CIT CHANGE - replaces check for lying with check for recoveringstam
if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || (C.combat_flags & COMBAT_FLAG_HARD_STAMCRIT)))//CIT CHANGE - replaces check for lying with check for recoveringstam
continue
//If emagged, target all but dead carbons
@@ -706,7 +706,7 @@
/obj/machinery/porta_turret/syndicate/energy/pirate
max_integrity = 260
integrity_failure = 20
integrity_failure = 0.08
armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
@@ -970,8 +970,7 @@
..()
update_icon()
/obj/machinery/turretid/update_icon()
..()
/obj/machinery/turretid/update_icon_state()
if(stat & NOPOWER)
icon_state = "control_off"
else if (enabled)
+14 -16
View File
@@ -10,6 +10,7 @@
pass_flags = PASSTABLE
var/obj/item/charging = null
var/recharge_coeff = 1
var/using_power = FALSE //Did we put power into "charging" last process()?
var/static/list/allowed_devices = typecacheof(list(
/obj/item/gun/energy,
@@ -45,9 +46,11 @@
if (new_charging)
START_PROCESSING(SSmachines, src)
use_power = ACTIVE_POWER_USE
update_icon(scan = TRUE)
using_power = TRUE
update_icon()
else
use_power = IDLE_POWER_USE
using_power = FALSE
update_icon()
/obj/machinery/recharger/attackby(obj/item/G, mob/user, params)
@@ -120,23 +123,23 @@
if(stat & (NOPOWER|BROKEN) || !anchored)
return PROCESS_KILL
var/using_power = 0
using_power = FALSE
if(charging)
var/obj/item/stock_parts/cell/C = charging.get_cell()
if(C)
if(C.charge < C.maxcharge)
C.give(C.chargerate * recharge_coeff)
use_power(250 * recharge_coeff)
using_power = 1
update_icon(using_power)
using_power = TRUE
update_icon()
if(istype(charging, /obj/item/ammo_box/magazine/recharge))
var/obj/item/ammo_box/magazine/recharge/R = charging
if(R.stored_ammo.len < R.max_ammo)
R.stored_ammo += new R.ammo_type(R)
use_power(200 * recharge_coeff)
using_power = 1
update_icon(using_power)
using_power = TRUE
update_icon()
return
else
return PROCESS_KILL
@@ -161,20 +164,15 @@
B.cell.charge = 0
/obj/machinery/recharger/update_icon(using_power = 0, scan) //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
/obj/machinery/recharger/update_icon_state()
if(stat & (NOPOWER|BROKEN) || !anchored)
icon_state = "rechargeroff"
return
if(scan)
icon_state = "rechargeroff"
return
if(panel_open)
else if(panel_open)
icon_state = "rechargeropen"
return
if(charging)
else if(charging)
if(using_power)
icon_state = "recharger1"
else
icon_state = "recharger2"
return
icon_state = "recharger0"
else
icon_state = "recharger0"
+1 -1
View File
@@ -112,7 +112,7 @@
use_power = ACTIVE_POWER_USE
add_fingerprint(occupant)
/obj/machinery/recharge_station/update_icon()
/obj/machinery/recharge_station/update_icon_state()
if(is_operational())
if(state_open)
icon_state = "borgcharger0"
+10 -11
View File
@@ -8,7 +8,7 @@
layer = ABOVE_ALL_MOB_LAYER // Overhead
density = TRUE
circuit = /obj/item/circuitboard/machine/recycler
var/safety_mode = FALSE // Temporarily stops machine if it detects a mob
var/safety_mode = FALSE // Temporarily stops machine if it detects a mob, or upon deconstruction.
var/icon_name = "grinder-o"
var/blood = 0
var/eat_dir = WEST
@@ -24,6 +24,10 @@
update_icon()
req_one_access = get_all_accesses() + get_all_centcom_access()
/obj/machinery/recycler/deconstruct(disassembled = TRUE)
safety_mode = TRUE //to stop stock parts and circuit from being deleted.
return ..()
/obj/machinery/recycler/RefreshParts()
var/amt_made = 0
var/mat_mod = 0
@@ -77,8 +81,7 @@
to_chat(user, "<span class='notice'>You use the cryptographic sequencer on [src].</span>")
return TRUE
/obj/machinery/recycler/update_icon()
..()
/obj/machinery/recycler/update_icon_state()
var/is_powered = !(stat & (BROKEN|NOPOWER))
if(safety_mode)
is_powered = FALSE
@@ -98,18 +101,14 @@
. = ..()
/obj/machinery/recycler/proc/eat(atom/AM0, sound=TRUE)
if(stat & (BROKEN|NOPOWER))
return
if(safety_mode)
if(stat & (BROKEN|NOPOWER) || safety_mode)
return
var/list/to_eat
if(isitem(AM0))
to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
else
to_eat = list(AM0)
to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
var/items_recycled = 0
for(var/i in to_eat)
var/atom/movable/AM = i
var/obj/item/bodypart/head/as_head = AM
+1 -1
View File
@@ -60,7 +60,7 @@ GLOBAL_LIST_EMPTY(allConsoles)
..()
update_icon()
/obj/machinery/requests_console/update_icon()
/obj/machinery/requests_console/update_icon_state()
if(stat & NOPOWER)
set_light(0)
else
+1 -1
View File
@@ -208,7 +208,7 @@
to_chat(user, "<span class='warning'>You short out the access controller.</span>")
return TRUE
/obj/machinery/shieldgen/update_icon()
/obj/machinery/shieldgen/update_icon_state()
if(active)
icon_state = (stat & BROKEN) ? "shieldonbr":"shieldon"
else
+1 -1
View File
@@ -56,7 +56,7 @@
money++ //SPESSH MAJICKS
/obj/machinery/computer/slot_machine/update_icon()
/obj/machinery/computer/slot_machine/update_icon_state()
if(stat & NOPOWER)
icon_state = "slots0"
+5 -4
View File
@@ -53,17 +53,18 @@
else
. += "There is no power cell installed."
if(in_range(user, src) || isobserver(user))
. += "<span class='notice'>The status display reads: Temperature range at <b>[settableTemperatureRange]°C</b>.<br>Heating power at <b>[heatingPower*0.001]kJ</b>.<br>Power consumption at <b>[(efficiency*-0.0025)+150]%</b>.<span>" //100%, 75%, 50%, 25%
. += "<span class='notice'>The status display reads: Temperature range at <b>[settableTemperatureRange]°C</b>.<br>Heating power at <b>[heatingPower*0.001]kJ</b>.<br>Power consumption at <b>[(efficiency*-0.0025)+150]%</b>.<span>" //100%, 75%, 50%, 25%
/obj/machinery/space_heater/update_icon()
/obj/machinery/space_heater/update_icon_state()
if(on)
icon_state = "sheater-[mode]"
else
icon_state = "sheater-off"
cut_overlays()
/obj/machinery/space_heater/update_overlays()
. = ..()
if(panel_open)
add_overlay("sheater-open")
. += "sheater-open"
/obj/machinery/space_heater/process()
if(!on || !is_operational())
+17 -12
View File
@@ -75,6 +75,12 @@
suit_type = /obj/item/clothing/suit/space/hardsuit/medical
mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/paramedic
name = "paramedic suit storage unit"
suit_type = /obj/item/clothing/suit/space/eva/paramedic
helmet_type = /obj/item/clothing/head/helmet/space/eva/paramedic
mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/rd
suit_type = /obj/item/clothing/suit/space/hardsuit/rd
mask_type = /obj/item/clothing/mask/breath
@@ -134,29 +140,28 @@
QDEL_NULL(storage)
return ..()
/obj/machinery/suit_storage_unit/update_icon()
cut_overlays()
/obj/machinery/suit_storage_unit/update_overlays()
. = ..()
if(uv)
if(uv_super)
add_overlay("super")
. += "super"
else if(occupant)
add_overlay("uvhuman")
. += "uvhuman"
else
add_overlay("uv")
. += "uv"
else if(state_open)
if(stat & BROKEN)
add_overlay("broken")
. += "broken"
else
add_overlay("open")
. += "open"
if(suit)
add_overlay("suit")
. += "suit"
if(helmet)
add_overlay("helm")
. += "helm"
if(storage)
add_overlay("storage")
. += "storage"
else if(occupant)
add_overlay("human")
. += "human"
/obj/machinery/suit_storage_unit/power_change()
..()
+1 -1
View File
@@ -102,7 +102,7 @@
. = ..()
. += "A digital display on it reads \"[seconds_remaining()]\"."
/obj/machinery/syndicatebomb/update_icon()
/obj/machinery/syndicatebomb/update_icon_state()
icon_state = "[initial(icon_state)][active ? "-active" : "-inactive"][open_panel ? "-wires" : ""]"
/obj/machinery/syndicatebomb/proc/seconds_remaining()
@@ -35,8 +35,6 @@
signal.data["compression"] = 0
signal.mark_done()
if(signal.data["slow"] > 0)
sleep(signal.data["slow"]) // simulate the network lag if necessary
signal.broadcast()
/obj/machinery/telecomms/allinone/attackby(obj/item/P, mob/user, params)
@@ -41,9 +41,6 @@ GLOBAL_VAR_INIT(message_delay, 0) // To make sure restarting the recentmessages
return
GLOB.recentmessages.Add(signal_message)
if(signal.data["slow"] > 0)
sleep(signal.data["slow"]) // simulate the network lag if necessary
signal.broadcast()
if(!GLOB.message_delay)
@@ -31,17 +31,10 @@
if(relay_information(signal, /obj/machinery/telecomms/processor))
return
// failed to send to a processor, relay information anyway
signal.data["slow"] += rand(1, 5) // slow the signal down only slightly
// Try sending it!
var/list/try_send = list(signal.server_type, /obj/machinery/telecomms/hub, /obj/machinery/telecomms/broadcaster)
var/i = 0
for(var/send in try_send)
if(i)
signal.data["slow"] += rand(0, 1) // slow the signal down only slightly
i++
if(relay_information(signal, send))
break
@@ -79,4 +72,4 @@
/obj/machinery/telecomms/bus/preset_one/birdstation
name = "Bus"
autolinkers = list("processor1", "common")
freq_listening = list()
freq_listening = list()
@@ -74,7 +74,7 @@
if(!relay_information(signal, /obj/machinery/telecomms/hub))
relay_information(signal, /obj/machinery/telecomms/broadcaster)
/obj/machinery/telecomms/message_server/update_icon()
/obj/machinery/telecomms/message_server/update_icon_state()
if((stat & (BROKEN|NOPOWER)))
icon_state = "server-nopower"
else if (!toggled)
@@ -28,7 +28,6 @@
if(istype(machine_from, /obj/machinery/telecomms/bus))
relay_direct_information(signal, machine_from) // send the signal back to the machine
else // no bus detected - send the signal to servers instead
signal.data["slow"] += rand(5, 10) // slow the signal down
relay_information(signal, signal.server_type)
//Preset Processors
@@ -39,11 +39,6 @@ GLOBAL_LIST_EMPTY(telecomms_list)
return
var/send_count = 0
// Apply some lag based on traffic rates
var/netlag = round(traffic / 50)
if(netlag > signal.data["slow"])
signal.data["slow"] = netlag
// Loop through all linked machines and send the signal or copy.
for(var/obj/machinery/telecomms/machine in links)
if(filter && !istype( machine, filter ))
@@ -109,7 +104,7 @@ GLOBAL_LIST_EMPTY(telecomms_list)
links |= T
T.links |= src
/obj/machinery/telecomms/update_icon()
/obj/machinery/telecomms/update_icon_state()
if(on)
if(panel_open)
icon_state = "[initial(icon_state)]_o"
+2 -2
View File
@@ -85,7 +85,7 @@
calibrated = FALSE
return
/obj/machinery/teleport/hub/update_icon()
/obj/machinery/teleport/hub/update_icon_state()
if(panel_open)
icon_state = "tele-o"
else if(is_ready())
@@ -218,7 +218,7 @@
if(teleporter_hub)
teleporter_hub.update_icon()
/obj/machinery/teleport/station/update_icon()
/obj/machinery/teleport/station/update_icon_state()
if(panel_open)
icon_state = "controller-o"
else if(stat & (BROKEN|NOPOWER))
+7 -2
View File
@@ -46,7 +46,12 @@
)
/obj/machinery/autoylathe/Initialize()
AddComponent(/datum/component/material_container, list(/datum/material/iron, /datum/material/glass, /datum/material/plastic), 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
var/static/list/allowed_materials = list(
/datum/material/iron,
/datum/material/glass,
/datum/material/plastic
)
AddComponent(/datum/component/material_container, allowed_materials, 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
. = ..()
wires = new /datum/wires/autoylathe(src)
@@ -121,7 +126,7 @@
return ..()
/obj/machinery/autoylathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
if(item_inserted.custom_materials?.len && item_inserted.custom_materials[getmaterialref(/datum/material/glass)])
if(item_inserted.custom_materials?.len && item_inserted.custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
flick("autolathe_r",src)//plays glass insertion animation by default otherwise
else
flick("autolathe_o",src)//plays metal insertion animation
+1 -2
View File
@@ -38,8 +38,7 @@
..()
update_icon()
/obj/machinery/transformer/update_icon()
..()
/obj/machinery/transformer/update_icon_state()
if(stat & (BROKEN|NOPOWER) || cooldown == 1)
icon_state = "separator-AO0"
else
+5 -3
View File
@@ -199,8 +199,7 @@
/obj/machinery/washing_machine/update_icon()
cut_overlays()
/obj/machinery/washing_machine/update_icon_state()
if(busy)
icon_state = "wm_running_[bloody_mess]"
else if(bloody_mess)
@@ -208,8 +207,11 @@
else
var/full = contents.len ? 1 : 0
icon_state = "wm_[state_open]_[full]"
/obj/machinery/washing_machine/update_overlays()
. = ..()
if(panel_open)
add_overlay("wm_panel")
. += "wm_panel"
/obj/machinery/washing_machine/attackby(obj/item/W, mob/user, params)
if(panel_open && !busy && default_unfasten_wrench(user, W))
@@ -226,8 +226,7 @@
return
if(M.health > 0)
M.adjustOxyLoss(-1)
M.AdjustStun(-80)
M.AdjustKnockdown(-80)
M.AdjustAllImmobility(-80)
M.AdjustUnconscious(-80)
if(M.reagents.get_reagent_amount(/datum/reagent/medicine/epinephrine) < 5)
M.reagents.add_reagent(/datum/reagent/medicine/epinephrine, 5)
@@ -283,13 +283,13 @@
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_charge()
if(equip_ready) //disabled
return
var/area/A = get_base_area(chassis)
var/pow_chan = get_power_channel(A)
var/area/A = get_area(chassis)
var/pow_chan = get_MUTATION_POWER_channel(A)
if(pow_chan)
return 1000 //making magic
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_power_channel(var/area/A)
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_MUTATION_POWER_channel(var/area/A)
var/pow_chan
if(A)
for(var/c in use_channels)
+1 -1
View File
@@ -177,7 +177,7 @@
M.SetSleeping(0)
M.stuttering += 20
M.adjustEarDamage(0, 30)
M.Knockdown(60)
M.DefaultCombatKnockdown(60)
if(prob(30))
M.Stun(200)
M.Unconscious(80)
+3 -3
View File
@@ -128,11 +128,11 @@
else
recharge_port = null
/obj/machinery/computer/mech_bay_power_console/update_icon()
..()
/obj/machinery/computer/mech_bay_power_console/update_overlays()
. = ..()
if(!recharge_port || !recharge_port.recharging_mech || !recharge_port.recharging_mech.cell || !(recharge_port.recharging_mech.cell.charge < recharge_port.recharging_mech.cell.maxcharge) || stat & (NOPOWER|BROKEN))
return
add_overlay("recharge_comp_on")
. += "recharge_comp_on"
/obj/machinery/computer/mech_bay_power_console/Initialize()
. = ..()
+13 -3
View File
@@ -35,9 +35,19 @@
)
/obj/machinery/mecha_part_fabricator/Initialize()
var/datum/component/material_container/materials = AddComponent(/datum/component/material_container,
list(/datum/material/iron, /datum/material/glass, /datum/material/silver, /datum/material/gold, /datum/material/diamond, /datum/material/plasma, /datum/material/uranium, /datum/material/bananium, /datum/material/titanium, /datum/material/bluespace), 0,
TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
var/static/list/allowed_types = list(
/datum/material/iron,
/datum/material/glass,
/datum/material/silver,
/datum/material/gold,
/datum/material/diamond,
/datum/material/plasma,
/datum/material/uranium,
/datum/material/bananium,
/datum/material/titanium,
/datum/material/bluespace
)
var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, allowed_types, 0, TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
materials.precise_insertion = TRUE
stored_research = new
return ..()
+3 -4
View File
@@ -755,7 +755,7 @@
AI.cancel_camera()
AI.controlled_mech = src
AI.remote_control = src
AI.canmove = 1 //Much easier than adding AI checks! Be sure to set this back to 0 if you decide to allow an AI to leave a mech somehow.
AI.mobility_flags = MOBILITY_FLAGS_DEFAULT //Much easier than adding AI checks! Be sure to set this back to 0 if you decide to allow an AI to leave a mech somehow.
AI.can_shunt = 0 //ONE AI ENTERS. NO AI LEAVES.
to_chat(AI, AI.can_dominate_mechs ? "<span class='announce'>Takeover of [name] complete! You are now loaded onto the onboard computer. Do not attempt to leave the station sector!</span>" :\
"<span class='notice'>You have been uploaded to a mech's onboard computer.</span>")
@@ -927,7 +927,7 @@
brainmob.forceMove(src) //should allow relaymove
brainmob.reset_perspective(src)
brainmob.remote_control = src
brainmob.update_canmove()
brainmob.update_mobility()
brainmob.update_mouse_pointer()
icon_state = initial(icon_state)
update_icon()
@@ -941,7 +941,6 @@
/obj/mecha/container_resist(mob/living/user)
go_out()
/obj/mecha/Exited(atom/movable/M, atom/newloc)
if(occupant && occupant == M) // The occupant exited the mech without calling go_out()
go_out(TRUE, newloc)
@@ -993,7 +992,7 @@
L.reset_perspective()
mmi.mecha = null
mmi.update_icon()
L.canmove = 0
L.mobility_flags = NONE
icon_state = initial(icon_state)+"-open"
setDir(dir_in)
+1 -5
View File
@@ -320,11 +320,7 @@
clearInternalDamage(MECHA_INT_CONTROL_LOST)
/obj/mecha/narsie_act()
if(occupant)
var/mob/living/L = occupant
go_out(TRUE)
if(L)
L.narsie_act()
emp_act(EMP_HEAVY)
/obj/mecha/ratvar_act()
if((GLOB.ratvar_awakens || GLOB.clockwork_gateway_activated) && occupant)
-10
View File
@@ -45,16 +45,6 @@
..()
update_icon()
/obj/mecha/working/ripley/update_icon()
..()
var/datum/component/armor_plate/C = GetComponent(/datum/component/armor_plate)
if (C.amount)
cut_overlays()
if(C.amount < 3)
add_overlay(occupant ? "ripley-g" : "ripley-g-open")
else
add_overlay(occupant ? "ripley-g-full" : "ripley-g-full-open")
/obj/mecha/working/ripley/Initialize()
. = ..()
AddComponent(/datum/component/armor_plate,3,/obj/item/stack/sheet/animalhide/goliath_hide,list("melee" = 10, "bullet" = 5, "laser" = 5))
+3 -4
View File
@@ -36,8 +36,7 @@
//procs that handle the actual buckling and unbuckling
/atom/movable/proc/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE)
if(!buckled_mobs)
buckled_mobs = list()
LAZYINITLIST(buckled_mobs)
if(!istype(M))
return FALSE
@@ -66,7 +65,7 @@
M.buckled = src
M.setDir(dir)
buckled_mobs |= M
M.update_canmove()
M.update_mobility()
M.throw_alert("buckled", /obj/screen/alert/restrained/buckled)
post_buckle_mob(M)
@@ -85,7 +84,7 @@
. = buckled_mob
buckled_mob.buckled = null
buckled_mob.anchored = initial(buckled_mob.anchored)
buckled_mob.update_canmove()
buckled_mob.update_mobility()
buckled_mob.clear_alert("buckled")
buckled_mobs -= buckled_mob
SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force)

Some files were not shown because too many files have changed in this diff Show More