# Conflicts:
#	config/custom_items.txt
#	icons/mob/vore/taurs_vr.dmi
This commit is contained in:
Kelshark
2017-05-12 13:06:10 -04:00
233 changed files with 2136 additions and 1265 deletions

View File

@@ -3,9 +3,9 @@ language: c
sudo: false sudo: false
env: env:
BYOND_MAJOR="510" BYOND_MAJOR="511"
BYOND_MINOR="1346" BYOND_MINOR="1381"
MACRO_COUNT=986 MACRO_COUNT=875
cache: cache:
directories: directories:

View File

@@ -57,11 +57,11 @@ turf/c_airblock(turf/other)
#ifdef ZASDBG #ifdef ZASDBG
ASSERT(isturf(other)) ASSERT(isturf(other))
#endif #endif
if(blocks_air || other.blocks_air) if(((blocks_air & AIR_BLOCKED) || (other.blocks_air & AIR_BLOCKED)))
return BLOCKED return BLOCKED
//Z-level handling code. Always block if there isn't an open space. //Z-level handling code. Always block if there isn't an open space.
#ifdef ZLEVELS #ifdef MULTIZAS
if(other.z != src.z) if(other.z != src.z)
if(other.z < src.z) if(other.z < src.z)
if(!istype(src, /turf/simulated/open)) return BLOCKED if(!istype(src, /turf/simulated/open)) return BLOCKED
@@ -69,6 +69,12 @@ turf/c_airblock(turf/other)
if(!istype(other, /turf/simulated/open)) return BLOCKED if(!istype(other, /turf/simulated/open)) return BLOCKED
#endif #endif
if(((blocks_air & ZONE_BLOCKED) || (other.blocks_air & ZONE_BLOCKED)))
if(z == other.z)
return ZONE_BLOCKED
else
return AIR_BLOCKED
var/result = 0 var/result = 0
for(var/atom/movable/M in contents) for(var/atom/movable/M in contents)
result |= M.c_airblock(other) result |= M.c_airblock(other)

View File

@@ -37,7 +37,7 @@ Class Procs:
/connection_manager/var/connection/E /connection_manager/var/connection/E
/connection_manager/var/connection/W /connection_manager/var/connection/W
#ifdef ZLEVELS #ifdef MULTIZAS
/connection_manager/var/connection/U /connection_manager/var/connection/U
/connection_manager/var/connection/D /connection_manager/var/connection/D
#endif #endif
@@ -57,7 +57,7 @@ Class Procs:
if(check(W)) return W if(check(W)) return W
else return null else return null
#ifdef ZLEVELS #ifdef MULTIZAS
if(UP) if(UP)
if(check(U)) return U if(check(U)) return U
else return null else return null
@@ -73,7 +73,7 @@ Class Procs:
if(EAST) E = c if(EAST) E = c
if(WEST) W = c if(WEST) W = c
#ifdef ZLEVELS #ifdef MULTIZAS
if(UP) U = c if(UP) U = c
if(DOWN) D = c if(DOWN) D = c
#endif #endif
@@ -83,7 +83,7 @@ Class Procs:
if(check(S)) S.update() if(check(S)) S.update()
if(check(E)) E.update() if(check(E)) E.update()
if(check(W)) W.update() if(check(W)) W.update()
#ifdef ZLEVELS #ifdef MULTIZAS
if(check(U)) U.update() if(check(U)) U.update()
if(check(D)) D.update() if(check(D)) D.update()
#endif #endif
@@ -93,7 +93,7 @@ Class Procs:
if(check(S)) S.erase() if(check(S)) S.erase()
if(check(E)) E.erase() if(check(E)) E.erase()
if(check(W)) W.erase() if(check(W)) W.erase()
#ifdef ZLEVELS #ifdef MULTIZAS
if(check(U)) U.erase() if(check(U)) U.erase()
if(check(D)) D.erase() if(check(D)) D.erase()
#endif #endif

View File

@@ -158,6 +158,9 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
//defer updating of self-zone-blocked turfs until after all other turfs have been updated. //defer updating of self-zone-blocked turfs until after all other turfs have been updated.
//this hopefully ensures that non-self-zone-blocked turfs adjacent to self-zone-blocked ones //this hopefully ensures that non-self-zone-blocked turfs adjacent to self-zone-blocked ones
//have valid zones when the self-zone-blocked turfs update. //have valid zones when the self-zone-blocked turfs update.
//This ensures that doorways don't form their own single-turf zones, since doorways are self-zone-blocked and
//can merge with an adjacent zone, whereas zones that are formed on adjacent turfs cannot merge with the doorway.
var/list/deferred = list() var/list/deferred = list()
for(var/turf/T in updating) for(var/turf/T in updating)

View File

@@ -39,6 +39,10 @@ client/proc/Test_ZAS_Connection(var/turf/simulated/T as turf)
"South" = SOUTH,\ "South" = SOUTH,\
"East" = EAST,\ "East" = EAST,\
"West" = WEST,\ "West" = WEST,\
#ifdef MULTIZAS
"Up" = UP,\
"Down" = DOWN,\
#endif
"N/A" = null) "N/A" = null)
var/direction = input("What direction do you wish to test?","Set direction") as null|anything in direction_list var/direction = input("What direction do you wish to test?","Set direction") as null|anything in direction_list
if(!direction) if(!direction)

View File

@@ -16,7 +16,7 @@
//dbg(blocked) //dbg(blocked)
return 1 return 1
#ifdef ZLEVELS #ifdef MULTIZAS
for(var/d = 1, d < 64, d *= 2) for(var/d = 1, d < 64, d *= 2)
#else #else
for(var/d = 1, d < 16, d *= 2) for(var/d = 1, d < 16, d *= 2)
@@ -52,34 +52,40 @@
*/ */
/turf/simulated/proc/can_safely_remove_from_zone() /turf/simulated/proc/can_safely_remove_from_zone()
#ifdef ZLEVELS
return 0 //TODO generalize this to multiz.
#else
if(!zone) return 1 if(!zone) return 1
var/check_dirs = get_zone_neighbours(src) var/check_dirs = get_zone_neighbours(src)
var/unconnected_dirs = check_dirs var/unconnected_dirs = check_dirs
for(var/dir in list(NORTHWEST, NORTHEAST, SOUTHEAST, SOUTHWEST)) #ifdef MULTIZAS
var/to_check = cornerdirsz
#else
var/to_check = cornerdirs
#endif
for(var/dir in to_check)
//for each pair of "adjacent" cardinals (e.g. NORTH and WEST, but not NORTH and SOUTH) //for each pair of "adjacent" cardinals (e.g. NORTH and WEST, but not NORTH and SOUTH)
if((dir & check_dirs) == dir) if((dir & check_dirs) == dir)
//check that they are connected by the corner turf //check that they are connected by the corner turf
var/connected_dirs = get_zone_neighbours(get_step(src, dir)) var/connected_dirs = get_zone_neighbours(get_step(src, dir))
if(connected_dirs && (dir & turn(connected_dirs, 180)) == dir) if(connected_dirs && (dir & reverse_dir[connected_dirs]) == dir)
unconnected_dirs &= ~dir //they are, so unflag the cardinals in question unconnected_dirs &= ~dir //they are, so unflag the cardinals in question
//it is safe to remove src from the zone if all cardinals are connected by corner turfs //it is safe to remove src from the zone if all cardinals are connected by corner turfs
return !unconnected_dirs return !unconnected_dirs
#endif
//helper for can_safely_remove_from_zone() //helper for can_safely_remove_from_zone()
/turf/simulated/proc/get_zone_neighbours(turf/simulated/T) /turf/simulated/proc/get_zone_neighbours(turf/simulated/T)
. = 0 . = 0
if(istype(T) && T.zone) if(istype(T) && T.zone)
for(var/dir in cardinal) #ifdef MULTIZAS
var/to_check = cardinalz
#else
var/to_check = cardinal
#endif
for(var/dir in to_check)
var/turf/simulated/other = get_step(T, dir) var/turf/simulated/other = get_step(T, dir)
if(istype(other) && other.zone == T.zone && !(other.c_airblock(T) & AIR_BLOCKED) && get_dist(src, other) <= 1) if(istype(other) && other.zone == T.zone && !(other.c_airblock(T) & AIR_BLOCKED) && get_dist(src, other) <= 1)
. |= dir . |= dir
@@ -110,7 +116,7 @@
open_directions = 0 open_directions = 0
var/list/postponed var/list/postponed
#ifdef ZLEVELS #ifdef MULTIZAS
for(var/d = 1, d < 64, d *= 2) for(var/d = 1, d < 64, d *= 2)
#else #else
for(var/d = 1, d < 16, d *= 2) for(var/d = 1, d < 16, d *= 2)

View File

@@ -28,8 +28,7 @@ Notes for people who used ZAS before:
*/ */
//#define ZASDBG //#define ZASDBG
//#define ZLEVELS //#define MULTIZAS
#define AIR_BLOCKED 1 #define AIR_BLOCKED 1
#define ZONE_BLOCKED 2 #define ZONE_BLOCKED 2
#define BLOCKED 3 #define BLOCKED 3

View File

