diff --git a/.travis.yml b/.travis.yml index 432d4093149..2ccfc698015 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,9 @@ language: c sudo: false env: - BYOND_MAJOR="510" - BYOND_MINOR="1346" - MACRO_COUNT=986 + BYOND_MAJOR="511" + BYOND_MINOR="1381" + MACRO_COUNT=875 cache: directories: diff --git a/code/ZAS/Atom.dm b/code/ZAS/Atom.dm index ce69ad71622..49613559409 100644 --- a/code/ZAS/Atom.dm +++ b/code/ZAS/Atom.dm @@ -57,11 +57,11 @@ turf/c_airblock(turf/other) #ifdef ZASDBG ASSERT(isturf(other)) #endif - if(blocks_air || other.blocks_air) + if(((blocks_air & AIR_BLOCKED) || (other.blocks_air & AIR_BLOCKED))) return BLOCKED //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(!istype(src, /turf/simulated/open)) return BLOCKED @@ -69,6 +69,12 @@ turf/c_airblock(turf/other) if(!istype(other, /turf/simulated/open)) return BLOCKED #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 for(var/atom/movable/M in contents) result |= M.c_airblock(other) diff --git a/code/ZAS/ConnectionManager.dm b/code/ZAS/ConnectionManager.dm index 1c101f4b45a..28ef3658304 100644 --- a/code/ZAS/ConnectionManager.dm +++ b/code/ZAS/ConnectionManager.dm @@ -37,7 +37,7 @@ Class Procs: /connection_manager/var/connection/E /connection_manager/var/connection/W -#ifdef ZLEVELS +#ifdef MULTIZAS /connection_manager/var/connection/U /connection_manager/var/connection/D #endif @@ -57,7 +57,7 @@ Class Procs: if(check(W)) return W else return null - #ifdef ZLEVELS + #ifdef MULTIZAS if(UP) if(check(U)) return U else return null @@ -73,7 +73,7 @@ Class Procs: if(EAST) E = c if(WEST) W = c - #ifdef ZLEVELS + #ifdef MULTIZAS if(UP) U = c if(DOWN) D = c #endif @@ -83,7 +83,7 @@ Class Procs: if(check(S)) S.update() if(check(E)) E.update() if(check(W)) W.update() - #ifdef ZLEVELS + #ifdef MULTIZAS if(check(U)) U.update() if(check(D)) D.update() #endif @@ -93,7 +93,7 @@ Class Procs: if(check(S)) S.erase() if(check(E)) E.erase() if(check(W)) W.erase() - #ifdef ZLEVELS + #ifdef MULTIZAS if(check(U)) U.erase() if(check(D)) D.erase() #endif diff --git a/code/ZAS/Controller.dm b/code/ZAS/Controller.dm index cfd6cff4148..2469f7a36ff 100644 --- a/code/ZAS/Controller.dm +++ b/code/ZAS/Controller.dm @@ -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. //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. + + //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() for(var/turf/T in updating) diff --git a/code/ZAS/Diagnostic.dm b/code/ZAS/Diagnostic.dm index ed94b7d5825..10ec2e731b5 100644 --- a/code/ZAS/Diagnostic.dm +++ b/code/ZAS/Diagnostic.dm @@ -39,6 +39,10 @@ client/proc/Test_ZAS_Connection(var/turf/simulated/T as turf) "South" = SOUTH,\ "East" = EAST,\ "West" = WEST,\ + #ifdef MULTIZAS + "Up" = UP,\ + "Down" = DOWN,\ + #endif "N/A" = null) var/direction = input("What direction do you wish to test?","Set direction") as null|anything in direction_list if(!direction) diff --git a/code/ZAS/Turf.dm b/code/ZAS/Turf.dm index 62cad5e469c..bb5eb5050eb 100644 --- a/code/ZAS/Turf.dm +++ b/code/ZAS/Turf.dm @@ -16,7 +16,7 @@ //dbg(blocked) return 1 - #ifdef ZLEVELS + #ifdef MULTIZAS for(var/d = 1, d < 64, d *= 2) #else for(var/d = 1, d < 16, d *= 2) @@ -52,34 +52,40 @@ */ /turf/simulated/proc/can_safely_remove_from_zone() - #ifdef ZLEVELS - return 0 //TODO generalize this to multiz. - #else - + + if(!zone) return 1 - + var/check_dirs = get_zone_neighbours(src) 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) if((dir & check_dirs) == dir) //check that they are connected by the corner turf 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 - + //it is safe to remove src from the zone if all cardinals are connected by corner turfs return !unconnected_dirs - - #endif //helper for can_safely_remove_from_zone() /turf/simulated/proc/get_zone_neighbours(turf/simulated/T) . = 0 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) if(istype(other) && other.zone == T.zone && !(other.c_airblock(T) & AIR_BLOCKED) && get_dist(src, other) <= 1) . |= dir @@ -98,7 +104,7 @@ #endif if(zone) var/zone/z = zone - + if(can_safely_remove_from_zone()) //Helps normal airlocks avoid rebuilding zones all the time z.remove(src) else @@ -110,7 +116,7 @@ open_directions = 0 var/list/postponed - #ifdef ZLEVELS + #ifdef MULTIZAS for(var/d = 1, d < 64, d *= 2) #else for(var/d = 1, d < 16, d *= 2) @@ -161,7 +167,7 @@ //Might have assigned a zone, since this happens for each direction. if(!zone) - //We do not merge if + //We do not merge if // they are blocking us and we are not blocking them, or if // we are blocking them and not blocking ourselves - this prevents tiny zones from forming on doorways. if(((block & ZONE_BLOCKED) && !(r_block & ZONE_BLOCKED)) || ((r_block & ZONE_BLOCKED) && !(s_block & ZONE_BLOCKED))) diff --git a/code/ZAS/_docs.dm b/code/ZAS/_docs.dm index 1f652ffaaba..4433478e321 100644 --- a/code/ZAS/_docs.dm +++ b/code/ZAS/_docs.dm @@ -28,8 +28,7 @@ Notes for people who used ZAS before: */ //#define ZASDBG -//#define ZLEVELS - +//#define MULTIZAS #define AIR_BLOCKED 1 #define ZONE_BLOCKED 2 #define BLOCKED 3 diff --git a/code/__defines/gamemode.dm b/code/__defines/gamemode.dm index 8115790c506..cd0c9955c13 100644 --- a/code/__defines/gamemode.dm +++ b/code/__defines/gamemode.dm @@ -123,4 +123,6 @@ var/list/be_special_flags = list( //casting costs #define Sp_RECHARGE "recharge" #define Sp_CHARGES "charges" -#define Sp_HOLDVAR "holdervar" \ No newline at end of file +#define Sp_HOLDVAR "holdervar" + +#define CHANGELING_STASIS_COST 20 \ No newline at end of file diff --git a/code/__defines/items_clothing.dm b/code/__defines/items_clothing.dm index eb572aa0e29..0a8598d21f1 100644 --- a/code/__defines/items_clothing.dm +++ b/code/__defines/items_clothing.dm @@ -33,7 +33,7 @@ #define PROXMOVE 0x80 // Does this object require proximity checking in Enter()? //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 AIRTIGHT 0x4 // Functions with internals. #define NOSLIP 0x8 // Prevents from slipping on wet floors, in space, etc. diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 09f5e81ca00..f85ac5e7d4a 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -69,6 +69,11 @@ #define COLOR_PALE_RED_GRAY "#CC9090" #define COLOR_PALE_PURPLE_GRAY "#BDA2BA" #define COLOR_PURPLE_GRAY "#A2819E" +#define COLOR_RED_LIGHT "#FF3333" +#define COLOR_DEEP_SKY_BLUE "#00e1ff" + + + // Shuttles. diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 7180fe4c376..ef00eed3341 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -206,4 +206,10 @@ #define TASTE_SENSITIVE 2 //anything below 7% #define TASTE_NORMAL 1 //anything below 15% #define TASTE_DULL 0.5 //anything below 30% -#define TASTE_NUMB 0.1 //anything below 150% \ No newline at end of file +#define TASTE_NUMB 0.1 //anything below 150% + +// If they're in an FBP, what braintype. +#define FBP_NONE "" +#define FBP_CYBORG "Cyborg" +#define FBP_POSI "Positronic" +#define FBP_DRONE "Drone" \ No newline at end of file diff --git a/code/_helpers/datum_pool.dm b/code/_helpers/datum_pool.dm deleted file mode 100644 index b5bcea123fe..00000000000 --- a/code/_helpers/datum_pool.dm +++ /dev/null @@ -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 diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm index 1531a67d5b4..b59857c8f6b 100644 --- a/code/_helpers/game.dm +++ b/code/_helpers/game.dm @@ -284,7 +284,7 @@ if(M.loc && M.locs[1] in hearturfs) mobs |= M - else if(M.stat == DEAD) + else if(M.stat == DEAD && !M.forbid_seeing_deadchat) switch(type) if(1) //Audio messages use ghost_ears if(M.is_preference_enabled(/datum/client_preference/ghost_ears)) diff --git a/code/_onclick/hud/ability_screen_objects.dm b/code/_onclick/hud/ability_screen_objects.dm index 1e6844b6ad1..2081e011b35 100644 --- a/code/_onclick/hud/ability_screen_objects.dm +++ b/code/_onclick/hud/ability_screen_objects.dm @@ -32,11 +32,6 @@ my_mob.client.screen -= src my_mob = null -/obj/screen/movable/ability_master/ResetVars() - ..("ability_objects", args) - remove_all_abilities() -// ability_objects = list() - /obj/screen/movable/ability_master/MouseDrop() if(showing) return diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index fd226eb70c9..a00fa6e10dc 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -20,7 +20,7 @@ return null if(!screen) - screen = PoolOrNew(type) + screen = new type() screen.icon_state = "[initial(screen.icon_state)][severity]" screen.severity = severity diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm index 71eff4a3920..3602a524811 100644 --- a/code/_onclick/hud/movable_screen_objects.dm +++ b/code/_onclick/hud/movable_screen_objects.dm @@ -45,49 +45,61 @@ screen_loc = "[screen_loc_X[1]]:[pix_X],[screen_loc_Y[1]]:[pix_Y]" /obj/screen/movable/proc/encode_screen_X(X) - if(X > usr.client.view+1) - . = "EAST-[usr.client.view*2 + 1-X]" - else if(X < usr.client.view+1) + var/view_dist = world.view + if(view_dist) + view_dist = view_dist + if(X > view_dist+1) + . = "EAST-[view_dist *2 + 1-X]" + else if(X < view_dist +1) . = "WEST+[X-1]" else . = "CENTER" /obj/screen/movable/proc/decode_screen_X(X) + var/view_dist = world.view + if(view_dist) + view_dist = view_dist //Find EAST/WEST implementations if(findtext(X,"EAST-")) var/num = text2num(copytext(X,6)) //Trim EAST- if(!num) num = 0 - . = usr.client.view*2 + 1 - num + . = view_dist*2 + 1 - num else if(findtext(X,"WEST+")) var/num = text2num(copytext(X,6)) //Trim WEST+ if(!num) num = 0 . = num+1 else if(findtext(X,"CENTER")) - . = usr.client.view+1 + . = view_dist+1 /obj/screen/movable/proc/encode_screen_Y(Y) - if(Y > usr.client.view+1) - . = "NORTH-[usr.client.view*2 + 1-Y]" - else if(Y < usr.client.view+1) + var/view_dist = world.view + if(view_dist) + view_dist = view_dist + if(Y > view_dist+1) + . = "NORTH-[view_dist*2 + 1-Y]" + else if(Y < view_dist+1) . = "SOUTH+[Y-1]" else . = "CENTER" /obj/screen/movable/proc/decode_screen_Y(Y) + var/view_dist = world.view + if(view_dist) + view_dist = view_dist if(findtext(Y,"NORTH-")) var/num = text2num(copytext(Y,7)) //Trim NORTH- if(!num) num = 0 - . = usr.client.view*2 + 1 - num + . = view_dist*2 + 1 - num else if(findtext(Y,"SOUTH+")) var/num = text2num(copytext(Y,7)) //Time SOUTH+ if(!num) num = 0 . = num+1 else if(findtext(Y,"CENTER")) - . = usr.client.view+1 + . = view_dist+1 //Debug procs /client/proc/test_movable_UI() diff --git a/code/_onclick/hud/spell_screen_objects.dm b/code/_onclick/hud/spell_screen_objects.dm index 262ece09e48..a599381730a 100644 --- a/code/_onclick/hud/spell_screen_objects.dm +++ b/code/_onclick/hud/spell_screen_objects.dm @@ -23,10 +23,6 @@ spell_holder.client.screen -= src spell_holder = null -/obj/screen/movable/spell_master/ResetVars() - ..("spell_objects", args) - spell_objects = list() - /obj/screen/movable/spell_master/MouseDrop() if(showing) return @@ -93,7 +89,7 @@ if(spell.spell_flags & NO_BUTTON) //no button to add if we don't get one return - var/obj/screen/spell/newscreen = PoolOrNew(/obj/screen/spell) + var/obj/screen/spell/newscreen = new /obj/screen/spell() newscreen.spellmaster = src newscreen.spell = spell diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm index 4c976f44585..f08727abf35 100644 --- a/code/_onclick/telekinesis.dm +++ b/code/_onclick/telekinesis.dm @@ -149,7 +149,7 @@ var/const/tk_maxrange = 15 /obj/item/tk_grab/proc/apply_focus_overlay() 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.anchored = 1 O.density = 0 diff --git a/code/controllers/Processes/garbage.dm b/code/controllers/Processes/garbage.dm index 2d56dde1a26..02f04113320 100644 --- a/code/controllers/Processes/garbage.dm +++ b/code/controllers/Processes/garbage.dm @@ -152,19 +152,13 @@ world/loop_checks = 0 A.finalize_qdel() /datum/proc/finalize_qdel() - if(IsPooled(src)) - PlaceInPool(src) - else - del(src) + del(src) /atom/finalize_qdel() - if(IsPooled(src)) - PlaceInPool(src) + if(garbage_collector) + garbage_collector.AddTrash(src) else - if(garbage_collector) - garbage_collector.AddTrash(src) - else - delayed_garbage |= src + delayed_garbage |= src /icon/finalize_qdel() del(src) @@ -180,7 +174,7 @@ world/loop_checks = 0 // Default implementation of clean-up code. // 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() nanomanager.close_uis(src) tag = null diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 57f22472551..5021453462e 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -166,6 +166,7 @@ var/list/gamemode_cache = list() var/simultaneous_pm_warning_timeout = 100 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/gateway_delay = 18000 //How long the gateway takes before it activates. Default is half an hour. @@ -283,6 +284,9 @@ var/list/gamemode_cache = list() if ("use_recursive_explosions") use_recursive_explosions = 1 + if ("multi_z_explosion_scalar") + multi_z_explosion_scalar = text2num(value) + if ("log_ooc") config.log_ooc = 1 diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index d40fd4fa5a3..274c0c0903d 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -184,6 +184,10 @@ G.fields["real_rank"] = H.mind.assigned_role G.fields["rank"] = assignment G.fields["age"] = H.age + if(H.get_FBP_type()) + G.fields["brain_type"] = H.get_FBP_type() + else + G.fields["brain_type"] = "Organic" G.fields["fingerprint"] = md5(H.dna.uni_identity) G.fields["p_stat"] = "Active" G.fields["m_stat"] = "Stable" @@ -201,11 +205,19 @@ M.fields["b_type"] = H.b_type M.fields["b_dna"] = H.dna.unique_enzymes M.fields["id_gender"] = gender2text(H.identifying_gender) + if(H.get_FBP_type()) + M.fields["brain_type"] = H.get_FBP_type() + else + M.fields["brain_type"] = "Organic" if(H.med_record && !jobban_isbanned(H, "Records")) M.fields["notes"] = H.med_record //Security Record var/datum/data/record/S = CreateSecurityRecord(H.real_name, id) + if(H.get_FBP_type()) + S.fields["brain_type"] = H.get_FBP_type() + else + S.fields["brain_type"] = "Organic" if(H.sec_record && !jobban_isbanned(H, "Records")) S.fields["notes"] = H.sec_record @@ -218,6 +230,10 @@ L.fields["fingerprint"] = md5(H.dna.uni_identity) L.fields["sex"] = gender2text(H.gender) L.fields["id_gender"] = gender2text(H.identifying_gender) + if(H.get_FBP_type()) + L.fields["brain_type"] = H.get_FBP_type() + else + L.fields["brain_type"] = "Organic" L.fields["b_type"] = H.b_type L.fields["b_dna"] = H.dna.unique_enzymes L.fields["enzymes"] = H.dna.SE // Used in respawning @@ -426,6 +442,7 @@ G.fields["real_rank"] = "Unassigned" G.fields["sex"] = "Unknown" G.fields["age"] = "Unknown" + G.fields["brain_type"] = "Unknown" G.fields["fingerprint"] = "Unknown" G.fields["p_stat"] = "Active" G.fields["m_stat"] = "Stable" @@ -447,6 +464,7 @@ R.name = "Security Record #[id]" R.fields["name"] = name R.fields["id"] = id + R.fields["brain_type"] = "Unknown" R.fields["criminal"] = "None" R.fields["mi_crim"] = "None" R.fields["mi_crim_d"] = "No minor crime convictions." @@ -467,6 +485,7 @@ M.fields["b_type"] = "AB+" M.fields["b_dna"] = md5(name) M.fields["id_gender"] = "Unknown" + M.fields["brain_type"] = "Unknown" M.fields["mi_dis"] = "None" M.fields["mi_dis_d"] = "No minor disabilities have been declared." M.fields["ma_dis"] = "None" diff --git a/code/datums/repositories/decls.dm b/code/datums/repositories/decls.dm new file mode 100644 index 00000000000..e87be74f531 --- /dev/null +++ b/code/datums/repositories/decls.dm @@ -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 \ No newline at end of file diff --git a/code/datums/repositories/repository.dm b/code/datums/repositories/repository.dm index 6267099c930..04eee505401 100644 --- a/code/datums/repositories/repository.dm +++ b/code/datums/repositories/repository.dm @@ -1,4 +1,19 @@ +/repository/New() + return + /datum/cache_entry var/timestamp 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 \ No newline at end of file diff --git a/code/datums/supplypacks/contraband.dm b/code/datums/supplypacks/contraband.dm index d6427f063f2..0c7fd3f4eda 100644 --- a/code/datums/supplypacks/contraband.dm +++ b/code/datums/supplypacks/contraband.dm @@ -32,6 +32,17 @@ containername = "Special Ops crate" 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 name = "Surplus militia rifles" contains = list( diff --git a/code/datums/supplypacks/security.dm b/code/datums/supplypacks/security.dm index 1ec25bc28d0..e248acc46c0 100644 --- a/code/datums/supplypacks/security.dm +++ b/code/datums/supplypacks/security.dm @@ -200,6 +200,7 @@ /obj/item/clothing/under/det/black = 2, /obj/item/clothing/under/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/head/det = 2, /obj/item/clothing/suit/storage/det_trench, diff --git a/code/datums/underwear/undershirts.dm b/code/datums/underwear/undershirts.dm index 83cae026cec..59f33be094a 100644 --- a/code/datums/underwear/undershirts.dm +++ b/code/datums/underwear/undershirts.dm @@ -8,11 +8,6 @@ icon_state = "undershirt" 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 name = "Babydoll shirt" icon_state = "undershirt_fem" @@ -23,11 +18,22 @@ icon_state = "undershirt_long" 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 name = "Longsleeve Shirt, feminine" icon_state = "undershirt_long_fem" 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 name = "Tank top" icon_state = "tanktop" diff --git a/code/datums/uplink/medical.dm b/code/datums/uplink/medical.dm index eab9d9cd021..0c616793ca1 100644 --- a/code/datums/uplink/medical.dm +++ b/code/datums/uplink/medical.dm @@ -22,12 +22,12 @@ /datum/uplink_item/item/medical/clotting name = "Clotting Medicine injector" 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 name = "Bone Repair injector" 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 name = "Box of 7x ambrosia deus seed packets" diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 01e95e5716a..b98b2370ce1 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -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/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/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/forced_ambience = null var/sound_env = STANDARD_STATION diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index f1520509902..32a58c5dbea 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -53,22 +53,28 @@ danger_level = max(danger_level, AA.danger_level) 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 + //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) AA.update_icon() return 1 return 0 -/area/proc/air_doors_close() - if(!air_doors_activated) - air_doors_activated = 1 +// Either close or open firedoors depending on current alert statuses +/area/proc/firedoors_update() + 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) if(!E.blocked) if(E.operating) @@ -77,9 +83,10 @@ spawn(0) E.close() -/area/proc/air_doors_open() - if(air_doors_activated) - air_doors_activated = 0 +// Open all firedoors in the area +/area/proc/firedoors_open() + if(firedoors_closed) + firedoors_closed = FALSE for(var/obj/machinery/door/firedoor/E in all_doors) if(!E.blocked) if(E.operating) @@ -93,27 +100,13 @@ if(!fire) fire = 1 //used for firedoor checks updateicon() - mouse_opacity = 0 - 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() + firedoors_update() /area/proc/fire_reset() if (fire) fire = 0 //used for firedoor checks updateicon() - mouse_opacity = 0 - 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() + firedoors_update() /area/proc/readyalert() if(!eject) @@ -131,21 +124,14 @@ if (!( party )) party = 1 updateicon() - mouse_opacity = 0 + firedoors_update() return /area/proc/partyreset() if (party) party = 0 - mouse_opacity = 0 updateicon() - for(var/obj/machinery/door/firedoor/D in src) - if(!D.blocked) - if(D.operating) - D.nextstate = FIREDOOR_OPEN - else if(D.density) - spawn(0) - D.open() + firedoors_update() return /area/proc/updateicon() diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index 2234e0a540a..e54eb3c1cd0 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -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/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/last_shriek = null // world.time when the ling last used a shriek. /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 ;_; ////////// +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) if(M.loc == src.loc) 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 << "We cannot reach \the [M] with a sting!" 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 - 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 << "We cannot find a path to sting \the [M] by!" return 0 return 1 diff --git a/code/game/gamemodes/changeling/generic_equip_procs.dm b/code/game/gamemodes/changeling/generic_equip_procs.dm index e8ed12a446b..9c73a4e3d22 100644 --- a/code/game/gamemodes/changeling/generic_equip_procs.dm +++ b/code/game/gamemodes/changeling/generic_equip_procs.dm @@ -32,7 +32,7 @@ return 1 if(M.head || M.wear_suit) //Make sure our slots aren't full - src << "We require nothing to be on our head, and we cannot wear any external suits." + src << "We require nothing to be on our head, and we cannot wear any external suits, or shoes." return 0 var/obj/item/clothing/suit/A = new armor_type(src) @@ -140,7 +140,7 @@ playsound(src, 'sound/effects/blobattack.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["w_uniform"] if(!M.w_uniform && t) @@ -150,7 +150,7 @@ playsound(src, 'sound/effects/blobattack.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["gloves"] if(!M.gloves && t) @@ -160,7 +160,7 @@ playsound(src, 'sound/effects/splat.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["shoes"] if(!M.shoes && t) @@ -170,7 +170,7 @@ playsound(src, 'sound/effects/splat.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["belt"] if(!M.belt && t) @@ -180,7 +180,7 @@ playsound(src, 'sound/effects/splat.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["glasses"] if(!M.glasses && t) @@ -190,7 +190,7 @@ playsound(src, 'sound/effects/splat.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["wear_mask"] if(!M.wear_mask && t) @@ -200,7 +200,7 @@ playsound(src, 'sound/effects/splat.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["back"] if(!M.back && t) @@ -210,7 +210,7 @@ playsound(src, 'sound/effects/blobattack.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["wear_suit"] if(!M.wear_suit && t) @@ -220,7 +220,7 @@ playsound(src, 'sound/effects/blobattack.ogg', 30, 1) M.update_icons() success = 1 - sleep(20) + sleep(1 SECOND) t = stuff_to_equip["wear_id"] if(!M.wear_id && t) @@ -230,7 +230,7 @@ playsound(src, 'sound/effects/splat.ogg', 30, 1) M.update_icons() 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 = "" ) diff --git a/code/game/gamemodes/changeling/powers/boost_range.dm b/code/game/gamemodes/changeling/powers/boost_range.dm index fd15d94daec..a22130484ca 100644 --- a/code/game/gamemodes/changeling/powers/boost_range.dm +++ b/code/game/gamemodes/changeling/powers/boost_range.dm @@ -18,11 +18,11 @@ if(!changeling) return 0 changeling.chem_charges -= 10 - src << "Your throat adjusts to launch the sting." + to_chat(src, "Your throat adjusts to launch the sting.") var/range = 2 if(src.mind.changeling.recursive_enhancement) range = range + 3 - src << "We can fire our next sting from five squares away." + to_chat(src, "We can fire our next sting from five squares away.") changeling.sting_range = range src.verbs -= /mob/proc/changeling_boost_range spawn(5) diff --git a/code/game/gamemodes/changeling/powers/fabricate_clothing.dm b/code/game/gamemodes/changeling/powers/fabricate_clothing.dm index f106d9167fb..138cd156e38 100644 --- a/code/game/gamemodes/changeling/powers/fabricate_clothing.dm +++ b/code/game/gamemodes/changeling/powers/fabricate_clothing.dm @@ -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. \ To remove our new fabricated clothing, use this ability again." ability_icon_state = "ling_fabricate_clothing" - genomecost = 2 + genomecost = 1 verbpath = /mob/proc/changeling_fabricate_clothing //Grows biological versions of chameleon clothes. diff --git a/code/game/gamemodes/changeling/powers/fake_death.dm b/code/game/gamemodes/changeling/powers/fake_death.dm index dee603fc4a9..765dbb51e61 100644 --- a/code/game/gamemodes/changeling/powers/fake_death.dm +++ b/code/game/gamemodes/changeling/powers/fake_death.dm @@ -12,7 +12,7 @@ set category = "Changeling" 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) return @@ -28,6 +28,7 @@ C.update_canmove() C.remove_changeling_powers() + changeling.chem_charges -= CHANGELING_STASIS_COST if(C.suiciding) C.suiciding = 0 @@ -35,7 +36,9 @@ if(C.stat != DEAD) 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 src.verbs += /mob/proc/changeling_revive src << "We are ready to rise. Use the Revive verb when you are ready." diff --git a/code/game/gamemodes/changeling/powers/respec.dm b/code/game/gamemodes/changeling/powers/respec.dm index d984083aba9..66f13e720f1 100644 --- a/code/game/gamemodes/changeling/powers/respec.dm +++ b/code/game/gamemodes/changeling/powers/respec.dm @@ -29,6 +29,3 @@ src << "We have removed our evolutions from this form, and are now ready to readapt." ling_datum.purchased_powers_history.Add("Re-adapt (Reset to [ling_datum.max_geneticpoints])") - - //Now to lose the verb, so no unlimited resets. - diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm index 2f0b9c57e75..c640e353925 100644 --- a/code/game/gamemodes/changeling/powers/revive.dm +++ b/code/game/gamemodes/changeling/powers/revive.dm @@ -41,6 +41,10 @@ current_limb.undislocate() 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.shock_stage = 0 //Pain C << "We have regenerated." @@ -48,8 +52,12 @@ C.mind.changeling.purchased_powers -= C feedback_add_details("changeling_powers","CR") C.stat = CONSCIOUS + C.forbid_seeing_deadchat = FALSE C.timeofdeath = null src.verbs -= /mob/proc/changeling_revive // re-add our changeling powers C.make_changeling() + + + return 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/shriek.dm b/code/game/gamemodes/changeling/powers/shriek.dm index ded66148fa4..37e7f67fe04 100644 --- a/code/game/gamemodes/changeling/powers/shriek.dm +++ b/code/game/gamemodes/changeling/powers/shriek.dm @@ -35,6 +35,14 @@ src << "You can't speak!" return 0 + if(world.time < (changeling.last_shriek + 10 SECONDS) ) + to_chat(src, "We are still recovering from our last shriek...") + return 0 + + if(!isturf(loc)) + to_chat(src, "Shrieking here would be a bad idea.") + return 0 + src.break_cloak() //No more invisible shrieking changeling.chem_charges -= 20 @@ -47,6 +55,8 @@ message_admins("[key_name(src)] used Resonant Shriek ([src.x],[src.y],[src.z]) (JMP).") log_game("[key_name(src)] used Resonant Shriek.") + visible_message("[src] appears to shout.") + for(var/mob/living/M in range(range, src)) if(iscarbon(M)) if(!M.mind || !M.mind.changeling) @@ -73,11 +83,7 @@ L.on = 1 L.broken() -/* src.verbs -= /mob/proc/changeling_resonant_shriek - spawn(30 SECONDS) - src << "We are ready to use our resonant shriek once more." - src.verbs |= /mob/proc/changeling_resonant_shriek -Ability Cooldowns don't work properly right now, need to redo this when they are */ + changeling.last_shriek = world.time feedback_add_details("changeling_powers","RS") return 1 @@ -101,6 +107,14 @@ Ability Cooldowns don't work properly right now, need to redo this when they are src << "You can't speak!" return 0 + if(world.time < (changeling.last_shriek + 10 SECONDS) ) + to_chat(src, "We are still recovering from our last shriek...") + return 0 + + if(!isturf(loc)) + to_chat(src, "Shrieking here would be a bad idea.") + return 0 + src.break_cloak() //No more invisible shrieking changeling.chem_charges -= 20 @@ -117,6 +131,8 @@ Ability Cooldowns don't work properly right now, need to redo this when they are src << "We are extra loud." src.mind.changeling.recursive_enhancement = 0 + visible_message("[src] appears to shout.") + src.attack_log += text("\[[time_stamp()]\] Used Dissonant Shriek.") message_admins("[key_name(src)] used Dissonant Shriek ([src.x],[src.y],[src.z]) (JMP).") 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() empulse(get_turf(src), range_heavy, range_light, 1) -/* src.verbs -= /mob/proc/changeling_dissonant_shriek - spawn(30 SECONDS) - src << "We are ready to use our dissonant shriek once more." - src.verbs |= /mob/proc/changeling_dissonant_shriek -Ability Cooldowns don't work properly right now, need to redo this when they are */ + changeling.last_shriek = world.time + return 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm index 236af69f5fd..37a99452102 100644 --- a/code/game/gamemodes/changeling/powers/transform.dm +++ b/code/game/gamemodes/changeling/powers/transform.dm @@ -13,6 +13,10 @@ var/datum/changeling/changeling = changeling_power(5,1,0) if(!changeling) return + if(!isturf(loc)) + to_chat(src, "Transforming here would be a bad idea.") + return 0 + var/list/names = list() for(var/datum/absorbed_dna/DNA in changeling.absorbed_dna) names += "[DNA.name]" diff --git a/code/game/gamemodes/changeling/powers/visible_camouflage.dm b/code/game/gamemodes/changeling/powers/visible_camouflage.dm index 00e31cc932d..167f6f41b9b 100644 --- a/code/game/gamemodes/changeling/powers/visible_camouflage.dm +++ b/code/game/gamemodes/changeling/powers/visible_camouflage.dm @@ -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. \ 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." - enhancedtext = "True invisiblity while cloaked." + enhancedtext = "Can run while hidden." ability_icon_state = "ling_camoflage" genomecost = 3 verbpath = /mob/proc/changeling_visible_camouflage @@ -31,20 +31,35 @@ var/old_regen_rate = H.mind.changeling.chem_recharge_rate H << "We vanish from sight, and will remain hidden, so long as we move carefully." - H.set_m_intent("walk") H.mind.changeling.cloaked = 1 H.mind.changeling.chem_recharge_rate = 0 animate(src,alpha = 255, alpha = 10, time = 10) + var/must_walk = TRUE if(src.mind.changeling.recursive_enhancement) - H.invisibility = INVISIBILITY_OBSERVER - src << "We are now truly invisible." + must_walk = FALSE + to_chat(src, "We may move at our normal speed while hidden.") + + 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. 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. - sleep(10) + H.invisibility = initial(invisibility) diff --git a/code/game/gamemodes/events/holidays/Holidays.dm b/code/game/gamemodes/events/holidays/Holidays.dm index 7838ba3dd39..8392002a362 100644 --- a/code/game/gamemodes/events/holidays/Holidays.dm +++ b/code/game/gamemodes/events/holidays/Holidays.dm @@ -59,7 +59,7 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t if(14) 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 \ - 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) Holiday["St. Patrick's Day"] = "An old holiday originating from Earth, Sol, celebrating the color green, \ 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) if(1) 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) 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." @@ -105,6 +111,9 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t if(14) 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." + 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 switch(DD) diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index 2d43e67f243..b9418bfea9b 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -7,20 +7,13 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' /datum/game_mode/heist name = "Heist" config_tag = "heist" - required_players = 8 - required_players_secret = 8 - required_enemies = 3 + required_players = 15 + required_players_secret = 15 + required_enemies = 4 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 \ station to be a highly valuable target for many competing organizations and individuals. Being a \ colony of sizable population and considerable wealth causes it to often be the target of various \ attempts of robbery, fraud and other malicious actions." end_on_antag_death = 0 - 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 + antag_tags = list(MODE_RAIDER) \ No newline at end of file diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index e2f6b8a56cc..098f9fd3292 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -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 \ attempts of robbery, fraud and other malicious actions." config_tag = "mercenary" - required_players = 8 - required_players_secret = 8 - required_enemies = 3 + required_players = 15 + required_players_secret = 15 + required_enemies = 4 end_on_antag_death = 0 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 diff --git a/code/game/gamemodes/technomancer/assistance/assistance.dm b/code/game/gamemodes/technomancer/assistance/assistance.dm index 3cdf7014ade..8b060429e8f 100644 --- a/code/game/gamemodes/technomancer/assistance/assistance.dm +++ b/code/game/gamemodes/technomancer/assistance/assistance.dm @@ -30,7 +30,7 @@ /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.attach(loc) @@ -98,8 +98,8 @@ /datum/technomancer/assistance/golem name = "Friendly GOLEM unit" desc = "Teleports a specially designed synthetic unit to you, which is very durable, has an advanced AI, and can also use \ - functions. It knows Shield, Targeted Blink, Beam, Flame Tongue, Mend Wounds, and Mend Burns. It also has a large storage \ - capacity for energy, and due to it's synthetic nature, instability is less of an issue for them." + functions. It knows Shield, Targeted Blink, Beam, Mend Life, Mend Synthetic, Lightning, Repel Missiles, Corona, Ionic Bolt, Dispel, and Chain Lightning. \ + It also has a large storage capacity for energy, and due to it's synthetic nature, instability is less of an issue for them." cost = 350 obj_path = null //TODO one_use_only = 1 diff --git a/code/game/gamemodes/technomancer/assistance/golem.dm b/code/game/gamemodes/technomancer/assistance/golem.dm index 8bb6ef2ea0c..e0a0a5fd716 100644 --- a/code/game/gamemodes/technomancer/assistance/golem.dm +++ b/code/game/gamemodes/technomancer/assistance/golem.dm @@ -1,9 +1,9 @@ //An AI-controlled 'companion' for the Technomancer. It's tough, strong, and can also use spells. -/mob/living/simple_animal/hostile/technomancer_golem +/mob/living/simple_animal/technomancer_golem name = "G.O.L.E.M." desc = "A rather unusual looking synthetic." - icon = 'icons/mob/robots.dmi' - icon_state = "Security" + icon = 'icons/mob/mob.dmi' + icon_state = "technomancer_golem" health = 250 maxHealth = 250 stop_automated_movement = 1 @@ -27,46 +27,137 @@ unsuitable_atoms_damage = 0 speed = 0 - melee_damage_lower = 10 - melee_damage_upper = 10 - attacktext = "pummeled" + melee_damage_lower = 30 // It has a built in esword. + melee_damage_upper = 30 + attacktext = "slashed" attack_sound = null friendly = "hugs" resistance = 0 - var/obj/item/weapon/technomancer_core/core = null - var/obj/item/weapon/spell/active_spell = null + var/obj/item/weapon/technomancer_core/golem/core = null + var/obj/item/weapon/spell/active_spell = null // Shield and ranged spells var/mob/living/master = null -/mob/living/simple_animal/hostile/technomancer_golem/New() - ..() - core = new core(src) + var/list/known_spells = list( + "reflect" = /obj/item/weapon/spell/reflect, + "shield" = /obj/item/weapon/spell/shield, + "dispel" = /obj/item/weapon/spell/dispel, + "mend life" = /obj/item/weapon/spell/modifier/mend_life, + "mend synthetic" = /obj/item/weapon/spell/modifier/mend_synthetic, + "repel missiles" = /obj/item/weapon/spell/modifier/repel_missiles, + "corona" = /obj/item/weapon/spell/modifier/corona, + "beam" = /obj/item/weapon/spell/projectile/beam, + "chain lightning" = /obj/item/weapon/spell/projectile/chain_lightning, + "force missile" = /obj/item/weapon/spell/projectile/force_missile, + "ionic bolt" = /obj/item/weapon/spell/projectile/ionic_bolt, + "lightning" = /obj/item/weapon/spell/projectile/lightning + ) -/mob/living/simple_animal/hostile/technomancer_golem/Destroy() +/mob/living/simple_animal/technomancer_golem/New() + ..() + core = new(src) + update_icon() + +/mob/living/simple_animal/technomancer_golem/Destroy() qdel(core) ..() -/mob/living/simple_animal/hostile/technomancer_golem/proc/bind_to_mob(mob/user) +/mob/living/simple_animal/technomancer_golem/update_icon() + overlays.Cut() + overlays.Add(image(icon, src, "golem_sword")) + overlays.Add(image(icon, src, "golem_spell")) + +/mob/living/simple_animal/technomancer_golem/isSynthetic() + return TRUE // So Mend Synthetic will work on them. + +/mob/living/simple_animal/technomancer_golem/place_spell_in_hand(var/path) + if(!path || !ispath(path)) + return 0 + + if(active_spell) + qdel(active_spell) // Get rid of our old spell. + + var/obj/item/weapon/spell/S = new path(src) + active_spell = S + +/mob/living/simple_animal/technomancer_golem/verb/test_giving_spells() + var/choice = input(usr, "What spell?", "Give spell") as null|anything in known_spells + if(choice) + place_spell_in_hand(known_spells[choice]) + +// Used to cast spells. +/mob/living/simple_animal/technomancer_golem/RangedAttack(var/atom/A, var/params) + if(active_spell) + if(active_spell.cast_methods & CAST_RANGED) + active_spell.on_ranged_cast(A, src) + +/mob/living/simple_animal/technomancer_golem/UnarmedAttack(var/atom/A, var/proximity) + if(proximity) + if(active_spell) + if(active_spell.cast_methods & CAST_MELEE) + active_spell.on_melee_cast(A, src) + else if(active_spell.cast_methods & CAST_RANGED) + active_spell.on_ranged_cast(A, src) + var/effective_cooldown = round(active_spell.cooldown * core.cooldown_modifier, 5) + src.setClickCooldown(effective_cooldown) + else + ..() + +/mob/living/simple_animal/technomancer_golem/get_technomancer_core() + return core + +/mob/living/simple_animal/technomancer_golem/proc/bind_to_mob(mob/user) if(!user || master) return master = user name = "[master]'s [initial(name)]" -/mob/living/simple_animal/hostile/technomancer_golem/examine(mob/user) +/mob/living/simple_animal/technomancer_golem/examine(mob/user) ..() if(user.mind && technomancers.is_antagonist(user.mind)) user << "Your pride and joy. It's a very special synthetic robot, capable of using functions similar to you, and you built it \ yourself! It'll always stand by your side, ready to help you out. You have no idea what GOLEM stands for, however..." -/mob/living/simple_animal/hostile/technomancer_golem/Life() +/mob/living/simple_animal/technomancer_golem/Life() + ..() handle_ai() -/mob/living/simple_animal/hostile/technomancer_golem/proc/handle_ai() +// This is where the real spaghetti begins. +/mob/living/simple_animal/technomancer_golem/proc/handle_ai() if(!master) return if(get_dist(src, master) > 6 || src.z != master.z) - recall_to_master() + targeted_blink(master) + + // Give our allies buffs and heals. + for(var/mob/living/L in view(src)) + if(L in friends) + support_friend(L) + return + +/mob/living/simple_animal/technomancer_golem/proc/support_friend(var/mob/living/L) + if(L.getBruteLoss() >= 10 || L.getFireLoss() >= 10) + if(L.isSynthetic() && !L.has_modifier_of_type(/datum/modifier/technomancer/mend_synthetic)) + place_spell_in_hand(known_spells["mend synthetic"]) + targeted_blink(L) + UnarmedAttack(L, 1) + else if(!L.has_modifier_of_type(/datum/modifier/technomancer/mend_life)) + place_spell_in_hand(known_spells["mend life"]) + targeted_blink(L) + UnarmedAttack(L, 1) + return -/mob/living/simple_animal/hostile/technomancer_golem/proc/recall_to_master() + // Give them repel missiles if they lack it. + if(!L.has_modifier_of_type(/datum/modifier/technomancer/repel_missiles)) + place_spell_in_hand(known_spells["repel missiles"]) + RangedAttack(L) + return + +/mob/living/simple_animal/technomancer_golem/proc/targeted_blink(var/atom/target) + var/datum/effect/effect/system/spark_spread/spark_system = new() + spark_system.set_up(5, 0, get_turf(src)) + spark_system.start() + src.visible_message("\The [src] vanishes!") + src.forceMove(get_turf(target)) return \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/core_obj.dm b/code/game/gamemodes/technomancer/core_obj.dm index 079db9a90be..7cea66660e4 100644 --- a/code/game/gamemodes/technomancer/core_obj.dm +++ b/code/game/gamemodes/technomancer/core_obj.dm @@ -330,6 +330,18 @@ spell_power_modifier = 1.75 energy_cost_modifier = 2.0 +// For use only for the GOLEM. +/obj/item/weapon/technomancer_core/golem + name = "integrated core" + desc = "A bewilderingly complex 'black box' that allows the wearer to accomplish amazing feats. This type is not meant \ + to be worn on the back like other cores. Instead it is meant to be installed inside a synthetic shell. As a result, it's \ + a lot more robust." + energy = 25000 + max_energy = 25000 + regen_rate = 100 //250 seconds to full + instability_modifier = 0.75 + + /obj/item/weapon/technomancer_core/verb/toggle_lock() set name = "Toggle Core Lock" set category = "Object" diff --git a/code/game/gamemodes/technomancer/devices/hypos.dm b/code/game/gamemodes/technomancer/devices/hypos.dm index b54ce5e35c8..dd0fa4436ac 100644 --- a/code/game/gamemodes/technomancer/devices/hypos.dm +++ b/code/game/gamemodes/technomancer/devices/hypos.dm @@ -5,12 +5,11 @@ amount_per_transfer_from_this = 15 volume = 15 origin_tech = list(TECH_BIO = 4) + filled_reagents = list("inaprovaline" = 15) /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/New() ..() - reagents.remove_reagent("inaprovaline", 5) - update_icon() - return + /datum/technomancer/consumable/hypo_brute name = "Trauma Hypo" @@ -66,127 +65,44 @@ name = "trauma hypo" desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to be used on victims of \ moderate blunt trauma." - icon_state = "autoinjector" - 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 + filled_reagents = list("bicaridine" = 15) /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn name = "burn hypo" 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." - icon_state = "autoinjector" - 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 + filled_reagents = list("kelotane" = 7.5, "dermaline" = 7.5) /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/toxin name = "toxin hypo" desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to counteract toxins." - icon_state = "autoinjector" - 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 + filled_reagents = list("anti_toxin" = 15) /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/oxy name = "oxy hypo" desc = "A refined version of the standard autoinjector, allowing greater capacity. This one is made to counteract oxygen \ deprivation." - icon_state = "autoinjector" - 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 + filled_reagents = list("dexalinp" = 10, "tricordrazine" = 5) /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity name = "purity hypo" desc = "A refined version of the standard autoinjector, allowing greater capacity. This varient excels at \ resolving viruses, infections, radiation, and genetic maladies." - icon_state = "autoinjector" - 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 + filled_reagents = list("spaceacillin" = 9, "arithrazine" = 5, "ryetalyn" = 1) /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain name = "pain hypo" desc = "A refined version of the standard autoinjector, allowing greater capacity. This one contains potent painkillers." - icon_state = "autoinjector" - 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 + filled_reagents = list("tramadol" = 15) /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ name = "organ hypo" desc = "A refined version of the standard autoinjector, allowing greater capacity. Organ damage is resolved by this varient." - icon_state = "autoinjector" - 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 + filled_reagents = list("alkysine" = 1, "imidazoline" = 1, "peridaxon" = 13) /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat name = "combat hypo" 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 \ ability." - icon_state = "autoinjector" - 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 + filled_reagents = list("bicaridine" = 3, "kelotane" = 1.5, "dermaline" = 1.5, "oxycodone" = 3, "hyperzine" = 3, "tricordrazine" = 3) diff --git a/code/game/gamemodes/technomancer/devices/shield_armor.dm b/code/game/gamemodes/technomancer/devices/shield_armor.dm index bacb2c60ed2..0bbb6ef0850 100644 --- a/code/game/gamemodes/technomancer/devices/shield_armor.dm +++ b/code/game/gamemodes/technomancer/devices/shield_armor.dm @@ -26,7 +26,7 @@ /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) /obj/item/clothing/suit/armor/shield/Destroy() diff --git a/code/game/gamemodes/technomancer/devices/tesla_armor.dm b/code/game/gamemodes/technomancer/devices/tesla_armor.dm index 6b981aa8eb0..2e9a60a8e63 100644 --- a/code/game/gamemodes/technomancer/devices/tesla_armor.dm +++ b/code/game/gamemodes/technomancer/devices/tesla_armor.dm @@ -1,8 +1,8 @@ /datum/technomancer/equipment/tesla_armor name = "Tesla Armor" desc = "This piece of armor offers a retaliation-based defense. When the armor is 'ready', it will completely protect you from \ - the next attack you suffer, and strike the attacker with a strong bolt of lightning. This effect requires twenty seconds to \ - recharge. If you are attacked while this is recharging, a weaker lightning bolt is sent out, however you won't be protected from \ + the next attack you suffer, and strike the attacker with a strong bolt of lightning, provided they are close enough. This effect requires \ + fifteen seconds to recharge. If you are attacked while this is recharging, a weaker lightning bolt is sent out, however you won't be protected from \ the person beating you." cost = 150 obj_path = /obj/item/clothing/suit/armor/tesla @@ -10,23 +10,33 @@ /obj/item/clothing/suit/armor/tesla name = "tesla armor" desc = "This rather dangerous looking armor will hopefully shock your enemies, and not you in the process." - icon_state = "reactiveoff" //wip - item_state = "reactiveoff" + icon_state = "reactive" //wip + item_state = "reactive" blood_overlay_type = "armor" slowdown = 1 armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) var/ready = 1 //Determines if the next attack will be blocked, as well if a strong lightning bolt is sent out at the attacker. var/ready_icon_state = "reactive" //also wip - var/cooldown_to_charge = 20 SECONDS + var/normal_icon_state = "reactiveoff" + var/cooldown_to_charge = 15 SECONDS /obj/item/clothing/suit/armor/tesla/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") //First, some retaliation. - if(attacker && attacker != user) - if(get_dist(user, attacker) <= 3) //Anyone farther away than three tiles is too far to shoot lightning at. + if(istype(damage_source, /obj/item/projectile)) + var/obj/item/projectile/P = damage_source + if(P.firer && get_dist(user, P.firer) <= 3) if(ready) - shoot_lightning(attacker, 40) + shoot_lightning(P.firer, 40) else - shoot_lightning(attacker, 15) + shoot_lightning(P.firer, 15) + + else + if(attacker && attacker != user) + if(get_dist(user, attacker) <= 3) //Anyone farther away than three tiles is too far to shoot lightning at. + if(ready) + shoot_lightning(attacker, 40) + else + shoot_lightning(attacker, 15) //Deal with protecting our wearer now. if(ready) @@ -45,10 +55,14 @@ if(ready) icon_state = ready_icon_state else - icon_state = initial(icon_state) + icon_state = normal_icon_state + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + H.update_inv_wear_suit(0) /obj/item/clothing/suit/armor/tesla/proc/shoot_lightning(var/mob/target, var/power) var/obj/item/projectile/beam/lightning/lightning = new(src) lightning.power = power lightning.launch(target) - visible_message("\The [src] strikes \the [target] with lightning!") \ No newline at end of file + visible_message("\The [src] strikes \the [target] with lightning!") + playsound(get_turf(src), 'sound/weapons/gauss_shoot.ogg', 75, 1) \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/equipment.dm b/code/game/gamemodes/technomancer/equipment.dm index 5c440d0dcd8..8d1fb4c6ad1 100644 --- a/code/game/gamemodes/technomancer/equipment.dm +++ b/code/game/gamemodes/technomancer/equipment.dm @@ -191,6 +191,7 @@ icon_state = "scepter" force = 15 slot_flags = SLOT_BELT + attack_verb = list("beaten", "smashed", "struck", "whacked") /obj/item/weapon/scepter/attack_self(mob/living/carbon/human/user) var/obj/item/item_to_test = user.get_other_hand(src) diff --git a/code/game/gamemodes/technomancer/instability.dm b/code/game/gamemodes/technomancer/instability.dm index fa9985b1b6b..21d746742ff 100644 --- a/code/game/gamemodes/technomancer/instability.dm +++ b/code/game/gamemodes/technomancer/instability.dm @@ -44,25 +44,25 @@ // Description: Makes instability decay. instability_effects() handles the bad effects for having instability. It will also hold back // from causing bad effects more than one every ten seconds, to prevent sudden death from angry RNG. /mob/living/proc/handle_instability() - instability = round(Clamp(instability, 0, 200)) + instability = Ceiling(Clamp(instability, 0, 200)) //This should cushon against really bad luck. if(instability && last_instability_event < (world.time - 10 SECONDS) && prob(20)) instability_effects() switch(instability) if(1 to 10) - adjust_instability(-2) + adjust_instability(-1) if(11 to 20) - adjust_instability(-4) + adjust_instability(-2) if(21 to 30) - adjust_instability(-6) + adjust_instability(-3) if(31 to 40) - adjust_instability(-8) + adjust_instability(-4) if(41 to 50) - adjust_instability(-10) + adjust_instability(-5) if(51 to 100) - adjust_instability(-20) + adjust_instability(-10) if(101 to 200) - adjust_instability(-40) + adjust_instability(-20) /mob/living/carbon/human/handle_instability() ..() @@ -102,7 +102,7 @@ rng = rand(0,1) switch(rng) 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.attach(loc) sparks.start() @@ -167,10 +167,10 @@ rng = rand(0,1) switch(rng) 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.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.attach(src) sparks.start() @@ -277,12 +277,17 @@ // People next to the source take a third of the instability. Further distance decreases the amount absorbed. var/outgoing_instability = (instability / 3) * ( 1 / (radius**2) ) - // Energy armor like from the AMI RIG can protect from this. - var/armor = getarmor(null, "energy") - var/armor_factor = abs( (armor - 100) / 100) - outgoing_instability = outgoing_instability * armor_factor - if(outgoing_instability) - to_chat(H, "The purple glow makes you feel strange...") - H.adjust_instability(outgoing_instability) - set_light(distance, distance * 2, l_color = "#C26DDE") + H.receive_radiated_instability(outgoing_instability) + + set_light(distance, distance * 4, l_color = "#C26DDE") + +// This should only be used for EXTERNAL sources of instability, such as from someone or something glowing. +/mob/living/proc/receive_radiated_instability(amount) + // Energy armor like from the AMI RIG can protect from this. + var/armor = getarmor(null, "energy") + var/armor_factor = abs( (armor - 100) / 100) + amount = amount * armor_factor + if(amount && prob(10)) + to_chat(src, "The purple glow makes you feel strange...") + adjust_instability(amount) diff --git a/code/game/gamemodes/technomancer/spell_objs.dm b/code/game/gamemodes/technomancer/spell_objs.dm index fb22001d309..2dede11a942 100644 --- a/code/game/gamemodes/technomancer/spell_objs.dm +++ b/code/game/gamemodes/technomancer/spell_objs.dm @@ -31,7 +31,8 @@ ) throwforce = 0 force = 0 - var/mob/living/carbon/human/owner = null +// var/mob/living/carbon/human/owner = null + var/mob/living/owner = null var/obj/item/weapon/technomancer_core/core = null var/cast_methods = null // Controls how the spell is casted. var/aspect = null // Used for combining spells. @@ -115,16 +116,33 @@ amount = round(amount * core.instability_modifier, 0.1) owner.adjust_instability(amount) +// Proc: get_technomancer_core() +// Parameters: 0 +// Description: Returns the technomancer's core, assuming it is being worn properly. +/mob/living/proc/get_technomancer_core() + return null + +/mob/living/carbon/human/get_technomancer_core() + var/obj/item/weapon/technomancer_core/core = back + if(istype(core)) + return core + return null + // Proc: New() // Parameters: 0 // Description: Sets owner to equal its loc, links to the owner's core, then applies overlays if needed. /obj/item/weapon/spell/New() ..() - if(ishuman(loc)) + if(isliving(loc)) owner = loc if(owner) - if(istype(/obj/item/weapon/technomancer_core, owner.back)) - core = owner.back + core = owner.get_technomancer_core() + if(!core) + to_chat(owner, "You need a Core to do that.") + qdel(src) + return +// if(istype(/obj/item/weapon/technomancer_core, owner.back)) +// core = owner.back update_icon() // Proc: Destroy() @@ -247,7 +265,7 @@ if(!path || !ispath(path)) 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) //No hands needed for innate casts. diff --git a/code/game/gamemodes/technomancer/spells/aura/fire_aura.dm b/code/game/gamemodes/technomancer/spells/aura/fire_aura.dm index 952fd5d43d2..6111784d6f4 100644 --- a/code/game/gamemodes/technomancer/spells/aura/fire_aura.dm +++ b/code/game/gamemodes/technomancer/spells/aura/fire_aura.dm @@ -13,17 +13,18 @@ /obj/item/weapon/spell/aura/fire name = "Fire Storm" desc = "Things are starting to heat up." - icon_state = "generic" + icon_state = "fire_bolt" aspect = ASPECT_FIRE glow_color = "#FF6A00" /obj/item/weapon/spell/aura/fire/process() if(!pay_energy(100)) qdel(src) - var/list/nearby_things = range(calculate_spell_power(4),owner) + var/list/nearby_things = range(round(calculate_spell_power(4)),owner) - var/temp_change = calculate_spell_power(80) - var/temp_cap = calculate_spell_power(600) + var/temp_change = calculate_spell_power(150) + var/datum/species/baseline = all_species["Human"] + var/temp_cap = baseline.heat_level_3 * 2 var/fire_power = calculate_spell_power(2) if(check_for_scepter()) @@ -38,7 +39,8 @@ var/protection = H.get_heat_protection(1000) if(protection < 1) var/heat_factor = abs(protection - 1) - H.bodytemperature = min( (H.bodytemperature + temp_change) * heat_factor, temp_cap) + temp_change *= heat_factor + H.bodytemperature = min(H.bodytemperature + temp_change, temp_cap) turf_check: for(var/turf/simulated/T in nearby_things) diff --git a/code/game/gamemodes/technomancer/spells/aura/frost_aura.dm b/code/game/gamemodes/technomancer/spells/aura/frost_aura.dm index c2106d5aa33..7e788de96e4 100644 --- a/code/game/gamemodes/technomancer/spells/aura/frost_aura.dm +++ b/code/game/gamemodes/technomancer/spells/aura/frost_aura.dm @@ -2,7 +2,7 @@ name = "Chilling Aura" desc = "Lowers the core body temperature of everyone around you (except for your friends), causing them to become very slow if \ they stay within four meters of you." - enhancement_desc = "The chill becomes lethal." + enhancement_desc = "Will make nearby entities even slower." spell_power_desc = "Radius and rate of cooling are scaled." cost = 100 obj_path = /obj/item/weapon/spell/aura/frost @@ -20,14 +20,16 @@ /obj/item/weapon/spell/aura/frost/process() if(!pay_energy(100)) qdel(src) - var/list/nearby_mobs = range(calculate_spell_power(4),owner) + var/list/nearby_mobs = range(round(calculate_spell_power(4)),owner) var/temp_change = calculate_spell_power(40) - var/temp_cap = 260 // Just above the damage threshold, for humans. Unathi are less fortunate. + var/datum/species/baseline = all_species["Human"] + var/temp_cap = baseline.cold_level_2 - 5 if(check_for_scepter()) temp_change *= 2 - temp_cap = 200 + temp_cap = baseline.cold_level_3 - 5 + for(var/mob/living/carbon/human/H in nearby_mobs) if(is_ally(H)) continue @@ -35,6 +37,7 @@ var/protection = H.get_cold_protection(1000) if(protection < 1) var/cold_factor = abs(protection - 1) - H.bodytemperature = max( (H.bodytemperature - temp_change) * cold_factor, temp_cap) + temp_change *= cold_factor + H.bodytemperature = max(H.bodytemperature - temp_change, temp_cap) adjust_instability(1) \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/condensation.dm b/code/game/gamemodes/technomancer/spells/condensation.dm index c02e1c1ac54..c303c2a5fb0 100644 --- a/code/game/gamemodes/technomancer/spells/condensation.dm +++ b/code/game/gamemodes/technomancer/spells/condensation.dm @@ -24,7 +24,7 @@ spawn(1) var/turf/desired_turf = get_step(T,direction) 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.reagents.add_reagent(id = "water", amount = 60, data = null, safety = 0) W.set_color() diff --git a/code/game/gamemodes/technomancer/spells/dispel.dm b/code/game/gamemodes/technomancer/spells/dispel.dm index 87edf6a6212..60266426cb5 100644 --- a/code/game/gamemodes/technomancer/spells/dispel.dm +++ b/code/game/gamemodes/technomancer/spells/dispel.dm @@ -18,8 +18,6 @@ /obj/item/weapon/spell/dispel/on_ranged_cast(atom/hit_atom, mob/living/user) if(isliving(hit_atom) && within_range(hit_atom) && pay_energy(1000)) var/mob/living/target = hit_atom - for(var/obj/item/weapon/inserted_spell/I in target) - I.on_expire(dispelled = 1) - log_and_message_admins("dispelled [I] on [target].") + target.remove_modifiers_of_type(/datum/modifier/technomancer) user.adjust_instability(10) qdel(src) \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/gambit.dm b/code/game/gamemodes/technomancer/spells/gambit.dm index 0541e5473ed..e0116073dc7 100644 --- a/code/game/gamemodes/technomancer/spells/gambit.dm +++ b/code/game/gamemodes/technomancer/spells/gambit.dm @@ -1,6 +1,9 @@ /datum/technomancer/spell/gambit name = "Gambit" desc = "This function causes you to receive a random function, including those which you haven't purchased." +// enhancement_desc = "Makes results less random and more biased towards what the function thinks you need in your current situation." + enhancement_desc = "Instead of a purely random spell, it will give you a \"random\" spell." + spell_power_desc = "Makes certain rare functions possible to acquire via Gambit which cannot be obtained otherwise, if above 100%." ability_icon_state = "tech_gambit" cost = 50 obj_path = /obj/item/weapon/spell/gambit @@ -11,9 +14,10 @@ /obj/item/weapon/spell/gambit, /obj/item/weapon/spell/projectile, /obj/item/weapon/spell/aura, - /obj/item/weapon/spell/insert, +// /obj/item/weapon/spell/insert, /obj/item/weapon/spell/spawner, - /obj/item/weapon/spell/summon) + /obj/item/weapon/spell/summon, + /obj/item/weapon/spell/modifier) /obj/item/weapon/spell/gambit name = "gambit" @@ -21,12 +25,110 @@ icon_state = "gambit" cast_methods = CAST_USE aspect = ASPECT_UNSTABLE + var/list/rare_spells = list( + /obj/item/weapon/spell/modifier/mend_all + ) + /obj/item/weapon/spell/gambit/on_use_cast(mob/living/carbon/human/user) if(pay_energy(200)) adjust_instability(3) - var/obj/item/weapon/spell/random_spell = pick(all_technomancer_gambit_spells) - if(random_spell) - user.drop_from_inventory(src, null) - user.place_spell_in_hand(random_spell) + if(check_for_scepter()) + give_new_spell(biased_random_spell()) + else + give_new_spell(random_spell()) qdel(src) + +/obj/item/weapon/spell/gambit/proc/give_new_spell(var/spell_type) + owner.drop_from_inventory(src, null) + owner.place_spell_in_hand(spell_type) + +// Gives a random spell. +/obj/item/weapon/spell/gambit/proc/random_spell() + var/list/potential_spells = all_technomancer_gambit_spells.Copy() + var/rare_spell_chance = between(0, calculate_spell_power(100) - 100, 100) // Having 120% spellpower means a 20% chance to get to roll for rare spells. + if(prob(rare_spell_chance)) + potential_spells += rare_spells.Copy() + to_chat(owner, "You feel a bit luckier...") + return pick(potential_spells) + +// Gives a "random" spell. +/obj/item/weapon/spell/gambit/proc/biased_random_spell() + var/list/potential_spells = list() + var/rare_spell_chance = between(0, calculate_spell_power(100) - 100, 100) + var/give_rare_spells = FALSE + if(prob(rare_spell_chance)) + give_rare_spells = TRUE + to_chat(owner, "You feel a bit luckier...") + + // First the spell will concern itself with the health of the technomancer. + if(prob(owner.getBruteLoss() + owner.getBruteLoss() * 2)) // Having 20 brute means a 40% chance of being added to the pool. + if(!owner.isSynthetic()) + potential_spells |= /obj/item/weapon/spell/modifier/mend_life + else + potential_spells |= /obj/item/weapon/spell/modifier/mend_synthetic + if(give_rare_spells) + potential_spells |= /obj/item/weapon/spell/modifier/mend_all + + // Second, the spell will try to prepare the technomancer for threats. + var/hostile_mobs = 0 // Counts how many hostile mobs. Higher numbers make it more likely for AoE spells to be chosen. + + for(var/mob/living/L in view(owner)) + // Spiders, carp... bears. + if(istype(L, /mob/living/simple_animal)) + var/mob/living/simple_animal/SM = L + if(!is_ally(SM) && SM.hostile) + hostile_mobs++ + if(SM.summoned || SM.supernatural) // Our creations might be trying to kill us. + potential_spells |= /obj/item/weapon/spell/abjuration + + // Always assume borgs are hostile. + if(istype(L, /mob/living/silicon/robot)) + if(!istype(L, /mob/living/silicon/robot/drone)) // Drones are okay, however. + hostile_mobs++ + potential_spells |= /obj/item/weapon/spell/projectile/ionic_bolt + + // Finally we get to humanoids. + if(istype(L, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = L + if(is_ally(H)) // Don't get scared by our apprentice. + continue + + for(var/obj/item/I in list(H.l_hand, H.r_hand)) + // Guns are scary. + if(istype(I, /obj/item/weapon/gun)) // Toy guns will count as well but oh well. + hostile_mobs++ + continue + // Strong melee weapons are scary as well. + else if(I.force >= 15) + hostile_mobs++ + continue + + if(hostile_mobs) + potential_spells |= /obj/item/weapon/spell/shield + potential_spells |= /obj/item/weapon/spell/reflect + potential_spells |= /obj/item/weapon/spell/targeting_matrix + potential_spells |= /obj/item/weapon/spell/warp_strike + + if(hostile_mobs >= 3) // Lots of baddies, give them AoE. + potential_spells |= /obj/item/weapon/spell/projectile/chain_lightning + potential_spells |= /obj/item/weapon/spell/projectile/chain_lightning/lesser + potential_spells |= /obj/item/weapon/spell/spawner/fire_blast + potential_spells |= /obj/item/weapon/spell/condensation + potential_spells |= /obj/item/weapon/spell/aura/frost + else + potential_spells |= /obj/item/weapon/spell/projectile/beam + potential_spells |= /obj/item/weapon/spell/projectile/overload + potential_spells |= /obj/item/weapon/spell/projectile/force_missile + potential_spells |= /obj/item/weapon/spell/projectile/lightning + + // Third priority is recharging the core. + if(core.energy / core.max_energy <= 0.5) + potential_spells |= /obj/item/weapon/spell/energy_siphon + potential_spells |= /obj/item/weapon/spell/instability_tap + + // Fallback method in case nothing gets added. + if(!potential_spells.len) + potential_spells = all_technomancer_gambit_spells.Copy() + + return pick(potential_spells) \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/illusion.dm b/code/game/gamemodes/technomancer/spells/illusion.dm index 12f04db48c2..50a9bf5da74 100644 --- a/code/game/gamemodes/technomancer/spells/illusion.dm +++ b/code/game/gamemodes/technomancer/spells/illusion.dm @@ -93,6 +93,9 @@ var/walking = 0 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) if(!thing_to_copy) return 0 diff --git a/code/game/gamemodes/technomancer/spells/insert/corona.dm b/code/game/gamemodes/technomancer/spells/insert/corona.dm deleted file mode 100644 index 0ecd700732f..00000000000 --- a/code/game/gamemodes/technomancer/spells/insert/corona.dm +++ /dev/null @@ -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("You start to glow very brightly!") - 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 << "Your glow has ended." - ..() \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/insert/haste.dm b/code/game/gamemodes/technomancer/spells/insert/haste.dm deleted file mode 100644 index 30422cef3f4..00000000000 --- a/code/game/gamemodes/technomancer/spells/insert/haste.dm +++ /dev/null @@ -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 << "You suddenly find it much easier to move." - 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 << "You feel slow again." - ..() \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/insert/mend_burns.dm b/code/game/gamemodes/technomancer/spells/insert/mend_burns.dm deleted file mode 100644 index 2201787d34a..00000000000 --- a/code/game/gamemodes/technomancer/spells/insert/mend_burns.dm +++ /dev/null @@ -1,30 +0,0 @@ -/datum/technomancer/spell/mend_burns - name = "Mend Burns" - desc = "Heals minor burns, such as from exposure to flame, electric shock, or lasers." - spell_power_desc = "Healing amount increased." - cost = 50 - obj_path = /obj/item/weapon/spell/insert/mend_burns - ability_icon_state = "tech_mendburns" - category = SUPPORT_SPELLS - -/obj/item/weapon/spell/insert/mend_burns - name = "mend burns" - desc = "Ointment is a thing of the past." - icon_state = "mend_burns" - cast_methods = CAST_MELEE - aspect = ASPECT_BIOMED - light_color = "#FF5C5C" - inserting = /obj/item/weapon/inserted_spell/mend_burns - -/obj/item/weapon/inserted_spell/mend_burns/on_insert() - spawn(1) - if(ishuman(host)) - var/mob/living/carbon/human/H = host - var/heal_power = host == origin ? 10 : 30 - heal_power = round(heal_power * spell_power_at_creation, 1) - origin.adjust_instability(10) - for(var/i = 0, i<5,i++) - if(H) - H.adjustFireLoss(-heal_power / 5) - sleep(1 SECOND) - on_expire() \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/insert/mend_metal.dm b/code/game/gamemodes/technomancer/spells/insert/mend_metal.dm deleted file mode 100644 index 376ab8df1ce..00000000000 --- a/code/game/gamemodes/technomancer/spells/insert/mend_metal.dm +++ /dev/null @@ -1,33 +0,0 @@ -/datum/technomancer/spell/mend_metal - name = "Mend Metal" - desc = "Restores integrity to external robotic components." - spell_power_desc = "Healing amount increased." - cost = 50 - obj_path = /obj/item/weapon/spell/insert/mend_metal - ability_icon_state = "tech_mendwounds" - category = SUPPORT_SPELLS - -/obj/item/weapon/spell/insert/mend_metal - name = "mend metal" - desc = "A roboticist is now obsolete." - icon_state = "mend_wounds" - cast_methods = CAST_MELEE - aspect = ASPECT_BIOMED - light_color = "#FF5C5C" - inserting = /obj/item/weapon/inserted_spell/mend_metal - -/obj/item/weapon/inserted_spell/mend_metal/on_insert() - spawn(1) - if(ishuman(host)) - var/mob/living/carbon/human/H = host - var/heal_power = host == origin ? 10 : 30 - heal_power = round(heal_power * spell_power_at_creation, 1) - origin.adjust_instability(10) - for(var/i = 0, i<5,i++) - if(H) - for(var/obj/item/organ/external/O in H.organs) - if(O.robotic < ORGAN_ROBOT) // Robot parts only. - continue - O.heal_damage(heal_power / 5, 0, internal = 1, robo_repair = 1) - sleep(1 SECOND) - on_expire() \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/insert/mend_organs.dm b/code/game/gamemodes/technomancer/spells/insert/mend_organs.dm deleted file mode 100644 index 4ac29658edb..00000000000 --- a/code/game/gamemodes/technomancer/spells/insert/mend_organs.dm +++ /dev/null @@ -1,56 +0,0 @@ -/datum/technomancer/spell/mend_organs - name = "Great Mend Wounds" - desc = "Greatly heals the target's wounds, both external and internal. Restores internal organs to functioning states, even if \ - robotic, reforms bones, patches internal bleeding, and restores missing blood." - spell_power_desc = "Healing amount increased." - cost = 100 - obj_path = /obj/item/weapon/spell/insert/mend_organs - ability_icon_state = "tech_mendwounds" - category = SUPPORT_SPELLS - -/obj/item/weapon/spell/insert/mend_organs - name = "great mend wounds" - desc = "A walking medbay is now you!" - icon_state = "mend_wounds" - cast_methods = CAST_MELEE - aspect = ASPECT_BIOMED - light_color = "#FF5C5C" - inserting = /obj/item/weapon/inserted_spell/mend_organs - -/obj/item/weapon/inserted_spell/mend_organs/on_insert() - spawn(1) - if(ishuman(host)) - var/mob/living/carbon/human/H = host - var/heal_power = host == origin ? 2 : 5 - heal_power = round(heal_power * spell_power_at_creation, 1) - origin.adjust_instability(15) - - for(var/i = 0, i<5,i++) - if(H) - for(var/obj/item/organ/O in H.internal_organs) - if(O.damage > 0) // Fix internal damage - O.damage = max(O.damage - (heal_power / 5), 0) - if(O.damage <= 5 && O.organ_tag == O_EYES) // Fix eyes - H.sdisabilities &= ~BLIND - - for(var/obj/item/organ/external/O in H.organs) // Fix limbs - if(!O.robotic < ORGAN_ROBOT) // No robot parts for this. - continue - O.heal_damage(0, heal_power / 5, internal = 1, robo_repair = 0) - - for(var/obj/item/organ/E in H.bad_external_organs) // Fix bones - var/obj/item/organ/external/affected = E - if((affected.damage < affected.min_broken_damage * config.organ_health_multiplier) && (affected.status & ORGAN_BROKEN)) - affected.status &= ~ORGAN_BROKEN - - for(var/datum/wound/W in affected.wounds) // Fix IB - if(istype(W, /datum/wound/internal_bleeding)) - affected.wounds -= W - affected.update_damages() - - H.restore_blood() // Fix bloodloss - - H.adjustBruteLoss(-heal_power) - - sleep(1 SECOND) - on_expire() \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/insert/mend_wires.dm b/code/game/gamemodes/technomancer/spells/insert/mend_wires.dm deleted file mode 100644 index aad59dc7c41..00000000000 --- a/code/game/gamemodes/technomancer/spells/insert/mend_wires.dm +++ /dev/null @@ -1,33 +0,0 @@ -/datum/technomancer/spell/mend_wires - name = "Mend Wires" - desc = "Binds the internal wiring of robotic limbs and components over time." - spell_power_desc = "Healing amount increased." - cost = 50 - obj_path = /obj/item/weapon/spell/insert/mend_wires - ability_icon_state = "tech_mendwounds" - category = SUPPORT_SPELLS - -/obj/item/weapon/spell/insert/mend_wires - name = "mend wires" - desc = "A roboticist is now obsolete." - icon_state = "mend_wounds" - cast_methods = CAST_MELEE - aspect = ASPECT_BIOMED - light_color = "#FF5C5C" - inserting = /obj/item/weapon/inserted_spell/mend_wires - -/obj/item/weapon/inserted_spell/mend_wires/on_insert() - spawn(1) - if(ishuman(host)) - var/mob/living/carbon/human/H = host - var/heal_power = host == origin ? 10 : 30 - heal_power = round(heal_power * spell_power_at_creation, 1) - origin.adjust_instability(10) - for(var/i = 0, i<5,i++) - if(H) - for(var/obj/item/organ/external/O in H.organs) - if(O.robotic < ORGAN_ROBOT) // Robot parts only. - continue - O.heal_damage(0, heal_power / 5, internal = 1, robo_repair = 1) - sleep(1 SECOND) - on_expire() \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/insert/mend_wounds.dm b/code/game/gamemodes/technomancer/spells/insert/mend_wounds.dm deleted file mode 100644 index 38f5b5dc55b..00000000000 --- a/code/game/gamemodes/technomancer/spells/insert/mend_wounds.dm +++ /dev/null @@ -1,31 +0,0 @@ -/datum/technomancer/spell/mend_wounds - name = "Mend Wounds" - desc = "Heals minor wounds, such as cuts, bruises, and other non-lifethreatening injuries. \ - Instability is split between the target and technomancer, if seperate." - spell_power_desc = "Healing amount increased." - cost = 50 - obj_path = /obj/item/weapon/spell/insert/mend_wounds - ability_icon_state = "tech_mendwounds" - category = SUPPORT_SPELLS - -/obj/item/weapon/spell/insert/mend_wounds - name = "mend wounds" - desc = "Watch your wounds close up before your eyes." - icon_state = "mend_wounds" - cast_methods = CAST_MELEE - aspect = ASPECT_BIOMED - light_color = "#FF5C5C" - inserting = /obj/item/weapon/inserted_spell/mend_wounds - -/obj/item/weapon/inserted_spell/mend_wounds/on_insert() - spawn(1) - if(ishuman(host)) - var/mob/living/carbon/human/H = host - var/heal_power = host == origin ? 10 : 30 - heal_power = round(heal_power * spell_power_at_creation, 1) - origin.adjust_instability(10) - for(var/i = 0, i<5,i++) - if(H) - H.adjustBruteLoss(-heal_power / 5) - sleep(1 SECOND) - on_expire() diff --git a/code/game/gamemodes/technomancer/spells/insert/purify.dm b/code/game/gamemodes/technomancer/spells/insert/purify.dm deleted file mode 100644 index 6ba36d44c66..00000000000 --- a/code/game/gamemodes/technomancer/spells/insert/purify.dm +++ /dev/null @@ -1,49 +0,0 @@ -/datum/technomancer/spell/purify - name = "Purify" - desc = "Clenses the body of harmful impurities, such as toxins, radiation, viruses, genetic damage, and such." - spell_power_desc = "Healing amount increased." - cost = 25 - obj_path = /obj/item/weapon/spell/insert/purify - ability_icon_state = "tech_purify" - category = SUPPORT_SPELLS - -/obj/item/weapon/spell/insert/purify - name = "purify" - desc = "Illness and toxins will be no more." - icon_state = "purify" - cast_methods = CAST_MELEE - aspect = ASPECT_BIOMED - light_color = "#03A728" - inserting = /obj/item/weapon/inserted_spell/purify - -/obj/item/weapon/inserted_spell/purify/on_insert() - spawn(1) - if(ishuman(host)) - var/mob/living/carbon/human/H = host - H.sdisabilities = 0 - H.disabilities = 0 -// for(var/datum/disease/D in H.viruses) -// D.cure() - var/heal_power = host == origin ? 10 : 30 - heal_power = round(heal_power * spell_power_at_creation, 1) - origin.adjust_instability(10) - for(var/i = 0, i<5,i++) - if(H) - H.adjustToxLoss(-heal_power / 5) - H.adjustCloneLoss(-heal_power / 5) - H.radiation = max(host.radiation - ( (heal_power * 2) / 5), 0) - - for(var/obj/item/organ/external/E in H.organs) - var/obj/item/organ/external/G = E - if(G.germ_level) - var/germ_heal = heal_power * 10 - G.germ_level = min(0, G.germ_level - germ_heal) - - for(var/obj/item/organ/internal/I in H.internal_organs) - var/obj/item/organ/internal/G = I - if(G.germ_level) - var/germ_heal = heal_power * 10 - G.germ_level = min(0, G.germ_level - germ_heal) - - sleep(1 SECOND) - on_expire() diff --git a/code/game/gamemodes/technomancer/spells/insert/repel_missiles.dm b/code/game/gamemodes/technomancer/spells/insert/repel_missiles.dm deleted file mode 100644 index 38e4ef47205..00000000000 --- a/code/game/gamemodes/technomancer/spells/insert/repel_missiles.dm +++ /dev/null @@ -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 << "You have a repulsion field around you, which will attempt to deflect projectiles." - 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 << "Your repulsion field has expired." - ..() \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/instability_tap.dm b/code/game/gamemodes/technomancer/spells/instability_tap.dm index 9092039165b..13a2b5e318b 100644 --- a/code/game/gamemodes/technomancer/spells/instability_tap.dm +++ b/code/game/gamemodes/technomancer/spells/instability_tap.dm @@ -1,8 +1,8 @@ /datum/technomancer/spell/instability_tap name = "Instability Tap" - desc = "Creates a large sum of energy, at the cost of a very large amount of instability afflicting you." + desc = "Creates a large sum of energy (5,000 at normal spell power), at the cost of a very large amount of instability afflicting you." enhancement_desc = "50% more energy gained, 20% less instability gained." - spell_power_desc = "Amount of energy gained scaled up with spell power." + spell_power_desc = "Amount of energy gained scaled with spell power." cost = 100 obj_path = /obj/item/weapon/spell/instability_tap ability_icon_state = "tech_instabilitytap" @@ -26,4 +26,5 @@ else core.give_energy(amount) adjust_instability(50) + playsound(get_turf(src), 'sound/effects/supermatter.ogg', 75, 1) qdel(src) \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/mend_organs.dm b/code/game/gamemodes/technomancer/spells/mend_organs.dm new file mode 100644 index 00000000000..16c212f084d --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/mend_organs.dm @@ -0,0 +1,56 @@ +/datum/technomancer/spell/mend_organs + name = "Mend Internals" + desc = "Greatly heals the target's wounds, both external and internal. Restores internal organs to functioning states, even if \ + robotic, reforms bones, patches internal bleeding, and restores missing blood." + spell_power_desc = "Healing amount increased." + cost = 100 + obj_path = /obj/item/weapon/spell/mend_organs + ability_icon_state = "tech_mendwounds" + category = SUPPORT_SPELLS + +/obj/item/weapon/spell/mend_organs + name = "great mend wounds" + desc = "A walking medbay is now you!" + icon_state = "mend_wounds" + cast_methods = CAST_MELEE + aspect = ASPECT_BIOMED + light_color = "#FF5C5C" + +/obj/item/weapon/spell/mend_organs/on_melee_cast(atom/hit_atom, mob/living/user, def_zone) + if(isliving(hit_atom)) + var/mob/living/L = hit_atom + var/heal_power = calculate_spell_power(40) + L.adjustBruteLoss(-heal_power) + L.adjustFireLoss(-heal_power) + user.adjust_instability(5) + L.adjust_instability(5) + + if(ishuman(hit_atom)) + var/mob/living/carbon/human/H = hit_atom + + user.adjust_instability(5) + L.adjust_instability(5) + + for(var/obj/item/organ/O in H.internal_organs) + if(O.damage > 0) // Fix internal damage + O.damage = max(O.damage - (heal_power / 2), 0) + if(O.damage <= 5 && O.organ_tag == O_EYES) // Fix eyes + H.sdisabilities &= ~BLIND + + for(var/obj/item/organ/external/O in H.organs) // Fix limbs + if(!O.robotic < ORGAN_ROBOT) // No robot parts for this. + continue + O.heal_damage(0, heal_power / 4, internal = 1, robo_repair = 0) + + for(var/obj/item/organ/E in H.bad_external_organs) // Fix bones + var/obj/item/organ/external/affected = E + if((affected.damage < affected.min_broken_damage * config.organ_health_multiplier) && (affected.status & ORGAN_BROKEN)) + affected.status &= ~ORGAN_BROKEN + + for(var/datum/wound/W in affected.wounds) // Fix IB + if(istype(W, /datum/wound/internal_bleeding)) + affected.wounds -= W + affected.update_damages() + + H.restore_blood() // Fix bloodloss + qdel(src) diff --git a/code/game/gamemodes/technomancer/spells/modifier/corona.dm b/code/game/gamemodes/technomancer/spells/modifier/corona.dm new file mode 100644 index 00000000000..74a06855d9f --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/modifier/corona.dm @@ -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 = "You start to glow very brightly!" + on_expired_text = "Your glow has ended." + evasion = -2 + stacks = MODIFIER_STACK_EXTEND + +/datum/modifier/technomancer/corona/tick() + holder.break_cloak() \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/modifier/haste.dm b/code/game/gamemodes/technomancer/spells/modifier/haste.dm new file mode 100644 index 00000000000..7f7c1045b36 --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/modifier/haste.dm @@ -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 = "You suddenly find it much easier to move." + on_expired_text = "You feel slow again." + haste = TRUE + stacks = MODIFIER_STACK_EXTEND \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/modifier/mend_all.dm b/code/game/gamemodes/technomancer/spells/modifier/mend_all.dm new file mode 100644 index 00000000000..1da3554573e --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/modifier/mend_all.dm @@ -0,0 +1,35 @@ +// Gambit only spell. Heals everything unconditionally. + +/obj/item/weapon/spell/modifier/mend_all + name = "mend all" + desc = "One function to heal them all." + icon_state = "mend_all" + cast_methods = CAST_MELEE + aspect = ASPECT_BIOMED + light_color = "#FF5C5C" + modifier_type = /datum/modifier/technomancer/mend_life + modifier_duration = 1 MINUTE + +/datum/modifier/technomancer/mend_all + name = "mend all" + desc = "You feel serene and well rested." + mob_overlay_state = "green_sparkles" + + on_created_text = "Sparkles begin to appear around you, and all your ills seem to fade away." + on_expired_text = "The sparkles have faded, although you feel much healthier than before." + stacks = MODIFIER_STACK_EXTEND + +/datum/modifier/technomancer/mend_all/tick() + if(!holder.getBruteLoss() && !holder.getFireLoss() && !holder.getToxLoss() && !holder.getOxyLoss() && !holder.getCloneLoss()) // No point existing if the spell can't heal. + expire() + return + holder.adjustBruteLoss(-4 * spell_power) // Should heal roughly 120 damage over 1 minute, as tick() is run every 2 seconds. + holder.adjustFireLoss(-4 * spell_power) + holder.adjustToxLoss(-4 * spell_power) + holder.adjustOxyLoss(-4 * spell_power) + holder.adjustCloneLoss(-2 * spell_power) // 60 cloneloss + holder.adjust_instability(1) + if(origin) + var/mob/living/L = origin.resolve() + if(istype(L)) + L.adjust_instability(1) \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/modifier/mend_life.dm b/code/game/gamemodes/technomancer/spells/modifier/mend_life.dm new file mode 100644 index 00000000000..a766767b181 --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/modifier/mend_life.dm @@ -0,0 +1,44 @@ +/datum/technomancer/spell/mend_life + name = "Mend Life" + desc = "Heals minor wounds, such as cuts, bruises, burns, and other non-lifethreatening injuries. \ + Instability is split between the target and technomancer, if seperate. The function will end prematurely \ + if the target is completely healthy, preventing further instability." + spell_power_desc = "Healing amount increased." + cost = 50 + obj_path = /obj/item/weapon/spell/modifier/mend_life + ability_icon_state = "tech_mendwounds" + category = SUPPORT_SPELLS + +/obj/item/weapon/spell/modifier/mend_life + name = "mend life" + desc = "Watch your wounds close up before your eyes." + icon_state = "mend_life" + cast_methods = CAST_MELEE + aspect = ASPECT_BIOMED + light_color = "#FF5C5C" + modifier_type = /datum/modifier/technomancer/mend_life + modifier_duration = 10 SECONDS + +/datum/modifier/technomancer/mend_life + name = "mend life" + desc = "You feel rather refreshed." + mob_overlay_state = "green_sparkles" + + on_created_text = "Sparkles begin to appear around you, and you feel really.. refreshed." + on_expired_text = "The sparkles have faded, although you feel healthier than before." + stacks = MODIFIER_STACK_EXTEND + +/datum/modifier/technomancer/mend_life/tick() + if(holder.isSynthetic()) // Don't heal synths! + expire() + return + if(!holder.getBruteLoss() && !holder.getFireLoss()) // No point existing if the spell can't heal. + expire() + return + holder.adjustBruteLoss(-4 * spell_power) // Should heal roughly 20 burn/brute over 10 seconds, as tick() is run every 2 seconds. + holder.adjustFireLoss(-4 * spell_power) // Ditto. + holder.adjust_instability(1) + if(origin) + var/mob/living/L = origin.resolve() + if(istype(L)) + L.adjust_instability(1) \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/modifier/mend_synthetic.dm b/code/game/gamemodes/technomancer/spells/modifier/mend_synthetic.dm new file mode 100644 index 00000000000..d91530b0c93 --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/modifier/mend_synthetic.dm @@ -0,0 +1,44 @@ +/datum/technomancer/spell/mend_synthetic + name = "Mend Synthetic" + desc = "Repairs minor damages to robotic entities. \ + Instability is split between the target and technomancer, if seperate. The function will end prematurely \ + if the target is completely healthy, preventing further instability." + spell_power_desc = "Healing amount increased." + cost = 50 + obj_path = /obj/item/weapon/spell/modifier/mend_synthetic + ability_icon_state = "tech_mendwounds" + category = SUPPORT_SPELLS + +/obj/item/weapon/spell/modifier/mend_synthetic + name = "mend synthetic" + desc = "You are the Robotics lab" + icon_state = "mend_synthetic" + cast_methods = CAST_MELEE + aspect = ASPECT_BIOMED // sorta?? + light_color = "#FF5C5C" + modifier_type = /datum/modifier/technomancer/mend_synthetic + modifier_duration = 10 SECONDS + +/datum/modifier/technomancer/mend_synthetic + name = "mend synthetic" + desc = "Something seems to be repairing you." + mob_overlay_state = "cyan_sparkles" + + on_created_text = "Sparkles begin to appear around you, and your systems report integrity rising." + on_expired_text = "The sparkles have faded, although your systems seem to be better than before." + stacks = MODIFIER_STACK_EXTEND + +/datum/modifier/technomancer/mend_synthetic/tick() + if(!holder.isSynthetic()) // Don't heal biologicals! + expire() + return + if(!holder.getBruteLoss() && !holder.getFireLoss()) // No point existing if the spell can't heal. + expire() + return + holder.adjustBruteLoss(-4 * spell_power) // Should heal roughly 20 burn/brute over 10 seconds, as tick() is run every 2 seconds. + holder.adjustFireLoss(-4 * spell_power) // Ditto. + holder.adjust_instability(1) + if(origin) + var/mob/living/L = origin.resolve() + if(istype(L)) + L.adjust_instability(1) \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/modifier/modifier.dm b/code/game/gamemodes/technomancer/spells/modifier/modifier.dm new file mode 100644 index 00000000000..a8b93069456 --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/modifier/modifier.dm @@ -0,0 +1,38 @@ +/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) + var/datum/modifier/M = L.add_modifier(modifier_type, duration, owner) + if(istype(M, /datum/modifier/technomancer)) + var/datum/modifier/technomancer/MT = M + MT.spell_power = calculate_spell_power(1) + log_and_message_admins("has casted [src] on [L].") + qdel(src) + +// Technomancer specific subtype which keeps track of spell power and gets targeted specificially by Dispel. +/datum/modifier/technomancer + var/spell_power = null // Set by on_add_modifier. \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/modifier/purify.dm b/code/game/gamemodes/technomancer/spells/modifier/purify.dm new file mode 100644 index 00000000000..ae90a04cb1b --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/modifier/purify.dm @@ -0,0 +1,40 @@ +/datum/technomancer/spell/purify + name = "Purify" + desc = "Clenses the body of harmful impurities, such as toxins, radiation, viruses, genetic damage, and such. \ + Instability is split between the target and technomancer, if seperate. The function will end prematurely \ + if the target is completely healthy, preventing further instability." + spell_power_desc = "Healing amount increased." + cost = 25 + obj_path = /obj/item/weapon/spell/modifier/purify + ability_icon_state = "tech_purify" + category = SUPPORT_SPELLS + +/obj/item/weapon/spell/modifier/purify + name = "mend life" + desc = "Watch your wounds close up before your eyes." + icon_state = "mend_life" + cast_methods = CAST_MELEE + aspect = ASPECT_BIOMED + light_color = "#FF5C5C" + modifier_type = /datum/modifier/technomancer/purify + modifier_duration = 10 SECONDS + +/datum/modifier/technomancer/purify + name = "purify" + desc = "You feel rather clean and pure." + mob_overlay_state = "green_sparkles" + + on_created_text = "Sparkles begin to appear around you, and you feel really.. pure." + on_expired_text = "The sparkles have faded, although you feel healthier than before." + stacks = MODIFIER_STACK_EXTEND + +/datum/modifier/technomancer/purify/tick() + if(!holder.getToxLoss()) // No point existing if the spell can't heal. + expire() + return + holder.adjustToxLoss(-4 * spell_power) // Should heal roughly 120 damage over 1 minute, as tick() is run every 2 seconds. + holder.adjust_instability(1) + if(origin) + var/mob/living/L = origin.resolve() + if(istype(L)) + L.adjust_instability(1) \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/modifier/repel_missiles.dm b/code/game/gamemodes/technomancer/spells/modifier/repel_missiles.dm new file mode 100644 index 00000000000..6ead04f30cc --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/modifier/repel_missiles.dm @@ -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 45% 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 = "You have a repulsion field around you, which will attempt to deflect projectiles." + on_expired_text = "Your repulsion field has expired." + evasion = 3 + stacks = MODIFIER_STACK_EXTEND \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/oxygenate.dm b/code/game/gamemodes/technomancer/spells/oxygenate.dm index b121e6f4d4b..fcc2cbcecf8 100644 --- a/code/game/gamemodes/technomancer/spells/oxygenate.dm +++ b/code/game/gamemodes/technomancer/spells/oxygenate.dm @@ -2,7 +2,7 @@ name = "Oxygenate" desc = "This function creates oxygen at a location of your chosing. If used on a humanoid entity, it heals oxygen deprivation. \ If casted on the envirnment, air (oxygen and nitrogen) is moved from a distant location to your target." - cost = 50 + cost = 25 obj_path = /obj/item/weapon/spell/oxygenate ability_icon_state = "oxygenate" category = SUPPORT_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/passwall.dm b/code/game/gamemodes/technomancer/spells/passwall.dm index aa16a8a4fc6..e786134b4c0 100644 --- a/code/game/gamemodes/technomancer/spells/passwall.dm +++ b/code/game/gamemodes/technomancer/spells/passwall.dm @@ -39,7 +39,7 @@ visible_message("[user] rests a hand on \the [hit_atom].") 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) while(i) diff --git a/code/game/gamemodes/technomancer/spells/projectile/chain_lightning.dm b/code/game/gamemodes/technomancer/spells/projectile/chain_lightning.dm index acb00a2c7f8..5614d04a888 100644 --- a/code/game/gamemodes/technomancer/spells/projectile/chain_lightning.dm +++ b/code/game/gamemodes/technomancer/spells/projectile/chain_lightning.dm @@ -32,7 +32,7 @@ var/bounces = 3 //How many times it 'chains'. Note that the first hit is not counted as it counts /bounces/. var/list/hit_mobs = list() //Mobs which were already hit. - var/power = 20 //How hard it will hit for with electrocute_act(), decreases with each bounce. + var/power = 35 //How hard it will hit for with electrocute_act(), decreases with each bounce. /obj/item/projectile/beam/chain_lightning/attack_mob(var/mob/living/target_mob, var/distance, var/miss_modifier=0) //First we shock the guy we just hit. diff --git a/code/game/gamemodes/technomancer/spells/projectile/ionic_bolt.dm b/code/game/gamemodes/technomancer/spells/projectile/ionic_bolt.dm index 68070d15c1e..d6665b2ee0d 100644 --- a/code/game/gamemodes/technomancer/spells/projectile/ionic_bolt.dm +++ b/code/game/gamemodes/technomancer/spells/projectile/ionic_bolt.dm @@ -2,7 +2,7 @@ name = "Ionic Bolt" desc = "Shoots a bolt of ion energy at the target. If it hits something, it will generally drain energy, corrupt electronics, \ or otherwise ruin complex machinery." - cost = 100 + cost = 50 obj_path = /obj/item/weapon/spell/projectile/ionic_bolt category = OFFENSIVE_SPELLS diff --git a/code/game/gamemodes/technomancer/spells/projectile/lesser_chain_lightning.dm b/code/game/gamemodes/technomancer/spells/projectile/lesser_chain_lightning.dm new file mode 100644 index 00000000000..85881fefb07 --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/projectile/lesser_chain_lightning.dm @@ -0,0 +1,23 @@ +/datum/technomancer/spell/lesser_chain_lightning + name = "Lesser Chain Lightning" + desc = "This is very similar to the function Chain Lightning, however it is considerably less powerful. As a result, it's a lot \ + more economical in terms of energy cost, as well as instability generation. Lightning functions cannot miss due to distance." + cost = 100 + obj_path = /obj/item/weapon/spell/projectile/chain_lightning/lesser + ability_icon_state = "tech_chain_lightning" + category = OFFENSIVE_SPELLS + +/obj/item/weapon/spell/projectile/chain_lightning/lesser + name = "lesser chain lightning" + icon_state = "chain_lightning" + desc = "Now you can throw around lightning like it's nobody's business." + cast_methods = CAST_RANGED + aspect = ASPECT_SHOCK + spell_projectile = /obj/item/projectile/beam/chain_lightning + energy_cost_per_shot = 1000 + instability_per_shot = 5 + cooldown = 10 + +/obj/item/projectile/beam/chain_lightning/lesser + bounces = 2 + power = 20 \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/reflect.dm b/code/game/gamemodes/technomancer/spells/reflect.dm index d841db2accc..60abcee63fa 100644 --- a/code/game/gamemodes/technomancer/spells/reflect.dm +++ b/code/game/gamemodes/technomancer/spells/reflect.dm @@ -19,7 +19,7 @@ /obj/item/weapon/spell/reflect/New() ..() 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) owner << "Your shield will expire in 3 seconds!" spawn(5 SECONDS) diff --git a/code/game/gamemodes/technomancer/spells/shield.dm b/code/game/gamemodes/technomancer/spells/shield.dm index a9514aaa29f..4ea507e9596 100644 --- a/code/game/gamemodes/technomancer/spells/shield.dm +++ b/code/game/gamemodes/technomancer/spells/shield.dm @@ -21,7 +21,7 @@ /obj/item/weapon/spell/shield/New() ..() 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) /obj/item/weapon/spell/shield/Destroy() @@ -37,8 +37,10 @@ if(issmall(user)) // Smaller shields are more efficent. damage_to_energy_cost *= 0.75 - if(istype(owner.get_other_hand(src), src.type)) // Two shields in both hands. - damage_to_energy_cost *= 0.75 + if(ishuman(owner)) + var/mob/living/carbon/human/H = owner + if(istype(H.get_other_hand(src), src.type)) // Two shields in both hands. + damage_to_energy_cost *= 0.75 else if(check_for_scepter()) damage_to_energy_cost *= 0.50 diff --git a/code/game/gamemodes/technomancer/spells/spawner/darkness.dm b/code/game/gamemodes/technomancer/spells/spawner/darkness.dm index eafb167dd42..be978e7ee44 100644 --- a/code/game/gamemodes/technomancer/spells/spawner/darkness.dm +++ b/code/game/gamemodes/technomancer/spells/spawner/darkness.dm @@ -20,10 +20,10 @@ /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 name = "darkness" time_to_die = 2 MINUTES new_light_range = 6 - new_light_power = -5 \ No newline at end of file + new_light_power = -20 \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/spawner/destablize.dm b/code/game/gamemodes/technomancer/spells/spawner/destablize.dm new file mode 100644 index 00000000000..38172b0d146 --- /dev/null +++ b/code/game/gamemodes/technomancer/spells/spawner/destablize.dm @@ -0,0 +1,53 @@ +/datum/technomancer/spell/destablize + name = "Destablize" + desc = "Creates an unstable disturbance at the targeted tile, which will afflict anyone nearby with instability who remains nearby. This can affect you \ + and your allies as well. The disturbance lasts for twenty seconds." + cost = 100 + obj_path = /obj/item/weapon/spell/spawner/destablize + category = OFFENSIVE_SPELLS + +/obj/item/weapon/spell/spawner/destablize + name = "destablize" + desc = "Now your enemies can feel what you go through when you have too much fun." + icon_state = "destablize" + cast_methods = CAST_RANGED + aspect = ASPECT_UNSTABLE + spawner_type = /obj/effect/temporary_effect/destablize + +/obj/item/weapon/spell/spawner/destablize/New() + ..() + set_light(3, 2, l_color = "#C26DDE") + +/obj/item/weapon/spell/spawner/destablize/on_ranged_cast(atom/hit_atom, mob/user) + if(within_range(hit_atom) && pay_energy(2000)) + adjust_instability(15) + ..() + +/obj/effect/temporary_effect/destablize + name = "destablizing disturbance" + desc = "This can't be good..." + icon = 'icons/effects/effects.dmi' + icon_state = "blueshatter" + time_to_die = null + invisibility = 0 + new_light_range = 6 + new_light_power = 20 + new_light_color = "#C26DDE" + var/pulses_remaining = 40 // Lasts 20 seconds. + var/instability_power = 5 + var/instability_range = 6 + +/obj/effect/temporary_effect/destablize/New() + ..() + radiate_loop() + +/obj/effect/temporary_effect/destablize/proc/radiate_loop() + while(pulses_remaining) + sleep(5) + for(var/mob/living/L in range(src, instability_range) ) + var/radius = max(get_dist(L, src), 1) + // Being farther away lessens the amount of instabity received. + var/outgoing_instability = instability_power * ( 1 / (radius**2) ) + L.receive_radiated_instability(outgoing_instability) + pulses_remaining-- + qdel(src) \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/warp_strike.dm b/code/game/gamemodes/technomancer/spells/warp_strike.dm index 94074ffcf01..3f8939e0ba5 100644 --- a/code/game/gamemodes/technomancer/spells/warp_strike.dm +++ b/code/game/gamemodes/technomancer/spells/warp_strike.dm @@ -16,7 +16,7 @@ /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.attach(loc) diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index 1e4398546c5..5d105d6e874 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -27,11 +27,13 @@ H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/bartender(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/device/pda/bar(H), slot_belt) if(has_alt_title(H, alt_title,"Bartender")) + var/obj/item/weapon/permit/gun/bar/permit = new(H) if(H.backbag == 1) - H.equip_to_slot_or_del(new /obj/item/weapon/permit/gun/bar(H), slot_l_hand) + H.equip_to_slot_or_del(permit, slot_l_hand) else - H.equip_to_slot_or_del(new /obj/item/weapon/permit/gun/bar(H.back), slot_in_backpack) - return 1 + H.equip_to_slot_or_del(permit, slot_in_backpack) + permit.set_name(H.real_name) + return 1 @@ -264,6 +266,7 @@ economic_modifier = 7 access = list(access_lawyer, access_sec_doors, access_maint_tunnels, 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) diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm index e8b24b04460..e0efde55ad9 100644 --- a/code/game/jobs/job/engineering.dm +++ b/code/game/jobs/job/engineering.dm @@ -66,6 +66,7 @@ minimal_access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction) alt_titles = list("Maintenance Technician","Engine Technician","Electrician") + minimal_player_age = 3 /datum/job/engineer/equip(var/mob/living/carbon/human/H, var/alt_title) if(!H) return 0 diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 9ca5c327fa9..8bfb5760a22 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -375,6 +375,7 @@ var/global/datum/controller/occupations/job_master job.equip_backpack(H) job.equip_survival(H) job.apply_fingerprints(H) + H.equip_post_job() //If some custom items could not be equipped before, try again now. for(var/thing in custom_equip_leftovers) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index f69f5f6b2ae..f54d069b9d4 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -68,10 +68,12 @@ anchored = 1 circuit = /obj/item/weapon/circuitboard/sleeper 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/filtering = 0 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 idle_power_usage = 15 @@ -98,18 +100,23 @@ /obj/machinery/sleeper/process() if(stat & (NOPOWER|BROKEN)) 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() icon_state = "sleeper_[occupant ? "1" : "0"]" @@ -154,6 +161,13 @@ data["beaker"] = -1 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) if(!ui) ui = new(user, src, ui_key, "sleeper.tmpl", "Sleeper UI", 600, 600, state = state) @@ -182,12 +196,20 @@ if(occupant && occupant.stat != DEAD) 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"])) + 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 /obj/machinery/sleeper/attackby(var/obj/item/I, var/mob/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 else if(default_deconstruction_crowbar(user, I)) return @@ -201,6 +223,28 @@ user << "\The [src] has a beaker already." 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 << "You struggle through the haze to hit the eject button. This will take a couple of minutes..." + 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) if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user)|| !ishuman(target)) return @@ -261,6 +305,7 @@ if(occupant.client) occupant.client.eye = occupant.client.mob occupant.client.perspective = MOB_PERSPECTIVE + occupant.Stasis(0) occupant.loc = src.loc occupant = null for(var/atom/movable/A in src) // In case an object was dropped inside or something diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index bba12887a9b..b1cf9bac081 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -301,6 +301,15 @@ 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] for(var/obj/item/organ/external/E in H.organs) var/organData[0] @@ -394,7 +403,7 @@ P.info += "Time of scan: [worldtime2stationtime(world.time)]

" P.info += "[printing_text]" P.info += "

Notes:
" - P.name = "Body Scan - [href_list["name"]]" + P.name = "Body Scan - [href_list["name"]] ([worldtime2stationtime(world.time)])" printing = null printing_text = null @@ -457,9 +466,13 @@ dat += "[extra_font]\tBlood Level %: [blood_percent] ([blood_volume] units)
" 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]
" + if(occupant.ingested) + for(var/datum/reagent/R in occupant.ingested.reagent_list) + dat += "Stomach: [R.name], Amount: [R.volume]
" + dat += "
" dat += "" dat += "" diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index d4f5dac431b..1344543b65b 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -719,9 +719,9 @@ if(href_list["atmos_unlock"]) switch(href_list["atmos_unlock"]) if("0") - alarm_area.air_doors_close() + alarm_area.firedoors_close() if("1") - alarm_area.air_doors_open() + alarm_area.firedoors_open() return 1 if(href_list["atmos_alarm"]) diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index 31c8fe78197..1aadf981c4f 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -232,6 +232,8 @@ mob/living/proc/near_camera() return TRACKING_TERMINATE if(digitalcamo) return TRACKING_TERMINATE + if(alpha < 127) // For lings and possible future alpha-based cloaks. + return TRACKING_TERMINATE if(istype(loc,/obj/effect/dummy)) return TRACKING_TERMINATE diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 6eae870cfd4..b51fa788ab9 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -85,6 +85,7 @@ if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1))) dat += "
Organ
Name: [active1.fields["name"]] \ ID: [active1.fields["id"]]
\n \ + Entity Classification: [active1.fields["brain_type"]]
\n \ Sex: [active1.fields["sex"]]
\n" if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2))) dat += "Gender identity: [active2.fields["id_gender"]]
" diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 389828843f1..465884b2caa 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -127,6 +127,7 @@ dat += text("
\ Name: [active1.fields["name"]]
\ ID: [active1.fields["id"]]
\n \ + Entity Classification: [active1.fields["brain_type"]]
\n \ Sex: [active1.fields["sex"]]
\n \ Age: [active1.fields["age"]]
\n \ Rank: [active1.fields["rank"]]
\n \ diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm index 1a67778fdf6..bd9c66dbaed 100644 --- a/code/game/machinery/computer/skills.dm +++ b/code/game/machinery/computer/skills.dm @@ -93,6 +93,7 @@ dat += text("
\ Name: [active1.fields["name"]]
\ ID: [active1.fields["id"]]
\n \ + Entity Classification: [active1.fields["brain_type"]]
\n \ Sex: [active1.fields["sex"]]
\n \ Age: [active1.fields["age"]]
\n \ Rank: [active1.fields["rank"]]
\n \ diff --git a/code/game/machinery/computer3/computers/medical.dm b/code/game/machinery/computer3/computers/medical.dm index 57a662db46f..bb4228397dd 100644 --- a/code/game/machinery/computer3/computers/medical.dm +++ b/code/game/machinery/computer3/computers/medical.dm @@ -95,6 +95,7 @@ dat += "
Name: [active1.fields["name"]] \ ID: [active1.fields["id"]]
\n \ + Entity Classification: [active1.fields["brain_type"]]
\n \ Sex: [active1.fields["sex"]]
\n \ Age: [active1.fields["age"]]
\n \ Fingerprint: [active1.fields["fingerprint"]]
\n \ diff --git a/code/game/machinery/computer3/computers/security.dm b/code/game/machinery/computer3/computers/security.dm index a314bed2736..6b77a274bf5 100644 --- a/code/game/machinery/computer3/computers/security.dm +++ b/code/game/machinery/computer3/computers/security.dm @@ -134,6 +134,7 @@ dat += text("
\ Name: [active1.fields["name"]]
\ ID: [active1.fields["id"]]
\n \ + Entity Classification: [active1.fields["brain_type"]]
\n \ Sex: [active1.fields["sex"]]
\n \ Age: [active1.fields["age"]]
\n \ Rank: [active1.fields["rank"]]
\n \ diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 6441a5e72ae..672a6a425b7 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -534,7 +534,7 @@ time_entered = world.time if(ishuman(M) && applies_stasis) var/mob/living/carbon/human/H = M - H.in_stasis = 1 + H.Stasis(1000) // Book keeping! var/turf/location = get_turf(src) @@ -602,7 +602,7 @@ set_occupant(usr) if(ishuman(usr) && applies_stasis) var/mob/living/carbon/human/H = occupant - H.in_stasis = 1 + H.Stasis(1000) icon_state = occupied_icon_state @@ -638,7 +638,7 @@ occupant.forceMove(get_turf(src)) if(ishuman(occupant) && applies_stasis) var/mob/living/carbon/human/H = occupant - H.in_stasis = 0 + H.Stasis(0) set_occupant(null) icon_state = base_icon_state diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index fa4b601e91e..76eb2da2d5a 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -61,7 +61,7 @@ for reference: var/health = 100 var/maxhealth = 100 var/material/material - + /obj/structure/barricade/New(var/newloc, var/material_name) ..(newloc) if(!material_name) @@ -74,7 +74,7 @@ for reference: desc = "This space is blocked off by a barricade made of [material.display_name]." color = material.icon_colour maxhealth = material.integrity - health = maxhealth + health = maxhealth /obj/structure/barricade/get_material() return material @@ -237,7 +237,7 @@ for reference: var/turf/Tsec = get_turf(src) /* 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 s.set_up(3, 1, src) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 6aeecfc8e5d..e78cba35688 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -777,7 +777,7 @@ About the new airlock wires panel: src.welded = 1 else src.welded = null - playsound(src, 'sound/items/Welder.ogg', 100, 1) + playsound(src, 'sound/items/Welder.ogg', 75, 1) src.update_icon() return else @@ -802,7 +802,7 @@ About the new airlock wires panel: cable.plugin(src, user) else if(!repairing && istype(C, /obj/item/weapon/crowbar)) 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.") if(do_after(user,40)) to_chat(user,"You removed the airlock electronics!") @@ -895,9 +895,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(arePowerSystemsOn()) - playsound(src.loc, open_sound_powered, 100, 1) + playsound(src.loc, open_sound_powered, 75, 1) 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) src.closeOther.close() @@ -992,9 +992,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 has_beeped = 0 if(arePowerSystemsOn()) - playsound(src.loc, open_sound_powered, 100, 1) + playsound(src.loc, open_sound_powered, 75, 1) else - playsound(src.loc, open_sound_unpowered, 100, 1) + playsound(src.loc, open_sound_unpowered, 75, 1) for(var/turf/turf in locs) var/obj/structure/window/killthis = (locate(/obj/structure/window) in turf) if(killthis) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index cd38f9f1ceb..7a1d6abd026 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -164,7 +164,7 @@ switch (Proj.damage_type) if(BRUTE) 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) new /obj/effect/decal/cleanable/ash(src.loc) // Turn it to ashes! qdel(src) diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index cbdcfb9f2fe..1162264dd7b 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -141,7 +141,7 @@ var/alarmed = lockdown 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 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) 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 - if(A.fire || A.air_doors_activated) + if(A.firedoors_closed) alarmed = 1 if(alarmed) nextstate = FIREDOOR_CLOSED diff --git a/code/game/machinery/kitchen/cooking_machines/_cooker.dm b/code/game/machinery/kitchen/cooking_machines/_cooker.dm index a6af0f13f28..552e05d95ab 100644 --- a/code/game/machinery/kitchen/cooking_machines/_cooker.dm +++ b/code/game/machinery/kitchen/cooking_machines/_cooker.dm @@ -170,7 +170,7 @@ cooking_obj = new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(src) // Produce nasty smoke. visible_message("\The [src] vomits a gout of rancid smoke!") - 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.set_up(10, 0, usr.loc) smoke.start() diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index ae48142b4d2..a18edbc5fa5 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -78,7 +78,7 @@ C.traits = new() C.nameVar = "grey" I.add_product(C) - + /obj/machinery/smartfridge/secure/medbay name = "\improper Refrigerated Medicine Storage" @@ -139,6 +139,7 @@ icon_state = "drying_rack" icon_on = "drying_rack_on" icon_off = "drying_rack" + icon_panel = "drying_rack-panel" /obj/machinery/smartfridge/drying_rack/accept_check(var/obj/item/O as obj) if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/)) @@ -260,7 +261,7 @@ locked = -1 user << "You short out the product lock on [src]." return 1 - + /obj/machinery/smartfridge/proc/stock(obj/item/O) var/hasRecord = FALSE //Check to see if this passes or not. for(var/datum/stored_item/I in item_records) @@ -273,7 +274,7 @@ item.add_product(O) item_records.Add(item) nanomanager.update_uis(src) - + /obj/machinery/smartfridge/proc/vend(datum/stored_item/I) I.get_product(get_turf(src)) nanomanager.update_uis(src) @@ -357,7 +358,7 @@ if (!throw_item) continue break - + if(!throw_item) return 0 spawn(0) diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index b0946bf3479..6e9f31889d0 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -155,7 +155,7 @@ Class Procs: if(use_power && stat == 0) 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_state = "empdisable" pulse2.name = "emp sparks" diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 595712afd3a..6d7a6f82a70 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -567,7 +567,7 @@ var/list/turret_icons set_raised_raising(raised, 1) 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("popup", flick_holder) sleep(10) @@ -588,7 +588,7 @@ var/list/turret_icons set_raised_raising(raised, 1) 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("popdown", flick_holder) sleep(10) diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index ffe30bf3fd8..1e10e03f4f8 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -7,7 +7,7 @@ energy_drain = 20 range = MELEE equip_cooldown = 50 - var/mob/living/carbon/occupant = null + var/mob/living/carbon/human/occupant = null var/datum/global_iterator/pr_mech_sleeper var/inject_amount = 10 required_type = /obj/mecha/medical @@ -28,7 +28,7 @@ Exit(atom/movable/O) return 0 - action(var/mob/living/carbon/target) + action(var/mob/living/carbon/human/target) if(!action_checks(target)) return if(!istype(target)) @@ -56,6 +56,7 @@ target.forceMove(src) occupant = target target.reset_view(src) + occupant.Stasis(3) /* if(target.client) target.client.perspective = EYE_PERSPECTIVE @@ -80,6 +81,7 @@ occupant.client.eye = occupant.client.mob occupant.client.perspective = MOB_PERSPECTIVE */ + occupant.Stasis(0) occupant = null pr_mech_sleeper.stop() set_ready_state(1) diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm index 41f1ba44ef2..9b2e0aa26dc 100644 --- a/code/game/mecha/equipment/tools/tools.dm +++ b/code/game/mecha/equipment/tools/tools.dm @@ -208,7 +208,7 @@ for(var/a = 1 to 5) 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 if(a == 1) my_target = T diff --git a/code/game/objects/effects/chem/chemsmoke.dm b/code/game/objects/effects/chem/chemsmoke.dm index 3f077116e93..45cfcc83488 100644 --- a/code/game/objects/effects/chem/chemsmoke.dm +++ b/code/game/objects/effects/chem/chemsmoke.dm @@ -152,7 +152,7 @@ if(passed_smoke) smoke = passed_smoke else - smoke = PoolOrNew(/obj/effect/effect/smoke/chem, location) + smoke = new /obj/effect/effect/smoke/chem(location) 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 @@ -169,7 +169,7 @@ qdel(src) /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]" ..(T, I, dist, spores) diff --git a/code/game/objects/effects/chem/foam.dm b/code/game/objects/effects/chem/foam.dm index b29b2440e6c..5f29bd6448e 100644 --- a/code/game/objects/effects/chem/foam.dm +++ b/code/game/objects/effects/chem/foam.dm @@ -108,7 +108,7 @@ F.amount += amount return - F = PoolOrNew(/obj/effect/effect/foam, list(location, metal)) + F = new /obj/effect/effect/foam(location, metal) F.amount = amount if(!metal) // don't carry other chemicals if a metal foam diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index fc764efd02d..3cdca23fdeb 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -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++) sleep(3) 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.update_icon() diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index 485ea6987b2..2343871b95a 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -75,7 +75,7 @@ steam.start() -- spawns the effect spawn(0) if(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 if(src.cardinals) direction = pick(cardinal) @@ -146,7 +146,7 @@ steam.start() -- spawns the effect spawn(0) if(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++ var/direction if(src.cardinals) @@ -283,7 +283,7 @@ steam.start() -- spawns the effect spawn(0) if(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++ smoke.color = I var/direction = src.direction @@ -334,7 +334,7 @@ steam.start() -- spawns the effect var/turf/T = get_turf(src.holder) if(T != src.oldposition) 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 I.set_dir(src.holder.dir) flick("ion_fade", I) @@ -380,7 +380,7 @@ steam.start() -- spawns the effect src.processing = 0 spawn(0) 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.oldposition = get_turf(holder) I.set_dir(src.holder.dir) @@ -420,7 +420,7 @@ steam.start() -- spawns the effect start() 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.start() diff --git a/code/game/objects/effects/gibs.dm b/code/game/objects/effects/gibs.dm index 9d630113bbf..16db09edb6b 100644 --- a/code/game/objects/effects/gibs.dm +++ b/code/game/objects/effects/gibs.dm @@ -24,7 +24,7 @@ var/obj/effect/decal/cleanable/blood/gibs/gib = null 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.start() diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index 27e6d7c74a2..52f920775eb 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -26,7 +26,7 @@ call(src,triggerproc)(M) /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.start() obj:radiation += 50 @@ -39,7 +39,7 @@ if(ismob(obj)) var/mob/M = obj 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.start() spawn(0) @@ -67,7 +67,7 @@ qdel(src) /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.start() qdel(obj:client) diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index 1077d757ae3..4396465bc98 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -105,7 +105,7 @@ O = loc for(var/i=0, i[src] dies!") - PoolOrNew(/obj/effect/decal/cleanable/spiderling_remains, src.loc) + new /obj/effect/decal/cleanable/spiderling_remains(src.loc) qdel(src) /obj/effect/spider/spiderling/healthcheck() diff --git a/code/game/objects/empulse.dm b/code/game/objects/empulse.dm index 3b1a3b54f52..3d97946bd4e 100644 --- a/code/game/objects/empulse.dm +++ b/code/game/objects/empulse.dm @@ -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] ") 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_state = "emppulse" pulse.name = "emp pulse" diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index b081530e10b..0bf146f0379 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -1,23 +1,26 @@ //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 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 epicenter = get_turf(epicenter) if(!epicenter) return // Handles recursive propagation of explosions. - if(devastation_range > 2 || heavy_impact_range > 2) - if(HasAbove(epicenter.z) && z_transfer & UP) - explosion(GetAbove(epicenter), max(0, devastation_range - 2), max(0, heavy_impact_range - 2), max(0, light_impact_range - 2), max(0, flash_range - 2), 0, UP) - if(HasBelow(epicenter.z) && z_transfer & DOWN) - explosion(GetAbove(epicenter), max(0, devastation_range - 2), max(0, heavy_impact_range - 2), max(0, light_impact_range - 2), max(0, flash_range - 2), 0, DOWN) + if(z_transfer && multi_z_scalar) + var/adj_dev = max(0, (multi_z_scalar * devastation_range) - (shaped ? 2 : 0) ) + var/adj_heavy = max(0, (multi_z_scalar * heavy_impact_range) - (shaped ? 2 : 0) ) + var/adj_light = max(0, (multi_z_scalar * light_impact_range) - (shaped ? 2 : 0) ) + 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) @@ -30,31 +33,30 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa far_dist += devastation_range * 20 var/frequency = get_rand_frequency() for(var/mob/M in player_list) - // Double check for client - if(M && M.client) + if(M.z == epicenter.z) var/turf/M_turf = get_turf(M) - if(M_turf && M_turf.z == epicenter.z) - var/dist = get_dist(M_turf, epicenter) - // If inside the blast radius + world.view - 2 - 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 - - //You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station. - - 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/dist = get_dist(M_turf, epicenter) + // If inside the blast radius + world.view - 2 + 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 + 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) // to all distanced mobs play a different sound - for(var/mob/M in world) if(M.z == epicenter.z) if(!(M in close)) - // 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' + for(var/mob/M in world) + if(M.z == epicenter.z) + if(!(M in close)) + // 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) - message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (JMP)") - log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ") + 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]) (JMP)") + 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/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/y0 = epicenter.y 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)) - var/dist = sqrt((T.x - x0)**2 + (T.y - y0)**2) + if(dist < devastation_range) dist = 1 + else if(dist < heavy_impact_range) dist = 2 + else if(dist < light_impact_range) dist = 3 + else continue - if(dist < devastation_range) dist = 1 - else if(dist < heavy_impact_range) dist = 2 - else if(dist < light_impact_range) dist = 3 - else continue - - T.ex_act(dist) - if(T) + if(!T) + T = locate(x0,y0,z0) 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 if(AM && AM.simulated) AM.ex_act(dist) + T.ex_act(dist) + 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 - 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. for(var/i,i<=doppler_arrays.len,i++) var/obj/machinery/doppler_array/Array = doppler_arrays[i] if(Array) Array.sense_explosion(x0,y0,z0,devastation_range,heavy_impact_range,light_impact_range,took) - sleep(8) if(!powernet_rebuild_was_deferred_already && defer_powernet_rebuild) makepowernets() defer_powernet_rebuild = 0 - return 1 - - proc/secondaryexplosion(turf/epicenter, range) for(var/turf/tile in range(range, epicenter)) tile.ex_act(2) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 4316da3c499..de91b79d60c 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -50,7 +50,7 @@ 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/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. @@ -79,12 +79,12 @@ var/list/sprite_sheets_obj = list() /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() ..() diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index 1450fa94ce5..4d77da4ae93 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -77,14 +77,20 @@ /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(!ishuman(usr)) return + if(!ishuman(usr)) return 0 if(opened) return 0 if(contents.len) return 0 visible_message("[usr] folds up the [src.name]") - new item_path(get_turf(src)) + var/folded = new item_path(get_turf(src)) spawn(0) qdel(src) - return + return folded + +/obj/structure/closet/body_bag/relaymove(mob/user,direction) + if(src.loc != get_turf(src)) + src.loc.relaymove(user,direction) + else + ..() /obj/structure/closet/body_bag/proc/get_occupants() var/list/occupants = list() @@ -109,34 +115,43 @@ /obj/item/bodybag/cryobag 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 \ - a hostile enviroment." + desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \ + especially useful if short on time or in a hostile enviroment." icon = 'icons/obj/cryobag.dmi' icon_state = "bodybag_folded" item_state = "bodybag_cryo_folded" origin_tech = list(TECH_BIO = 4) + var/obj/item/weapon/reagent_containers/syringe/syringe /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) R.add_fingerprint(user) + if(syringe) + R.syringe = syringe + syringe = null qdel(src) /obj/structure/closet/body_bag/cryobag 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 \ - a hostile enviroment." + desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \ + especially useful if short on time or in a hostile enviroment." icon = 'icons/obj/cryobag.dmi' item_path = /obj/item/bodybag/cryobag store_misc = 0 store_items = 0 var/used = 0 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() 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() + if(syringe) + qdel(syringe) + syringe = null qdel(tank) tank = null ..() @@ -151,11 +166,19 @@ O.desc = "Pretty useless now.." 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) if(ishuman(AM)) var/mob/living/carbon/human/H = AM - H.in_stasis = 1 + H.Stasis(stasis_level) src.used = 1 + inject_occupant(H) if(istype(AM, /obj/item/organ)) var/obj/item/organ/O = AM @@ -167,7 +190,7 @@ /obj/structure/closet/body_bag/cryobag/Exited(atom/movable/AM) if(ishuman(AM)) var/mob/living/carbon/human/H = AM - H.in_stasis = 0 + H.Stasis(0) if(istype(AM, /obj/item/organ)) var/obj/item/organ/O = AM @@ -181,10 +204,19 @@ 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) ..() if(Adjacent(user)) //The bag's rather thick and opaque from a distance. user << "You peer into \the [src]." + if(syringe) + user << "It has a syringe added to it." for(var/mob/living/L in contents) L.examine(user) @@ -196,5 +228,28 @@ var/obj/item/device/healthanalyzer/analyzer = W for(var/mob/living/L in contents) analyzer.attack(L,user) + + else if(istype(W,/obj/item/weapon/reagent_containers/syringe)) + if(syringe) + to_chat(user,"\The [src] already has an injector! Remove it first.") + else + var/obj/item/weapon/reagent_containers/syringe/syringe = W + to_chat(user,"You insert \the [syringe] into \the [src], and it locks into place.") + 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,"The injector cannot be removed now that the stasis bag has been used!") + else + syringe.forceMove(src.loc) + to_chat(user,"You pry \the [syringe] out of \the [src].") + syringe = null + else ..() diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 674e746c28b..667adfc712f 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -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(istype(M, /mob/new_player)) continue + if(M.forbid_seeing_deadchat) + continue M.show_message("PDA Message - [owner] -> [P.owner]: [t]") if(!conversations.Find("\ref[P]")) diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm index 4b870481fa1..9775d640421 100644 --- a/code/game/objects/items/devices/chameleonproj.dm +++ b/code/game/objects/items/devices/chameleonproj.dm @@ -47,7 +47,7 @@ qdel(active_dummy) active_dummy = null usr << "You deactivate the [src]." - 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' flick("emppulse",T) spawn(8) qdel(T) @@ -55,7 +55,7 @@ playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6) var/obj/O = new saved_item(src) 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) qdel(O) usr << "You activate the [src]." diff --git a/code/game/objects/items/devices/communicator/communicator.dm b/code/game/objects/items/devices/communicator/communicator.dm index 8bfe2dffca2..42c8e4949b7 100644 --- a/code/game/objects/items/devices/communicator/communicator.dm +++ b/code/game/objects/items/devices/communicator/communicator.dm @@ -212,6 +212,8 @@ var/global/list/obj/item/device/communicator/all_communicators = list() alert_called = 0 update_icon() ui_interact(user) + if(video_source) + watch_video(user) // Proc: MouseDrop() //Same thing PDAs do @@ -1032,7 +1034,8 @@ var/global/list/obj/item/device/communicator/all_communicators = list() if(!Adjacent(user) || !video_source) return user.set_machine(video_source) user.reset_view(video_source) - user << "Now viewing video session. To leave camera view: OOC -> Cancel Camera View" + to_chat(user,"Now viewing video session. To leave camera view, close the communicator window OR: OOC -> Cancel Camera View") + to_chat(user,"To return to an active video session, use the communicator in your hand.") spawn(0) while(user.machine == video_source && Adjacent(user)) var/turf/T = get_turf(video_source) diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm index 73efffe121b..8b048a035e0 100644 --- a/code/game/objects/items/devices/defib.dm +++ b/code/game/objects/items/devices/defib.dm @@ -75,7 +75,7 @@ if(user.r_hand && user.l_hand) cell.forceMove(get_turf(user)) else - cell.forceMove(user.put_in_hands(cell)) + user.put_in_hands(cell) cell = null playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) else @@ -141,14 +141,15 @@ sleep(15 SECONDS) break - if(patient.client) - patient.adjustOxyLoss(-20) //Look, blood stays oxygenated for quite some time, but I'm not recoding the entire oxy system - patient.stat = CONSCIOUS //Note that if whatever killed them in the first place wasn't fixed, they're likely to die again. - dead_mob_list -= patient - living_mob_list += patient - patient.timeofdeath = null - patient.visible_message("[patient]'s eyes open!") - log_and_message_admins("[patient] was revived.") + if(!(HUSK in patient.mutations)) // Husked people can't come back with a Defib. + if(patient.client) + patient.adjustOxyLoss(-20) //Look, blood stays oxygenated for quite some time, but I'm not recoding the entire oxy system + patient.stat = CONSCIOUS //Note that if whatever killed them in the first place wasn't fixed, they're likely to die again. + dead_mob_list -= patient + living_mob_list += patient + patient.timeofdeath = null + patient.visible_message("[patient]'s eyes open!") + log_and_message_admins("[patient] was revived by a defib.") cell.charge -= charge_cost //Always charge the cost after any attempt, failed or not sleep(20) //Wait 2 seconds before next attempt statechange(1,patient) //Back to ready diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 9b573a2cf1d..c3cbf5f7ef3 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -73,7 +73,7 @@ if(brightness_level == "low") set_light(brightness_on/2) else if(brightness_level == "high") - set_light(brightness_on*4) + set_light(brightness_on*1.5) else set_light(brightness_on) diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 15f33103225..db4e890d604 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -155,7 +155,7 @@ singular_name = "advanced trauma kit" desc = "An advanced trauma kit for severe injuries." icon_state = "traumakit" - heal_brute = 0 + heal_brute = 5 origin_tech = list(TECH_BIO = 1) /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" desc = "An advanced treatment kit for severe burns." icon_state = "burnkit" - heal_burn = 0 + heal_burn = 5 origin_tech = list(TECH_BIO = 1) diff --git a/code/game/objects/items/weapons/RSF.dm b/code/game/objects/items/weapons/RSF.dm index 10a847b4695..d404b5cd445 100644 --- a/code/game/objects/items/weapons/RSF.dm +++ b/code/game/objects/items/weapons/RSF.dm @@ -39,7 +39,7 @@ RSF playsound(src.loc, 'sound/effects/pop.ogg', 50, 0) if (mode == 1) mode = 2 - user << "Changed dispensing mode to 'Drinking Glass'" + user << "Changed dispensing mode to 'Drinking Glass:Pint'" return if (mode == 2) mode = 3 @@ -82,7 +82,7 @@ RSF product = new /obj/item/clothing/mask/smokable/cigarette() used_energy = 10 if(2) - product = new /obj/item/weapon/reagent_containers/food/drinks/glass2() + product = new /obj/item/weapon/reagent_containers/food/drinks/glass2/pint() used_energy = 50 if(3) product = new /obj/item/weapon/paper() diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm deleted file mode 100644 index 9099ff3bd10..00000000000 --- a/code/game/objects/items/weapons/dice.dm +++ /dev/null @@ -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("[user] has thrown [src]. It lands on [result]. [comment]", \ - "You throw [src]. It lands on a [result]. [comment]", \ - "You hear [src] landing on a [result]. [comment]") diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm index 3bcb68bcee7..eba48464f03 100644 --- a/code/game/objects/items/weapons/extinguisher.dm +++ b/code/game/objects/items/weapons/extinguisher.dm @@ -107,7 +107,7 @@ spawn(0) 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 if(a <= the_targets.len) my_target = the_targets[a] diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm index c3f93a016f0..84bee725588 100644 --- a/code/game/objects/items/weapons/flamethrower.dm +++ b/code/game/objects/items/weapons/flamethrower.dm @@ -86,7 +86,7 @@ if(ptank) ptank.loc = T ptank = null - PoolOrNew(/obj/item/stack/rods, T) + new /obj/item/stack/rods(T) qdel(src) return diff --git a/code/game/objects/items/weapons/grenades/smokebomb.dm b/code/game/objects/items/weapons/grenades/smokebomb.dm index d64627fcf38..2c89be0ac7d 100644 --- a/code/game/objects/items/weapons/grenades/smokebomb.dm +++ b/code/game/objects/items/weapons/grenades/smokebomb.dm @@ -12,7 +12,7 @@ /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) /obj/item/weapon/grenade/smokebomb/Destroy() diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index 1190d7f8120..62941c24f08 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -41,6 +41,8 @@ user << "You need to have a firm grip on [C] before you can put \the [src] on!" /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(user.Adjacent(target)) return 1 diff --git a/code/game/objects/items/weapons/implants/implantcircuits.dm b/code/game/objects/items/weapons/implants/implantcircuits.dm index cf55cbd7067..db24be3c0af 100644 --- a/code/game/objects/items/weapons/implants/implantcircuits.dm +++ b/code/game/objects/items/weapons/implants/implantcircuits.dm @@ -38,7 +38,10 @@ IC.examine(user) /obj/item/weapon/implant/integrated_circuit/attackby(var/obj/item/O, var/mob/user) - if(istype(O, /obj/item/weapon/crowbar) || istype(O, /obj/item/device/integrated_electronics) || istype(O, /obj/item/integrated_circuit) || istype(O, /obj/item/weapon/screwdriver) ) + if(istype(O, /obj/item/weapon/crowbar) || istype(O, /obj/item/device/integrated_electronics) || istype(O, /obj/item/integrated_circuit) || istype(O, /obj/item/weapon/screwdriver) || istype(O, /obj/item/weapon/cell/device) ) IC.attackby(O, user) else - ..() \ No newline at end of file + ..() + +/obj/item/weapon/implant/integrated_circuit/attack_self(mob/user) + IC.attack_self(user) \ No newline at end of file diff --git a/code/game/objects/items/weapons/permits.dm b/code/game/objects/items/weapons/permits.dm index bb0ebfdd0c2..8008959460a 100644 --- a/code/game/objects/items/weapons/permits.dm +++ b/code/game/objects/items/weapons/permits.dm @@ -32,4 +32,9 @@ /obj/item/weapon/permit/gun/bar name = "bar shotgun permit" - desc = "A card indicating that the owner is allowed to carry a shotgun in the bar." \ No newline at end of file + desc = "A card indicating that the owner is allowed to carry a shotgun in the bar." + +/obj/item/weapon/permit/drone + name = "drone identification card" + desc = "A card issued by the EIO, indicating that the owner is a Drone Intelligence. Drones are mandated to carry this card within SolGov space, by law." + icon_state = "drone" \ No newline at end of file diff --git a/code/game/objects/items/weapons/policetape.dm b/code/game/objects/items/weapons/policetape.dm index a9f2a15deaf..9b4cb3ca9bc 100644 --- a/code/game/objects/items/weapons/policetape.dm +++ b/code/game/objects/items/weapons/policetape.dm @@ -2,12 +2,12 @@ /obj/item/taperoll name = "tape roll" icon = 'icons/policetape.dmi' - icon_state = "rollstart" + icon_state = "tape" w_class = ITEMSIZE_SMALL var/turf/start var/turf/end var/tape_type = /obj/item/tape - var/icon_base + var/icon_base = "tape" var/apply_tape = FALSE @@ -33,7 +33,7 @@ var/list/tape_roll_applications = list() var/lifted = 0 var/crumpled = 0 var/tape_dir = 0 - var/icon_base + var/icon_base = "tape" /obj/item/tape/update_icon() //Possible directional bitflags: 0 (AIRLOCK), 1 (NORTH), 2 (SOUTH), 4 (EAST), 8 (WEST), 3 (VERTICAL), 12 (HORIZONTAL) @@ -60,22 +60,20 @@ var/list/tape_roll_applications = list() /obj/item/taperoll/police name = "police tape" desc = "A roll of police tape used to block off crime scenes from the public." - icon_state = "police" tape_type = /obj/item/tape/police - icon_base = "police" + color = COLOR_RED_LIGHT /obj/item/tape/police name = "police tape" desc = "A length of police tape. Do not cross." req_access = list(access_security) - icon_base = "police" + color = COLOR_RED_LIGHT /obj/item/taperoll/engineering name = "engineering tape" desc = "A roll of engineering tape used to block off working areas from the public." - icon_state = "engineering" tape_type = /obj/item/tape/engineering - icon_base = "engineering" + color = COLOR_YELLOW /obj/item/taperoll/engineering/applied apply_tape = TRUE @@ -84,28 +82,31 @@ var/list/tape_roll_applications = list() name = "engineering tape" desc = "A length of engineering tape. Better not cross it." req_one_access = list(access_engine,access_atmospherics) - icon_base = "engineering" + color = COLOR_YELLOW /obj/item/taperoll/atmos name = "atmospherics tape" desc = "A roll of atmospherics tape used to block off working areas from the public." - icon_state = "atmos" tape_type = /obj/item/tape/atmos - icon_base = "atmos" + color = COLOR_DEEP_SKY_BLUE /obj/item/tape/atmos name = "atmospherics tape" desc = "A length of atmospherics tape. Better not cross it." req_one_access = list(access_engine,access_atmospherics) - icon_base = "atmos" + color = COLOR_DEEP_SKY_BLUE /obj/item/taperoll/update_icon() overlays.Cut() + var/image/overlay = image(icon = src.icon) + overlay.appearance_flags = RESET_COLOR if(ismob(loc)) if(!start) - overlays += "start" + overlay.icon_state = "start" else - overlays += "stop" + overlay.icon_state = "stop" + overlays += overlay + /obj/item/taperoll/dropped(mob/user) update_icon() diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm index 2c47c8ab9d9..5e3c96c8a07 100644 --- a/code/game/objects/items/weapons/shields.dm +++ b/code/game/objects/items/weapons/shields.dm @@ -130,7 +130,7 @@ . = ..() 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.start() playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1) diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index 61a9a99f96d..3ceb940bbbe 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -126,7 +126,7 @@ 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/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) return @@ -161,7 +161,7 @@ if (empty) return 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 /* diff --git a/code/game/objects/items/weapons/storage/misc.dm b/code/game/objects/items/weapons/storage/misc.dm index bf4856501a8..64952046a56 100644 --- a/code/game/objects/items/weapons/storage/misc.dm +++ b/code/game/objects/items/weapons/storage/misc.dm @@ -1,30 +1,3 @@ -/obj/item/weapon/storage/pill_bottle/dice //7d6 - name = "bag of dice" - desc = "It's a small bag with dice inside." - icon = 'icons/obj/dice.dmi' - icon_state = "dicebag" - -/obj/item/weapon/storage/pill_bottle/dice/New() - ..() - for(var/i = 1 to 7) - new /obj/item/weapon/dice( src ) - -/obj/item/weapon/storage/pill_bottle/dice_nerd //DnD dice - name = "bag of gaming dice" - desc = "It's a small bag with gaming dice inside." - icon = 'icons/obj/dice.dmi' - icon_state = "magicdicebag" - -/obj/item/weapon/storage/pill_bottle/dice_nerd/New() - ..() - new /obj/item/weapon/dice/d4( src ) - new /obj/item/weapon/dice( src ) - new /obj/item/weapon/dice/d8( src ) - new /obj/item/weapon/dice/d10( src ) - new /obj/item/weapon/dice/d12( src ) - new /obj/item/weapon/dice/d20( src ) - new /obj/item/weapon/dice/d100( src ) - /* * Donut Box */ diff --git a/code/game/objects/structures/crates_lockers/closets/job_closets.dm b/code/game/objects/structures/crates_lockers/closets/job_closets.dm index c93f68a82a0..25d0e576ea8 100644 --- a/code/game/objects/structures/crates_lockers/closets/job_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/job_closets.dm @@ -28,6 +28,7 @@ new /obj/item/clothing/under/sl_suit(src) new /obj/item/clothing/under/rank/bartender(src) new /obj/item/clothing/under/rank/bartender(src) + new /obj/item/clothing/under/rank/bartender/skirt(src) new /obj/item/clothing/under/dress/dress_saloon(src) new /obj/item/clothing/accessory/wcoat(src) new /obj/item/clothing/accessory/wcoat(src) @@ -97,16 +98,24 @@ new /obj/item/clothing/under/lawyer/female(src) new /obj/item/clothing/under/lawyer/black(src) new /obj/item/clothing/under/lawyer/black(src) + new /obj/item/clothing/under/lawyer/black/skirt(src) + new /obj/item/clothing/under/lawyer/black/skirt(src) new /obj/item/clothing/under/lawyer/red(src) new /obj/item/clothing/under/lawyer/red(src) + new /obj/item/clothing/under/lawyer/red/skirt(src) + new /obj/item/clothing/under/lawyer/red/skirt(src) new /obj/item/clothing/suit/storage/toggle/internalaffairs(src) new /obj/item/clothing/suit/storage/toggle/internalaffairs(src) new /obj/item/clothing/under/lawyer/bluesuit(src) new /obj/item/clothing/under/lawyer/bluesuit(src) + new /obj/item/clothing/under/lawyer/bluesuit/skirt(src) + new /obj/item/clothing/under/lawyer/bluesuit/skirt(src) new /obj/item/clothing/suit/storage/toggle/lawyer/bluejacket(src) new /obj/item/clothing/suit/storage/toggle/lawyer/bluejacket(src) new /obj/item/clothing/under/lawyer/purpsuit(src) new /obj/item/clothing/under/lawyer/purpsuit(src) + new /obj/item/clothing/under/lawyer/purpsuit/skirt(src) + new /obj/item/clothing/under/lawyer/purpsuit/skirt(src) new /obj/item/clothing/suit/storage/toggle/lawyer/purpjacket(src) new /obj/item/clothing/suit/storage/toggle/lawyer/purpjacket(src) new /obj/item/clothing/shoes/brown(src) @@ -119,5 +128,7 @@ new /obj/item/clothing/glasses/sunglasses/big(src) new /obj/item/clothing/under/lawyer/blue(src) new /obj/item/clothing/under/lawyer/blue(src) + new /obj/item/clothing/under/lawyer/blue/skirt(src) + new /obj/item/clothing/under/lawyer/blue/skirt(src) new /obj/item/device/tape/random(src) new /obj/item/device/tape/random(src) \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 6aea41942ff..dc80d178276 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -65,7 +65,9 @@ new /obj/item/clothing/under/dress/dress_hr(src) new /obj/item/clothing/under/lawyer/female(src) new /obj/item/clothing/under/lawyer/black(src) + new /obj/item/clothing/under/lawyer/black/skirt(src) new /obj/item/clothing/under/lawyer/red(src) + new /obj/item/clothing/under/lawyer/red/skirt(src) new /obj/item/clothing/under/lawyer/oldman(src) new /obj/item/clothing/shoes/brown(src) new /obj/item/clothing/shoes/black(src) @@ -74,6 +76,7 @@ new /obj/item/clothing/under/rank/head_of_personnel_whimsy(src) new /obj/item/clothing/head/caphat/hop(src) new /obj/item/clothing/under/gimmick/rank/head_of_personnel/suit(src) + new /obj/item/clothing/under/gimmick/rank/head_of_personnel/suit/skirt(src) new /obj/item/clothing/glasses/sunglasses(src) return diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm index 3e5b494e7f0..191e01798be 100644 --- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm +++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm @@ -82,6 +82,7 @@ new /obj/item/clothing/under/det/grey/waistcoat(src) new /obj/item/clothing/under/det/black(src) new /obj/item/clothing/under/det/black(src) + new /obj/item/clothing/under/det/skirt(src) new /obj/item/clothing/under/det/corporate(src) new /obj/item/clothing/under/det/corporate(src) new /obj/item/clothing/suit/storage/det_trench(src) @@ -600,17 +601,25 @@ ..() new /obj/item/clothing/under/assistantformal(src) new /obj/item/clothing/under/suit_jacket/charcoal(src) + new /obj/item/clothing/under/suit_jacket/charcoal/skirt(src) new /obj/item/clothing/under/suit_jacket/navy(src) + new /obj/item/clothing/under/suit_jacket/navy/skirt(src) new /obj/item/clothing/under/suit_jacket/burgundy(src) + new /obj/item/clothing/under/suit_jacket/burgundy/skirt(src) new /obj/item/clothing/under/suit_jacket/checkered(src) + new /obj/item/clothing/under/suit_jacket/checkered/skirt(src) new /obj/item/clothing/under/suit_jacket/tan(src) + new /obj/item/clothing/under/suit_jacket/tan/skirt(src) new /obj/item/clothing/under/sl_suit(src) new /obj/item/clothing/under/suit_jacket(src) new /obj/item/clothing/under/suit_jacket/female(src) new /obj/item/clothing/under/suit_jacket/female/skirt(src) new /obj/item/clothing/under/suit_jacket/really_black(src) + new /obj/item/clothing/under/suit_jacket/really_black/skirt(src) new /obj/item/clothing/under/suit_jacket/red(src) + new /obj/item/clothing/under/suit_jacket/red/skirt(src) new /obj/item/clothing/under/scratch(src) + new /obj/item/clothing/under/scratch/skirt(src) new /obj/item/weapon/storage/backpack/satchel(src) new /obj/item/weapon/storage/backpack/satchel(src) return @@ -637,5 +646,6 @@ new /obj/item/clothing/suit/storage/hooded/wintercoat/captain(src) new /obj/item/clothing/head/beret/centcom/captain(src) new /obj/item/clothing/under/gimmick/rank/captain/suit(src) + new /obj/item/clothing/under/gimmick/rank/captain/suit/skirt(src) new /obj/item/clothing/glasses/sunglasses(src) return \ No newline at end of file diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 0691d3d68e1..720d8a92d35 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -97,7 +97,7 @@ if(iswirecutter(W)) if(!shock(user, 100)) playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1) - PoolOrNew(/obj/item/stack/rods, list(get_turf(src), destroyed ? 1 : 2)) + new /obj/item/stack/rods(get_turf(src), destroyed ? 1 : 2) qdel(src) else if((isscrewdriver(W)) && (istype(loc, /turf/simulated) || anchored)) if(!shock(user, 90)) @@ -152,7 +152,7 @@ else if(!(W.flags & CONDUCT) || !shock(user, 70)) user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) - user.do_attack_animation(src) + user.do_attack_animation(src) playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) switch(W.damtype) if("fire") @@ -170,11 +170,11 @@ density = 0 destroyed = 1 update_icon() - PoolOrNew(/obj/item/stack/rods, get_turf(src)) + new /obj/item/stack/rods(get_turf(src)) else if(health <= -6) - PoolOrNew(/obj/item/stack/rods, get_turf(src)) + new /obj/item/stack/rods(get_turf(src)) qdel(src) return return diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index 0eb48e94e08..96291ecd274 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -65,7 +65,7 @@ if(WT.welding == 1) if(WT.remove_fuel(0, user)) user << "Slicing lattice joints ..." - PoolOrNew(/obj/item/stack/rods, src.loc) + new /obj/item/stack/rods(src.loc) qdel(src) return diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index bd280787827..42ee6af2e3e 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -77,34 +77,44 @@ return return + /obj/structure/morgue/attack_hand(mob/user as mob) if (src.connected) - for(var/atom/movable/A as mob|obj in src.connected.loc) - if (!( A.anchored )) - A.forceMove(src) - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - qdel(src.connected) - src.connected = null + close() else - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - src.connected = new /obj/structure/m_tray( src.loc ) - step(src.connected, src.dir) - src.connected.layer = OBJ_LAYER - var/turf/T = get_step(src, src.dir) - if (T.contents.Find(src.connected)) - src.connected.connected = src - src.icon_state = "morgue0" - for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.connected.loc) - src.connected.icon_state = "morguet" - src.connected.set_dir(src.dir) - else - qdel(src.connected) - src.connected = null + open() src.add_fingerprint(user) update() return + +/obj/structure/morgue/proc/close() + for(var/atom/movable/A as mob|obj in src.connected.loc) + if (!( A.anchored )) + A.forceMove(src) + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + qdel(src.connected) + src.connected = null + + +/obj/structure/morgue/proc/open() + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + src.connected = new /obj/structure/m_tray( src.loc ) + step(src.connected, src.dir) + src.connected.layer = OBJ_LAYER + var/turf/T = get_step(src, src.dir) + if (T.contents.Find(src.connected)) + src.connected.connected = src + src.icon_state = "morgue0" + for(var/atom/movable/A as mob|obj in src) + A.forceMove(src.connected.loc) + src.connected.icon_state = "morguet" + src.connected.set_dir(src.dir) + else + qdel(src.connected) + src.connected = null + + /obj/structure/morgue/attackby(P as obj, mob/user as mob) if (istype(P, /obj/item/weapon/pen)) var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) as text @@ -123,21 +133,8 @@ /obj/structure/morgue/relaymove(mob/user as mob) if (user.stat) return - src.connected = new /obj/structure/m_tray( src.loc ) - step(src.connected, EAST) - src.connected.layer = OBJ_LAYER - var/turf/T = get_step(src, EAST) - if (T.contents.Find(src.connected)) - src.connected.connected = src - src.icon_state = "morgue0" - for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.connected.loc) - src.connected.icon_state = "morguet" - else - qdel(src.connected) - src.connected = null - return - + if (user in src.occupants) + open() /* * Morgue tray diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index a382858c543..94aa30c24d3 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -182,13 +182,13 @@ spawn(50) if(src && on) ismist = 1 - mymist = PoolOrNew(/obj/effect/mist,loc) + mymist = new /obj/effect/mist(loc) else ismist = 1 - mymist = PoolOrNew(/obj/effect/mist,loc) + mymist = new /obj/effect/mist(loc) else if(ismist) ismist = 1 - mymist = PoolOrNew(/obj/effect/mist,loc) + mymist = new /obj/effect/mist(loc) spawn(250) if(src && !on) qdel(mymist) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 15d6e322130..809dd008a48 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -92,11 +92,11 @@ index = 0 while(index < 2) new shardtype(loc) //todo pooling? - if(reinf) PoolOrNew(/obj/item/stack/rods, loc) + if(reinf) new /obj/item/stack/rods(loc) index++ else new shardtype(loc) //todo pooling? - if(reinf) PoolOrNew(/obj/item/stack/rods, loc) + if(reinf) new /obj/item/stack/rods(loc) qdel(src) return diff --git a/code/game/objects/structures/window_spawner.dm b/code/game/objects/structures/window_spawner.dm index 7cdf301f6c1..d0db6e7f08b 100644 --- a/code/game/objects/structures/window_spawner.dm +++ b/code/game/objects/structures/window_spawner.dm @@ -35,7 +35,7 @@ /obj/effect/wingrille_spawn/proc/activate() if(activated) return if (!locate(/obj/structure/grille) in get_turf(src)) - var/obj/structure/grille/G = PoolOrNew(/obj/structure/grille, src.loc) + var/obj/structure/grille/G = new /obj/structure/grille(src.loc) handle_grille_spawn(G) var/list/neighbours = list() for (var/dir in cardinal) @@ -49,7 +49,7 @@ found_connection = 1 qdel(W) if(!found_connection) - var/obj/structure/window/new_win = PoolOrNew(win_path, src.loc) + var/obj/structure/window/new_win = new win_path(src.loc) new_win.set_dir(dir) handle_window_spawn(new_win) else diff --git a/code/game/turfs/initialization/maintenance.dm b/code/game/turfs/initialization/maintenance.dm index 16b1d03d21e..558f6385882 100644 --- a/code/game/turfs/initialization/maintenance.dm +++ b/code/game/turfs/initialization/maintenance.dm @@ -15,9 +15,10 @@ T.update_dirt() if(prob(2)) - PoolOrNew(junk(), T) + var/type = junk() + new type(T) if(prob(2)) - PoolOrNew(/obj/effect/decal/cleanable/blood/oil, T) + new /obj/effect/decal/cleanable/blood/oil(T) if(prob(25)) // Keep in mind that only "corners" get any sort of web attempt_web(T, cardinal_turfs) @@ -54,7 +55,7 @@ var/global/list/random_junk var/turf/neighbour = get_step(T, dir) if(neighbour && neighbour.density) if(dir == WEST) - PoolOrNew(/obj/effect/decal/cleanable/cobweb, T) + new /obj/effect/decal/cleanable/cobweb(T) if(dir == EAST) - PoolOrNew(/obj/effect/decal/cleanable/cobweb2, T) + new /obj/effect/decal/cleanable/cobweb2(T) return diff --git a/code/game/turfs/simulated/wall_attacks.dm b/code/game/turfs/simulated/wall_attacks.dm index 47620d030a8..098782ebdf0 100644 --- a/code/game/turfs/simulated/wall_attacks.dm +++ b/code/game/turfs/simulated/wall_attacks.dm @@ -1,3 +1,6 @@ +#define ZONE_BLOCKED 2 +#define AIR_BLOCKED 1 + //Interactions /turf/simulated/wall/proc/toggle_open(var/mob/user) @@ -8,7 +11,9 @@ can_open = WALL_OPENING //flick("[material.icon_base]fwall_opening", src) density = 0 + blocks_air = ZONE_BLOCKED update_icon() + update_air() set_light(0) src.blocks_air = 0 set_opacity(0) @@ -18,7 +23,9 @@ can_open = WALL_OPENING //flick("[material.icon_base]fwall_closing", src) density = 1 + blocks_air = AIR_BLOCKED update_icon() + update_air() set_light(1) src.blocks_air = 1 set_opacity(1) @@ -28,6 +35,25 @@ can_open = WALL_CAN_OPEN update_icon() +#undef ZONE_BLOCKED +#undef AIR_BLOCKED + +/turf/simulated/wall/proc/update_air() + if(!air_master) + return + + for(var/turf/simulated/turf in loc) + update_thermal(turf) + air_master.mark_for_update(turf) + + +/turf/simulated/wall/proc/update_thermal(var/turf/simulated/source) + if(istype(source)) + if(density && opacity) + source.thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT + else + source.thermal_conductivity = initial(source.thermal_conductivity) + /turf/simulated/wall/proc/fail_smash(var/mob/user) user << "You smash against the wall!" take_damage(rand(25,75)) diff --git a/code/game/turfs/turf_flick_animations.dm b/code/game/turfs/turf_flick_animations.dm index 94f5fec4c58..81b248ec0df 100644 --- a/code/game/turfs/turf_flick_animations.dm +++ b/code/game/turfs/turf_flick_animations.dm @@ -5,7 +5,7 @@ location = get_turf(target) if(location && !target) target = location - var/atom/movable/overlay/animation = PoolOrNew(/atom/movable/overlay, location) + var/atom/movable/overlay/animation = new /atom/movable/overlay(location) if(direction) animation.set_dir(direction) animation.icon = a_icon diff --git a/code/global.dm b/code/global.dm index 6970e68dffa..ea27e3f8233 100644 --- a/code/global.dm +++ b/code/global.dm @@ -89,7 +89,9 @@ var/list/blobstart = list() var/list/ninjastart = list() var/list/cardinal = list(NORTH, SOUTH, EAST, WEST) +var/list/cardinalz = list(NORTH, SOUTH, EAST, WEST, UP, DOWN) var/list/cornerdirs = list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST) +var/list/cornerdirsz = list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST, NORTH|UP, EAST|UP, WEST|UP, SOUTH|UP, NORTH|DOWN, EAST|DOWN, WEST|DOWN, SOUTH|DOWN) var/list/alldirs = list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST) var/list/reverse_dir = list( // reverse_dir[dir] = reverse of dir 2, 1, 3, 8, 10, 9, 11, 4, 6, 5, 7, 12, 14, 13, 15, 32, 34, 33, 35, 40, 42, diff --git a/code/modules/busy_space/organizations.dm b/code/modules/busy_space/organizations.dm index 4dcde05bf02..88beb83d85e 100644 --- a/code/modules/busy_space/organizations.dm +++ b/code/modules/busy_space/organizations.dm @@ -249,7 +249,11 @@ "Anything Legal Considered", "New Toy", "Me, I'm Always Counting", - "Just Five More Minutes" + "Just Five More Minutes", + "Are You Feeling It", + "Great White Snark", + "No Shirt No Shoes", + "Callsign" ) diff --git a/code/modules/client/preference_setup/loadout/loadout_general.dm b/code/modules/client/preference_setup/loadout/loadout_general.dm index a97d5776fcc..6f3115fd2f2 100644 --- a/code/modules/client/preference_setup/loadout/loadout_general.dm +++ b/code/modules/client/preference_setup/loadout/loadout_general.dm @@ -10,6 +10,10 @@ display_name = "dice pack (gaming)" path = /obj/item/weapon/storage/pill_bottle/dice_nerd +/datum/gear/dice/cup + display_name = "dice cup and dice" + path = /obj/item/weapon/storage/dicecup/loaded + /datum/gear/cards display_name = "deck of cards" path = /obj/item/weapon/deck/cards diff --git a/code/modules/client/preference_setup/loadout/loadout_uniform.dm b/code/modules/client/preference_setup/loadout/loadout_uniform.dm index ccc5214b55b..881da0b8c81 100644 --- a/code/modules/client/preference_setup/loadout/loadout_uniform.dm +++ b/code/modules/client/preference_setup/loadout/loadout_uniform.dm @@ -5,6 +5,10 @@ slot = slot_w_uniform sort_category = "Uniforms and Casual Dress" +/datum/gear/uniform/blazerskirt + display_name = "blazer, blue with skirt" + path = /obj/item/clothing/under/blazer/skirt + /datum/gear/uniform/cheongsam display_name = "cheongsam selection" @@ -190,26 +194,50 @@ display_name = "suit, shiny-black" path = /obj/item/clothing/under/lawyer/black +/datum/gear/uniform/suit/shinyblackskirt + display_name = "suit, shiny-black skirt" + path = /obj/item/clothing/under/lawyer/black/skirt + /datum/gear/uniform/suit/blue display_name = "suit, blue" path = /obj/item/clothing/under/lawyer/blue +/datum/gear/uniform/suit/blueskirt + display_name = "suit, blue skirt" + path = /obj/item/clothing/under/lawyer/blue/skirt + /datum/gear/uniform/suit/burgundy display_name = "suit, burgundy" path = /obj/item/clothing/under/suit_jacket/burgundy +/datum/gear/uniform/suit/burgundyskirt + display_name = "suit, burgundy skirt" + path = /obj/item/clothing/under/suit_jacket/burgundy/skirt + /datum/gear/uniform/suit/checkered display_name = "suit, checkered" path = /obj/item/clothing/under/suit_jacket/checkered +/datum/gear/uniform/suit/checkeredskirt + display_name = "suit, checkered skirt" + path = /obj/item/clothing/under/suit_jacket/checkered/skirt + /datum/gear/uniform/suit/charcoal display_name = "suit, charcoal" path = /obj/item/clothing/under/suit_jacket/charcoal +/datum/gear/uniform/suit/charcoalskirt + display_name = "suit, charcoal skirt" + path = /obj/item/clothing/under/suit_jacket/charcoal/skirt + /datum/gear/uniform/suit/exec display_name = "suit, executive" path = /obj/item/clothing/under/suit_jacket/really_black +/datum/gear/uniform/suit/execskirt + display_name = "suit, executive skirt" + path = /obj/item/clothing/under/suit_jacket/really_black/skirt + /datum/gear/uniform/suit/femaleexec display_name = "suit, female-executive" path = /obj/item/clothing/under/suit_jacket/female @@ -218,18 +246,34 @@ display_name = "suit, gentlemen" path = /obj/item/clothing/under/gentlesuit +/datum/gear/uniform/suit/gentleskirt + display_name = "suit, lady" + path = /obj/item/clothing/under/gentlesuit/skirt + /datum/gear/uniform/suit/navy display_name = "suit, navy" path = /obj/item/clothing/under/suit_jacket/navy +/datum/gear/uniform/suit/navyskirt + display_name = "suit, navy skirt" + path = /obj/item/clothing/under/suit_jacket/navy/skirt + /datum/gear/uniform/suit/red display_name = "suit, red" path = /obj/item/clothing/under/suit_jacket/red +/datum/gear/uniform/suit/redskirt + display_name = "suit, red skirt" + path = /obj/item/clothing/under/suit_jacket/red/skirt + /datum/gear/uniform/suit/redlawyer display_name = "suit, lawyer-red" path = /obj/item/clothing/under/lawyer/red +/datum/gear/uniform/suit/redlawyerskirt + display_name = "suit, lawyer-red skirt" + path = /obj/item/clothing/under/lawyer/red/skirt + /datum/gear/uniform/suit/oldman display_name = "suit, old-man" path = /obj/item/clothing/under/lawyer/oldman @@ -238,18 +282,49 @@ display_name = "suit, purple" path = /obj/item/clothing/under/lawyer/purpsuit +/datum/gear/uniform/suit/purpleskirt + display_name = "suit, purple skirt" + path = /obj/item/clothing/under/lawyer/purpsuit/skirt + /datum/gear/uniform/suit/tan display_name = "suit, tan" path = /obj/item/clothing/under/suit_jacket/tan +/datum/gear/uniform/suit/tanskirt + display_name = "suit, tan skirt" + path = /obj/item/clothing/under/suit_jacket/tan/skirt + /datum/gear/uniform/suit/white display_name = "suit, white" path = /obj/item/clothing/under/scratch +/datum/gear/uniform/suit/whiteskirt + display_name = "suit, white skirt" + path = /obj/item/clothing/under/scratch/skirt + /datum/gear/uniform/suit/whiteblue display_name = "suit, white-blue" path = /obj/item/clothing/under/lawyer/bluesuit +/datum/gear/uniform/suit/whiteblueskirt + display_name = "suit, white-blue skirt" + path = /obj/item/clothing/under/lawyer/bluesuit/skirt + +/datum/gear/uniform/suit/detectiveskirt + display_name = "suit, detective skirt (Detective)" + path = /obj/item/clothing/under/det/skirt + allowed_roles = list("Detective") + +/datum/gear/uniform/suit/iaskirt + display_name = "suit, Internal Affairs skirt (Internal Affairs)" + path = /obj/item/clothing/under/rank/internalaffairs/skirt + allowed_roles = list("Internal Affairs Agent") + +/datum/gear/uniform/suit/bartenderskirt + display_name = "suit, bartender skirt (Bartender)" + path = /obj/item/clothing/under/rank/bartender/skirt + allowed_roles = list("Bartender") + /datum/gear/uniform/scrubs display_name = "scrubs, black" path = /obj/item/clothing/under/rank/medical/black @@ -271,6 +346,10 @@ display_name = "scrubs, navy blue" path = /obj/item/clothing/under/rank/medical/navyblue +/datum/gear/uniform/oldwoman + display_name = "old woman attire" + path = /obj/item/clothing/under/lawyer/oldwoman + /datum/gear/uniform/sundress display_name = "sundress" path = /obj/item/clothing/under/sundress diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm index ffea7b7fab7..099aa439787 100644 --- a/code/modules/clothing/chameleon.dm +++ b/code/modules/clothing/chameleon.dm @@ -408,6 +408,7 @@ projectile_type = /obj/item/projectile/chameleon charge_meter = 0 charge_cost = 48 //uses next to no power, since it's just holograms + battery_lock = 1 var/obj/item/projectile/copy_projectile var/global/list/gun_choices diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 9e27f5c73dd..4fb748f73ae 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -132,7 +132,7 @@ BLIND // can't see anything eye = !eye if(eye) - icon_state = "[icon_state]_r" + icon_state = "[icon_state]_1" else icon_state = initial(icon_state) update_clothing_icon() @@ -395,7 +395,8 @@ BLIND // can't see anything toggleable = 1 action_button_name = "Toggle Goggles" vision_flags = SEE_MOBS - see_invisible = INVISIBILITY_LEVEL_TWO + see_invisible = SEE_INVISIBLE_NOLIGHTING + emp_act(severity) if(istype(src.loc, /mob/living/carbon/human)) diff --git a/code/modules/clothing/spacesuits/alien.dm b/code/modules/clothing/spacesuits/alien.dm index ff0f8ae0776..e23c3c0c264 100644 --- a/code/modules/clothing/spacesuits/alien.dm +++ b/code/modules/clothing/spacesuits/alien.dm @@ -34,7 +34,7 @@ item_flags = STOPPRESSUREDAMAGE | THICKMATERIAL | PHORONGUARD allowed = list(/obj/item/weapon/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs,/obj/item/weapon/tank) phoronproof = 1 - slowdown = 2 + slowdown = 0.5 armor = list(melee = 60, bullet = 50, laser = 40,energy = 15, bomb = 30, bio = 100, rad = 50) siemens_coefficient = 0.2 heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS diff --git a/code/modules/clothing/spacesuits/rig/modules/ninja.dm b/code/modules/clothing/spacesuits/rig/modules/ninja.dm index da4e8c9da5d..075411cd294 100644 --- a/code/modules/clothing/spacesuits/rig/modules/ninja.dm +++ b/code/modules/clothing/spacesuits/rig/modules/ninja.dm @@ -183,7 +183,7 @@ /obj/item/rig_module/self_destruct/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) /obj/item/rig_module/self_destruct/Destroy() diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 4394d661955..cd345fc8aa4 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -257,6 +257,14 @@ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER +/obj/item/clothing/suit/straight_jacket/attack_hand(mob/living/user as mob) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(src == H.wear_suit) + to_chat(H, "You need help taking this off!") + return + ..() + /obj/item/clothing/suit/ianshirt name = "worn shirt" desc = "A worn out, curiously comfortable t-shirt with a picture of Ian. You wouldn't go so far as to say it feels like being hugged when you wear it but it's pretty close. Good for sleeping in." diff --git a/code/modules/clothing/under/accessories/holster.dm b/code/modules/clothing/under/accessories/holster.dm index a68605ff913..5d734c9d95a 100644 --- a/code/modules/clothing/under/accessories/holster.dm +++ b/code/modules/clothing/under/accessories/holster.dm @@ -107,7 +107,7 @@ if(!H.holstered) var/obj/item/W = usr.get_active_hand() if(!istype(W, /obj/item)) - usr << "You need your gun equiped to holster it." + usr << "You need your gun equipped to holster it." return H.holster(W, usr) else diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm index a6b5c15ea3a..d14cff333be 100644 --- a/code/modules/clothing/under/jobs/civilian.dm +++ b/code/modules/clothing/under/jobs/civilian.dm @@ -6,6 +6,12 @@ icon_state = "ba_suit" rolled_sleeves = 0 +/obj/item/clothing/under/rank/bartender/skirt + desc = "Short and cute." + name = "bartender's skirt" + icon_state = "ba_suit_skirt" + item_state_slots = list(slot_r_hand_str = "ba_suit", slot_l_hand_str = "ba_suit") + /obj/item/clothing/under/rank/captain //Alright, technically not a 'civilian' but its better then giving a .dm file for a single define. desc = "It's a blue jumpsuit with some gold markings denoting the rank of \"Colony Director\"." name = "colony director's jumpsuit" @@ -97,6 +103,11 @@ rolled_sleeves = 0 starting_accessories = list(/obj/item/clothing/accessory/black) +/obj/item/clothing/under/rank/internalaffairs/skirt + desc = "The plain, professional attire of an Internal Affairs Agent. The top button is sewn shut." + name = "Internal Affairs skirt" + icon_state = "internalaffairs_skirt" + /obj/item/clothing/under/rank/janitor desc = "It's the official uniform of the station's janitor. It has minor protection from biohazards." name = "janitor's jumpsuit" @@ -112,6 +123,11 @@ name = "black Lawyer suit" icon_state = "lawyer_black" +/obj/item/clothing/under/lawyer/black/skirt + name = "black Lawyer skirt" + icon_state = "lawyer_black_skirt" + item_state_slots = list(slot_r_hand_str = "lawyer_black", slot_l_hand_str = "lawyer_black") + /obj/item/clothing/under/lawyer/female name = "black Lawyer suit" icon_state = "black_suit_fem" @@ -121,28 +137,52 @@ name = "red Lawyer suit" icon_state = "lawyer_red" +/obj/item/clothing/under/lawyer/red/skirt + name = "red Lawyer skirt" + icon_state = "lawyer_red_skirt" + item_state_slots = list(slot_r_hand_str = "lawyer_red", slot_l_hand_str = "lawyer_red") + /obj/item/clothing/under/lawyer/blue name = "blue Lawyer suit" icon_state = "lawyer_blue" +/obj/item/clothing/under/lawyer/blue/skirt + name = "blue Lawyer skirt" + icon_state = "lawyer_blue_skirt" + item_state_slots = list(slot_r_hand_str = "lawyer_blue", slot_l_hand_str = "lawyer_blue") + /obj/item/clothing/under/lawyer/bluesuit - name = "Blue Suit" + name = "blue suit" desc = "A classy suit." icon_state = "bluesuit" item_state_slots = list(slot_r_hand_str = "lawyer_blue", slot_l_hand_str = "lawyer_blue") starting_accessories = list(/obj/item/clothing/accessory/red) +/obj/item/clothing/under/lawyer/bluesuit/skirt + name = "blue skirt suit" + icon_state = "bluesuit_skirt" + /obj/item/clothing/under/lawyer/purpsuit - name = "Purple Suit" + name = "purple Suit" icon_state = "lawyer_purp" item_state_slots = list(slot_r_hand_str = "purple", slot_l_hand_str = "purple") +/obj/item/clothing/under/lawyer/purpsuit/skirt + name = "purple skirt suit" + icon_state = "lawyer_purp_skirt" + /obj/item/clothing/under/lawyer/oldman name = "Old Man's Suit" desc = "A classic suit for the older gentleman with built in back support." icon_state = "oldman" item_state_slots = list(slot_r_hand_str = "johnny", slot_l_hand_str = "johnny") +/obj/item/clothing/under/lawyer/oldwoman + name = "Old Woman's Attire" + desc = "A typical outfit for the older woman, a lovely cardigan and comfortable skirt." + icon_state = "oldwoman" + item_state_slots = list(slot_r_hand_str = "johnny", slot_l_hand_str = "johnny") + /obj/item/clothing/under/librarian name = "sensible suit" desc = "It's very... sensible." diff --git a/code/modules/clothing/under/jobs/security.dm b/code/modules/clothing/under/jobs/security.dm index c745e7e9b4e..02dde0f8151 100644 --- a/code/modules/clothing/under/jobs/security.dm +++ b/code/modules/clothing/under/jobs/security.dm @@ -113,6 +113,12 @@ desc = "A serious-looking tan dress shirt paired with freshly-pressed black slacks, complete with a red striped tie and waistcoat." starting_accessories = list(/obj/item/clothing/accessory/red_long, /obj/item/clothing/accessory/wcoat) +/obj/item/clothing/under/det/skirt + name = "detective's skirt" + icon_state = "detective_skirt" + desc = "A serious-looking white blouse paired with a formal black pencil skirt." + item_state_slots = list(slot_r_hand_str = "sl_suit", slot_l_hand_str = "sl_suit") + /* * Head of Security */ diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index a6336e3cc51..4dc7d78feb2 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -21,6 +21,11 @@ desc = "A white suit, suitable for an excellent host" icon_state = "scratch" +/obj/item/clothing/under/scratch/skirt + name = "white skirt suit" + icon_state = "scratch_skirt" + item_state_slots = list(slot_r_hand_str = "scratch", slot_l_hand_str = "scratch") + /obj/item/clothing/under/sl_suit desc = "It's a very amish looking suit." name = "amish suit" @@ -98,6 +103,11 @@ rolled_sleeves = 0 starting_accessories = list(/obj/item/clothing/accessory/darkgreen) +/obj/item/clothing/under/gov/skirt + name = "Green formal skirt uniform" + desc = "A neat proper uniform of someone on offical business. The top button is sewn shut." + icon_state = "greensuit_skirt" + /obj/item/clothing/under/space name = "\improper NASA jumpsuit" desc = "It has a NASA logo on it and is made of space-proofed materials." @@ -147,24 +157,37 @@ /obj/item/clothing/under/gentlesuit name = "gentlemans suit" - desc = "A silk black shirt with a white tie and a matching gray vest and slacks. Feels proper." + desc = "A silk black shirt with matching gray slacks. Feels proper." icon_state = "gentlesuit" item_state_slots = list(slot_r_hand_str = "grey", slot_l_hand_str = "grey") rolled_sleeves = 0 starting_accessories = list(/obj/item/clothing/accessory/white, /obj/item/clothing/accessory/wcoat/gentleman) +/obj/item/clothing/under/gentlesuit/skirt + name = "lady's suit" + desc = "A silk black blouse with a matching gray skirt. Feels proper." + icon_state = "gentlesuit_skirt" + /obj/item/clothing/under/gimmick/rank/captain/suit name = "colony director's suit" desc = "A green suit and yellow necktie. Exemplifies authority." icon_state = "green_suit" item_state_slots = list(slot_r_hand_str = "centcom", slot_l_hand_str = "centcom") +/obj/item/clothing/under/gimmick/rank/captain/suit/skirt + name = "colony director's skirt suit" + icon_state = "green_suit_skirt" + /obj/item/clothing/under/gimmick/rank/head_of_personnel/suit name = "head of personnel's suit" desc = "A teal suit and yellow necktie. An authoritative yet tacky ensemble." icon_state = "teal_suit" item_state_slots = list(slot_r_hand_str = "green", slot_l_hand_str = "green") +/obj/item/clothing/under/gimmick/rank/head_of_personnel/suit/skirt + name = "head of personnel's skirt suit" + icon_state = "teal_suit_skirt" + /obj/item/clothing/under/suit_jacket name = "black suit" desc = "A black suit and red tie. Very formal." @@ -177,6 +200,11 @@ icon_state = "really_black_suit" item_state_slots = list(slot_r_hand_str = "lawyer_black", slot_l_hand_str = "lawyer_black") +/obj/item/clothing/under/suit_jacket/really_black/skirt + name = "executive skirt suit" + desc = "A formal black suit and red necktie, intended for the station's finest." + icon_state = "really_black_suit_skirt" + /obj/item/clothing/under/suit_jacket/female name = "executive suit" desc = "A formal trouser suit for women, intended for the station's finest." @@ -196,6 +224,11 @@ icon_state = "red_suit" item_state_slots = list(slot_r_hand_str = "lawyer_red", slot_l_hand_str = "lawyer_red") +/obj/item/clothing/under/suit_jacket/red/skirt + name = "red skirt suit" + desc = "A red suit and blue necktie. Somewhat formal." + icon_state = "red_suit_skirt" + /obj/item/clothing/under/schoolgirl name = "schoolgirl uniform" desc = "It's just like one of my Japanese animes!" @@ -421,6 +454,10 @@ item_state_slots = list(slot_r_hand_str = "lawyer_black", slot_l_hand_str = "lawyer_black") starting_accessories = list(/obj/item/clothing/accessory/navy, /obj/item/clothing/accessory/charcoal_jacket) +/obj/item/clothing/under/suit_jacket/charcoal/skirt + name = "charcoal skirt" + icon_state = "charcoal_suit_skirt" + /obj/item/clothing/under/suit_jacket/navy name = "navy suit" desc = "A navy suit and red tie, intended for the station's finest." @@ -428,6 +465,10 @@ item_state_slots = list(slot_r_hand_str = "lawyer_blue", slot_l_hand_str = "lawyer_blue") starting_accessories = list(/obj/item/clothing/accessory/red, /obj/item/clothing/accessory/navy_jacket) +/obj/item/clothing/under/suit_jacket/navy/skirt + name = "navy skirt" + icon_state = "navy_suit_skirt" + /obj/item/clothing/under/suit_jacket/burgundy name = "burgundy suit" desc = "A burgundy suit and black tie. Somewhat formal." @@ -435,6 +476,10 @@ item_state_slots = list(slot_r_hand_str = "lawyer_red", slot_l_hand_str = "lawyer_red") starting_accessories = list(/obj/item/clothing/accessory/black, /obj/item/clothing/accessory/burgundy_jacket) +/obj/item/clothing/under/suit_jacket/burgundy/skirt + name = "burgundy skirt" + icon_state = "burgundy_suit_skirt" + /obj/item/clothing/under/suit_jacket/checkered name = "checkered suit" desc = "That's a very nice suit you have there. Shame if something were to happen to it, eh?" @@ -442,6 +487,10 @@ item_state_slots = list(slot_r_hand_str = "lawyer_black", slot_l_hand_str = "lawyer_black") starting_accessories = list(/obj/item/clothing/accessory/black, /obj/item/clothing/accessory/checkered_jacket) +/obj/item/clothing/under/suit_jacket/checkered/skirt + name = "checkered skirt" + icon_state = "checkered_suit_skirt" + /obj/item/clothing/under/suit_jacket/tan name = "tan suit" desc = "A tan suit. Smart, but casual." @@ -449,6 +498,10 @@ item_state_slots = list(slot_r_hand_str = "tan_suit", slot_l_hand_str = "tan_suit") starting_accessories = list(/obj/item/clothing/accessory/yellow, /obj/item/clothing/accessory/tan_jacket) +/obj/item/clothing/under/suit_jacket/tan/skirt + name = "tan skirt" + icon_state = "tan_suit_skirt" + /obj/item/clothing/under/serviceoveralls name = "workman outfit" desc = "The very image of a working man. Not that you're probably doing work." @@ -483,6 +536,11 @@ icon_state = "blue_blazer" item_state_slots = list(slot_r_hand_str = "lawyer_blue", slot_l_hand_str = "lawyer_blue") +/obj/item/clothing/under/blazer/skirt + name = "ladies blue blazer" + desc = "A bold but yet conservative outfit, a red pencil skirt and a navy blazer." + icon_state = "blue_blazer_skirt" + /obj/item/clothing/under/croptop name = "crop top" desc = "A shirt that has had the top cropped. This one is NT sponsored." diff --git a/code/modules/games/dice.dm b/code/modules/games/dice.dm new file mode 100644 index 00000000000..039631cdb4c --- /dev/null +++ b/code/modules/games/dice.dm @@ -0,0 +1,157 @@ +/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 + var/result = 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 + result = 4 + +/obj/item/weapon/dice/d8 + name = "d8" + desc = "A dice with eight sides." + icon_state = "d88" + sides = 8 + result = 8 + +/obj/item/weapon/dice/d10 + name = "d10" + desc = "A dice with ten sides." + icon_state = "d1010" + sides = 10 + result = 10 + +/obj/item/weapon/dice/d12 + name = "d12" + desc = "A dice with twelve sides." + icon_state = "d1212" + sides = 12 + result = 12 + +/obj/item/weapon/dice/d20 + name = "d20" + desc = "A dice with twenty sides." + icon_state = "d2020" + sides = 20 + result = 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 + result = 10 + +/obj/item/weapon/dice/attack_self(mob/user as mob) + rollDice(user, 0) + +/obj/item/weapon/dice/proc/rollDice(mob/user as mob, var/silent = 0) + result = rand(1, sides) + icon_state = "[name][result]" + + if(!silent) + var/comment = "" + if(sides == 20 && result == 20) + comment = "Nat 20!" + else if(sides == 20 && result == 1) + comment = "Ouch, bad luck." + + user.visible_message("[user] has thrown [src]. It lands on [result]. [comment]", \ + "You throw [src]. It lands on a [result]. [comment]", \ + "You hear [src] landing on a [result]. [comment]") + +/* + * Dice packs + */ + +/obj/item/weapon/storage/pill_bottle/dice //7d6 + name = "bag of dice" + desc = "It's a small bag with dice inside." + icon = 'icons/obj/dice.dmi' + icon_state = "dicebag" + +/obj/item/weapon/storage/pill_bottle/dice/New() + ..() + for(var/i = 1 to 7) + new /obj/item/weapon/dice( src ) + +/obj/item/weapon/storage/pill_bottle/dice_nerd //DnD dice + name = "bag of gaming dice" + desc = "It's a small bag with gaming dice inside." + icon = 'icons/obj/dice.dmi' + icon_state = "magicdicebag" + +/obj/item/weapon/storage/pill_bottle/dice_nerd/New() + ..() + new /obj/item/weapon/dice/d4( src ) + new /obj/item/weapon/dice( src ) + new /obj/item/weapon/dice/d8( src ) + new /obj/item/weapon/dice/d10( src ) + new /obj/item/weapon/dice/d12( src ) + new /obj/item/weapon/dice/d20( src ) + new /obj/item/weapon/dice/d100( src ) + +/* + *Liar's Dice cup + */ + +/obj/item/weapon/storage/dicecup + name = "dice cup" + desc = "A cup used to conceal and hold dice." + icon = 'icons/obj/dice.dmi' + icon_state = "dicecup" + w_class = ITEMSIZE_SMALL + storage_slots = 5 + can_hold = list( + /obj/item/weapon/dice, + ) + +/obj/item/weapon/storage/dicecup/attack_self(mob/user as mob) + user.visible_message("[user] shakes [src].", \ + "You shake [src].", \ + "You hear dice rolling.") + rollCup(user) + +/obj/item/weapon/storage/dicecup/proc/rollCup(mob/user as mob) + for(var/obj/item/weapon/dice/I in src.contents) + var/obj/item/weapon/dice/D = I + D.rollDice(user, 1) + +/obj/item/weapon/storage/dicecup/proc/revealDice(var/mob/viewer) + for(var/obj/item/weapon/dice/I in src.contents) + var/obj/item/weapon/dice/D = I + to_chat(viewer, "The [D.name] shows a [D.result].") + +/obj/item/weapon/storage/dicecup/verb/peekAtDice() + set category = "Object" + set name = "Peek at Dice" + set desc = "Peek at the dice under your cup." + + revealDice(usr) + +/obj/item/weapon/storage/dicecup/verb/revealDiceHand() + + set category = "Object" + set name = "Reveal Dice" + set desc = "Reveal the dice hidden under your cup." + + for(var/mob/living/player in viewers(3)) + to_chat(player, "[usr] reveals their dice.") + revealDice(player) + + +/obj/item/weapon/storage/dicecup/loaded/New() + ..() + for(var/i = 1 to 5) + new /obj/item/weapon/dice( src ) \ No newline at end of file diff --git a/code/modules/holodeck/HolodeckControl.dm b/code/modules/holodeck/HolodeckControl.dm index eb18581551b..ff0b95f3653 100644 --- a/code/modules/holodeck/HolodeckControl.dm +++ b/code/modules/holodeck/HolodeckControl.dm @@ -18,23 +18,57 @@ var/mob/last_to_emag = null var/last_change = 0 var/last_gravity_change = 0 - var/list/supported_programs = list( \ - "Empty Court" = "emptycourt", \ - "Basketball Court" = "basketball", \ - "Thunderdome Court" = "thunderdomecourt", \ - "Boxing Ring"="boxingcourt", \ - "Beach" = "beach", \ - "Desert" = "desert", \ - "Space" = "space", \ - "Picnic Area" = "picnicarea", \ - "Snow Field" = "snowfield", \ - "Theatre" = "theatre", \ - "Meeting Hall" = "meetinghall", \ - "Courtroom" = "courtroom", \ - "Turn Off" = "turnoff" \ + + var/area/projection_area = /area/holodeck/alphadeck + var/current_program + var/powerdown_program = "Turn Off" + var/default_program = "Empty Court" + + var/list/supported_programs = list( + "Empty Court" = new/datum/holodeck_program(/area/holodeck/source_emptycourt, list('sound/music/THUNDERDOME.ogg')), + "Boxing Ring" = new/datum/holodeck_program(/area/holodeck/source_boxingcourt, list('sound/music/THUNDERDOME.ogg')), + "Basketball" = new/datum/holodeck_program(/area/holodeck/source_basketball, list('sound/music/THUNDERDOME.ogg')), + "Thunderdome" = new/datum/holodeck_program(/area/holodeck/source_thunderdomecourt, list('sound/music/THUNDERDOME.ogg')), + "Beach" = new/datum/holodeck_program(/area/holodeck/source_beach), + "Desert" = new/datum/holodeck_program(/area/holodeck/source_desert, + list( + 'sound/effects/wind/wind_2_1.ogg', + 'sound/effects/wind/wind_2_2.ogg', + 'sound/effects/wind/wind_3_1.ogg', + 'sound/effects/wind/wind_4_1.ogg', + 'sound/effects/wind/wind_4_2.ogg', + 'sound/effects/wind/wind_5_1.ogg' + ) + ), + "Snowfield" = new/datum/holodeck_program(/area/holodeck/source_snowfield, + list( + 'sound/effects/wind/wind_2_1.ogg', + 'sound/effects/wind/wind_2_2.ogg', + 'sound/effects/wind/wind_3_1.ogg', + 'sound/effects/wind/wind_4_1.ogg', + 'sound/effects/wind/wind_4_2.ogg', + 'sound/effects/wind/wind_5_1.ogg' + ) + ), + "Space" = new/datum/holodeck_program(/area/holodeck/source_space, + list( + 'sound/ambience/ambispace.ogg', + 'sound/music/main.ogg', + 'sound/music/space.ogg', + 'sound/music/traitor.ogg', + ) + ), + "Picnic Area" = new/datum/holodeck_program(/area/holodeck/source_picnicarea, list('sound/music/title2.ogg')), + "Theatre" = new/datum/holodeck_program(/area/holodeck/source_theatre), + "Meetinghall" = new/datum/holodeck_program(/area/holodeck/source_meetinghall), + "Courtroom" = new/datum/holodeck_program(/area/holodeck/source_courtroom, list('sound/music/traitor.ogg')), + "Turn Off" = new/datum/holodeck_program(/area/holodeck/source_plating, list()) + ) + + var/list/restricted_programs = list( + "Burnoff Test Simulation" = new/datum/holodeck_program(/area/holodeck/source_burntest, list()), + "Wildlife Simulation" = new/datum/holodeck_program(/area/holodeck/source_wildlife, list()) ) - var/list/restricted_programs = list("Atmospheric Burn Simulation" = "burntest", "Wildlife Simulation" = "wildlifecarp") - var/current_program = "turnoff" /obj/machinery/computer/HolodeckControl/attack_ai(var/mob/user as mob) return src.attack_hand(user) @@ -59,10 +93,10 @@ var/restricted_program_list[0] for(var/P in supported_programs) - program_list[++program_list.len] = list("name" = P, "program" = supported_programs[P]) + program_list[++program_list.len] = P for(var/P in restricted_programs) - restricted_program_list[++restricted_program_list.len] = list("name" = P, "program" = restricted_programs[P]) + restricted_program_list[++restricted_program_list.len] = P data["supportedPrograms"] = program_list data["restrictedPrograms"] = restricted_program_list @@ -93,9 +127,9 @@ if(href_list["program"]) var/prog = href_list["program"] - if(prog in holodeck_programs) - loadProgram(holodeck_programs[prog]) - current_program = href_list["program"] + if(prog in (supported_programs + restricted_programs)) + loadProgram(prog) + current_program = prog else if(href_list["AIoverride"]) if(!issilicon(usr)) @@ -150,7 +184,10 @@ /obj/machinery/computer/HolodeckControl/New() ..() - linkedholodeck = locate(/area/holodeck/alphadeck) + current_program = powerdown_program + linkedholodeck = locate(projection_area) + if(!linkedholodeck) + world << "Holodeck computer at [x],[y],[z] failed to locate projection area." //This could all be done better, but it works for now. /obj/machinery/computer/HolodeckControl/Destroy() @@ -185,7 +222,7 @@ if(!checkInteg(linkedholodeck)) damaged = 1 - loadProgram(holodeck_programs["turnoff"], 0) + loadProgram(powerdown_program, 0) active = 0 use_power = 1 for(var/mob/M in range(10,src)) @@ -227,9 +264,9 @@ //Why is it called toggle if it doesn't toggle? /obj/machinery/computer/HolodeckControl/proc/togglePower(var/toggleOn = 0) if(toggleOn) - loadProgram(holodeck_programs["emptycourt"], 0) + loadProgram(default_program, 0) else - loadProgram(holodeck_programs["turnoff"], 0) + loadProgram(powerdown_program, 0) if(!linkedholodeck.has_gravity) linkedholodeck.gravitychange(1,linkedholodeck) @@ -238,9 +275,18 @@ use_power = 1 -/obj/machinery/computer/HolodeckControl/proc/loadProgram(var/datum/holodeck_program/HP, var/check_delay = 1) +/obj/machinery/computer/HolodeckControl/proc/loadProgram(var/prog, var/check_delay = 1) + if(!prog) + return + + var/datum/holodeck_program/HP + if(prog in supported_programs) + HP = supported_programs[prog] + else if(prog in restricted_programs) + HP = restricted_programs[prog] if(!HP) return + var/area/A = locate(HP.target) if(!A) return @@ -324,7 +370,7 @@ /obj/machinery/computer/HolodeckControl/proc/emergencyShutdown() //Turn it back to the regular non-holographic room - loadProgram(holodeck_programs["turnoff"], 0) + loadProgram(powerdown_program, 0) if(!linkedholodeck.has_gravity) linkedholodeck.gravitychange(1,linkedholodeck) diff --git a/code/modules/holodeck/HolodeckPrograms.dm b/code/modules/holodeck/HolodeckPrograms.dm index 9cb77f2a4bd..4ae4361a21c 100644 --- a/code/modules/holodeck/HolodeckPrograms.dm +++ b/code/modules/holodeck/HolodeckPrograms.dm @@ -1,46 +1,3 @@ -var/global/list/holodeck_programs = list( - "emptycourt" = new/datum/holodeck_program(/area/holodeck/source_emptycourt, list('sound/music/THUNDERDOME.ogg')), - "boxingcourt" = new/datum/holodeck_program(/area/holodeck/source_boxingcourt, list('sound/music/THUNDERDOME.ogg')), - "basketball" = new/datum/holodeck_program(/area/holodeck/source_basketball, list('sound/music/THUNDERDOME.ogg')), - "thunderdomecourt" = new/datum/holodeck_program(/area/holodeck/source_thunderdomecourt, list('sound/music/THUNDERDOME.ogg')), - "beach" = new/datum/holodeck_program(/area/holodeck/source_beach), - "desert" = new/datum/holodeck_program(/area/holodeck/source_desert, - list( - 'sound/effects/wind/wind_2_1.ogg', - 'sound/effects/wind/wind_2_2.ogg', - 'sound/effects/wind/wind_3_1.ogg', - 'sound/effects/wind/wind_4_1.ogg', - 'sound/effects/wind/wind_4_2.ogg', - 'sound/effects/wind/wind_5_1.ogg' - ) - ), - "snowfield" = new/datum/holodeck_program(/area/holodeck/source_snowfield, - list( - 'sound/effects/wind/wind_2_1.ogg', - 'sound/effects/wind/wind_2_2.ogg', - 'sound/effects/wind/wind_3_1.ogg', - 'sound/effects/wind/wind_4_1.ogg', - 'sound/effects/wind/wind_4_2.ogg', - 'sound/effects/wind/wind_5_1.ogg' - ) - ), - "space" = new/datum/holodeck_program(/area/holodeck/source_space, - list( - 'sound/ambience/ambispace.ogg', - 'sound/music/main.ogg', - 'sound/music/space.ogg', - 'sound/music/traitor.ogg', - ) - ), - "picnicarea" = new/datum/holodeck_program(/area/holodeck/source_picnicarea, list('sound/music/title2.ogg')), - "theatre" = new/datum/holodeck_program(/area/holodeck/source_theatre), - "meetinghall" = new/datum/holodeck_program(/area/holodeck/source_meetinghall), - "courtroom" = new/datum/holodeck_program(/area/holodeck/source_courtroom, list('sound/music/traitor.ogg')), - "burntest" = new/datum/holodeck_program(/area/holodeck/source_burntest, list()), - "wildlifecarp" = new/datum/holodeck_program(/area/holodeck/source_wildlife, list()), - "turnoff" = new/datum/holodeck_program(/area/holodeck/source_plating, list()) - ) - /datum/holodeck_program var/target var/list/ambience = null diff --git a/code/modules/hydroponics/seed_controller.dm b/code/modules/hydroponics/seed_controller.dm index 89cb299f5f6..82b2f62abdb 100644 --- a/code/modules/hydroponics/seed_controller.dm +++ b/code/modules/hydroponics/seed_controller.dm @@ -13,11 +13,11 @@ if(!holder) return if(!plant_controller || !plant_controller.gene_tag_masks) - usr << "Gene masks not set." + to_chat(usr, "Gene masks not set.") return for(var/mask in plant_controller.gene_tag_masks) - usr << "[mask]: [plant_controller.gene_tag_masks[mask]]" + to_chat(usr, "[mask]: [plant_controller.gene_tag_masks[mask]]") var/global/datum/controller/plants/plant_controller // Set in New(). @@ -33,6 +33,8 @@ var/global/datum/controller/plants/plant_controller // Set in New(). var/list/plant_sprites = list() // List of all harvested product sprites. var/list/plant_product_sprites = list() // List of all growth sprites plus number of growth stages. var/processing = 0 // Off/on. + var/list/gene_masked_list = list() // Stored gene masked list, rather than recreating it when needed. + var/list/plant_gene_datums = list() // Stored datum versions of the gene masked list. /datum/controller/plants/New() if(plant_controller && plant_controller != src) @@ -83,6 +85,7 @@ var/global/datum/controller/plants/plant_controller // Set in New(). S.update_seed() //Might as well mask the gene types while we're at it. + var/list/gene_datums = decls_repository.decls_of_subtype(/decl/plantgene) var/list/used_masks = list() var/list/plant_traits = ALL_GENES while(plant_traits && plant_traits.len) @@ -92,9 +95,18 @@ var/global/datum/controller/plants/plant_controller // Set in New(). while(gene_mask in used_masks) gene_mask = "[uppertext(num2hex(rand(0,255)))]" + var/decl/plantgene/G + + for(var/D in gene_datums) + var/decl/plantgene/P = gene_datums[D] + if(gene_tag == P.gene_tag) + G = P + gene_datums -= D used_masks += gene_mask plant_traits -= gene_tag gene_tag_masks[gene_tag] = gene_mask + plant_gene_datums[gene_mask] = G + gene_masked_list.Add(list(list("tag" = gene_tag, "mask" = gene_mask))) // Proc for creating a random seed type. /datum/controller/plants/proc/create_random_seed(var/survive_on_station) @@ -147,4 +159,4 @@ var/global/datum/controller/plants/plant_controller // Set in New(). plant_queue |= plant /datum/controller/plants/proc/remove_plant(var/obj/effect/plant/plant) - plant_queue -= plant + plant_queue -= plant \ No newline at end of file diff --git a/code/modules/hydroponics/seed_gene_mut.dm b/code/modules/hydroponics/seed_gene_mut.dm new file mode 100644 index 00000000000..cdb7048957c --- /dev/null +++ b/code/modules/hydroponics/seed_gene_mut.dm @@ -0,0 +1,135 @@ +/datum/seed/proc/diverge_mutate_gene(var/decl/plantgene/G, var/turf/T) + if(!istype(G)) + log_debug("Attempted to mutate [src] with a non-plantgene var.") + return src + + var/datum/seed/S = diverge() //Let's not modify all of the seeds. + T.visible_message("\The [S.display_name] quivers!") //Mimicks the normal mutation. + G.mutate(S, T) + + return S + +/decl/plantgene + var/gene_tag + +/decl/plantgene/biochem + gene_tag = GENE_BIOCHEMISTRY + +/decl/plantgene/hardiness + gene_tag = GENE_HARDINESS + +/decl/plantgene/environment + gene_tag = GENE_ENVIRONMENT + +/decl/plantgene/metabolism + gene_tag = GENE_METABOLISM + +/decl/plantgene/structure + gene_tag = GENE_STRUCTURE + +/decl/plantgene/diet + gene_tag = GENE_DIET + +/decl/plantgene/pigment + gene_tag = GENE_PIGMENT + +/decl/plantgene/output + gene_tag = GENE_OUTPUT + +/decl/plantgene/atmosphere + gene_tag = GENE_ATMOSPHERE + +/decl/plantgene/vigour + gene_tag = GENE_VIGOUR + +/decl/plantgene/fruit + gene_tag = GENE_FRUIT + +/decl/plantgene/special + gene_tag = GENE_SPECIAL + +/decl/plantgene/proc/mutate(var/datum/seed/S) + return + +/decl/plantgene/biochem/mutate(var/datum/seed/S) + S.set_trait(TRAIT_POTENCY, S.get_trait(TRAIT_POTENCY)+rand(-20,20),200, 0) + +/decl/plantgene/hardiness/mutate(var/datum/seed/S) + if(prob(60)) + S.set_trait(TRAIT_TOXINS_TOLERANCE, S.get_trait(TRAIT_TOXINS_TOLERANCE)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_PEST_TOLERANCE, S.get_trait(TRAIT_PEST_TOLERANCE)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_WEED_TOLERANCE, S.get_trait(TRAIT_WEED_TOLERANCE)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_ENDURANCE, S.get_trait(TRAIT_ENDURANCE)+rand(-5,5),100,0) + +/decl/plantgene/environment/mutate(var/datum/seed/S) + if(prob(60)) + S.set_trait(TRAIT_IDEAL_HEAT, S.get_trait(TRAIT_IDEAL_HEAT)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_IDEAL_LIGHT, S.get_trait(TRAIT_IDEAL_LIGHT)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_LIGHT_TOLERANCE, S.get_trait(TRAIT_LIGHT_TOLERANCE)+rand(-5,5),100,0) + +/decl/plantgene/metabolism/mutate(var/datum/seed/S) + if(prob(65)) + S.set_trait(TRAIT_REQUIRES_NUTRIENTS, S.get_trait(TRAIT_REQUIRES_NUTRIENTS)+rand(-2,2),10,0) + if(prob(65)) + S.set_trait(TRAIT_REQUIRES_WATER, S.get_trait(TRAIT_REQUIRES_WATER)+rand(-2,2),10,0) + if(prob(40)) + S.set_trait(TRAIT_ALTER_TEMP, S.get_trait(TRAIT_ALTER_TEMP)+rand(-5,5),100,0) + +/decl/plantgene/diet/mutate(var/datum/seed/S) + if(prob(60)) + S.set_trait(TRAIT_CARNIVOROUS, S.get_trait(TRAIT_CARNIVOROUS)+rand(-1,1),2,0) + if(prob(60)) + S.set_trait(TRAIT_PARASITE, !S.get_trait(TRAIT_PARASITE)) + if(prob(65)) + S.set_trait(TRAIT_NUTRIENT_CONSUMPTION, S.get_trait(TRAIT_NUTRIENT_CONSUMPTION)+rand(-0.1,0.1),5,0) + if(prob(65)) + S.set_trait(TRAIT_WATER_CONSUMPTION, S.get_trait(TRAIT_WATER_CONSUMPTION)+rand(-1,1),50,0) + +/decl/plantgene/output/mutate(var/datum/seed/S, var/turf/T) + if(prob(50)) + S.set_trait(TRAIT_BIOLUM, !S.get_trait(TRAIT_BIOLUM)) + if(S.get_trait(TRAIT_BIOLUM)) + T.visible_message("\The [S.display_name] begins to glow!") + if(prob(50)) + S.set_trait(TRAIT_BIOLUM_COLOUR,get_random_colour(0,75,190)) + T.visible_message("\The [S.display_name]'s glow changes colour!") + else + T.visible_message("\The [S.display_name]'s glow dims...") + if(prob(60)) + S.set_trait(TRAIT_PRODUCES_POWER, !S.get_trait(TRAIT_PRODUCES_POWER)) + +/decl/plantgene/atmosphere/mutate(var/datum/seed/S) + if(prob(60)) + S.set_trait(TRAIT_TOXINS_TOLERANCE, S.get_trait(TRAIT_TOXINS_TOLERANCE)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_PEST_TOLERANCE, S.get_trait(TRAIT_PEST_TOLERANCE)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_WEED_TOLERANCE, S.get_trait(TRAIT_WEED_TOLERANCE)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_ENDURANCE, S.get_trait(TRAIT_ENDURANCE)+rand(-5,5),100,0) + +/decl/plantgene/vigour/mutate(var/datum/seed/S, var/turf/T) + if(prob(65)) + S.set_trait(TRAIT_PRODUCTION, S.get_trait(TRAIT_PRODUCTION)+rand(-1,1),10,0) + if(prob(65)) + S.set_trait(TRAIT_MATURATION, S.get_trait(TRAIT_MATURATION)+rand(-1,1),30,0) + if(prob(55)) + S.set_trait(TRAIT_SPREAD, S.get_trait(TRAIT_SPREAD)+rand(-1,1),2,0) + T.visible_message("\The [S.display_name] spasms visibly, shifting in the tray.") + +/decl/plantgene/fruit/mutate(var/datum/seed/S) + if(prob(65)) + S.set_trait(TRAIT_STINGS, !S.get_trait(TRAIT_STINGS)) + if(prob(65)) + S.set_trait(TRAIT_EXPLOSIVE, !S.get_trait(TRAIT_EXPLOSIVE)) + if(prob(65)) + S.set_trait(TRAIT_JUICY, !S.get_trait(TRAIT_JUICY)) + +/decl/plantgene/special/mutate(var/datum/seed/S) + if(prob(65)) + S.set_trait(TRAIT_TELEPORTING, !S.get_trait(TRAIT_TELEPORTING)) diff --git a/code/modules/hydroponics/seed_machines.dm b/code/modules/hydroponics/seed_machines.dm index 1479ffdc5c4..bc96f064c9c 100644 --- a/code/modules/hydroponics/seed_machines.dm +++ b/code/modules/hydroponics/seed_machines.dm @@ -137,9 +137,7 @@ var/list/data = list() - var/list/geneMasks[0] - for(var/gene_tag in plant_controller.gene_tag_masks) - geneMasks.Add(list(list("tag" = gene_tag, "mask" = plant_controller.gene_tag_masks[gene_tag]))) + var/list/geneMasks = plant_controller.gene_masked_list data["geneMasks"] = geneMasks data["activity"] = active diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm index efdae46db78..e69c3eec8a3 100644 --- a/code/modules/hydroponics/trays/tray.dm +++ b/code/modules/hydroponics/trays/tray.dm @@ -181,9 +181,14 @@ return //Override for somatoray projectiles. - if(istype(Proj ,/obj/item/projectile/energy/floramut) && prob(20)) - mutate(1) - return + if(istype(Proj ,/obj/item/projectile/energy/floramut)&& prob(20)) + if(istype(Proj, /obj/item/projectile/energy/floramut/gene)) + var/obj/item/projectile/energy/floramut/gene/G = Proj + if(seed) + seed = seed.diverge_mutate_gene(G.gene, get_turf(loc)) //get_turf just in case it's not in a turf. + else + mutate(1) + return else if(istype(Proj ,/obj/item/projectile/energy/florayield) && prob(20)) yield_mod = min(10,yield_mod+rand(1,2)) return diff --git a/code/modules/integrated_electronics/_defines.dm b/code/modules/integrated_electronics/_defines.dm index c404f615812..7089c19d515 100644 --- a/code/modules/integrated_electronics/_defines.dm +++ b/code/modules/integrated_electronics/_defines.dm @@ -8,7 +8,7 @@ #define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box. #define IC_SPAWN_RESEARCH 2 // If the circuit design will be autogenerated for RnD. -#define IC_FORMAT_STRING "\" +#define IC_FORMAT_STRING "\" #define IC_FORMAT_NUMBER "\" #define IC_FORMAT_REF "\" #define IC_FORMAT_LIST "\" diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm index 88b804f80a3..5c49e1817c7 100644 --- a/code/modules/integrated_electronics/core/assemblies.dm +++ b/code/modules/integrated_electronics/core/assemblies.dm @@ -107,6 +107,7 @@ for(var/obj/item/integrated_circuit/circuit in contents) HTML += "[circuit.name] | " HTML += "\[Rename\] | " + HTML += "\[Scan with Debugger\] | " if(circuit.removable) HTML += "\[Remove\]" HTML += "
" @@ -223,9 +224,10 @@ if(proximity) var/scanned = FALSE for(var/obj/item/integrated_circuit/input/sensor/S in contents) - S.set_pin_data(IC_OUTPUT, 1, weakref(target)) - S.check_then_do_work() - scanned = TRUE +// S.set_pin_data(IC_OUTPUT, 1, weakref(target)) +// S.check_then_do_work() + if(S.scan(target)) + scanned = TRUE if(scanned) visible_message("\The [user] waves \the [src] around [target].") diff --git a/code/modules/integrated_electronics/core/integrated_circuit.dm b/code/modules/integrated_electronics/core/integrated_circuit.dm index 87bb4cd182f..1593297734d 100644 --- a/code/modules/integrated_electronics/core/integrated_circuit.dm +++ b/code/modules/integrated_electronics/core/integrated_circuit.dm @@ -6,6 +6,7 @@ a creative player the means to solve many problems. Circuits are held inside an /obj/item/integrated_circuit/examine(mob/user) . = ..() external_examine(user) + interact(user) // This should be used when someone is examining while the case is opened. /obj/item/integrated_circuit/proc/internal_examine(mob/user) @@ -86,16 +87,14 @@ a creative player the means to solve many problems. Circuits are held inside an var/HTML = list() HTML += "[src.name]" HTML += "
" - HTML += "" + HTML += "
" HTML += "
\[Refresh\] | " HTML += "\[Rename\] | " + HTML += "\[Scan with Debugger\] | " HTML += "\[Remove\]
" HTML += "" - //HTML += "" - //HTML += "" - //HTML += "" HTML += "" HTML += "" HTML += "" @@ -212,6 +211,16 @@ a creative player the means to solve many problems. Circuits are held inside an if(href_list["rename"]) rename_component(usr) + if(href_list["scan"]) + if(istype(held_item, /obj/item/device/integrated_electronics/debugger)) + var/obj/item/device/integrated_electronics/debugger/D = held_item + if(D.accepting_refs) + D.afterattack(src, usr, TRUE) + else + to_chat(usr, "The Debugger's 'ref scanner' needs to be on.") + else + to_chat(usr, "You need a Debugger set to 'ref' mode to do that.") + if(href_list["autopulse"]) if(autopulse != -1) autopulse = !autopulse @@ -260,10 +269,10 @@ a creative player the means to solve many problems. Circuits are held inside an return TRUE // Battery has enough. return FALSE // Not enough power. -/obj/item/integrated_circuit/proc/check_then_do_work() +/obj/item/integrated_circuit/proc/check_then_do_work(var/ignore_power = FALSE) if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam. return - if(power_draw_per_use) + if(power_draw_per_use && !ignore_power) if(!check_power()) power_fail() return diff --git a/code/modules/integrated_electronics/core/tools.dm b/code/modules/integrated_electronics/core/tools.dm index 8220162be72..a8759174411 100644 --- a/code/modules/integrated_electronics/core/tools.dm +++ b/code/modules/integrated_electronics/core/tools.dm @@ -160,7 +160,7 @@ data_to_show = A.name to_chat(user, "You write '[data_to_write ? data_to_show : "NULL"]' to the '[io]' pin of \the [io.holder].") else if(io.io_type == PULSE_CHANNEL) - io.holder.check_then_do_work() + io.holder.check_then_do_work(ignore_power = TRUE) to_chat(user, "You pulse \the [io.holder]'s [io].") io.holder.interact(user) // This is to update the UI. diff --git a/code/modules/integrated_electronics/subtypes/arithmetic.dm b/code/modules/integrated_electronics/subtypes/arithmetic.dm index c6134f9bd1d..059c699e502 100644 --- a/code/modules/integrated_electronics/subtypes/arithmetic.dm +++ b/code/modules/integrated_electronics/subtypes/arithmetic.dm @@ -1,9 +1,18 @@ //These circuits do simple math. /obj/item/integrated_circuit/arithmetic complexity = 1 - inputs = list("A","B","C","D","E","F","G","H") - outputs = list("result") - activators = list("compute") + inputs = list( + "\ A", + "\ B", + "\ C", + "\ D", + "\ E", + "\ F", + "\ G", + "\ H" + ) + outputs = list("\ result") + activators = list("\ compute", "\ on computed") category_text = "Arithmetic" autopulse = 1 power_draw_per_use = 5 // Math is pretty cheap. @@ -30,9 +39,9 @@ if(isnum(I.data)) result = result + I.data - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // -Subtracting- // @@ -58,9 +67,9 @@ if(isnum(I.data)) result = result - I.data - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // *Multiply* // @@ -86,9 +95,9 @@ if(isnum(I.data)) result = result * I.data - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // /Division/ // @@ -114,9 +123,9 @@ if(isnum(I.data) && I.data != 0) //No runtimes here. result = result / I.data - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) //^ Exponent ^// @@ -134,9 +143,9 @@ if(isnum(A.data) && isnum(B.data)) result = A.data ** B.data - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // +-Sign-+ // @@ -159,9 +168,9 @@ else result = 0 - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Round // @@ -183,9 +192,9 @@ else result = round(A.data) - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Absolute // @@ -204,9 +213,9 @@ if(isnum(I.data)) result = abs(I.data) - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Averaging // @@ -229,9 +238,9 @@ if(inputs_used) result = result / inputs_used - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Pi, because why the hell not? // /obj/item/integrated_circuit/arithmetic/pi @@ -242,9 +251,9 @@ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/pi/do_work() - var/datum/integrated_io/output/O = outputs[1] - O.data = 3.14159 - O.push_data() + set_pin_data(IC_OUTPUT, 1, 3.14159) + push_data() + activate_pin(2) // Random // /obj/item/integrated_circuit/arithmetic/random @@ -253,20 +262,20 @@ extended_desc = "'Inclusive' means that the upper bound is included in the range of numbers, e.g. L = 1 and H = 3 will allow \ for outputs of 1, 2, or 3. H being the higher number is not strictly required." icon_state = "random" - inputs = list("L","H") + inputs = list("\ L","\ H") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/random/do_work() var/result = 0 - var/datum/integrated_io/L = inputs[1] - var/datum/integrated_io/H = inputs[2] + var/L = get_pin_data(IC_INPUT, 1) + var/H = get_pin_data(IC_INPUT, 2) - if(isnum(L.data) && isnum(H.data)) - result = rand(L.data, H.data) + if(isnum(L) && isnum(H)) + result = rand(L, H) - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Square Root // @@ -274,7 +283,7 @@ name = "square root circuit" desc = "This outputs the square root of a number you put in." icon_state = "square_root" - inputs = list("A") + inputs = list("\ A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/square_root/do_work() @@ -284,9 +293,9 @@ if(isnum(I.data)) result = sqrt(I.data) - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // % Modulo % // @@ -294,17 +303,17 @@ name = "modulo circuit" desc = "Gets the remainder of A / B." icon_state = "modulo" - inputs = list("A", "B") + inputs = list("\ A", "\ B") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/modulo/do_work() var/result = 0 - var/datum/integrated_io/input/A = inputs[1] - var/datum/integrated_io/input/B = inputs[2] - if(isnum(A.data) && isnum(B.data) && B.data != 0) - result = A.data % B.data + var/A = get_pin_data(IC_INPUT, 1) + var/B = get_pin_data(IC_INPUT, 2) + if(isnum(A) && isnum(B) && B != 0) + result = A % B - for(var/datum/integrated_io/output/O in outputs) - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) diff --git a/code/modules/integrated_electronics/subtypes/converters.dm b/code/modules/integrated_electronics/subtypes/converters.dm index 9e04e24db51..431faa241f9 100644 --- a/code/modules/integrated_electronics/subtypes/converters.dm +++ b/code/modules/integrated_electronics/subtypes/converters.dm @@ -3,7 +3,7 @@ complexity = 2 inputs = list("input") outputs = list("output") - activators = list("convert") + activators = list("\ convert", "\ on convert") category_text = "Converter" autopulse = 1 power_draw_per_use = 10 @@ -16,89 +16,113 @@ name = "number to string" desc = "This circuit can convert a number variable into a string." icon_state = "num-string" + inputs = list("\ input") + outputs = list("\ output") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/num2text/do_work() var/result = null - var/datum/integrated_io/incoming = inputs[1] - var/datum/integrated_io/outgoing = outputs[1] - if(incoming.data && isnum(incoming.data)) - result = num2text(incoming.data) + pull_data() + var/incoming = get_pin_data(IC_INPUT, 1) + if(incoming && isnum(incoming)) + result = num2text(incoming) - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/text2num name = "string to number" desc = "This circuit can convert a string variable into a number." icon_state = "string-num" + inputs = list("\ input") + outputs = list("\ output") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/text2num/do_work() var/result = null - var/datum/integrated_io/incoming = inputs[1] - var/datum/integrated_io/outgoing = outputs[1] - if(incoming.data && istext(incoming.data)) - result = text2num(incoming.data) + pull_data() + var/incoming = get_pin_data(IC_INPUT, 1) + if(incoming && istext(incoming)) + result = text2num(incoming) - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/ref2text name = "reference to string" desc = "This circuit can convert a reference to something else to a string, specifically the name of that reference." icon_state = "ref-string" + inputs = list("\ input") + outputs = list("\ output") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/ref2text/do_work() var/result = null - var/datum/integrated_io/incoming = inputs[1] - var/datum/integrated_io/outgoing = outputs[1] - var/atom/A = incoming.data_as_type(/atom) - result = A && A.name + pull_data() + var/atom/A = get_pin_data(IC_INPUT, 1) + if(A && istype(A)) + result = A.name - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/lowercase name = "lowercase string converter" desc = "this will cause a string to come out in all lowercase." icon_state = "lowercase" + inputs = list("\ input") + outputs = list("\ output") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/lowercase/do_work() var/result = null - var/datum/integrated_io/incoming = inputs[1] - var/datum/integrated_io/outgoing = outputs[1] - if(incoming.data && istext(incoming.data)) - result = lowertext(incoming.data) + pull_data() + var/incoming = get_pin_data(IC_INPUT, 1) + if(incoming && istext(incoming)) + result = lowertext(incoming) - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/uppercase name = "uppercase string converter" desc = "THIS WILL CAUSE A STRING TO COME OUT IN ALL UPPERCASE." icon_state = "uppercase" + inputs = list("\ input") + outputs = list("\ output") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/uppercase/do_work() var/result = null - var/datum/integrated_io/incoming = inputs[1] - var/datum/integrated_io/outgoing = outputs[1] - if(incoming.data && istext(incoming.data)) - result = uppertext(incoming.data) + pull_data() + var/incoming = get_pin_data(IC_INPUT, 1) + if(incoming && istext(incoming)) + result = uppertext(incoming) - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/concatenatior name = "concatenatior" - desc = "This joins many strings together to get one big string." + desc = "This joins many strings or numbers together to get one big string." complexity = 4 - inputs = list("A","B","C","D","E","F","G","H") - outputs = list("result") - activators = list("concatenate") + inputs = list( + "\ A", + "\ B", + "\ C", + "\ D", + "\ E", + "\ F", + "\ G", + "\ H" + ) + outputs = list("\ result") + activators = list("\ concatenate", "\ on concatenated") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/concatenatior/do_work() @@ -107,70 +131,70 @@ I.pull_data() if(istext(I.data)) result = result + I.data + else if(!isnull(I.data) && num2text(I.data)) + result = result + num2text(I.data) var/datum/integrated_io/outgoing = outputs[1] outgoing.data = result outgoing.push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/radians2degrees name = "radians to degrees converter" desc = "Converts radians to degrees." - inputs = list("radian") - outputs = list("degrees") + inputs = list("\ radian") + outputs = list("\ degrees") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/radians2degrees/do_work() var/result = null - var/datum/integrated_io/incoming = inputs[1] - var/datum/integrated_io/outgoing = outputs[1] - incoming.pull_data() - if(incoming.data && isnum(incoming.data)) - result = ToDegrees(incoming.data) + pull_data() + var/incoming = get_pin_data(IC_INPUT, 1) + if(incoming && isnum(incoming)) + result = ToDegrees(incoming) - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/degrees2radians name = "degrees to radians converter" desc = "Converts degrees to radians." - inputs = list("degrees") - outputs = list("radians") + inputs = list("\ degrees") + outputs = list("\ radians") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/degrees2radians/do_work() var/result = null - var/datum/integrated_io/incoming = inputs[1] - var/datum/integrated_io/outgoing = outputs[1] - incoming.pull_data() - if(incoming.data && isnum(incoming.data)) - result = ToRadians(incoming.data) + pull_data() + var/incoming = get_pin_data(IC_INPUT, 1) + if(incoming && isnum(incoming)) + result = ToRadians(incoming) - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) /obj/item/integrated_circuit/converter/abs_to_rel_coords name = "abs to rel coordinate converter" desc = "Easily convert absolute coordinates to relative coordinates with this." complexity = 4 - inputs = list("X1 (abs)", "Y1 (abs)", "X2 (abs)", "Y2 (abs)") - outputs = list("X (rel)", "Y (rel)") - activators = list("compute rel coordinates") + inputs = list("\ X1", "\ Y1", "\ X2", "\ Y2") + outputs = list("\ X", "\ Y") + activators = list("\ compute rel coordinates", "\ on convert") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/abs_to_rel_coords/do_work() - var/datum/integrated_io/x1 = inputs[1] - var/datum/integrated_io/y1 = inputs[2] + var/x1 = get_pin_data(IC_INPUT, 1) + var/y1 = get_pin_data(IC_INPUT, 2) - var/datum/integrated_io/x2 = inputs[3] - var/datum/integrated_io/y2 = inputs[4] + var/x2 = get_pin_data(IC_INPUT, 3) + var/y2 = get_pin_data(IC_INPUT, 4) - var/datum/integrated_io/result_x = outputs[1] - var/datum/integrated_io/result_y = outputs[2] + if(x1 && y1 && x2 && y2) + set_pin_data(IC_OUTPUT, 1, x1 - x2) + set_pin_data(IC_OUTPUT, 2, y1 - y2) - if(x1.data && y1.data && x2.data && y2.data) - result_x.data = x1.data - x2.data - result_y.data = y1.data - y2.data - - for(var/datum/integrated_io/output/O in outputs) - O.push_data() \ No newline at end of file + push_data() + activate_pin(2) \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/input_output.dm b/code/modules/integrated_electronics/subtypes/input_output.dm index 6f7003ed948..456fae889f2 100644 --- a/code/modules/integrated_electronics/subtypes/input_output.dm +++ b/code/modules/integrated_electronics/subtypes/input_output.dm @@ -14,28 +14,27 @@ can_be_asked_input = 1 inputs = list() outputs = list() - activators = list("on pressed") + activators = list("\ on pressed") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/input/button/ask_for_input(mob/user) //Bit misleading name for this specific use. - var/datum/integrated_io/A = activators[1] - if(A.linked.len) - for(var/datum/integrated_io/activate/target in A.linked) - target.holder.check_then_do_work() to_chat(user, "You press the button labeled '[src.name]'.") + activate_pin(1) /obj/item/integrated_circuit/input/toggle_button name = "toggle button" desc = "It toggles on, off, on, off..." icon_state = "toggle_button" complexity = 1 + can_be_asked_input = 1 inputs = list() - outputs = list("on" = 0) - activators = list("on toggle") + outputs = list("\ on" = 0) + activators = list("\ on toggle") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/input/toggle_button/ask_for_input(mob/user) // Ditto. set_pin_data(IC_OUTPUT, 1, !get_pin_data(IC_OUTPUT, 1)) + push_data() activate_pin(1) to_chat(user, "You toggle the button labeled '[src.name]' [get_pin_data(IC_OUTPUT, 1) ? "on" : "off"].") @@ -46,19 +45,17 @@ complexity = 2 can_be_asked_input = 1 inputs = list() - outputs = list("number entered") - activators = list("on entered") + outputs = list("\ number entered") + activators = list("\ on entered") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 /obj/item/integrated_circuit/input/numberpad/ask_for_input(mob/user) var/new_input = input(user, "Enter a number, please.","Number pad") as null|num if(isnum(new_input) && CanInteract(user, physical_state)) - var/datum/integrated_io/O = outputs[1] - O.data = new_input - O.push_data() - var/datum/integrated_io/A = activators[1] - A.push_data() + set_pin_data(IC_OUTPUT, 1, new_input) + push_data() + activate_pin(1) /obj/item/integrated_circuit/input/textpad name = "text pad" @@ -67,49 +64,43 @@ complexity = 2 can_be_asked_input = 1 inputs = list() - outputs = list("string entered") - activators = list("on entered") + outputs = list("\ string entered") + activators = list("\ on entered") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 /obj/item/integrated_circuit/input/textpad/ask_for_input(mob/user) var/new_input = input(user, "Enter some words, please.","Number pad") as null|text if(istext(new_input) && CanInteract(user, physical_state)) - var/datum/integrated_io/O = outputs[1] - O.data = new_input - O.push_data() - var/datum/integrated_io/A = activators[1] - A.push_data() + set_pin_data(IC_OUTPUT, 1, new_input) + push_data() + activate_pin(1) /obj/item/integrated_circuit/input/med_scanner name = "integrated medical analyser" desc = "A very small version of the common medical analyser. This allows the machine to know how healthy someone is." icon_state = "medscan" complexity = 4 - inputs = list("target ref") - outputs = list("total health %", "total missing health") - activators = list("scan") + inputs = list("\ target") + outputs = list("\ total health %", "\ total missing health") + activators = list("\ scan", "\ on scanned") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) power_draw_per_use = 40 /obj/item/integrated_circuit/input/med_scanner/do_work() - var/datum/integrated_io/I = inputs[1] - var/mob/living/carbon/human/H = I.data_as_type(/mob/living/carbon/human) + var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human) if(!istype(H)) //Invalid input return if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range. var/total_health = round(H.health/H.getMaxHealth(), 0.1)*100 var/missing_health = H.getMaxHealth() - H.health - var/datum/integrated_io/total = outputs[1] - var/datum/integrated_io/missing = outputs[2] + set_pin_data(IC_OUTPUT, 1, total_health) + set_pin_data(IC_OUTPUT, 2, missing_health) - total.data = total_health - missing.data = missing_health - - for(var/datum/integrated_io/output/O in outputs) - O.push_data() + push_data() + activate_pin(2) /obj/item/integrated_circuit/input/adv_med_scanner name = "integrated advanced medical analyser" @@ -117,48 +108,39 @@ This type is much more precise, allowing the machine to know much more about the target than a normal analyzer." icon_state = "medscan_adv" complexity = 12 - inputs = list("target ref") + inputs = list("\ target") outputs = list( - "total health %", - "total missing health", - "brute damage", - "burn damage", - "tox damage", - "oxy damage", - "clone damage" + "\ total health %", + "\ total missing health", + "\ brute damage", + "\ burn damage", + "\ tox damage", + "\ oxy damage", + "\ clone damage" ) - activators = list("scan") + activators = list("\ scan", "\ on scanned") spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 4) power_draw_per_use = 80 /obj/item/integrated_circuit/input/adv_med_scanner/do_work() - var/datum/integrated_io/I = inputs[1] - var/mob/living/carbon/human/H = I.data_as_type(/mob/living/carbon/human) + var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human) if(!istype(H)) //Invalid input return if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range. var/total_health = round(H.health/H.getMaxHealth(), 0.1)*100 var/missing_health = H.getMaxHealth() - H.health - var/datum/integrated_io/total = outputs[1] - var/datum/integrated_io/missing = outputs[2] - var/datum/integrated_io/brute = outputs[3] - var/datum/integrated_io/burn = outputs[4] - var/datum/integrated_io/tox = outputs[5] - var/datum/integrated_io/oxy = outputs[6] - var/datum/integrated_io/clone = outputs[7] + set_pin_data(IC_OUTPUT, 1, total_health) + set_pin_data(IC_OUTPUT, 2, missing_health) + set_pin_data(IC_OUTPUT, 3, H.getBruteLoss()) + set_pin_data(IC_OUTPUT, 4, H.getFireLoss()) + set_pin_data(IC_OUTPUT, 5, H.getToxLoss()) + set_pin_data(IC_OUTPUT, 6, H.getOxyLoss()) + set_pin_data(IC_OUTPUT, 7, H.getCloneLoss()) - total.data = total_health - missing.data = missing_health - brute.data = H.getBruteLoss() - burn.data = H.getFireLoss() - tox.data = H.getToxLoss() - oxy.data = H.getOxyLoss() - clone.data = H.getCloneLoss() - - for(var/datum/integrated_io/output/O in outputs) - O.push_data() + push_data() + activate_pin(2) /obj/item/integrated_circuit/input/local_locator name = "local locator" @@ -222,9 +204,9 @@ Meaning the default frequency is expressed as 1457, not 145.7. To send a signal, pulse the 'send signal' activator pin." icon_state = "signal" complexity = 4 - inputs = list("frequency","code") + inputs = list("\ frequency","\ code") outputs = list() - activators = list("send signal","on signal received") + activators = list("\ send signal","\ on signal sent", "\ on signal received") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2) power_draw_idle = 5 @@ -237,11 +219,9 @@ /obj/item/integrated_circuit/input/signaler/initialize() ..() set_frequency(frequency) - var/datum/integrated_io/new_freq = inputs[1] - var/datum/integrated_io/new_code = inputs[2] // Set the pins so when someone sees them, they won't show as null - new_freq.data = frequency - new_code.data = code + set_pin_data(IC_INPUT, 1, frequency) + set_pin_data(IC_INPUT, 2, code) /obj/item/integrated_circuit/input/signaler/Destroy() if(radio_controller) @@ -250,12 +230,12 @@ . = ..() /obj/item/integrated_circuit/input/signaler/on_data_written() - var/datum/integrated_io/new_freq = inputs[1] - var/datum/integrated_io/new_code = inputs[2] - if(isnum(new_freq.data) && new_freq.data > 0) - set_frequency(new_freq.data) - if(isnum(new_code.data)) - code = new_code.data + var/new_freq = get_pin_data(IC_INPUT, 1) + var/new_code = get_pin_data(IC_INPUT, 2) + if(isnum(new_freq) && new_freq > 0) + set_frequency(new_freq) + if(isnum(new_code)) + code = new_code /obj/item/integrated_circuit/input/signaler/do_work() // Sends a signal. @@ -267,6 +247,7 @@ signal.encryption = code signal.data["message"] = "ACTIVATE" radio_connection.post_signal(src, signal) + activate_pin(2) /obj/item/integrated_circuit/input/signaler/proc/set_frequency(new_frequency) if(!frequency) @@ -280,11 +261,11 @@ radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT) /obj/item/integrated_circuit/input/signaler/receive_signal(datum/signal/signal) - var/datum/integrated_io/new_code = inputs[2] + var/new_code = get_pin_data(IC_INPUT, 2) var/code = 0 - if(isnum(new_code.data)) - code = new_code.data + if(isnum(new_code)) + code = new_code if(!signal) return 0 if(signal.encryption != code) @@ -292,8 +273,7 @@ if(signal.source == src) // Don't trigger ourselves. return 0 - var/datum/integrated_io/A = activators[2] - A.push_data() + activate_pin(3) for(var/mob/O in hearers(1, get_turf(src))) O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2) @@ -306,9 +286,9 @@ will pulse whatever's connected to it. Pulsing the first activation pin will send a message." icon_state = "signal" complexity = 4 - inputs = list("target EPv2 address", "data to send", "secondary text") - outputs = list("address received", "data received", "secondary text received") - activators = list("send data", "on data received") + inputs = list("\ target EPv2 address", "\ data to send", "\ secondary text") + outputs = list("\ address received", "\ data received", "\ secondary text received") + activators = list("\ send data", "\ on data received") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2, TECH_BLUESPACE = 2) power_draw_per_use = 50 @@ -318,7 +298,7 @@ ..() exonet = new(src) exonet.make_address("EPv2_circuit-\ref[src]") - desc += "
This circuit's EPv2 address is: [exonet.address]." + desc += "
This circuit's EPv2 address is: [exonet.address]" /obj/item/integrated_circuit/input/EPv2/Destroy() if(exonet) @@ -327,64 +307,60 @@ ..() /obj/item/integrated_circuit/input/EPv2/do_work() - var/datum/integrated_io/target_address = inputs[1] - var/datum/integrated_io/message = inputs[2] - var/datum/integrated_io/text = inputs[3] - if(istext(target_address.data)) - exonet.send_message(target_address.data, message.data, text.data) + var/target_address = get_pin_data(IC_INPUT, 1) + var/message = get_pin_data(IC_INPUT, 2) + var/text = get_pin_data(IC_INPUT, 3) + + if(target_address && istext(target_address)) + exonet.send_message(target_address, message, text) /obj/item/integrated_circuit/input/receive_exonet_message(var/atom/origin_atom, var/origin_address, var/message, var/text) - var/datum/integrated_io/message_received = outputs[1] - var/datum/integrated_io/data_received = outputs[2] - var/datum/integrated_io/text_received = outputs[3] + set_pin_data(IC_OUTPUT, 1, origin_address) + set_pin_data(IC_OUTPUT, 2, message) + set_pin_data(IC_OUTPUT, 3, text) - var/datum/integrated_io/A = activators[2] - A.push_data() - - message_received.write_data_to_pin(origin_address) - data_received.write_data_to_pin(message) - text_received.write_data_to_pin(text) - - for(var/datum/integrated_io/output/O in outputs) - O.push_data() + push_data() + activate_pin(2) //This circuit gives information on where the machine is. /obj/item/integrated_circuit/input/gps name = "global positioning system" desc = "This allows you to easily know the position of a machine containing this device." + extended_desc = "The GPS's coordinates it gives is absolute, not relative." icon_state = "gps" complexity = 4 inputs = list() - outputs = list("X (abs)", "Y (abs)") - activators = list("get coordinates") + outputs = list("\ X", "\ Y") + activators = list("\ get coordinates", "\ on get coordinates") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 30 /obj/item/integrated_circuit/input/gps/do_work() var/turf/T = get_turf(src) - var/datum/integrated_io/result_x = outputs[1] - var/datum/integrated_io/result_y = outputs[2] - result_x.data = null - result_y.data = null + set_pin_data(IC_OUTPUT, 1, null) + set_pin_data(IC_OUTPUT, 2, null) if(!T) return - result_x.data = T.x - result_y.data = T.y + set_pin_data(IC_OUTPUT, 1, T.x) + set_pin_data(IC_OUTPUT, 2, T.y) - for(var/datum/integrated_io/output/O in outputs) - O.push_data() + push_data() + activate_pin(2) /obj/item/integrated_circuit/input/microphone name = "microphone" desc = "Useful for spying on people or for voice activated machines." + extended_desc = "This will automatically translate most languages it hears to Galactic Common. \ + The first activation pin is always pulsed when the circuit hears someone talk, while the second one \ + is only triggered if it hears someone speaking a language other than Galactic Common." icon_state = "recorder" complexity = 8 inputs = list() - outputs = list("speaker \", "message \") - activators = list("on message received") + outputs = list("\ speaker", "\ message") + activators = list("\ on message received", "\ on translation") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 15 @@ -397,42 +373,45 @@ ..() /obj/item/integrated_circuit/input/microphone/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null) - var/datum/integrated_io/V = outputs[1] - var/datum/integrated_io/O = outputs[2] - var/datum/integrated_io/A = activators[1] + var/translated = FALSE if(M && msg) if(speaking) if(!speaking.machine_understands) msg = speaking.scramble(msg) - V.data = M.GetVoice() - O.data = msg - A.push_data() + if(!istype(speaking, /datum/language/common)) + translated = TRUE + set_pin_data(IC_OUTPUT, 1, M.GetVoice()) + set_pin_data(IC_OUTPUT, 2, msg) - for(var/datum/integrated_io/output/out in outputs) - out.push_data() - - A.push_data() + push_data() + activate_pin(1) + if(translated) + activate_pin(2) /obj/item/integrated_circuit/input/sensor name = "sensor" desc = "Scans and obtains a reference for any objects or persons near you. All you need to do is shove the machine in their face." + extended_desc = "If 'ignore storage' pin is set to 1, the sensor will disregard scanning various storage containers such as backpacks." icon_state = "recorder" complexity = 12 - inputs = list() - outputs = list("scanned ref \") - activators = list("on scanned") + inputs = list("\ ignore storage" = 1) + outputs = list("\ scanned") + activators = list("\ on scanned") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 120 -/obj/item/integrated_circuit/input/sensor/do_work() - // Because this gets called by attack(), all this needs to do is pulse the activator. - for(var/datum/integrated_io/output/O in outputs) - O.push_data() - var/datum/integrated_io/activate/A = activators[1] - A.push_data() +/obj/item/integrated_circuit/input/sensor/proc/scan(var/atom/A) + var/ignore_bags = get_pin_data(IC_INPUT, 1) + if(ignore_bags) + if(istype(A, /obj/item/weapon/storage)) + return FALSE + set_pin_data(IC_OUTPUT, 1, weakref(A)) + push_data() + activate_pin(1) + return TRUE /obj/item/integrated_circuit/output category_text = "Output" @@ -441,9 +420,9 @@ name = "small screen" desc = "This small screen can display a single piece of data, when the machine is examined closely." icon_state = "screen" - inputs = list("displayed data") + inputs = list("\ displayed data") outputs = list() - activators = list("load data") + activators = list("\ load data") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 10 autopulse = 1 @@ -497,7 +476,7 @@ complexity = 4 inputs = list() outputs = list() - activators = list("toggle light") + activators = list("\ toggle light") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH var/light_toggled = 0 var/light_brightness = 3 @@ -519,18 +498,18 @@ power_draw_idle = light_toggled ? light_brightness * 2 : 0 /obj/item/integrated_circuit/output/light/advanced/update_lighting() - var/datum/integrated_io/R = inputs[1] - var/datum/integrated_io/G = inputs[2] - var/datum/integrated_io/B = inputs[3] - var/datum/integrated_io/brightness = inputs[4] + var/R = get_pin_data(IC_INPUT, 1) + var/G = get_pin_data(IC_INPUT, 2) + var/B = get_pin_data(IC_INPUT, 3) + var/brightness = get_pin_data(IC_INPUT, 4) - if(isnum(R.data) && isnum(G.data) && isnum(B.data) && isnum(brightness.data)) - R.data = Clamp(R.data, 0, 255) - G.data = Clamp(G.data, 0, 255) - B.data = Clamp(B.data, 0, 255) - brightness.data = Clamp(brightness.data, 0, 6) - light_rgb = rgb(R.data, G.data, B.data) - light_brightness = brightness.data + if(isnum(R) && isnum(G) && isnum(B) && isnum(brightness)) + R = Clamp(R, 0, 255) + G = Clamp(G, 0, 255) + B = Clamp(B, 0, 255) + brightness = Clamp(brightness, 0, 6) + light_rgb = rgb(R, G, B) + light_brightness = brightness ..() @@ -544,10 +523,10 @@ icon_state = "light_adv" complexity = 8 inputs = list( - "R", - "G", - "B", - "Brightness" + "\ R", + "\ G", + "\ B", + "\ Brightness" ) outputs = list() spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH @@ -563,9 +542,9 @@ complexity = 8 cooldown_per_use = 4 SECONDS inputs = list( - "sound ID", - "volume", - "frequency" + "\ sound ID", + "\ volume", + "\ frequency" ) outputs = list() activators = list("play sound") diff --git a/code/modules/integrated_electronics/subtypes/logic.dm b/code/modules/integrated_electronics/subtypes/logic.dm index beb44bf5354..ee5a36785b8 100644 --- a/code/modules/integrated_electronics/subtypes/logic.dm +++ b/code/modules/integrated_electronics/subtypes/logic.dm @@ -4,7 +4,7 @@ extended_desc = "Logic circuits will treat a null, 0, and a \"\" string value as FALSE and anything else as TRUE." complexity = 3 outputs = list("result") - activators = list("compare", "on true result", "on false result") + activators = list("\ compare") category_text = "Logic" autopulse = 1 power_draw_per_use = 1 @@ -14,36 +14,39 @@ check_then_do_work() /obj/item/integrated_circuit/logic/do_work() - var/datum/integrated_io/O = outputs[1] - var/datum/integrated_io/T = activators[2] - var/datum/integrated_io/F = activators[3] - O.push_data() - if(O.data) - T.push_data() - else - F.push_data() + push_data() /obj/item/integrated_circuit/logic/binary - inputs = list("A","B") + inputs = list("\ A","\ B") + activators = list("\ compare", "\ on true result", "\ on false result") /obj/item/integrated_circuit/logic/binary/do_work() + pull_data() var/datum/integrated_io/A = inputs[1] var/datum/integrated_io/B = inputs[2] var/datum/integrated_io/O = outputs[1] O.data = do_compare(A, B) ? TRUE : FALSE + + if(get_pin_data(IC_OUTPUT, 1)) + activate_pin(2) + else + activate_pin(3) ..() /obj/item/integrated_circuit/logic/binary/proc/do_compare(var/datum/integrated_io/A, var/datum/integrated_io/B) return FALSE /obj/item/integrated_circuit/logic/unary - inputs = list("A") + inputs = list("\ A") + activators = list("\ compare", "\ on compare") /obj/item/integrated_circuit/logic/unary/do_work() + pull_data() var/datum/integrated_io/A = inputs[1] var/datum/integrated_io/O = outputs[1] O.data = do_check(A) ? TRUE : FALSE ..() + activate_pin(2) /obj/item/integrated_circuit/logic/unary/proc/do_check(var/datum/integrated_io/A) return FALSE @@ -125,6 +128,7 @@ desc = "This gate inverts what's fed into it." icon_state = "not" spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + activators = list("\ invert", "\ on inverted") /obj/item/integrated_circuit/logic/unary/not/do_check(var/datum/integrated_io/A) return !A.data diff --git a/code/modules/integrated_electronics/subtypes/manipulation.dm b/code/modules/integrated_electronics/subtypes/manipulation.dm index 65bae751e00..4ee51451790 100644 --- a/code/modules/integrated_electronics/subtypes/manipulation.dm +++ b/code/modules/integrated_electronics/subtypes/manipulation.dm @@ -11,12 +11,12 @@ complexity = 20 w_class = ITEMSIZE_NORMAL inputs = list( - "target X rel", - "target Y rel" + "\ target X rel", + "\ target Y rel" ) outputs = list() activators = list( - "fire" + "\ fire" ) var/obj/item/weapon/gun/installed_gun = null spawn_flags = IC_SPAWN_RESEARCH diff --git a/code/modules/integrated_electronics/subtypes/power.dm b/code/modules/integrated_electronics/subtypes/power.dm index 7b3256e06b9..3480a83a4a4 100644 --- a/code/modules/integrated_electronics/subtypes/power.dm +++ b/code/modules/integrated_electronics/subtypes/power.dm @@ -11,9 +11,9 @@ some power is lost due to ineffiency." w_class = ITEMSIZE_SMALL complexity = 16 - inputs = list("target ref") - outputs = list("target cell charge", "target cell max charge", "target cell percentage") - activators = list("transmit") + inputs = list("\ target") + outputs = list("\ target cell charge", "\ target cell max charge", "\ target cell percentage") + activators = list("\ transmit") spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 4, TECH_MAGNET = 3) power_draw_per_use = 500 // Inefficency has to come from somewhere. diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm index d0c26baf663..e3b69d31cd4 100644 --- a/code/modules/integrated_electronics/subtypes/reagents.dm +++ b/code/modules/integrated_electronics/subtypes/reagents.dm @@ -43,39 +43,39 @@ flags = OPENCONTAINER complexity = 20 cooldown_per_use = 6 SECONDS - inputs = list("target ref", "injection amount" = 5) + inputs = list("\ target", "\ injection amount" = 5) outputs = list() - activators = list("inject") + activators = list("\ inject") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH volume = 30 power_draw_per_use = 15 /obj/item/integrated_circuit/reagent/injector/proc/inject_amount() - var/datum/integrated_io/amount = inputs[2] - if(isnum(amount.data)) - return Clamp(amount.data, 0, 30) + var/amount = get_pin_data(IC_INPUT, 2) + if(isnum(amount)) + return Clamp(amount, 0, 30) /obj/item/integrated_circuit/reagent/injector/do_work() set waitfor = 0 // Don't sleep in a proc that is called by a processor without this set, otherwise it'll delay the entire thing - var/datum/integrated_io/target = inputs[1] - var/atom/movable/AM = target.data_as_type(/atom/movable) + var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable) if(!istype(AM)) //Invalid input return if(!reagents.total_volume) // Empty return if(AM.can_be_injected_by(src)) if(isliving(AM)) + var/mob/living/L = AM var/turf/T = get_turf(AM) - T.visible_message("[src] is trying to inject [AM]!") + T.visible_message("[src] is trying to inject [L]!") sleep(3 SECONDS) - if(!AM.can_be_injected_by(src)) + if(!L.can_be_injected_by(src)) return var/contained = reagents.get_reagents() - var/trans = reagents.trans_to_mob(target, inject_amount(), CHEM_BLOOD) - message_admins("[src] injected \the [AM] with [trans]u of [contained].") + var/trans = reagents.trans_to_mob(L, inject_amount(), CHEM_BLOOD) + message_admins("[src] injected \the [L] with [trans]u of [contained].") to_chat(AM, "You feel a tiny prick!") - visible_message("[src] injects [AM]!") + visible_message("[src] injects [L]!") else reagents.trans_to(AM, inject_amount()) @@ -88,9 +88,9 @@ outside the machine if it is next to the machine. Note that this cannot be used on entities." flags = OPENCONTAINER complexity = 8 - inputs = list("source ref", "target ref", "injection amount" = 10) + inputs = list("\ source", "\ target", "\ injection amount" = 10) outputs = list() - activators = list("transfer reagents") + activators = list("\ transfer reagents", "\ on transfer") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) var/transfer_amount = 10 @@ -103,10 +103,9 @@ transfer_amount = amount.data /obj/item/integrated_circuit/reagent/pump/do_work() - var/datum/integrated_io/A = inputs[1] - var/datum/integrated_io/B = inputs[2] - var/atom/movable/source = A.data_as_type(/atom/movable) - var/atom/movable/target = B.data_as_type(/atom/movable) + var/atom/movable/source = get_pin_data_as_type(IC_INPUT, 1, /atom/movable) + var/atom/movable/target = get_pin_data_as_type(IC_INPUT, 2, /atom/movable) + if(!istype(source) || !istype(target)) //Invalid input return var/turf/T = get_turf(src) @@ -117,10 +116,11 @@ return if(!source.is_open_container() || !target.is_open_container()) return - if(!source.reagents.get_free_space() || !target.reagents.get_free_space()) + if(!target.reagents.get_free_space()) return source.reagents.trans_to(target, transfer_amount) + activate_pin(2) /obj/item/integrated_circuit/reagent/storage name = "reagent storage" diff --git a/code/modules/integrated_electronics/subtypes/smart.dm b/code/modules/integrated_electronics/subtypes/smart.dm index c159522e974..a90a3f57a36 100644 --- a/code/modules/integrated_electronics/subtypes/smart.dm +++ b/code/modules/integrated_electronics/subtypes/smart.dm @@ -8,17 +8,16 @@ cannot see the target, it will not be able to calculate the correct direction." icon_state = "numberpad" complexity = 25 - inputs = list("target ref") - outputs = list("dir") - activators = list("calculate dir") + inputs = list("\ target") + outputs = list("\ dir") + activators = list("\ calculate dir", "\ on calculated") spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 5) power_draw_per_use = 40 /obj/item/integrated_circuit/smart/basic_pathfinder/do_work() var/datum/integrated_io/I = inputs[1] - var/datum/integrated_io/O = outputs[1] - O.data = null + set_pin_data(IC_OUTPUT, 1, null) if(!isweakref(I.data)) return @@ -28,6 +27,6 @@ if(!(A in view(get_turf(src)))) return // Can't see the target. var/desired_dir = get_dir(get_turf(src), A) - if(desired_dir) - O.data = desired_dir - O.push_data() \ No newline at end of file + + set_pin_data(IC_OUTPUT, 1, desired_dir) + push_data() \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/time.dm b/code/modules/integrated_electronics/subtypes/time.dm index 72766c0c48c..322ee2f9e09 100644 --- a/code/modules/integrated_electronics/subtypes/time.dm +++ b/code/modules/integrated_electronics/subtypes/time.dm @@ -12,16 +12,15 @@ This circuit is set to send a pulse after a delay of two seconds." icon_state = "delay-20" var/delay = 2 SECONDS - activators = list("incoming pulse","outgoing pulse") + activators = list("\ incoming","\ outgoing") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 2 /obj/item/integrated_circuit/time/delay/do_work() set waitfor = 0 // Don't sleep in a proc that is called by a processor. It'll delay the entire thing - var/datum/integrated_io/out_pulse = activators[2] sleep(delay) - out_pulse.push_data() + activate_pin(2) /obj/item/integrated_circuit/time/delay/five_sec name = "five-sec delay circuit" @@ -60,14 +59,13 @@ desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \ This circuit's delay can be customized, between 1/10th of a second to one hour. The delay is updated upon receiving a pulse." icon_state = "delay" - inputs = list("delay time") + inputs = list("\ delay time") spawn_flags = IC_SPAWN_RESEARCH /obj/item/integrated_circuit/time/delay/custom/do_work() - var/datum/integrated_io/delay_input = inputs[1] - if(delay_input.data && isnum(delay_input.data) ) - var/new_delay = min(delay_input.data, 1) - new_delay = max(new_delay, 36000) //An hour. + var/delay_input = get_pin_data(IC_INPUT, 1) + if(delay_input && isnum(delay_input) ) + var/new_delay = between(1, delay_input, 36000) //An hour. delay = new_delay ..() @@ -80,8 +78,8 @@ var/ticks_to_pulse = 4 var/ticks_completed = 0 var/is_running = FALSE - inputs = list("enable ticking") - activators = list("outgoing pulse") + inputs = list("\ enable ticking" = 0) + activators = list("\ outgoing pulse") spawn_flags = IC_SPAWN_RESEARCH power_draw_per_use = 4 @@ -91,8 +89,8 @@ . = ..() /obj/item/integrated_circuit/time/ticker/on_data_written() - var/datum/integrated_io/do_tick = inputs[1] - if(do_tick.data && !is_running) + var/do_tick = get_pin_data(IC_INPUT, 1) + if(do_tick && !is_running) is_running = TRUE processing_objects |= src else if(is_running) @@ -108,8 +106,7 @@ ticks_completed -= ticks_to_pulse else ticks_completed = 0 - var/datum/integrated_io/pulser = activators[1] - pulser.push_data() + activate_pin(1) /obj/item/integrated_circuit/time/ticker/fast name = "fast ticker" @@ -134,20 +131,16 @@ desc = "Tells you what the local time is, specific to your station or planet." icon_state = "clock" inputs = list() - outputs = list("time (string)", "hours (number)", "minutes (number)", "seconds (number)") + outputs = list("\ time", "\ hours", "\ minutes", "\ seconds") + activators = list("\ get time","\ on time got") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 /obj/item/integrated_circuit/time/clock/do_work() - var/datum/integrated_io/time = outputs[1] - var/datum/integrated_io/hour = outputs[2] - var/datum/integrated_io/min = outputs[3] - var/datum/integrated_io/sec = outputs[4] + set_pin_data(IC_OUTPUT, 1, time2text(station_time_in_ticks, "hh:mm:ss") ) + set_pin_data(IC_OUTPUT, 2, text2num(time2text(station_time_in_ticks, "hh") ) ) + set_pin_data(IC_OUTPUT, 3, text2num(time2text(station_time_in_ticks, "mm") ) ) + set_pin_data(IC_OUTPUT, 4, text2num(time2text(station_time_in_ticks, "ss") ) ) - time.data = time2text(station_time_in_ticks, "hh:mm:ss") - hour.data = text2num(time2text(station_time_in_ticks, "hh")) - min.data = text2num(time2text(station_time_in_ticks, "mm")) - sec.data = text2num(time2text(station_time_in_ticks, "ss")) - - for(var/datum/integrated_io/output/O in outputs) - O.push_data() \ No newline at end of file + push_data() + activate_pin(2) \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/trig.dm b/code/modules/integrated_electronics/subtypes/trig.dm index b1a19f4a406..72d779b6218 100644 --- a/code/modules/integrated_electronics/subtypes/trig.dm +++ b/code/modules/integrated_electronics/subtypes/trig.dm @@ -1,9 +1,18 @@ //These circuits do not-so-simple math. /obj/item/integrated_circuit/trig complexity = 1 - inputs = list("A","B","C","D","E","F","G","H") - outputs = list("result") - activators = list("compute") + inputs = list( + "\ A", + "\ B", + "\ C", + "\ D", + "\ E", + "\ F", + "\ G", + "\ H" + ) + outputs = list("\ result") + activators = list("\ compute", "\ on computed") category_text = "Trig" extended_desc = "Input and output are in degrees." autopulse = 1 @@ -19,19 +28,19 @@ name = "sin circuit" desc = "Has nothing to do with evil, unless you consider trigonometry to be evil. Outputs the sine of A." icon_state = "sine" - inputs = list("A") + inputs = list("\ A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/sine/do_work() + pull_data() var/result = null - var/datum/integrated_io/input/A = inputs[1] - A.pull_data() - if(isnum(A.data)) - result = sin(A.data) + var/A = get_pin_data(IC_INPUT, 1) + if(isnum(A)) + result = sin(A) - var/datum/integrated_io/output/O = outputs[1] - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Cosine // @@ -39,19 +48,19 @@ name = "cos circuit" desc = "Outputs the cosine of A." icon_state = "cosine" - inputs = list("A") + inputs = list("\ A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/cosine/do_work() + pull_data() var/result = null - var/datum/integrated_io/input/A = inputs[1] - A.pull_data() - if(isnum(A.data)) - result = cos(A.data) + var/A = get_pin_data(IC_INPUT, 1) + if(isnum(A)) + result = cos(A) - var/datum/integrated_io/output/O = outputs[1] - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Tangent // @@ -59,19 +68,19 @@ name = "tan circuit" desc = "Outputs the tangent of A. Guaranteed to not go on a tangent about its existance." icon_state = "tangent" - inputs = list("A") + inputs = list("\ A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/tangent/do_work() + pull_data() var/result = null - var/datum/integrated_io/input/A = inputs[1] - A.pull_data() - if(isnum(A.data)) - result = Tan(A.data) + var/A = get_pin_data(IC_INPUT, 1) + if(isnum(A)) + result = Tan(A) - var/datum/integrated_io/output/O = outputs[1] - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Cosecant // @@ -79,19 +88,19 @@ name = "csc circuit" desc = "Outputs the cosecant of A." icon_state = "cosecant" - inputs = list("A") + inputs = list("\ A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/cosecant/do_work() + pull_data() var/result = null - var/datum/integrated_io/input/A = inputs[1] - A.pull_data() - if(isnum(A.data)) - result = Csc(A.data) + var/A = get_pin_data(IC_INPUT, 1) + if(isnum(A)) + result = Csc(A) - var/datum/integrated_io/output/O = outputs[1] - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Secant // @@ -100,19 +109,19 @@ name = "sec circuit" desc = "Outputs the secant of A. Has nothing to do with the security department." icon_state = "secant" - inputs = list("A") + inputs = list("\ A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/secant/do_work() + pull_data() var/result = null - var/datum/integrated_io/input/A = inputs[1] - A.pull_data() - if(isnum(A.data)) - result = Sec(A.data) + var/A = get_pin_data(IC_INPUT, 1) + if(isnum(A)) + result = Sec(A) - var/datum/integrated_io/output/O = outputs[1] - O.data = result - O.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) // Cotangent // @@ -121,16 +130,16 @@ name = "cot circuit" desc = "Outputs the cotangent of A." icon_state = "cotangent" - inputs = list("A") + inputs = list("\ A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/cotangent/do_work() + pull_data() var/result = null - var/datum/integrated_io/input/A = inputs[1] - A.pull_data() - if(isnum(A.data)) - result = Cot(A.data) + var/A = get_pin_data(IC_INPUT, 1) + if(isnum(A)) + result = Cot(A) - var/datum/integrated_io/output/O = outputs[1] - O.data = result - O.push_data() \ No newline at end of file + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) \ No newline at end of file diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 07562ad190d..4384151cbd4 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -212,7 +212,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set name = "Ghost" set desc = "Relinquish your life and enter the land of the dead." - if(stat == DEAD) + if(stat == DEAD && !forbid_seeing_deadchat) announce_ghost_joinleave(ghostize(1)) else var/response @@ -223,7 +223,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return src.client.admin_ghost() else - response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost, you won't be able to play this round for another 30 minutes! You can't change your mind so choose wisely!)", "Are you sure you want to ghost?", "Ghost", "Stay in body") + response = alert(src, "Are you -sure- you want to ghost?\n(You are alive, or otherwise have the potential to become alive. If you ghost, you won't be able to play this round until you respawn as a new character! You can't change your mind so choose wisely!)", "Are you sure you want to ghost?", "Ghost", "Stay in body") if(response != "Ghost") return resting = 1 diff --git a/code/modules/mob/freelook/ai/eye.dm b/code/modules/mob/freelook/ai/eye.dm index 7b0cbde24e0..62f0d931520 100644 --- a/code/modules/mob/freelook/ai/eye.dm +++ b/code/modules/mob/freelook/ai/eye.dm @@ -43,7 +43,7 @@ /mob/living/silicon/ai/proc/create_eyeobj(var/newloc) if(eyeobj) destroy_eyeobj() if(!newloc) newloc = src.loc - eyeobj = PoolOrNew(/mob/observer/eye/aiEye, newloc) + eyeobj = new /mob/observer/eye/aiEye(newloc) eyeobj.owner = src eyeobj.name = "[src.name] (AI Eye)" // Give it a name if(client) client.eye = eyeobj diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm index fdb0b012ef8..3a451bff448 100644 --- a/code/modules/mob/hear_say.dm +++ b/code/modules/mob/hear_say.dm @@ -101,7 +101,7 @@ /mob/living/silicon/ai/special_mentions() return list("AI") // AI door! -// Converts specific characters, like *, |, and _ to formatted output. +// Converts specific characters, like +, |, and _ to formatted output. /mob/proc/say_emphasis(var/message) message = encode_html_emphasis(message, "|", "i") message = encode_html_emphasis(message, "+", "b") diff --git a/code/modules/mob/language/station.dm b/code/modules/mob/language/station.dm index b1411f2faef..44e0d002808 100644 --- a/code/modules/mob/language/station.dm +++ b/code/modules/mob/language/station.dm @@ -60,7 +60,7 @@ flags = WHITELISTED syllables = list("mrr","rr","tajr","kir","raj","kii","mir","kra","ahk","nal","vah","khaz","jri","ran","darr", "mi","jri","dynh","manq","rhe","zar","rrhaz","kal","chur","eech","thaa","dra","jurl","mah","sanu","dra","ii'r", - "ka","aasi","far","wa","baq","ara","qara","zir","sam","mak","hrar","nja","rir","khan","jun","dar","rik","kah", + "ka","aasi","far","wa","baq","ara","qara","zir","saam","mak","hrar","nja","rir","khan","jun","dar","rik","kah", "hal","ket","jurl","mah","tul","cresh","azu","ragh","mro","mra","mrro","mrra") /datum/language/tajaran/get_random_name(var/gender) diff --git a/code/modules/mob/living/bot/floorbot.dm b/code/modules/mob/living/bot/floorbot.dm index 323d2909fb7..a843206e5e1 100644 --- a/code/modules/mob/living/bot/floorbot.dm +++ b/code/modules/mob/living/bot/floorbot.dm @@ -221,7 +221,7 @@ if(building == 1) I = new /obj/item/stack/tile/floor(src) else - I = PoolOrNew(/obj/item/stack/rods, src) + I = new /obj/item/stack/rods(src) A.attackby(I, src) target = null busy = 0 diff --git a/code/modules/mob/living/bot/mulebot.dm b/code/modules/mob/living/bot/mulebot.dm index 2079f77a35e..ead145e3881 100644 --- a/code/modules/mob/living/bot/mulebot.dm +++ b/code/modules/mob/living/bot/mulebot.dm @@ -268,8 +268,8 @@ var/turf/Tsec = get_turf(src) new /obj/item/device/assembly/prox_sensor(Tsec) - PoolOrNew(/obj/item/stack/rods, Tsec) - PoolOrNew(/obj/item/stack/rods, Tsec) + new /obj/item/stack/rods(Tsec) + new /obj/item/stack/rods(Tsec) new /obj/item/stack/cable_coil/cut(Tsec) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread diff --git a/code/modules/mob/living/carbon/give.dm b/code/modules/mob/living/carbon/give.dm index 14c8efbbadd..6b07140211f 100644 --- a/code/modules/mob/living/carbon/give.dm +++ b/code/modules/mob/living/carbon/give.dm @@ -1,11 +1,11 @@ -/mob/living/carbon/human/verb/give(var/mob/living/target in view(1)-usr) +/mob/living/carbon/human/verb/give(var/mob/living/carbon/target in view(1)-usr) set category = "IC" set name = "Give" // TODO : Change to incapacitated() on merge. - if(src.stat || src.lying || src.resting || src.buckled) + if(src.stat || src.lying || src.resting || src.handcuffed) return - if(!istype(target) || target.stat || target.lying || target.resting || target.buckled || target.client == null) + if(!istype(target) || target.stat || target.lying || target.resting || target.handcuffed || target.client == null) return var/obj/item/I = src.get_active_hand() diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index ee0c867ffb6..b4a47d2e47f 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -41,6 +41,13 @@ species.handle_death(src) animate_tail_stop() + //Handle snowflake ling stuff. + if(mind && mind.changeling) + // If the ling is capable of revival, don't allow them to see deadchat. + if(mind.changeling.chem_charges >= CHANGELING_STASIS_COST) + if(mind.changeling.max_geneticpoints >= 0) // Absorbed lings don't count, as they can't revive. + forbid_seeing_deadchat = TRUE + //Handle brain slugs. var/obj/item/organ/external/Hd = get_organ(BP_HEAD) var/mob/living/simple_animal/borer/B diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 5bdea526652..66abc50cabe 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1497,3 +1497,11 @@ /mob/living/carbon/human/is_muzzled() return (wear_mask && (istype(wear_mask, /obj/item/clothing/mask/muzzle) || istype(src.wear_mask, /obj/item/weapon/grenade))) +// Called by job_controller. Makes drones start with a permit, might be useful for other people later too. +/mob/living/carbon/human/equip_post_job() + var/braintype = get_FBP_type() + if(braintype == FBP_DRONE) + var/turf/T = get_turf(src) + var/obj/item/weapon/permit/drone/permit = new(T) + permit.set_name(real_name) + equip_to_appropriate_slot(permit) // If for some reason it can't find room, it'll still be on the floor. \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 5c895d43ae0..963bab63673 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -207,7 +207,7 @@ miss_type = 1 if(prob(80)) - hit_zone = ran_zone(hit_zone) + hit_zone = ran_zone(hit_zone, 70) //70% chance to hit what you're aiming at seems fair? if(prob(15) && hit_zone != BP_TORSO) // Missed! if(!src.lying) attack_message = "[H] attempted to strike [src], but missed!" @@ -248,13 +248,13 @@ rand_damage *= 2 real_damage = max(1, real_damage) - var/armour = run_armor_check(affecting, "melee") - var/soaked = get_armor_soak(affecting, "melee") + var/armour = run_armor_check(hit_zone, "melee") + var/soaked = get_armor_soak(hit_zone, "melee") // Apply additional unarmed effects. attack.apply_effects(H, src, armour, rand_damage, hit_zone) // Finally, apply damage to target - apply_damage(real_damage, (attack.deal_halloss ? HALLOSS : BRUTE), affecting, armour, soaked, sharp=attack.sharp, edge=attack.edge) + apply_damage(real_damage, (attack.deal_halloss ? HALLOSS : BRUTE), hit_zone, armour, soaked, sharp=attack.sharp, edge=attack.edge) if(I_DISARM) M.attack_log += text("\[[time_stamp()]\] Disarmed [src.name] ([src.ckey])") diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 02d85bbcfaf..30ee7c64d6e 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -185,6 +185,26 @@ wearing_rig.notify_ai("Warning: user consciousness failure. Mobility control passed to integrated intelligence system.") ..() +/mob/living/carbon/human/proc/Stasis(amount) + if((species.flags & NO_SCAN) || isSynthetic()) + in_stasis = 0 + else + in_stasis = amount + +/mob/living/carbon/human/proc/getStasis() + if((species.flags & NO_SCAN) || isSynthetic()) + return 0 + + return in_stasis + +//This determines if, RIGHT NOW, the life() tick is being skipped due to stasis +/mob/living/carbon/human/proc/inStasisNow() + var/stasisValue = getStasis() + if(stasisValue && (life_tick % stasisValue)) + return 1 + + return 0 + /mob/living/carbon/human/getCloneLoss() if((species.flags & NO_SCAN) || isSynthetic()) cloneloss = 0 diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 7682f675b08..cb49001d3c9 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -90,6 +90,24 @@ return 0 +// Returns a string based on what kind of brain the FBP has. +/mob/living/carbon/human/proc/get_FBP_type() + if(!isSynthetic()) + return FBP_NONE + var/obj/item/organ/internal/brain/B + B = internal_organs_by_name[O_BRAIN] + if(B) // Incase we lost our brain for some reason, like if we got decapped. + if(istype(B, /obj/item/organ/internal/mmi_holder)) + var/obj/item/organ/internal/mmi_holder/mmi_holder = B + if(istype(mmi_holder.stored_mmi, /obj/item/device/mmi/digital/posibrain)) + return FBP_POSI + else if(istype(mmi_holder.stored_mmi, /obj/item/device/mmi/digital/robot)) + return FBP_DRONE + else if(istype(mmi_holder.stored_mmi, /obj/item/device/mmi)) // This needs to come last because inheritence. + return FBP_CYBORG + + return FBP_NONE + #undef HUMAN_EATING_NO_ISSUE #undef HUMAN_EATING_NO_MOUTH #undef HUMAN_EATING_BLOCKED_MOUTH diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index ba590f92bc4..98f8f81d9c7 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -13,9 +13,11 @@ handle_embedded_objects() //Moving with objects stuck in you can cause bad times. if(force_max_speed) - return -3 // Returning -1 will actually result in a slowdown for Teshari. + return -3 for(var/datum/modifier/M in modifiers) + if(!isnull(M.haste) && M.haste == TRUE) + return -3 // Returning -1 will actually result in a slowdown for Teshari. if(!isnull(M.slowdown)) tally += M.slowdown @@ -84,9 +86,7 @@ if(T && T.movement_cost) tally += T.movement_cost - if(species.item_slowdown_halved) - if(item_tally > 0) - item_tally *= 0.5 + item_tally *= species.item_slowdown_mod tally += item_tally diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 7ce62e1ae9a..2738686c38a 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -62,8 +62,12 @@ voice = GetVoice() + var/stasis = inStasisNow() + if(getStasis() > 2) + Sleeping(20) + //No need to update all of these procs if the guy is dead. - if(stat != DEAD && !in_stasis) + if(stat != DEAD && !stasis) //Updates the number of stored chemicals for powers handle_changeling() @@ -82,7 +86,6 @@ if(!client) species.handle_npc(src) - if(!handle_some_updates()) return //We go ahead and process them 5 times for HUD images and other stuff though. @@ -97,7 +100,7 @@ return 1 /mob/living/carbon/human/breathe() - if(!in_stasis) + if(!inStasisNow()) ..() // Calculate how vulnerable the human is to under- and overpressure. @@ -207,7 +210,7 @@ /mob/living/carbon/human/handle_mutations_and_radiation() - if(in_stasis) + if(inStasisNow()) return if(getFireLoss()) @@ -789,7 +792,7 @@ /mob/living/carbon/human/handle_chemicals_in_body() - if(in_stasis) + if(inStasisNow()) return if(reagents) @@ -1339,7 +1342,7 @@ if(!druggy && !seer) see_invisible = SEE_INVISIBLE_LIVING /mob/living/carbon/human/handle_random_events() - if(in_stasis) + if(inStasisNow()) return // Puke if toxloss is too high diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 8a8650aa9ba..f547cba9fcb 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -133,7 +133,7 @@ var/appearance_flags = 0 // Appearance/display related features. var/spawn_flags = 0 // Flags that specify who can spawn as this species var/slowdown = 0 // Passive movement speed malus (or boost, if negative) - var/item_slowdown_halved = 0 // If this is on, they're not as affected by item weights for slowdown + var/item_slowdown_mod = 1 // How affected by item slowdown the species is. var/primitive_form // Lesser form, if any (ie. monkey for humans) var/greater_form // Greater form, if any, ie. human for monkeys. var/holder_type diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index c88c1c1028a..e49236af940 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -37,7 +37,7 @@ brute_mod = 0.85 burn_mod = 0.85 metabolic_rate = 0.85 - item_slowdown_halved = 1 + item_slowdown_mod = 0.5 num_alternate_languages = 3 secondary_langs = list(LANGUAGE_UNATHI) name_language = LANGUAGE_UNATHI @@ -256,6 +256,7 @@ secondary_langs = list(LANGUAGE_ROOTGLOBAL) name_language = LANGUAGE_ROOTLOCAL health_hud_intensity = 2.5 + item_slowdown_mod = 0.25 min_age = 1 max_age = 300 diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index a84a2889dc5..1924bd5e78f 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -131,10 +131,11 @@ Please contact me on #coderbus IRC. ~Carn x #define LEGCUFF_LAYER 23 #define L_HAND_LAYER 24 #define R_HAND_LAYER 25 -#define FIRE_LAYER 26 //If you're on fire -#define WATER_LAYER 27 //If you're submerged in water. -#define TARGETED_LAYER 28 //BS12: Layer for the target overlay from weapon targeting system -#define TOTAL_LAYERS 29 +#define MODIFIER_EFFECTS_LAYER 26 +#define FIRE_LAYER 27 //If you're on fire +#define WATER_LAYER 28 //If you're submerged in water. +#define TARGETED_LAYER 29 //BS12: Layer for the target overlay from weapon targeting system +#define TOTAL_LAYERS 30 ////////////////////////////////// /mob/living/carbon/human @@ -1118,6 +1119,18 @@ var/global/list/damage_icon_parts = list() if(update_icons) update_icons() +/mob/living/carbon/human/update_modifier_visuals(var/update_icons=1) + overlays_standing[MODIFIER_EFFECTS_LAYER] = null + var/image/effects = new() + for(var/datum/modifier/M in modifiers) + if(M.mob_overlay_state) + var/image/I = image("icon" = 'icons/mob/modifier_effects.dmi', "icon_state" = M.mob_overlay_state) + effects.overlays += I + + overlays_standing[MODIFIER_EFFECTS_LAYER] = effects + + if(update_icons) + update_icons() /mob/living/carbon/human/update_fire(var/update_icons=1) overlays_standing[FIRE_LAYER] = null diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 9e99a09d527..0b47ba7870f 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -958,6 +958,11 @@ default behaviour is: update_icons() return canmove +// Adds overlays for specific modifiers. +// You'll have to add your own implementation for non-humans currently, just override this proc. +/mob/living/proc/update_modifier_visuals() + return + /mob/living/proc/update_water() // Involves overlays for humans. Maybe we'll get submerged sprites for borgs in the future? return @@ -965,3 +970,7 @@ default behaviour is: if(isSynthetic()) return FALSE return TRUE + +// Called by job_controller. +/mob/living/proc/equip_post_job() + return diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index b60ff078a3c..66e1278e225 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -439,3 +439,11 @@ hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1) //hud_used.SetButtonCoords(hud_used.hide_actions_toggle,button_number+1) client.screen += hud_used.hide_actions_toggle + +// Returns a number to determine if something is harder or easier to hit than normal. +/mob/living/proc/get_evasion() + var/result = evasion // First we get the 'base' evasion. Generally this is zero. + for(var/datum/modifier/M in modifiers) + if(!isnull(M.evasion)) + result += M.evasion + return result diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 1aef4eca81e..80c0dbc505a 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -141,7 +141,7 @@ proc/get_radio_key_from_channel(var/channel) //Redirect to say_dead if talker is dead if(stat) - if(stat == DEAD) + if(stat == DEAD && !forbid_seeing_deadchat) return say_dead(message) return @@ -308,7 +308,7 @@ proc/get_radio_key_from_channel(var/channel) if(M && src) //If we still exist, when the spawn processes var/dst = get_dist(get_turf(M),get_turf(src)) - if(dst <= message_range || M.stat == DEAD) //Inside normal message range, or dead with ears (handled in the view proc) + if(dst <= message_range || (M.stat == DEAD && !forbid_seeing_deadchat)) //Inside normal message range, or dead with ears (handled in the view proc) M << speech_bubble M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol) diff --git a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm index 26e1b264fda..9a5bd4e574c 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm @@ -80,7 +80,7 @@ time_last_drone = world.time if(player.mob && player.mob.mind) player.mob.mind.reset() - var/mob/living/silicon/robot/drone/new_drone = PoolOrNew(drone_type, get_turf(src)) + var/mob/living/silicon/robot/drone/new_drone = new drone_type(get_turf(src)) new_drone.transfer_personality(player) new_drone.master_fabricator = src diff --git a/code/modules/mob/living/simple_animal/aliens/drone.dm b/code/modules/mob/living/simple_animal/aliens/drone.dm index 06de6b4d141..186afd6ed32 100644 --- a/code/modules/mob/living/simple_animal/aliens/drone.dm +++ b/code/modules/mob/living/simple_animal/aliens/drone.dm @@ -176,16 +176,16 @@ step_to(O, get_turf(pick(view(7, src)))) //rods - O = PoolOrNew(/obj/item/stack/rods, src.loc) + O = new /obj/item/stack/rods(src.loc) step_to(O, get_turf(pick(view(7, src)))) if(prob(75)) - O = PoolOrNew(/obj/item/stack/rods, src.loc) + O = new /obj/item/stack/rods(src.loc) step_to(O, get_turf(pick(view(7, src)))) if(prob(50)) - O = PoolOrNew(/obj/item/stack/rods, src.loc) + O = new /obj/item/stack/rods(src.loc) step_to(O, get_turf(pick(view(7, src)))) if(prob(25)) - O = PoolOrNew(/obj/item/stack/rods, src.loc) + O = new /obj/item/stack/rods(src.loc) step_to(O, get_turf(pick(view(7, src)))) //plasteel diff --git a/code/modules/mob/living/simple_animal/animals/giant_spider.dm b/code/modules/mob/living/simple_animal/animals/giant_spider.dm index acb1d7a1b79..e2c833000ec 100644 --- a/code/modules/mob/living/simple_animal/animals/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/animals/giant_spider.dm @@ -103,7 +103,7 @@ if(istype(I, /obj/effect/spider/eggcluster)) eggcount ++ if(!eggcount) - var/eggs = PoolOrNew(/obj/effect/spider/eggcluster/small, list(O, src)) + var/eggs = new /obj/effect/spider/eggcluster/small(O, src) O.implants += eggs H << "The [src] injects something into your [O.name]!" @@ -172,7 +172,7 @@ if(busy == LAYING_EGGS) E = locate() in get_turf(src) if(!E) - PoolOrNew(/obj/effect/spider/eggcluster, list(loc, src)) + new /obj/effect/spider/eggcluster(loc, src) fed-- busy = 0 stop_automated_movement = 0 diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 1901902c80d..a63590acf8b 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -207,3 +207,4 @@ var/list/active_genes=list() var/mob_size = MOB_MEDIUM + var/forbid_seeing_deadchat = FALSE // Used for lings to not see deadchat, and to have ghosting behave as if they were not really dead. diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 4327840a478..ba5b24dbe70 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -390,10 +390,16 @@ proc/is_blind(A) else name = realname + if(subject && subject.forbid_seeing_deadchat && !subject.client.holder) + return // Can't talk in deadchat if you can't see it. + for(var/mob/M in player_list) if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && !is_mentor(M.client))) && M.is_preference_enabled(/datum/client_preference/show_dsay)) var/follow var/lname + if(M.forbid_seeing_deadchat && !M.client.holder) + continue + if(subject) if(M.is_key_ignored(subject.client.key)) // If we're ignored, do nothing. continue diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 476a8b68105..a553d4309ca 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -199,7 +199,7 @@ if(S.victim == mob) return - if(mob.stat==DEAD && isliving(mob)) + if(mob.stat==DEAD && isliving(mob) && !mob.forbid_seeing_deadchat) mob.ghostize() return diff --git a/code/modules/mob/modifiers.dm b/code/modules/mob/modifiers.dm index 6ba148916e3..f67ffc374b6 100644 --- a/code/modules/mob/modifiers.dm +++ b/code/modules/mob/modifiers.dm @@ -7,6 +7,7 @@ var/desc = null // Ditto. var/icon_state = null // See above. var/mob/living/holder = null // The mob that this datum is affecting. + var/weakref/origin = null // A weak reference to whatever caused the modifier to appear. THIS NEEDS TO BE A MOB/LIVING. It's a weakref to not interfere with qdel(). var/expire_at = null // world.time when holder's Life() will remove the datum. If null, it lasts forever or until it gets deleted by something else. var/on_created_text = null // Text to show to holder upon being created. var/on_expired_text = null // Text to show to holder when it expires. @@ -14,6 +15,11 @@ var/stacks = MODIFIER_STACK_FORBID // If true, attempts to add a second instance of this type will refresh expire_at instead. var/flags = 0 // Flags for the modifier, see mobs.dm defines for more details. + var/light_color = null // If set, the mob possessing the modifier will glow in this color. Not implemented yet. + var/light_range = null // How far the light for the above var goes. Not implemented yet. + var/light_intensity = null // Ditto. Not implemented yet. + var/mob_overlay_state = null // Icon_state for an overlay to apply to a (human) mob while this exists. This is actually implemented. + // Now for all the different effects. // Percentage modifiers are expressed as a multipler. (e.g. +25% damage should be written as 1.25) var/max_health_flat // Adjusts max health by a flat (e.g. +20) amount. Note this is added to base health. @@ -29,9 +35,15 @@ var/incoming_healing_percent // Adjusts amount of healing received. var/outgoing_melee_damage_percent // Adjusts melee damage inflicted by holder by a percentage. Affects attacks by melee weapons and hand-to-hand. var/slowdown // Negative numbers speed up, positive numbers slow down movement. + var/haste // If set to 1, the mob will be 'hasted', which makes it ignore slowdown and go really fast. + var/evasion // Positive numbers reduce the odds of being hit by 15% each. Negative numbers increase the odds. -/datum/modifier/New(var/new_holder) +/datum/modifier/New(var/new_holder, var/new_origin) holder = new_holder + if(new_origin) + origin = weakref(new_origin) + else // We assume the holder caused the modifier if not told otherwise. + origin = weakref(holder) ..() // Checks to see if this datum should continue existing. @@ -44,12 +56,18 @@ to_chat(holder, on_expired_text) on_expire() holder.modifiers.Remove(src) + if(mob_overlay_state) // We do this after removing ourselves from the list so that the overlay won't remain. + holder.update_modifier_visuals() qdel(src) // Override this for special effects when it gets removed. /datum/modifier/proc/on_expire() return +// Called every Life() tick. Override for special behaviour. +/datum/modifier/proc/tick() + return + /mob/living var/list/modifiers = list() // A list of modifier datums, which can adjust certain mob numbers. @@ -64,13 +82,17 @@ // Get rid of anything we shouldn't have. for(var/datum/modifier/M in modifiers) M.check_if_valid() + // Remaining modifiers will now receive a tick(). This is in a second loop for safety in order to not tick() an expired modifier. + for(var/datum/modifier/M in modifiers) + M.tick() // Call this to add a modifier to a mob. First argument is the modifier type you want, second is how long it should last, in ticks. +// Third argument is the 'source' of the modifier, if it's from someone else. If null, it will default to the mob being applied to. // The SECONDS/MINUTES macro is very helpful for this. E.g. M.add_modifier(/datum/modifier/example, 5 MINUTES) -/mob/living/proc/add_modifier(var/modifier_type, var/expire_at = null) +/mob/living/proc/add_modifier(var/modifier_type, var/expire_at = null, var/mob/living/origin = null) // First, check if the mob already has this modifier. for(var/datum/modifier/M in modifiers) - if(ispath(modifier_type, M.type)) + if(istype(modifier_type, M)) switch(M.stacks) if(MODIFIER_STACK_FORBID) return // Stop here. @@ -83,12 +105,16 @@ return // If we're at this point, the mob doesn't already have it, or it does but stacking is allowed. - var/datum/modifier/mod = new modifier_type(src) + var/datum/modifier/mod = new modifier_type(src, origin) if(expire_at) mod.expire_at = world.time + expire_at if(mod.on_created_text) to_chat(src, mod.on_created_text) modifiers.Add(mod) + if(mod.mob_overlay_state) + update_modifier_visuals() + + return mod // Removes a specific instance of modifier /mob/living/proc/remove_specific_modifier(var/datum/modifier/M, var/silent = FALSE) @@ -97,10 +123,17 @@ // Removes all modifiers of a type /mob/living/proc/remove_modifiers_of_type(var/modifier_type, var/silent = FALSE) for(var/datum/modifier/M in modifiers) - if(ispath(modifier_type, M.type)) + if(istype(M, modifier_type)) M.expire(silent) // Removes all modifiers, useful if the mob's being deleted /mob/living/proc/remove_all_modifiers(var/silent = FALSE) for(var/datum/modifier/M in modifiers) - M.expire(silent) \ No newline at end of file + M.expire(silent) + +// Checks if the mob has a modifier type. +/mob/living/proc/has_modifier_of_type(var/modifier_type) + for(var/datum/modifier/M in modifiers) + if(istype(M, modifier_type)) + return TRUE + return FALSE \ No newline at end of file diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index f6679a6dfea..04e45f93d0b 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -206,6 +206,10 @@ icon_state = "hair_bobcut" species_allowed = list("Human","Unathi") + bobcutalt + name = "Chin Length Bob" + icon_state = "hair_bobcutalt" + bun name = "Bun" icon_state = "hair_bun" @@ -361,6 +365,14 @@ name = "Hime Cut" icon_state = "hair_himecut" + shorthime + name = "Short Hime Cut" + icon_state = "hair_shorthime" + + grandebraid + name = "Grande Braid" + icon_state = "hair_grande" + mbraid name = "Medium Braid" icon_state = "hair_shortbraid" @@ -369,6 +381,10 @@ name = "Long Braid" icon_state = "hair_hbraid" + braid + name = "Floorlength Braid" + icon_state = "hair_braid" + odango name = "Odango" icon_state = "hair_odango" @@ -398,6 +414,10 @@ name = "Drillruru" icon_state = "hair_drillruru" + fringetail + name = "Fringetail" + icon_state = "hair_fringetail" + dandypomp name = "Dandy Pompadour" icon_state = "hair_dandypompadour" @@ -549,7 +569,53 @@ icon_state = "hair_shavedpart" gender = MALE + hightight + name = "High and Tight" + icon_state = "hair_hightight" + rowbun + name = "Row Bun" + icon_state = "hair_rowbun" + + rowdualbraid + name = "Row Dual Braid" + icon_state = "hair_rowdualtail" + + rowbraid + name = "Row Braid" + icon_state = "hair_rowbraid" + + regulationmohawk + name = "Regulation Mohawk" + icon_state = "hair_shavedmohawk" + + topknot + name = "Topknot" + icon_state = "hair_topknot" + + ronin + name = "Ronin" + icon_state = "hair_ronin" + + bowlcut2 + name = "Bowl2" + icon_state = "hair_bowlcut2" + + thinning + name = "Thinning" + icon_state = "hair_thinning" + + thinningfront + name = "Thinning Front" + icon_state = "hair_thinningfront" + + thinningback + name = "Thinning Back" + icon_state = "hair_thinningrear" + + manbun + name = "Manbun" + icon_state = "hair_manbun" /* /////////////////////////////////// / =---------------------------= / @@ -674,6 +740,13 @@ name = "Walrus Moustache" icon_state = "facial_walrus" + croppedbeard + name = "Full Cropped Beard" + icon_state = "facial_croppedfullbeard" + + chinless + name = "Chinless Beard" + icon_state = "facial_chinlessbeard" /* /////////////////////////////////// / =---------------------------= / diff --git a/code/modules/multiz/pipes.dm b/code/modules/multiz/pipes.dm index 6b6b24c4705..7c1fee0525e 100644 --- a/code/modules/multiz/pipes.dm +++ b/code/modules/multiz/pipes.dm @@ -51,7 +51,7 @@ obj/machinery/atmospherics/pipe/zpipe/New() invisibility = i ? 101 : 0 update_icon() -obj/machinery/atmospherics/pipe/up/process() +obj/machinery/atmospherics/pipe/zpipe/process() if(!parent) //This should cut back on the overhead calling build_network thousands of times per cycle ..() else @@ -81,10 +81,10 @@ obj/machinery/atmospherics/pipe/zpipe/proc/burst() qdel(src) // NOT qdel. obj/machinery/atmospherics/pipe/zpipe/proc/normalize_dir() - if(dir==3) - set_dir(1) - else if(dir==12) - set_dir(4) + if(dir == (NORTH|SOUTH)) + set_dir(NORTH) + else if(dir == (EAST|WEST)) + set_dir(EAST) obj/machinery/atmospherics/pipe/zpipe/Destroy() if(node1) @@ -97,6 +97,7 @@ obj/machinery/atmospherics/pipe/zpipe/pipeline_expansion() return list(node1, node2) obj/machinery/atmospherics/pipe/zpipe/update_icon() + color = pipe_color return obj/machinery/atmospherics/pipe/zpipe/disconnect(obj/machinery/atmospherics/reference) diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm index 0f5ea190f26..c6670d2a30e 100644 --- a/code/modules/organs/blood.dm +++ b/code/modules/organs/blood.dm @@ -37,7 +37,7 @@ var/const/CE_STABLE_THRESHOLD = 0.5 // Takes care blood loss and regeneration /mob/living/carbon/human/handle_blood() - if(in_stasis) + if(inStasisNow()) return if(!should_have_organ(O_HEART)) diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 67c1d3c2a79..20390a35553 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -882,7 +882,7 @@ Note that amputating the affected organ does in fact remove the infection from t if(!clean) // Throw limb around. if(src && istype(loc,/turf)) - throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) + throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) dir = 2 if(DROPLIMB_BURN) new /obj/effect/decal/cleanable/ash(get_turf(victim)) @@ -901,19 +901,19 @@ Note that amputating the affected organ does in fact remove the infection from t gore.basecolor = use_blood_colour gore.update_icon() - gore.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) + gore.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) for(var/obj/item/organ/I in internal_organs) I.removed() if(istype(loc,/turf)) - I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) + I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) for(var/obj/item/I in src) if(I.w_class <= ITEMSIZE_SMALL) qdel(I) continue I.loc = get_turf(src) - I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) + I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) qdel(src) diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm index 25db1953d67..69d14c1dd16 100644 --- a/code/modules/organs/robolimbs.dm +++ b/code/modules/organs/robolimbs.dm @@ -44,6 +44,14 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\ var/parts = BP_ALL //Defines what parts said brand can replace on a body. var/health_hud_intensity = 1 // Intensity modifier for the health GUI indicator. +/datum/robolimb/unbranded_monitor + company = "Unbranded Monitor" + desc = "A generic unbranded interpretation of a popular prosthetic head model. It looks rudimentary and cheaply constructed." + icon = 'icons/mob/human_races/cyberlimbs/unbranded/unbranded_monitor.dmi' + parts = list(BP_HEAD) + monitor_styles = standard_monitor_styles + unavailable_to_build = 1 + /datum/robolimb/nanotrasen company = "NanoTrasen" desc = "A simple but efficient robotic limb, created by NanoTrasen." diff --git a/code/modules/paperwork/papershredder.dm b/code/modules/paperwork/papershredder.dm index 3283e67f7d6..41f0619187c 100644 --- a/code/modules/paperwork/papershredder.dm +++ b/code/modules/paperwork/papershredder.dm @@ -123,7 +123,7 @@ if(!paperamount) return paperamount-- - return PoolOrNew(/obj/item/weapon/shreddedp, get_turf(src)) + return new /obj/item/weapon/shreddedp(get_turf(src)) /obj/machinery/papershredder/power_change() ..() @@ -185,5 +185,5 @@ var/mob/living/M = loc if(istype(M)) M.drop_from_inventory(src) - PoolOrNew(/obj/effect/decal/cleanable/ash,get_turf(src)) + new /obj/effect/decal/cleanable/ash(get_turf(src)) qdel(src) diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index f7d963523c6..9cb7292baf8 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -182,7 +182,11 @@ if (A == user && user.zone_sel.selecting == O_MOUTH && !mouthshoot) handle_suicide(user) else if(user.a_intent == I_HURT) //point blank shooting - Fire(A, user, pointblank=1) + if(user && user.client && user.aiming && user.aiming.active && user.aiming.aiming_at != A && A != user) + PreFire(A,user) //They're using the new gun system, locate what they're aiming at. + return + else + Fire(A, user, pointblank=1) else return ..() //Pistolwhippin' @@ -326,6 +330,8 @@ user.setMoveCooldown(move_delay) next_fire_time = world.time + fire_delay + accuracy = initial(accuracy) //Reset the gun's accuracy + if(muzzle_flash) set_light(0) @@ -396,6 +402,8 @@ //update timing next_fire_time = world.time + fire_delay + accuracy = initial(accuracy) //Reset the gun's accuracy + if(muzzle_flash) set_light(0) @@ -482,11 +490,11 @@ // Certain statuses make it harder to aim, blindness especially. Same chances as melee, however guns accuracy uses multiples of 15. if(user.eye_blind) - accuracy -= 5 + P.accuracy -= 5 if(user.eye_blurry) - accuracy -= 2 + P.accuracy -= 2 if(user.confused) - accuracy -= 3 + P.accuracy -= 3 //accuracy bonus from aiming if (aim_targets && (target in aim_targets)) diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index 6fd294f9284..604c936172b 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -28,6 +28,7 @@ name = "practice laser carbine" desc = "A modified version of the HI G40E, this one fires less concentrated energy bolts designed for target practice." projectile_type = /obj/item/projectile/beam/practice + charge_cost = 48 cell_type = /obj/item/weapon/cell/device diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 8fbfc0e6579..46988c99340 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -44,10 +44,12 @@ origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3, TECH_POWER = 3) modifystate = "floramut" self_recharge = 1 + var/decl/plantgene/gene = null firemodes = list( list(mode_name="induce mutations", projectile_type=/obj/item/projectile/energy/floramut, modifystate="floramut"), list(mode_name="increase yield", projectile_type=/obj/item/projectile/energy/florayield, modifystate="florayield"), + list(mode_name="induce specific mutations", projectile_type=/obj/item/projectile/energy/floramut/gene, modifystate="floramut"), ) /obj/item/weapon/gun/energy/floragun/afterattack(obj/target, mob/user, adjacent_flag) @@ -58,6 +60,28 @@ return ..() +/obj/item/weapon/gun/energy/floragun/verb/select_gene() + set name = "Select Gene" + set category = "Object" + set src in view(1) + + var/genemask = input("Choose a gene to modify.") as null|anything in plant_controller.plant_gene_datums + + if(!genemask) + return + + gene = plant_controller.plant_gene_datums[genemask] + + to_chat(usr, "You set the [src]'s targeted genetic area to [genemask].") + + return + +/obj/item/weapon/gun/energy/floragun/consume_next_projectile() + . = ..() + var/obj/item/projectile/energy/floramut/gene/G = . + if(istype(G)) + G.gene = gene + /obj/item/weapon/gun/energy/meteorgun name = "meteor gun" desc = "For the love of god, make sure you're aiming this the right way!" diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 750164a2602..f5a7460cc32 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -173,7 +173,7 @@ return //roll to-hit - miss_modifier = max(15*(distance-2) - round(15*accuracy) + miss_modifier + round(15*target_mob.evasion), 0) + miss_modifier = max(15*(distance-2) - round(15*accuracy) + miss_modifier + round(15*target_mob.get_evasion()), 0) var/hit_zone = get_zone_with_miss_chance(def_zone, target_mob, miss_modifier, ranged_attack=(distance > 1 || original != target_mob)) //if the projectile hits a target we weren't originally aiming at then retain the chance to miss var/result = PROJECTILE_FORCE_MISS diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index 033b4065102..ebb786c60e8 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -38,7 +38,7 @@ playsound(src, 'sound/effects/snap.ogg', 50, 1) src.visible_message("\The [src] explodes in a bright flash!") - 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(2, 1, T) sparks.start() diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index dd81d713fe3..c8c26f5f396 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -121,6 +121,15 @@ else return 1 +/obj/item/projectile/energy/floramut/gene + name = "gamma somatoray" + icon_state = "energy2" + damage = 0 + damage_type = TOX + nodamage = 1 + check_armour = "energy" + var/decl/plantgene/gene = null + /obj/item/projectile/energy/florayield name = "beta somatoray" icon_state = "energy2" diff --git a/code/modules/random_map/automata/diona.dm b/code/modules/random_map/automata/diona.dm index 523f6880385..e9e58a03a47 100644 --- a/code/modules/random_map/automata/diona.dm +++ b/code/modules/random_map/automata/diona.dm @@ -38,7 +38,7 @@ if(1) new_growth = 2 var/obj/structure/diona/vines/existing = locate() in T - if(!istype(existing)) existing = PoolOrNew(/obj/structure/diona/vines, T) + if(!istype(existing)) existing = new /obj/structure/diona/vines(T) if(existing.growth < new_growth) existing.growth = new_growth existing.update_icon() @@ -161,11 +161,11 @@ switch(value) if(ARTIFACT_CHAR) - PoolOrNew(/obj/structure/diona/bulb,T) + new /obj/structure/diona/bulb(T) if(MONSTER_CHAR) spawn_diona_nymph(T) if(DOOR_CHAR) - var/obj/structure/diona/vines/V = PoolOrNew(/obj/structure/diona/vines,T) + var/obj/structure/diona/vines/V = new /obj/structure/diona/vines(T) V.growth = 3 V.update_icon() spawn(1) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm index 5909ed906f3..d0be0469c10 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm @@ -95,7 +95,7 @@ if(alien == IS_SKRELL) strength_mod *= 5 if(alien == IS_TAJARA) - strength_mod *= 1.75 + strength_mod *= 1.25 if(alien == IS_UNATHI) strength_mod *= 0.75 if(alien == IS_DIONA) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm index 4532dc43fca..a5469149307 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm @@ -1799,6 +1799,7 @@ reagent_state = LIQUID color = "#7F00FF" strength = 10 + druggy = 15 glass_name = "Pan-Galactic Gargle Blaster" glass_desc = "Does... does this mean that Arthur and Ford are on the station? Oh joy." @@ -2232,8 +2233,8 @@ glass_name = "special blend whiskey" glass_desc = "Just when you thought regular station whiskey was good... This silky, amber goodness has to come along and ruin everything." -/datum/reagent/ethanol/unathiliquor //Needs a better name - name = "Unathi Liquor" +/datum/reagent/ethanol/unathiliquor + name = "Redeemer's Brew" id = "unathiliquor" description = "This barely qualifies as a drink, and could give jetfuel a run for its money. Also known to cause feelings of euphoria and numbness." taste_description = "spiced numbness" diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm index 41ad4cb5c6c..e20ee9459f7 100644 --- a/code/modules/reagents/Chemistry-Recipes.dm +++ b/code/modules/reagents/Chemistry-Recipes.dm @@ -384,7 +384,7 @@ name = "Stimm" id = "stimm" result = "stimm" - required_reagents = list("sugar" = 1, "fuel" = 1) + required_reagents = list("left4zed" = 1, "fuel" = 1) catalysts = list("fuel" = 5) result_amount = 2 diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index ce377c87091..16a1cb3b265 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -121,7 +121,7 @@ recharge_time = 3 volume = 60 possible_transfer_amounts = list(5, 10, 20, 30) - reagent_ids = list("beer", "kahlua", "whiskey", "specialwhiskey", "wine", "vodka", "gin", "rum", "tequilla", "vermouth", "cognac", "ale", "mead", "water", "sugar", "ice", "tea", "icetea", "cola", "spacemountainwind", "dr_gibb", "space_up", "tonic", "sodawater", "lemon_lime", "orangejuice", "limejuice", "watermelonjuice") + reagent_ids = list("ale", "beer", "berryjuice", "coffee", "cognac", "cola", "dr_gibb", "egg", "gin", "hot_coco", "ice", "icetea", "kahlua", "lemonjuice", "lemon_lime", "limejuice", "mead", "milk", "mint", "orangejuice", "rum", "sodawater", "soymilk", "space_up", "spacemountainwind", "specialwhiskey", "sugar", "tea", "tequilla", "tomatojuice", "tonic", "vermouth", "vodka", "water", "watermelonjuice", "whiskey", "wine") /obj/item/weapon/reagent_containers/borghypo/service/attack(var/mob/M, var/mob/user) return diff --git a/code/modules/reagents/reagent_containers/food/drinks/bottle.dm b/code/modules/reagents/reagent_containers/food/drinks/bottle.dm index 3300eb91d6e..2dcdd126057 100644 --- a/code/modules/reagents/reagent_containers/food/drinks/bottle.dm +++ b/code/modules/reagents/reagent_containers/food/drinks/bottle.dm @@ -407,6 +407,16 @@ ..() reagents.add_reagent("pwine", 100) +/obj/item/weapon/reagent_containers/food/drinks/bottle/redeemersbrew + name = "Redeemer's Brew" + desc = "Just opening the top of this bottle makes you feel a bit tipsy. Not for the faint of heart." + icon_state = "redeemersbrew" + center_of_mass = list("x"=16, "y"=3) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/redeemersbrew/New() + ..() + reagents.add_reagent("unathiliquor", 100) + //////////////////////////JUICES AND STUFF /////////////////////// /obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index e9e3c62dada..427d08d141c 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -14,11 +14,19 @@ possible_transfer_amounts = null flags = OPENCONTAINER slot_flags = SLOT_BELT + var/reusable = 1 + var/used = 0 + var/filled = 0 + var/list/filled_reagents = list() -///obj/item/weapon/reagent_containers/hypospray/New() //comment this to make hypos start off empty -// ..() -// reagents.add_reagent("tricordrazine", 30) -// return +/obj/item/weapon/reagent_containers/hypospray/New() + ..() + if(filled) + if(filled_reagents) + for(var/r in filled_reagents) + reagents.add_reagent(r, filled_reagents[r]) + update_icon() + return /obj/item/weapon/reagent_containers/hypospray/do_surgery(mob/living/carbon/M, mob/living/user) if(user.a_intent != I_HELP) //in case it is ever used as a surgery tool @@ -53,6 +61,9 @@ admin_inject_log(user, M, src, contained, trans) user << "[trans] units injected. [reagents.total_volume] units remaining in \the [src]." + if(!reusable && !used) + used = !used + return /obj/item/weapon/reagent_containers/hypospray/autoinjector @@ -62,59 +73,52 @@ item_state = "autoinjector" amount_per_transfer_from_this = 5 volume = 5 + reusable = 0 + filled = 1 + filled_reagents = list("inaprovaline" = 5) -/obj/item/weapon/reagent_containers/hypospray/autoinjector/New() +/obj/item/weapon/reagent_containers/hypospray/autoinjector/on_reagent_change() ..() - reagents.add_reagent("inaprovaline", 5) update_icon() - return + +/obj/item/weapon/reagent_containers/hypospray/autoinjector/empty + filled = 0 + filled_reagents = list() + +/obj/item/weapon/reagent_containers/hypospray/autoinjector/used + used = 1 + filled_reagents = list() /obj/item/weapon/reagent_containers/hypospray/autoinjector/attack(mob/M as mob, mob/user as mob) ..() - if(reagents.total_volume <= 0) //Prevents autoinjectors to be refilled. + if(used) //Prevents autoinjectors to be refilled. flags &= ~OPENCONTAINER update_icon() return /obj/item/weapon/reagent_containers/hypospray/autoinjector/update_icon() - if(reagents.total_volume > 0) + if(!used && reagents.reagent_list.len) icon_state = "[initial(icon_state)]1" - else + else if(used) icon_state = "[initial(icon_state)]0" + else + icon_state = "[initial(icon_state)]2" /obj/item/weapon/reagent_containers/hypospray/autoinjector/examine(mob/user) ..(user) if(reagents && reagents.reagent_list.len) user << "It is currently loaded." - else + else if(used) user << "It is spent." + else + user << "It is currently unloaded." -/obj/item/weapon/reagent_containers/hypospray/autoinjector/clotting +/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting name = "clotting agent" - desc = "A rapid and safe way to administer clotting drugs by untrained or trained personnel." - icon_state = "autoinjector" - item_state = "autoinjector" - amount_per_transfer_from_this = 10 - volume = 10 + desc = "A refined version of the standard autoinjector, allowing greater capacity. This variant excels at treating bleeding wounds and internal bleeding." + filled_reagents = list("inaprovaline" = 5, "myelamine" = 10) -/obj/item/weapon/reagent_containers/hypospray/autoinjector/clotting/New() - ..() - reagents.remove_reagent("inaprovaline", 5) - reagents.add_reagent("myelamine", 10) - update_icon() - return - -/obj/item/weapon/reagent_containers/hypospray/autoinjector/bonemed +/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed name = "bone repair injector" - desc = "A rapid and safe way to administer advanced drugs by untrained or trained personnel." - icon_state = "autoinjector" - item_state = "autoinjector" - amount_per_transfer_from_this = 10 - volume = 10 - -/obj/item/weapon/reagent_containers/hypospray/autoinjector/bonemed/New() - ..() - reagents.remove_reagent("inaprovaline", 5) - reagents.add_reagent("osteodaxon", 10) - update_icon() - return \ No newline at end of file + desc = "A refined version of the standard autoinjector, allowing greater capacity. This one excels at treating damage to bones." + filled_reagents = list("inaprovaline" = 5, "osteodaxon" = 10) diff --git a/code/modules/spells/spell_projectile.dm b/code/modules/spells/spell_projectile.dm index c94131b252c..07adda00818 100644 --- a/code/modules/spells/spell_projectile.dm +++ b/code/modules/spells/spell_projectile.dm @@ -26,7 +26,7 @@ /obj/item/projectile/spell_projectile/before_move() if(proj_trail && src && src.loc) //pretty trails - var/obj/effect/overlay/trail = PoolOrNew(/obj/effect/overlay, src.loc) + var/obj/effect/overlay/trail = new /obj/effect/overlay(src.loc) trails += trail trail.icon = proj_trail_icon trail.icon_state = proj_trail_icon_state diff --git a/code/modules/supermatter/supermatter.dm b/code/modules/supermatter/supermatter.dm index df9c900d384..1ebd8207e06 100644 --- a/code/modules/supermatter/supermatter.dm +++ b/code/modules/supermatter/supermatter.dm @@ -249,7 +249,13 @@ env.merge(removed) for(var/mob/living/carbon/human/l in view(src, min(7, round(sqrt(power/6))))) // If they can see it without mesons on. Bad on them. - if(!istype(l.glasses, /obj/item/clothing/glasses/meson)) + var/eye_shield = 0 //How protected they are + if(istype(l.glasses, /obj/item/clothing/glasses/meson)) + eye_shield += 1 + if(istype(l.head, /obj/item/clothing/head/helmet/space)) + if(l.run_armor_check(BP_HEAD, "rad") >= 60) + eye_shield += 1 + if(eye_shield < 1) l.hallucination = max(0, min(200, l.hallucination + power * config_hallucination_power * sqrt( 1 / max(1,get_dist(l, src)) ) ) ) //adjusted range so that a power of 170 (pretty high) results in 9 tiles, roughly the distance from the core to the engine monitoring room. diff --git a/code/modules/turbolift/turbolift.dm b/code/modules/turbolift/turbolift.dm index 7d2f3c11a83..90273250cb5 100644 --- a/code/modules/turbolift/turbolift.dm +++ b/code/modules/turbolift/turbolift.dm @@ -108,7 +108,7 @@ current_floor = next_floor control_panel_interior.visible_message("The elevator [moving_upwards ? "rises" : "descends"] smoothly.") - return 1 + return (next_floor.delay_time || move_delay || 30) /datum/turbolift/proc/queue_move_to(var/datum/turbolift_floor/floor) if(!floor || !(floor in floors) || (floor in queued_floors)) diff --git a/code/modules/turbolift/turbolift_areas.dm b/code/modules/turbolift/turbolift_areas.dm index dbf568aec2e..f9d69cc16f7 100644 --- a/code/modules/turbolift/turbolift_areas.dm +++ b/code/modules/turbolift/turbolift_areas.dm @@ -9,3 +9,4 @@ var/lift_floor_name = null var/lift_announce_str = "Ding!" var/arrival_sound = 'sound/machines/ding.ogg' + var/delay_time diff --git a/code/modules/turbolift/turbolift_console.dm b/code/modules/turbolift/turbolift_console.dm index 4cbee6a7737..f6619516816 100644 --- a/code/modules/turbolift/turbolift_console.dm +++ b/code/modules/turbolift/turbolift_console.dm @@ -123,7 +123,7 @@ dat += "Emergency Stop" dat += "
" - var/datum/browser/popup = new(user, "turbolift_panel", "Lift Panel", 230, 260) + var/datum/browser/popup = new(user, "turbolift_panel", "Lift Panel", 250, 320) popup.set_content(jointext(dat, null)) popup.open() return diff --git a/code/modules/turbolift/turbolift_floor.dm b/code/modules/turbolift/turbolift_floor.dm index 7761f092843..46e4dfa0f48 100644 --- a/code/modules/turbolift/turbolift_floor.dm +++ b/code/modules/turbolift/turbolift_floor.dm @@ -5,6 +5,7 @@ var/name var/announce_str var/arrival_sound + var/delay_time var/list/doors = list() var/obj/structure/lift/button/ext_panel @@ -20,6 +21,7 @@ name = A.lift_floor_name ? A.lift_floor_name : A.name announce_str = A.lift_announce_str arrival_sound = A.arrival_sound + delay_time = A.delay_time //called when a lift has queued this floor as a destination /datum/turbolift_floor/proc/pending_move(var/datum/turbolift/lift) diff --git a/code/modules/turbolift/turbolift_process.dm b/code/modules/turbolift/turbolift_process.dm index 83ce1b9faf0..124049d42e4 100644 --- a/code/modules/turbolift/turbolift_process.dm +++ b/code/modules/turbolift/turbolift_process.dm @@ -20,16 +20,17 @@ var/datum/controller/process/turbolift/turbolift_controller continue spawn(0) lift.busy = 1 - if(!lift.do_move()) + var/floor_delay + if(!(floor_delay = lift.do_move())) moving_lifts[liftref] = null moving_lifts -= liftref if(lift.target_floor) lift.target_floor.ext_panel.reset() lift.target_floor = null else - lift_is_moving(lift) + lift_is_moving(lift,floor_delay) lift.busy = 0 SCHECK -/datum/controller/process/turbolift/proc/lift_is_moving(var/datum/turbolift/lift) - moving_lifts["\ref[lift]"] = world.time + lift.move_delay +/datum/controller/process/turbolift/proc/lift_is_moving(var/datum/turbolift/lift,var/floor_delay) + moving_lifts["\ref[lift]"] = world.time + floor_delay diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm index 80eb2f1a447..4da307cb910 100644 --- a/code/modules/vehicles/vehicle.dm +++ b/code/modules/vehicles/vehicle.dm @@ -139,7 +139,7 @@ /obj/vehicle/emp_act(severity) var/was_on = on stat |= EMPED - 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_state = "empdisable" pulse2.name = "emp sparks" @@ -192,8 +192,8 @@ src.visible_message("\red [src] blows apart!", 1) var/turf/Tsec = get_turf(src) - PoolOrNew(/obj/item/stack/rods, Tsec) - PoolOrNew(/obj/item/stack/rods, Tsec) + new /obj/item/stack/rods(Tsec) + new /obj/item/stack/rods(Tsec) new /obj/item/stack/cable_coil/cut(Tsec) if(cell) diff --git a/code/modules/ventcrawl/ventcrawl.dm b/code/modules/ventcrawl/ventcrawl.dm index 5c2db9f3deb..1ece0248335 100644 --- a/code/modules/ventcrawl/ventcrawl.dm +++ b/code/modules/ventcrawl/ventcrawl.dm @@ -44,10 +44,15 @@ var/list/ventcrawl_machinery = list( /mob/living/proc/is_allowed_vent_crawl_item(var/obj/item/carried_item) if(carried_item == ability_master) return 1 + + var/list/allowed = list() for(var/type in can_enter_vent_with) - if(istype(carried_item, can_enter_vent_with)) - return get_inventory_slot(carried_item) == 0 - return 0 + var/list/types = typesof(type) + allowed += types + + if(carried_item.type in allowed) + if(get_inventory_slot(carried_item) == 0) + return 1 /mob/living/carbon/is_allowed_vent_crawl_item(var/obj/item/carried_item) if(carried_item in internal_organs) diff --git a/code/modules/xenoarcheaology/finds/find_spawning.dm b/code/modules/xenoarcheaology/finds/find_spawning.dm index 3be0dfbca22..f6a42006541 100644 --- a/code/modules/xenoarcheaology/finds/find_spawning.dm +++ b/code/modules/xenoarcheaology/finds/find_spawning.dm @@ -244,7 +244,7 @@ apply_material_decorations = 0 if(23) apply_prefix = 0 - new_item = PoolOrNew(/obj/item/stack/rods, src.loc) + new_item = new /obj/item/stack/rods(src.loc) apply_image_decorations = 0 apply_material_decorations = 0 if(24) diff --git a/code/modules/xenobio2/mob/xeno procs.dm b/code/modules/xenobio2/mob/xeno procs.dm index b72b1567fb7..03fde9efc8e 100644 --- a/code/modules/xenobio2/mob/xeno procs.dm +++ b/code/modules/xenobio2/mob/xeno procs.dm @@ -6,6 +6,7 @@ Proc for metabolism Proc for mutating Procs for copying speech, if applicable Procs for targeting +Divergence proc, used in mutation to make unique datums. */ /mob/living/simple_animal/xeno/proc/ProcessTraits() if(maleable >= MAX_MALEABLE) @@ -84,8 +85,14 @@ Procs for targeting return 1 //Everything worked out okay. return 0 + +/mob/living/simple_animal/xeno/proc/diverge() + var/datum/xeno/traits/newtraits = new() + newtraits.copy_traits(traitdat) + return newtraits /mob/living/simple_animal/xeno/proc/Mutate() + traitdat = diverge() nameVar = "mutated" if((COLORMUT & mutable)) traitdat.traits[TRAIT_XENO_COLOR] = "#" diff --git a/config/example/config.txt b/config/example/config.txt index 8437829fd38..232d3c66ad1 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -33,6 +33,9 @@ JOBS_HAVE_MINIMAL_ACCESS ## Unhash this to use recursive explosions, keep it hashed to use circle explosions. Recursive explosions react to walls, airlocks and blast doors, making them look a lot cooler than the boring old circular explosions. They require more CPU and are (as of january 2013) experimental #USE_RECURSIVE_EXPLOSIONS +Configure how fast explosion strength diminishes when travelling up/down z levels. All explosion distances are multiplied by this each time they go up/down z-levels. +#MULTI_Z_EXPLOSION_SCALAR 0.5 + ## log OOC channel LOG_OOC diff --git a/html/changelog.html b/html/changelog.html index e6e2d363523..e062e723b95 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -53,6 +53,119 @@ -->
+

09 May 2017

+

Anewbe updated:

+
    +
  • Ports but does not enable Bay's MultiZAS.
  • +
+

Leshana updated:

+
    +
  • Optimized (but still not enabled) multi-z ZAS
  • +
  • Multi-Z explosion transfer coefficient is now configurable
  • +
+

N3X15 updated:

+
    +
  • Flashlights on the high setting are no longer Beacons of Gondor.
  • +
+

Neerti updated:

+
    +
  • Tesla armor now retaliates against ranged attacks if within 3 tiles, and recharges in 15 seconds, from 20.
  • +
  • Technomancer Instability fades away slower.
  • +
  • Fire and frost auras made more potent.
  • +
  • Gambit can now give rare spells unobtainable by other means, based on spell power.
  • +
  • Mend Wounds and Mend Burns combined into Mend Life. Mend Metal and Mend Wires combined into Mend Synthetic.
  • +
  • Adds Lesser Chain Lightning, a more spammable version, but weaker.
  • +
  • Adds Destabilize, which makes an area glow with instability for 20 seconds.
  • +
  • Adds Ionic Bolt, which ruins the lives of synthetics.
  • +
  • Oxygenate made cheaper.
  • +
+

SiegDerMaus updated:

+
    +
  • Adds one new haircut, a chin-length bob.
  • +
+

Yosh updated:

+
    +
  • Ports a bunch of hair from Bay. Knock yourself out.
  • +
+ +

05 May 2017

+

Anewbe updated:

+
    +
  • Adds a cup for dice games, in the loadout.
  • +
  • Thermals now let you see in the dark.
  • +
+

Arokha updated:

+
    +
  • Sleepers now have a 'stasis' level setting, that will ignore varying numbers of life() ticks on the patient.
  • +
  • Stasis bags and Ody sleepers now use a fixed level of this new stasis system (ignore 2/3 life ticks).
  • +
  • You can escape from being asleep in a sleeper, similar to escaping from a cryotube.
  • +
  • You can now use grabs on sleepers to insert patients, same as scanners.
  • +
+

Datraen updated:

+
    +
  • Xenobiological traits are made unique on each mutate, avoiding mutating other mobs with same trait data.
  • +
+

Leshana updated:

+
    +
  • Resetting a fire alert will no longer open firedoors if atmos alert is in effect and vice versa
  • +
+

LorenLuke updated:

+
    +
  • Unfucks the screen bug on roundstart changelings.
  • +
  • Changeling now display 'alive' status on Medhuds properly.
  • +
  • Refactors changeling ranged stings not passing over tables. Can now pass over tables, any machinery (except doors), machine frames, and past closet subtypes.
  • +
  • You can now view an active video call by using the communicator in hand.
  • +
  • Guns on harm intent in aim mode will target, rather than shoot pointblank on first click.
  • +
  • You can now put handcuffs on yourself.
  • +
+ +

25 April 2017

+

Anewbe updated:

+
    +
  • Cultist armor now has better protection from strange energies.
  • +
  • Adds the ion pistol to the uplink.
  • +
  • The ion pistol can now be holstered.
  • +
  • Sprites on the smoking pipes should be fixed.
  • +
+

Atermonera updated:

+
    +
  • Brain type (Organic, cyborg, posi, or drone) is now displayed in all records.
  • +
+

Belsima updated:

+
    +
  • Changes relaymove() code in bodybags.
  • +
  • Above tweak used to allow exiting bodybag while in closed morgue tray.
  • +
+

Leshana updated:

+
    +
  • Implements footstep sound system and adds sounds to various floor types including plating, tiles, wood, and carpet.
  • +
+

LorenLuke updated:

+
    +
  • Allows people who are bucked to give/receive items.
  • +
  • Can click-drag people onto chairs/beds from 1 tile away to buckle them.
  • +
  • Allows you to place tape masks/restraints back on the roll (roll is still infinite).
  • +
  • Fixes ventcrawling for spiderbots/implants/etc.
  • +
+

Neerti updated:

+
    +
  • Drones will now spawn with an EIO-mandated ID card alongside their NT ID.
  • +
  • Fabricate Clothing for Changelings costs one point instead of two, and is fabricated twice as fast.
  • +
  • Dead changelings can no longer hear deadchat or freely ghost.
  • +
  • Shrieks now share a 10 second cooldown.
  • +
  • Lings cannot transform or shriek inside containers such as closets and pipes.
  • +
  • Regen. Stasis timer adjusted to be between 2 to 4 minutes.
  • +
  • Visible Camo. should end if the user is stunned.
  • +
  • Visible Camo. now blocks AI tracking when active.
  • +
  • Recursive Visible Camo. no longer gives true invis.
  • +
  • Recursive Visible Camo. will allow the changeling to run while cloaked instead.
  • +
  • Ling chemical meter on HUD now has a blinking exclaimation mark if below 20 chemicals, to warn that they cannot revive if they should die while still below 20.
  • +
+

Yoshax updated:

+
    +
  • Tape color is different now. Security tape is red rather than yellow, Engineering tape remains yellow and Atmos tape is a lighter cyan rather than blue.
  • +
+

19 April 2017

Anewbe updated:

    diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 794250f1630..293051b3192 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -3451,3 +3451,96 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. Yoshax: - bugfix: Water such as the pool will no longer apply fire stacks when you enter, meaning you will no longer be flammable from swimming. +2017-04-25: + Anewbe: + - rscadd: Cultist armor now has better protection from strange energies. + - rscadd: Adds the ion pistol to the uplink. + - tweak: The ion pistol can now be holstered. + - bugfix: Sprites on the smoking pipes should be fixed. + Atermonera: + - rscadd: Brain type (Organic, cyborg, posi, or drone) is now displayed in all records. + Belsima: + - tweak: Changes relaymove() code in bodybags. + - bugfix: Above tweak used to allow exiting bodybag while in closed morgue tray. + Leshana: + - rscadd: Implements footstep sound system and adds sounds to various floor types + including plating, tiles, wood, and carpet. + LorenLuke: + - bugfix: Allows people who are bucked to give/receive items. + - tweak: Can click-drag people onto chairs/beds from 1 tile away to buckle them. + - tweak: Allows you to place tape masks/restraints back on the roll (roll is still + infinite). + - bugfix: Fixes ventcrawling for spiderbots/implants/etc. + Neerti: + - rscadd: Drones will now spawn with an EIO-mandated ID card alongside their NT + ID. + - tweak: Fabricate Clothing for Changelings costs one point instead of two, and + is fabricated twice as fast. + - tweak: Dead changelings can no longer hear deadchat or freely ghost. + - tweak: Shrieks now share a 10 second cooldown. + - tweak: Lings cannot transform or shriek inside containers such as closets and + pipes. + - tweak: Regen. Stasis timer adjusted to be between 2 to 4 minutes. + - tweak: Visible Camo. should end if the user is stunned. + - rscadd: Visible Camo. now blocks AI tracking when active. + - rscdel: Recursive Visible Camo. no longer gives true invis. + - rscadd: Recursive Visible Camo. will allow the changeling to run while cloaked + instead. + - rscadd: Ling chemical meter on HUD now has a blinking exclaimation mark if below + 20 chemicals, to warn that they cannot revive if they should die while still + below 20. + Yoshax: + - tweak: Tape color is different now. Security tape is red rather than yellow, Engineering + tape remains yellow and Atmos tape is a lighter cyan rather than blue. +2017-05-05: + Anewbe: + - rscadd: Adds a cup for dice games, in the loadout. + - rscadd: Thermals now let you see in the dark. + Arokha: + - rscadd: Sleepers now have a 'stasis' level setting, that will ignore varying numbers + of life() ticks on the patient. + - tweak: Stasis bags and Ody sleepers now use a fixed level of this new stasis system + (ignore 2/3 life ticks). + - tweak: You can escape from being asleep in a sleeper, similar to escaping from + a cryotube. + - rscadd: You can now use grabs on sleepers to insert patients, same as scanners. + Datraen: + - bugfix: Xenobiological traits are made unique on each mutate, avoiding mutating + other mobs with same trait data. + Leshana: + - bugfix: Resetting a fire alert will no longer open firedoors if atmos alert is + in effect and vice versa + LorenLuke: + - Bugfix: Unfucks the screen bug on roundstart changelings. + - bugfix: Changeling now display 'alive' status on Medhuds properly. + - tweak: Refactors changeling ranged stings not passing over tables. Can now pass + over tables, any machinery (except doors), machine frames, and past closet subtypes. + - bugfix: You can now view an active video call by using the communicator in hand. + - tweak: Guns on harm intent in aim mode will target, rather than shoot pointblank + on first click. + - bugfix: You can now put handcuffs on yourself. +2017-05-09: + Anewbe: + - rscadd: Ports but does not enable Bay's MultiZAS. + Leshana: + - tweak: Optimized (but still not enabled) multi-z ZAS + - rscadd: Multi-Z explosion transfer coefficient is now configurable + N3X15: + - tweak: Flashlights on the high setting are no longer Beacons of Gondor. + Neerti: + - tweak: Tesla armor now retaliates against ranged attacks if within 3 tiles, and + recharges in 15 seconds, from 20. + - tweak: Technomancer Instability fades away slower. + - tweak: Fire and frost auras made more potent. + - rscadd: Gambit can now give rare spells unobtainable by other means, based on + spell power. + - tweak: Mend Wounds and Mend Burns combined into Mend Life. Mend Metal and Mend + Wires combined into Mend Synthetic. + - rscadd: Adds Lesser Chain Lightning, a more spammable version, but weaker. + - rscadd: Adds Destabilize, which makes an area glow with instability for 20 seconds. + - rscadd: Adds Ionic Bolt, which ruins the lives of synthetics. + - tweak: Oxygenate made cheaper. + SiegDerMaus: + - rscadd: Adds one new haircut, a chin-length bob. + Yosh: + - rscadd: Ports a bunch of hair from Bay. Knock yourself out. diff --git a/html/changelogs/Anewbe - CultRobesEnergy.yml b/html/changelogs/Anewbe - CultRobesEnergy.yml deleted file mode 100644 index 1d865cb090f..00000000000 --- a/html/changelogs/Anewbe - CultRobesEnergy.yml +++ /dev/null @@ -1,36 +0,0 @@ -################################ -# Example Changelog File -# -# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. -# -# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) -# When it is, any changes listed below will disappear. -# -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -# Your name. -author: Anewbe - -# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. -delete-after: True - -# Any changes you've made. See valid prefix list above. -# INDENT WITH TWO SPACES. NOT TABS. SPACES. -# SCREW THIS UP AND IT WON'T WORK. -# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. -# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. -changes: - - rscadd: "Cultist armor now has better protection from strange energies." diff --git a/html/changelogs/Anewbe - Ion Pistol.yml b/html/changelogs/Anewbe - Ion Pistol.yml deleted file mode 100644 index efc5c77c0e5..00000000000 --- a/html/changelogs/Anewbe - Ion Pistol.yml +++ /dev/null @@ -1,37 +0,0 @@ -################################ -# Example Changelog File -# -# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. -# -# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) -# When it is, any changes listed below will disappear. -# -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -# Your name. -author: Anewbe - -# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. -delete-after: True - -# Any changes you've made. See valid prefix list above. -# INDENT WITH TWO SPACES. NOT TABS. SPACES. -# SCREW THIS UP AND IT WON'T WORK. -# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. -# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. -changes: - - rscadd: "Adds the ion pistol to the uplink." - - tweak: "The ion pistol can now be holstered. \ No newline at end of file diff --git a/html/changelogs/Anewbe - Smoking Pipes.yml b/html/changelogs/Anewbe - Smoking Pipes.yml deleted file mode 100644 index 33ebbe81588..00000000000 --- a/html/changelogs/Anewbe - Smoking Pipes.yml +++ /dev/null @@ -1,36 +0,0 @@ -################################ -# Example Changelog File -# -# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. -# -# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) -# When it is, any changes listed below will disappear. -# -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -# Your name. -author: Anewbe - -# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. -delete-after: True - -# Any changes you've made. See valid prefix list above. -# INDENT WITH TWO SPACES. NOT TABS. SPACES. -# SCREW THIS UP AND IT WON'T WORK. -# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. -# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. -changes: - - bugfix: "Sprites on the smoking pipes should be fixed." diff --git a/html/changelogs/Leshana-footstep-sounds.yml b/html/changelogs/Leshana-footstep-sounds.yml deleted file mode 100644 index 2e0045dd905..00000000000 --- a/html/changelogs/Leshana-footstep-sounds.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Leshana -delete-after: True -changes: - - rscadd: "Implements footstep sound system and adds sounds to various floor types including plating, tiles, wood, and carpet." diff --git a/html/changelogs/LorenLuke - Bucklechanges.yml b/html/changelogs/LorenLuke - Bucklechanges.yml deleted file mode 100644 index 771cce11482..00000000000 --- a/html/changelogs/LorenLuke - Bucklechanges.yml +++ /dev/null @@ -1,36 +0,0 @@ -################################ -# Example Changelog File -# -# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. -# -# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) -# When it is, any changes listed below will disappear. -# -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -# Your name. -author: LorenLuke - -# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. -delete-after: True - -# Any changes you've made. See valid prefix list above. -# INDENT WITH TWO SPACES. NOT TABS. SPACES. -# SCREW THIS UP AND IT WON'T WORK. -# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. -# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. -changes: - - tweak: "Can click-drag people onto chairs/beds from 1 tile away to buckle them." diff --git a/html/changelogs/LorenLuke - Tape.yml b/html/changelogs/LorenLuke - Tape.yml deleted file mode 100644 index 42135bb9ca2..00000000000 --- a/html/changelogs/LorenLuke - Tape.yml +++ /dev/null @@ -1,36 +0,0 @@ -################################ -# Example Changelog File -# -# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. -# -# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) -# When it is, any changes listed below will disappear. -# -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -# Your name. -author: LorenLuke - -# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. -delete-after: True - -# Any changes you've made. See valid prefix list above. -# INDENT WITH TWO SPACES. NOT TABS. SPACES. -# SCREW THIS UP AND IT WON'T WORK. -# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. -# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. -changes: - - tweak: "Allows you to place tape masks/restraints back on the roll (roll is still infinite)." diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi index 66574573449..1f4bd4a68f2 100644 Binary files a/icons/mob/eyes.dmi and b/icons/mob/eyes.dmi differ diff --git a/icons/mob/human.dmi b/icons/mob/human.dmi index 9bc29db45ff..ab3dac1df9f 100644 Binary files a/icons/mob/human.dmi and b/icons/mob/human.dmi differ diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi index 9b4431a6207..253821118ee 100644 Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ diff --git a/icons/mob/human_races/cyberlimbs/unbranded/unbranded_monitor.dmi b/icons/mob/human_races/cyberlimbs/unbranded/unbranded_monitor.dmi new file mode 100644 index 00000000000..70f3b98db24 Binary files /dev/null and b/icons/mob/human_races/cyberlimbs/unbranded/unbranded_monitor.dmi differ diff --git a/icons/mob/mask.dmi b/icons/mob/mask.dmi index 8a4ce2c73ea..02ffbf4e658 100644 Binary files a/icons/mob/mask.dmi and b/icons/mob/mask.dmi differ diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi index c20a2cbc0ff..94028db1fa0 100644 Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ diff --git a/icons/mob/modifier_effects.dmi b/icons/mob/modifier_effects.dmi new file mode 100644 index 00000000000..e0fe0b1697c Binary files /dev/null and b/icons/mob/modifier_effects.dmi differ diff --git a/icons/mob/screen1.dmi b/icons/mob/screen1.dmi index 9a326ac8a40..809046036da 100644 Binary files a/icons/mob/screen1.dmi and b/icons/mob/screen1.dmi differ diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi index cad42f3b4f5..428ab27ad89 100644 Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ diff --git a/icons/obj/card.dmi b/icons/obj/card.dmi index e1a2c1c2ae4..390fdb88ea8 100644 Binary files a/icons/obj/card.dmi and b/icons/obj/card.dmi differ diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi index ff4ea400ede..0e863674733 100644 Binary files a/icons/obj/clothing/glasses.dmi and b/icons/obj/clothing/glasses.dmi differ diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi index 3669a4702ea..a399164c590 100644 Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ diff --git a/icons/obj/dice.dmi b/icons/obj/dice.dmi index f6a209b4687..17a3c64cd41 100644 Binary files a/icons/obj/dice.dmi and b/icons/obj/dice.dmi differ diff --git a/icons/obj/drinks.dmi b/icons/obj/drinks.dmi index c70873ccc7f..330915356a7 100644 Binary files a/icons/obj/drinks.dmi and b/icons/obj/drinks.dmi differ diff --git a/icons/obj/spells.dmi b/icons/obj/spells.dmi index 7c040983c15..01ced388513 100644 Binary files a/icons/obj/spells.dmi and b/icons/obj/spells.dmi differ diff --git a/icons/obj/syringe.dmi b/icons/obj/syringe.dmi index a9a46f6046d..e604b23f3fa 100644 Binary files a/icons/obj/syringe.dmi and b/icons/obj/syringe.dmi differ diff --git a/icons/obj/vending.dmi b/icons/obj/vending.dmi index 5671731aab6..9bb3378c8ef 100755 Binary files a/icons/obj/vending.dmi and b/icons/obj/vending.dmi differ diff --git a/icons/policetape.dmi b/icons/policetape.dmi index bc469f2eabc..5dde02f1b52 100644 Binary files a/icons/policetape.dmi and b/icons/policetape.dmi differ diff --git a/nano/templates/adv_med.tmpl b/nano/templates/adv_med.tmpl index 2dbd997cbd5..71e02e25095 100644 --- a/nano/templates/adv_med.tmpl +++ b/nano/templates/adv_med.tmpl @@ -94,7 +94,7 @@ Used In File(s): \code\game\machinery\adv_med.dm
{{:data.occupant.blood.percent}}%
-

Reagents

+

Blood Reagents

{{if data.occupant.reagents}} {{for data.occupant.reagents}} @@ -105,7 +105,20 @@ Used In File(s): \code\game\machinery\adv_med.dm {{/for}}
{{else}} -
No reagents detected.
+
No blood reagents detected.
+ {{/if}} +

Stomach Reagents

+ {{if data.occupant.ingested}} + + {{for data.occupant.ingested}} + + + + + {{/for}} +
{{:value.name}}:{{:value.amount}}
+ {{else}} +
No stomach reagents detected.
{{/if}}

External Organs

diff --git a/nano/templates/holodeck.tmpl b/nano/templates/holodeck.tmpl index 71d4ad56056..a91d5a60e51 100644 --- a/nano/templates/holodeck.tmpl +++ b/nano/templates/holodeck.tmpl @@ -5,7 +5,7 @@

Current Loaded Programs:

{{for data.supportedPrograms}} -
{{:helper.link(value.name, data.currentProgram == value.program ? 'check' : 'close', {'program' : value.program}, null, data.currentProgram == value.program ? 'linkOn' : null)}}
+
{{:helper.link(value, data.currentProgram == value ? 'check' : 'close', {'program' : value}, null, data.currentProgram == value ? 'linkOn' : null)}}
{{/for}}
Please ensure that only holographic weapons are used in the holodeck if a combat simulation has been loaded.
{{if data.isSilicon}} @@ -22,7 +22,7 @@ {{if data.safetyDisabled}} {{for data.restrictedPrograms}} -
{{:helper.link('Begin ' + value.name, data.currentProgram == value.program ? 'check' : 'close', {'program' : value.program}, null, data.currentProgram == value.program ? 'linkOn' : null)}}
+
{{:helper.link('Begin ' + value, data.currentProgram == value ? 'check' : 'close', {'program' : value.program}, null, data.currentProgram == value ? 'linkOn' : null)}}
{{/for}}
Ensure the holodeck is empty before testing.
Safety Protocols are DISABLED
diff --git a/nano/templates/pai_medrecords.tmpl b/nano/templates/pai_medrecords.tmpl index 89926d3915b..24e00e949f1 100644 --- a/nano/templates/pai_medrecords.tmpl +++ b/nano/templates/pai_medrecords.tmpl @@ -19,6 +19,10 @@ code/modules/mob/living/silicon/pai/software_modules.dm
Record ID
{{:data.general.id}}
+
+
Entity Classification
+
{{:data.general.brain_type}}
+
Sex
{{:data.general.sex}}
diff --git a/nano/templates/pai_secrecords.tmpl b/nano/templates/pai_secrecords.tmpl index 51cb45dee2e..5ba1e4d90dc 100644 --- a/nano/templates/pai_secrecords.tmpl +++ b/nano/templates/pai_secrecords.tmpl @@ -19,6 +19,10 @@ code/modules/mob/living/silicon/pai/software_modules.dm
Record ID
{{:data.general.id}}
+
+
Entity Classification
+
{{:data.general.brain_type}}
+
Sex
{{:data.general.sex}}
diff --git a/nano/templates/pda.tmpl b/nano/templates/pda.tmpl index 6cd3004654e..77f026a3495 100644 --- a/nano/templates/pda.tmpl +++ b/nano/templates/pda.tmpl @@ -568,6 +568,7 @@ Used In File(s): \code\game\objects\items\devices\PDA\PDA.dm
{{if data.records.general_exists == 1}} Name: {{:data.records.general.name}}
+ Entity Class: {{:data.records.general.brain_type}}
Sex: {{:data.records.general.sex}}
Species: {{:data.records.general.species}}
Age: {{:data.records.general.age}}
diff --git a/nano/templates/sleeper.tmpl b/nano/templates/sleeper.tmpl index 49fb0ae8d75..7ee370e890f 100644 --- a/nano/templates/sleeper.tmpl +++ b/nano/templates/sleeper.tmpl @@ -88,4 +88,12 @@
{{/if}} +
+
+ Stasis Level: +
+
+ {{:helper.link(data.stasis, null, {'change_stasis' : 1})}} +
+
{{/if}} diff --git a/polaris.dme b/polaris.dme index f259635324e..60819747754 100644 --- a/polaris.dme +++ b/polaris.dme @@ -47,7 +47,6 @@ #include "code\_compatibility\509\type2type.dm" #include "code\_helpers\_global_objects.dm" #include "code\_helpers\atmospherics.dm" -#include "code\_helpers\datum_pool.dm" #include "code\_helpers\files.dm" #include "code\_helpers\game.dm" #include "code\_helpers\global_lists.dm" @@ -212,6 +211,7 @@ #include "code\datums\observation\~cleanup.dm" #include "code\datums\repositories\cameras.dm" #include "code\datums\repositories\crew.dm" +#include "code\datums\repositories\decls.dm" #include "code\datums\repositories\repository.dm" #include "code\datums\supplypacks\atmospherics.dm" #include "code\datums\supplypacks\contraband.dm" @@ -454,6 +454,7 @@ #include "code\game\gamemodes\technomancer\spells\illusion.dm" #include "code\game\gamemodes\technomancer\spells\instability_tap.dm" #include "code\game\gamemodes\technomancer\spells\mark_recall.dm" +#include "code\game\gamemodes\technomancer\spells\mend_organs.dm" #include "code\game\gamemodes\technomancer\spells\oxygenate.dm" #include "code\game\gamemodes\technomancer\spells\passwall.dm" #include "code\game\gamemodes\technomancer\spells\phase_shift.dm" @@ -471,23 +472,24 @@ #include "code\game\gamemodes\technomancer\spells\aura\frost_aura.dm" #include "code\game\gamemodes\technomancer\spells\aura\shock_aura.dm" #include "code\game\gamemodes\technomancer\spells\aura\unstable_aura.dm" -#include "code\game\gamemodes\technomancer\spells\insert\corona.dm" -#include "code\game\gamemodes\technomancer\spells\insert\haste.dm" -#include "code\game\gamemodes\technomancer\spells\insert\insert.dm" -#include "code\game\gamemodes\technomancer\spells\insert\mend_burns.dm" -#include "code\game\gamemodes\technomancer\spells\insert\mend_metal.dm" -#include "code\game\gamemodes\technomancer\spells\insert\mend_organs.dm" -#include "code\game\gamemodes\technomancer\spells\insert\mend_wires.dm" -#include "code\game\gamemodes\technomancer\spells\insert\mend_wounds.dm" -#include "code\game\gamemodes\technomancer\spells\insert\purify.dm" -#include "code\game\gamemodes\technomancer\spells\insert\repel_missiles.dm" +#include "code\game\gamemodes\technomancer\spells\modifier\corona.dm" +#include "code\game\gamemodes\technomancer\spells\modifier\haste.dm" +#include "code\game\gamemodes\technomancer\spells\modifier\mend_all.dm" +#include "code\game\gamemodes\technomancer\spells\modifier\mend_life.dm" +#include "code\game\gamemodes\technomancer\spells\modifier\mend_synthetic.dm" +#include "code\game\gamemodes\technomancer\spells\modifier\modifier.dm" +#include "code\game\gamemodes\technomancer\spells\modifier\purify.dm" +#include "code\game\gamemodes\technomancer\spells\modifier\repel_missiles.dm" #include "code\game\gamemodes\technomancer\spells\projectile\beam.dm" #include "code\game\gamemodes\technomancer\spells\projectile\chain_lightning.dm" #include "code\game\gamemodes\technomancer\spells\projectile\force_missile.dm" +#include "code\game\gamemodes\technomancer\spells\projectile\ionic_bolt.dm" +#include "code\game\gamemodes\technomancer\spells\projectile\lesser_chain_lightning.dm" #include "code\game\gamemodes\technomancer\spells\projectile\lightning.dm" #include "code\game\gamemodes\technomancer\spells\projectile\overload.dm" #include "code\game\gamemodes\technomancer\spells\projectile\projectile.dm" #include "code\game\gamemodes\technomancer\spells\spawner\darkness.dm" +#include "code\game\gamemodes\technomancer\spells\spawner\destablize.dm" #include "code\game\gamemodes\technomancer\spells\spawner\fire_blast.dm" #include "code\game\gamemodes\technomancer\spells\spawner\pulsar.dm" #include "code\game\gamemodes\technomancer\spells\spawner\spawner.dm" @@ -820,7 +822,6 @@ #include "code\game\objects\items\weapons\cigs_lighters.dm" #include "code\game\objects\items\weapons\clown_items.dm" #include "code\game\objects\items\weapons\cosmetics.dm" -#include "code\game\objects\items\weapons\dice.dm" #include "code\game\objects\items\weapons\dna_injector.dm" #include "code\game\objects\items\weapons\explosives.dm" #include "code\game\objects\items\weapons\extinguisher.dm" @@ -1397,6 +1398,7 @@ #include "code\modules\games\cah_white_cards.dm" #include "code\modules\games\cardemon.dm" #include "code\modules\games\cards.dm" +#include "code\modules\games\dice.dm" #include "code\modules\games\spaceball_cards.dm" #include "code\modules\games\tarot.dm" #include "code\modules\genetics\side_effects.dm" @@ -1411,6 +1413,7 @@ #include "code\modules\hydroponics\seed.dm" #include "code\modules\hydroponics\seed_controller.dm" #include "code\modules\hydroponics\seed_datums.dm" +#include "code\modules\hydroponics\seed_gene_mut.dm" #include "code\modules\hydroponics\seed_machines.dm" #include "code\modules\hydroponics\seed_mobs.dm" #include "code\modules\hydroponics\seed_packets.dm"