Merge remote-tracking branch 'upstream/master' into AnPrimAssistants
This commit is contained in:
@@ -312,6 +312,7 @@
|
||||
#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled)
|
||||
#define COMSIG_OBJ_BREAK "obj_break" //from base of /obj/obj_break(): (damage_flag)
|
||||
#define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value)
|
||||
#define COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH "obj_default_unfasten_wrench" //called exclusively in plumbing, for now
|
||||
#define COMSIG_OBJ_ATTACK_GENERIC "obj_attack_generic" //from base of atom/animal_attack(): (/mob/user)
|
||||
#define COMPONENT_STOP_GENERIC_ATTACK 1
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#define FIRST_DUCT_LAYER 1
|
||||
#define SECOND_DUCT_LAYER 2
|
||||
#define THIRD_DUCT_LAYER 4
|
||||
#define FOURTH_DUCT_LAYER 8
|
||||
#define FIFTH_DUCT_LAYER 16
|
||||
|
||||
#define DUCT_LAYER_DEFAULT THIRD_DUCT_LAYER
|
||||
|
||||
#define MACHINE_REAGENT_TRANSFER 10
|
||||
@@ -57,6 +57,10 @@
|
||||
#define ADD_REAGENT 2 // reagent added
|
||||
#define REM_REAGENT 3 // reagent removed (may still exist)
|
||||
|
||||
|
||||
#define PILL_STYLE_COUNT 22 //Update this if you add more pill icons or you die (literally, we'll toss a nuke at whever your ip turns up)
|
||||
#define RANDOM_PILL_STYLE 22 //Dont change this one though
|
||||
|
||||
#define THRESHOLD_UNHUSK 50 // health threshold for synthflesh/rezadone to unhusk someone
|
||||
|
||||
//reagent bitflags, used for altering how they works
|
||||
|
||||
@@ -146,11 +146,11 @@
|
||||
#define SSAIR_EQUALIZE 8
|
||||
#define SSAIR_ACTIVETURFS 9
|
||||
|
||||
// |= on overlays is not actually guaranteed to not add same appearances but we're optimistically using it anyway.
|
||||
#define COMPILE_OVERLAYS(A)\
|
||||
if (TRUE) {\
|
||||
var/list/ad = A.add_overlays;\
|
||||
var/list/rm = A.remove_overlays;\
|
||||
var/list/po = A.priority_overlays;\
|
||||
if(LAZYLEN(rm)){\
|
||||
A.overlays -= rm;\
|
||||
A.remove_overlays = null;\
|
||||
@@ -159,11 +159,5 @@
|
||||
A.overlays |= ad;\
|
||||
A.add_overlays = null;\
|
||||
}\
|
||||
if(LAZYLEN(po)){\
|
||||
A.overlays |= po;\
|
||||
}\
|
||||
else{\
|
||||
A.priority_overlays = null;\
|
||||
}\
|
||||
A.flags_1 &= ~OVERLAY_QUEUED_1;\
|
||||
}
|
||||
|
||||
@@ -122,13 +122,13 @@
|
||||
if(pixel_size == pixels)
|
||||
return
|
||||
pixel_size = pixels
|
||||
cut_overlays(TRUE)
|
||||
cut_overlays()
|
||||
//our icon size is 32 pixels.
|
||||
transform = matrix((pixels - (VOLUMETRIC_STORAGE_BOX_BORDER_SIZE * 2)) / VOLUMETRIC_STORAGE_BOX_ICON_SIZE, 0, 0, 0, 1, 0)
|
||||
left.pixel_x = -((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) - VOLUMETRIC_STORAGE_BOX_BORDER_SIZE
|
||||
right.pixel_x = ((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) + VOLUMETRIC_STORAGE_BOX_BORDER_SIZE
|
||||
add_overlay(left, TRUE)
|
||||
add_overlay(right, TRUE)
|
||||
add_overlay(left)
|
||||
add_overlay(right)
|
||||
|
||||
/obj/screen/storage/volumetric_edge
|
||||
layer = VOLUMETRIC_STORAGE_BOX_LAYER
|
||||
|
||||
@@ -29,7 +29,7 @@ SUBSYSTEM_DEF(acid)
|
||||
|
||||
if(O.acid_level && O.acid_processing())
|
||||
else
|
||||
O.cut_overlay(GLOB.acid_overlay, TRUE)
|
||||
O.update_icon()
|
||||
processing -= O
|
||||
|
||||
if (MC_TICK_CHECK)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
PROCESSING_SUBSYSTEM_DEF(fluids)
|
||||
name = "Fluids"
|
||||
wait = 20
|
||||
stat_tag = "FD" //its actually Fluid Ducts
|
||||
flags = SS_NO_INIT | SS_TICKER
|
||||
@@ -114,67 +114,47 @@ SUBSYSTEM_DEF(overlays)
|
||||
|
||||
#define NOT_QUEUED_ALREADY (!(flags_1 & OVERLAY_QUEUED_1))
|
||||
#define QUEUE_FOR_COMPILE flags_1 |= OVERLAY_QUEUED_1; SSoverlays.queue += src;
|
||||
/atom/proc/cut_overlays(priority = FALSE)
|
||||
LAZYINITLIST(priority_overlays)
|
||||
/atom/proc/cut_overlays()
|
||||
LAZYINITLIST(remove_overlays)
|
||||
LAZYINITLIST(add_overlays)
|
||||
remove_overlays = overlays.Copy()
|
||||
add_overlays.Cut()
|
||||
|
||||
if(priority)
|
||||
priority_overlays.Cut()
|
||||
|
||||
//If not already queued for work and there are overlays to remove
|
||||
if(NOT_QUEUED_ALREADY && remove_overlays.len)
|
||||
QUEUE_FOR_COMPILE
|
||||
|
||||
/atom/proc/cut_overlay(list/overlays, priority)
|
||||
/atom/proc/cut_overlay(list/overlays)
|
||||
if(!overlays)
|
||||
return
|
||||
overlays = build_appearance_list(overlays)
|
||||
LAZYINITLIST(add_overlays) //always initialized after this point
|
||||
LAZYINITLIST(priority_overlays)
|
||||
LAZYINITLIST(remove_overlays)
|
||||
var/a_len = add_overlays.len
|
||||
var/r_len = remove_overlays.len
|
||||
var/p_len = priority_overlays.len
|
||||
remove_overlays += overlays
|
||||
add_overlays -= overlays
|
||||
|
||||
|
||||
if(priority)
|
||||
var/list/cached_priority = priority_overlays
|
||||
LAZYREMOVE(cached_priority, overlays)
|
||||
|
||||
var/fa_len = add_overlays.len
|
||||
var/fr_len = remove_overlays.len
|
||||
var/fp_len = priority_overlays.len
|
||||
|
||||
//If not already queued and there is work to be done
|
||||
if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len || fp_len != p_len))
|
||||
if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len))
|
||||
QUEUE_FOR_COMPILE
|
||||
|
||||
/atom/proc/add_overlay(list/overlays, priority = FALSE)
|
||||
/atom/proc/add_overlay(list/overlays)
|
||||
if(!overlays)
|
||||
return
|
||||
|
||||
overlays = build_appearance_list(overlays)
|
||||
|
||||
LAZYINITLIST(add_overlays) //always initialized after this point
|
||||
LAZYINITLIST(priority_overlays)
|
||||
var/a_len = add_overlays.len
|
||||
var/p_len = priority_overlays.len
|
||||
|
||||
if(priority)
|
||||
priority_overlays += overlays //or in the image. Can we use [image] = image?
|
||||
var/fp_len = priority_overlays.len
|
||||
if(NOT_QUEUED_ALREADY && fp_len != p_len)
|
||||
QUEUE_FOR_COMPILE
|
||||
else
|
||||
add_overlays += overlays
|
||||
var/fa_len = add_overlays.len
|
||||
if(NOT_QUEUED_ALREADY && fa_len != a_len)
|
||||
QUEUE_FOR_COMPILE
|
||||
add_overlays += overlays
|
||||
var/fa_len = add_overlays.len
|
||||
if(NOT_QUEUED_ALREADY && fa_len != a_len)
|
||||
QUEUE_FOR_COMPILE
|
||||
|
||||
/atom/proc/copy_overlays(atom/other, cut_old) //copys our_overlays from another atom
|
||||
if(!other)
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
|
||||
/datum/action/proc/ApplyIcon(obj/screen/movable/action_button/current_button, force = FALSE)
|
||||
if(icon_icon && button_icon_state && ((current_button.button_icon_state != button_icon_state) || force))
|
||||
current_button.cut_overlays(TRUE)
|
||||
current_button.cut_overlays()
|
||||
current_button.add_overlay(mutable_appearance(icon_icon, button_icon_state))
|
||||
current_button.button_icon_state = button_icon_state
|
||||
|
||||
|
||||
@@ -40,13 +40,23 @@
|
||||
reqs = list(/obj/item/paper = 20)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/balaclavabreath
|
||||
name = "Breathaclava"
|
||||
result = /obj/item/clothing/mask/balaclava/breath
|
||||
time = 10
|
||||
reqs = list(/obj/item/clothing/mask/balaclava = 1,
|
||||
/obj/item/clothing/mask/breath = 1)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
|
||||
|
||||
/datum/crafting_recipe/armwraps
|
||||
name = "Armwraps"
|
||||
result = /obj/item/clothing/gloves/fingerless/pugilist
|
||||
time = 60
|
||||
tools = list(TOOL_WIRECUTTER)
|
||||
reqs = list(/obj/item/stack/sheet/cloth = 4,
|
||||
/obj/item/stack/sheet/durathread = 2,
|
||||
/obj/item/stack/sticky_tape = 2,
|
||||
/obj/item/stack/sheet/leather = 2)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
//Large Objects//
|
||||
/////////////////
|
||||
|
||||
/datum/crafting_recipe/plunger
|
||||
name = "Plunger"
|
||||
result = /obj/item/plunger
|
||||
time = 1
|
||||
reqs = list(/obj/item/stack/sheet/plastic = 1,
|
||||
/obj/item/stack/sheet/mineral/wood = 1)
|
||||
category = CAT_MISC
|
||||
subcategory = CAT_TOOL
|
||||
|
||||
/datum/crafting_recipe/showercurtain
|
||||
name = "Shower Curtains"
|
||||
reqs = list(/obj/item/stack/sheet/cloth = 2,
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
UnregisterSignal(weapon, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING))
|
||||
if(overlay)
|
||||
var/atom/A = parent
|
||||
A.cut_overlay(overlay, TRUE)
|
||||
UnregisterSignal(A,COMSIG_ATOM_UPDATE_OVERLAYS)
|
||||
qdel(overlay)
|
||||
|
||||
return ..()
|
||||
@@ -326,7 +326,8 @@
|
||||
var/matrix/M = matrix()
|
||||
M.Translate(pixelX, pixelY)
|
||||
overlay.transform = M
|
||||
hit.add_overlay(overlay, TRUE)
|
||||
RegisterSignal(hit,COMSIG_ATOM_UPDATE_OVERLAYS,.proc/apply_overlay)
|
||||
hit.update_icon()
|
||||
|
||||
if(harmful)
|
||||
hit.visible_message("<span class='danger'>[weapon] embeds itself in [hit]!</span>")
|
||||
@@ -339,6 +340,8 @@
|
||||
else
|
||||
hit.visible_message("<span class='danger'>[weapon] sticks itself to [hit]!</span>")
|
||||
|
||||
/datum/component/embedded/proc/apply_overlay(atom/source, list/overlay_list)
|
||||
overlay_list += overlay
|
||||
|
||||
/datum/component/embedded/proc/examineTurf(datum/source, mob/user, list/examine_list)
|
||||
if(harmful)
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
/datum/component/plumbing
|
||||
///Index with "1" = /datum/ductnet/theductpointingnorth etc. "1" being the num2text from NORTH define
|
||||
var/list/datum/ductnet/ducts = list()
|
||||
///shortcut to our parents' reagent holder
|
||||
var/datum/reagents/reagents
|
||||
///TRUE if we wanna add proper pipe outless under our parent object. this is pretty good if i may so so myself
|
||||
var/use_overlays = TRUE
|
||||
///We can't just cut all of the parents' overlays, so we'll track them here
|
||||
var/list/image/ducterlays
|
||||
///directions in wich we act as a supplier
|
||||
var/supply_connects
|
||||
///direction in wich we act as a demander
|
||||
var/demand_connects
|
||||
///FALSE to pretty much just not exist in the plumbing world so we can be moved, TRUE to go plumbo mode
|
||||
var/active = FALSE
|
||||
///if TRUE connects will spin with the parent object visually and codually, so you can have it work in any direction. FALSE if you want it to be static
|
||||
var/turn_connects = TRUE
|
||||
|
||||
/datum/component/plumbing/Initialize(start=TRUE, _turn_connects=TRUE) //turn_connects for wheter or not we spin with the object to change our pipes
|
||||
if(parent && !istype(parent, /atom/movable))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
var/atom/movable/AM = parent
|
||||
if(!AM.reagents)
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
reagents = AM.reagents
|
||||
turn_connects = _turn_connects
|
||||
|
||||
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED,COMSIG_PARENT_PREQDELETED), .proc/disable)
|
||||
RegisterSignal(parent, list(COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH), .proc/toggle_active)
|
||||
|
||||
if(start)
|
||||
enable()
|
||||
|
||||
if(use_overlays)
|
||||
create_overlays()
|
||||
|
||||
/datum/component/plumbing/process()
|
||||
if(!demand_connects || !reagents)
|
||||
STOP_PROCESSING(SSfluids, src)
|
||||
return
|
||||
if(reagents.total_volume < reagents.maximum_volume)
|
||||
for(var/D in GLOB.cardinals)
|
||||
if(D & demand_connects)
|
||||
send_request(D)
|
||||
///Can we be added to the ductnet?
|
||||
/datum/component/plumbing/proc/can_add(datum/ductnet/D, dir)
|
||||
if(!active)
|
||||
return
|
||||
if(!dir || !D)
|
||||
return FALSE
|
||||
if(num2text(dir) in ducts)
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
///called from in process(). only calls process_request(), but can be overwritten for children with special behaviour
|
||||
/datum/component/plumbing/proc/send_request(dir)
|
||||
process_request(amount = MACHINE_REAGENT_TRANSFER, reagent = null, dir = dir)
|
||||
///check who can give us what we want, and how many each of them will give us
|
||||
/datum/component/plumbing/proc/process_request(amount, reagent, dir)
|
||||
var/list/valid_suppliers = list()
|
||||
var/datum/ductnet/net
|
||||
if(!ducts.Find(num2text(dir)))
|
||||
return
|
||||
net = ducts[num2text(dir)]
|
||||
for(var/A in net.suppliers)
|
||||
var/datum/component/plumbing/supplier = A
|
||||
if(supplier.can_give(amount, reagent, net))
|
||||
valid_suppliers += supplier
|
||||
for(var/A in valid_suppliers)
|
||||
var/datum/component/plumbing/give = A
|
||||
give.transfer_to(src, amount / valid_suppliers.len, reagent, net)
|
||||
///returns TRUE when they can give the specified amount and reagent. called by process request
|
||||
/datum/component/plumbing/proc/can_give(amount, reagent, datum/ductnet/net)
|
||||
if(amount <= 0)
|
||||
return
|
||||
|
||||
if(reagent) //only asked for one type of reagent
|
||||
for(var/A in reagents.reagent_list)
|
||||
var/datum/reagent/R = A
|
||||
if(R.type == reagent)
|
||||
return TRUE
|
||||
else if(reagents.total_volume > 0) //take whatever
|
||||
return TRUE
|
||||
///this is where the reagent is actually transferred and is thus the finish point of our process()
|
||||
/datum/component/plumbing/proc/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net)
|
||||
if(!reagents || !target || !target.reagents)
|
||||
return FALSE
|
||||
if(reagent)
|
||||
reagents.trans_id_to(target.parent, reagent, amount)
|
||||
else
|
||||
reagents.trans_to(target.parent, amount)
|
||||
///We create our luxurious piping overlays/underlays, to indicate where we do what. only called once if use_overlays = TRUE in Initialize()
|
||||
/datum/component/plumbing/proc/create_overlays()
|
||||
var/atom/movable/AM = parent
|
||||
for(var/image/I in ducterlays)
|
||||
AM.overlays.Remove(I)
|
||||
qdel(I)
|
||||
ducterlays = list()
|
||||
for(var/D in GLOB.cardinals)
|
||||
var/color
|
||||
var/direction
|
||||
if(D & demand_connects)
|
||||
color = "red" //red because red is mean and it takes
|
||||
else if(D & supply_connects)
|
||||
color = "blue" //blue is nice and gives
|
||||
else
|
||||
continue
|
||||
var/image/I
|
||||
if(turn_connects)
|
||||
switch(D)
|
||||
if(NORTH)
|
||||
direction = "north"
|
||||
if(SOUTH)
|
||||
direction = "south"
|
||||
if(EAST)
|
||||
direction = "east"
|
||||
if(WEST)
|
||||
direction = "west"
|
||||
I = image('icons/obj/plumbing/plumbers.dmi', "[direction]-[color]", layer = AM.layer - 1)
|
||||
else
|
||||
I = image('icons/obj/plumbing/plumbers.dmi', color, layer = AM.layer - 1) //color is not color as in the var, it's just the name
|
||||
I.dir = D
|
||||
AM.add_overlay(I)
|
||||
ducterlays += I
|
||||
///we stop acting like a plumbing thing and disconnect if we are, so we can safely be moved and stuff
|
||||
/datum/component/plumbing/proc/disable()
|
||||
if(!active)
|
||||
return
|
||||
STOP_PROCESSING(SSfluids, src)
|
||||
for(var/A in ducts)
|
||||
var/datum/ductnet/D = ducts[A]
|
||||
D.remove_plumber(src)
|
||||
active = FALSE
|
||||
for(var/D in GLOB.cardinals)
|
||||
if(D & (demand_connects | supply_connects))
|
||||
for(var/obj/machinery/duct/duct in get_step(parent, D))
|
||||
duct.attempt_connect()
|
||||
|
||||
///settle wherever we are, and start behaving like a piece of plumbing
|
||||
/datum/component/plumbing/proc/enable()
|
||||
if(active)
|
||||
return
|
||||
update_dir()
|
||||
active = TRUE
|
||||
var/atom/movable/AM = parent
|
||||
for(var/obj/machinery/duct/D in AM.loc) //Destroy any ducts under us. Ducts also self destruct if placed under a plumbing machine. machines disable when they get moved
|
||||
if(D.anchored) //that should cover everything
|
||||
D.disconnect_duct()
|
||||
|
||||
if(demand_connects)
|
||||
START_PROCESSING(SSfluids, src)
|
||||
|
||||
for(var/D in GLOB.cardinals)
|
||||
if(D & (demand_connects | supply_connects))
|
||||
for(var/atom/movable/A in get_step(parent, D))
|
||||
if(istype(A, /obj/machinery/duct))
|
||||
var/obj/machinery/duct/duct = A
|
||||
duct.attempt_connect()
|
||||
else
|
||||
var/datum/component/plumbing/P = A.GetComponent(/datum/component/plumbing)
|
||||
if(P)
|
||||
direct_connect(P, D)
|
||||
|
||||
/// Toggle our machinery on or off. This is called by a hook from default_unfasten_wrench with anchored as only param, so we dont have to copypaste this on every object that can move
|
||||
/datum/component/plumbing/proc/toggle_active(obj/O, new_state)
|
||||
if(new_state)
|
||||
enable()
|
||||
else
|
||||
disable()
|
||||
/** We update our connects only when we settle down by taking our current and original direction to find our new connects
|
||||
* If someone wants it to fucking spin while connected to something go actually knock yourself out
|
||||
*/
|
||||
/datum/component/plumbing/proc/update_dir()
|
||||
if(!turn_connects)
|
||||
return
|
||||
var/atom/movable/AM = parent
|
||||
var/new_demand_connects
|
||||
var/new_supply_connects
|
||||
var/new_dir = AM.dir
|
||||
var/angle = 180 - dir2angle(new_dir)
|
||||
if(new_dir == SOUTH)
|
||||
demand_connects = initial(demand_connects)
|
||||
supply_connects = initial(supply_connects)
|
||||
else
|
||||
for(var/D in GLOB.cardinals)
|
||||
if(D & initial(demand_connects))
|
||||
new_demand_connects += turn(D, angle)
|
||||
if(D & initial(supply_connects))
|
||||
new_supply_connects += turn(D, angle)
|
||||
demand_connects = new_demand_connects
|
||||
supply_connects = new_supply_connects
|
||||
///Give the direction of a pipe, and it'll return wich direction it originally was when it's object pointed SOUTH
|
||||
/datum/component/plumbing/proc/get_original_direction(dir)
|
||||
var/atom/movable/AM = parent
|
||||
return turn(dir, dir2angle(AM.dir) - 180)
|
||||
//special case in-case we want to connect directly with another machine without a duct
|
||||
/datum/component/plumbing/proc/direct_connect(datum/component/plumbing/P, dir)
|
||||
if(!P.active)
|
||||
return
|
||||
var/opposite_dir = turn(dir, 180)
|
||||
if(P.demand_connects & opposite_dir && supply_connects & dir || P.supply_connects & opposite_dir && demand_connects & dir) //make sure we arent connecting two supplies or demands
|
||||
var/datum/ductnet/net = new()
|
||||
net.add_plumber(src, dir)
|
||||
net.add_plumber(P, opposite_dir)
|
||||
|
||||
///has one pipe input that only takes, example is manual output pipe
|
||||
/datum/component/plumbing/simple_demand
|
||||
demand_connects = NORTH
|
||||
///has one pipe output that only supplies. example is liquid pump and manual input pipe
|
||||
/datum/component/plumbing/simple_supply
|
||||
supply_connects = NORTH
|
||||
///input and output, like a holding tank
|
||||
/datum/component/plumbing/tank
|
||||
demand_connects = WEST
|
||||
supply_connects = EAST
|
||||
@@ -0,0 +1,21 @@
|
||||
/datum/component/plumbing/acclimator
|
||||
demand_connects = WEST
|
||||
supply_connects = EAST
|
||||
var/obj/machinery/plumbing/acclimator/AC
|
||||
|
||||
/datum/component/plumbing/acclimator/Initialize(start=TRUE, _turn_connects=TRUE)
|
||||
. = ..()
|
||||
if(!istype(parent, /obj/machinery/plumbing/acclimator))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
AC = parent
|
||||
|
||||
/datum/component/plumbing/acclimator/can_give(amount, reagent)
|
||||
. = ..()
|
||||
if(. && AC.emptying)
|
||||
return TRUE
|
||||
return FALSE
|
||||
///We're overriding process and not send_request, because all process does is do the requests, so we might aswell cut out the middle man and save some code from running
|
||||
/datum/component/plumbing/acclimator/process()
|
||||
if(AC.emptying)
|
||||
return
|
||||
. = ..()
|
||||
@@ -0,0 +1,59 @@
|
||||
///The magical plumbing component used by the chemical filters. The different supply connects behave differently depending on the filters set on the chemical filter
|
||||
/datum/component/plumbing/filter
|
||||
demand_connects = NORTH
|
||||
supply_connects = SOUTH | EAST | WEST //SOUTH is straight, EAST is left and WEST is right. We look from the perspective of the insert
|
||||
|
||||
/datum/component/plumbing/filter/Initialize()
|
||||
. = ..()
|
||||
if(!istype(parent, /obj/machinery/plumbing/filter))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
/datum/component/plumbing/filter/can_give(amount, reagent, datum/ductnet/net)
|
||||
. = ..()
|
||||
if(.)
|
||||
var/direction
|
||||
for(var/A in ducts)
|
||||
if(ducts[A] == net)
|
||||
direction = get_original_direction(text2num(A)) //we need it relative to the direction, so filters don't change when we turn the filter
|
||||
break
|
||||
if(!direction)
|
||||
return FALSE
|
||||
if(reagent)
|
||||
if(!can_give_in_direction(direction, reagent))
|
||||
return FALSE
|
||||
|
||||
/datum/component/plumbing/filter/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net)
|
||||
if(!reagents || !target || !target.reagents)
|
||||
return FALSE
|
||||
var/direction
|
||||
for(var/A in ducts)
|
||||
if(ducts[A] == net)
|
||||
direction = get_original_direction(text2num(A))
|
||||
break
|
||||
if(reagent)
|
||||
reagents.trans_id_to(target.parent, reagent, amount)
|
||||
else
|
||||
for(var/A in reagents.reagent_list)
|
||||
var/datum/reagent/R = A
|
||||
if(!can_give_in_direction(direction, R.type))
|
||||
continue
|
||||
var/new_amount
|
||||
if(R.volume < amount)
|
||||
new_amount = amount - R.volume
|
||||
reagents.trans_id_to(target.parent, R.type, amount)
|
||||
amount = new_amount
|
||||
if(amount <= 0)
|
||||
break
|
||||
///We check if the direction and reagent are valid to give. Needed for filters since different outputs have different behaviours
|
||||
/datum/component/plumbing/filter/proc/can_give_in_direction(dir, reagent)
|
||||
var/obj/machinery/plumbing/filter/F = parent
|
||||
switch(dir)
|
||||
if(SOUTH) //straight
|
||||
if(!F.left.Find(reagent) && !F.right.Find(reagent))
|
||||
return TRUE
|
||||
if(WEST) //right
|
||||
if(F.right.Find(reagent))
|
||||
return TRUE
|
||||
if(EAST) //left
|
||||
if(F.left.Find(reagent))
|
||||
return TRUE
|
||||
@@ -0,0 +1,38 @@
|
||||
/datum/component/plumbing/reaction_chamber
|
||||
demand_connects = WEST
|
||||
supply_connects = EAST
|
||||
|
||||
/datum/component/plumbing/reaction_chamber/Initialize(start=TRUE, _turn_connects=TRUE)
|
||||
. = ..()
|
||||
if(!istype(parent, /obj/machinery/plumbing/reaction_chamber))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
/datum/component/plumbing/reaction_chamber/can_give(amount, reagent, datum/ductnet/net)
|
||||
. = ..()
|
||||
var/obj/machinery/plumbing/reaction_chamber/RC = parent
|
||||
if(!. || !RC.emptying)
|
||||
return FALSE
|
||||
|
||||
/datum/component/plumbing/reaction_chamber/send_request(dir)
|
||||
var/obj/machinery/plumbing/reaction_chamber/RC = parent
|
||||
if(RC.emptying || !LAZYLEN(RC.required_reagents))
|
||||
return
|
||||
for(var/RT in RC.required_reagents)
|
||||
var/has_reagent = FALSE
|
||||
for(var/A in reagents.reagent_list)
|
||||
var/datum/reagent/RD = A
|
||||
if(RT == RD.type)
|
||||
has_reagent = TRUE
|
||||
if(RD.volume < RC.required_reagents[RT])
|
||||
process_request(min(RC.required_reagents[RT] - RD.volume, MACHINE_REAGENT_TRANSFER) , RT, dir)
|
||||
return
|
||||
if(!has_reagent)
|
||||
process_request(min(RC.required_reagents[RT], MACHINE_REAGENT_TRANSFER), RT, dir)
|
||||
return
|
||||
|
||||
RC.reagent_flags &= ~NO_REACT
|
||||
reagents.handle_reactions()
|
||||
|
||||
RC.emptying = TRUE //If we move this up, it'll instantly get turned off since any reaction always sets the reagent_total to zero. Other option is make the reaction update
|
||||
//everything for every chemical removed, wich isn't a good option either.
|
||||
RC.on_reagent_change() //We need to check it now, because some reactions leave nothing left.
|
||||
@@ -0,0 +1,45 @@
|
||||
/datum/component/plumbing/splitter
|
||||
demand_connects = NORTH
|
||||
supply_connects = SOUTH | EAST
|
||||
|
||||
/datum/component/plumbing/splitter/Initialize()
|
||||
. = ..()
|
||||
if(. && !istype(parent, /obj/machinery/plumbing/splitter))
|
||||
return FALSE
|
||||
|
||||
/datum/component/plumbing/splitter/can_give(amount, reagent, datum/ductnet/net)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
. = FALSE
|
||||
var/direction
|
||||
for(var/A in ducts)
|
||||
if(ducts[A] == net)
|
||||
direction = get_original_direction(text2num(A))
|
||||
break
|
||||
var/obj/machinery/plumbing/splitter/S = parent
|
||||
switch(direction)
|
||||
if(SOUTH)
|
||||
if(S.turn_straight && S.transfer_straight <= amount)
|
||||
S.turn_straight = FALSE
|
||||
return TRUE
|
||||
if(EAST)
|
||||
if(!S.turn_straight && S.transfer_side <= amount)
|
||||
S.turn_straight = TRUE
|
||||
return TRUE
|
||||
|
||||
/datum/component/plumbing/splitter/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net)
|
||||
var/direction
|
||||
for(var/A in ducts)
|
||||
if(ducts[A] == net)
|
||||
direction = get_original_direction(text2num(A))
|
||||
break
|
||||
var/obj/machinery/plumbing/splitter/S = parent
|
||||
switch(direction)
|
||||
if(SOUTH)
|
||||
if(amount >= S.transfer_straight)
|
||||
amount = S.transfer_straight
|
||||
if(EAST)
|
||||
if(amount >= S.transfer_side)
|
||||
amount = S.transfer_side
|
||||
. = ..()
|
||||
@@ -14,6 +14,7 @@
|
||||
var/mob/living/holder //who is currently benefiting from the shield.
|
||||
var/dissipating = FALSE //Is this shield meant to dissipate over time instead of recharging.
|
||||
var/del_on_overload = FALSE //will delete itself once it has no charges left.
|
||||
var/cached_vis_overlay //text identifier of the visual overlay.
|
||||
|
||||
/datum/component/shielded/Initialize(current, max = 3, delay = 20 SECONDS, rate = 1, slots, state = "shield-old", broken, \
|
||||
sound = 'sound/magic/charge.ogg', end_sound = 'sound/machines/ding.ogg', diss = FALSE, del_overload = FALSE)
|
||||
@@ -47,9 +48,8 @@
|
||||
holder = L
|
||||
var/to_add = charges >= 1 ? shield_state : broken_state
|
||||
if(to_add)
|
||||
var/mutable_appearance/M = mutable_appearance('icons/effects/effects.dmi', to_add)
|
||||
M.layer = (L.layer > MOB_LAYER ? L.layer : MOB_LAYER) + 0.01
|
||||
holder.add_overlay(M, TRUE)
|
||||
var/layer = (L.layer > MOB_LAYER ? L.layer : MOB_LAYER) + 0.01
|
||||
SSvis_overlays.add_vis_overlay(L, 'icons/effects/effects.dmi', to_add, layer, GAME_PLANE, L.dir)
|
||||
|
||||
/datum/component/shielded/UnregisterFromParent()
|
||||
. = ..()
|
||||
@@ -57,9 +57,9 @@
|
||||
UnregisterSignal(parent, list(COMSIG_ITEM_RUN_BLOCK,COMSIG_ITEM_CHECK_BLOCK,COMSIG_ITEM_EQUIPPED,COMSIG_ITEM_DROPPED))
|
||||
if(holder)
|
||||
UnregisterSignal(holder, list(COMSIG_LIVING_RUN_BLOCK, COMSIG_LIVING_GET_BLOCKING_ITEMS))
|
||||
var/to_remove = charges >= 1 ? shield_state : broken_state
|
||||
if(to_remove)
|
||||
holder.cut_overlay(mutable_appearance('icons/effects/effects.dmi', to_remove), TRUE)
|
||||
if(cached_vis_overlay)
|
||||
SSvis_overlays.remove_vis_overlay(holder, cached_vis_overlay)
|
||||
cached_vis_overlay = null
|
||||
holder = null
|
||||
|
||||
/datum/component/shielded/process()
|
||||
@@ -80,7 +80,7 @@
|
||||
holder.visible_message("[holder]'s shield overloads!")
|
||||
qdel(src)
|
||||
return
|
||||
if(holder && (old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1))
|
||||
if(holder && ((old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1)))
|
||||
update_shield_overlay(charges < 1)
|
||||
|
||||
/datum/component/shielded/proc/adjust_charges(amount)
|
||||
@@ -93,20 +93,19 @@
|
||||
holder.visible_message("[holder]'s shield overloads!")
|
||||
qdel(src)
|
||||
return
|
||||
if(holder && (old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1))
|
||||
if(holder && ((old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1)))
|
||||
update_shield_overlay(charges < 1)
|
||||
|
||||
/datum/component/shielded/proc/update_shield_overlay(broken)
|
||||
if(!holder)
|
||||
return
|
||||
var/to_remove = broken ? shield_state : broken_state
|
||||
var/to_add = broken ? broken_state : shield_state
|
||||
if(to_remove)
|
||||
holder.cut_overlay(mutable_appearance('icons/effects/effects.dmi', to_remove), TRUE)
|
||||
if(cached_vis_overlay)
|
||||
SSvis_overlays.remove_vis_overlay(holder, cached_vis_overlay)
|
||||
cached_vis_overlay = null
|
||||
if(to_add)
|
||||
var/mutable_appearance/M = mutable_appearance('icons/effects/effects.dmi', to_add)
|
||||
M.layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01
|
||||
holder.add_overlay(M, TRUE)
|
||||
var/layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01
|
||||
SSvis_overlays.add_vis_overlay(holder, 'icons/effects/effects.dmi', to_add, layer, GAME_PLANE, holder.dir)
|
||||
|
||||
/datum/component/shielded/proc/on_equip(obj/item/source, mob/living/equipper, slot)
|
||||
if(!(accepted_slots & slotdefine2slotbit(slot)))
|
||||
@@ -117,17 +116,16 @@
|
||||
RegisterSignal(equipper, COMSIG_LIVING_GET_BLOCKING_ITEMS, .proc/include_shield)
|
||||
var/to_add = charges >= 1 ? shield_state : broken_state
|
||||
if(to_add)
|
||||
var/mutable_appearance/M = mutable_appearance('icons/effects/effects.dmi', to_add)
|
||||
M.layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01
|
||||
equipper.add_overlay(M, TRUE)
|
||||
var/layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01
|
||||
cached_vis_overlay = SSvis_overlays.add_vis_overlay(holder, 'icons/effects/effects.dmi', to_add, layer, GAME_PLANE, holder.dir)
|
||||
|
||||
/datum/component/shielded/proc/on_drop(obj/item/source, mob/dropper)
|
||||
if(holder == dropper)
|
||||
UnregisterSignal(holder, COMSIG_LIVING_GET_BLOCKING_ITEMS)
|
||||
UnregisterSignal(parent, list(COMSIG_ITEM_RUN_BLOCK, COMSIG_ITEM_CHECK_BLOCK))
|
||||
var/to_remove = charges >= 1 ? shield_state : broken_state
|
||||
if(to_remove)
|
||||
holder.cut_overlay(mutable_appearance('icons/effects/effects.dmi', to_remove), TRUE)
|
||||
if(cached_vis_overlay)
|
||||
SSvis_overlays.remove_vis_overlay(holder, cached_vis_overlay)
|
||||
cached_vis_overlay = null
|
||||
holder = null
|
||||
|
||||
/datum/component/shielded/proc/include_shield(mob/source, list/items)
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
///We handle the unity part of plumbing. We track who is connected to who.
|
||||
/datum/ductnet
|
||||
var/list/suppliers = list()
|
||||
var/list/demanders = list()
|
||||
var/list/obj/machinery/duct/ducts = list()
|
||||
|
||||
var/capacity
|
||||
///Add a duct to our network
|
||||
/datum/ductnet/proc/add_duct(obj/machinery/duct/D)
|
||||
if(!D || (D in ducts))
|
||||
return
|
||||
ducts += D
|
||||
D.duct = src
|
||||
///Remove a duct from our network and commit suicide, because this is probably easier than to check who that duct was connected to and what part of us was lost
|
||||
/datum/ductnet/proc/remove_duct(obj/machinery/duct/ducting)
|
||||
destroy_network(FALSE)
|
||||
for(var/obj/machinery/duct/D in ducting.neighbours)
|
||||
addtimer(CALLBACK(D, /obj/machinery/duct/proc/reconnect), 0) //all needs to happen after the original duct that was destroyed finishes destroying itself
|
||||
addtimer(CALLBACK(D, /obj/machinery/duct/proc/generate_connects), 0)
|
||||
qdel(src)
|
||||
///add a plumbing object to either demanders or suppliers
|
||||
/datum/ductnet/proc/add_plumber(datum/component/plumbing/P, dir)
|
||||
if(!P.can_add(src, dir))
|
||||
return FALSE
|
||||
P.ducts[num2text(dir)] = src
|
||||
if(dir & P.supply_connects)
|
||||
suppliers += P
|
||||
else if(dir & P.demand_connects)
|
||||
demanders += P
|
||||
return TRUE
|
||||
///remove a plumber. we dont delete ourselves because ductnets dont persist through plumbing objects
|
||||
/datum/ductnet/proc/remove_plumber(datum/component/plumbing/P)
|
||||
suppliers.Remove(P) //we're probably only in one of these, but Remove() is inherently sane so this is fine
|
||||
demanders.Remove(P)
|
||||
|
||||
for(var/dir in P.ducts)
|
||||
if(P.ducts[dir] == src)
|
||||
P.ducts -= dir
|
||||
if(!ducts.len) //there were no ducts, so it was a direct connection. we destroy ourselves since a ductnet with only one plumber and no ducts is worthless
|
||||
destroy_network()
|
||||
///we combine ductnets. this occurs when someone connects to seperate sets of fluid ducts
|
||||
/datum/ductnet/proc/assimilate(datum/ductnet/D)
|
||||
ducts.Add(D.ducts)
|
||||
suppliers.Add(D.suppliers)
|
||||
demanders.Add(D.demanders)
|
||||
for(var/A in D.suppliers + D.demanders)
|
||||
var/datum/component/plumbing/P = A
|
||||
for(var/s in P.ducts)
|
||||
if(P.ducts[s] != D)
|
||||
continue
|
||||
P.ducts[s] = src //all your ducts are belong to us
|
||||
for(var/A in D.ducts)
|
||||
var/obj/machinery/duct/M = A
|
||||
M.duct = src //forget your old master
|
||||
|
||||
destroy_network()
|
||||
///destroy the network and tell all our ducts and plumbers we are gone
|
||||
/datum/ductnet/proc/destroy_network(delete=TRUE)
|
||||
for(var/A in suppliers + demanders)
|
||||
remove_plumber(A)
|
||||
for(var/A in ducts)
|
||||
var/obj/machinery/duct/D = A
|
||||
D.duct = null
|
||||
if(delete) //I don't want code to run with qdeleted objects because that can never be good, so keep this in-case the ductnet has some business left to attend to before commiting suicide
|
||||
qdel(src)
|
||||
@@ -33,39 +33,34 @@
|
||||
if(description)
|
||||
RegisterSignal(A, COMSIG_PARENT_EXAMINE, .proc/examine)
|
||||
|
||||
apply(A, TRUE)
|
||||
|
||||
num_decals_per_atom[A]++
|
||||
apply(A)
|
||||
|
||||
/datum/element/decal/Detach(datum/target)
|
||||
var/atom/A = target
|
||||
remove(A, A.dir)
|
||||
UnregisterSignal(A, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE))
|
||||
LAZYREMOVE(num_decals_per_atom, A)
|
||||
num_decals_per_atom[A]--
|
||||
apply(A, TRUE)
|
||||
if(!num_decals_per_atom[A])
|
||||
UnregisterSignal(A, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE, COMSIG_ATOM_UPDATE_OVERLAYS))
|
||||
LAZYREMOVE(num_decals_per_atom, A)
|
||||
return ..()
|
||||
|
||||
/datum/element/decal/proc/remove(atom/target, old_dir)
|
||||
pic.dir = first_dir == NORTH ? target.dir : turn(first_dir, dir2angle(old_dir))
|
||||
for(var/i in 1 to num_decals_per_atom[target])
|
||||
target.cut_overlay(pic, TRUE)
|
||||
/datum/element/decal/proc/apply(atom/target, removing = FALSE)
|
||||
if(num_decals_per_atom[target] == 1 && !removing)
|
||||
RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/apply_overlay, TRUE)
|
||||
target.update_icon()
|
||||
if(isitem(target))
|
||||
addtimer(CALLBACK(target, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
|
||||
|
||||
/datum/element/decal/proc/apply(atom/target, init = FALSE)
|
||||
pic.dir = first_dir == NORTH ? target.dir : turn(first_dir, dir2angle(target.dir))
|
||||
if(init)
|
||||
target.add_overlay(pic, TRUE)
|
||||
else
|
||||
for(var/i in 1 to num_decals_per_atom[target])
|
||||
target.add_overlay(pic, TRUE)
|
||||
if(isitem(target))
|
||||
addtimer(CALLBACK(target, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
|
||||
/datum/element/decal/proc/apply_overlay(atom/source, list/overlay_list)
|
||||
pic.dir = first_dir == NORTH ? source.dir : turn(first_dir, dir2angle(source.dir))
|
||||
for(var/i in 1 to num_decals_per_atom[source])
|
||||
overlay_list += pic
|
||||
|
||||
/datum/element/decal/proc/rotate_react(datum/source, old_dir, new_dir)
|
||||
/datum/element/decal/proc/rotate_react(atom/source, old_dir, new_dir)
|
||||
if(old_dir == new_dir)
|
||||
return
|
||||
remove(source, old_dir)
|
||||
apply(source)
|
||||
source.update_icon()
|
||||
|
||||
/datum/element/decal/proc/clean_react(datum/source, strength)
|
||||
if(strength >= cleanable)
|
||||
|
||||
+1
-3
@@ -26,7 +26,6 @@
|
||||
var/list/atom_colours //used to store the different colors on an atom
|
||||
//its inherent color, the colored paint applied on it, special color effect etc...
|
||||
|
||||
var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4.
|
||||
var/list/remove_overlays // a very temporary list of overlays to remove
|
||||
var/list/add_overlays // a very temporary list of overlays to add
|
||||
|
||||
@@ -145,7 +144,6 @@
|
||||
qdel(reagents)
|
||||
|
||||
LAZYCLEARLIST(overlays)
|
||||
LAZYCLEARLIST(priority_overlays)
|
||||
|
||||
for(var/i in targeted_by)
|
||||
var/mob/M = i
|
||||
@@ -1128,4 +1126,4 @@
|
||||
* Override this if you want custom behaviour in whatever gets hit by the rust
|
||||
*/
|
||||
/atom/proc/rust_heretic_act()
|
||||
return
|
||||
return
|
||||
|
||||
@@ -646,3 +646,10 @@
|
||||
animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING)
|
||||
sleep(1)
|
||||
animate(I, alpha = 0, transform = matrix(), time = 1)
|
||||
|
||||
/atom/movable/proc/set_anchored(anchorvalue) //literally only for plumbing ran
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(anchored == anchorvalue)
|
||||
return
|
||||
. = anchored
|
||||
anchored = anchorvalue
|
||||
|
||||
@@ -50,10 +50,6 @@ Property weights are:
|
||||
for(var/r in SSevents.running)
|
||||
var/datum/round_event/R = r
|
||||
threat += R.threat()
|
||||
for(var/mob/living/simple_animal/hostile/H in GLOB.mob_living_list)
|
||||
var/turf/T = get_turf(H)
|
||||
if(H.stat != DEAD && is_station_level(T.z) && !("Station" in H.faction))
|
||||
threat += H.threat()
|
||||
for(var/obj/item/phylactery/P in GLOB.poi_list)
|
||||
threat += 25 // can't be giving them too much of a break
|
||||
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
|
||||
@@ -91,6 +87,8 @@ Property weights are:
|
||||
mean += 2.5
|
||||
if(CHAOS_MAX)
|
||||
mean += 5
|
||||
else
|
||||
voters += 0.5
|
||||
if(voters)
|
||||
GLOB.dynamic_curve_centre += (mean/voters)
|
||||
if(flags & USE_PREV_ROUND_WEIGHTS)
|
||||
@@ -128,7 +126,8 @@ Property weights are:
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights) // just treat it as 0 if it's not in there
|
||||
property_weight += rule.property_weights[property] * property_weights[property]
|
||||
drafted_rules[rule] = (rule.get_weight() * property_weight)*rule.weight_mult
|
||||
if(property_weight > 0)
|
||||
drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/proc/midround_draft()
|
||||
@@ -140,25 +139,26 @@ Property weights are:
|
||||
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
|
||||
continue
|
||||
rule.trim_candidates()
|
||||
var/threat_weight = 1
|
||||
if(!(rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway
|
||||
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
|
||||
/* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to
|
||||
pick this particular ruleset.
|
||||
Let's use a toy example: there's 60 threat level and 10 threat spent.
|
||||
We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets.
|
||||
Ruleset 1 has 30 cost, ruleset 2 has 5 cost.
|
||||
When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1
|
||||
is 2.26 times as likely to be picked, all other things considered.
|
||||
Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight.
|
||||
*/
|
||||
threat_weight = abs(1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
|
||||
if (rule.ready())
|
||||
var/property_weight = 0
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights)
|
||||
if(property in rule.property_weights) // just treat it as 0 if it's not in there
|
||||
property_weight += rule.property_weights[property] * property_weights[property]
|
||||
drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1)
|
||||
if(property_weight > 0)
|
||||
var/threat_weight = 1
|
||||
if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway
|
||||
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
|
||||
/* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to
|
||||
pick this particular ruleset.
|
||||
Let's use a toy example: there's 60 threat level and 10 threat spent.
|
||||
We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets.
|
||||
Ruleset 1 has 30 cost, ruleset 2 has 5 cost.
|
||||
When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1
|
||||
is 2.26 times as likely to be picked, all other things considered.
|
||||
Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight.
|
||||
*/
|
||||
threat_weight = abs(1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
|
||||
drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult * threat_weight
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/proc/latejoin_draft(mob/living/carbon/human/newPlayer)
|
||||
@@ -175,28 +175,29 @@ Property weights are:
|
||||
|
||||
rule.candidates = list(newPlayer)
|
||||
rule.trim_candidates()
|
||||
var/threat_weight = 1
|
||||
if(!(rule.flags & MINOR_RULESET))
|
||||
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
|
||||
threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
|
||||
if (rule.ready())
|
||||
var/property_weight = 0
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights)
|
||||
property_weight += rule.property_weights[property] * property_weights[property]
|
||||
drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1)
|
||||
if(property_weight > 0)
|
||||
var/threat_weight = 1
|
||||
if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET))
|
||||
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
|
||||
threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
|
||||
drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult * threat_weight
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/proc/event_draft()
|
||||
var/list/drafted_rules = list()
|
||||
for(var/datum/dynamic_ruleset/event/rule in mode.events)
|
||||
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && (mode.threat_level - mode.threat) >= rule.cost)
|
||||
if(rule.ready())
|
||||
var/property_weight = 0
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights)
|
||||
property_weight += rule.property_weights[property] * property_weights[property]
|
||||
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
|
||||
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && (mode.threat_level + 20 - mode.threat) >= rule.cost && rule.ready())
|
||||
var/property_weight = 0
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights)
|
||||
property_weight += rule.property_weights[property] * property_weights[property]
|
||||
if(property_weight > 0)
|
||||
drafted_rules[rule] = rule.get_weight() + property_weight * rule.weight_mult
|
||||
return drafted_rules
|
||||
|
||||
|
||||
@@ -313,9 +314,8 @@ Property weights are:
|
||||
/datum/dynamic_storyteller/random/event_draft()
|
||||
var/list/drafted_rules = list()
|
||||
for(var/datum/dynamic_ruleset/event/rule in mode.events)
|
||||
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
|
||||
if(rule.ready())
|
||||
drafted_rules[rule] = 1
|
||||
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && rule.ready())
|
||||
drafted_rules[rule] = 1
|
||||
return drafted_rules
|
||||
|
||||
/datum/dynamic_storyteller/story
|
||||
@@ -330,7 +330,7 @@ Property weights are:
|
||||
|
||||
/datum/dynamic_storyteller/story/calculate_threat()
|
||||
var/current_time = (world.time / SSautotransfer.targettime)*180
|
||||
mode.threat_level = round(mode.initial_threat_level*(sin(current_time)+0.25),0.1)
|
||||
mode.threat_level = round((mode.initial_threat_level*(sin(current_time)/2)+0.75),0.1)
|
||||
return ..()
|
||||
|
||||
/datum/dynamic_storyteller/classic
|
||||
|
||||
@@ -117,6 +117,7 @@ Class Procs:
|
||||
var/new_occupant_dir = SOUTH //The direction the occupant will be set to look at when entering the machine.
|
||||
var/speed_process = FALSE // Process as fast as possible?
|
||||
var/obj/item/circuitboard/circuit // Circuit to be created and inserted when the machinery is created
|
||||
var/wire_compatible = FALSE
|
||||
// For storing and overriding ui id and dimensions
|
||||
var/tgui_id // ID of TGUI interface
|
||||
var/ui_style // ID of custom TGUI style (optional)
|
||||
@@ -433,6 +434,7 @@ Class Procs:
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [src].</span>")
|
||||
setAnchored(!anchored)
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
SEND_SIGNAL(src, COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH, anchored)
|
||||
return SUCCESSFUL_UNFASTEN
|
||||
return FAILED_UNFASTEN
|
||||
return CANT_UNFASTEN
|
||||
|
||||
@@ -135,6 +135,14 @@ RLD
|
||||
flick("[icon_state]_empty", src) //somewhat hacky thing to make RCDs with ammo counters actually have a blinking yellow light
|
||||
return .
|
||||
|
||||
|
||||
/obj/item/construction/proc/check_menu(mob/living/user)
|
||||
if(!istype(user))
|
||||
return FALSE
|
||||
if(user.incapacitated() || !user.Adjacent(src))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/construction/proc/range_check(atom/A, mob/user)
|
||||
if(!(A in range(custom_range, get_turf(user))))
|
||||
to_chat(user, "<span class='warning'>The \'Out of Range\' light on [src] blinks red.</span>")
|
||||
@@ -276,13 +284,6 @@ RLD
|
||||
//Not scaling these down to button size because they look horrible then, instead just bumping up radius.
|
||||
return MA
|
||||
|
||||
/obj/item/construction/rcd/proc/check_menu(mob/living/user)
|
||||
if(!istype(user))
|
||||
return FALSE
|
||||
if(user.incapacitated() || !user.Adjacent(src))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/construction/rcd/proc/change_computer_dir(mob/user)
|
||||
if(!user)
|
||||
return
|
||||
@@ -856,6 +857,82 @@ RLD
|
||||
desc = "It contains the design for firelock, air alarm, fire alarm, apc circuits and crap power cells."
|
||||
upgrade = RCD_UPGRADE_SIMPLE_CIRCUITS
|
||||
|
||||
/obj/item/construction/plumbing
|
||||
name = "Plumbing Constructor"
|
||||
desc = "An expertly modified RCD outfitted to construct plumbing machinery. Reload with compressed matter cartridges."
|
||||
icon = 'icons/obj/tools.dmi'
|
||||
icon_state = "arcd"
|
||||
item_state = "oldrcd"
|
||||
has_ammobar = FALSE
|
||||
matter = 200
|
||||
max_matter = 200
|
||||
|
||||
///type of the plumbing machine
|
||||
var/blueprint = null
|
||||
///index, used in the attack self to get the type. stored here since it doesnt change
|
||||
var/list/choices = list()
|
||||
///index, used in the attack self to get the type. stored here since it doesnt change
|
||||
var/list/name_to_type = list()
|
||||
///
|
||||
var/list/machinery_data = list("cost" = list(), "delay" = list())
|
||||
|
||||
/obj/item/construction/plumbing/attack_self(mob/user)
|
||||
..()
|
||||
if(!choices.len)
|
||||
for(var/A in subtypesof(/obj/machinery/plumbing))
|
||||
var/obj/machinery/plumbing/M = A
|
||||
if(initial(M.rcd_constructable))
|
||||
choices += list(initial(M.name) = image(icon = initial(M.icon), icon_state = initial(M.icon_state)))
|
||||
name_to_type[initial(M.name)] = M
|
||||
machinery_data["cost"][A] = initial(M.rcd_cost)
|
||||
machinery_data["delay"][A] = initial(M.rcd_delay)
|
||||
|
||||
var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE)
|
||||
if(!check_menu(user))
|
||||
return
|
||||
|
||||
blueprint = name_to_type[choice]
|
||||
playsound(src, 'sound/effects/pop.ogg', 50, FALSE)
|
||||
to_chat(user, "<span class='notice'>You change [name]s blueprint to '[choice]'.</span>")
|
||||
|
||||
///pretty much rcd_create, but named differently to make myself feel less bad for copypasting from a sibling-type
|
||||
/obj/item/construction/plumbing/proc/create_machine(atom/A, mob/user)
|
||||
if(!machinery_data || !isopenturf(A))
|
||||
return FALSE
|
||||
|
||||
if(checkResource(machinery_data["cost"][blueprint], user) && blueprint)
|
||||
if(do_after(user, machinery_data["delay"][blueprint], target = A))
|
||||
if(checkResource(machinery_data["cost"][blueprint], user) && canPlace(A))
|
||||
useResource(machinery_data["cost"][blueprint], user)
|
||||
activate()
|
||||
playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE)
|
||||
new blueprint (A, FALSE, FALSE)
|
||||
return TRUE
|
||||
|
||||
/obj/item/construction/plumbing/proc/canPlace(turf/T)
|
||||
if(!isopenturf(T))
|
||||
return FALSE
|
||||
. = TRUE
|
||||
for(var/obj/O in T.contents)
|
||||
if(O.density) //let's not built ontop of dense stuff, like big machines and other obstacles, it kills my immershion
|
||||
return FALSE
|
||||
|
||||
/obj/item/construction/plumbing/afterattack(atom/A, mob/user)
|
||||
. = ..()
|
||||
if(!range_check(A, user))
|
||||
return
|
||||
if(istype(A, /obj/machinery/plumbing))
|
||||
var/obj/machinery/plumbing/P = A
|
||||
if(P.anchored)
|
||||
to_chat(user, "<span class='warning'>The [P.name] needs to be unanchored!</span>")
|
||||
return
|
||||
if(do_after(user, 20, target = P))
|
||||
P.deconstruct() //Let's not substract matter
|
||||
playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE) //this is just such a great sound effect
|
||||
else
|
||||
create_machine(A, user)
|
||||
|
||||
|
||||
#undef GLOW_MODE
|
||||
#undef LIGHT_MODE
|
||||
#undef REMOVE_MODE
|
||||
|
||||
@@ -6,6 +6,7 @@ RPD
|
||||
#define ATMOS_CATEGORY 0
|
||||
#define DISPOSALS_CATEGORY 1
|
||||
#define TRANSIT_CATEGORY 2
|
||||
#define PLUMBING_CATEGORY 3
|
||||
|
||||
#define BUILD_MODE (1<<0)
|
||||
#define WRENCH_MODE (1<<1)
|
||||
@@ -75,6 +76,13 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
)
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(fluid_duct_recipes, list(
|
||||
"Fluid Ducts" = list(
|
||||
new /datum/pipe_info/plumbing("Duct", /obj/machinery/duct, PIPE_ONEDIR),
|
||||
new /datum/pipe_info/plumbing/multilayer("Duct Layer-Manifold",/obj/machinery/duct/multilayered, PIPE_STRAIGHT)
|
||||
)
|
||||
))
|
||||
|
||||
/datum/pipe_info
|
||||
var/name
|
||||
var/icon_state
|
||||
@@ -175,6 +183,15 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
if(dt == PIPE_UNARY_FLIPPABLE)
|
||||
icon_state = "[icon_state]_preview"
|
||||
|
||||
/datum/pipe_info/plumbing/New(label, obj/path, dt=PIPE_UNARY)
|
||||
name = label
|
||||
id = path
|
||||
icon_state = initial(path.icon_state)
|
||||
dirtype = dt
|
||||
|
||||
/datum/pipe_info/plumbing/multilayer //exists as identifier so we can see the difference between multi_layer and just ducts properly later on
|
||||
|
||||
|
||||
/obj/item/pipe_dispenser
|
||||
name = "Rapid Piping Device (RPD)"
|
||||
desc = "A device used to rapidly pipe things."
|
||||
@@ -200,15 +217,19 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
var/atmos_build_speed = 5 //deciseconds (500ms)
|
||||
var/disposal_build_speed = 5
|
||||
var/transit_build_speed = 5
|
||||
var/plumbing_build_speed = 5
|
||||
var/destroy_speed = 5
|
||||
var/paint_speed = 5
|
||||
var/category = ATMOS_CATEGORY
|
||||
var/piping_layer = PIPING_LAYER_DEFAULT
|
||||
var/ducting_layer = DUCT_LAYER_DEFAULT
|
||||
var/datum/pipe_info/recipe
|
||||
var/static/datum/pipe_info/first_atmos
|
||||
var/static/datum/pipe_info/first_disposal
|
||||
var/static/datum/pipe_info/first_transit
|
||||
var/mode = BUILD_MODE | DESTROY_MODE | WRENCH_MODE
|
||||
var/static/datum/pipe_info/first_plumbing
|
||||
var/locked = FALSE //wheter we can change categories. Useful for the plumber
|
||||
|
||||
/obj/item/pipe_dispenser/New()
|
||||
. = ..()
|
||||
@@ -253,12 +274,15 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
var/list/data = list(
|
||||
"category" = category,
|
||||
"piping_layer" = piping_layer,
|
||||
// "ducting_layer" = ducting_layer, //uhh is this for chem thing?
|
||||
|
||||
"ducting_layer" = ducting_layer,
|
||||
|
||||
"preview_rows" = recipe.get_preview(p_dir),
|
||||
"categories" = list(),
|
||||
"selected_color" = paint_color,
|
||||
"paint_colors" = GLOB.pipe_paint_colors,
|
||||
"mode" = mode
|
||||
"mode" = mode,
|
||||
"locked" = locked
|
||||
)
|
||||
|
||||
var/list/recipes
|
||||
@@ -269,6 +293,8 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
recipes = GLOB.disposal_pipe_recipes
|
||||
if(TRANSIT_CATEGORY)
|
||||
recipes = GLOB.transit_tube_recipes
|
||||
if(PLUMBING_CATEGORY)
|
||||
recipes = GLOB.fluid_duct_recipes
|
||||
for(var/c in recipes)
|
||||
var/list/cat = recipes[c]
|
||||
var/list/r = list()
|
||||
@@ -297,6 +323,8 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
recipe = first_atmos
|
||||
if(TRANSIT_CATEGORY)
|
||||
recipe = first_transit
|
||||
if(PLUMBING_CATEGORY)
|
||||
recipe = first_plumbing
|
||||
p_dir = NORTH
|
||||
playeffect = FALSE
|
||||
if("piping_layer")
|
||||
@@ -468,16 +496,56 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
if(mode & WRENCH_MODE)
|
||||
tube.wrench_act(user, src)
|
||||
return
|
||||
|
||||
if(PLUMBING_CATEGORY) //Plumbing.
|
||||
if(!can_make_pipe)
|
||||
return ..()
|
||||
A = get_turf(A)
|
||||
if(isclosedturf(A))
|
||||
to_chat(user, "<span class='warning'>[src]'s error light flickers; there's something in the way!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start building a fluid duct...</span>")
|
||||
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
|
||||
if(do_after(user, plumbing_build_speed, target = A))
|
||||
var/obj/machinery/duct/D
|
||||
if(recipe.type == /datum/pipe_info/plumbing/multilayer)
|
||||
var/temp_connects = NORTH + SOUTH
|
||||
if(queued_p_dir == EAST)
|
||||
temp_connects = EAST + WEST
|
||||
D = new queued_p_type (A, TRUE, GLOB.pipe_paint_colors[paint_color], ducting_layer, temp_connects)
|
||||
else
|
||||
D = new queued_p_type (A, TRUE, GLOB.pipe_paint_colors[paint_color], ducting_layer)
|
||||
D.add_fingerprint(usr)
|
||||
if(mode & WRENCH_MODE)
|
||||
D.wrench_act(user, src)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/pipe_dispenser/proc/activate()
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
/* unneeded, you can craft ducts from plastic
|
||||
/obj/item/pipe_dispenser/plumbing
|
||||
name = "Plumberinator"
|
||||
desc = "A crude device to rapidly plumb things."
|
||||
icon_state = "plumberer"
|
||||
category = PLUMBING_CATEGORY
|
||||
locked = TRUE
|
||||
|
||||
/obj/item/pipe_dispenser/plumbing/Initialize()
|
||||
. = ..()
|
||||
spark_system = new
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.attach(src)
|
||||
if(!first_plumbing)
|
||||
first_plumbing = GLOB.fluid_duct_recipes[GLOB.fluid_duct_recipes[1]][1]
|
||||
|
||||
recipe = first_plumbing
|
||||
|
||||
*/
|
||||
|
||||
#undef ATMOS_CATEGORY
|
||||
#undef DISPOSALS_CATEGORY
|
||||
#undef TRANSIT_CATEGORY
|
||||
#undef PLUMBING_CATEGORY
|
||||
|
||||
#undef BUILD_MODE
|
||||
#undef DESTROY_MODE
|
||||
|
||||
@@ -48,6 +48,13 @@
|
||||
/obj/item/stack/cable_coil = 5,
|
||||
/obj/item/stack/sheet/glass = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/medipen_refiller
|
||||
name = "Medipen Refiller (Machine Board)"
|
||||
icon_state = "medical"
|
||||
build_path = /obj/machinery/medipen_refiller
|
||||
req_components = list(
|
||||
/obj/item/stock_parts/matter_bin = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/clonepod
|
||||
name = "Clone Pod (Machine Board)"
|
||||
build_path = /obj/machinery/clonepod
|
||||
@@ -512,6 +519,10 @@
|
||||
/obj/item/stack/sheet/glass = 1)
|
||||
needs_anchored = FALSE
|
||||
|
||||
/obj/item/circuitboard/machine/hydroponics/automagic
|
||||
name = "Automatic Hydroponics Tray (Machine Board)"
|
||||
build_path = /obj/machinery/hydroponics/constructable/automagic
|
||||
|
||||
/obj/item/circuitboard/machine/seed_extractor
|
||||
name = "Seed Extractor (Machine Board)"
|
||||
build_path = /obj/machinery/seed_extractor
|
||||
|
||||
@@ -60,7 +60,8 @@
|
||||
if(target)
|
||||
if(!QDELETED(target))
|
||||
location = get_turf(target)
|
||||
target.cut_overlay(plastic_overlay, TRUE)
|
||||
target.cut_overlay(plastic_overlay)
|
||||
UnregisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/add_plastic_overlay)
|
||||
if(!ismob(target) || full_damage_on_mobs)
|
||||
target.ex_act(EXPLODE_HEAVY, target)
|
||||
else
|
||||
@@ -126,13 +127,17 @@
|
||||
I.embedding["embed_chance"] = 0
|
||||
I.updateEmbedding()
|
||||
|
||||
target.add_overlay(plastic_overlay, TRUE)
|
||||
RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/add_plastic_overlay)
|
||||
target.update_icon()
|
||||
if(!nadeassembly)
|
||||
to_chat(user, "<span class='notice'>You plant the bomb. Timer counting down from [det_time].</span>")
|
||||
addtimer(CALLBACK(src, .proc/prime), det_time*10)
|
||||
else
|
||||
qdel(src) //How?
|
||||
|
||||
/obj/item/grenade/plastic/proc/add_plastic_overlay(atom/source, list/overlay_list)
|
||||
overlay_list += plastic_overlay
|
||||
|
||||
/obj/item/grenade/plastic/proc/shout_syndicate_crap(mob/M)
|
||||
if(!M)
|
||||
return
|
||||
|
||||
@@ -128,6 +128,7 @@
|
||||
absorption_capacity = 5
|
||||
splint_factor = 0.35
|
||||
custom_price = PRICE_REALLY_CHEAP
|
||||
grind_results = list(/datum/reagent/cellulose = 2)
|
||||
|
||||
// gauze is only relevant for wounds, which are handled in the wounds themselves
|
||||
/obj/item/stack/medical/gauze/try_heal(mob/living/M, mob/user, silent)
|
||||
|
||||
@@ -413,6 +413,7 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
|
||||
force = 0
|
||||
throwforce = 0
|
||||
merge_type = /obj/item/stack/sheet/cloth
|
||||
grind_results = list(/datum/reagent/cellulose = 2)
|
||||
|
||||
/obj/item/stack/sheet/cloth/get_main_recipes()
|
||||
. = ..()
|
||||
@@ -782,6 +783,7 @@ GLOBAL_LIST_INIT(plastic_recipes, list(
|
||||
new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/empty), \
|
||||
new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/large/empty,3), \
|
||||
new /datum/stack_recipe("shower curtain", /obj/structure/curtain, 10, time = 10, one_per_turf = 1, on_floor = 1), \
|
||||
new /datum/stack_recipe("duct", /obj/item/stack/ducts,1), \
|
||||
new /datum/stack_recipe("laser pointer case", /obj/item/glasswork/glass_base/laserpointer_shell, 30), \
|
||||
new /datum/stack_recipe("wet floor sign", /obj/item/caution, 2)))
|
||||
|
||||
@@ -850,6 +852,7 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra
|
||||
merge_type = /obj/item/stack/sheet/cotton
|
||||
var/pull_effort = 30
|
||||
var/loom_result = /obj/item/stack/sheet/cloth
|
||||
grind_results = list(/datum/reagent/cellulose = 5)
|
||||
|
||||
/obj/item/stack/sheet/cotton/ten
|
||||
amount = 10
|
||||
@@ -865,6 +868,7 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra
|
||||
merge_type = /obj/item/stack/sheet/cotton/durathread
|
||||
pull_effort = 70
|
||||
loom_result = /obj/item/stack/sheet/durathread
|
||||
grind_results = list(/datum/reagent/cellulose = 10)
|
||||
|
||||
/obj/item/stack/sheet/meat
|
||||
name = "meat sheets"
|
||||
|
||||
@@ -478,7 +478,7 @@
|
||||
/obj/item/assembly/signaler,
|
||||
/obj/item/lightreplacer,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/construction/rcd,
|
||||
/obj/item/construction,
|
||||
/obj/item/pipe_dispenser,
|
||||
/obj/item/stack/rods,
|
||||
/obj/item/stack/tile/plasteel,
|
||||
|
||||
@@ -252,6 +252,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
/obj/item/katana/timestop
|
||||
name = "temporal katana"
|
||||
desc = "Delicately balanced, this finely-crafted blade hums with barely-restrained potential."
|
||||
icon_state = "temporalkatana"
|
||||
item_state = "temporalkatana"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
||||
block_chance = 0 // oops
|
||||
force = 27.5 // oops
|
||||
item_flags = ITEM_CAN_PARRY
|
||||
@@ -263,6 +267,21 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
flynn.emote("smirk")
|
||||
new /obj/effect/timestop/magic(get_turf(owner), 1, 50, list(owner)) // null roddies counter
|
||||
|
||||
/obj/item/katana/timestop/suicide_act(mob/living/user) // stolen from hierophant staff
|
||||
new /obj/effect/timestop/magic(get_turf(user), 1, 50, list(user)) // free usage for dying
|
||||
user.visible_message("<span class='suicide'>[user] poses menacingly with the [src]! It looks like [user.p_theyre()] trying to teleport behind someone!</span>")
|
||||
user.say("Heh.. Nothing personnel, kid..", forced = "temporal katana suicide")
|
||||
sleep(20)
|
||||
if(!user)
|
||||
return
|
||||
user.visible_message("<span class='hierophant_warning'>[user] vanishes into a cloud of falling dust and burning embers, likely off to style on some poor sod in the distance!</span>")
|
||||
playsound(user,'sound/magic/blink.ogg', 75, TRUE)
|
||||
for(var/obj/item/I in user)
|
||||
if(I != src)
|
||||
user.dropItemToGround(I)
|
||||
user.dropItemToGround(src) //Drop us last, so it goes on top of their stuff
|
||||
qdel(user)
|
||||
|
||||
/obj/item/melee/bokken // parrying stick
|
||||
name = "bokken"
|
||||
desc = "A space-Japanese training sword made of wood and shaped like a katana."
|
||||
|
||||
@@ -186,7 +186,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
|
||||
if(!acid_level)
|
||||
SSacid.processing[src] = src
|
||||
add_overlay(GLOB.acid_overlay, TRUE)
|
||||
update_icon()
|
||||
var/acid_cap = acidpwr * 300 //so we cannot use huge amounts of weak acids to do as well as strong acids.
|
||||
if(acid_level < acid_cap)
|
||||
acid_level = min(acid_level + acidpwr * acid_volume, acid_cap)
|
||||
@@ -224,7 +224,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
if(!(resistance_flags & ON_FIRE) && (resistance_flags & FLAMMABLE))
|
||||
resistance_flags |= ON_FIRE
|
||||
SSfire_burning.processing[src] = src
|
||||
add_overlay(GLOB.fire_overlay, TRUE)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
//called when the obj is destroyed by fire
|
||||
@@ -236,7 +236,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
/obj/proc/extinguish()
|
||||
if(resistance_flags & ON_FIRE)
|
||||
resistance_flags &= ~ON_FIRE
|
||||
cut_overlay(GLOB.fire_overlay, TRUE)
|
||||
update_icon()
|
||||
SSfire_burning.processing -= src
|
||||
|
||||
/obj/zap_act(power, zap_flags, shocked_targets)
|
||||
|
||||
@@ -317,6 +317,13 @@
|
||||
icon_state = unique_reskin[choice]
|
||||
to_chat(M, "[src] is now skinned as '[choice]'.")
|
||||
|
||||
/obj/update_overlays()
|
||||
. = ..()
|
||||
if(acid_level)
|
||||
. += GLOB.acid_overlay
|
||||
if(resistance_flags & ON_FIRE)
|
||||
. += GLOB.fire_overlay
|
||||
|
||||
//Called when the object is constructed by an autolathe
|
||||
//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes
|
||||
/obj/proc/autolathe_crafted(obj/machinery/autolathe/A)
|
||||
@@ -329,3 +336,6 @@
|
||||
. = ..()
|
||||
if(. && ricochet_damage_mod)
|
||||
take_damage(P.damage * ricochet_damage_mod, P.damage_type, P.flag, 0, turn(P.dir, 180), P.armour_penetration) // pass along ricochet_damage_mod damage to the structure for the ricochet
|
||||
|
||||
/obj/proc/plunger_act(obj/item/plunger/P, mob/living/user, reinforced)
|
||||
return
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
var/erupting_state = null //set to null to get it greyscaled from "[icon_state]_soup". Not very usable with the whole random thing, but more types can be added if you change the spawn prob
|
||||
var/activated = FALSE //whether we are active and generating chems
|
||||
var/reagent_id = /datum/reagent/fuel/oil
|
||||
var/reagent_id = /datum/reagent/oil
|
||||
var/potency = 2 //how much reagents we add every process (2 seconds)
|
||||
var/max_volume = 500
|
||||
var/start_volume = 50
|
||||
@@ -77,10 +77,10 @@
|
||||
|
||||
/obj/item/plunger/reinforced
|
||||
name = "reinforced plunger"
|
||||
desc = "It's an M. 7 Reinforced Plunger© for heavy duty plunging."
|
||||
desc = "It's an M. 7 Reinforced Plunger� for heavy duty plunging."
|
||||
icon_state = "reinforced_plunger"
|
||||
|
||||
reinforced = TRUE
|
||||
plunge_mod = 0.8
|
||||
|
||||
custom_premium_price = 1200
|
||||
custom_premium_price = 600
|
||||
|
||||
@@ -149,6 +149,8 @@
|
||||
var/list/megafauna_spawn_list
|
||||
/// Flora that can spawn in the tunnel, weighted list
|
||||
var/list/flora_spawn_list
|
||||
//terrain to spawn weighted list
|
||||
var/list/terrain_spawn_list
|
||||
/// Turf type to choose when spawning in tunnel at 1% chance, weighted list
|
||||
var/list/choose_turf_type
|
||||
/// if the tunnel should keep being created
|
||||
@@ -230,7 +232,8 @@
|
||||
megafauna_spawn_list = list(/mob/living/simple_animal/hostile/megafauna/dragon = 4, /mob/living/simple_animal/hostile/megafauna/colossus = 2, /mob/living/simple_animal/hostile/megafauna/bubblegum = SPAWN_BUBBLEGUM)
|
||||
if (!flora_spawn_list)
|
||||
flora_spawn_list = list(/obj/structure/flora/ash/leaf_shroom = 2 , /obj/structure/flora/ash/cap_shroom = 2 , /obj/structure/flora/ash/stem_shroom = 2 , /obj/structure/flora/ash/cacti = 1, /obj/structure/flora/ash/tall_shroom = 2)
|
||||
|
||||
if(!terrain_spawn_list)
|
||||
terrain_spawn_list = list(/obj/structure/geyser/random = 1)
|
||||
. = ..()
|
||||
if(!has_data)
|
||||
produce_tunnel_from_data()
|
||||
@@ -334,8 +337,19 @@
|
||||
spawned_flora = SpawnFlora(T)
|
||||
if(!spawned_flora) // no rocks beneath mob spawners / mobs.
|
||||
SpawnMonster(T)
|
||||
SpawnTerrain(T)
|
||||
T.ChangeTurf(turf_type, null, CHANGETURF_IGNORE_AIR)
|
||||
|
||||
/turf/open/floor/plating/asteroid/airless/cave/proc/SpawnTerrain(turf/T)
|
||||
if(prob(1))
|
||||
if(istype(loc, /area/mine/explored) || istype(loc, /area/lavaland/surface/outdoors/explored))
|
||||
return
|
||||
var/randumb = pickweight(terrain_spawn_list)
|
||||
for(var/obj/structure/geyser/F in range(7, T))
|
||||
if(istype(F, randumb))
|
||||
return
|
||||
new randumb(T)
|
||||
|
||||
/// Spawns a random mob or megafauna in the tunnel
|
||||
/turf/open/floor/plating/asteroid/airless/cave/proc/SpawnMonster(turf/T)
|
||||
if(!isarea(loc))
|
||||
|
||||
@@ -281,7 +281,6 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
. = CONFIG_GET(keyed_list/antag_threat)[lowertext(name)]
|
||||
if(. == null)
|
||||
return threat
|
||||
return threat
|
||||
|
||||
//This one is created by admin tools for custom objectives
|
||||
/datum/antagonist/custom
|
||||
|
||||
@@ -4,11 +4,17 @@
|
||||
antagpanel_category = "Blob"
|
||||
show_to_ghosts = TRUE
|
||||
job_rank = ROLE_BLOB
|
||||
threat = 20
|
||||
threat = 50
|
||||
var/datum/action/innate/blobpop/pop_action
|
||||
var/starting_points_human_blob = 60
|
||||
var/point_rate_human_blob = 2
|
||||
|
||||
/datum/antagonist/blob/threat()
|
||||
. = ..()
|
||||
if(isovermind(owner.current))
|
||||
var/mob/camera/blob/overmind = owner.current
|
||||
. *= (overmind.blobs_legit.len / overmind.max_count)
|
||||
|
||||
/datum/antagonist/blob/roundend_report()
|
||||
var/basic_report = ..()
|
||||
//Display max blobpoints for blebs that lost
|
||||
|
||||
@@ -75,7 +75,6 @@
|
||||
desc = "A floating, fragile spore."
|
||||
icon_state = "blobpod"
|
||||
icon_living = "blobpod"
|
||||
threat = 0.2
|
||||
health = 30
|
||||
maxHealth = 30
|
||||
verb_say = "psychically pulses"
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
unique_name = 1
|
||||
minbodytemp = 0
|
||||
unsuitable_atmos_damage = 0
|
||||
threat = 1
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) //Robotic
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
|
||||
healable = FALSE
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
desc = "The stalwart apparition of a soldier, blazing with crimson flames. It's armed with a gladius and shield."
|
||||
icon_state = "clockwork_marauder"
|
||||
mob_biotypes = MOB_HUMANOID
|
||||
threat = 3
|
||||
health = 120
|
||||
maxHealth = 120
|
||||
force_threshold = 8
|
||||
|
||||
@@ -70,7 +70,6 @@
|
||||
icon_living = "swarmer"
|
||||
icon_dead = "swarmer_unactivated"
|
||||
icon_gib = null
|
||||
threat = 0.5
|
||||
wander = 0
|
||||
harm_intent_damage = 5
|
||||
minbodytemp = 0
|
||||
|
||||
@@ -16,6 +16,18 @@
|
||||
var/datum/team/xeno/xeno_team
|
||||
threat = 3
|
||||
|
||||
/datum/antagonist/xeno/threat()
|
||||
. = 1
|
||||
if(isalienhunter(owner))
|
||||
. = 2
|
||||
else if(isaliensentinel(owner))
|
||||
. = 4
|
||||
else if(isalienroyal(owner))
|
||||
if(isalienqueen(owner))
|
||||
. = 8
|
||||
else
|
||||
. = 6
|
||||
|
||||
/datum/antagonist/xeno/create_team(datum/team/xeno/new_team)
|
||||
if(!new_team)
|
||||
for(var/datum/antagonist/xeno/X in GLOB.antagonists)
|
||||
|
||||
@@ -264,7 +264,7 @@
|
||||
name = "pipes"
|
||||
|
||||
/datum/asset/spritesheet/pipes/register()
|
||||
for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi'))
|
||||
for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi', 'icons/obj/atmospherics/pipes/transit_tube.dmi', 'icons/obj/plumbing/fluid_ducts.dmi'))
|
||||
InsertAll("", each, GLOB.alldirs)
|
||||
..()
|
||||
|
||||
@@ -388,9 +388,11 @@
|
||||
Insert("polycrystal", 'icons/obj/telescience.dmi', "polycrystal")
|
||||
..()
|
||||
|
||||
|
||||
/datum/asset/spritesheet/mafia
|
||||
name = "mafia"
|
||||
|
||||
/datum/asset/spritesheet/mafia/register()
|
||||
InsertAll("", 'icons/obj/mafia.dmi')
|
||||
..()
|
||||
|
||||
|
||||
@@ -118,8 +118,7 @@
|
||||
|
||||
// Set the clothing's integrity back to 100%, remove all damage to bodyparts, and generally fix it up
|
||||
/obj/item/clothing/proc/repair(mob/user, params)
|
||||
damaged_clothes = CLOTHING_PRISTINE
|
||||
update_clothes_damaged_state(FALSE)
|
||||
update_clothes_damaged_state(CLOTHING_PRISTINE)
|
||||
obj_integrity = max_integrity
|
||||
name = initial(name) // remove "tattered" or "shredded" if there's a prefix
|
||||
body_parts_covered = initial(body_parts_covered)
|
||||
@@ -196,7 +195,7 @@
|
||||
if(3 to INFINITY) // take better care of your shit, dude
|
||||
name = "tattered [initial(name)]"
|
||||
|
||||
update_clothes_damaged_state()
|
||||
update_clothes_damaged_state(CLOTHING_DAMAGED)
|
||||
|
||||
/obj/item/clothing/Destroy()
|
||||
user_vars_remembered = null //Oh god somebody put REFERENCES in here? not to worry, we'll clean it up
|
||||
@@ -257,7 +256,7 @@
|
||||
how_cool_are_your_threads += "Adding or removing items from [src] makes no noise.\n"
|
||||
how_cool_are_your_threads += "</span>"
|
||||
. += how_cool_are_your_threads.Join()
|
||||
|
||||
|
||||
if(LAZYLEN(armor_list))
|
||||
armor_list.Cut()
|
||||
if(armor.bio)
|
||||
@@ -346,10 +345,16 @@
|
||||
var/mob/M = loc
|
||||
to_chat(M, "<span class='warning'>Your [name] starts to fall apart!</span>")
|
||||
|
||||
/obj/item/clothing/proc/update_clothes_damaged_state(damaging = TRUE)
|
||||
var/index = "[REF(initial(icon))]-[initial(icon_state)]"
|
||||
var/static/list/damaged_clothes_icons = list()
|
||||
if(damaging)
|
||||
//This mostly exists so subtypes can call appriopriate update icon calls on the wearer.
|
||||
/obj/item/clothing/proc/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED)
|
||||
damaged_clothes = damaged_state
|
||||
update_icon()
|
||||
|
||||
/obj/item/clothing/update_overlays()
|
||||
. = ..()
|
||||
if(damaged_clothes)
|
||||
var/index = "[REF(initial(icon))]-[initial(icon_state)]"
|
||||
var/static/list/damaged_clothes_icons = list()
|
||||
var/icon/damaged_clothes_icon = damaged_clothes_icons[index]
|
||||
if(!damaged_clothes_icon)
|
||||
damaged_clothes_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply damaged effect to the initial icon_state for each object
|
||||
@@ -357,9 +362,7 @@
|
||||
damaged_clothes_icon.Blend(icon('icons/effects/item_damage.dmi', "itemdamaged"), ICON_MULTIPLY) //adds damage effect and the remaining white areas become transparant
|
||||
damaged_clothes_icon = fcopy_rsc(damaged_clothes_icon)
|
||||
damaged_clothes_icons[index] = damaged_clothes_icon
|
||||
add_overlay(damaged_clothes_icon, TRUE)
|
||||
else
|
||||
cut_overlay(damaged_clothes_icons[index], TRUE)
|
||||
. += damaged_clothes_icon
|
||||
|
||||
/*
|
||||
SEE_SELF // can see self, no matter what
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
/obj/item/clothing/mask/balaclava/attack_self(mob/user)
|
||||
adjustmask(user)
|
||||
|
||||
/obj/item/clothing/mask/balaclava/breath
|
||||
name = "breathaclava"
|
||||
clothing_flags = ALLOWINTERNALS
|
||||
|
||||
/obj/item/clothing/mask/infiltrator
|
||||
name = "insidious balaclava"
|
||||
desc = "An incredibly suspicious balaclava made with Syndicate nanofibers to absorb impacts slightly while obfuscating the voice and face using a garbled vocoder."
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
typepath = /datum/round_event/ghost_role/alien_infestation
|
||||
weight = 5
|
||||
gamemode_blacklist = list("dynamic")
|
||||
min_players = 10
|
||||
min_players = 25
|
||||
max_occurrences = 1
|
||||
|
||||
/datum/round_event/ghost_role/alien_infestation
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
"How do I vore people?",
|
||||
"ERP?",
|
||||
"Not epic bros...")
|
||||
threat = 5
|
||||
|
||||
|
||||
/datum/round_event/brand_intelligence/announce(fake)
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
icon_dead = "magicarp_dead"
|
||||
icon_gib = "magicarp_gib"
|
||||
ranged = 1
|
||||
threat = 4
|
||||
retreat_distance = 2
|
||||
minimum_distance = 0 //Between shots they can and will close in to nash
|
||||
projectiletype = /obj/item/projectile/magic
|
||||
@@ -52,7 +51,6 @@
|
||||
color = "#00FFFF"
|
||||
maxHealth = 75
|
||||
health = 75
|
||||
threat = 7
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/ranged/chaos/Shoot()
|
||||
projectiletype = pick(allowed_projectile_types)
|
||||
|
||||
@@ -190,7 +190,6 @@
|
||||
icon_dead = "scary_clown"
|
||||
icon_gib = "scary_clown"
|
||||
speak = list("...", ". . .")
|
||||
threat = 3
|
||||
maxHealth = 120
|
||||
health = 120
|
||||
emote_see = list("silently stares")
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
var/self_sufficiency_req = 20 //Required total dose to make a self-sufficient hydro tray. 1:1 with earthsblood.
|
||||
var/self_sufficiency_progress = 0
|
||||
var/self_sustaining = FALSE //If the tray generates nutrients and water on its own
|
||||
|
||||
var/canirrigate = TRUE //tin
|
||||
|
||||
/obj/machinery/hydroponics/constructable
|
||||
name = "hydroponics tray"
|
||||
@@ -847,12 +847,13 @@
|
||||
if (!anchored)
|
||||
to_chat(user, "<span class='warning'>Anchor the tray first!</span>")
|
||||
return
|
||||
using_irrigation = !using_irrigation
|
||||
O.play_tool_sound(src)
|
||||
user.visible_message("<span class='notice'>[user] [using_irrigation ? "" : "dis"]connects [src]'s irrigation hoses.</span>", \
|
||||
"<span class='notice'>You [using_irrigation ? "" : "dis"]connect [src]'s irrigation hoses.</span>")
|
||||
for(var/obj/machinery/hydroponics/h in range(1,src))
|
||||
h.update_icon()
|
||||
if(canirrigate)
|
||||
using_irrigation = !using_irrigation
|
||||
O.play_tool_sound(src)
|
||||
user.visible_message("<span class='notice'>[user] [using_irrigation ? "" : "dis"]connects [src]'s irrigation hoses.</span>", \
|
||||
"<span class='notice'>You [using_irrigation ? "" : "dis"]connect [src]'s irrigation hoses.</span>")
|
||||
for(var/obj/machinery/hydroponics/h in range(1,src))
|
||||
h.update_icon()
|
||||
|
||||
else if(istype(O, /obj/item/shovel/spade))
|
||||
if(!myseed && !weedlevel)
|
||||
@@ -910,11 +911,14 @@
|
||||
harvest = 0
|
||||
lastproduce = age
|
||||
if(istype(myseed, /obj/item/seeds/replicapod))
|
||||
to_chat(user, "<span class='notice'>You harvest from the [myseed.plantname].</span>")
|
||||
if(user)//runtimes
|
||||
to_chat(user, "<span class='notice'>You harvest from the [myseed.plantname].</span>")
|
||||
else if(myseed.getYield() <= 0)
|
||||
to_chat(user, "<span class='warning'>You fail to harvest anything useful!</span>")
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>You fail to harvest anything useful!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You harvest [myseed.getYield()] items from the [myseed.plantname].</span>")
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>You harvest [myseed.getYield()] items from the [myseed.plantname].</span>")
|
||||
if(!myseed.get_gene(/datum/plant_gene/trait/repeated_harvest))
|
||||
qdel(myseed)
|
||||
myseed = null
|
||||
|
||||
@@ -190,6 +190,31 @@ obj/item/seeds/proc/is_gene_forbidden(typepath)
|
||||
parent.update_tray(user)
|
||||
return result
|
||||
|
||||
/obj/item/seeds/proc/harvest_userless()
|
||||
var/obj/machinery/hydroponics/parent = loc //for ease of access
|
||||
var/t_amount = 0
|
||||
var/list/result = list()
|
||||
var/output_loc = parent.loc
|
||||
var/product_name
|
||||
while(t_amount < getYield())
|
||||
var/obj/item/reagent_containers/food/snacks/grown/t_prod = new product(output_loc, src)
|
||||
if(parent.myseed.plantname != initial(parent.myseed.plantname))
|
||||
t_prod.name = lowertext(parent.myseed.plantname)
|
||||
if(productdesc)
|
||||
t_prod.desc = productdesc
|
||||
t_prod.seed.name = parent.myseed.name
|
||||
t_prod.seed.desc = parent.myseed.desc
|
||||
t_prod.seed.plantname = parent.myseed.plantname
|
||||
result.Add(t_prod) // User gets a consumable
|
||||
if(!t_prod)
|
||||
return
|
||||
t_amount++
|
||||
product_name = parent.myseed.plantname
|
||||
if(getYield() >= 1)
|
||||
SSblackbox.record_feedback("tally", "food_harvested", getYield(), product_name)
|
||||
parent.investigate_log("autmoatic harvest of [getYield()] of [src], with seed traits [english_list(genes)] and reagents_add [english_list(reagents_add)] and potency [potency].", INVESTIGATE_BOTANY)
|
||||
parent.update_tray()
|
||||
return result
|
||||
|
||||
/obj/item/seeds/proc/prepare_result(var/obj/item/reagent_containers/food/snacks/grown/T)
|
||||
if(!T.reagents)
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
/datum/sprite_accessory/snouts/mam_snouts
|
||||
color_src = MATRIXED
|
||||
icon = 'modular_citadel/icons/mob/mam_snouts.dmi'
|
||||
recommended_species = list("mammal", "slimeperson", "insect", "podweak")
|
||||
recommended_species = list("mammal", "slimeperson", "insect", "podweak", "lizard")
|
||||
mutant_part_string = "snout"
|
||||
relevant_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER)
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
|
||||
/mob/living/carbon/human/dummy/proc/wipe_state()
|
||||
delete_equipment()
|
||||
icon_render_key = null
|
||||
cut_overlays(TRUE)
|
||||
cut_overlays()
|
||||
|
||||
//Inefficient pooling/caching way.
|
||||
GLOBAL_LIST_EMPTY(human_dummy_list)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
say_mod = "hisses"
|
||||
default_color = "00FF00"
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE)
|
||||
mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs", "taur", "deco_wings")
|
||||
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE
|
||||
mutanttongue = /obj/item/organ/tongue/lizard
|
||||
mutanttail = /obj/item/organ/tail/lizard
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
response_disarm_simple = "flail at"
|
||||
response_harm_continuous = "punches"
|
||||
response_harm_simple = "punch"
|
||||
threat = 1
|
||||
speak_chance = 1
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
speed = 0
|
||||
@@ -122,7 +121,6 @@
|
||||
desc = "A massive, armored construct built to spearhead attacks and soak up enemy fire."
|
||||
icon_state = "behemoth"
|
||||
icon_living = "behemoth"
|
||||
threat = 3
|
||||
maxHealth = 150
|
||||
health = 150
|
||||
response_harm_continuous = "harmlessly punches"
|
||||
@@ -187,7 +185,6 @@
|
||||
desc = "A wicked, clawed shell constructed to assassinate enemies and sow chaos behind enemy lines."
|
||||
icon_state = "floating"
|
||||
icon_living = "floating"
|
||||
threat = 3
|
||||
maxHealth = 65
|
||||
health = 65
|
||||
melee_damage_lower = 20
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
eyes_overlay.pixel_y = -8
|
||||
moustache_overlay.pixel_y = -8
|
||||
|
||||
cut_overlays(TRUE)
|
||||
cut_overlays()
|
||||
add_overlay(body_overlay)
|
||||
add_overlay(eyes_overlay)
|
||||
add_overlay(moustache_overlay)
|
||||
|
||||
@@ -8,7 +8,6 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
name = "Guardian Spirit"
|
||||
real_name = "Guardian Spirit"
|
||||
desc = "A mysterious being that stands by its charge, ever vigilant."
|
||||
threat = 5
|
||||
speak_emote = list("hisses")
|
||||
gender = NEUTER
|
||||
mob_biotypes = NONE
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
icon_dead = "alienh_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
gender = FEMALE
|
||||
threat = 1
|
||||
response_help_continuous = "pokes"
|
||||
response_help_simple = "poke"
|
||||
response_disarm_continuous = "shoves"
|
||||
@@ -69,7 +68,6 @@
|
||||
icon_state = "aliens"
|
||||
icon_living = "aliens"
|
||||
icon_dead = "aliens_dead"
|
||||
threat = 3
|
||||
health = 150
|
||||
maxHealth = 150
|
||||
melee_damage_lower = 15
|
||||
@@ -87,7 +85,6 @@
|
||||
icon_living = "alienq"
|
||||
icon_dead = "alienq_dead"
|
||||
pixel_x = -16
|
||||
threat = 8
|
||||
health = 250
|
||||
maxHealth = 250
|
||||
melee_damage_lower = 15
|
||||
@@ -167,7 +164,6 @@
|
||||
name = "lusty xenomorph maid"
|
||||
melee_damage_lower = 0
|
||||
melee_damage_upper = 0
|
||||
threat = -1
|
||||
a_intent = INTENT_HELP
|
||||
friendly_verb_continuous = "caresses"
|
||||
friendly_verb_simple = "caress"
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
/mob/living/simple_animal/hostile/bear
|
||||
name = "space bear"
|
||||
desc = "You don't need to be faster than a space bear, you just need to outrun your crewmates."
|
||||
threat = 1
|
||||
icon_state = "bear"
|
||||
icon_living = "bear"
|
||||
icon_dead = "bear_dead"
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
icon_state = ""
|
||||
icon_living = ""
|
||||
icon = 'icons/mob/bees.dmi'
|
||||
threat = 0.3
|
||||
gender = FEMALE
|
||||
speak_emote = list("buzzes")
|
||||
emote_hear = list("buzzes")
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/mob/living/simple_animal/hostile/boss
|
||||
name = "A Perfectly Generic Boss Placeholder"
|
||||
desc = ""
|
||||
threat = 10
|
||||
robust_searching = TRUE
|
||||
stat_attack = UNCONSCIOUS
|
||||
status_flags = NONE
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
icon_living = "carp"
|
||||
icon_dead = "carp_dead"
|
||||
icon_gib = "carp_gib"
|
||||
threat = 0.1
|
||||
mob_biotypes = MOB_ORGANIC|MOB_BEAST
|
||||
speak_chance = 0
|
||||
turns_per_move = 5
|
||||
@@ -74,7 +73,6 @@
|
||||
icon_living = "megacarp"
|
||||
icon_dead = "megacarp_dead"
|
||||
icon_gib = "megacarp_gib"
|
||||
threat = 3
|
||||
regen_amount = 6
|
||||
|
||||
maxHealth = 30
|
||||
@@ -98,7 +96,6 @@
|
||||
name = "Cayenne"
|
||||
desc = "A failed Syndicate experiment in weaponized space carp technology, it now serves as a lovable mascot."
|
||||
gender = FEMALE
|
||||
threat = 5
|
||||
regen_amount = 8
|
||||
|
||||
speak_emote = list("squeaks")
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/mob/living/simple_animal/hostile/dark_wizard
|
||||
name = "Dark Wizard"
|
||||
desc = "Killing amateurs since the dawn of times."
|
||||
threat = 3
|
||||
icon = 'icons/mob/simple_human.dmi'
|
||||
icon_state = "dark_wizard"
|
||||
icon_living = "dark_wizard"
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
icon_state = "faithless"
|
||||
icon_living = "faithless"
|
||||
icon_dead = "faithless_dead"
|
||||
threat = 1
|
||||
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
|
||||
gender = MALE
|
||||
speak_chance = 0
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
//basic spider mob, these generally guard nests
|
||||
/mob/living/simple_animal/hostile/poison/giant_spider
|
||||
threat = 1
|
||||
name = "giant spider"
|
||||
desc = "Furry and black, it makes you shudder to look at it. This one has deep red eyes."
|
||||
icon_state = "guard"
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
icon_state = "crawling"
|
||||
icon_living = "crawling"
|
||||
icon_dead = "dead"
|
||||
threat = 0.5
|
||||
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
|
||||
speak_chance = 80
|
||||
maxHealth = 220
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
icon_state = "headcrab"
|
||||
icon_living = "headcrab"
|
||||
icon_dead = "headcrab_dead"
|
||||
threat = 1
|
||||
gender = NEUTER
|
||||
health = 50
|
||||
maxHealth = 50
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
stop_automated_movement_when_pulled = 0
|
||||
obj_damage = 40
|
||||
environment_smash = ENVIRONMENT_SMASH_STRUCTURES //Bitflags. Set to ENVIRONMENT_SMASH_STRUCTURES to break closets,tables,racks, etc; ENVIRONMENT_SMASH_WALLS for walls; ENVIRONMENT_SMASH_RWALLS for rwalls
|
||||
var/threat = 0 // for dynamic
|
||||
var/atom/target
|
||||
var/ranged = FALSE
|
||||
var/rapid = 0 //How many shots per volley.
|
||||
@@ -600,6 +599,3 @@ mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with mega
|
||||
. += M
|
||||
else if (M.loc.type in hostile_machines)
|
||||
. += M.loc
|
||||
|
||||
/mob/living/simple_animal/hostile/proc/threat()
|
||||
return threat
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
icon_living = "leaper"
|
||||
icon_dead = "leaper_dead"
|
||||
mob_biotypes = MOB_ORGANIC|MOB_BEAST
|
||||
threat = 2
|
||||
maxHealth = 300
|
||||
health = 300
|
||||
ranged = TRUE
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
icon_living = "arachnid"
|
||||
icon_dead = "arachnid_dead"
|
||||
mob_biotypes = MOB_ORGANIC|MOB_BUG
|
||||
threat = 2
|
||||
melee_damage_lower = 30
|
||||
melee_damage_upper = 30
|
||||
maxHealth = 300
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
icon_living = "mook"
|
||||
icon_dead = "mook_dead"
|
||||
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
|
||||
threat = 0.5
|
||||
pixel_x = -16
|
||||
maxHealth = 45
|
||||
health = 45
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
icon_state = "seedling"
|
||||
icon_living = "seedling"
|
||||
icon_dead = "seedling_dead"
|
||||
threat = 0.5
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
melee_damage_lower = 30
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
icon_living = "tomato"
|
||||
icon_dead = "tomato_dead"
|
||||
gender = NEUTER
|
||||
threat = 0.3
|
||||
speak_chance = 0
|
||||
turns_per_move = 5
|
||||
maxHealth = 30
|
||||
|
||||
@@ -23,7 +23,6 @@ Difficulty: Medium
|
||||
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner
|
||||
name = "blood-drunk miner"
|
||||
desc = "A miner destined to wander forever, engaged in an endless hunt."
|
||||
threat = 15
|
||||
health = 900
|
||||
maxHealth = 900
|
||||
icon_state = "miner"
|
||||
|
||||
@@ -26,7 +26,6 @@ Difficulty: Hard
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum
|
||||
name = "bubblegum"
|
||||
desc = "In what passes for a hierarchy among slaughter demons, this one is king."
|
||||
threat = 35
|
||||
health = 2500
|
||||
maxHealth = 2500
|
||||
attack_verb_continuous = "rends"
|
||||
|
||||
@@ -24,7 +24,6 @@ Difficulty: Very Hard
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus
|
||||
name = "colossus"
|
||||
desc = "A monstrous creature protected by heavy shielding."
|
||||
threat = 40
|
||||
health = 2500
|
||||
maxHealth = 2500
|
||||
attack_verb_continuous = "judges"
|
||||
@@ -603,7 +602,6 @@ Difficulty: Very Hard
|
||||
icon_state = "lightgeist"
|
||||
icon_living = "lightgeist"
|
||||
icon_dead = "butterfly_dead"
|
||||
threat = -0.7
|
||||
turns_per_move = 1
|
||||
response_help_continuous = "waves away"
|
||||
response_help_simple = "wave away"
|
||||
|
||||
@@ -38,7 +38,6 @@ Difficulty: Medium
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon
|
||||
name = "ash drake"
|
||||
desc = "Guardians of the necropolis."
|
||||
threat = 30
|
||||
health = 2500
|
||||
maxHealth = 2500
|
||||
spacewalk = TRUE
|
||||
|
||||
@@ -37,7 +37,6 @@ Difficulty: Normal
|
||||
/mob/living/simple_animal/hostile/megafauna/hierophant
|
||||
name = "hierophant"
|
||||
desc = "A massive metal club that hangs in the air as though waiting. It'll make you dance to its beat."
|
||||
threat = 30
|
||||
health = 2500
|
||||
maxHealth = 2500
|
||||
attack_verb_continuous = "clubs"
|
||||
|
||||
@@ -18,7 +18,6 @@ Difficulty: Medium
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/legion
|
||||
name = "Legion"
|
||||
threat = 30
|
||||
health = 800
|
||||
maxHealth = 800
|
||||
spacewalk = TRUE
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
icon_aggro = "Basilisk_alert"
|
||||
icon_dead = "Basilisk_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
threat = 4
|
||||
mob_biotypes = MOB_ORGANIC|MOB_BEAST
|
||||
move_to_delay = 20
|
||||
projectiletype = /obj/item/projectile/temp/basilisk
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
move_to_delay = 5
|
||||
vision_range = 20
|
||||
aggro_vision_range = 20
|
||||
threat = 1
|
||||
maxHealth = 40 //easy to kill, but oh, will you be seeing a lot of them.
|
||||
health = 40
|
||||
melee_damage_lower = 10
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
robust_searching = TRUE
|
||||
ranged_ignores_vision = TRUE
|
||||
ranged = TRUE
|
||||
threat = 5
|
||||
obj_damage = 5
|
||||
vision_range = 6
|
||||
aggro_vision_range = 18
|
||||
|
||||
-1
@@ -25,7 +25,6 @@
|
||||
icon_aggro = "broodmother"
|
||||
icon_dead = "egg_sac"
|
||||
icon_gib = "syndicate_gib"
|
||||
threat = 10
|
||||
maxHealth = 800
|
||||
health = 800
|
||||
melee_damage_lower = 30
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
icon_aggro = "herald"
|
||||
icon_dead = "herald_dying"
|
||||
icon_gib = "syndicate_gib"
|
||||
threat = 10
|
||||
maxHealth = 800
|
||||
health = 800
|
||||
melee_damage_lower = 20
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
icon_aggro = "legionnaire"
|
||||
icon_dead = "legionnaire_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
threat = 10
|
||||
maxHealth = 800
|
||||
health = 800
|
||||
melee_damage_lower = 30
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
icon_aggro = "pandora"
|
||||
icon_dead = "pandora_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
threat = 10
|
||||
maxHealth = 800
|
||||
health = 800
|
||||
melee_damage_lower = 15
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
icon_aggro = "Goldgrub_alert"
|
||||
icon_dead = "Goldgrub_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
threat = 0.2
|
||||
mob_biotypes = MOB_ORGANIC|MOB_BEAST
|
||||
vision_range = 2
|
||||
aggro_vision_range = 9
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
icon_gib = "syndicate_gib"
|
||||
mob_biotypes = MOB_ORGANIC|MOB_BEAST
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
threat = 2
|
||||
move_to_delay = 10
|
||||
ranged = 1
|
||||
ranged_cooldown_time = 60
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
icon_gib = "syndicate_gib"
|
||||
mob_biotypes = MOB_ORGANIC
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
threat = 4
|
||||
move_to_delay = 14
|
||||
ranged = 1
|
||||
vision_range = 4
|
||||
@@ -241,7 +240,6 @@
|
||||
icon_state = "legion"
|
||||
icon_living = "legion"
|
||||
icon_dead = "legion"
|
||||
threat = 5
|
||||
health = 450
|
||||
maxHealth = 450
|
||||
melee_damage_lower = 20
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
obj_damage = 100
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 50
|
||||
threat = 2
|
||||
attack_verb_continuous = "slashes"
|
||||
attack_verb_simple = "slash"
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
turns_per_move = 5
|
||||
response_help_continuous = "pushes"
|
||||
response_help_simple = "push"
|
||||
threat = 3
|
||||
speed = 0
|
||||
maxHealth = 115
|
||||
health = 115
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
speak_chance = 0
|
||||
turns_per_move = 5
|
||||
speed = 0
|
||||
threat = 1
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
harm_intent_damage = 5
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
response_harm_continuous = "kicks"
|
||||
response_harm_simple = "kick"
|
||||
speed = 0
|
||||
threat = 1
|
||||
maxHealth = 75
|
||||
health = 75
|
||||
harm_intent_damage = 18
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
speak_emote = list("rattles")
|
||||
emote_see = list("rattles")
|
||||
a_intent = INTENT_HARM
|
||||
threat = 0.5
|
||||
maxHealth = 40
|
||||
blood_volume = 0
|
||||
health = 40
|
||||
@@ -64,7 +63,6 @@
|
||||
icon_state = "templar"
|
||||
icon_living = "templar"
|
||||
icon_dead = "templar_dead"
|
||||
threat = 1.5
|
||||
maxHealth = 150
|
||||
health = 150
|
||||
weather_immunities = list("snow")
|
||||
@@ -98,7 +96,6 @@
|
||||
icon_state = "plasma_miner"
|
||||
icon_living = "plasma_miner"
|
||||
icon_dead = "plasma_miner"
|
||||
threat = 2
|
||||
maxHealth = 150
|
||||
health = 150
|
||||
harm_intent_damage = 10
|
||||
@@ -116,7 +113,6 @@
|
||||
icon_state = "plasma_miner_tool"
|
||||
icon_living = "plasma_miner_tool"
|
||||
icon_dead = "plasma_miner_tool"
|
||||
threat = 3
|
||||
maxHealth = 185
|
||||
health = 185
|
||||
harm_intent_damage = 15
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
gender = NEUTER
|
||||
a_intent = INTENT_HARM
|
||||
mob_biotypes = MOB_HUMANOID
|
||||
threat = 3
|
||||
response_help_continuous = "touches"
|
||||
response_help_simple = "touch"
|
||||
response_disarm_continuous = "pushes"
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
icon_living = "stickman"
|
||||
icon_dead = "stickman_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
threat = 0.5
|
||||
mob_biotypes = MOB_HUMANOID
|
||||
gender = MALE
|
||||
speak_chance = 0
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
|
||||
speak_chance = 0
|
||||
turns_per_move = 5
|
||||
threat = 1
|
||||
speed = 0
|
||||
stat_attack = UNCONSCIOUS
|
||||
robust_searching = 1
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
icon_dead = "pine_1"
|
||||
icon_gib = "pine_1"
|
||||
gender = NEUTER
|
||||
threat = 1
|
||||
speak_chance = 0
|
||||
turns_per_move = 5
|
||||
response_help_continuous = "brushes"
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
|
||||
speak_chance = 0
|
||||
turns_per_move = 3
|
||||
threat = 3
|
||||
speed = 0
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user