@@ -124,3 +124,5 @@ var/list/be_special_flags = list(
#define Sp_RECHARGE "recharge" #define Sp_RECHARGE "recharge"
#define Sp_CHARGES "charges" #define Sp_CHARGES "charges"
#define Sp_HOLDVAR "holdervar" #define Sp_HOLDVAR "holdervar"
#define CHANGELING_STASIS_COST 20

View File

@@ -33,7 +33,7 @@
#define PROXMOVE 0x80 // Does this object require proximity checking in Enter()? #define PROXMOVE 0x80 // Does this object require proximity checking in Enter()?
//Flags for items (equipment) //Flags for items (equipment)
#define THICKMATERIAL 0x1 // Prevents syringes, parapens and hyposprays if equiped to slot_suit or slot_head. #define THICKMATERIAL 0x1 // Prevents syringes, parapens and hyposprays if equipped to slot_suit or slot_head.
#define STOPPRESSUREDAMAGE 0x2 // Counts towards pressure protection. Note that like temperature protection, body_parts_covered is considered here as well. #define STOPPRESSUREDAMAGE 0x2 // Counts towards pressure protection. Note that like temperature protection, body_parts_covered is considered here as well.
#define AIRTIGHT 0x4 // Functions with internals. #define AIRTIGHT 0x4 // Functions with internals.
#define NOSLIP 0x8 // Prevents from slipping on wet floors, in space, etc. #define NOSLIP 0x8 // Prevents from slipping on wet floors, in space, etc.

View File

@@ -1,110 +0,0 @@
/*
/tg/station13 /atom/movable Pool:
---------------------------------
By RemieRichards
Creation/Deletion is laggy, so let's reduce reuse and recycle!
*/
#define ATOM_POOL_COUNT 100
// "define DEBUG_ATOM_POOL 1
var/global/list/GlobalPool = list()
//You'll be using this proc 90% of the time.
//It grabs a type from the pool if it can
//And if it can't, it creates one
//The pool is flexible and will expand to fit
//The new created atom when it eventually
//Goes into the pool
//Second argument can be a new location, if the type is /atom/movable
//Or a list of arguments
//Either way it gets passed to new
/proc/PoolOrNew(var/get_type,var/second_arg)
var/datum/D
D = GetFromPool(get_type,second_arg)
if(!D)
// So the GC knows we're pooling this type.
if(!GlobalPool[get_type])
GlobalPool[get_type] = list()
if(islist(second_arg))
return new get_type (arglist(second_arg))
else
return new get_type (second_arg)
return D
/proc/GetFromPool(var/get_type,var/second_arg)
if(isnull(GlobalPool[get_type]))
return 0
if(length(GlobalPool[get_type]) == 0)
return 0
var/datum/D = pick_n_take(GlobalPool[get_type])
if(D)
D.ResetVars()
D.Prepare(second_arg)
return D
return 0
/proc/PlaceInPool(var/datum/D)
if(!istype(D))
return
if(length(GlobalPool[D.type]) > ATOM_POOL_COUNT)
#ifdef DEBUG_ATOM_POOL
world << text("DEBUG_DATUM_POOL: PlaceInPool([]) exceeds []. Discarding.", D.type, ATOM_POOL_COUNT)
#endif
if(garbage_collector)
garbage_collector.AddTrash(D)
else
del(D)
return
if(D in GlobalPool[D.type])
return
if(!GlobalPool[D.type])
GlobalPool[D.type] = list()
GlobalPool[D.type] += D
D.Destroy()
D.ResetVars()
/proc/IsPooled(var/datum/D)
if(isnull(GlobalPool[D.type]))
return 0
return 1
/datum/proc/Prepare(args)
if(islist(args))
New(arglist(args))
else
New(args)
/atom/movable/Prepare(args)
var/list/args_list = args
if(istype(args_list) && args_list.len)
loc = args[1]
else
loc = args
..()
/datum/proc/ResetVars(var/list/exlude = list())
var/list/excluded = list("animate_movement", "loc", "locs", "parent_type", "vars", "verbs", "type") + exlude
for(var/V in vars)
if(V in excluded)
continue
vars[V] = initial(vars[V])
/atom/movable/ResetVars()
..()
vars["loc"] = null
#undef ATOM_POOL_COUNT

View File

@@ -284,7 +284,7 @@
if(M.loc && M.locs[1] in hearturfs) if(M.loc && M.locs[1] in hearturfs)
mobs |= M mobs |= M
else if(M.stat == DEAD) else if(M.stat == DEAD && !M.forbid_seeing_deadchat)
switch(type) switch(type)
if(1) //Audio messages use ghost_ears if(1) //Audio messages use ghost_ears
if(M.is_preference_enabled(/datum/client_preference/ghost_ears)) if(M.is_preference_enabled(/datum/client_preference/ghost_ears))

View File

@@ -32,11 +32,6 @@
my_mob.client.screen -= src my_mob.client.screen -= src
my_mob = null my_mob = null
/obj/screen/movable/ability_master/ResetVars()
..("ability_objects", args)
remove_all_abilities()
// ability_objects = list()
/obj/screen/movable/ability_master/MouseDrop() /obj/screen/movable/ability_master/MouseDrop()
if(showing) if(showing)
return return

View File

@@ -20,7 +20,7 @@
return null return null
if(!screen) if(!screen)
screen = PoolOrNew(type) screen = new type()
screen.icon_state = "[initial(screen.icon_state)][severity]" screen.icon_state = "[initial(screen.icon_state)][severity]"
screen.severity = severity screen.severity = severity

View File

@@ -45,49 +45,61 @@
screen_loc = "[screen_loc_X[1]]:[pix_X],[screen_loc_Y[1]]:[pix_Y]" screen_loc = "[screen_loc_X[1]]:[pix_X],[screen_loc_Y[1]]:[pix_Y]"
/obj/screen/movable/proc/encode_screen_X(X) /obj/screen/movable/proc/encode_screen_X(X)
if(X > usr.client.view+1) var/view_dist = world.view
. = "EAST-[usr.client.view*2 + 1-X]" if(view_dist)
else if(X < usr.client.view+1) view_dist = view_dist
if(X > view_dist+1)
. = "EAST-[view_dist *2 + 1-X]"
else if(X < view_dist +1)
. = "WEST+[X-1]" . = "WEST+[X-1]"
else else
. = "CENTER" . = "CENTER"
/obj/screen/movable/proc/decode_screen_X(X) /obj/screen/movable/proc/decode_screen_X(X)
var/view_dist = world.view
if(view_dist)
view_dist = view_dist
//Find EAST/WEST implementations //Find EAST/WEST implementations
if(findtext(X,"EAST-")) if(findtext(X,"EAST-"))
var/num = text2num(copytext(X,6)) //Trim EAST- var/num = text2num(copytext(X,6)) //Trim EAST-
if(!num) if(!num)
num = 0 num = 0
. = usr.client.view*2 + 1 - num . = view_dist*2 + 1 - num
else if(findtext(X,"WEST+")) else if(findtext(X,"WEST+"))
var/num = text2num(copytext(X,6)) //Trim WEST+ var/num = text2num(copytext(X,6)) //Trim WEST+
if(!num) if(!num)
num = 0 num = 0
. = num+1 . = num+1
else if(findtext(X,"CENTER")) else if(findtext(X,"CENTER"))
. = usr.client.view+1 . = view_dist+1
/obj/screen/movable/proc/encode_screen_Y(Y) /obj/screen/movable/proc/encode_screen_Y(Y)
if(Y > usr.client.view+1) var/view_dist = world.view
. = "NORTH-[usr.client.view*2 + 1-Y]" if(view_dist)
else if(Y < usr.client.view+1) view_dist = view_dist
if(Y > view_dist+1)
. = "NORTH-[view_dist*2 + 1-Y]"
else if(Y < view_dist+1)
. = "SOUTH+[Y-1]" . = "SOUTH+[Y-1]"
else else
. = "CENTER" . = "CENTER"
/obj/screen/movable/proc/decode_screen_Y(Y) /obj/screen/movable/proc/decode_screen_Y(Y)
var/view_dist = world.view
if(view_dist)
view_dist = view_dist
if(findtext(Y,"NORTH-")) if(findtext(Y,"NORTH-"))
var/num = text2num(copytext(Y,7)) //Trim NORTH- var/num = text2num(copytext(Y,7)) //Trim NORTH-
if(!num) if(!num)
num = 0 num = 0
. = usr.client.view*2 + 1 - num . = view_dist*2 + 1 - num
else if(findtext(Y,"SOUTH+")) else if(findtext(Y,"SOUTH+"))
var/num = text2num(copytext(Y,7)) //Time SOUTH+ var/num = text2num(copytext(Y,7)) //Time SOUTH+
if(!num) if(!num)
num = 0 num = 0
. = num+1 . = num+1
else if(findtext(Y,"CENTER")) else if(findtext(Y,"CENTER"))
. = usr.client.view+1 . = view_dist+1
//Debug procs //Debug procs
/client/proc/test_movable_UI() /client/proc/test_movable_UI()

View File

@@ -23,10 +23,6 @@
spell_holder.client.screen -= src spell_holder.client.screen -= src
spell_holder = null spell_holder = null
/obj/screen/movable/spell_master/ResetVars()
..("spell_objects", args)
spell_objects = list()
/obj/screen/movable/spell_master/MouseDrop() /obj/screen/movable/spell_master/MouseDrop()
if(showing) if(showing)
return return
@@ -93,7 +89,7 @@
if(spell.spell_flags & NO_BUTTON) //no button to add if we don't get one if(spell.spell_flags & NO_BUTTON) //no button to add if we don't get one
return return
var/obj/screen/spell/newscreen = PoolOrNew(/obj/screen/spell) var/obj/screen/spell/newscreen = new /obj/screen/spell()
newscreen.spellmaster = src newscreen.spellmaster = src
newscreen.spell = spell newscreen.spell = spell

View File

@@ -149,7 +149,7 @@ var/const/tk_maxrange = 15
/obj/item/tk_grab/proc/apply_focus_overlay() /obj/item/tk_grab/proc/apply_focus_overlay()
if(!focus) return if(!focus) return
var/obj/effect/overlay/O = PoolOrNew(/obj/effect/overlay, locate(focus.x,focus.y,focus.z)) var/obj/effect/overlay/O = new /obj/effect/overlay(locate(focus.x,focus.y,focus.z))
O.name = "sparkles" O.name = "sparkles"
O.anchored = 1 O.anchored = 1
O.density = 0 O.density = 0

View File

@@ -152,19 +152,13 @@ world/loop_checks = 0
A.finalize_qdel() A.finalize_qdel()
/datum/proc/finalize_qdel() /datum/proc/finalize_qdel()
if(IsPooled(src)) del(src)
PlaceInPool(src)
else
del(src)
/atom/finalize_qdel() /atom/finalize_qdel()
if(IsPooled(src)) if(garbage_collector)
PlaceInPool(src) garbage_collector.AddTrash(src)
else else
if(garbage_collector) delayed_garbage |= src
garbage_collector.AddTrash(src)
else
delayed_garbage |= src
/icon/finalize_qdel() /icon/finalize_qdel()
del(src) del(src)
@@ -180,7 +174,7 @@ world/loop_checks = 0
// Default implementation of clean-up code. // Default implementation of clean-up code.
// This should be overridden to remove all references pointing to the object being destroyed. // This should be overridden to remove all references pointing to the object being destroyed.
// Return true if the the GC controller should allow the object to continue existing. (Useful if pooling objects.) // Return true if the the GC controller should allow the object to continue existing.
/datum/proc/Destroy() /datum/proc/Destroy()
nanomanager.close_uis(src) nanomanager.close_uis(src)
tag = null tag = null

View File

@@ -167,6 +167,7 @@ var/list/gamemode_cache = list()
var/simultaneous_pm_warning_timeout = 100 var/simultaneous_pm_warning_timeout = 100
var/use_recursive_explosions //Defines whether the server uses recursive or circular explosions. var/use_recursive_explosions //Defines whether the server uses recursive or circular explosions.
var/multi_z_explosion_scalar = 0.5 //Multiplier for how much weaker explosions are on neighboring z levels.
var/assistant_maint = 0 //Do assistants get maint access? var/assistant_maint = 0 //Do assistants get maint access?
var/gateway_delay = 18000 //How long the gateway takes before it activates. Default is half an hour. var/gateway_delay = 18000 //How long the gateway takes before it activates. Default is half an hour.
@@ -284,6 +285,9 @@ var/list/gamemode_cache = list()
if ("use_recursive_explosions") if ("use_recursive_explosions")
use_recursive_explosions = 1 use_recursive_explosions = 1
if ("multi_z_explosion_scalar")
multi_z_explosion_scalar = text2num(value)
if ("log_ooc") if ("log_ooc")
config.log_ooc = 1 config.log_ooc = 1

View File

@@ -0,0 +1,39 @@
/var/repository/decls/decls_repository = new()
/repository/decls
var/list/fetched_decls
var/list/fetched_decl_types
var/list/fetched_decl_subtypes
/repository/decls/New()
..()
fetched_decls = list()
fetched_decl_types = list()
fetched_decl_subtypes = list()
/repository/decls/proc/decls_of_type(var/decl_prototype)
. = fetched_decl_types[decl_prototype]
if(!.)
. = get_decls(typesof(decl_prototype))
fetched_decl_types[decl_prototype] = .
/repository/decls/proc/decls_of_subtype(var/decl_prototype)
. = fetched_decl_subtypes[decl_prototype]
if(!.)
. = get_decls(subtypesof(decl_prototype))
fetched_decl_subtypes[decl_prototype] = .
/repository/decls/proc/get_decl(var/decl_type)
. = fetched_decls[decl_type]
if(!.)
. = new decl_type()
fetched_decls[decl_type] = .
/repository/decls/proc/get_decls(var/list/decl_types)
. = list()
for(var/decl_type in decl_types)
.[decl_type] = get_decl(decl_type)
/decls/Destroy()
crash_with("Prevented attempt to delete a decl instance: [log_info_line(src)]")
return 1 // Prevents Decl destruction

View File

@@ -1,4 +1,19 @@
/repository/New()
return
/datum/cache_entry /datum/cache_entry
var/timestamp var/timestamp
var/data var/data
/datum/cache_entry/New()
timestamp = world.time
/datum/cache_entry/proc/is_valid()
return FALSE
/datum/cache_entry/valid_until/New(var/valid_duration)
..()
timestamp += valid_duration
/datum/cache_entry/valid_until/is_valid()
return world.time < timestamp

View File

@@ -32,6 +32,17 @@
containername = "Special Ops crate" containername = "Special Ops crate"
contraband = 1 contraband = 1
/datum/supply_packs/supply/moghes
name = "Moghes imports"
contains = list(
/obj/item/weapon/reagent_containers/food/drinks/bottle/redeemersbrew = 2,
/obj/item/weapon/reagent_containers/food/snacks/unajerky = 4
)
cost = 25
containertype = /obj/structure/closet/crate
containername = "Moghes imports crate"
contraband = 1
/datum/supply_packs/security/bolt_rifles_mosin /datum/supply_packs/security/bolt_rifles_mosin
name = "Surplus militia rifles" name = "Surplus militia rifles"
contains = list( contains = list(

View File

@@ -200,6 +200,7 @@
/obj/item/clothing/under/det/black = 2, /obj/item/clothing/under/det/black = 2,
/obj/item/clothing/under/det/grey = 2, /obj/item/clothing/under/det/grey = 2,
/obj/item/clothing/head/det/grey = 2, /obj/item/clothing/head/det/grey = 2,
/obj/item/clothing/under/det/skirt = 2,
/obj/item/clothing/under/det = 2, /obj/item/clothing/under/det = 2,
/obj/item/clothing/head/det = 2, /obj/item/clothing/head/det = 2,
/obj/item/clothing/suit/storage/det_trench, /obj/item/clothing/suit/storage/det_trench,

View File

@@ -8,11 +8,6 @@
icon_state = "undershirt" icon_state = "undershirt"
has_color = TRUE has_color = TRUE
/datum/category_item/underwear/undershirt/shirt_long
name = "Long Shirt"
icon_state = "undershirt_long"
has_color = TRUE
/datum/category_item/underwear/undershirt/shirt_fem /datum/category_item/underwear/undershirt/shirt_fem
name = "Babydoll shirt" name = "Babydoll shirt"
icon_state = "undershirt_fem" icon_state = "undershirt_fem"
@@ -23,11 +18,22 @@
icon_state = "undershirt_long" icon_state = "undershirt_long"
has_color = TRUE has_color = TRUE
/datum/category_item/underwear/undershirt/shirt_long_s
name = "Shirt, button-down"
icon_state = "shirt_long_s"
has_color = TRUE
/datum/category_item/underwear/undershirt/shirt_long_fem /datum/category_item/underwear/undershirt/shirt_long_fem
name = "Longsleeve Shirt, feminine" name = "Longsleeve Shirt, feminine"
icon_state = "undershirt_long_fem" icon_state = "undershirt_long_fem"
has_color = TRUE has_color = TRUE
/datum/category_item/underwear/undershirt/shirt_long_female_s
name = "Button-down Shirt, feminine"
icon_state = "shirt_long_female_s"
has_color = TRUE
/datum/category_item/underwear/undershirt/tank_top /datum/category_item/underwear/undershirt/tank_top
name = "Tank top" name = "Tank top"
icon_state = "tanktop" icon_state = "tanktop"

View File

@@ -22,12 +22,12 @@
/datum/uplink_item/item/medical/clotting /datum/uplink_item/item/medical/clotting
name = "Clotting Medicine injector" name = "Clotting Medicine injector"
item_cost = 10 item_cost = 10
path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/clotting path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting
/datum/uplink_item/item/medical/bonemeds /datum/uplink_item/item/medical/bonemeds
name = "Bone Repair injector" name = "Bone Repair injector"
item_cost = 10 item_cost = 10
path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/bonemed path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed
/datum/uplink_item/item/medical/ambrosiadeusseeds /datum/uplink_item/item/medical/ambrosiadeusseeds
name = "Box of 7x ambrosia deus seed packets" name = "Box of 7x ambrosia deus seed packets"

View File

@@ -49,7 +49,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
var/no_air = null var/no_air = null
// var/list/lights // list of all lights on this area // var/list/lights // list of all lights on this area
var/list/all_doors = list() //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area var/list/all_doors = list() //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area
var/air_doors_activated = 0 var/firedoors_closed = 0
var/list/ambience = list('sound/ambience/ambigen1.ogg','sound/ambience/ambigen3.ogg','sound/ambience/ambigen4.ogg','sound/ambience/ambigen5.ogg','sound/ambience/ambigen6.ogg','sound/ambience/ambigen7.ogg','sound/ambience/ambigen8.ogg','sound/ambience/ambigen9.ogg','sound/ambience/ambigen10.ogg','sound/ambience/ambigen11.ogg','sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg') var/list/ambience = list('sound/ambience/ambigen1.ogg','sound/ambience/ambigen3.ogg','sound/ambience/ambigen4.ogg','sound/ambience/ambigen5.ogg','sound/ambience/ambigen6.ogg','sound/ambience/ambigen7.ogg','sound/ambience/ambigen8.ogg','sound/ambience/ambigen9.ogg','sound/ambience/ambigen10.ogg','sound/ambience/ambigen11.ogg','sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg')
var/list/forced_ambience = null var/list/forced_ambience = null
var/sound_env = STANDARD_STATION var/sound_env = STANDARD_STATION

View File

@@ -53,22 +53,28 @@
danger_level = max(danger_level, AA.danger_level) danger_level = max(danger_level, AA.danger_level)
if(danger_level != atmosalm) if(danger_level != atmosalm)
if (danger_level < 1 && atmosalm >= 1)
//closing the doors on red and opening on green provides a bit of hysteresis that will hopefully prevent fire doors from opening and closing repeatedly due to noise
air_doors_open()
else if (danger_level >= 2 && atmosalm < 2)
air_doors_close()
atmosalm = danger_level atmosalm = danger_level
//closing the doors on red and opening on green provides a bit of hysteresis that will hopefully prevent fire doors from opening and closing repeatedly due to noise
if (danger_level < 1 || danger_level >= 2)
firedoors_update()
for (var/obj/machinery/alarm/AA in src) for (var/obj/machinery/alarm/AA in src)
AA.update_icon() AA.update_icon()
return 1 return 1
return 0 return 0
/area/proc/air_doors_close() // Either close or open firedoors depending on current alert statuses
if(!air_doors_activated) /area/proc/firedoors_update()
air_doors_activated = 1 if(fire || party || atmosalm)
firedoors_close()
else
firedoors_open()
// Close all firedoors in the area
/area/proc/firedoors_close()
if(!firedoors_closed)
firedoors_closed = TRUE
for(var/obj/machinery/door/firedoor/E in all_doors) for(var/obj/machinery/door/firedoor/E in all_doors)
if(!E.blocked) if(!E.blocked)
if(E.operating) if(E.operating)
@@ -77,9 +83,10 @@
spawn(0) spawn(0)
E.close() E.close()
/area/proc/air_doors_open() // Open all firedoors in the area
if(air_doors_activated) /area/proc/firedoors_open()
air_doors_activated = 0 if(firedoors_closed)
firedoors_closed = FALSE
for(var/obj/machinery/door/firedoor/E in all_doors) for(var/obj/machinery/door/firedoor/E in all_doors)
if(!E.blocked) if(!E.blocked)
if(E.operating) if(E.operating)
@@ -93,27 +100,13 @@
if(!fire) if(!fire)
fire = 1 //used for firedoor checks fire = 1 //used for firedoor checks
updateicon() updateicon()
mouse_opacity = 0 firedoors_update()
for(var/obj/machinery/door/firedoor/D in all_doors)
if(!D.blocked)
if(D.operating)
D.nextstate = FIREDOOR_CLOSED
else if(!D.density)
spawn()
D.close()
/area/proc/fire_reset() /area/proc/fire_reset()
if (fire) if (fire)
fire = 0 //used for firedoor checks fire = 0 //used for firedoor checks
updateicon() updateicon()
mouse_opacity = 0 firedoors_update()
for(var/obj/machinery/door/firedoor/D in all_doors)
if(!D.blocked)
if(D.operating)
D.nextstate = FIREDOOR_OPEN
else if(D.density)
spawn(0)
D.open()
/area/proc/readyalert() /area/proc/readyalert()
if(!eject) if(!eject)
@@ -131,21 +124,14 @@
if (!( party )) if (!( party ))
party = 1 party = 1
updateicon() updateicon()
mouse_opacity = 0 firedoors_update()
return return
/area/proc/partyreset() /area/proc/partyreset()
if (party) if (party)
party = 0 party = 0
mouse_opacity = 0
updateicon() updateicon()
for(var/obj/machinery/door/firedoor/D in src) firedoors_update()
if(!D.blocked)
if(D.operating)
D.nextstate = FIREDOOR_OPEN
else if(D.density)
spawn(0)
D.open()
return return
/area/proc/updateicon() /area/proc/updateicon()

View File

@@ -21,6 +21,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
var/armor_deployed = 0 //This is only used for changeling_generic_equip_all_slots() at the moment. var/armor_deployed = 0 //This is only used for changeling_generic_equip_all_slots() at the moment.
var/recursive_enhancement = 0 //Used to power up other abilities from the ling power with the same name. var/recursive_enhancement = 0 //Used to power up other abilities from the ling power with the same name.
var/list/purchased_powers_history = list() //Used for round-end report, includes respec uses too. var/list/purchased_powers_history = list() //Used for round-end report, includes respec uses too.
var/last_shriek = null // world.time when the ling last used a shriek.
/datum/changeling/New(var/gender=FEMALE) /datum/changeling/New(var/gender=FEMALE)
..() ..()
@@ -156,6 +157,46 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
//STINGS// //They get a pretty header because there's just so fucking many of them ;_; //STINGS// //They get a pretty header because there's just so fucking many of them ;_;
////////// //////////
turf/proc/AdjacentTurfsRangedSting()
//Yes this is snowflakey, but I couldn't get it to work any other way.. -Luke
var/list/allowed = list(
/obj/structure/table,
/obj/structure/closet,
/obj/structure/frame,
/obj/structure/target_stake,
/obj/structure/cable,
/obj/structure/disposalpipe,
/obj/machinery/
)
var/L[] = new()
for(var/turf/simulated/t in oview(src,1))
var/add = 1
if(t.density)
add = 0
if(add && LinkBlocked(src,t))
add = 0
if(add && TurfBlockedNonWindow(t))
add = 0
for(var/obj/O in t)
if(!O.density)
add = 1
break
if(istype(O, /obj/machinery/door))
//not sure why this doesn't fire on LinkBlocked()
add = 0
break
for(var/type in allowed)
if (istype(O, type))
add = 1
break
if(!add)
break
if(add)
L.Add(t)
return L
/mob/proc/sting_can_reach(mob/M as mob, sting_range = 1) /mob/proc/sting_can_reach(mob/M as mob, sting_range = 1)
if(M.loc == src.loc) if(M.loc == src.loc)
return 1 //target and source are in the same thing return 1 //target and source are in the same thing
@@ -163,7 +204,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
src << "<span class='warning'>We cannot reach \the [M] with a sting!</span>" src << "<span class='warning'>We cannot reach \the [M] with a sting!</span>"
return 0 //One is inside, the other is outside something. return 0 //One is inside, the other is outside something.
// Maximum queued turfs set to 25; I don't *think* anything raises sting_range above 2, but if it does the 25 may need raising // Maximum queued turfs set to 25; I don't *think* anything raises sting_range above 2, but if it does the 25 may need raising
if(!AStar(src.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, max_nodes=25, max_node_depth=sting_range)) //If we can't find a path, fail if(!AStar(src.loc, M.loc, /turf/proc/AdjacentTurfsRangedSting, /turf/proc/Distance, max_nodes=25, max_node_depth=sting_range)) //If we can't find a path, fail
src << "<span class='warning'>We cannot find a path to sting \the [M] by!</span>" src << "<span class='warning'>We cannot find a path to sting \the [M] by!</span>"
return 0 return 0
return 1 return 1

View File

@@ -32,7 +32,7 @@
return 1 return 1
if(M.head || M.wear_suit) //Make sure our slots aren't full if(M.head || M.wear_suit) //Make sure our slots aren't full
src << "<span class='warning'>We require nothing to be on our head, and we cannot wear any external suits.</span>" src << "<span class='warning'>We require nothing to be on our head, and we cannot wear any external suits, or shoes.</span>"
return 0 return 0
var/obj/item/clothing/suit/A = new armor_type(src) var/obj/item/clothing/suit/A = new armor_type(src)
@@ -140,7 +140,7 @@
playsound(src, 'sound/effects/blobattack.ogg', 30, 1) playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
M.update_icons() M.update_icons()
success = 1 success = 1
sleep(20) sleep(1 SECOND)
t = stuff_to_equip["w_uniform"] t = stuff_to_equip["w_uniform"]
if(!M.w_uniform && t) if(!M.w_uniform && t)
@@ -150,7 +150,7 @@
playsound(src, 'sound/effects/blobattack.ogg', 30, 1) playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
M.update_icons() M.update_icons()
success = 1 success = 1
sleep(20) sleep(1 SECOND)
t = stuff_to_equip["gloves"] t = stuff_to_equip["gloves"]
if(!M.gloves && t) if(!M.gloves && t)
@@ -160,7 +160,7 @@
playsound(src, 'sound/effects/splat.ogg', 30, 1) playsound(src, 'sound/effects/splat.ogg', 30, 1)
M.update_icons() M.update_icons()
success = 1 success = 1
sleep(20) sleep(1 SECOND)
t = stuff_to_equip["shoes"] t = stuff_to_equip["shoes"]
if(!M.shoes && t) if(!M.shoes && t)
@@ -170,7 +170,7 @@
playsound(src, 'sound/effects/splat.ogg', 30, 1) playsound(src, 'sound/effects/splat.ogg', 30, 1)
M.update_icons() M.update_icons()
success = 1 success = 1
sleep(20) sleep(1 SECOND)
t = stuff_to_equip["belt"] t = stuff_to_equip["belt"]
if(!M.belt && t) if(!M.belt && t)
@@ -180,7 +180,7 @@
playsound(src, 'sound/effects/splat.ogg', 30, 1) playsound(src, 'sound/effects/splat.ogg', 30, 1)
M.update_icons() M.update_icons()
success = 1 success = 1
sleep(20) sleep(1 SECOND)
t = stuff_to_equip["glasses"] t = stuff_to_equip["glasses"]
if(!M.glasses && t) if(!M.glasses && t)
@@ -190,7 +190,7 @@
playsound(src, 'sound/effects/splat.ogg', 30, 1) playsound(src, 'sound/effects/splat.ogg', 30, 1)
M.update_icons() M.update_icons()
success = 1 success = 1
sleep(20) sleep(1 SECOND)
t = stuff_to_equip["wear_mask"] t = stuff_to_equip["wear_mask"]
if(!M.wear_mask && t) if(!M.wear_mask && t)
@@ -200,7 +200,7 @@
playsound(src, 'sound/effects/splat.ogg', 30, 1) playsound(src, 'sound/effects/splat.ogg', 30, 1)
M.update_icons() M.update_icons()
success = 1 success = 1
sleep(20) sleep(1 SECOND)
t = stuff_to_equip["back"] t = stuff_to_equip["back"]
if(!M.back && t) if(!M.back && t)
@@ -210,7 +210,7 @@
playsound(src, 'sound/effects/blobattack.ogg', 30, 1) playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
M.update_icons() M.update_icons()
success = 1 success = 1
sleep(20) sleep(1 SECOND)
t = stuff_to_equip["wear_suit"] t = stuff_to_equip["wear_suit"]
if(!M.wear_suit && t) if(!M.wear_suit && t)
@@ -220,7 +220,7 @@
playsound(src, 'sound/effects/blobattack.ogg', 30, 1) playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
M.update_icons() M.update_icons()
success = 1 success = 1
sleep(20) sleep(1 SECOND)
t = stuff_to_equip["wear_id"] t = stuff_to_equip["wear_id"]
if(!M.wear_id && t) if(!M.wear_id && t)
@@ -230,7 +230,7 @@
playsound(src, 'sound/effects/splat.ogg', 30, 1) playsound(src, 'sound/effects/splat.ogg', 30, 1)
M.update_icons() M.update_icons()
success = 1 success = 1
sleep(20) sleep(1 SECOND)
var/feedback = english_list(grown_items_list, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" ) var/feedback = english_list(grown_items_list, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )

View File

@@ -18,11 +18,11 @@
if(!changeling) if(!changeling)
return 0 return 0
changeling.chem_charges -= 10 changeling.chem_charges -= 10
src << "<span class='notice'>Your throat adjusts to launch the sting.</span>" to_chat(src, "<span class='notice'>Your throat adjusts to launch the sting.</span>")
var/range = 2 var/range = 2
if(src.mind.changeling.recursive_enhancement) if(src.mind.changeling.recursive_enhancement)
range = range + 3 range = range + 3
src << "<span class='notice'>We can fire our next sting from five squares away.</span>" to_chat(src, "<span class='notice'>We can fire our next sting from five squares away.</span>")
changeling.sting_range = range changeling.sting_range = range
src.verbs -= /mob/proc/changeling_boost_range src.verbs -= /mob/proc/changeling_boost_range
spawn(5) spawn(5)

View File

@@ -18,7 +18,7 @@ var/global/list/changeling_fabricated_clothing = list(
helptext = "The disguise we create offers no defensive ability. Each equipment slot that is empty will be filled with fabricated equipment. \ helptext = "The disguise we create offers no defensive ability. Each equipment slot that is empty will be filled with fabricated equipment. \
To remove our new fabricated clothing, use this ability again." To remove our new fabricated clothing, use this ability again."
ability_icon_state = "ling_fabricate_clothing" ability_icon_state = "ling_fabricate_clothing"
genomecost = 2 genomecost = 1
verbpath = /mob/proc/changeling_fabricate_clothing verbpath = /mob/proc/changeling_fabricate_clothing
//Grows biological versions of chameleon clothes. //Grows biological versions of chameleon clothes.

View File

@@ -12,7 +12,7 @@
set category = "Changeling" set category = "Changeling"
set name = "Regenerative Stasis (20)" set name = "Regenerative Stasis (20)"
var/datum/changeling/changeling = changeling_power(20,1,100,DEAD) var/datum/changeling/changeling = changeling_power(CHANGELING_STASIS_COST,1,100,DEAD)
if(!changeling) if(!changeling)
return return
@@ -28,6 +28,7 @@
C.update_canmove() C.update_canmove()
C.remove_changeling_powers() C.remove_changeling_powers()
changeling.chem_charges -= CHANGELING_STASIS_COST
if(C.suiciding) if(C.suiciding)
C.suiciding = 0 C.suiciding = 0
@@ -35,7 +36,9 @@
if(C.stat != DEAD) if(C.stat != DEAD)
C.adjustOxyLoss(C.maxHealth * 2) C.adjustOxyLoss(C.maxHealth * 2)
spawn(rand(800,2000)) C.forbid_seeing_deadchat = TRUE
spawn(rand(2 MINUTES, 4 MINUTES))
//The ling will now be able to choose when to revive //The ling will now be able to choose when to revive
src.verbs += /mob/proc/changeling_revive src.verbs += /mob/proc/changeling_revive
src << "<span class='notice'><font size='5'>We are ready to rise. Use the <b>Revive</b> verb when you are ready.</font></span>" src << "<span class='notice'><font size='5'>We are ready to rise. Use the <b>Revive</b> verb when you are ready.</font></span>"

View File

@@ -29,6 +29,3 @@
src << "<span class='notice'>We have removed our evolutions from this form, and are now ready to readapt.</span>" src << "<span class='notice'>We have removed our evolutions from this form, and are now ready to readapt.</span>"
ling_datum.purchased_powers_history.Add("Re-adapt (Reset to [ling_datum.max_geneticpoints])") ling_datum.purchased_powers_history.Add("Re-adapt (Reset to [ling_datum.max_geneticpoints])")
//Now to lose the verb, so no unlimited resets.

View File

@@ -41,6 +41,10 @@
current_limb.undislocate() current_limb.undislocate()
current_limb.open = 0 current_limb.open = 0
BITSET(H.hud_updateflag, HEALTH_HUD)
BITSET(H.hud_updateflag, STATUS_HUD)
BITSET(H.hud_updateflag, LIFE_HUD)
C.halloss = 0 C.halloss = 0
C.shock_stage = 0 //Pain C.shock_stage = 0 //Pain
C << "<span class='notice'>We have regenerated.</span>" C << "<span class='notice'>We have regenerated.</span>"
@@ -48,8 +52,12 @@
C.mind.changeling.purchased_powers -= C C.mind.changeling.purchased_powers -= C
feedback_add_details("changeling_powers","CR") feedback_add_details("changeling_powers","CR")
C.stat = CONSCIOUS C.stat = CONSCIOUS
C.forbid_seeing_deadchat = FALSE
C.timeofdeath = null C.timeofdeath = null
src.verbs -= /mob/proc/changeling_revive src.verbs -= /mob/proc/changeling_revive
// re-add our changeling powers // re-add our changeling powers
C.make_changeling() C.make_changeling()
return 1 return 1

View File

@@ -35,6 +35,14 @@
src << "<span class='danger'>You can't speak!</span>" src << "<span class='danger'>You can't speak!</span>"
return 0 return 0
if(world.time < (changeling.last_shriek + 10 SECONDS) )
to_chat(src, "<span class='warning'>We are still recovering from our last shriek...</span>")
return 0
if(!isturf(loc))
to_chat(src, "<span class='warning'>Shrieking here would be a bad idea.</span>")
return 0
src.break_cloak() //No more invisible shrieking src.break_cloak() //No more invisible shrieking
changeling.chem_charges -= 20 changeling.chem_charges -= 20
@@ -47,6 +55,8 @@
message_admins("[key_name(src)] used Resonant Shriek ([src.x],[src.y],[src.z]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>).") message_admins("[key_name(src)] used Resonant Shriek ([src.x],[src.y],[src.z]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>).")
log_game("[key_name(src)] used Resonant Shriek.") log_game("[key_name(src)] used Resonant Shriek.")
visible_message("<span class='notice'>[src] appears to shout.</span>")
for(var/mob/living/M in range(range, src)) for(var/mob/living/M in range(range, src))
if(iscarbon(M)) if(iscarbon(M))
if(!M.mind || !M.mind.changeling) if(!M.mind || !M.mind.changeling)
@@ -73,11 +83,7 @@
L.on = 1 L.on = 1
L.broken() L.broken()
/* src.verbs -= /mob/proc/changeling_resonant_shriek changeling.last_shriek = world.time
spawn(30 SECONDS)
src << "<span class='notice'>We are ready to use our resonant shriek once more.</span>"
src.verbs |= /mob/proc/changeling_resonant_shriek
Ability Cooldowns don't work properly right now, need to redo this when they are */
feedback_add_details("changeling_powers","RS") feedback_add_details("changeling_powers","RS")
return 1 return 1
@@ -101,6 +107,14 @@ Ability Cooldowns don't work properly right now, need to redo this when they are
src << "<span class='danger'>You can't speak!</span>" src << "<span class='danger'>You can't speak!</span>"
return 0 return 0
if(world.time < (changeling.last_shriek + 10 SECONDS) )
to_chat(src, "<span class='warning'>We are still recovering from our last shriek...</span>")
return 0
if(!isturf(loc))
to_chat(src, "<span class='warning'>Shrieking here would be a bad idea.</span>")
return 0
src.break_cloak() //No more invisible shrieking src.break_cloak() //No more invisible shrieking
changeling.chem_charges -= 20 changeling.chem_charges -= 20
@@ -117,6 +131,8 @@ Ability Cooldowns don't work properly right now, need to redo this when they are
src << "<span class='notice'>We are extra loud.</span>" src << "<span class='notice'>We are extra loud.</span>"
src.mind.changeling.recursive_enhancement = 0 src.mind.changeling.recursive_enhancement = 0
visible_message("<span class='notice'>[src] appears to shout.</span>")
src.attack_log += text("\[[time_stamp()]\] <font color='red'>Used Dissonant Shriek.</font>") src.attack_log += text("\[[time_stamp()]\] <font color='red'>Used Dissonant Shriek.</font>")
message_admins("[key_name(src)] used Dissonant Shriek ([src.x],[src.y],[src.z]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>).") message_admins("[key_name(src)] used Dissonant Shriek ([src.x],[src.y],[src.z]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>).")
log_game("[key_name(src)] used Dissonant Shriek.") log_game("[key_name(src)] used Dissonant Shriek.")
@@ -126,9 +142,6 @@ Ability Cooldowns don't work properly right now, need to redo this when they are
L.broken() L.broken()
empulse(get_turf(src), range_heavy, range_light, 1) empulse(get_turf(src), range_heavy, range_light, 1)
/* src.verbs -= /mob/proc/changeling_dissonant_shriek changeling.last_shriek = world.time
spawn(30 SECONDS)
src << "<span class='notice'>We are ready to use our dissonant shriek once more.</span>"
src.verbs |= /mob/proc/changeling_dissonant_shriek
Ability Cooldowns don't work properly right now, need to redo this when they are */
return 1 return 1

View File

@@ -13,6 +13,10 @@
var/datum/changeling/changeling = changeling_power(5,1,0) var/datum/changeling/changeling = changeling_power(5,1,0)
if(!changeling) return if(!changeling) return
if(!isturf(loc))
to_chat(src, "<span class='warning'>Transforming here would be a bad idea.</span>")
return 0
var/list/names = list() var/list/names = list()
for(var/datum/absorbed_dna/DNA in changeling.absorbed_dna) for(var/datum/absorbed_dna/DNA in changeling.absorbed_dna)
names += "[DNA.name]" names += "[DNA.name]"

View File

@@ -3,7 +3,7 @@
desc = "We rapidly shape the color of our skin and secrete easily reversible dye on our clothes, to blend in with our surroundings. \ desc = "We rapidly shape the color of our skin and secrete easily reversible dye on our clothes, to blend in with our surroundings. \
We are undetectable, so long as we move slowly.(Toggle)" We are undetectable, so long as we move slowly.(Toggle)"
helptext = "Running, and performing most acts will reveal us. Our chemical regeneration is halted while we are hidden." helptext = "Running, and performing most acts will reveal us. Our chemical regeneration is halted while we are hidden."
enhancedtext = "True invisiblity while cloaked." enhancedtext = "Can run while hidden."
ability_icon_state = "ling_camoflage" ability_icon_state = "ling_camoflage"
genomecost = 3 genomecost = 3
verbpath = /mob/proc/changeling_visible_camouflage verbpath = /mob/proc/changeling_visible_camouflage
@@ -31,20 +31,35 @@
var/old_regen_rate = H.mind.changeling.chem_recharge_rate var/old_regen_rate = H.mind.changeling.chem_recharge_rate
H << "<span class='notice'>We vanish from sight, and will remain hidden, so long as we move carefully.</span>" H << "<span class='notice'>We vanish from sight, and will remain hidden, so long as we move carefully.</span>"
H.set_m_intent("walk")
H.mind.changeling.cloaked = 1 H.mind.changeling.cloaked = 1
H.mind.changeling.chem_recharge_rate = 0 H.mind.changeling.chem_recharge_rate = 0
animate(src,alpha = 255, alpha = 10, time = 10) animate(src,alpha = 255, alpha = 10, time = 10)
var/must_walk = TRUE
if(src.mind.changeling.recursive_enhancement) if(src.mind.changeling.recursive_enhancement)
H.invisibility = INVISIBILITY_OBSERVER must_walk = FALSE
src << "<span class='notice'>We are now truly invisible.</span>" to_chat(src, "<span class='notice'>We may move at our normal speed while hidden.</span>")
if(must_walk)
H.set_m_intent("walk")
var/remain_cloaked = TRUE
while(remain_cloaked) //This loop will keep going until the player uncloaks.
sleep(1 SECOND) // Sleep at the start so that if something invalidates a cloak, it will drop immediately after the check and not in one second.
if(H.m_intent != "walk" && must_walk) // Moving too fast uncloaks you.
remain_cloaked = 0
if(!H.mind.changeling.cloaked)
remain_cloaked = 0
if(H.stat) // Dead or unconscious lings can't stay cloaked.
remain_cloaked = 0
if(H.incapacitated(INCAPACITATION_DISABLED)) // Stunned lings also can't stay cloaked.
remain_cloaked = 0
while(H.m_intent == "walk" && H.mind.changeling.cloaked && !H.stat) //This loop will keep going until the player uncloaks.
if(mind.changeling.chem_recharge_rate != 0) //Without this, there is an exploit that can be done, if one buys engorged chem sacks while cloaked. if(mind.changeling.chem_recharge_rate != 0) //Without this, there is an exploit that can be done, if one buys engorged chem sacks while cloaked.
old_regen_rate += mind.changeling.chem_recharge_rate //Unfortunately, it has to occupy this part of the proc. This fixes it while at the same time old_regen_rate += mind.changeling.chem_recharge_rate //Unfortunately, it has to occupy this part of the proc. This fixes it while at the same time
mind.changeling.chem_recharge_rate = 0 //making sure nobody loses out on their bonus regeneration after they're done hiding. mind.changeling.chem_recharge_rate = 0 //making sure nobody loses out on their bonus regeneration after they're done hiding.
sleep(10)
H.invisibility = initial(invisibility) H.invisibility = initial(invisibility)

View File

@@ -59,7 +59,7 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
if(14) if(14)
Holiday["Pi Day"] = "An unoffical holiday celebrating the mathematical constant Pi. It is celebrated on \ Holiday["Pi Day"] = "An unoffical holiday celebrating the mathematical constant Pi. It is celebrated on \
March 14th, as the digits form 3 14, the first three significant digits of Pi. Observance of Pi Day generally \ March 14th, as the digits form 3 14, the first three significant digits of Pi. Observance of Pi Day generally \
imvolve eating (or throwing) pie, due to a pun. Pies also tend to be round, and thus relatable to Pi." involve eating (or throwing) pie, due to a pun. Pies also tend to be round, and thus relatable to Pi."
if(17) if(17)
Holiday["St. Patrick's Day"] = "An old holiday originating from Earth, Sol, celebrating the color green, \ Holiday["St. Patrick's Day"] = "An old holiday originating from Earth, Sol, celebrating the color green, \
shamrocks, attending parades, and drinking alcohol." shamrocks, attending parades, and drinking alcohol."
@@ -93,6 +93,12 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
switch(DD) switch(DD)
if(1) if(1)
Holiday["Interstellar Workers' Day"] = "This holiday celebrates the work of laborers and the working class." Holiday["Interstellar Workers' Day"] = "This holiday celebrates the work of laborers and the working class."
if(18)
Holiday["Remembrance Day"] = "Remembrance Day (or, as it is more informally known, Armistice Day) is a confederation-wide holiday \
mostly observed by its member states since late 2520. Officially, it is a day of remembering the men and women who died in various armed conflicts \
throughout human history. Unofficially, however, it is commonly treated as a holiday honoring the victims of the Human-Unathi war. \
Observance of this day varies throughout human space, but most common traditions are the act of bringing flowers to graves,\
attending parades, and the wearing of poppies (either paper or real) in one's clothing."
if(28) if(28)
Holiday["Jiql-tes"] = "A Skrellian holiday that translates to 'Day of Celebration', Skrell communities \ Holiday["Jiql-tes"] = "A Skrellian holiday that translates to 'Day of Celebration', Skrell communities \
gather for a grand feast and give gifts to friends and close relatives." gather for a grand feast and give gifts to friends and close relatives."
@@ -105,6 +111,9 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
if(14) if(14)
Holiday["Blood Donor Day"] = "This holiday was created to raise awareness of the need for safe blood and blood products, \ Holiday["Blood Donor Day"] = "This holiday was created to raise awareness of the need for safe blood and blood products, \
and to thank blood donors for their voluntary, life-saving gifts of blood." and to thank blood donors for their voluntary, life-saving gifts of blood."
if(20)
Holiday["Civil Servant's Day"] = "Civil Servant's Day is a holiday observed in SCG member states that honors civil servants everywhere,\
+ (especially those who are members of the armed forces and the emergency services), or have been or have been civil servants in the past."
if(7) //Jul if(7) //Jul
switch(DD) switch(DD)

View File

@@ -7,9 +7,9 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind'
/datum/game_mode/heist /datum/game_mode/heist
name = "Heist" name = "Heist"
config_tag = "heist" config_tag = "heist"
required_players = 8 required_players = 15
required_players_secret = 8 required_players_secret = 15
required_enemies = 3 required_enemies = 4
round_description = "An unidentified bluespace signature is approaching the station!" round_description = "An unidentified bluespace signature is approaching the station!"
extended_round_description = "The Company's majority control of phoron in the system has marked the \ extended_round_description = "The Company's majority control of phoron in the system has marked the \
station to be a highly valuable target for many competing organizations and individuals. Being a \ station to be a highly valuable target for many competing organizations and individuals. Being a \
@@ -17,10 +17,3 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind'
attempts of robbery, fraud and other malicious actions." attempts of robbery, fraud and other malicious actions."
end_on_antag_death = 0 end_on_antag_death = 0
antag_tags = list(MODE_RAIDER) antag_tags = list(MODE_RAIDER)
/datum/game_mode/heist/check_finished()
if(!..())
var/datum/shuttle/multi_shuttle/skipjack = shuttle_controller.shuttles["Skipjack"]
if (skipjack && skipjack.returned_home)
return 1
return 0

View File

@@ -12,9 +12,9 @@ var/list/nuke_disks = list()
colony of sizable population and considerable wealth causes it to often be the target of various \ colony of sizable population and considerable wealth causes it to often be the target of various \
attempts of robbery, fraud and other malicious actions." attempts of robbery, fraud and other malicious actions."
config_tag = "mercenary" config_tag = "mercenary"
required_players = 8 required_players = 15
required_players_secret = 8 required_players_secret = 15
required_enemies = 3 required_enemies = 4
end_on_antag_death = 0 end_on_antag_death = 0
var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station
var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level

View File

@@ -30,7 +30,7 @@
/obj/item/weapon/antag_spawner/technomancer_apprentice/New() /obj/item/weapon/antag_spawner/technomancer_apprentice/New()
..() ..()
sparks = PoolOrNew(/datum/effect/effect/system/spark_spread) sparks = new /datum/effect/effect/system/spark_spread()
sparks.set_up(5, 0, src) sparks.set_up(5, 0, src)
sparks.attach(loc) sparks.attach(loc)

View File

@@ -5,12 +5,11 @@
amount_per_transfer_from_this = 15 amount_per_transfer_from_this = 15
volume = 15 volume = 15
origin_tech = list(TECH_BIO = 4) origin_tech = list(TECH_BIO = 4)
filled_reagents = list("inaprovaline" = 15)
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/New() /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/New()
..() ..()
reagents.remove_reagent("inaprovaline", 5)
update_icon()
return
/datum/technomancer/consumable/hypo_brute /datum/technomancer/consumable/hypo_brute
name = "Trauma Hypo" name = "Trauma Hypo"
@@ -66,127 +65,44 @@
name = "trauma hypo" name = "trauma hypo"
desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to be used on victims of \ desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to be used on victims of \
moderate blunt trauma." moderate blunt trauma."
icon_state = "autoinjector" filled_reagents = list("bicaridine" = 15)
amount_per_transfer_from_this = 15
volume = 15
origin_tech = list(TECH_BIO = 4)
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute/New()
..()
reagents.add_reagent("bicaridine", 15)
update_icon()
return
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn
name = "burn hypo" name = "burn hypo"
desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to be used on burn victims, \ desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to be used on burn victims, \
featuring an optimized chemical mixture to allow for rapid healing." featuring an optimized chemical mixture to allow for rapid healing."
icon_state = "autoinjector" filled_reagents = list("kelotane" = 7.5, "dermaline" = 7.5)
amount_per_transfer_from_this = 15
volume = 15
origin_tech = list(TECH_BIO = 4)
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn/New()
..()
reagents.add_reagent("kelotane", 7.5)
reagents.add_reagent("dermaline", 7.5)
update_icon()
return
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/toxin /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/toxin
name = "toxin hypo" name = "toxin hypo"
desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to counteract toxins." desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to counteract toxins."
icon_state = "autoinjector" filled_reagents = list("anti_toxin" = 15)
amount_per_transfer_from_this = 15
volume = 15
origin_tech = list(TECH_BIO = 4)
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/toxin/New()
..()
reagents.add_reagent("anti_toxin", 15)
update_icon()
return
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/oxy /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/oxy
name = "oxy hypo" name = "oxy hypo"
desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to counteract oxygen \ desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to counteract oxygen \
deprivation." deprivation."
icon_state = "autoinjector" filled_reagents = list("dexalinp" = 10, "tricordrazine" = 5)
amount_per_transfer_from_this = 15
volume = 15
origin_tech = list(TECH_BIO = 4)
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/oxy/New()
..()
reagents.add_reagent("dexalinp", 10)
reagents.add_reagent("tricordrazine", 5) //Dex+ ODs above 10, so we add tricord to pad it out somewhat.
update_icon()
return
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity
name = "purity hypo" name = "purity hypo"
desc = "A refined version of the standard autoinjector, allowing greater capacity. This varient excels at \ desc = "A refined version of the standard autoinjector, allowing greater capacity. This varient excels at \
resolving viruses, infections, radiation, and genetic maladies." resolving viruses, infections, radiation, and genetic maladies."
icon_state = "autoinjector" filled_reagents = list("spaceacillin" = 9, "arithrazine" = 5, "ryetalyn" = 1)
amount_per_transfer_from_this = 15
volume = 15
origin_tech = list(TECH_BIO = 4)
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity/New()
..()
reagents.add_reagent("spaceacillin", 9)
reagents.add_reagent("arithrazine", 5)
reagents.add_reagent("ryetalyn", 1)
update_icon()
return
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain
name = "pain hypo" name = "pain hypo"
desc = "A refined version of the standard autoinjector, allowing greater capacity. This one contains potent painkillers." desc = "A refined version of the standard autoinjector, allowing greater capacity. This one contains potent painkillers."
icon_state = "autoinjector" filled_reagents = list("tramadol" = 15)
amount_per_transfer_from_this = 15
volume = 15
origin_tech = list(TECH_BIO = 4)
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain/New()
..()
reagents.add_reagent("tramadol", 15)
update_icon()
return
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ
name = "organ hypo" name = "organ hypo"
desc = "A refined version of the standard autoinjector, allowing greater capacity. Organ damage is resolved by this varient." desc = "A refined version of the standard autoinjector, allowing greater capacity. Organ damage is resolved by this varient."
icon_state = "autoinjector" filled_reagents = list("alkysine" = 1, "imidazoline" = 1, "peridaxon" = 13)
amount_per_transfer_from_this = 15
volume = 15
origin_tech = list(TECH_BIO = 4)
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ/New()
..()
reagents.add_reagent("alkysine", 1)
reagents.add_reagent("imidazoline", 1)
reagents.add_reagent("peridaxon", 13)
update_icon()
return
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat
name = "combat hypo" name = "combat hypo"
desc = "A refined version of the standard autoinjector, allowing greater capacity. This is a more dangerous and potentially \ desc = "A refined version of the standard autoinjector, allowing greater capacity. This is a more dangerous and potentially \
addictive hypo compared to others, as it contains a potent cocktail of various chemicals to optimize the recipient's combat \ addictive hypo compared to others, as it contains a potent cocktail of various chemicals to optimize the recipient's combat \
ability." ability."
icon_state = "autoinjector" filled_reagents = list("bicaridine" = 3, "kelotane" = 1.5, "dermaline" = 1.5, "oxycodone" = 3, "hyperzine" = 3, "tricordrazine" = 3)
amount_per_transfer_from_this = 15
volume = 15
origin_tech = list(TECH_BIO = 4)
/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat/New()
..()
reagents.add_reagent("bicaridine", 3)
reagents.add_reagent("kelotane", 1.5)
reagents.add_reagent("dermaline", 1.5)
reagents.add_reagent("oxycodone", 3)
reagents.add_reagent("hyperzine", 3)
reagents.add_reagent("tricordrazine", 3)
update_icon()
return

View File

@@ -26,7 +26,7 @@
/obj/item/clothing/suit/armor/shield/New() /obj/item/clothing/suit/armor/shield/New()
..() ..()
spark_system = PoolOrNew(/datum/effect/effect/system/spark_spread) spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src) spark_system.set_up(5, 0, src)
/obj/item/clothing/suit/armor/shield/Destroy() /obj/item/clothing/suit/armor/shield/Destroy()

View File

@@ -191,6 +191,7 @@
icon_state = "scepter" icon_state = "scepter"
force = 15 force = 15
slot_flags = SLOT_BELT slot_flags = SLOT_BELT
attack_verb = list("beaten", "smashed", "struck", "whacked")
/obj/item/weapon/scepter/attack_self(mob/living/carbon/human/user) /obj/item/weapon/scepter/attack_self(mob/living/carbon/human/user)
var/obj/item/item_to_test = user.get_other_hand(src) var/obj/item/item_to_test = user.get_other_hand(src)

View File

@@ -102,7 +102,7 @@
rng = rand(0,1) rng = rand(0,1)
switch(rng) switch(rng)
if(0) if(0)
var/datum/effect/effect/system/spark_spread/sparks = PoolOrNew(/datum/effect/effect/system/spark_spread) var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
sparks.set_up(5, 0, src) sparks.set_up(5, 0, src)
sparks.attach(loc) sparks.attach(loc)
sparks.start() sparks.start()
@@ -167,10 +167,10 @@
rng = rand(0,1) rng = rand(0,1)
switch(rng) switch(rng)
if(0) if(0)
var/datum/effect/effect/system/spark_spread/sparks = PoolOrNew(/datum/effect/effect/system/spark_spread) var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
sparks.set_up(5, 0, src) sparks.set_up(5, 0, src)
sparks.attach(loc) sparks.attach(loc)
// var/datum/effect/effect/system/spark_spread/spark_system = PoolOrNew(/datum/effect/effect/system/spark_spread) // var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
// spark_system.set_up(5, 0, get_turf(src)) // spark_system.set_up(5, 0, get_turf(src))
// spark_system.attach(src) // spark_system.attach(src)
sparks.start() sparks.start()
@@ -285,4 +285,4 @@
to_chat(H, "<span class='warning'>The purple glow makes you feel strange...</span>") to_chat(H, "<span class='warning'>The purple glow makes you feel strange...</span>")
H.adjust_instability(outgoing_instability) H.adjust_instability(outgoing_instability)
set_light(distance, distance * 2, l_color = "#C26DDE") set_light(distance, distance * 4, l_color = "#C26DDE")

View File

@@ -247,7 +247,7 @@
if(!path || !ispath(path)) if(!path || !ispath(path))
return 0 return 0
//var/obj/item/weapon/spell/S = PoolOrNew(path, src) //var/obj/item/weapon/spell/S = new path(src)
var/obj/item/weapon/spell/S = new path(src) var/obj/item/weapon/spell/S = new path(src)
//No hands needed for innate casts. //No hands needed for innate casts.

View File

@@ -24,7 +24,7 @@
spawn(1) spawn(1)
var/turf/desired_turf = get_step(T,direction) var/turf/desired_turf = get_step(T,direction)
if(desired_turf) // This shouldn't fail but... if(desired_turf) // This shouldn't fail but...
var/obj/effect/effect/water/W = PoolOrNew(/obj/effect/effect/water, get_turf(T)) var/obj/effect/effect/water/W = new /obj/effect/effect/water(get_turf(T))
W.create_reagents(60) W.create_reagents(60)
W.reagents.add_reagent(id = "water", amount = 60, data = null, safety = 0) W.reagents.add_reagent(id = "water", amount = 60, data = null, safety = 0)
W.set_color() W.set_color()

View File

@@ -21,5 +21,6 @@
for(var/obj/item/weapon/inserted_spell/I in target) for(var/obj/item/weapon/inserted_spell/I in target)
I.on_expire(dispelled = 1) I.on_expire(dispelled = 1)
log_and_message_admins("dispelled [I] on [target].") log_and_message_admins("dispelled [I] on [target].")
target.remove_modifiers_of_type(/datum/modifier/technomancer)
user.adjust_instability(10) user.adjust_instability(10)
qdel(src) qdel(src)

View File

@@ -93,6 +93,9 @@
var/walking = 0 var/walking = 0
var/step_delay = 10 var/step_delay = 10
/mob/living/simple_animal/illusion/update_icon() // We don't want the appearance changing AT ALL unless by copy_appearance().
return
/mob/living/simple_animal/illusion/proc/copy_appearance(var/atom/movable/thing_to_copy) /mob/living/simple_animal/illusion/proc/copy_appearance(var/atom/movable/thing_to_copy)
if(!thing_to_copy) if(!thing_to_copy)
return 0 return 0

View File

@@ -1,42 +0,0 @@
/datum/technomancer/spell/corona
name = "Corona"
desc = "Causes the victim to glow very brightly, which while harmless in itself, makes it easier for them to be hit. The \
bright glow also makes it very difficult to be stealthy. The effect lasts for one minute."
spell_power_desc = "Enemies become even easier to hit."
cost = 50
obj_path = /obj/item/weapon/spell/insert/corona
ability_icon_state = "tech_corona"
category = SUPPORT_SPELLS
/obj/item/weapon/spell/insert/corona
name = "corona"
desc = "How brillient!"
icon_state = "radiance"
cast_methods = CAST_RANGED
aspect = ASPECT_LIGHT
light_color = "#D9D900"
spell_light_intensity = 5
spell_light_range = 3
inserting = /obj/item/weapon/inserted_spell/corona
/obj/item/weapon/inserted_spell/corona
var/evasion_reduction = 2 // We store this here because spell power may change when the spell expires.
/obj/item/weapon/inserted_spell/corona/on_insert()
spawn(1)
if(isliving(host))
var/mob/living/L = host
evasion_reduction = round(2 * spell_power_at_creation, 1)
L.evasion -= evasion_reduction
L.visible_message("<span class='warning'>You start to glow very brightly!</span>")
spawn(1 MINUTE)
if(src)
on_expire()
/obj/item/weapon/inserted_spell/corona/on_expire()
if(isliving(host))
var/mob/living/L = host
L.evasion += evasion_reduction
L << "<span class='notice'>Your glow has ended.</span>"
..()

View File

@@ -1,36 +0,0 @@
/datum/technomancer/spell/haste
name = "Haste"
desc = "Allows the target to run at speeds that should not be possible for an ordinary being. For five seconds, the target \
runs extremly fast, and cannot be slowed by any means."
spell_power_desc = "Duration is scaled up."
cost = 100
obj_path = /obj/item/weapon/spell/insert/haste
ability_icon_state = "tech_haste"
category = SUPPORT_SPELLS
/obj/item/weapon/spell/insert/haste
name = "haste"
desc = "Now you can outrun a Teshari!"
icon_state = "haste"
cast_methods = CAST_RANGED
aspect = ASPECT_FORCE
light_color = "#FF5C5C"
inserting = /obj/item/weapon/inserted_spell/haste
/obj/item/weapon/inserted_spell/haste/on_insert()
spawn(1)
if(isliving(host))
var/mob/living/L = host
L.force_max_speed = 1
L << "<span class='notice'>You suddenly find it much easier to move.</span>"
L.adjust_instability(10)
spawn(round(5 SECONDS * spell_power_at_creation, 1))
if(src)
on_expire()
/obj/item/weapon/inserted_spell/haste/on_expire()
if(isliving(host))
var/mob/living/L = host
L.force_max_speed = 0
L << "<span class='warning'>You feel slow again.</span>"
..()

View File

@@ -1,39 +0,0 @@
/datum/technomancer/spell/repel_missiles
name = "Repel Missiles"
desc = "Places a repulsion field around you, which attempts to deflect incoming bullets and lasers, making them 30% less likely \
to hit you. The field lasts for five minutes and can be granted to yourself or an ally."
spell_power_desc = "Projectiles will be more likely to be deflected."
cost = 25
obj_path = /obj/item/weapon/spell/insert/repel_missiles
ability_icon_state = "tech_repelmissiles"
category = SUPPORT_SPELLS
/obj/item/weapon/spell/insert/repel_missiles
name = "repel missiles"
desc = "Use it before they start shooting at you!"
icon_state = "generic"
cast_methods = CAST_RANGED
aspect = ASPECT_FORCE
light_color = "#FF5C5C"
inserting = /obj/item/weapon/inserted_spell/repel_missiles
/obj/item/weapon/inserted_spell/repel_missiles
var/evasion_increased = 2 // We store this here because spell power may change when the spell expires.
/obj/item/weapon/inserted_spell/repel_missiles/on_insert()
spawn(1)
if(isliving(host))
var/mob/living/L = host
evasion_increased = round(2 * spell_power_at_creation, 1)
L.evasion += evasion_increased
L << "<span class='notice'>You have a repulsion field around you, which will attempt to deflect projectiles.</span>"
spawn(5 MINUTES)
if(src)
on_expire()
/obj/item/weapon/inserted_spell/repel_missiles/on_expire()
if(isliving(host))
var/mob/living/L = host
L.evasion -= evasion_increased
L << "<span class='warning'>Your repulsion field has expired.</span>"
..()

View File

@@ -0,0 +1,33 @@
/datum/technomancer/spell/corona
name = "Corona"
desc = "Causes the victim to glow very brightly, which while harmless in itself, makes it easier for them to be hit. The \
bright glow also makes it very difficult to be stealthy. The effect lasts for one minute."
cost = 50
obj_path = /obj/item/weapon/spell/modifier/corona
ability_icon_state = "tech_corona"
category = SUPPORT_SPELLS
/obj/item/weapon/spell/modifier/corona
name = "corona"
desc = "How brillient!"
icon_state = "radiance"
cast_methods = CAST_RANGED
aspect = ASPECT_LIGHT
light_color = "#D9D900"
spell_light_intensity = 5
spell_light_range = 3
modifier_type = /datum/modifier/technomancer/corona
modifier_duration = 1 MINUTE
/datum/modifier/technomancer/corona
name = "corona"
desc = "You appear to be glowing really bright. It doesn't seem to hurt, however hiding will be impossible."
mob_overlay_state = "corona"
on_created_text = "<span class='warning'>You start to glow very brightly!</span>"
on_expired_text = "<span class='notice'>Your glow has ended.</span>"
evasion = -2
stacks = MODIFIER_STACK_EXTEND
/datum/modifier/technomancer/corona/tick()
holder.break_cloak()

View File

@@ -0,0 +1,28 @@
/datum/technomancer/spell/haste
name = "Haste"
desc = "Allows the target to run at speeds that should not be possible for an ordinary being. For five seconds, the target \
runs extremly fast, and cannot be slowed by any means."
cost = 100
obj_path = /obj/item/weapon/spell/modifier/haste
ability_icon_state = "tech_haste"
category = SUPPORT_SPELLS
/obj/item/weapon/spell/modifier/haste
name = "haste"
desc = "Now you can outrun a Teshari!"
icon_state = "haste"
cast_methods = CAST_RANGED
aspect = ASPECT_FORCE
light_color = "#FF5C5C"
modifier_type = /datum/modifier/technomancer/haste
modifier_duration = 5 SECONDS
/datum/modifier/technomancer/haste
name = "haste"
desc = "Moving is almost effortless!"
mob_overlay_state = "haste"
on_created_text = "<span class='notice'>You suddenly find it much easier to move.</span>"
on_expired_text = "<span class='warning'>You feel slow again.</span>"
haste = TRUE
stacks = MODIFIER_STACK_EXTEND

View File

@@ -0,0 +1,31 @@
/obj/item/weapon/spell/modifier
name = "modifier template"
desc = "Tell a coder if you can read this in-game."
icon_state = "purify"
cast_methods = CAST_MELEE
var/modifier_type = null
var/modifier_duration = null // Will last forever by default. Final duration may differ due to 'spell power'
// var/spell_color = "#03A728"
var/spell_light_intensity = 2
var/spell_light_range = 3
/obj/item/weapon/spell/modifier/New()
..()
set_light(spell_light_range, spell_light_intensity, l_color = light_color)
/obj/item/weapon/spell/modifier/on_melee_cast(atom/hit_atom, mob/user)
if(istype(hit_atom, /mob/living))
on_add_modifier(hit_atom)
/obj/item/weapon/spell/modifier/on_ranged_cast(atom/hit_atom, mob/user)
if(istype(hit_atom, /mob/living))
on_add_modifier(hit_atom)
/obj/item/weapon/spell/modifier/proc/on_add_modifier(var/mob/living/L)
var/duration = modifier_duration
if(duration)
duration = round(duration * calculate_spell_power(1.0), 1)
L.add_modifier(modifier_type, duration)
log_and_message_admins("has casted [src] on [L].")
qdel(src)

View File

@@ -0,0 +1,28 @@
/datum/technomancer/spell/repel_missiles
name = "Repel Missiles"
desc = "Places a repulsion field around you, which attempts to deflect incoming bullets and lasers, making them 30% less likely \
to hit you. The field lasts for 10 minutes and can be granted to yourself or an ally."
cost = 25
obj_path = /obj/item/weapon/spell/modifier/repel_missiles
ability_icon_state = "tech_repelmissiles"
category = SUPPORT_SPELLS
/obj/item/weapon/spell/modifier/repel_missiles
name = "repel missiles"
desc = "Use it before they start shooting at you!"
icon_state = "generic"
cast_methods = CAST_RANGED
aspect = ASPECT_FORCE
light_color = "#FF5C5C"
modifier_type = /datum/modifier/technomancer/repel_missiles
modifier_duration = 10 MINUTES
/datum/modifier/technomancer/repel_missiles
name = "repel_missiles"
desc = "A repulsion field can always be useful to have."
mob_overlay_state = "repel_missiles"
on_created_text = "<span class='notice'>You have a repulsion field around you, which will attempt to deflect projectiles.</span>"
on_expired_text = "<span class='warning'>Your repulsion field has expired.</span>"
evasion = 3
stacks = MODIFIER_STACK_EXTEND

View File

@@ -39,7 +39,7 @@
visible_message("<span class='info'>[user] rests a hand on \the [hit_atom].</span>") visible_message("<span class='info'>[user] rests a hand on \the [hit_atom].</span>")
busy = 1 busy = 1
var/datum/effect/effect/system/spark_spread/spark_system = PoolOrNew(/datum/effect/effect/system/spark_spread) var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, our_turf) spark_system.set_up(5, 0, our_turf)
while(i) while(i)

View File

@@ -19,7 +19,7 @@
/obj/item/weapon/spell/reflect/New() /obj/item/weapon/spell/reflect/New()
..() ..()
set_light(3, 2, l_color = "#006AFF") set_light(3, 2, l_color = "#006AFF")
spark_system = PoolOrNew(/datum/effect/effect/system/spark_spread) spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src) spark_system.set_up(5, 0, src)
owner << "<span class='notice'>Your shield will expire in 3 seconds!</span>" owner << "<span class='notice'>Your shield will expire in 3 seconds!</span>"
spawn(5 SECONDS) spawn(5 SECONDS)

View File

@@ -21,7 +21,7 @@
/obj/item/weapon/spell/shield/New() /obj/item/weapon/spell/shield/New()
..() ..()
set_light(3, 2, l_color = "#006AFF") set_light(3, 2, l_color = "#006AFF")
spark_system = PoolOrNew(/datum/effect/effect/system/spark_spread) spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src) spark_system.set_up(5, 0, src)
/obj/item/weapon/spell/shield/Destroy() /obj/item/weapon/spell/shield/Destroy()

View File

@@ -20,10 +20,10 @@
/obj/item/weapon/spell/spawner/darkness/New() /obj/item/weapon/spell/spawner/darkness/New()
..() ..()
set_light(6, -5, l_color = "#FFFFFF") set_light(6, -20, l_color = "#FFFFFF")
/obj/effect/temporary_effect/darkness /obj/effect/temporary_effect/darkness
name = "darkness" name = "darkness"
time_to_die = 2 MINUTES time_to_die = 2 MINUTES
new_light_range = 6 new_light_range = 6
new_light_power = -5 new_light_power = -20

View File

@@ -16,7 +16,7 @@
/obj/item/weapon/spell/warp_strike/New() /obj/item/weapon/spell/warp_strike/New()
..() ..()
sparks = PoolOrNew(/datum/effect/effect/system/spark_spread) sparks = new /datum/effect/effect/system/spark_spread()
sparks.set_up(5, 0, src) sparks.set_up(5, 0, src)
sparks.attach(loc) sparks.attach(loc)

View File

@@ -266,6 +266,7 @@
economic_modifier = 7 economic_modifier = 7
access = list(access_lawyer, access_sec_doors, access_maint_tunnels, access_heads) access = list(access_lawyer, access_sec_doors, access_maint_tunnels, access_heads)
minimal_access = list(access_lawyer, access_sec_doors, access_heads) minimal_access = list(access_lawyer, access_sec_doors, access_heads)
minimal_player_age = 7
/datum/job/lawyer/equip(var/mob/living/carbon/human/H, var/alt_title) /datum/job/lawyer/equip(var/mob/living/carbon/human/H, var/alt_title)

View File

@@ -68,10 +68,12 @@
anchored = 1 anchored = 1
circuit = /obj/item/weapon/circuitboard/sleeper circuit = /obj/item/weapon/circuitboard/sleeper
var/mob/living/carbon/human/occupant = null var/mob/living/carbon/human/occupant = null
var/list/available_chemicals = list("inaprovaline" = "Inaprovaline", "stoxin" = "Soporific", "paracetamol" = "Paracetamol", "anti_toxin" = "Dylovene", "dexalin" = "Dexalin") var/list/available_chemicals = list("inaprovaline" = "Inaprovaline", "paracetamol" = "Paracetamol", "anti_toxin" = "Dylovene", "dexalin" = "Dexalin")
var/obj/item/weapon/reagent_containers/glass/beaker = null var/obj/item/weapon/reagent_containers/glass/beaker = null
var/filtering = 0 var/filtering = 0
var/obj/machinery/sleep_console/console var/obj/machinery/sleep_console/console
var/stasis_level = 0 //Every 'this' life ticks are applied to the mob (when life_ticks%stasis_level == 1)
var/stasis_choices = list("Complete (1%)" = 100, "Deep (10%)" = 10, "Moderate (20%)" = 5, "Light (50%)" = 2, "None (100%)" = 0)
use_power = 1 use_power = 1
idle_power_usage = 15 idle_power_usage = 15
@@ -98,18 +100,23 @@
/obj/machinery/sleeper/process() /obj/machinery/sleeper/process()
if(stat & (NOPOWER|BROKEN)) if(stat & (NOPOWER|BROKEN))
return return
if(occupant)
occupant.Stasis(stasis_level)
if(stasis_level >= 100 && occupant.timeofdeath)
occupant.timeofdeath += 1 SECOND
if(filtering > 0)
if(beaker)
if(beaker.reagents.total_volume < beaker.reagents.maximum_volume)
var/pumped = 0
for(var/datum/reagent/x in occupant.reagents.reagent_list)
occupant.reagents.trans_to_obj(beaker, 3)
pumped++
if(ishuman(occupant))
occupant.vessel.trans_to_obj(beaker, pumped + 1)
else
toggle_filter()
if(filtering > 0)
if(beaker)
if(beaker.reagents.total_volume < beaker.reagents.maximum_volume)
var/pumped = 0
for(var/datum/reagent/x in occupant.reagents.reagent_list)
occupant.reagents.trans_to_obj(beaker, 3)
pumped++
if(ishuman(occupant))
occupant.vessel.trans_to_obj(beaker, pumped + 1)
else
toggle_filter()
/obj/machinery/sleeper/update_icon() /obj/machinery/sleeper/update_icon()
icon_state = "sleeper_[occupant ? "1" : "0"]" icon_state = "sleeper_[occupant ? "1" : "0"]"
@@ -154,6 +161,13 @@
data["beaker"] = -1 data["beaker"] = -1
data["filtering"] = filtering data["filtering"] = filtering
var/stasis_level_name = "Error!"
for(var/N in stasis_choices)
if(stasis_choices[N] == stasis_level)
stasis_level_name = N
break
data["stasis"] = stasis_level_name
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "sleeper.tmpl", "Sleeper UI", 600, 600, state = state) ui = new(user, src, ui_key, "sleeper.tmpl", "Sleeper UI", 600, 600, state = state)
@@ -182,12 +196,20 @@
if(occupant && occupant.stat != DEAD) if(occupant && occupant.stat != DEAD)
if(href_list["chemical"] in available_chemicals) // Your hacks are bad and you should feel bad if(href_list["chemical"] in available_chemicals) // Your hacks are bad and you should feel bad
inject_chemical(usr, href_list["chemical"], text2num(href_list["amount"])) inject_chemical(usr, href_list["chemical"], text2num(href_list["amount"]))
if(href_list["change_stasis"])
var/new_stasis = input("Levels deeper than 50% stasis level will render the patient unconscious.","Stasis Level") as null|anything in stasis_choices
if(new_stasis && CanUseTopic(usr, default_state) == STATUS_INTERACTIVE)
stasis_level = stasis_choices[new_stasis]
return 1 return 1
/obj/machinery/sleeper/attackby(var/obj/item/I, var/mob/user) /obj/machinery/sleeper/attackby(var/obj/item/I, var/mob/user)
add_fingerprint(user) add_fingerprint(user)
if(default_deconstruction_screwdriver(user, I)) if(istype(I, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = I
if(G.affecting)
go_in(G.affecting, user)
else if(default_deconstruction_screwdriver(user, I))
return return
else if(default_deconstruction_crowbar(user, I)) else if(default_deconstruction_crowbar(user, I))
return return
@@ -201,6 +223,28 @@
user << "<span class='warning'>\The [src] has a beaker already.</span>" user << "<span class='warning'>\The [src] has a beaker already.</span>"
return return
/obj/machinery/sleeper/verb/move_eject()
set name = "Eject occupant"
set category = "Object"
set src in oview(1)
if(usr == occupant)
switch(usr.stat)
if(DEAD)
return
if(UNCONSCIOUS)
usr << "<span class='notice'>You struggle through the haze to hit the eject button. This will take a couple of minutes...</span>"
sleep(2 MINUTES)
if(!src || !usr || !occupant || (occupant != usr)) //Check if someone's released/replaced/bombed him already
return
go_out()
if(CONSCIOUS)
go_out()
else
if(usr.stat != 0)
return
go_out()
add_fingerprint(usr)
/obj/machinery/sleeper/MouseDrop_T(var/mob/target, var/mob/user) /obj/machinery/sleeper/MouseDrop_T(var/mob/target, var/mob/user)
if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user)|| !ishuman(target)) if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user)|| !ishuman(target))
return return
@@ -261,6 +305,7 @@
if(occupant.client) if(occupant.client)
occupant.client.eye = occupant.client.mob occupant.client.eye = occupant.client.mob
occupant.client.perspective = MOB_PERSPECTIVE occupant.client.perspective = MOB_PERSPECTIVE
occupant.Stasis(0)
occupant.loc = src.loc occupant.loc = src.loc
occupant = null occupant = null
for(var/atom/movable/A in src) // In case an object was dropped inside or something for(var/atom/movable/A in src) // In case an object was dropped inside or something

View File

@@ -301,6 +301,15 @@
occupantData["reagents"] = reagentData occupantData["reagents"] = reagentData
var/ingestedData[0]
if(H.ingested.reagent_list.len >= 1)
for(var/datum/reagent/R in H.ingested.reagent_list)
ingestedData[++ingestedData.len] = list("name" = R.name, "amount" = R.volume)
else
ingestedData = null
occupantData["ingested"] = ingestedData
var/extOrganData[0] var/extOrganData[0]
for(var/obj/item/organ/external/E in H.organs) for(var/obj/item/organ/external/E in H.organs)
var/organData[0] var/organData[0]
@@ -394,7 +403,7 @@
P.info += "<b>Time of scan:</b> [worldtime2stationtime(world.time)]<br><br>" P.info += "<b>Time of scan:</b> [worldtime2stationtime(world.time)]<br><br>"
P.info += "[printing_text]" P.info += "[printing_text]"
P.info += "<br><br><b>Notes:</b><br>" P.info += "<br><br><b>Notes:</b><br>"
P.name = "Body Scan - [href_list["name"]]" P.name = "Body Scan - [href_list["name"]] ([worldtime2stationtime(world.time)])"
printing = null printing = null
printing_text = null printing_text = null
@@ -457,9 +466,13 @@
dat += "[extra_font]\tBlood Level %: [blood_percent] ([blood_volume] units)</font><br>" dat += "[extra_font]\tBlood Level %: [blood_percent] ([blood_volume] units)</font><br>"
if(occupant.reagents) if(occupant.reagents)
for(var/datum/reagent/R in occupant.reagents) for(var/datum/reagent/R in occupant.reagents.reagent_list)
dat += "Reagent: [R.name], Amount: [R.volume]<br>" dat += "Reagent: [R.name], Amount: [R.volume]<br>"
if(occupant.ingested)
for(var/datum/reagent/R in occupant.ingested.reagent_list)
dat += "Stomach: [R.name], Amount: [R.volume]<br>"
dat += "<hr><table border='1'>" dat += "<hr><table border='1'>"
dat += "<tr>" dat += "<tr>"
dat += "<th>Organ</th>" dat += "<th>Organ</th>"

View File

@@ -719,9 +719,9 @@
if(href_list["atmos_unlock"]) if(href_list["atmos_unlock"])
switch(href_list["atmos_unlock"]) switch(href_list["atmos_unlock"])
if("0") if("0")
alarm_area.air_doors_close() alarm_area.firedoors_close()
if("1") if("1")
alarm_area.air_doors_open() alarm_area.firedoors_open()
return 1 return 1
if(href_list["atmos_alarm"]) if(href_list["atmos_alarm"])

View File

@@ -232,6 +232,8 @@ mob/living/proc/near_camera()
return TRACKING_TERMINATE return TRACKING_TERMINATE
if(digitalcamo) if(digitalcamo)
return TRACKING_TERMINATE return TRACKING_TERMINATE
if(alpha < 127) // For lings and possible future alpha-based cloaks.
return TRACKING_TERMINATE
if(istype(loc,/obj/effect/dummy)) if(istype(loc,/obj/effect/dummy))
return TRACKING_TERMINATE return TRACKING_TERMINATE

View File

@@ -548,7 +548,7 @@
time_entered = world.time time_entered = world.time
if(ishuman(M) && applies_stasis) if(ishuman(M) && applies_stasis)
var/mob/living/carbon/human/H = M var/mob/living/carbon/human/H = M
H.in_stasis = 1 H.Stasis(1000)
// Book keeping! // Book keeping!
var/turf/location = get_turf(src) var/turf/location = get_turf(src)
@@ -616,7 +616,7 @@
set_occupant(usr) set_occupant(usr)
if(ishuman(usr) && applies_stasis) if(ishuman(usr) && applies_stasis)
var/mob/living/carbon/human/H = occupant var/mob/living/carbon/human/H = occupant
H.in_stasis = 1 H.Stasis(1000)
icon_state = occupied_icon_state icon_state = occupied_icon_state
@@ -652,7 +652,7 @@
occupant.forceMove(get_turf(src)) occupant.forceMove(get_turf(src))
if(ishuman(occupant) && applies_stasis) if(ishuman(occupant) && applies_stasis)
var/mob/living/carbon/human/H = occupant var/mob/living/carbon/human/H = occupant
H.in_stasis = 0 H.Stasis(0)
set_occupant(null) set_occupant(null)
icon_state = base_icon_state icon_state = base_icon_state

View File

@@ -237,7 +237,7 @@ for reference:
var/turf/Tsec = get_turf(src) var/turf/Tsec = get_turf(src)
/* var/obj/item/stack/rods/ =*/ /* var/obj/item/stack/rods/ =*/
PoolOrNew(/obj/item/stack/rods, Tsec) new /obj/item/stack/rods(Tsec)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src) s.set_up(3, 1, src)

View File

@@ -778,7 +778,7 @@ About the new airlock wires panel:
src.welded = 1 src.welded = 1
else else
src.welded = null src.welded = null
playsound(src, 'sound/items/Welder.ogg', 100, 1) playsound(src, 'sound/items/Welder.ogg', 75, 1)
src.update_icon() src.update_icon()
return return
else else
@@ -803,7 +803,7 @@ About the new airlock wires panel:
cable.plugin(src, user) cable.plugin(src, user)
else if(!repairing && istype(C, /obj/item/weapon/crowbar)) else if(!repairing && istype(C, /obj/item/weapon/crowbar))
if(src.p_open && (operating < 0 || (!operating && welded && !src.arePowerSystemsOn() && density && (!src.locked || (stat & BROKEN)))) ) if(src.p_open && (operating < 0 || (!operating && welded && !src.arePowerSystemsOn() && density && (!src.locked || (stat & BROKEN)))) )
playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) playsound(src.loc, 'sound/items/Crowbar.ogg', 75, 1)
user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics from the airlock assembly.") user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics from the airlock assembly.")
if(do_after(user,40)) if(do_after(user,40))
to_chat(user,"<span class='notice'>You removed the airlock electronics!</span>") to_chat(user,"<span class='notice'>You removed the airlock electronics!</span>")
@@ -896,9 +896,9 @@ About the new airlock wires panel:
//if the door is unpowered then it doesn't make sense to hear the woosh of a pneumatic actuator //if the door is unpowered then it doesn't make sense to hear the woosh of a pneumatic actuator
if(arePowerSystemsOn()) if(arePowerSystemsOn())
playsound(src.loc, open_sound_powered, 100, 1) playsound(src.loc, open_sound_powered, 75, 1)
else else
playsound(src.loc, open_sound_unpowered, 100, 1) playsound(src.loc, open_sound_unpowered, 75, 1)
if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density) if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density)
src.closeOther.close() src.closeOther.close()
@@ -993,9 +993,9 @@ About the new airlock wires panel:
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
has_beeped = 0 has_beeped = 0
if(arePowerSystemsOn()) if(arePowerSystemsOn())
playsound(src.loc, open_sound_powered, 100, 1) playsound(src.loc, open_sound_powered, 75, 1)
else else
playsound(src.loc, open_sound_unpowered, 100, 1) playsound(src.loc, open_sound_unpowered, 75, 1)
for(var/turf/turf in locs) for(var/turf/turf in locs)
var/obj/structure/window/killthis = (locate(/obj/structure/window) in turf) var/obj/structure/window/killthis = (locate(/obj/structure/window) in turf)
if(killthis) if(killthis)

View File

@@ -164,7 +164,7 @@
switch (Proj.damage_type) switch (Proj.damage_type)
if(BRUTE) if(BRUTE)
new /obj/item/stack/material/steel(src.loc, 2) new /obj/item/stack/material/steel(src.loc, 2)
PoolOrNew(/obj/item/stack/rods, list(src.loc, 3)) new /obj/item/stack/rods(src.loc, 3)
if(BURN) if(BURN)
new /obj/effect/decal/cleanable/ash(src.loc) // Turn it to ashes! new /obj/effect/decal/cleanable/ash(src.loc) // Turn it to ashes!
qdel(src) qdel(src)

View File

@@ -141,7 +141,7 @@
var/alarmed = lockdown var/alarmed = lockdown
for(var/area/A in areas_added) //Checks if there are fire alarms in any areas associated with that firedoor for(var/area/A in areas_added) //Checks if there are fire alarms in any areas associated with that firedoor
if(A.fire || A.air_doors_activated) if(A.firedoors_closed)
alarmed = 1 alarmed = 1
var/answer = alert(user, "Would you like to [density ? "open" : "close"] this [src.name]?[ alarmed && density ? "\nNote that by doing so, you acknowledge any damages from opening this\n[src.name] as being your own fault, and you will be held accountable under the law." : ""]",\ var/answer = alert(user, "Would you like to [density ? "open" : "close"] this [src.name]?[ alarmed && density ? "\nNote that by doing so, you acknowledge any damages from opening this\n[src.name] as being your own fault, and you will be held accountable under the law." : ""]",\
@@ -179,7 +179,7 @@
spawn(50) spawn(50)
alarmed = 0 alarmed = 0
for(var/area/A in areas_added) //Just in case a fire alarm is turned off while the firedoor is going through an autoclose cycle for(var/area/A in areas_added) //Just in case a fire alarm is turned off while the firedoor is going through an autoclose cycle
if(A.fire || A.air_doors_activated) if(A.firedoors_closed)
alarmed = 1 alarmed = 1
if(alarmed) if(alarmed)
nextstate = FIREDOOR_CLOSED nextstate = FIREDOOR_CLOSED

View File

@@ -170,7 +170,7 @@
cooking_obj = new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(src) cooking_obj = new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(src)
// Produce nasty smoke. // Produce nasty smoke.
visible_message("<span class='danger'>\The [src] vomits a gout of rancid smoke!</span>") visible_message("<span class='danger'>\The [src] vomits a gout of rancid smoke!</span>")
var/datum/effect/effect/system/smoke_spread/bad/smoke = PoolOrNew(/datum/effect/effect/system/smoke_spread/bad) var/datum/effect/effect/system/smoke_spread/bad/smoke = new /datum/effect/effect/system/smoke_spread/bad()
smoke.attach(src) smoke.attach(src)
smoke.set_up(10, 0, usr.loc) smoke.set_up(10, 0, usr.loc)
smoke.start() smoke.start()

View File

@@ -155,7 +155,7 @@ Class Procs:
if(use_power && stat == 0) if(use_power && stat == 0)
use_power(7500/severity) use_power(7500/severity)
var/obj/effect/overlay/pulse2 = PoolOrNew(/obj/effect/overlay, src.loc) var/obj/effect/overlay/pulse2 = new /obj/effect/overlay(src.loc)
pulse2.icon = 'icons/effects/effects.dmi' pulse2.icon = 'icons/effects/effects.dmi'
pulse2.icon_state = "empdisable" pulse2.icon_state = "empdisable"
pulse2.name = "emp sparks" pulse2.name = "emp sparks"

View File

@@ -567,7 +567,7 @@ var/list/turret_icons
set_raised_raising(raised, 1) set_raised_raising(raised, 1)
update_icon() update_icon()
var/atom/flick_holder = PoolOrNew(/atom/movable/porta_turret_cover, loc) var/atom/flick_holder = new /atom/movable/porta_turret_cover(loc)
flick_holder.layer = layer + 0.1 flick_holder.layer = layer + 0.1
flick("popup", flick_holder) flick("popup", flick_holder)
sleep(10) sleep(10)
@@ -588,7 +588,7 @@ var/list/turret_icons
set_raised_raising(raised, 1) set_raised_raising(raised, 1)
update_icon() update_icon()
var/atom/flick_holder = PoolOrNew(/atom/movable/porta_turret_cover, loc) var/atom/flick_holder = new /atom/movable/porta_turret_cover(loc)
flick_holder.layer = layer + 0.1 flick_holder.layer = layer + 0.1
flick("popdown", flick_holder) flick("popdown", flick_holder)
sleep(10) sleep(10)

View File

@@ -7,7 +7,7 @@
products += list(/obj/item/weapon/gun/energy/taser = 8,/obj/item/weapon/gun/energy/stunrevolver = 4, products += list(/obj/item/weapon/gun/energy/taser = 8,/obj/item/weapon/gun/energy/stunrevolver = 4,
/obj/item/weapon/reagent_containers/spray/pepper = 6,/obj/item/taperoll/police = 6, /obj/item/weapon/reagent_containers/spray/pepper = 6,/obj/item/taperoll/police = 6,
/obj/item/weapon/gun/projectile/sec/flash = 4, /obj/item/ammo_magazine/c45m/flash = 8, /obj/item/weapon/gun/projectile/sec/flash = 4, /obj/item/ammo_magazine/c45m/flash = 8,
/obj/item/clothing/glasses/omnihud/sec = 4) /obj/item/clothing/glasses/omnihud/sec = 6)
..() ..()
/obj/machinery/vending/tool/New() /obj/machinery/vending/tool/New()
@@ -15,12 +15,12 @@
..() ..()
/obj/machinery/vending/engivend/New() /obj/machinery/vending/engivend/New()
products += list(/obj/item/clothing/glasses/omnihud/eng = 4) products += list(/obj/item/clothing/glasses/omnihud/eng = 6)
..() ..()
/obj/machinery/vending/medical/New() /obj/machinery/vending/medical/New()
products += list(/obj/item/weapon/storage/box/khcrystal = 4,/obj/item/weapon/backup_implanter = 3, products += list(/obj/item/weapon/storage/box/khcrystal = 4,/obj/item/weapon/backup_implanter = 3,
/obj/item/clothing/glasses/omnihud/med = 2, /obj/item/device/glasses_kit = 1) /obj/item/clothing/glasses/omnihud/med = 4, /obj/item/device/glasses_kit = 1)
..() ..()
//Custom vendors //Custom vendors

View File

@@ -7,7 +7,7 @@
energy_drain = 20 energy_drain = 20
range = MELEE range = MELEE
equip_cooldown = 50 equip_cooldown = 50
var/mob/living/carbon/occupant = null var/mob/living/carbon/human/occupant = null
var/datum/global_iterator/pr_mech_sleeper var/datum/global_iterator/pr_mech_sleeper
var/inject_amount = 10 var/inject_amount = 10
required_type = /obj/mecha/medical required_type = /obj/mecha/medical
@@ -28,7 +28,7 @@
Exit(atom/movable/O) Exit(atom/movable/O)
return 0 return 0
action(var/mob/living/carbon/target) action(var/mob/living/carbon/human/target)
if(!action_checks(target)) if(!action_checks(target))
return return
if(!istype(target)) if(!istype(target))
@@ -56,6 +56,7 @@
target.forceMove(src) target.forceMove(src)
occupant = target occupant = target
target.reset_view(src) target.reset_view(src)
occupant.Stasis(3)
/* /*
if(target.client) if(target.client)
target.client.perspective = EYE_PERSPECTIVE target.client.perspective = EYE_PERSPECTIVE
@@ -80,6 +81,7 @@
occupant.client.eye = occupant.client.mob occupant.client.eye = occupant.client.mob
occupant.client.perspective = MOB_PERSPECTIVE occupant.client.perspective = MOB_PERSPECTIVE
*/ */
occupant.Stasis(0)
occupant = null occupant = null
pr_mech_sleeper.stop() pr_mech_sleeper.stop()
set_ready_state(1) set_ready_state(1)

View File

@@ -208,7 +208,7 @@
for(var/a = 1 to 5) for(var/a = 1 to 5)
spawn(0) spawn(0)
var/obj/effect/effect/water/W = PoolOrNew(/obj/effect/effect/water, get_turf(chassis)) var/obj/effect/effect/water/W = new /obj/effect/effect/water(get_turf(chassis))
var/turf/my_target var/turf/my_target
if(a == 1) if(a == 1)
my_target = T my_target = T

View File

@@ -197,25 +197,25 @@
set src in view(1) set src in view(1)
if(!istype(usr, /mob/living/carbon/human)) //Only living, intelligent creatures with hands can empty ore boxes. if(!istype(usr, /mob/living/carbon/human)) //Only living, intelligent creatures with hands can empty ore boxes.
usr << "\red You are physically incapable of emptying the ore box." to_chat(usr, "<span class='warning'>You are physically incapable of emptying the ore box.</span>")
return return
if( usr.stat || usr.restrained() ) if( usr.stat || usr.restrained() )
return return
if(!Adjacent(usr)) //You can only empty the box if you can physically reach it if(!Adjacent(usr)) //You can only empty the box if you can physically reach it
usr << "You cannot reach the ore box." to_chat(usr, "You cannot reach the ore box.")
return return
add_fingerprint(usr) add_fingerprint(usr)
if(contents.len < 1) if(contents.len < 1)
usr << "\red The ore box is empty" to_chat(usr, "<span class='warning'>The ore box is empty</span>")
return return
for (var/obj/item/weapon/ore/O in contents) for (var/obj/item/weapon/ore/O in contents)
contents -= O contents -= O
O.loc = src.loc O.loc = src.loc
usr << "\blue You empty the ore box" to_chat(usr, "<span class='info'>You empty the ore box</span>")
return return

View File

@@ -152,7 +152,7 @@
if(passed_smoke) if(passed_smoke)
smoke = passed_smoke smoke = passed_smoke
else else
smoke = PoolOrNew(/obj/effect/effect/smoke/chem, location) smoke = new /obj/effect/effect/smoke/chem(location)
if(chemholder.reagents.reagent_list.len) if(chemholder.reagents.reagent_list.len)
chemholder.reagents.trans_to_obj(smoke, chemholder.reagents.total_volume / dist, copy = 1) //copy reagents to the smoke so mob/breathe() can handle inhaling the reagents chemholder.reagents.trans_to_obj(smoke, chemholder.reagents.total_volume / dist, copy = 1) //copy reagents to the smoke so mob/breathe() can handle inhaling the reagents
@@ -169,7 +169,7 @@
qdel(src) qdel(src)
/datum/effect/effect/system/smoke_spread/chem/spores/spawnSmoke(var/turf/T, var/icon/I, var/dist = 1) /datum/effect/effect/system/smoke_spread/chem/spores/spawnSmoke(var/turf/T, var/icon/I, var/dist = 1)
var/obj/effect/effect/smoke/chem/spores = PoolOrNew(/obj/effect/effect/smoke/chem, location) var/obj/effect/effect/smoke/chem/spores = new /obj/effect/effect/smoke/chem(location)
spores.name = "cloud of [seed.seed_name] [seed.seed_noun]" spores.name = "cloud of [seed.seed_name] [seed.seed_noun]"
..(T, I, dist, spores) ..(T, I, dist, spores)

View File

@@ -108,7 +108,7 @@
F.amount += amount F.amount += amount
return return
F = PoolOrNew(/obj/effect/effect/foam, list(location, metal)) F = new /obj/effect/effect/foam(location, metal)
F.amount = amount F.amount = amount
if(!metal) // don't carry other chemicals if a metal foam if(!metal) // don't carry other chemicals if a metal foam

View File

@@ -222,7 +222,7 @@ var/global/list/image/splatter_cache=list()
for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++) for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++)
sleep(3) sleep(3)
if (i > 0) if (i > 0)
var/obj/effect/decal/cleanable/blood/b = PoolOrNew(/obj/effect/decal/cleanable/blood/splatter, src.loc) var/obj/effect/decal/cleanable/blood/b = new /obj/effect/decal/cleanable/blood/splatter(src.loc)
b.basecolor = src.basecolor b.basecolor = src.basecolor
b.update_icon() b.update_icon()

View File

@@ -75,7 +75,7 @@ steam.start() -- spawns the effect
spawn(0) spawn(0)
if(holder) if(holder)
src.location = get_turf(holder) src.location = get_turf(holder)
var/obj/effect/effect/steam/steam = PoolOrNew(/obj/effect/effect/steam, src.location) var/obj/effect/effect/steam/steam = new /obj/effect/effect/steam(src.location)
var/direction var/direction
if(src.cardinals) if(src.cardinals)
direction = pick(cardinal) direction = pick(cardinal)
@@ -146,7 +146,7 @@ steam.start() -- spawns the effect
spawn(0) spawn(0)
if(holder) if(holder)
src.location = get_turf(holder) src.location = get_turf(holder)
var/obj/effect/effect/sparks/sparks = PoolOrNew(/obj/effect/effect/sparks, src.location) var/obj/effect/effect/sparks/sparks = new /obj/effect/effect/sparks(src.location)
src.total_sparks++ src.total_sparks++
var/direction var/direction
if(src.cardinals) if(src.cardinals)
@@ -283,7 +283,7 @@ steam.start() -- spawns the effect
spawn(0) spawn(0)
if(holder) if(holder)
src.location = get_turf(holder) src.location = get_turf(holder)
var/obj/effect/effect/smoke/smoke = PoolOrNew(smoke_type, src.location) var/obj/effect/effect/smoke/smoke = new smoke_type(src.location)
src.total_smoke++ src.total_smoke++
smoke.color = I smoke.color = I
var/direction = src.direction var/direction = src.direction
@@ -334,7 +334,7 @@ steam.start() -- spawns the effect
var/turf/T = get_turf(src.holder) var/turf/T = get_turf(src.holder)
if(T != src.oldposition) if(T != src.oldposition)
if(isturf(T)) if(isturf(T))
var/obj/effect/effect/ion_trails/I = PoolOrNew(/obj/effect/effect/ion_trails, src.oldposition) var/obj/effect/effect/ion_trails/I = new /obj/effect/effect/ion_trails(src.oldposition)
src.oldposition = T src.oldposition = T
I.set_dir(src.holder.dir) I.set_dir(src.holder.dir)
flick("ion_fade", I) flick("ion_fade", I)
@@ -380,7 +380,7 @@ steam.start() -- spawns the effect
src.processing = 0 src.processing = 0
spawn(0) spawn(0)
if(src.number < 3) if(src.number < 3)
var/obj/effect/effect/steam/I = PoolOrNew(/obj/effect/effect/steam, src.oldposition) var/obj/effect/effect/steam/I = new /obj/effect/effect/steam(src.oldposition)
src.number++ src.number++
src.oldposition = get_turf(holder) src.oldposition = get_turf(holder)
I.set_dir(src.holder.dir) I.set_dir(src.holder.dir)
@@ -420,7 +420,7 @@ steam.start() -- spawns the effect
start() start()
if (amount <= 2) if (amount <= 2)
var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
s.set_up(2, 1, location) s.set_up(2, 1, location)
s.start() s.start()

View File

@@ -24,7 +24,7 @@
var/obj/effect/decal/cleanable/blood/gibs/gib = null var/obj/effect/decal/cleanable/blood/gibs/gib = null
if(sparks) if(sparks)
var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
s.set_up(2, 1, get_turf(location)) // Not sure if it's safe to pass an arbitrary object to set_up, todo s.set_up(2, 1, get_turf(location)) // Not sure if it's safe to pass an arbitrary object to set_up, todo
s.start() s.start()

View File

@@ -26,7 +26,7 @@
call(src,triggerproc)(M) call(src,triggerproc)(M)
/obj/effect/mine/proc/triggerrad(obj) /obj/effect/mine/proc/triggerrad(obj)
var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
s.set_up(3, 1, src) s.set_up(3, 1, src)
s.start() s.start()
obj:radiation += 50 obj:radiation += 50
@@ -39,7 +39,7 @@
if(ismob(obj)) if(ismob(obj))
var/mob/M = obj var/mob/M = obj
M.Stun(30) M.Stun(30)
var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
s.set_up(3, 1, src) s.set_up(3, 1, src)
s.start() s.start()
spawn(0) spawn(0)
@@ -67,7 +67,7 @@
qdel(src) qdel(src)
/obj/effect/mine/proc/triggerkick(obj) /obj/effect/mine/proc/triggerkick(obj)
var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
s.set_up(3, 1, src) s.set_up(3, 1, src)
s.start() s.start()
qdel(obj:client) qdel(obj:client)

View File

@@ -105,7 +105,7 @@
O = loc O = loc
for(var/i=0, i<num, i++) for(var/i=0, i<num, i++)
var/spiderling = PoolOrNew(/obj/effect/spider/spiderling, list(src.loc, src)) var/spiderling = new /obj/effect/spider/spiderling(src.loc, src)
if(O) if(O)
O.implants += spiderling O.implants += spiderling
qdel(src) qdel(src)
@@ -148,7 +148,7 @@
/obj/effect/spider/spiderling/proc/die() /obj/effect/spider/spiderling/proc/die()
visible_message("<span class='alert'>[src] dies!</span>") visible_message("<span class='alert'>[src] dies!</span>")
PoolOrNew(/obj/effect/decal/cleanable/spiderling_remains, src.loc) new /obj/effect/decal/cleanable/spiderling_remains(src.loc)
qdel(src) qdel(src)
/obj/effect/spider/spiderling/healthcheck() /obj/effect/spider/spiderling/healthcheck()

View File

@@ -15,7 +15,7 @@ proc/empulse(turf/epicenter, first_range, second_range, third_range, fourth_rang
log_game("EMP with size ([first_range], [second_range], [third_range], [fourth_range]) in area [epicenter.loc.name] ") log_game("EMP with size ([first_range], [second_range], [third_range], [fourth_range]) in area [epicenter.loc.name] ")
if(first_range > 1) if(first_range > 1)
var/obj/effect/overlay/pulse = PoolOrNew(/obj/effect/overlay, epicenter) var/obj/effect/overlay/pulse = new /obj/effect/overlay(epicenter)
pulse.icon = 'icons/effects/effects.dmi' pulse.icon = 'icons/effects/effects.dmi'
pulse.icon_state = "emppulse" pulse.icon_state = "emppulse"
pulse.name = "emp pulse" pulse.name = "emp pulse"

View File

@@ -1,23 +1,26 @@
//TODO: Flash range does nothing currently //TODO: Flash range does nothing currently
proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = UP|DOWN) proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = UP|DOWN, shaped)
var/multi_z_scalar = config.multi_z_explosion_scalar
src = null //so we don't abort once src is deleted src = null //so we don't abort once src is deleted
spawn(0) spawn(0)
if(config.use_recursive_explosions)
var/power = devastation_range * 2 + heavy_impact_range + light_impact_range //The ranges add up, ie light 14 includes both heavy 7 and devestation 3. So this calculation means devestation counts for 4, heavy for 2 and light for 1 power, giving us a cap of 27 power.
explosion_rec(epicenter, power)
return
var/start = world.timeofday var/start = world.timeofday
epicenter = get_turf(epicenter) epicenter = get_turf(epicenter)
if(!epicenter) return if(!epicenter) return
// Handles recursive propagation of explosions. // Handles recursive propagation of explosions.
if(devastation_range > 2 || heavy_impact_range > 2) if(z_transfer && multi_z_scalar)
if(HasAbove(epicenter.z) && z_transfer & UP) var/adj_dev = max(0, (multi_z_scalar * devastation_range) - (shaped ? 2 : 0) )
explosion(GetAbove(epicenter), max(0, devastation_range - 2), max(0, heavy_impact_range - 2), max(0, light_impact_range - 2), max(0, flash_range - 2), 0, UP) var/adj_heavy = max(0, (multi_z_scalar * heavy_impact_range) - (shaped ? 2 : 0) )
if(HasBelow(epicenter.z) && z_transfer & DOWN) var/adj_light = max(0, (multi_z_scalar * light_impact_range) - (shaped ? 2 : 0) )
explosion(GetAbove(epicenter), max(0, devastation_range - 2), max(0, heavy_impact_range - 2), max(0, light_impact_range - 2), max(0, flash_range - 2), 0, DOWN) var/adj_flash = max(0, (multi_z_scalar * flash_range) - (shaped ? 2 : 0) )
if(adj_dev > 0 || adj_heavy > 0)
if(HasAbove(epicenter.z) && z_transfer & UP)
explosion(GetAbove(epicenter), round(adj_dev), round(adj_heavy), round(adj_light), round(adj_flash), 0, UP, shaped)
if(HasBelow(epicenter.z) && z_transfer & DOWN)
explosion(GetBelow(epicenter), round(adj_dev), round(adj_heavy), round(adj_light), round(adj_flash), 0, DOWN, shaped)
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flash_range) var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flash_range)
@@ -30,31 +33,30 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
far_dist += devastation_range * 20 far_dist += devastation_range * 20
var/frequency = get_rand_frequency() var/frequency = get_rand_frequency()
for(var/mob/M in player_list) for(var/mob/M in player_list)
// Double check for client if(M.z == epicenter.z)
if(M && M.client)
var/turf/M_turf = get_turf(M) var/turf/M_turf = get_turf(M)
if(M_turf && M_turf.z == epicenter.z) var/dist = get_dist(M_turf, epicenter)
var/dist = get_dist(M_turf, epicenter) // If inside the blast radius + world.view - 2
// If inside the blast radius + world.view - 2 if(dist <= round(max_range + world.view - 2, 1))
if(dist <= round(max_range + world.view - 2, 1)) M.playsound_local(epicenter, get_sfx("explosion"), 100, 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound
M.playsound_local(epicenter, get_sfx("explosion"), 100, 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound else if(dist <= far_dist)
var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
//You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station. far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
else if(dist <= far_dist)
var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
var/close = range(world.view+round(devastation_range,1), epicenter) var/close = range(world.view+round(devastation_range,1), epicenter)
// to all distanced mobs play a different sound // to all distanced mobs play a different sound
for(var/mob/M in world) if(M.z == epicenter.z) if(!(M in close)) for(var/mob/M in world)
// check if the mob can hear if(M.z == epicenter.z)
if(M.ear_deaf <= 0 || !M.ear_deaf) if(!istype(M.loc,/turf/space)) if(!(M in close))
M << 'sound/effects/explosionfar.ogg' // check if the mob can hear
if(M.ear_deaf <= 0 || !M.ear_deaf)
if(!istype(M.loc,/turf/space))
M << 'sound/effects/explosionfar.ogg'
if(adminlog) if(adminlog)
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[epicenter.x];Y=[epicenter.y];Z=[epicenter.z]'>JMP</a>)") message_admins("Explosion with [shaped ? "shaped" : "non-shaped"] size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[epicenter.x];Y=[epicenter.y];Z=[epicenter.z]'>JMP</a>)")
log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ") log_game("Explosion with [shaped ? "shaped" : "non-shaped"] size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ")
var/approximate_intensity = (devastation_range * 3) + (heavy_impact_range * 2) + light_impact_range var/approximate_intensity = (devastation_range * 3) + (heavy_impact_range * 2) + light_impact_range
var/powernet_rebuild_was_deferred_already = defer_powernet_rebuild var/powernet_rebuild_was_deferred_already = defer_powernet_rebuild
@@ -70,41 +72,42 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
var/x0 = epicenter.x var/x0 = epicenter.x
var/y0 = epicenter.y var/y0 = epicenter.y
var/z0 = epicenter.z var/z0 = epicenter.z
if(config.use_recursive_explosions)
var/power = devastation_range * 2 + heavy_impact_range + light_impact_range //The ranges add up, ie light 14 includes both heavy 7 and devestation 3. So this calculation means devestation counts for 4, heavy for 2 and light for 1 power, giving us a cap of 27 power.
explosion_rec(epicenter, power, shaped)
else
for(var/turf/T in trange(max_range, epicenter))
var/dist = sqrt((T.x - x0)**2 + (T.y - y0)**2)
for(var/turf/T in trange(max_range, epicenter)) if(dist < devastation_range) dist = 1
var/dist = sqrt((T.x - x0)**2 + (T.y - y0)**2) else if(dist < heavy_impact_range) dist = 2
else if(dist < light_impact_range) dist = 3
else continue
if(dist < devastation_range) dist = 1 if(!T)
else if(dist < heavy_impact_range) dist = 2 T = locate(x0,y0,z0)
else if(dist < light_impact_range) dist = 3
else continue
T.ex_act(dist)
if(T)
for(var/atom_movable in T.contents) //bypass type checking since only atom/movable can be contained by turfs anyway for(var/atom_movable in T.contents) //bypass type checking since only atom/movable can be contained by turfs anyway
var/atom/movable/AM = atom_movable var/atom/movable/AM = atom_movable
if(AM && AM.simulated) AM.ex_act(dist) if(AM && AM.simulated) AM.ex_act(dist)
T.ex_act(dist)
var/took = (world.timeofday-start)/10 var/took = (world.timeofday-start)/10
//You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare //You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare
if(Debug2) world.log << "## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds." if(Debug2) world.log << "## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds."
//Machines which report explosions. //Machines which report explosions.
for(var/i,i<=doppler_arrays.len,i++) for(var/i,i<=doppler_arrays.len,i++)
var/obj/machinery/doppler_array/Array = doppler_arrays[i] var/obj/machinery/doppler_array/Array = doppler_arrays[i]
if(Array) if(Array)
Array.sense_explosion(x0,y0,z0,devastation_range,heavy_impact_range,light_impact_range,took) Array.sense_explosion(x0,y0,z0,devastation_range,heavy_impact_range,light_impact_range,took)
sleep(8) sleep(8)
if(!powernet_rebuild_was_deferred_already && defer_powernet_rebuild) if(!powernet_rebuild_was_deferred_already && defer_powernet_rebuild)
makepowernets() makepowernets()
defer_powernet_rebuild = 0 defer_powernet_rebuild = 0
return 1 return 1
proc/secondaryexplosion(turf/epicenter, range) proc/secondaryexplosion(turf/epicenter, range)
for(var/turf/tile in range(range, epicenter)) for(var/turf/tile in range(range, epicenter))
tile.ex_act(2) tile.ex_act(2)

View File

@@ -50,7 +50,7 @@
var/zoomdevicename = null //name used for message when binoculars/scope is used var/zoomdevicename = null //name used for message when binoculars/scope is used
var/zoom = 0 //1 if item is actively being used to zoom. For scoped guns and binoculars. var/zoom = 0 //1 if item is actively being used to zoom. For scoped guns and binoculars.
var/embed_chance = -1 //-1 makes it calculate embed chance, 0 won't embed, and 100 will always embed var/embed_chance = -1 //0 won't embed, and 100 will always embed
var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc. var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc.
@@ -79,12 +79,12 @@
var/list/sprite_sheets_obj = list() var/list/sprite_sheets_obj = list()
/obj/item/New() /obj/item/New()
if(embed_chance == -1)
if(sharp)
embed_chance = force/w_class
else
embed_chance = force/(w_class*3)
..() ..()
if(embed_chance < 0)
if(sharp)
embed_chance = max(5, round(force/w_class))
else
embed_chance = max(5, round(force/(w_class*3)))
/obj/item/equipped() /obj/item/equipped()
..() ..()

View File

@@ -77,14 +77,14 @@
/obj/structure/closet/body_bag/MouseDrop(over_object, src_location, over_location) /obj/structure/closet/body_bag/MouseDrop(over_object, src_location, over_location)
..() ..()
if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src)))) if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src))))
if(!ishuman(usr)) return if(!ishuman(usr)) return 0
if(opened) return 0 if(opened) return 0
if(contents.len) return 0 if(contents.len) return 0
visible_message("[usr] folds up the [src.name]") visible_message("[usr] folds up the [src.name]")
new item_path(get_turf(src)) var/folded = new item_path(get_turf(src))
spawn(0) spawn(0)
qdel(src) qdel(src)
return return folded
/obj/structure/closet/body_bag/relaymove(mob/user,direction) /obj/structure/closet/body_bag/relaymove(mob/user,direction)
if(src.loc != get_turf(src)) if(src.loc != get_turf(src))
@@ -115,34 +115,43 @@
/obj/item/bodybag/cryobag /obj/item/bodybag/cryobag
name = "stasis bag" name = "stasis bag"
desc = "A folded, non-reusable bag designed to prevent additional damage to an occupant, especially useful if short on time or in \ desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \
a hostile enviroment." especially useful if short on time or in a hostile enviroment."
icon = 'icons/obj/cryobag.dmi' icon = 'icons/obj/cryobag.dmi'
icon_state = "bodybag_folded" icon_state = "bodybag_folded"
item_state = "bodybag_cryo_folded" item_state = "bodybag_cryo_folded"
origin_tech = list(TECH_BIO = 4) origin_tech = list(TECH_BIO = 4)
var/obj/item/weapon/reagent_containers/syringe/syringe
/obj/item/bodybag/cryobag/attack_self(mob/user) /obj/item/bodybag/cryobag/attack_self(mob/user)
var/obj/structure/closet/body_bag/cryobag/R = new /obj/structure/closet/body_bag/cryobag(user.loc) var/obj/structure/closet/body_bag/cryobag/R = new /obj/structure/closet/body_bag/cryobag(user.loc)
R.add_fingerprint(user) R.add_fingerprint(user)
if(syringe)
R.syringe = syringe
syringe = null
qdel(src) qdel(src)
/obj/structure/closet/body_bag/cryobag /obj/structure/closet/body_bag/cryobag
name = "stasis bag" name = "stasis bag"
desc = "A non-reusable plastic bag designed to prevent additional damage to an occupant, especially useful if short on time or in \ desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \
a hostile enviroment." especially useful if short on time or in a hostile enviroment."
icon = 'icons/obj/cryobag.dmi' icon = 'icons/obj/cryobag.dmi'
item_path = /obj/item/bodybag/cryobag item_path = /obj/item/bodybag/cryobag
store_misc = 0 store_misc = 0
store_items = 0 store_items = 0
var/used = 0 var/used = 0
var/obj/item/weapon/tank/tank = null var/obj/item/weapon/tank/tank = null
var/stasis_level = 3 //Every 'this' life ticks are applied to the mob (when life_ticks%stasis_level == 1)
var/obj/item/weapon/reagent_containers/syringe/syringe
/obj/structure/closet/body_bag/cryobag/New() /obj/structure/closet/body_bag/cryobag/New()
tank = new /obj/item/weapon/tank/emergency/oxygen(null) //It's in nullspace to prevent ejection when the bag is opened. tank = new /obj/item/weapon/tank/emergency/oxygen(null) //It's in nullspace to prevent ejection when the bag is opened.
..() ..()
/obj/structure/closet/body_bag/cryobag/Destroy() /obj/structure/closet/body_bag/cryobag/Destroy()
if(syringe)
qdel(syringe)
syringe = null
qdel(tank) qdel(tank)
tank = null tank = null
..() ..()
@@ -157,11 +166,19 @@
O.desc = "Pretty useless now.." O.desc = "Pretty useless now.."
qdel(src) qdel(src)
/obj/structure/closet/body_bag/cryobag/MouseDrop(over_object, src_location, over_location)
. = ..()
if(. && syringe)
var/obj/item/bodybag/cryobag/folded = .
folded.syringe = syringe
syringe = null
/obj/structure/closet/body_bag/cryobag/Entered(atom/movable/AM) /obj/structure/closet/body_bag/cryobag/Entered(atom/movable/AM)
if(ishuman(AM)) if(ishuman(AM))
var/mob/living/carbon/human/H = AM var/mob/living/carbon/human/H = AM
H.in_stasis = 1 H.Stasis(stasis_level)
src.used = 1 src.used = 1
inject_occupant(H)
if(istype(AM, /obj/item/organ)) if(istype(AM, /obj/item/organ))
var/obj/item/organ/O = AM var/obj/item/organ/O = AM
@@ -173,7 +190,7 @@
/obj/structure/closet/body_bag/cryobag/Exited(atom/movable/AM) /obj/structure/closet/body_bag/cryobag/Exited(atom/movable/AM)
if(ishuman(AM)) if(ishuman(AM))
var/mob/living/carbon/human/H = AM var/mob/living/carbon/human/H = AM
H.in_stasis = 0 H.Stasis(0)
if(istype(AM, /obj/item/organ)) if(istype(AM, /obj/item/organ))
var/obj/item/organ/O = AM var/obj/item/organ/O = AM
@@ -187,10 +204,19 @@
return tank.air_contents return tank.air_contents
..() ..()
/obj/structure/closet/body_bag/cryobag/proc/inject_occupant(var/mob/living/carbon/human/H)
if(!syringe)
return
if(H.reagents)
syringe.reagents.trans_to_mob(H, 30, CHEM_BLOOD)
/obj/structure/closet/body_bag/cryobag/examine(mob/user) /obj/structure/closet/body_bag/cryobag/examine(mob/user)
..() ..()
if(Adjacent(user)) //The bag's rather thick and opaque from a distance. if(Adjacent(user)) //The bag's rather thick and opaque from a distance.
user << "<span class='info'>You peer into \the [src].</span>" user << "<span class='info'>You peer into \the [src].</span>"
if(syringe)
user << "<span class='info'>It has a syringe added to it.</span>"
for(var/mob/living/L in contents) for(var/mob/living/L in contents)
L.examine(user) L.examine(user)
@@ -202,5 +228,28 @@
var/obj/item/device/healthanalyzer/analyzer = W var/obj/item/device/healthanalyzer/analyzer = W
for(var/mob/living/L in contents) for(var/mob/living/L in contents)
analyzer.attack(L,user) analyzer.attack(L,user)
else if(istype(W,/obj/item/weapon/reagent_containers/syringe))
if(syringe)
to_chat(user,"<span class='warning'>\The [src] already has an injector! Remove it first.</span>")
else
var/obj/item/weapon/reagent_containers/syringe/syringe = W
to_chat(user,"<span class='info'>You insert \the [syringe] into \the [src], and it locks into place.</span>")
user.unEquip(syringe)
src.syringe = syringe
syringe.loc = null
for(var/mob/living/carbon/human/H in contents)
inject_occupant(H)
break
else if(istype(W,/obj/item/weapon/screwdriver))
if(syringe)
if(used)
to_chat(user,"<span class='warning'>The injector cannot be removed now that the stasis bag has been used!</span>")
else
syringe.forceMove(src.loc)
to_chat(user,"<span class='info'>You pry \the [syringe] out of \the [src].</span>")
syringe = null
else else
..() ..()

View File

@@ -1105,6 +1105,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(M.stat == DEAD && M.client && (M.is_preference_enabled(/datum/client_preference/ghost_ears))) // src.client is so that ghosts don't have to listen to mice if(M.stat == DEAD && M.client && (M.is_preference_enabled(/datum/client_preference/ghost_ears))) // src.client is so that ghosts don't have to listen to mice
if(istype(M, /mob/new_player)) if(istype(M, /mob/new_player))
continue continue
if(M.forbid_seeing_deadchat)
continue
M.show_message("<span class='game say'>PDA Message - <span class='name'>[owner]</span> -> <span class='name'>[P.owner]</span>: <span class='message'>[t]</span></span>") M.show_message("<span class='game say'>PDA Message - <span class='name'>[owner]</span> -> <span class='name'>[P.owner]</span>: <span class='message'>[t]</span></span>")
if(!conversations.Find("\ref[P]")) if(!conversations.Find("\ref[P]"))

View File

@@ -47,7 +47,7 @@
qdel(active_dummy) qdel(active_dummy)
active_dummy = null active_dummy = null
usr << "<span class='notice'>You deactivate the [src].</span>" usr << "<span class='notice'>You deactivate the [src].</span>"
var/obj/effect/overlay/T = PoolOrNew(/obj/effect/overlay, get_turf(src)) var/obj/effect/overlay/T = new /obj/effect/overlay(get_turf(src))
T.icon = 'icons/effects/effects.dmi' T.icon = 'icons/effects/effects.dmi'
flick("emppulse",T) flick("emppulse",T)
spawn(8) qdel(T) spawn(8) qdel(T)
@@ -55,7 +55,7 @@
playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6) playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6)
var/obj/O = new saved_item(src) var/obj/O = new saved_item(src)
if(!O) return if(!O) return
var/obj/effect/dummy/chameleon/C = PoolOrNew(/obj/effect/dummy/chameleon, usr.loc) var/obj/effect/dummy/chameleon/C = new /obj/effect/dummy/chameleon(usr.loc)
C.activate(O, usr, saved_icon, saved_icon_state, saved_overlays, src) C.activate(O, usr, saved_icon, saved_icon_state, saved_overlays, src)
qdel(O) qdel(O)
usr << "<span class='notice'>You activate the [src].</span>" usr << "<span class='notice'>You activate the [src].</span>"

View File

@@ -212,6 +212,8 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
alert_called = 0 alert_called = 0
update_icon() update_icon()
ui_interact(user) ui_interact(user)
if(video_source)
watch_video(user)
// Proc: MouseDrop() // Proc: MouseDrop()
//Same thing PDAs do //Same thing PDAs do
@@ -1041,7 +1043,8 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
if(!Adjacent(user) || !video_source) return if(!Adjacent(user) || !video_source) return
user.set_machine(video_source) user.set_machine(video_source)
user.reset_view(video_source) user.reset_view(video_source)
user << "<span class='notice'>Now viewing video session. To leave camera view: OOC -> Cancel Camera View</span>" to_chat(user,"<span class='notice'>Now viewing video session. To leave camera view, close the communicator window OR: OOC -> Cancel Camera View</span>")
to_chat(user,"<span class='notice'>To return to an active video session, use the communicator in your hand.</span>")
spawn(0) spawn(0)
while(user.machine == video_source && (Adjacent(user) || loc == user)) while(user.machine == video_source && (Adjacent(user) || loc == user))
var/turf/T = get_turf(video_source) var/turf/T = get_turf(video_source)

View File

@@ -155,7 +155,7 @@
singular_name = "advanced trauma kit" singular_name = "advanced trauma kit"
desc = "An advanced trauma kit for severe injuries." desc = "An advanced trauma kit for severe injuries."
icon_state = "traumakit" icon_state = "traumakit"
heal_brute = 0 heal_brute = 5
origin_tech = list(TECH_BIO = 1) origin_tech = list(TECH_BIO = 1)
/obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob) /obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob)
@@ -213,7 +213,7 @@
singular_name = "advanced burn kit" singular_name = "advanced burn kit"
desc = "An advanced treatment kit for severe burns." desc = "An advanced treatment kit for severe burns."
icon_state = "burnkit" icon_state = "burnkit"
heal_burn = 0 heal_burn = 5
origin_tech = list(TECH_BIO = 1) origin_tech = list(TECH_BIO = 1)

View File

@@ -1,59 +0,0 @@
/obj/item/weapon/dice
name = "d6"
desc = "A dice with six sides."
icon = 'icons/obj/dice.dmi'
icon_state = "d66"
w_class = ITEMSIZE_TINY
var/sides = 6
attack_verb = list("diced")
/obj/item/weapon/dice/New()
icon_state = "[name][rand(1,sides)]"
/obj/item/weapon/dice/d4
name = "d4"
desc = "A dice with four sides."
icon_state = "d44"
sides = 4
/obj/item/weapon/dice/d8
name = "d8"
desc = "A dice with eight sides."
icon_state = "d88"
sides = 8
/obj/item/weapon/dice/d10
name = "d10"
desc = "A dice with ten sides."
icon_state = "d1010"
sides = 10
/obj/item/weapon/dice/d12
name = "d12"
desc = "A dice with twelve sides."
icon_state = "d1212"
sides = 12
/obj/item/weapon/dice/d20
name = "d20"
desc = "A dice with twenty sides."
icon_state = "d2020"
sides = 20
/obj/item/weapon/dice/d100
name = "d100"
desc = "A dice with ten sides. This one is for the tens digit."
icon_state = "d10010"
sides = 10
/obj/item/weapon/dice/attack_self(mob/user as mob)
var/result = rand(1, sides)
var/comment = ""
if(sides == 20 && result == 20)
comment = "Nat 20!"
else if(sides == 20 && result == 1)
comment = "Ouch, bad luck."
icon_state = "[name][result]"
user.visible_message("<span class='notice'>[user] has thrown [src]. It lands on [result]. [comment]</span>", \
"<span class='notice'>You throw [src]. It lands on a [result]. [comment]</span>", \
"<span class='notice'>You hear [src] landing on a [result]. [comment]</span>")

View File

@@ -107,7 +107,7 @@
spawn(0) spawn(0)
if(!src || !reagents.total_volume) return if(!src || !reagents.total_volume) return
var/obj/effect/effect/water/W = PoolOrNew(/obj/effect/effect/water, get_turf(src)) var/obj/effect/effect/water/W = new /obj/effect/effect/water(get_turf(src))
var/turf/my_target var/turf/my_target
if(a <= the_targets.len) if(a <= the_targets.len)
my_target = the_targets[a] my_target = the_targets[a]

View File

@@ -86,7 +86,7 @@
if(ptank) if(ptank)
ptank.loc = T ptank.loc = T
ptank = null ptank = null
PoolOrNew(/obj/item/stack/rods, T) new /obj/item/stack/rods(T)
qdel(src) qdel(src)
return return

View File

@@ -12,7 +12,7 @@
/obj/item/weapon/grenade/smokebomb/New() /obj/item/weapon/grenade/smokebomb/New()
..() ..()
src.smoke = PoolOrNew(/datum/effect/effect/system/smoke_spread/bad) src.smoke = new /datum/effect/effect/system/smoke_spread/bad()
src.smoke.attach(src) src.smoke.attach(src)
/obj/item/weapon/grenade/smokebomb/Destroy() /obj/item/weapon/grenade/smokebomb/Destroy()

View File

@@ -41,6 +41,8 @@
user << "<span class='danger'>You need to have a firm grip on [C] before you can put \the [src] on!</span>" user << "<span class='danger'>You need to have a firm grip on [C] before you can put \the [src] on!</span>"
/obj/item/weapon/handcuffs/proc/can_place(var/mob/target, var/mob/user) /obj/item/weapon/handcuffs/proc/can_place(var/mob/target, var/mob/user)
if(user == target)
return 1
if(istype(user, /mob/living/silicon/robot)) if(istype(user, /mob/living/silicon/robot))
if(user.Adjacent(target)) if(user.Adjacent(target))
return 1 return 1

View File

@@ -0,0 +1,96 @@
/obj/item/weapon/implant/reagent_generator
name = "reagent generator implant"
desc = "This is an implant that has attached storage and generates a reagent."
implant_color = "r"
var/datum/reagent/generated_reagent = null
var/gen_amount = 2 //amount of reagent generated per process tick
var/gen_cost = 0.5 //amount of nutrient taken from the host per process tick
var/transfer_amount = 30 //amount transferred when using verb
var/usable_volume = 120
var/list/empty_message = list("You feel as though your internal reagent implant is almost empty.")
var/list/full_message = "You feel as though your internal reagent implant is full."
var/list/emote_descriptor = list("tranfers something") //In format of [x] [emote_descriptor] into [container]
var/list/self_emote_descriptor = list("transfer") //In format of You [self_emote_descriptor] some [generated_reagent] into [container]
var/list/random_emote = list() //An emote the person with the implant may be forced to perform after a prob check, such as [X] meows.
var/assigned_proc = /mob/living/carbon/human/proc/use_reagent_implant
/obj/item/weapon/implant/reagent_generator/New()
..()
create_reagents(usable_volume)
/obj/item/weapon/implanter/reagent_generator
var/implant_type = /obj/item/weapon/implant/reagent_generator
/obj/item/weapon/implanter/reagent_generator/New()
..()
imp = new implant_type(src)
update()
return
/obj/item/weapon/implant/reagent_generator/implanted(mob/living/carbon/source)
processing_objects += src
to_chat(source, "<span class='notice'>You implant [source] with \the [src].</span>")
source.verbs |= assigned_proc
return 1
/obj/item/weapon/implant/reagent_generator/process()
var/before_gen
if(imp_in && generated_reagent)
before_gen = reagents.total_volume
if(reagents.total_volume < reagents.maximum_volume)
if(imp_in.nutrition >= gen_cost)
do_generation()
else
return
else
imp_in.verbs -= assigned_proc
return
if(reagents)
if(reagents.total_volume == reagents.maximum_volume * 0.05)
to_chat(imp_in, "<span class='notice'>[pick(empty_message)]</span>")
else if(reagents.total_volume == reagents.maximum_volume && before_gen < reagents.maximum_volume)
to_chat(imp_in, "<span class='warning'>[pick(full_message)]</span>")
/obj/item/weapon/implant/reagent_generator/proc/do_generation()
imp_in.nutrition -= gen_cost
reagents.add_reagent(generated_reagent, gen_amount)
/mob/living/carbon/human/proc/use_reagent_implant()
set name = "Transfer From Reagent Implant"
set desc = "Remove reagents from am internal reagent into a container."
set category = "Object"
set src in view(1)
do_reagent_implant(usr)
/mob/living/carbon/human/proc/do_reagent_implant(var/mob/living/carbon/human/user = usr)
if(!isliving(user) || !user.canClick())
return
if(user.incapacitated() || user.stat > CONSCIOUS)
return
var/obj/item/weapon/reagent_containers/container = user.get_active_hand()
if(!container)
to_chat(user,"<span class='notice'>You need an open container to do this!</span>")
return
var/obj/item/weapon/implant/reagent_generator/rimplant
for(var/I in src.contents)
if(istype(I, /obj/item/weapon/implant/reagent_generator))
rimplant = I
break
if(rimplant)
if(container.reagents.total_volume < container.volume)
var/container_name = container.name
if(rimplant.reagents.trans_to(container, amount = rimplant.transfer_amount))
user.visible_message("<span class='notice'>[usr] [pick(rimplant.emote_descriptor)] into \the [container_name].</span>",
"<span class='notice'>You [pick(rimplant.self_emote_descriptor)] some [rimplant.generated_reagent] into \the [container_name].</span>")
if(prob(5))
src.visible_message("<span class='notice'>[src] [pick(rimplant.random_emote)].</span>") // M-mlem.
if(rimplant.reagents.total_volume == rimplant.reagents.maximum_volume * 0.05)
to_chat(src, "<span class='notice'>[pick(rimplant.empty_message)]</span>")

View File

@@ -130,7 +130,7 @@
. = ..() . = ..()
if(.) if(.)
var/datum/effect/effect/system/spark_spread/spark_system = PoolOrNew(/datum/effect/effect/system/spark_spread) var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, user.loc) spark_system.set_up(5, 0, user.loc)
spark_system.start() spark_system.start()
playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1) playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)

View File

@@ -126,7 +126,7 @@
new /obj/item/weapon/storage/pill_bottle/dylovene(src) new /obj/item/weapon/storage/pill_bottle/dylovene(src)
new /obj/item/weapon/storage/pill_bottle/tramadol(src) new /obj/item/weapon/storage/pill_bottle/tramadol(src)
new /obj/item/weapon/storage/pill_bottle/spaceacillin(src) new /obj/item/weapon/storage/pill_bottle/spaceacillin(src)
new /obj/item/weapon/reagent_containers/hypospray/autoinjector/clotting(src) new /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting(src)
new /obj/item/stack/medical/splint(src) new /obj/item/stack/medical/splint(src)
return return
@@ -161,7 +161,7 @@
if (empty) if (empty)
return return
for(var/i = 1 to 8) for(var/i = 1 to 8)
new /obj/item/weapon/reagent_containers/hypospray/autoinjector/clotting(src) new /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting(src)
return return
/* /*

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