diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 537f77eee51..fc735594542 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -4,7 +4,7 @@ #define TRANSITIONEDGE 7 // Distance from edge to move to another z-level. -// Invisibility constants. +// Invisibility constants. These should only be used for TRUE invisibility, AKA nothing living players touch #define INVISIBILITY_LIGHTING 20 #define INVISIBILITY_LEVEL_ONE 35 #define INVISIBILITY_LEVEL_TWO 45 @@ -21,6 +21,9 @@ #define SEE_INVISIBLE_MINIMUM 5 #define INVISIBILITY_MAXIMUM 100 +// Pseudo-Invis, like Ninja, Ling, Etc. +#define EFFECTIVE_INVIS 50 // Below this, can't be examined, may as well be invisible to the game + // For the client FPS pref and anywhere else #define MAX_CLIENT_FPS 200 diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 012677200c3..c73ebf4d41e 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -177,6 +177,9 @@ #define O_LIVER "liver" #define O_KIDNEYS "kidneys" #define O_APPENDIX "appendix" +#define O_VOICE "voicebox" + +// Non-Standard organs #define O_PLASMA "plasma vessel" #define O_HIVE "hive node" #define O_NUTRIENT "nutrient vessel" diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm index 81a55f84d7b..f12b630979c 100644 --- a/code/__defines/species_languages.dm +++ b/code/__defines/species_languages.dm @@ -50,6 +50,7 @@ #define LANGUAGE_MINBUS "Minbus" #define LANGUAGE_EVENT1 "Occursus" #define LANGUAGE_AKHANI "Akhani" +#define LANGUAGE_ALAI "Alai" // Language flags. #define WHITELISTED 1 // Language is available if the speaker is whitelisted. diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm index d7905146141..44137b0431b 100644 --- a/code/__defines/subsystems.dm +++ b/code/__defines/subsystems.dm @@ -30,6 +30,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G #define INIT_ORDER_DEFAULT 0 #define INIT_ORDER_LIGHTING 0 #define INIT_ORDER_AIR -1 +#define INIT_ORDER_PLANETS -4 #define INIT_ORDER_OVERLAY -6 #define INIT_ORDER_XENOARCH -20 @@ -42,6 +43,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G #define FIRE_PRIORITY_AIRFLOW 30 #define FIRE_PRIORITY_AIR 35 #define FIRE_PRIORITY_DEFAULT 50 +#define FIRE_PRIORITY_PLANETS 75 #define FIRE_PRIORITY_MACHINES 100 #define FIRE_PRIORITY_OVERLAYS 500 diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index c0c4f18f6b8..13c02c88ba3 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -1073,47 +1073,7 @@ var/global/list/common_tools = list( if(istype(I, /obj/item/device/assembly/signaler)) return TRUE return -/* -/proc/iswrench(O) - if(istype(O, /obj/item/weapon/wrench)) - return 1 - return 0 -/proc/iswelder(O) - if(istype(O, /obj/item/weapon/weldingtool)) - return 1 - return 0 - -/proc/iscoil(O) - if(istype(O, /obj/item/stack/cable_coil)) - return 1 - return 0 - -/proc/iswirecutter(O) - if(istype(O, /obj/item/weapon/tool/wirecutters)) - return 1 - return 0 - -/proc/isscrewdriver(O) - if(istype(O, /obj/item/weapon/tool/screwdriver)) - return 1 - return 0 - -/proc/ismultitool(O) - if(istype(O, /obj/item/device/multitool)) - return 1 - return 0 - -/proc/iscrowbar(O) - if(istype(O, /obj/item/weapon/tool/crowbar)) - return 1 - return 0 - -/proc/iswire(O) - if(istype(O, /obj/item/stack/cable_coil)) - return 1 - return 0 -*/ proc/is_hot(obj/item/W as obj) switch(W.type) if(/obj/item/weapon/weldingtool) diff --git a/code/controllers/Processes/planet.dm b/code/controllers/Processes/planet.dm deleted file mode 100644 index 770b3a5e873..00000000000 --- a/code/controllers/Processes/planet.dm +++ /dev/null @@ -1,95 +0,0 @@ -var/datum/controller/process/planet/planet_controller = null - -/datum/controller/process/planet - var/list/planets = list() - var/list/z_to_planet = list() - -/datum/controller/process/planet/setup() - name = "planet controller" - planet_controller = src - schedule_interval = 1 MINUTE - - var/list/planet_datums = typesof(/datum/planet) - /datum/planet - for(var/P in planet_datums) - var/datum/planet/NP = new P() - planets.Add(NP) - - allocateTurfs() - -/datum/controller/process/planet/proc/allocateTurfs() - for(var/turf/simulated/OT in outdoor_turfs) - for(var/datum/planet/P in planets) - if(OT.z in P.expected_z_levels) - P.planet_floors |= OT - OT.vis_contents |= P.weather_holder.visuals - break - outdoor_turfs.Cut() //Why were you in there INCORRECTLY? - - for(var/turf/unsimulated/wall/planetary/PW in planetary_walls) - for(var/datum/planet/P in planets) - if(PW.type == P.planetary_wall_type) - P.planet_walls |= PW - break - planetary_walls.Cut() - -/datum/controller/process/planet/proc/unallocateTurf(var/turf/T) - for(var/planet in planets) - var/datum/planet/P = planet - if(T.z in P.expected_z_levels) - P.planet_floors -= T - T.vis_contents -= P.weather_holder.visuals - -/datum/controller/process/planet/doWork() - if(outdoor_turfs.len || planetary_walls.len) - allocateTurfs() - - for(var/datum/planet/P in planets) - P.process(schedule_interval / 10) - SCHECK //Your process() really shouldn't take this long... - - //Sun light needs changing - if(P.needs_work & PLANET_PROCESS_SUN) - P.needs_work &= ~PLANET_PROCESS_SUN - // Remove old value from corners - var/list/sunlit_corners = P.sunlit_corners - var/old_lum_r = -P.sun["lum_r"] - var/old_lum_g = -P.sun["lum_g"] - var/old_lum_b = -P.sun["lum_b"] - if(old_lum_r || old_lum_g || old_lum_b) - for(var/C in P.sunlit_corners) - var/datum/lighting_corner/LC = C - LC.update_lumcount(old_lum_r, old_lum_g, old_lum_b) - SCHECK - sunlit_corners.Cut() - - // Calculate new values to apply - var/new_brightness = P.sun["brightness"] - var/new_color = P.sun["color"] - var/lum_r = new_brightness * GetRedPart (new_color) / 255 - var/lum_g = new_brightness * GetGreenPart(new_color) / 255 - var/lum_b = new_brightness * GetBluePart (new_color) / 255 - var/static/update_gen = -1 // Used to prevent double-processing corners. Otherwise would happen when looping over adjacent turfs. - for(var/I in P.planet_floors) - var/turf/simulated/T = I - if(!T.lighting_corners_initialised) - T.generate_missing_corners() - for(var/C in T.get_corners()) - var/datum/lighting_corner/LC = C - if(LC.update_gen != update_gen && LC.active) - sunlit_corners += LC - LC.update_gen = update_gen - LC.update_lumcount(lum_r, lum_g, lum_b) - SCHECK - update_gen-- - P.sun["lum_r"] = lum_r - P.sun["lum_g"] = lum_g - P.sun["lum_b"] = lum_b - - //Temperature needs updating - if(P.needs_work & PLANET_PROCESS_TEMP) - P.needs_work &= ~PLANET_PROCESS_TEMP - //Set new temperatures - for(var/W in P.planet_walls) - var/turf/unsimulated/wall/planetary/wall = W - wall.set_temperature(P.weather_holder.temperature) - SCHECK diff --git a/code/controllers/Processes/supply.dm b/code/controllers/Processes/supply.dm index 891a511ec6d..5b3e4f6f2b1 100644 --- a/code/controllers/Processes/supply.dm +++ b/code/controllers/Processes/supply.dm @@ -1,6 +1,229 @@ +//Config stuff +#define SUPPLY_DOCKZ 2 //Z-level of the Dock. +#define SUPPLY_STATIONZ 1 //Z-level of the Station. +#define SUPPLY_STATION_AREATYPE "/area/supply/station" //Type of the supply shuttle area for station +#define SUPPLY_DOCK_AREATYPE "/area/supply/dock" //Type of the supply shuttle area for dock + +//Supply packs are in /code/datums/supplypacks +//Computers are in /code/game/machinery/computer/supply.dm + +/datum/supply_order + var/ordernum + var/datum/supply_packs/object = null + var/orderedby = null + var/comment = null + +/datum/exported_crate + var/name + var/value + + +var/datum/controller/supply/supply_controller = new() + +/datum/controller/supply + //supply points + var/points = 50 + var/points_per_process = 1.5 + var/points_per_slip = 2 + var/points_per_platinum = 5 // 5 points per sheet + var/points_per_phoron = 5 + var/points_per_money = 0.02 // 1 point for $50 + //control + var/ordernum + var/list/shoppinglist = list() + var/list/requestlist = list() + var/list/supply_packs = list() + var/list/exported_crates = list() + //shuttle movement + var/movetime = 1200 + var/datum/shuttle/ferry/supply/shuttle + +/datum/controller/supply/New() + ordernum = rand(1,9000) + + for(var/typepath in (typesof(/datum/supply_packs) - /datum/supply_packs)) + var/datum/supply_packs/P = new typepath() + supply_packs[P.name] = P + /datum/controller/process/supply/setup() name = "supply controller" schedule_interval = 300 // every 30 seconds /datum/controller/process/supply/doWork() - supply_controller.process() \ No newline at end of file + supply_controller.process() + +// Supply shuttle ticker - handles supply point regeneration +// This is called by the process scheduler every thirty seconds +/datum/controller/supply/proc/process() + points += points_per_process + +//To stop things being sent to CentCom which should not be sent to centcomm. Recursively checks for these types. +/datum/controller/supply/proc/forbidden_atoms_check(atom/A) + if(isliving(A)) + return 1 + if(istype(A,/obj/item/weapon/disk/nuclear)) + return 1 + if(istype(A,/obj/machinery/nuclearbomb)) + return 1 + if(istype(A,/obj/item/device/radio/beacon)) + return 1 + + for(var/atom/B in A.contents) + if(.(B)) + return 1 + +//Selling +/datum/controller/supply/proc/sell() + var/area/area_shuttle = shuttle.get_location_area() + if(!area_shuttle) + return + + callHook("sell_shuttle", list(area_shuttle)); + + var/phoron_count = 0 + var/plat_count = 0 + var/money_count = 0 + + exported_crates = list() + + for(var/atom/movable/MA in area_shuttle) + if(MA.anchored) + continue + + // Must be in a crate! + if(istype(MA,/obj/structure/closet/crate)) + var/oldpoints = points + var/oldphoron = phoron_count + var/oldplatinum = plat_count + var/oldmoney = money_count + + var/obj/structure/closet/crate/CR = MA + callHook("sell_crate", list(CR, area_shuttle)) + + points += CR.points_per_crate + var/find_slip = 1 + + for(var/atom/A in CR) + // Sell manifests + if(find_slip && istype(A,/obj/item/weapon/paper/manifest)) + var/obj/item/weapon/paper/manifest/slip = A + if(!slip.is_copy && slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense + points += points_per_slip + find_slip = 0 + continue + + // Sell phoron and platinum + if(istype(A, /obj/item/stack)) + var/obj/item/stack/P = A + switch(P.get_material_name()) + if("phoron") + phoron_count += P.get_amount() + if("platinum") + plat_count += P.get_amount() + + //Sell spacebucks + if(istype(A, /obj/item/weapon/spacecash)) + var/obj/item/weapon/spacecash/cashmoney = A + money_count += cashmoney.worth + + var/datum/exported_crate/EC = new /datum/exported_crate() + EC.name = CR.name + EC.value = points - oldpoints + EC.value += (phoron_count - oldphoron) * points_per_phoron + EC.value += (plat_count - oldplatinum) * points_per_platinum + EC.value += (money_count - oldmoney) * points_per_money + exported_crates += EC + + qdel(MA) + + points += phoron_count * points_per_phoron + points += plat_count * points_per_platinum + points += money_count * points_per_money + +//Buying +/datum/controller/supply/proc/buy() + if(!shoppinglist.len) + return + + var/orderedamount = shoppinglist.len + + var/area/area_shuttle = shuttle.get_location_area() + if(!area_shuttle) + return + + var/list/clear_turfs = list() + + for(var/turf/T in area_shuttle) + if(T.density) + continue + var/contcount + for(var/atom/A in T.contents) + if(!A.simulated) + continue + contcount++ + if(contcount) + continue + clear_turfs += T + + for(var/S in shoppinglist) + if(!clear_turfs.len) + break + + var/i = rand(1,clear_turfs.len) + var/turf/pickedloc = clear_turfs[i] + clear_turfs.Cut(i,i+1) + shoppinglist -= S + + var/datum/supply_order/SO = S + var/datum/supply_packs/SP = SO.object + + var/obj/A = new SP.containertype(pickedloc) + A.name = "[SP.containername] [SO.comment ? "([SO.comment])":"" ]" + + //supply manifest generation begin + var/obj/item/weapon/paper/manifest/slip + if(!SP.contraband) + slip = new /obj/item/weapon/paper/manifest(A) + slip.is_copy = 0 + slip.info = "

[command_name()] Shipping Manifest



" + slip.info +="Order #[SO.ordernum]
" + slip.info +="Destination: [station_name()]
" + slip.info +="[orderedamount] PACKAGES IN THIS SHIPMENT
" + slip.info +="CONTENTS:

" + slip.info += "CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS
" + + return diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index f6db4f65d43..9e29ba9998e 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -60,6 +60,7 @@ var/list/gamemode_cache = list() var/humans_need_surnames = 0 var/allow_random_events = 0 // enables random events mid-round when set to 1 var/allow_ai = 1 // allow ai job + var/allow_ai_drones = 0 // allow ai controlled drones var/hostedby = null var/respawn = 1 var/guest_jobban = 1 @@ -400,6 +401,9 @@ var/list/gamemode_cache = list() if ("allow_ai") config.allow_ai = 1 + if ("allow_ai_drones") + config.allow_ai_drones = 1 + // if ("authentication") // config.enable_authentication = 1 diff --git a/code/controllers/subsystems/planets.dm b/code/controllers/subsystems/planets.dm new file mode 100644 index 00000000000..f7fc49b6612 --- /dev/null +++ b/code/controllers/subsystems/planets.dm @@ -0,0 +1,187 @@ +SUBSYSTEM_DEF(planets) + name = "Planets" + init_order = INIT_ORDER_PLANETS + priority = FIRE_PRIORITY_PLANETS + wait = 2 SECONDS + flags = SS_BACKGROUND + runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + + var/list/new_outdoor_turfs = list() + var/list/new_outdoor_walls = list() + + var/list/planets = list() + var/list/z_to_planet = list() + + var/list/currentrun = list() + + var/list/needs_sun_update = list() + var/list/needs_temp_update = list() + +/datum/controller/subsystem/planets/Initialize(timeofday) + admin_notice("Initializing planetary weather.", R_DEBUG) + createPlanets() + allocateTurfs(TRUE) + ..() + +/datum/controller/subsystem/planets/proc/createPlanets() + var/list/planet_datums = subtypesof(/datum/planet) + for(var/P in planet_datums) + var/datum/planet/NP = new P() + planets.Add(NP) + for(var/Z in NP.expected_z_levels) + if(Z > z_to_planet.len) + z_to_planet.len = Z + if(z_to_planet[Z]) + admin_notice("Z[Z] is shared by more than one planet!", R_DEBUG) + continue + z_to_planet[Z] = NP + +/datum/controller/subsystem/planets/proc/addTurf(var/turf/T,var/is_edge) + if(is_edge) + new_outdoor_walls |= T + else + new_outdoor_turfs |= T + +/datum/controller/subsystem/planets/proc/removeTurf(var/turf/T,var/is_edge) + if(is_edge) + new_outdoor_walls -= T + else + new_outdoor_turfs -= T + + if(z_to_planet.len >= T.z) + var/datum/planet/P = z_to_planet[T.z] + if(!P) + return + if(is_edge) + P.planet_floors -= T + else + P.planet_walls -= T + T.vis_contents -= P.weather_holder.visuals + T.vis_contents -= P.weather_holder.special_visuals + +/datum/controller/subsystem/planets/proc/allocateTurfs(var/initial = FALSE) + var/list/currentlist = new_outdoor_turfs + while(currentlist.len) + var/turf/simulated/OT = currentlist[currentlist.len] + currentlist.len-- + if(istype(OT) && OT.outdoors && z_to_planet.len >= OT.z && z_to_planet[OT.z]) + var/datum/planet/P = z_to_planet[OT.z] + P.planet_floors |= OT + OT.vis_contents |= P.weather_holder.visuals + OT.vis_contents |= P.weather_holder.special_visuals + if(!initial && MC_TICK_CHECK) + return + + currentlist = new_outdoor_walls + while(currentlist.len) + var/turf/unsimulated/wall/planetary/PW = currentlist[currentlist.len] + currentlist.len-- + if(istype(PW) && z_to_planet.len >= PW.z && z_to_planet[PW.z]) + var/datum/planet/P = z_to_planet[PW.z] + P.planet_walls |= PW + if(!initial && MC_TICK_CHECK) + return + +/datum/controller/subsystem/planets/proc/unallocateTurf(var/turf/simulated/T) + if(istype(T) && z_to_planet[T.z]) + var/datum/planet/P = z_to_planet[T.z] + P.planet_floors -= T + T.vis_contents -= P.weather_holder.visuals + T.vis_contents -= P.weather_holder.special_visuals + + +/datum/controller/subsystem/planets/fire(resumed = 0) + if(new_outdoor_turfs.len || new_outdoor_walls.len) + allocateTurfs() + + if(!resumed) + src.currentrun = planets.Copy() + + var/list/needs_sun_update = src.needs_sun_update + while(needs_sun_update.len) + var/datum/planet/P = needs_sun_update[needs_sun_update.len] + needs_sun_update.len-- + updateSunlight(P) + if(MC_TICK_CHECK) + return + + var/list/needs_temp_update = src.needs_temp_update + while(needs_temp_update.len) + var/datum/planet/P = needs_temp_update[needs_temp_update.len] + needs_temp_update.len-- + updateTemp(P) + if(MC_TICK_CHECK) + return + + var/list/currentrun = src.currentrun + while(currentrun.len) + var/datum/planet/P = currentrun[currentrun.len] + currentrun.len-- + + P.process(last_fire) + + //Sun light needs changing + if(P.needs_work & PLANET_PROCESS_SUN) + P.needs_work &= ~PLANET_PROCESS_SUN + needs_sun_update |= P + + //Temperature needs updating + if(P.needs_work & PLANET_PROCESS_TEMP) + P.needs_work &= ~PLANET_PROCESS_TEMP + needs_temp_update |= P + + if(MC_TICK_CHECK) + return + +/datum/controller/subsystem/planets/proc/updateSunlight(var/datum/planet/P) + // Remove old value from corners + var/list/sunlit_corners = P.sunlit_corners + var/old_lum_r = -P.sun["lum_r"] + var/old_lum_g = -P.sun["lum_g"] + var/old_lum_b = -P.sun["lum_b"] + if(old_lum_r || old_lum_g || old_lum_b) + for(var/C in sunlit_corners) + var/datum/lighting_corner/LC = C + LC.update_lumcount(old_lum_r, old_lum_g, old_lum_b) + CHECK_TICK + sunlit_corners.Cut() + + // Calculate new values to apply + var/new_brightness = P.sun["brightness"] + var/new_color = P.sun["color"] + var/lum_r = new_brightness * GetRedPart (new_color) / 255 + var/lum_g = new_brightness * GetGreenPart(new_color) / 255 + var/lum_b = new_brightness * GetBluePart (new_color) / 255 + var/static/update_gen = -1 // Used to prevent double-processing corners. Otherwise would happen when looping over adjacent turfs. + for(var/I in P.planet_floors) + var/turf/simulated/T = I + if(!T.lighting_corners_initialised) + T.generate_missing_corners() + for(var/C in T.get_corners()) + var/datum/lighting_corner/LC = C + if(LC.update_gen != update_gen && LC.active) + sunlit_corners += LC + LC.update_gen = update_gen + LC.update_lumcount(lum_r, lum_g, lum_b) + CHECK_TICK + update_gen-- + P.sun["lum_r"] = lum_r + P.sun["lum_g"] = lum_g + P.sun["lum_b"] = lum_b + +/datum/controller/subsystem/planets/proc/updateTemp(var/datum/planet/P) + //Set new temperatures + for(var/W in P.planet_walls) + var/turf/unsimulated/wall/planetary/wall = W + wall.set_temperature(P.weather_holder.temperature) + CHECK_TICK + +/datum/controller/subsystem/planets/proc/weatherDisco() + var/count = 100000 + while(count > 0) + count-- + for(var/planet in planets) + var/datum/planet/P = planet + if(P.weather_holder) + P.weather_holder.change_weather(pick(P.weather_holder.allowed_weather_types)) + sleep(3) diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index 8d02fda2ebb..f1249cfe0c3 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -133,8 +133,5 @@ if("Vote") debug_variables(vote) feedback_add_details("admin_verb", "DVote") - if("Planets") - debug_variables(planet_controller) - feedback_add_details("admin_verb", "DPlanets") message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.") return diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index b6654650847..765e1ee9e93 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -84,10 +84,8 @@ for(var/mob/living/silicon/robot/robot in mob_list) // No combat/syndicate cyborgs, no drones. - if(robot.module && robot.module.hide_on_manifest) - continue - - bot[robot.name] = "[robot.modtype] [robot.braintype]" + if(!robot.scrambledcodes && !(robot.module && robot.module.hide_on_manifest)) + bot[robot.name] = "[robot.modtype] [robot.braintype]" if(heads.len > 0) diff --git a/code/datums/observation/turf_changed.dm b/code/datums/observation/turf_changed.dm index 861b4092274..0bb0ed91158 100644 --- a/code/datums/observation/turf_changed.dm +++ b/code/datums/observation/turf_changed.dm @@ -20,9 +20,9 @@ var/decl/observ/turf_changed/turf_changed_event = new() * Turf Changed Handling * ************************/ -/turf/ChangeTurf() +/turf/ChangeTurf(var/turf/N, var/tell_universe, var/force_lighting_update, var/preserve_outdoors) var/old_density = density var/old_opacity = opacity - . = ..() + . = ..(N, tell_universe, force_lighting_update, preserve_outdoors) if(.) turf_changed_event.raise_event(src, old_density, density, old_opacity, opacity) \ No newline at end of file diff --git a/code/defines/obj.dm b/code/defines/obj.dm index ba809cb977f..f2cec96aab8 100644 --- a/code/defines/obj.dm +++ b/code/defines/obj.dm @@ -144,7 +144,7 @@ var/global/list/PDA_Manifest = list() for(var/mob/living/silicon/robot/robot in mob_list) // No combat/syndicate cyborgs, no drones. - if(robot.module && robot.module.hide_on_manifest) + if(!robot.scrambledcodes && !(robot.module && robot.module.hide_on_manifest)) continue bot[++bot.len] = list("name" = robot.real_name, "rank" = "[robot.modtype] [robot.braintype]", "active" = "Active") diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index 484ff8ea33e..7496551c25f 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -79,7 +79,9 @@ Think through your actions and make the roleplay immersive! Please remember all \ rules aside from those without explicit exceptions apply to antagonists." - var/can_use_aooc = TRUE // If true, will be given the AOOC verb, along with the ability to use it. +// var/can_use_aooc = TRUE // If true, will be given the AOOC verb, along with the ability to use it. + var/can_hear_aooc = TRUE // If FALSE, the antag can neither speak nor hear AOOC. If TRUE, they can at least hear it. + var/can_speak_aooc = TRUE // If TRUE, the antag can freely spean in AOOC. /datum/antagonist/New() ..() diff --git a/code/game/antagonist/antagonist_add.dm b/code/game/antagonist/antagonist_add.dm index 67eb7e2e726..d5fa2c1fe6f 100644 --- a/code/game/antagonist/antagonist_add.dm +++ b/code/game/antagonist/antagonist_add.dm @@ -36,7 +36,7 @@ and it otherwise has no bearing on your round." player.current.verbs |= /mob/living/proc/write_ambition - if(can_use_aooc) + if(can_speak_aooc) player.current.client.verbs += /client/proc/aooc // Handle only adding a mind and not bothering with gear etc. diff --git a/code/game/antagonist/outsider/ert.dm b/code/game/antagonist/outsider/ert.dm index c1aec2bcf82..245296084c6 100644 --- a/code/game/antagonist/outsider/ert.dm +++ b/code/game/antagonist/outsider/ert.dm @@ -25,7 +25,8 @@ var/datum/antagonist/ert/ert initial_spawn_req = 5 initial_spawn_target = 7 - can_use_aooc = FALSE // They're the good guys. + can_hear_aooc = FALSE // They're the good guys. + can_speak_aooc = FALSE // Just in case the above var bugs, or gets touched. /datum/antagonist/ert/create_default(var/mob/source) var/mob/living/carbon/human/M = ..() diff --git a/code/game/antagonist/outsider/trader.dm b/code/game/antagonist/outsider/trader.dm index 9603b495238..69af3883b97 100644 --- a/code/game/antagonist/outsider/trader.dm +++ b/code/game/antagonist/outsider/trader.dm @@ -24,7 +24,7 @@ var/datum/antagonist/trader/traders initial_spawn_req = 5 initial_spawn_target = 7 - can_use_aooc = FALSE // They're not real antags. + can_speak_aooc = FALSE // They're not real antags. /datum/antagonist/trader/create_default(var/mob/source) var/mob/living/carbon/human/M = ..() diff --git a/code/game/antagonist/station/infiltrator.dm b/code/game/antagonist/station/infiltrator.dm index 8ca6f4ac4db..b51e7e74fbb 100644 --- a/code/game/antagonist/station/infiltrator.dm +++ b/code/game/antagonist/station/infiltrator.dm @@ -13,6 +13,7 @@ var/datum/antagonist/traitor/infiltrator/infiltrators welcome_text = "To speak on your team's private channel, use :t." protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director") flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE + can_speak_aooc = TRUE /datum/antagonist/traitor/infiltrator/New() ..() diff --git a/code/game/antagonist/station/renegade.dm b/code/game/antagonist/station/renegade.dm index 6f7ec893229..3e8afae32df 100644 --- a/code/game/antagonist/station/renegade.dm +++ b/code/game/antagonist/station/renegade.dm @@ -17,7 +17,7 @@ var/datum/antagonist/renegade/renegades Think through your actions and make the roleplay immersive! Please remember all \ rules aside from those without explicit exceptions apply to antagonists." flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE - can_use_aooc = FALSE + can_speak_aooc = FALSE // They aren't 'true' antags, but they still need to hear blanket antag instructions hard_cap = 8 hard_cap_round = 12 @@ -61,8 +61,6 @@ var/datum/antagonist/renegade/renegades list(/obj/item/weapon/gun/projectile/luger,/obj/item/weapon/gun/projectile/luger/brown) ) - can_use_aooc = FALSE // They aren't 'true' antags. - /datum/antagonist/renegade/New() ..() renegades = src diff --git a/code/game/antagonist/station/thug.dm b/code/game/antagonist/station/thug.dm index 8810fca7d04..61d92e1646f 100644 --- a/code/game/antagonist/station/thug.dm +++ b/code/game/antagonist/station/thug.dm @@ -15,4 +15,4 @@ var/datum/antagonist/thug/thugs Think through your actions and make the roleplay immersive! Please remember all \ rules aside from those with explicit exceptions apply to antagonists." flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE - can_use_aooc = FALSE + can_speak_aooc = FALSE diff --git a/code/game/antagonist/station/traitor.dm b/code/game/antagonist/station/traitor.dm index d0a1f54ed21..3681cf236d7 100644 --- a/code/game/antagonist/station/traitor.dm +++ b/code/game/antagonist/station/traitor.dm @@ -5,7 +5,7 @@ var/datum/antagonist/traitor/traitors id = MODE_TRAITOR protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director") flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE - can_use_aooc = FALSE + can_speak_aooc = FALSE // If they want to plot and plan as this sort of traitor, they'll need to do it ICly. /datum/antagonist/traitor/auto id = MODE_AUTOTRAITOR diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 337adfb7a36..873e720512d 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -31,7 +31,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station ambience = list('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/main.ogg','sound/music/traitor.ogg','sound/ambience/serspaceamb1.ogg') base_turf = /turf/space -area/space/atmosalert() +/area/space/atmosalert() return /area/space/fire_alert() @@ -451,20 +451,6 @@ area/space/atmosalert() icon_state = "cave" sound_env = SMALL_ENCLOSED - - - - - - - - - - - - - - /area/planet/clown name = "\improper Clown Planet" icon_state = "honk" @@ -906,9 +892,6 @@ area/space/atmosalert() /area/maintenance/substation/security // Security, Brig, Permabrig, etc. name = "Security Substation" - - - //Hallway /area/hallway/primary/ @@ -1115,7 +1098,7 @@ area/space/atmosalert() name = "\improper Research Server Room" icon_state = "server" -//Crew +//Civilian /area/crew_quarters name = "\improper Dormitories" @@ -1978,6 +1961,24 @@ area/space/atmosalert() name = "\improper Vacant Office" icon_state = "security" +/area/janitor/ + name = "\improper Custodial Closet" + icon_state = "janitor" + +/area/hydroponics + name = "\improper Hydroponics" + icon_state = "hydro" + +/area/hydroponics/cafegarden + name = "\improper Cafeteria Garden" + icon_state = "cafe_garden" + +/area/hydroponics/garden + name = "\improper Garden" + icon_state = "garden" + +// SUPPLY + /area/quartermaster name = "\improper Quartermasters" icon_state = "quart" @@ -2011,23 +2012,20 @@ area/space/atmosalert() name = "\improper Cargo Mining Dock" icon_state = "mining" -/area/janitor/ - name = "\improper Custodial Closet" - icon_state = "janitor" +/area/supply/station + name = "Supply Shuttle" + icon_state = "shuttle3" + requires_power = 0 + base_turf = /turf/space -/area/hydroponics - name = "\improper Hydroponics" - icon_state = "hydro" +/area/supply/dock + name = "Supply Shuttle" + icon_state = "shuttle3" + requires_power = 0 + base_turf = /turf/space -/area/hydroponics/cafegarden - name = "\improper Cafeteria Garden" - icon_state = "cafe_garden" +// SCIENCE -/area/hydroponics/garden - name = "\improper Garden" - icon_state = "garden" - -//rnd (Research and Development /area/rnd/research name = "\improper Research and Development" icon_state = "research" diff --git a/code/game/gamemodes/changeling/absorbed_dna.dm b/code/game/gamemodes/changeling/absorbed_dna.dm index 3c23f0270c3..26d433cd8cc 100644 --- a/code/game/gamemodes/changeling/absorbed_dna.dm +++ b/code/game/gamemodes/changeling/absorbed_dna.dm @@ -5,12 +5,14 @@ var/list/languages var/identifying_gender var/list/flavour_texts + var/list/genMods -/datum/absorbed_dna/New(var/newName, var/newDNA, var/newSpecies, var/newLanguages, var/newIdentifying_Gender, var/list/newFlavour) +/datum/absorbed_dna/New(var/newName, var/newDNA, var/newSpecies, var/newLanguages, var/newIdentifying_Gender, var/list/newFlavour, var/list/newGenMods) ..() name = newName dna = newDNA speciesName = newSpecies languages = newLanguages identifying_gender = newIdentifying_Gender - flavour_texts = newFlavour ? newFlavour.Copy() : null \ No newline at end of file + flavour_texts = newFlavour ? newFlavour.Copy() : null + genMods = newGenMods ? newGenMods.Copy() : null \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm index f76fd5ca477..45b230b00c1 100644 --- a/code/game/gamemodes/changeling/powers/absorb.dm +++ b/code/game/gamemodes/changeling/powers/absorb.dm @@ -78,7 +78,7 @@ src << "We can now re-adapt, reverting our evolution so that we may start anew, if needed." - var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages, T.identifying_gender, T.flavor_texts) + var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages, T.identifying_gender, T.flavor_texts, T.modifiers) absorbDNA(newDNA) if(T.mind && T.mind.changeling) diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm index 92257925757..6dd16061a12 100644 --- a/code/game/gamemodes/changeling/powers/transform.dm +++ b/code/game/gamemodes/changeling/powers/transform.dm @@ -48,6 +48,13 @@ src.UpdateAppearance() domutcheck(src, null) changeling_update_languages(changeling.absorbed_languages) + if(chosen_dna.genMods) + var/mob/living/carbon/human/self = src + for(var/datum/modifier/mod in self.modifiers) + self.modifiers.Remove(mod.type) + + for(var/datum/modifier/mod in chosen_dna.genMods) + self.modifiers.Add(mod.type) src.verbs -= /mob/proc/changeling_transform spawn(10) diff --git a/code/game/gamemodes/technomancer/spell_objs_helpers.dm b/code/game/gamemodes/technomancer/spell_objs_helpers.dm index f11c027566a..105b3b3e9c8 100644 --- a/code/game/gamemodes/technomancer/spell_objs_helpers.dm +++ b/code/game/gamemodes/technomancer/spell_objs_helpers.dm @@ -31,7 +31,7 @@ return TRUE /obj/item/weapon/spell/proc/within_range(var/atom/target, var/max_range = 7) // Beyond 7 is off the screen. - if(range(get_dist(owner, target) <= max_range)) + if(target in view(max_range, owner)) return TRUE return FALSE diff --git a/code/game/gamemodes/technomancer/spells/apportation.dm b/code/game/gamemodes/technomancer/spells/apportation.dm index 9fafc47ae38..452ddc52fa6 100644 --- a/code/game/gamemodes/technomancer/spells/apportation.dm +++ b/code/game/gamemodes/technomancer/spells/apportation.dm @@ -21,11 +21,13 @@ if(!AM.loc) //Don't teleport HUD telements to us. return if(AM.anchored) - user << "\The [hit_atom] is firmly secured and anchored, you can't move it!" + to_chat(user, "\The [hit_atom] is firmly secured and anchored, you can't move it!") return + if(!within_range(hit_atom) && !check_for_scepter()) - user << "\The [hit_atom] is too far away." + to_chat(user, "\The [hit_atom] is too far away.") return + //Teleporting an item. if(istype(hit_atom, /obj/item)) var/obj/item/I = hit_atom @@ -47,7 +49,7 @@ //Now let's try to teleport a living mob. else if(istype(hit_atom, /mob/living)) var/mob/living/L = hit_atom - L << "You are teleported towards \the [user]." + to_chat(L, "You are teleported towards \the [user].") var/datum/effect/effect/system/spark_spread/s1 = new /datum/effect/effect/system/spark_spread var/datum/effect/effect/system/spark_spread/s2 = new /datum/effect/effect/system/spark_spread s1.set_up(2, 1, user) @@ -60,7 +62,7 @@ spawn(1 SECOND) if(!user.Adjacent(L)) - user << "\The [L] is out of your reach." + to_chat(user, "\The [L] is out of your reach.") qdel(src) return diff --git a/code/game/jobs/job/civilian_chaplain.dm b/code/game/jobs/job/civilian_chaplain.dm index 2eece781ec8..e24e462fdf0 100644 --- a/code/game/jobs/job/civilian_chaplain.dm +++ b/code/game/jobs/job/civilian_chaplain.dm @@ -149,5 +149,7 @@ feedback_set_details("religion_book","[new_book_style]") return 1 +/* If you uncomment this, every time the mob preview updates it makes a new PDA. It seems to work just fine and display without it, so why this exists, haven't a clue. -Hawk /datum/job/chaplain/equip_preview(var/mob/living/carbon/human/H, var/alt_title) return equip(H, alt_title, FALSE) +*/ diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 04dbaffb539..bfc964f7f21 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -378,7 +378,8 @@ var/global/datum/controller/occupations/job_master H.amend_exploitable(G.path) if(G.slot == "implant") - H.implant_loadout(G) + var/obj/item/weapon/implant/I = G.spawn_item(H) + I.implant_loadout(H) continue if(G.slot && !(G.slot in custom_equip_slots)) diff --git a/code/game/machinery/bioprinter.dm b/code/game/machinery/bioprinter.dm index 0a43acb1724..f66b580c521 100644 --- a/code/game/machinery/bioprinter.dm +++ b/code/game/machinery/bioprinter.dm @@ -13,27 +13,29 @@ idle_power_usage = 40 active_power_usage = 300 - var/stored_matter = 0 - var/max_stored_matter = 0 + var/obj/item/weapon/reagent_containers/container = null // This is the beaker that holds all of the biomass + var/print_delay = 100 + var/base_print_delay = 100 // For Adminbus reasons var/printing var/loaded_dna //Blood sample for DNA hashing. // These should be subtypes of /obj/item/organ + // Costs roughly 20u Phoron (1 sheet) per internal organ, limbs are 60u for limb and extremity var/list/products = list( - "Heart" = list(/obj/item/organ/internal/heart, 25), - "Lungs" = list(/obj/item/organ/internal/lungs, 25), + "Heart" = list(/obj/item/organ/internal/heart, 20), + "Lungs" = list(/obj/item/organ/internal/lungs, 20), "Kidneys" = list(/obj/item/organ/internal/kidneys,20), "Eyes" = list(/obj/item/organ/internal/eyes, 20), - "Liver" = list(/obj/item/organ/internal/liver, 25), - "Arm, Left" = list(/obj/item/organ/external/arm, 65), - "Arm, Right" = list(/obj/item/organ/external/arm/right, 65), - "Leg, Left" = list(/obj/item/organ/external/leg, 65), - "Leg, Right" = list(/obj/item/organ/external/leg/right, 65), - "Foot, Left" = list(/obj/item/organ/external/foot, 40), - "Foot, Right" = list(/obj/item/organ/external/foot/right, 40), - "Hand, Left" = list(/obj/item/organ/external/hand, 40), - "Hand, Right" = list(/obj/item/organ/external/hand/right, 40) + "Liver" = list(/obj/item/organ/internal/liver, 20), + "Arm, Left" = list(/obj/item/organ/external/arm, 40), + "Arm, Right" = list(/obj/item/organ/external/arm/right, 40), + "Leg, Left" = list(/obj/item/organ/external/leg, 40), + "Leg, Right" = list(/obj/item/organ/external/leg/right, 40), + "Foot, Left" = list(/obj/item/organ/external/foot, 20), + "Foot, Right" = list(/obj/item/organ/external/foot/right, 20), + "Hand, Left" = list(/obj/item/organ/external/hand, 20), + "Hand, Right" = list(/obj/item/organ/external/hand/right, 20) ) /obj/machinery/organ_printer/attackby(var/obj/item/O, var/mob/user) @@ -57,25 +59,27 @@ /obj/machinery/organ_printer/New() ..() + component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) component_parts += new /obj/item/weapon/stock_parts/manipulator(src) component_parts += new /obj/item/weapon/stock_parts/manipulator(src) RefreshParts() /obj/machinery/organ_printer/examine(var/mob/user) . = ..() - to_chat(user, "It is loaded with [stored_matter]/[max_stored_matter] matter units.") + var/biomass = get_biomass_volume() + if(biomass) + to_chat(user, "It is loaded with [biomass] units of biomass.") + else + to_chat(user, "It is not loaded with any biomass.") /obj/machinery/organ_printer/RefreshParts() - print_delay = initial(print_delay) - max_stored_matter = 0 - for(var/obj/item/weapon/stock_parts/matter_bin/bin in component_parts) - max_stored_matter += bin.rating * 100 + // Print Delay updating + print_delay = base_print_delay for(var/obj/item/weapon/stock_parts/manipulator/manip in component_parts) print_delay -= (manip.rating-1)*10 print_delay = max(0,print_delay) + . = ..() /obj/machinery/organ_printer/attack_hand(mob/user) @@ -91,6 +95,14 @@ to_chat(user, "\The [src] is busy!") return + if(container) + var/response = alert(user, "What do you want to do?", "Bioprinter Menu", "Print Limbs", "Cancel") + if(response == "Print Limbs") + printing_menu(user) + else + to_chat(user, "\The [src] can't operate without a reagent reservoir!") + +/obj/machinery/organ_printer/proc/printing_menu(mob/user) var/choice = input("What would you like to print?") as null|anything in products if(!choice || printing || (stat & (BROKEN|NOPOWER))) @@ -99,7 +111,7 @@ if(!can_print(choice)) return - stored_matter -= products[choice][2] + container.reagents.remove_reagent("biomass", products[choice][2]) use_power = 2 printing = 1 @@ -118,9 +130,42 @@ print_organ(choice) + return + +/obj/machinery/organ_printer/verb/eject_beaker() + set name = "Eject Beaker" + set category = "Object" + set src in oview(1) + + if(usr.stat != 0) + return + add_fingerprint(usr) + remove_beaker() + return + +// Does exactly what it says it does +// Returns 1 if it succeeds, 0 if it fails. Added in case someone wants to add messages to the user. +/obj/machinery/organ_printer/proc/remove_beaker() + if(container) + container.forceMove(get_turf(src)) + container = null + return 1 + return 0 + +// Checks for reagents, then reports how much biomass it has in it +/obj/machinery/organ_printer/proc/get_biomass_volume() + var/biomass_count = 0 + if(container && container.reagents) + for(var/datum/reagent/R in container.reagents.reagent_list) + if(R.id == "biomass") + biomass_count += R.volume + + return biomass_count + /obj/machinery/organ_printer/proc/can_print(var/choice) - if(stored_matter < products[choice][2]) - visible_message("\The [src] displays a warning: 'Not enough matter. [stored_matter] stored and [products[choice][2]] needed.'") + var/biomass = get_biomass_volume() + if(biomass < products[choice][2]) + visible_message("\The [src] displays a warning: 'Not enough biomass. [biomass] stored and [products[choice][2]] needed.'") return 0 if(!loaded_dna || !loaded_dna["donor"]) @@ -162,6 +207,59 @@ /obj/item/weapon/stock_parts/matter_bin = 2, /obj/item/weapon/stock_parts/manipulator = 2) +// FLESH ORGAN PRINTER +/obj/machinery/organ_printer/flesh + name = "bioprinter" + desc = "It's a machine that prints replacement organs." + icon_state = "bioprinter" + circuit = /obj/item/weapon/circuitboard/bioprinter + +/obj/machinery/organ_printer/flesh/full/New() + . = ..() + container = new /obj/item/weapon/reagent_containers/glass/bottle/biomass(src) + +/obj/machinery/organ_printer/flesh/dismantle() + var/turf/T = get_turf(src) + if(T) + if(container) + container.forceMove(T) + container = null + return ..() + +/obj/machinery/organ_printer/flesh/print_organ(var/choice) + var/obj/item/organ/O = ..() + + playsound(src.loc, 'sound/machines/ding.ogg', 50, 1) + visible_message("\The [src] dings, then spits out \a [O].") + return O + +/obj/machinery/organ_printer/flesh/attackby(obj/item/weapon/W, mob/user) + // DNA sample from syringe. + if(istype(W,/obj/item/weapon/reagent_containers/syringe)) //TODO: Make this actually empty the syringe + var/obj/item/weapon/reagent_containers/syringe/S = W + var/datum/reagent/blood/injected = locate() in S.reagents.reagent_list //Grab some blood + if(injected && injected.data) + loaded_dna = injected.data + S.reagents.remove_reagent("blood", injected.volume) + to_chat(user, "You scan the blood sample into the bioprinter.") + return + else if(istype(W,/obj/item/weapon/reagent_containers/glass)) + var/obj/item/weapon/reagent_containers/glass/G = W + if(container) + to_chat(user, "\The [src] already has a container loaded!") + return + else if(do_after(user, 1 SECOND)) + user.visible_message("[user] has loaded \the [G] into \the [src].", "You load \the [G] into \the [src].") + container = G + user.drop_item() + G.forceMove(src) + return + + return ..() +// END FLESH ORGAN PRINTER + + +/* Roboprinter is made obsolete by the system already in place and mapped into Robotics /obj/item/weapon/circuitboard/roboprinter name = "roboprinter circuit" build_path = /obj/machinery/organ_printer/robot @@ -224,53 +322,4 @@ return return ..() // END ROBOT ORGAN PRINTER - -// FLESH ORGAN PRINTER -/obj/machinery/organ_printer/flesh - name = "bioprinter" - desc = "It's a machine that prints replacement organs." - icon_state = "bioprinter" - circuit = /obj/item/weapon/circuitboard/bioprinter - - var/amount_per_slab = 50 - -/obj/machinery/organ_printer/flesh/full/New() - . = ..() - stored_matter = max_stored_matter - -/obj/machinery/organ_printer/flesh/dismantle() - var/turf/T = get_turf(src) - if(T) - while(stored_matter >= amount_per_slab) - stored_matter -= amount_per_slab - new /obj/item/weapon/reagent_containers/food/snacks/meat(T) - return ..() - -/obj/machinery/organ_printer/flesh/print_organ(var/choice) - var/obj/item/organ/O = ..() - - playsound(src.loc, 'sound/machines/ding.ogg', 50, 1) - visible_message("\The [src] dings, then spits out \a [O].") - return O - -/obj/machinery/organ_printer/flesh/attackby(obj/item/weapon/W, mob/user) - // Load with matter for printing. - if(istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat)) - if((max_stored_matter - stored_matter) < amount_per_slab) - to_chat(user, "\The [src] is too full.") - return - stored_matter += amount_per_slab - user.drop_item() - to_chat(user, "\The [src] processes \the [W]. Levels of stored biomass now: [stored_matter]") - qdel(W) - return - // DNA sample from syringe. - else if(istype(W,/obj/item/weapon/reagent_containers/syringe)) //TODO: Make this actually empty the syringe - var/obj/item/weapon/reagent_containers/syringe/S = W - var/datum/reagent/blood/injected = locate() in S.reagents.reagent_list //Grab some blood - if(injected && injected.data) - loaded_dna = injected.data - to_chat(user, "You scan the blood sample into the bioprinter.") - return - return ..() -// END FLESH ORGAN PRINTER \ No newline at end of file +*/ \ No newline at end of file diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 4239a946fd8..69681d1775b 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -23,7 +23,7 @@ break return selected -#define CLONE_BIOMASS 150 +#define CLONE_BIOMASS 60 /obj/machinery/clonepod name = "cloning pod" @@ -33,17 +33,18 @@ circuit = /obj/item/weapon/circuitboard/clonepod icon = 'icons/obj/cloning.dmi' icon_state = "pod_0" - req_access = list(access_genetics) //For premature unlocking. + req_access = list(access_genetics) // For premature unlocking. var/mob/living/occupant - var/heal_level = 20 //The clone is released once its health reaches this level. + var/heal_level = 20 // The clone is released once its health reaches this level. var/heal_rate = 1 - var/notoxin = 0 var/locked = 0 var/obj/machinery/computer/cloning/connected = null //So we remember the connected clone machine. - var/mess = 0 //Need to clean out it if it's full of exploded clone. - var/attempting = 0 //One clone attempt at a time thanks - var/eject_wait = 0 //Don't eject them as soon as they are created fuckkk - var/biomass = CLONE_BIOMASS * 3 + var/mess = 0 // Need to clean out it if it's full of exploded clone. + var/attempting = 0 // One clone attempt at a time thanks + var/eject_wait = 0 // Don't eject them as soon as they are created fuckkk + + var/list/containers = list() // Beakers for our liquid biomass + var/container_limit = 3 // How many beakers can the machine hold? /obj/machinery/clonepod/New() ..() @@ -71,8 +72,6 @@ to_chat(user, "Current clone cycle is [round(completion)]% complete.") return -//Clonepod - //Start growing a human clone in the pod! /obj/machinery/clonepod/proc/growclone(var/datum/dna2/record/R) if(mess || attempting) @@ -98,6 +97,9 @@ if(istype(modifier_type, /datum/modifier/no_clone)) return 0 + // Remove biomass when the cloning is started, rather than when the guy pops out + remove_biomass(CLONE_BIOMASS) + attempting = 1 //One at a time!! locked = 1 @@ -164,6 +166,7 @@ for(var/datum/language/L in R.languages) H.add_language(L.name) + H.flavor_texts = R.flavor.Copy() H.suiciding = 0 attempting = 0 @@ -171,16 +174,6 @@ //Grow clones to maturity then kick them out. FREELOADERS /obj/machinery/clonepod/process() - - var/visible_message = 0 - for(var/obj/item/weapon/reagent_containers/food/snacks/meat/meat in range(1, src)) - qdel(meat) - biomass += 50 - visible_message = 1 // Prevent chatspam when multiple meat are near - - if(visible_message) - visible_message("[src] sucks in and processes the nearby biomass.") - if(stat & NOPOWER) //Autoeject if power is lost if(occupant) locked = 0 @@ -250,11 +243,14 @@ else locked = 0 to_chat(user, "System unlocked.") - else if(istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat)) - to_chat(user, "\The [src] processes \the [W].") - biomass += 50 - user.drop_item() - qdel(W) + else if(istype(W,/obj/item/weapon/reagent_containers/glass)) + if(LAZYLEN(containers) >= container_limit) + to_chat(user, "\The [src] has too many containers loaded!") + else if(do_after(user, 1 SECOND)) + user.visible_message("[user] has loaded \the [W] into \the [src].", "You load \the [W] into \the [src].") + containers += W + user.drop_item() + W.forceMove(src) return else if(W.is_wrench()) if(locked && (anchored || occupant)) @@ -271,7 +267,7 @@ user.visible_message("[user] secures [src] to the floor.", "You secure [src] to the floor.") else user.visible_message("[user] unsecures [src] from the floor.", "You unsecure [src] from the floor.") - else if(W.is_multitool()) + else if(istype(W, /obj/item/device/multitool)) var/obj/item/device/multitool/M = W M.connecting = src to_chat(user, "You load connection data from [src] to [M].") @@ -308,10 +304,6 @@ heal_level = rating * 10 - 20 heal_rate = round(rating / 4) - if(rating >= 8) - notoxin = 1 - else - notoxin = 0 /obj/machinery/clonepod/verb/eject() set name = "Eject Cloner" @@ -348,10 +340,66 @@ domutcheck(occupant) //Waiting until they're out before possible transforming. occupant = null - biomass -= CLONE_BIOMASS update_icon() return +// Returns the total amount of biomass reagent in all of the pod's stored containers +/obj/machinery/clonepod/proc/get_biomass() + var/biomass_count = 0 + if(LAZYLEN(containers)) + for(var/obj/item/weapon/reagent_containers/glass/G in containers) + for(var/datum/reagent/R in G.reagents.reagent_list) + if(R.id == "biomass") + biomass_count += R.volume + + return biomass_count + +// Removes [amount] biomass, spread across all containers. Doesn't have any check that you actually HAVE enough biomass, though. +/obj/machinery/clonepod/proc/remove_biomass(var/amount = CLONE_BIOMASS) //Just in case it doesn't get passed a new amount, assume one clone + var/to_remove = 0 // Tracks how much biomass has been found so far + if(LAZYLEN(containers)) + for(var/obj/item/weapon/reagent_containers/glass/G in containers) + if(to_remove < amount) //If we have what we need, we can stop. Checked every time we switch beakers + for(var/datum/reagent/R in G.reagents.reagent_list) + if(R.id == "biomass") // Finds Biomass + var/need_remove = max(0, amount - to_remove) //Figures out how much biomass is in this container + if(R.volume >= need_remove) //If we have more than enough in this beaker, only take what we need + R.remove_self(need_remove) + to_remove = amount + else //Otherwise, take everything and move on + to_remove += R.volume + R.remove_self(R.volume) + else + continue + else + return 1 + return 0 + +// Empties all of the beakers from the cloning pod, used to refill it +/obj/machinery/clonepod/verb/empty_beakers() + set name = "Eject Beakers" + set category = "Object" + set src in oview(1) + + if(usr.stat != 0) + return + + add_fingerprint(usr) + drop_beakers() + return + +// Actually does all of the beaker dropping +// Returns 1 if it succeeds, 0 if it fails. Added in case someone wants to add messages to the user. +/obj/machinery/clonepod/proc/drop_beakers() + if(LAZYLEN(containers)) + var/turf/T = get_turf(src) + if(T) + for(var/obj/item/weapon/reagent_containers/glass/G in containers) + G.forceMove(T) + containers -= G + return 1 + return 0 + /obj/machinery/clonepod/proc/malfunction() if(occupant) connected_message("Critical Error!") @@ -406,6 +454,12 @@ else if(mess) icon_state = "pod_g" + +/obj/machinery/clonepod/full/New() + ..() + for(var/i = 1 to container_limit) + containers += new /obj/item/weapon/reagent_containers/glass/bottle/biomass(src) + //Health Tracker Implant /obj/item/weapon/implant/health @@ -479,7 +533,7 @@ /obj/item/weapon/disk/data/examine(mob/user) ..(user) - to_chat(user, "The write-protect tab is set to [read_only ? "protected" : "unprotected"].") + to_chat(user, text("The write-protect tab is set to [read_only ? "protected" : "unprotected"].")) return /* diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index 334b4a97af1..cb66b376eb5 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -200,6 +200,8 @@ GLOBAL_LIST_BOILERPLATE(all_deactivated_AI_cores, /obj/structure/AIcore/deactiva if(!istype(transfer) || locate(/mob/living/silicon/ai) in src) return + if(transfer.controlling_drone) + transfer.controlling_drone.release_ai_control("Unit control lost. Core transfer completed.") transfer.aiRestorePowerRoutine = 0 transfer.control_disabled = 0 transfer.aiRadio.disabledAi = 0 diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 4935a2a552e..9660eca8bcb 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -67,7 +67,7 @@ user.drop_item() W.loc = src diskette = W - user << "You insert [W]." + to_chat(user, "You insert [W].") updateUsrDialog() return else if(istype(W, /obj/item/device/multitool)) @@ -77,7 +77,7 @@ pods += P P.connected = src P.name = "[initial(P.name)] #[pods.len]" - user << "You connect [P] to [src]." + to_chat(user, "You connect [P] to [src].") else if (menu == 4 && (istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda))) if(check_access(W)) @@ -116,7 +116,7 @@ var/pods_list_ui[0] for(var/obj/machinery/clonepod/pod in pods) - pods_list_ui[++pods_list_ui.len] = list("pod" = pod, "biomass" = pod.biomass) + pods_list_ui[++pods_list_ui.len] = list("pod" = pod, "biomass" = pod.get_biomass()) if(pods) data["pods"] = pods_list_ui @@ -244,7 +244,7 @@ //Look for that player! They better be dead! if(istype(C)) //Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs. - if(!pods.len) + if(!LAZYLEN(pods)) temp = "Error: No clone pods detected." else var/obj/machinery/clonepod/pod = pods[1] @@ -252,13 +252,12 @@ pod = input(usr,"Select a cloning pod to use", "Pod selection") as anything in pods if(pod.occupant) temp = "Error: Clonepod is currently occupied." - else if(pod.biomass < CLONE_BIOMASS) + else if(pod.get_biomass() < CLONE_BIOMASS) temp = "Error: Not enough biomass." else if(pod.mess) temp = "Error: Clonepod malfunction." else if(!config.revival_cloning) temp = "Error: Unable to initiate cloning cycle." - else if(pod.growclone(C)) temp = "Initiating cloning cycle..." records.Remove(C) diff --git a/code/game/machinery/computer3/laptop.dm b/code/game/machinery/computer3/laptop.dm index 38db5742006..9a8ba02b002 100644 --- a/code/game/machinery/computer3/laptop.dm +++ b/code/game/machinery/computer3/laptop.dm @@ -28,6 +28,9 @@ var/obj/machinery/computer3/laptop/stored_computer = null +/obj/item/device/laptop/get_cell() + return stored_computer.battery + /obj/item/device/laptop/verb/open_computer() set name = "Open Laptop" set category = "Object" diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 2bfb502a5bd..b3e0462af7a 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -47,6 +47,7 @@ var/check_synth = 0 //if active, will shoot at anything not an AI or cyborg var/check_all = 0 //If active, will fire on anything, including synthetics. var/ailock = 0 // AI cannot use this + var/faction = null //if set, will not fire at people in the same faction for any reason. var/attacked = 0 //if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!) @@ -80,6 +81,11 @@ lethal = 1 installation = /obj/item/weapon/gun/energy/laser +/obj/machinery/porta_turret/stationary/syndie // Generic turrets for POIs that need to not shoot their buddies. + enabled = TRUE + check_all = TRUE + faction = "syndicate" // Make sure this equals the faction that the mobs in the POI have or they will fight each other. + /obj/machinery/porta_turret/ai_defense name = "defense turret" desc = "This variant appears to be much more durable." @@ -552,6 +558,9 @@ var/list/turret_icons if(!L) return TURRET_NOT_TARGET + if(faction && L.faction == faction) + return TURRET_NOT_TARGET + if(!emagged && issilicon(L) && check_all == 0) // Don't target silica, unless told to neutralize everything. return TURRET_NOT_TARGET diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index d9cfb5d9f85..ddd50a8f50a 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -41,35 +41,12 @@ obj/machinery/recharger return if(istype(G, /obj/item/weapon/gun/energy)) var/obj/item/weapon/gun/energy/E = G - if(!E.power_supply) - to_chat(user, "Your gun has no power cell.") - return if(E.self_recharge) to_chat(user, "Your gun has no recharge port.") return - if(istype(G, /obj/item/weapon/gun/energy/staff)) + if(!G.get_cell()) + to_chat(user, "This device does not have a battery installed.") return - if(istype(G, /obj/item/device/flashlight)) - var/obj/item/device/flashlight/F = G - if(!F.power_use) - return - if(!F.cell) - return - if(istype(G, /obj/item/device/laptop)) - var/obj/item/device/laptop/L = G - if(!L.stored_computer.battery) - user << "There's no battery in it!" - return - if(istype(G, /obj/item/device/electronic_assembly)) - var/obj/item/device/electronic_assembly/assembly = G - if(!assembly.battery) - to_chat(user, "The assembly doesn't have a power cell.") - return - if(istype(G, /obj/item/weapon/weldingtool/electric)) - var/obj/item/weapon/weldingtool/electric/welder = G - if(!welder.power_supply) - to_chat(user, "Your welder has no power cell.") - return user.drop_item() G.loc = src @@ -109,71 +86,8 @@ obj/machinery/recharger update_use_power(1) icon_state = icon_state_idle else - if(istype(charging, /obj/item/weapon/gun/energy)) - var/obj/item/weapon/gun/energy/E = charging - if(!E.power_supply.fully_charged()) - icon_state = icon_state_charging - E.power_supply.give(active_power_usage*CELLRATE) - update_use_power(2) - else - icon_state = icon_state_charged - update_use_power(1) - return - - if(istype(charging, /obj/item/weapon/gun/magnetic)) - var/obj/item/weapon/gun/magnetic/M = charging - if(!M.cell.fully_charged()) - icon_state = icon_state_charging - M.cell.give(active_power_usage*CELLRATE) - update_use_power(2) - else - icon_state = icon_state_charged - update_use_power(1) - return - - if(istype(charging, /obj/item/weapon/melee/baton)) - var/obj/item/weapon/melee/baton/B = charging - if(B.bcell) - if(!B.bcell.fully_charged()) - icon_state = icon_state_charging - B.bcell.give(active_power_usage*CELLRATE) - update_use_power(2) - else - icon_state = icon_state_charged - update_use_power(1) - else - icon_state = icon_state_idle - update_use_power(1) - return - - if(istype(charging, /obj/item/device/laptop)) - var/obj/item/device/laptop/L = charging - if(!L.stored_computer.battery.fully_charged()) - icon_state = icon_state_charging - L.stored_computer.battery.give(active_power_usage*CELLRATE) - update_use_power(2) - else - icon_state = icon_state_charged - update_use_power(1) - return - - if(istype(charging, /obj/item/device/flashlight)) - var/obj/item/device/flashlight/F = charging - if(F.cell) - if(!F.cell.fully_charged()) - icon_state = icon_state_charging - F.cell.give(active_power_usage*CELLRATE) - update_use_power(2) - else - icon_state = icon_state_charged - update_use_power(1) - else - icon_state = icon_state_idle - update_use_power(1) - return - - if(istype(charging, /obj/item/weapon/cell)) - var/obj/item/weapon/cell/C = charging + var/obj/item/weapon/cell/C = charging.get_cell() + if(istype(C)) if(!C.fully_charged()) icon_state = icon_state_charging C.give(active_power_usage*CELLRATE) @@ -181,48 +95,17 @@ obj/machinery/recharger else icon_state = icon_state_charged update_use_power(1) - return - - if(istype(charging, /obj/item/device/electronic_assembly)) - var/obj/item/device/electronic_assembly/assembly = charging - if(assembly.battery) - if(!assembly.battery.fully_charged()) - icon_state = icon_state_charging - assembly.battery.give(active_power_usage*CELLRATE) - update_use_power(2) - else - icon_state = icon_state_charged - update_use_power(1) - else - icon_state = icon_state_idle - update_use_power(1) - return - - if(istype(charging, /obj/item/weapon/weldingtool/electric)) - var/obj/item/weapon/weldingtool/electric/C = charging - if(!C.power_supply.fully_charged()) - icon_state = icon_state_charging - C.power_supply.give(active_power_usage*CELLRATE) - update_use_power(2) - else - icon_state = icon_state_charged - update_use_power(1) - return /obj/machinery/recharger/emp_act(severity) if(stat & (NOPOWER|BROKEN) || !anchored) ..(severity) return - if(istype(charging, /obj/item/weapon/gun/energy)) - var/obj/item/weapon/gun/energy/E = charging - if(E.power_supply) - E.power_supply.emp_act(severity) + if(charging) + var/obj/item/weapon/cell/C = charging.get_cell() + if(istype(C)) + C.emp_act(severity) - else if(istype(charging, /obj/item/weapon/melee/baton)) - var/obj/item/weapon/melee/baton/B = charging - if(B.bcell) - B.bcell.charge = 0 ..(severity) /obj/machinery/recharger/update_icon() //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier. @@ -231,7 +114,6 @@ obj/machinery/recharger else icon_state = icon_state_idle - /obj/machinery/recharger/wallcharger name = "wall recharger" icon = 'icons/obj/stationobjs.dmi' diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index 90f708ff9df..0369b91d63b 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -248,6 +248,6 @@ var/global/list/image/splatter_cache=list() //This version should be used for admin spawns and pre-mapped virus vectors (e.g. in PoIs), this version does not dry /obj/effect/decal/cleanable/mucus/mapped/New() - ...() + ..() virus2 = new /datum/disease2/disease virus2.makerandom() diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm index aaebab43550..d7db6f2a0c7 100644 --- a/code/game/objects/effects/misc.dm +++ b/code/game/objects/effects/misc.dm @@ -46,4 +46,21 @@ /obj/effect/temporary_effect/shuttle_landing/initialize() flick("shuttle_warning", src) // flick() forces the animation to always begin at the start. + . = ..() + +// The manifestation of Zeus's might. Or just a really unlucky day. +// This is purely a visual effect, this isn't the part of the code that hurts things. +/obj/effect/temporary_effect/lightning_strike + name = "lightning" + desc = "How shocked you must be, to see this text. You must have lightning reflexes. \ + The humor in this description is just so electrifying." + icon = 'icons/effects/96x256.dmi' + icon_state = "lightning_strike" + plane = PLANE_LIGHTING_ABOVE + time_to_die = 1 SECOND + pixel_x = -32 + +/obj/effect/temporary_effect/lightning_strike/initialize() + icon_state += "[rand(1,2)]" // To have two variants of lightning sprites. + animate(src, alpha = 0, time = time_to_die - 1) . = ..() \ No newline at end of file diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm index 08f369d735e..dc4bf5146ab 100644 --- a/code/game/objects/effects/portals.dm +++ b/code/game/objects/effects/portals.dm @@ -31,6 +31,7 @@ GLOBAL_LIST_BOILERPLATE(all_portals, /obj/effect/portal) return /obj/effect/portal/New() + ..() // Necessary for the list boilerplate to work spawn(300) qdel(src) return diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 1f754ff2ca3..5df1daff3d4 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -1254,7 +1254,7 @@ var/global/list/obj/item/device/pda/PDAs = list() if(isnull(cartridge)) to_chat(usr, "There's no cartridge to eject.") - return + return cartridge.forceMove(get_turf(src)) if(ismob(loc)) @@ -1382,7 +1382,7 @@ var/global/list/obj/item/device/pda/PDAs = list() to_chat(user, "Blood type: [C:blood_DNA[blood]]\nDNA: [blood]") if(4) - user.visible_message("\The [user] has analyzed [C]'s radiation levels!", 1) + user.visible_message("\The [user] has analyzed [C]'s radiation levels!", "You have analyzed [C]'s radiation levels!") to_chat(user, "Analyzing Results for [C]:") if(C.radiation) to_chat(user, "Radiation Level: [C.radiation]") diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index b57c67bac09..7e288dbadcf 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -64,20 +64,24 @@ add_attack_logs(user,carded_ai,"Purged from AI Card") flush = 1 carded_ai.suiciding = 1 - carded_ai << "Your power has been disabled!" + to_chat(carded_ai, "Your power has been disabled!") while (carded_ai && carded_ai.stat != 2) + if(carded_ai.controlling_drone && prob(carded_ai.oxyloss)) //You feel it creeping? Eventually will reach 100, resulting in the second half of the AI's remaining life being lonely. + carded_ai.controlling_drone.release_ai_control("Unit lost. Integrity too low to maintain connection.") carded_ai.adjustOxyLoss(2) carded_ai.updatehealth() sleep(10) flush = 0 if (href_list["radio"]) carded_ai.aiRadio.disabledAi = text2num(href_list["radio"]) - carded_ai << "Your Subspace Transceiver has been [carded_ai.aiRadio.disabledAi ? "disabled" : "enabled"]!" - user << "You [carded_ai.aiRadio.disabledAi ? "disable" : "enable"] the AI's Subspace Transceiver." + to_chat(carded_ai, "Your Subspace Transceiver has been [carded_ai.aiRadio.disabledAi ? "disabled" : "enabled"]!") + to_chat(user, "You [carded_ai.aiRadio.disabledAi ? "disable" : "enable"] the AI's Subspace Transceiver.") if (href_list["wireless"]) carded_ai.control_disabled = text2num(href_list["wireless"]) - carded_ai << "Your wireless interface has been [carded_ai.control_disabled ? "disabled" : "enabled"]!" - user << "You [carded_ai.control_disabled ? "disable" : "enable"] the AI's wireless interface." + to_chat(carded_ai, "Your wireless interface has been [carded_ai.control_disabled ? "disabled" : "enabled"]!") + to_chat(user, "You [carded_ai.control_disabled ? "disable" : "enable"] the AI's wireless interface.") + if(carded_ai.control_disabled && carded_ai.controlling_drone) + carded_ai.controlling_drone.release_ai_control("Unit control terminated at intellicore port.") update_icon() return 1 @@ -94,12 +98,12 @@ icon_state = "aicard" /obj/item/device/aicard/proc/grab_ai(var/mob/living/silicon/ai/ai, var/mob/living/user) - if(!ai.client) - user << "ERROR: AI [ai.name] is offline. Unable to transfer." + if(!ai.client && !ai.controlling_drone) + to_chat(user, "ERROR: AI [ai.name] is offline. Unable to transfer.") return 0 if(carded_ai) - user << "Transfer failed: Existing AI found on remote device. Remove existing AI to install a new one." + to_chat(user, "Transfer failed: Existing AI found on remote device. Remove existing AI to install a new one.") return 0 if(!user.IsAdvancedToolUser() && isanimal(user)) @@ -108,7 +112,9 @@ return 0 user.visible_message("\The [user] starts transferring \the [ai] into \the [src]...", "You start transferring \the [ai] into \the [src]...") - ai << "\The [user] is transferring you into \the [src]!" + to_chat(ai, "\The [user] is transferring you into \the [src]!") + if(ai.controlling_drone) + to_chat(ai.controlling_drone, "\The [user] is transferring you into \the [src]!") if(do_after(user, 100)) if(istype(ai.loc, /turf/)) @@ -124,11 +130,13 @@ ai.control_disabled = 1 ai.aiRestorePowerRoutine = 0 carded_ai = ai + if(ai.controlling_drone) + ai.controlling_drone.release_ai_control("Unit control lost.") if(ai.client) - ai << "You have been transferred into a mobile core. Remote access lost." + to_chat(ai, "You have been transferred into a mobile core. Remote access lost.") if(user.client) - user << "Transfer successful: [ai.name] extracted from current device and placed within mobile core." + to_chat(ai, "Transfer successful: [ai.name] extracted from current device and placed within mobile core.") ai.canmove = 1 update_icon() diff --git a/code/game/objects/items/devices/communicator/UI.dm b/code/game/objects/items/devices/communicator/UI.dm index 4d6ff75c50a..fca4cf4866d 100644 --- a/code/game/objects/items/devices/communicator/UI.dm +++ b/code/game/objects/items/devices/communicator/UI.dm @@ -69,17 +69,16 @@ im_list_ui[++im_list_ui.len] = list("address" = I["address"], "to_address" = I["to_address"], "im" = I["im"]) //Weather reports. - if(planet_controller) - for(var/datum/planet/planet in planet_controller.planets) - if(planet.weather_holder && planet.weather_holder.current_weather) - var/list/W = list( - "Planet" = planet.name, - "Time" = planet.current_time.show_time("hh:mm"), - "Weather" = planet.weather_holder.current_weather.name, - "Temperature" = planet.weather_holder.temperature - T0C, - "High" = planet.weather_holder.current_weather.temp_high - T0C, - "Low" = planet.weather_holder.current_weather.temp_low - T0C) - weather[++weather.len] = W + for(var/datum/planet/planet in SSplanets.planets) + if(planet.weather_holder && planet.weather_holder.current_weather) + var/list/W = list( + "Planet" = planet.name, + "Time" = planet.current_time.show_time("hh:mm"), + "Weather" = planet.weather_holder.current_weather.name, + "Temperature" = planet.weather_holder.temperature - T0C, + "High" = planet.weather_holder.current_weather.temp_high - T0C, + "Low" = planet.weather_holder.current_weather.temp_low - T0C) + weather[++weather.len] = W injection = "
Test
" diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index d69c2c9d928..44d3c98c8c4 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -41,6 +41,9 @@ processing_objects -= src return ..() +/obj/item/device/flashlight/get_cell() + return cell + /obj/item/device/flashlight/verb/toggle() set name = "Toggle Flashlight Brightness" set category = "Object" diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm index ca4b8d8066e..9c9f1aba598 100644 --- a/code/game/objects/items/devices/megaphone.dm +++ b/code/game/objects/items/devices/megaphone.dm @@ -10,44 +10,162 @@ var/insults = 0 var/list/insultmsg = list("FUCK EVERYONE!", "I'M A TERRORIST!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "GLORY TO ALMACH!") -/obj/item/device/megaphone/attack_self(mob/living/user as mob) +/obj/item/device/megaphone/proc/can_broadcast(var/mob/living/user) if (user.client) if(user.client.prefs.muted & MUTE_IC) - src << "You cannot speak in IC (muted)." - return - if(!ishuman(user)) - user << "You don't know how to use this!" - return + to_chat(user, "You cannot speak in IC (muted).") + return 0 + if(!(ishuman(user) || user.isSynthetic())) + to_chat(user, "You don't know how to use this!") + return 0 if(user.silent) - return + return 0 if(spamcheck) - user << "\The [src] needs to recharge!" - return + to_chat(user, "\The [src] needs to recharge!") + return 0 + return 1 - var/message = sanitize(input(user, "Shout a message?", "Megaphone", null) as text) - if(!message) - return - message = capitalize(message) +/obj/item/device/megaphone/proc/do_broadcast(var/mob/living/user, var/message) if ((src.loc == user && usr.stat == 0)) if(emagged) if(insults) - for(var/mob/O in (viewers(user))) - O.show_message("[user] broadcasts, \"[pick(insultmsg)]\"",2) // 2 stands for hearable message + user.audible_message("[user] broadcasts, \"[pick(insultmsg)]\"") insults-- else - user << "*BZZZZzzzzzt*" + to_chat(user, "*BZZZZzzzzzt*") else - for(var/mob/O in (viewers(user))) - O.show_message("[user] broadcasts, \"[message]\"",2) // 2 stands for hearable message + user.audible_message("[user] broadcasts, \"[message]\"") spamcheck = 1 spawn(20) spamcheck = 0 return +/obj/item/device/megaphone/attack_self(mob/living/user as mob) + if(!can_broadcast(user)) + return + + var/message = sanitize(input(user, "Shout a message?", "Megaphone", null) as text) + if(!message) + return + message = capitalize(message) + + do_broadcast(user, message) + /obj/item/device/megaphone/emag_act(var/remaining_charges, var/mob/user) if(!emagged) - user << "You overload \the [src]'s voice synthesizer." + to_chat(user, "You overload \the [src]'s voice synthesizer.") emagged = 1 - insults = rand(1, 3)//to prevent dickflooding + insults = rand(1, 3)//to prevent caps spam. return 1 + +/obj/item/device/megaphone/super + name = "gigaphone" + desc = "A device used to project your voice. Loudly-er." + icon_state = "gigaphone" + + var/broadcast_font = "verdana" + var/broadcast_size = 3 + var/broadcast_color = "#000000" //Black by default. + var/list/volume_options = list(2, 3, 4) + var/list/font_options = list("times new roman", "times", "verdana", "sans-serif", "serif", "georgia") + var/list/color_options= list("#000000", "#ff0000", "#00ff00", "#0000ff") + + insultmsg = list("HONK?!", "HONK!", "HOOOOOOOONK!", "...!", "HUNK.", "Honk?") + +/obj/item/device/megaphone/super/emag_act(var/remaining_charges, var/mob/user) + ..() + if(emagged) + if(!(11 in volume_options)) + volume_options = list(11) + broadcast_size = 11 + if(!("comic sans ms" in font_options)) + font_options = list("comic sans ms") + broadcast_font = "comic sans ms" + to_chat(user, "\The [src] emits a silly sound.") + if(!("#ff69b4" in color_options)) + color_options = list("#ff69b4") + broadcast_color = "#ff69b4" + if(insults <= 0) + insults = rand(1,3) + to_chat(user, "You re-scramble \the [src]'s voice synthesizer.") + return 1 + +/obj/item/device/megaphone/super/verb/turn_volume_dial() + set name = "Change Volume" + set desc = "Allows you to change the megaphone's volume." + set category = "Object" + + adjust_volume(usr) + +/obj/item/device/megaphone/super/proc/adjust_volume(var/mob/living/user) + var/new_volume = input(user, "Set Volume") as null|anything in volume_options + + if(new_volume && Adjacent(user)) + broadcast_size = new_volume + +/obj/item/device/megaphone/super/verb/change_font() + set name = "Change... Pronunciation?" + set desc = "Allows you to change the megaphone's font." + set category = "Object" + + adjust_font(usr) + +/obj/item/device/megaphone/super/proc/adjust_font(var/mob/living/user) + var/new_font = input(user, "Set Volume") as null|anything in font_options + + if(new_font && Adjacent(user)) + broadcast_font = new_font + +/obj/item/device/megaphone/super/verb/change_color() + set name = "Change... Tune?" + set desc = "Allows you to change the megaphone's color." + set category = "Object" + + adjust_color(usr) + +/obj/item/device/megaphone/super/proc/adjust_color(var/mob/living/user) + var/new_color = input(user, "Set Volume") as null|anything in color_options + + if(new_color && Adjacent(user)) + broadcast_color = new_color + +/obj/item/device/megaphone/super/do_broadcast(var/mob/living/user, var/message) + if ((src.loc == user && usr.stat == 0)) + if(emagged) + if(insults) + user.audible_message("[user] broadcasts, \"[pick(insultmsg)]\"") + if(broadcast_size >= 11) + var/turf/T = get_turf(user) + playsound(T, 'sound/items/AirHorn.ogg', 100, 1) + for(var/mob/living/carbon/M in oviewers(4, T)) + if(M.get_ear_protection() >= 2) + continue + M.sleeping = 0 + M.stuttering += 20 + M.ear_deaf += 30 + M.Weaken(3) + if(prob(30)) + M.Stun(10) + M.Paralyse(4) + else + M.make_jittery(50) + insults-- + else + user.audible_message("*BZZZZzzzzzt*") + if(prob(40) && insults <= 0) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, get_turf(user)) + s.start() + user.visible_message("\The [src] sparks violently!") + spawn(30) + explosion(get_turf(src), -1, -1, 1, 3, adminlog = 1) + qdel(src) + return + else + user.audible_message("[user] broadcasts, \"[message]\"") + + spamcheck = 1 + spawn(20) + spamcheck = 0 + return diff --git a/code/game/objects/items/devices/radio/jammer.dm b/code/game/objects/items/devices/radio/jammer.dm index 680b5e2b37a..868f90251ce 100644 --- a/code/game/objects/items/devices/radio/jammer.dm +++ b/code/game/objects/items/devices/radio/jammer.dm @@ -38,6 +38,9 @@ var/global/list/active_radio_jammers = list() qdel_null(power_source) return ..() +/obj/item/device/radio_jammer/get_cell() + return power_source + /obj/item/device/radio_jammer/proc/turn_off(mob/user) if(user) to_chat(user,"\The [src] deactivates.") diff --git a/code/game/objects/items/poi_items.dm b/code/game/objects/items/poi_items.dm index 85a8b27854e..394212e4c48 100644 --- a/code/game/objects/items/poi_items.dm +++ b/code/game/objects/items/poi_items.dm @@ -52,8 +52,9 @@ /obj/structure/largecrate/animal/crashedshuttle name = "SCP" + /obj/structure/largecrate/animal/crashedshuttle/initialize() - starts_with = pick(/mob/living/simple_animal/hostile/statue, /obj/item/cursed_marble) + starts_with = pick(/mob/living/simple_animal/hostile/statue, /obj/item/cursed_marble, /obj/item/weapon/deadringer) name = pick("Spicy Crust Pizzeria", "Soap and Care Products", "Sally's Computer Parts", "Steve's Chocolate Pastries", "Smith & Christian's Plastics","Standard Containers & Packaging Co.", "Sanitary Chemical Purgation (LTD)") name += " delivery crate" return ..() diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index 5c17634ae26..18b13a8034a 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -199,3 +199,9 @@ throw_range = 20 flags = 0 no_variants = FALSE + +/obj/item/stack/tile/roofing + name = "roofing" + singular_name = "roofing" + desc = "A section of roofing material. You can use it to repair the ceiling, or expand it." + icon_state = "techtile_grid" \ No newline at end of file diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 02a308555bb..02e121d02c1 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1042,6 +1042,50 @@ name = "tuxedo cat plushie" icon_state = "tuxedocat" +// nah, squids are better than foxes :> + +/obj/item/toy/plushie/squid/green + name = "green squid plushie" + desc = "A small, cute and loveable squid friend. This one is green." + icon = 'icons/obj/toy.dmi' + icon_state = "greensquid" + slot_flags = SLOT_HEAD + +/obj/item/toy/plushie/squid/mint + name = "mint squid plushie" + desc = "A small, cute and loveable squid friend. This one is mint coloured." + icon = 'icons/obj/toy.dmi' + icon_state = "mintsquid" + slot_flags = SLOT_HEAD + +/obj/item/toy/plushie/squid/blue + name = "blue squid plushie" + desc = "A small, cute and loveable squid friend. This one is blue." + icon = 'icons/obj/toy.dmi' + icon_state = "bluesquid" + slot_flags = SLOT_HEAD + +/obj/item/toy/plushie/squid/orange + name = "orange squid plushie" + desc = "A small, cute and loveable squid friend. This one is orange." + icon = 'icons/obj/toy.dmi' + icon_state = "orangesquid" + slot_flags = SLOT_HEAD + +/obj/item/toy/plushie/squid/yellow + name = "yellow squid plushie" + desc = "A small, cute and loveable squid friend. This one is yellow." + icon = 'icons/obj/toy.dmi' + icon_state = "yellowsquid" + slot_flags = SLOT_HEAD + +/obj/item/toy/plushie/squid/pink + name = "pink squid plushie" + desc = "A small, cute and loveable squid friend. This one is pink." + icon = 'icons/obj/toy.dmi' + icon_state = "pinksquid" + slot_flags = SLOT_HEAD + /obj/item/toy/plushie/therapy/red name = "red therapy doll" desc = "A toy for therapeutic and recreational purposes. This one is red." diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index 58aa30547dc..d9543fed201 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -153,7 +153,7 @@ return 0 if(build_turf) - T.ChangeTurf(build_turf) + T.ChangeTurf(build_turf, preserve_outdoors = TRUE) else if(build_other) new build_other(T) else diff --git a/code/game/objects/items/weapons/autopsy.dm b/code/game/objects/items/weapons/autopsy.dm index d9606d28d24..7cddfd1efc6 100644 --- a/code/game/objects/items/weapons/autopsy.dm +++ b/code/game/objects/items/weapons/autopsy.dm @@ -167,21 +167,24 @@ if(!istype(M)) return 0 + if (user.a_intent == I_HELP) + return ..() + if(target_name != M.name) target_name = M.name src.wdata = list() src.chemtraces = list() src.timeofdeath = null - user << "A new patient has been registered. Purging data for previous patient." + to_chat(user, "A new patient has been registered. Purging data for previous patient.") src.timeofdeath = M.timeofdeath var/obj/item/organ/external/S = M.get_organ(user.zone_sel.selecting) if(!S) - usr << "You can't scan this body part." + to_chat(user, "You can't scan this body part.") return if(!S.open) - usr << "You have to cut [S] open first!" + to_chat(user, "You have to cut [S] open first!") return M.visible_message("\The [user] scans the wounds on [M]'s [S.name] with [src]") diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index 02e4cd48c44..f5bd38dcc17 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -21,12 +21,26 @@ /obj/item/weapon/implant/proc/activate() return - // What does the implant do upon injection? - // return 0 if the implant fails (ex. Revhead and loyalty implant.) - // return 1 if the implant succeeds (ex. Nonrevhead and loyalty implant.) -/obj/item/weapon/implant/proc/implanted(var/mob/source) +// Moves the implant where it needs to go, and tells it if there's more to be done in post_implant +/obj/item/weapon/implant/proc/handle_implant(var/mob/source, var/target_zone = BP_TORSO) + . = TRUE + imp_in = source + implanted = TRUE + if(ishuman(source)) + var/mob/living/carbon/human/H = source + var/obj/item/organ/external/affected = H.get_organ(target_zone) + if(affected) + affected.implants += src + part = affected + if(part) + forceMove(part) + else + forceMove(source) + listening_objects |= src - return 1 + +// Takes place after handle_implant, if that returns TRUE +/obj/item/weapon/implant/proc/post_implant(var/mob/source) /obj/item/weapon/implant/proc/get_data() return "No information available" @@ -49,6 +63,12 @@ icon_state = "implant_melted" malfunction = MALFUNCTION_PERMANENT +/obj/item/weapon/implant/proc/implant_loadout(var/mob/living/carbon/human/H) + if(H) + var/obj/item/organ/external/affected = H.organs_by_name[BP_HEAD] + if(handle_implant(H, affected)) + post_implant(H) + /obj/item/weapon/implant/Destroy() if(part) part.implants.Remove(src) @@ -69,6 +89,11 @@ else ..() + + +////////////////////////////// +// Tracking Implant +////////////////////////////// GLOBAL_LIST_BOILERPLATE(all_tracking_implants, /obj/item/weapon/implant/tracking) /obj/item/weapon/implant/tracking @@ -84,9 +109,8 @@ GLOBAL_LIST_BOILERPLATE(all_tracking_implants, /obj/item/weapon/implant/tracking id = rand(1, 1000) ..() -/obj/item/weapon/implant/tracking/implanted(var/mob/source) +/obj/item/weapon/implant/tracking/post_implant(var/mob/source) processing_objects.Add(src) - return 1 /obj/item/weapon/implant/tracking/Destroy() processing_objects.Remove(src) @@ -142,7 +166,9 @@ Implant Specifics:
"} spawn(delay) malfunction-- - +////////////////////////////// +// Death Explosive Implant +////////////////////////////// /obj/item/weapon/implant/dexplosive name = "explosive" desc = "And boom goes the weasel." @@ -177,7 +203,9 @@ Implant Specifics:
"} /obj/item/weapon/implant/dexplosive/islegal() return 0 -//BS12 Explosive +////////////////////////////// +// Explosive Implant +////////////////////////////// /obj/item/weapon/implant/explosive name = "explosive implant" desc = "A military grade micro bio-explosive. Highly dangerous." @@ -249,15 +277,13 @@ Implant Specifics:
"} if(t) t.hotspot_expose(3500,125) -/obj/item/weapon/implant/explosive/implanted(mob/source as mob) +/obj/item/weapon/implant/explosive/post_implant(mob/source as mob) elevel = alert("What sort of explosion would you prefer?", "Implant Intent", "Localized Limb", "Destroy Body", "Full Explosion") phrase = input("Choose activation phrase:") as text var/list/replacechars = list("'" = "","\"" = "",">" = "","<" = "","(" = "",")" = "") phrase = replace_characters(phrase, replacechars) usr.mind.store_memory("Explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate.", 0, 0) usr << "The implanted explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate." - listening_objects |= src - return 1 /obj/item/weapon/implant/explosive/emp_act(severity) if (malfunction) @@ -311,6 +337,9 @@ Implant Specifics:
"} explosion(get_turf(imp_in), -1, -1, 1, 3) qdel(src) +////////////////////////////// +// Chemical Implant +////////////////////////////// GLOBAL_LIST_BOILERPLATE(all_chem_implants, /obj/item/weapon/implant/chem) /obj/item/weapon/implant/chem @@ -336,20 +365,17 @@ Can only be loaded while still in its original case.
the implant may become unstable and either pre-maturely inject the subject or simply break."} return dat - /obj/item/weapon/implant/chem/New() ..() var/datum/reagents/R = new/datum/reagents(50) reagents = R R.my_atom = src - /obj/item/weapon/implant/chem/trigger(emote, source as mob) if(emote == "deathgasp") src.activate(src.reagents.total_volume) return - /obj/item/weapon/implant/chem/activate(var/cause) if((!cause) || (!src.imp_in)) return 0 var/mob/living/carbon/R = src.imp_in @@ -384,6 +410,9 @@ the implant may become unstable and either pre-maturely inject the subject or si spawn(20) malfunction-- +////////////////////////////// +// Loyalty Implant +////////////////////////////// /obj/item/weapon/implant/loyalty name = "loyalty implant" desc = "Makes you loyal or such." @@ -401,20 +430,24 @@ the implant may become unstable and either pre-maturely inject the subject or si Integrity: Implant will last so long as the nanobots are inside the bloodstream."} return dat - -/obj/item/weapon/implant/loyalty/implanted(mob/M) - if(!istype(M, /mob/living/carbon/human)) return 0 +/obj/item/weapon/implant/loyalty/handle_implant(mob/M, target_zone = BP_TORSO) + . = ..(M, target_zone) + if(!istype(M, /mob/living/carbon/human)) + . = FALSE var/mob/living/carbon/human/H = M var/datum/antagonist/antag_data = get_antag_data(H.mind.special_role) if(antag_data && (antag_data.flags & ANTAG_IMPLANT_IMMUNE)) H.visible_message("[H] seems to resist the implant!", "You feel the corporate tendrils of [using_map.company_name] try to invade your mind!") - return 0 - else - clear_antag_roles(H.mind, 1) - H << "You feel a surge of loyalty towards [using_map.company_name]." - return 1 + . = FALSE +/obj/item/weapon/implant/loyalty/post_implant(mob/M) + var/mob/living/carbon/human/H = M + clear_antag_roles(H.mind, 1) + to_chat(H, "You feel a surge of loyalty towards [using_map.company_name].") +////////////////////////////// +// Adrenaline Implant +////////////////////////////// /obj/item/weapon/implant/adrenalin name = "adrenalin" desc = "Removes all stuns and knockdowns." @@ -445,14 +478,13 @@ the implant may become unstable and either pre-maturely inject the subject or si return - -/obj/item/weapon/implant/adrenalin/implanted(mob/source) +/obj/item/weapon/implant/adrenalin/post_implant(mob/source) source.mind.store_memory("A implant can be activated by using the pale emote, say *pale to attempt to activate.", 0, 0) source << "The implanted freedom implant can be activated by using the pale emote, say *pale to attempt to activate." - listening_objects |= src - return 1 - +////////////////////////////// +// Death Alarm Implant +////////////////////////////// /obj/item/weapon/implant/death_alarm name = "death alarm implant" desc = "An alarm which monitors host vital signs and transmits a radio message upon death." @@ -529,11 +561,13 @@ the implant may become unstable and either pre-maturely inject the subject or si spawn(20) malfunction-- -/obj/item/weapon/implant/death_alarm/implanted(mob/source as mob) +/obj/item/weapon/implant/death_alarm/post_implant(mob/source as mob) mobname = source.real_name processing_objects.Add(src) - return 1 +////////////////////////////// +// Compressed Matter Implant +////////////////////////////// /obj/item/weapon/implant/compressed name = "compressed matter implant" desc = "Based on compressed matter technology, can store a single item." @@ -571,13 +605,12 @@ the implant may become unstable and either pre-maturely inject the subject or si scanned.loc = t qdel(src) -/obj/item/weapon/implant/compressed/implanted(mob/source as mob) +/obj/item/weapon/implant/compressed/post_implant(mob/source) src.activation_emote = input("Choose activation emote:") in list("blink", "blink_r", "eyebrow", "chuckle", "twitch", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") if (source.mind) source.mind.store_memory("Compressed matter implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0) source << "The implanted compressed matter implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate." - listening_objects |= src - return 1 + /obj/item/weapon/implant/compressed/islegal() return 0 diff --git a/code/game/objects/items/weapons/implants/implantchair.dm b/code/game/objects/items/weapons/implants/implantchair.dm index 44b33721cf0..c05d52442c1 100644 --- a/code/game/objects/items/weapons/implants/implantchair.dm +++ b/code/game/objects/items/weapons/implants/implantchair.dm @@ -135,10 +135,9 @@ for (var/mob/O in viewers(M, null)) O.show_message("\The [M] has been implanted by \the [src].", 1) - if(imp.implanted(M)) - imp.loc = M - imp.imp_in = M - imp.implanted = 1 + if(imp.handle_implant(M, BP_TORSO)) + imp.post_implant(M) + implant_list -= imp break return diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm index 8052b19de60..fcfd67bb6a3 100644 --- a/code/game/objects/items/weapons/implants/implanter.dm +++ b/code/game/objects/items/weapons/implants/implanter.dm @@ -56,16 +56,11 @@ add_attack_logs(user,M,"Implanted with [imp.name] using [name]") - if(src.imp.implanted(M)) - src.imp.loc = M - src.imp.imp_in = M - src.imp.implanted = 1 - if (ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting) - affected.implants += src.imp - imp.part = affected + if(imp.handle_implant(M)) + imp.post_implant(M) + if(ishuman(M)) + var/mob/living/carbon/human/H = M BITSET(H.hud_updateflag, IMPLOYAL_HUD) src.imp = null diff --git a/code/game/objects/items/weapons/implants/implantfreedom.dm b/code/game/objects/items/weapons/implants/implantfreedom.dm index 92021a46a2f..fab692775d3 100644 --- a/code/game/objects/items/weapons/implants/implantfreedom.dm +++ b/code/game/objects/items/weapons/implants/implantfreedom.dm @@ -16,7 +16,9 @@ /obj/item/weapon/implant/freedom/trigger(emote, mob/living/carbon/source as mob) - if (src.uses < 1) return 0 + if (src.uses < 1) + return 0 + if (emote == src.activation_emote) src.uses-- source << "You feel a faint click." @@ -46,13 +48,9 @@ W.layer = initial(W.layer) return - -/obj/item/weapon/implant/freedom/implanted(mob/living/carbon/source) +/obj/item/weapon/implant/freedom/post_implant(mob/source) source.mind.store_memory("Freedom implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0) source << "The implanted freedom implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate." - listening_objects |= src - return 1 - /obj/item/weapon/implant/freedom/get_data() var/dat = {" diff --git a/code/game/objects/items/weapons/implants/implantlanguage.dm b/code/game/objects/items/weapons/implants/implantlanguage.dm index d813a8d3888..7c6e33508b0 100644 --- a/code/game/objects/items/weapons/implants/implantlanguage.dm +++ b/code/game/objects/items/weapons/implants/implantlanguage.dm @@ -4,7 +4,26 @@ /obj/item/weapon/implant/language name = "GalCom language implant" - desc = "An implant allowing someone to speak and hear the range of frequencies used in Galactic Common, as well as produce any phonemes that they usually cannot. Only helps with hearing and producing sounds, not understanding them." + desc = "An implant allowing someone to speak the range of frequencies used in Galactic Common, as well as produce any phonemes that they usually cannot. Only helps with producing sounds, not understanding them." + var/list/languages = list(LANGUAGE_GALCOM) // List of languages that this assists with + +/obj/item/weapon/implant/language/post_implant(mob/M) // Amends the mob's voice organ, then deletes itself + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/internal/voicebox/V = locate() in H.internal_organs + if(V) + var/list/need_amend = list() // If they've already got all the languages they need, then they don't need this implant to do anything + for(var/L in languages) + if(L in V.will_assist_languages) + continue + else + need_amend |= L + if(LAZYLEN(need_amend)) + if(V.robotic < ORGAN_ASSISTED) + V.mechassist() + for(var/L in need_amend) + V.add_assistable_langs(L) + qdel_null(src) /obj/item/weapon/implant/language/get_data() var/dat = {" @@ -14,16 +33,19 @@ Important Notes: Affects hearing and speech.

Implant Details:
-Function: Allows a being otherwise incapable to both hear the frequencies Galactic Common is generally spoken at, as well as to produce the phonemes of the language.
+Function: Allows a being otherwise incapable of speaking Galactic Common to produce the phonemes of the language.
Special Features: None.
Integrity: Implant will function for expected life, barring physical damage."} return dat + +// EAL Implant /obj/item/weapon/implant/language/eal name = "EAL language implant" - desc = "An implant allowing an organic to both hear and speak Encoded Audio Language accurately. Only helps with hearing and producing sounds, not understanding them." + desc = "An implant allowing an organic to speak Encoded Audio Language passably. Only helps with producing sounds, not understanding them." + languages = list(LANGUAGE_EAL) -/obj/item/weapon/implant/language/get_data() +/obj/item/weapon/implant/language/eal/get_data() var/dat = {" Implant Specifications:
Name: Vey-Med L-2 Encoded Audio Language Implant
@@ -31,7 +53,25 @@ Important Notes: Affects hearing and speech.

Implant Details:
-Function: Allows an organic to accurately process and speak Encoded Audio Language.
+Function: Allows an organic to accurately speak Encoded Audio Language.
+Special Features: None.
+Integrity: Implant will function for expected life, barring physical damage."} + return dat + +/obj/item/weapon/implant/language/skrellian + name = "Skrellian language implant" + desc = "An implant allowing someone to speak the range of frequencies used in Skrellian, as well as produce any phonemes that they usually cannot. Only helps with hearing and producing sounds, not understanding them." + languages = list(LANGUAGE_SKRELLIAN) + +/obj/item/weapon/implant/language/skrellian/get_data() + var/dat = {" +Implant Specifications:
+Name: Vey-Med L-1 Galactic Common Implant
+Life: 5 years
+Important Notes: Affects hearing and speech.
+
+Implant Details:
+Function: Allows a being otherwise incapable of speaking Skrellian to produce the phonemes of the language.
Special Features: None.
Integrity: Implant will function for expected life, barring physical damage."} return dat \ No newline at end of file diff --git a/code/game/objects/items/weapons/implants/implantuplink.dm b/code/game/objects/items/weapons/implants/implantuplink.dm index 644ebf1bb7a..82809cfe61a 100644 --- a/code/game/objects/items/weapons/implants/implantuplink.dm +++ b/code/game/objects/items/weapons/implants/implantuplink.dm @@ -11,15 +11,13 @@ ..() return -/obj/item/weapon/implant/uplink/implanted(mob/source) +/obj/item/weapon/implant/uplink/post_implant(mob/source) + listening_objects |= src activation_emote = input("Choose activation emote:") in list("blink", "blink_r", "eyebrow", "chuckle", "twitch", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") source.mind.store_memory("Uplink implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0) source << "The implanted uplink implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate." - listening_objects |= src - return 1 - /obj/item/weapon/implant/uplink/trigger(emote, mob/source as mob) if(hidden_uplink && usr == source) // Let's not have another people activate our uplink hidden_uplink.check_trigger(source, emote, activation_emote) - return + return \ No newline at end of file diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm index 54f344eae10..0cfdd4792dd 100644 --- a/code/game/objects/items/weapons/mop.dm +++ b/code/game/objects/items/weapons/mop.dm @@ -16,6 +16,7 @@ GLOBAL_LIST_BOILERPLATE(all_mops, /obj/item/weapon/mop) /obj/item/weapon/mop/New() create_reagents(30) + ..() /obj/item/weapon/mop/afterattack(atom/A, mob/user, proximity) if(!proximity) return diff --git a/code/game/objects/items/weapons/policetape.dm b/code/game/objects/items/weapons/policetape.dm index 43183d45f44..aec6a790b21 100644 --- a/code/game/objects/items/weapons/policetape.dm +++ b/code/game/objects/items/weapons/policetape.dm @@ -4,6 +4,9 @@ icon = 'icons/policetape.dmi' icon_state = "tape" w_class = ITEMSIZE_SMALL + + toolspeed = 3 //You can use it in surgery. It's stupid, but you can. + var/turf/start var/turf/end var/tape_type = /obj/item/tape diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index f2aad7a86dd..c7607d5aeb8 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -86,7 +86,6 @@ /obj/item/weapon/weldingtool, /obj/item/weapon/tool/crowbar, /obj/item/weapon/tool/wirecutters, - /obj/item/device/t_scanner ) /obj/item/weapon/storage/belt/utility/chief diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm index 268a8d5ad77..e37b2f99770 100644 --- a/code/game/objects/items/weapons/stunbaton.dm +++ b/code/game/objects/items/weapons/stunbaton.dm @@ -19,16 +19,19 @@ var/obj/item/weapon/cell/bcell = null var/hitcost = 240 -/obj/item/weapon/melee/baton/suicide_act(mob/user) - var/datum/gender/TU = gender_datums[user.get_visible_gender()] - user.visible_message("\The [user] is putting the live [name] in [TU.his] mouth! It looks like [TU.he] [TU.is] trying to commit suicide.") - return (FIRELOSS) - /obj/item/weapon/melee/baton/New() ..() update_icon() return +/obj/item/weapon/melee/baton/get_cell() + return bcell + +/obj/item/weapon/melee/baton/suicide_act(mob/user) + var/datum/gender/TU = gender_datums[user.get_visible_gender()] + user.visible_message("\The [user] is putting the live [name] in [TU.his] mouth! It looks like [TU.he] [TU.is] trying to commit suicide.") + return (FIRELOSS) + /obj/item/weapon/melee/baton/MouseDrop(obj/over_object as obj) if(!canremove) return diff --git a/code/game/objects/items/weapons/tape.dm b/code/game/objects/items/weapons/tape.dm index 5a575155888..e3afddba4c5 100644 --- a/code/game/objects/items/weapons/tape.dm +++ b/code/game/objects/items/weapons/tape.dm @@ -5,8 +5,12 @@ icon_state = "taperoll" w_class = ITEMSIZE_TINY + toolspeed = 2 //It is now used in surgery as a not awful, but probably dangerous option, due to speed. + /obj/item/weapon/tape_roll/attack(var/mob/living/carbon/human/H, var/mob/user) if(istype(H)) + if(user.a_intent == I_HELP) + return var/can_place = 0 if(istype(user, /mob/living/silicon/robot)) can_place = 1 diff --git a/code/game/objects/items/weapons/tools/weldingtool.dm b/code/game/objects/items/weapons/tools/weldingtool.dm index bb082fe9ce0..31019176d82 100644 --- a/code/game/objects/items/weapons/tools/weldingtool.dm +++ b/code/game/objects/items/weapons/tools/weldingtool.dm @@ -1,5 +1,5 @@ -#define WELDER_FUEL_BURN_INTERVAL 13 +#define WELDER_FUEL_BURN_INTERVAL 13 /* * Welding Tool */ @@ -63,7 +63,7 @@ /obj/item/weapon/weldingtool/attackby(obj/item/W as obj, mob/living/user as mob) - if(W.is_screwdriver()) + if(istype(W,/obj/item/weapon/tool/screwdriver)) if(welding) to_chat(user, "Stop welding first!") return @@ -99,12 +99,15 @@ ..() return + /obj/item/weapon/weldingtool/process() if(welding) ++burned_fuel_for if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL) remove_fuel(1) + + if(get_fuel() < 1) setWelding(0) @@ -118,6 +121,7 @@ if (istype(location, /turf)) location.hotspot_expose(700, 5) + /obj/item/weapon/weldingtool/afterattack(obj/O as obj, mob/user as mob, proximity) if(!proximity) return if (istype(O, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,O) <= 1) @@ -146,6 +150,7 @@ location.hotspot_expose(700, 50, 1) return + /obj/item/weapon/weldingtool/attack_self(mob/user as mob) setWelding(!welding, usr) return @@ -209,24 +214,6 @@ M.update_inv_l_hand() M.update_inv_r_hand() -/obj/item/weapon/weldingtool/attack(var/atom/A, var/mob/living/user, var/def_zone) - if(ishuman(A) && user.a_intent == I_HELP) - var/mob/living/carbon/human/H = A - var/obj/item/organ/external/S = H.organs_by_name[user.zone_sel.selecting] - - if(!S || S.robotic < ORGAN_ROBOT || S.open == 3) - return ..() - - if(!welding) - to_chat(user, "You'll need to turn [src] on to patch the damage on [H]'s [S.name]!") - return 1 - - if(S.robo_repair(15, BRUTE, "some dents", src, user)) - remove_fuel(1, user) - - else - return ..() - /obj/item/weapon/weldingtool/MouseDrop(obj/over_object as obj) if(!canremove) return @@ -349,9 +336,6 @@ /obj/item/weapon/weldingtool/is_hot() return isOn() -/obj/item/weapon/weldingtool/is_welder() - return TRUE - /obj/item/weapon/weldingtool/largetank name = "industrial welding tool" desc = "A slightly larger welder with a larger tank." @@ -495,6 +479,9 @@ acti_sound = 'sound/effects/sparks4.ogg' deac_sound = 'sound/effects/sparks4.ogg' +/obj/item/weapon/weldingtool/electric/unloaded/New() + cell_type = null + /obj/item/weapon/weldingtool/electric/New() ..() if(cell_type == null) @@ -505,17 +492,17 @@ power_supply = new /obj/item/weapon/cell/device(src) update_icon() -/obj/item/weapon/weldingtool/electric/unloaded/New() - cell_type = null +/obj/item/weapon/weldingtool/electric/get_cell() + return power_supply /obj/item/weapon/weldingtool/electric/examine(mob/user) if(get_dist(src, user) > 1) to_chat(user, desc) else // The << need to stay, for some reason if(power_supply) - to_chat(user, text("\icon[] The [] has [] charge left.", src, src.name, get_fuel())) + user << text("\icon[] The [] has [] charge left.", src, src.name, get_fuel()) else - to_chat(user, text("\icon[] The [] has no power cell!", src, src.name)) + user << text("\icon[] The [] has no power cell!", src, src.name) /obj/item/weapon/weldingtool/electric/get_fuel() if(use_external_power) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index f8782c4728b..9c2fb604346 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -163,3 +163,6 @@ /obj/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2) return + +/obj/proc/get_cell() + return \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm index 96b0030d21e..cad925f6e88 100644 --- a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm +++ b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm @@ -16,6 +16,10 @@ starts_with = list(/obj/item/weapon/material/twohanded/fireaxe) +/obj/structure/closet/fireaxecabinet/initialize() + ..() + fireaxe = locate() in contents + /obj/structure/closet/fireaxecabinet/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri //..() //That's very useful, Erro @@ -115,6 +119,7 @@ if(src.locked) to_chat(user, "The cabinet won't budge!") return + if(localopened) if(fireaxe) user.put_in_hands(fireaxe) diff --git a/code/game/objects/structures/flora/trees.dm b/code/game/objects/structures/flora/trees.dm index ef58518e489..8b7f5bf0424 100644 --- a/code/game/objects/structures/flora/trees.dm +++ b/code/game/objects/structures/flora/trees.dm @@ -4,7 +4,8 @@ anchored = 1 density = 1 pixel_x = -16 - layer = MOB_LAYER // You know what, let's play it safe. + plane = MOB_PLANE // You know what, let's play it safe. + layer = ABOVE_MOB_LAYER var/base_state = null // Used for stumps. var/health = 200 // Used for chopping down trees. var/max_health = 200 @@ -51,12 +52,12 @@ animate(transform=null, pixel_x=init_px, time=6, easing=ELASTIC_EASING) // Used when the tree gets hurt. -/obj/structure/flora/tree/proc/adjust_health(var/amount, var/is_ranged = FALSE) +/obj/structure/flora/tree/proc/adjust_health(var/amount, var/damage_wood = FALSE) if(is_stump) return // Bullets and lasers ruin some of the wood - if(is_ranged && product_amount > 0) + if(damage_wood && product_amount > 0) var/wood = initial(product_amount) product_amount -= round(wood * (abs(amount)/max_health)) @@ -89,12 +90,16 @@ set_light(0) /obj/structure/flora/tree/ex_act(var/severity) - adjust_health(-(max_health / severity)) + adjust_health(-(max_health / severity), TRUE) /obj/structure/flora/tree/bullet_act(var/obj/item/projectile/Proj) if(Proj.get_structure_damage()) adjust_health(-Proj.get_structure_damage(), TRUE) +/obj/structure/flora/tree/tesla_act(power, explosive) + adjust_health(-power / 100, TRUE) // Kills most trees in one lightning strike. + ..() + /obj/structure/flora/tree/get_description_interaction() var/list/results = list() diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index 69237285647..4c1bc63618a 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -20,6 +20,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) /obj/structure/janitorialcart/New() create_reagents(300) + ..() /obj/structure/janitorialcart/examine(mob/user) diff --git a/code/game/objects/structures/plasticflaps.dm b/code/game/objects/structures/plasticflaps.dm new file mode 100644 index 00000000000..0340356e37c --- /dev/null +++ b/code/game/objects/structures/plasticflaps.dm @@ -0,0 +1,78 @@ +/obj/structure/plasticflaps //HOW DO YOU CALL THOSE THINGS ANYWAY + name = "\improper plastic flaps" + desc = "Completely impassable - or are they?" + icon = 'icons/obj/stationobjs.dmi' //Change this. + icon_state = "plasticflaps" + density = 0 + anchored = 1 + layer = MOB_LAYER + plane = MOB_PLANE + explosion_resistance = 5 + var/list/mobs_can_pass = list( + /mob/living/bot, + /mob/living/simple_animal/slime, + /mob/living/simple_animal/mouse, + /mob/living/silicon/robot/drone + ) + +/obj/structure/plasticflaps/attackby(obj/item/P, mob/user) + if(P.is_wirecutter()) + playsound(src, P.usesound, 50, 1) + user << "You start to cut the plastic flaps." + if(do_after(user, 10 * P.toolspeed)) + user << "You cut the plastic flaps." + var/obj/item/stack/material/plastic/A = new /obj/item/stack/material/plastic( src.loc ) + A.amount = 4 + qdel(src) + return + else + return + +/obj/structure/plasticflaps/CanPass(atom/A, turf/T) + if(istype(A) && A.checkpass(PASSGLASS)) + return prob(60) + + var/obj/structure/bed/B = A + if (istype(A, /obj/structure/bed) && B.has_buckled_mobs())//if it's a bed/chair and someone is buckled, it will not pass + return 0 + + if(istype(A, /obj/vehicle)) //no vehicles + return 0 + + var/mob/living/M = A + if(istype(M)) + if(M.lying) + return ..() + for(var/mob_type in mobs_can_pass) + if(istype(A, mob_type)) + return ..() + return issmall(M) + + return ..() + +/obj/structure/plasticflaps/ex_act(severity) + switch(severity) + if (1) + qdel(src) + if (2) + if (prob(50)) + qdel(src) + if (3) + if (prob(5)) + qdel(src) + +/obj/structure/plasticflaps/mining //A specific type for mining that doesn't allow airflow because of them damn crates + name = "airtight plastic flaps" + desc = "Heavy duty, airtight, plastic flaps." + +/obj/structure/plasticflaps/mining/New() //set the turf below the flaps to block air + var/turf/T = get_turf(loc) + if(T) + T.blocks_air = 1 + ..() + +/obj/structure/plasticflaps/mining/Destroy() //lazy hack to set the turf to allow air to pass if it's a simulated floor + var/turf/T = get_turf(loc) + if(T && istype(T, /turf/simulated/floor)) + T.blocks_air = 0 + ..() \ No newline at end of file diff --git a/code/game/objects/structures/alien_props.dm b/code/game/objects/structures/props/alien_props.dm similarity index 90% rename from code/game/objects/structures/alien_props.dm rename to code/game/objects/structures/props/alien_props.dm index eb8ae9d19f3..fa11e27b15d 100644 --- a/code/game/objects/structures/alien_props.dm +++ b/code/game/objects/structures/props/alien_props.dm @@ -6,15 +6,6 @@ icon = 'icons/obj/abductor.dmi' density = TRUE anchored = TRUE - var/interaction_message = null - -/obj/structure/prop/alien/attack_hand(mob/living/user) // Used to tell the player that this isn't useful for anything. - if(!istype(user)) - return FALSE - if(!interaction_message) - return ..() - else - to_chat(user, interaction_message) /obj/structure/prop/alien/computer name = "alien console" diff --git a/code/game/objects/structures/props/beam_prism.dm b/code/game/objects/structures/props/beam_prism.dm new file mode 100644 index 00000000000..44df2eb68b0 --- /dev/null +++ b/code/game/objects/structures/props/beam_prism.dm @@ -0,0 +1,215 @@ +//A series(?) of prisms for PoIs. The base one only works for beams. + +/obj/structure/prop/prism + name = "prismatic turret" + desc = "A raised, externally powered 'turret'. It seems to have a massive crystal ring around its base." + description_info = "This device is capable of redirecting any beam projectile." + icon = 'icons/obj/props/prism.dmi' + icon_state = "prism" + density = TRUE + anchored = TRUE + + layer = 3.1 //Layer over projectiles. + plane = -10 //Layer over projectiles. + + var/rotation_lock = 0 // Can you rotate the prism at all? + var/free_rotate = 1 // Does the prism rotate in any direction, or only in the eight standard compass directions? + var/external_control_lock = 0 // Does the prism only rotate from the controls of an external switch? + var/degrees_from_north = 0 // How far is it rotated clockwise? + var/compass_directions = list("North" = 0, "South" = 180, "East" = 90, "West" = 270, "Northwest" = 315, "Northeast" = 45, "Southeast" = 135, "Southwest" = 225) + var/interaction_sound = 'sound/mecha/mechmove04.ogg' + + var/redirect_type = /obj/item/projectile/beam + + var/dialID = null + var/obj/structure/prop/prismcontrol/remote_dial = null + + interaction_message = "The prismatic turret seems to be able to rotate." + +/obj/structure/prop/prism/initialize() + if(degrees_from_north) + animate(src, transform = turn(NORTH, degrees_from_north), time = 3) + +/obj/structure/prop/prism/Destroy() + if(remote_dial) + remote_dial.my_turrets -= src + remote_dial = null + ..() + +/obj/structure/prop/prism/proc/reset_rotation() + var/degrees_to_rotate = -1 * degrees_from_north + animate(src, transform = turn(src.transform, degrees_to_rotate), time = 2) + +/obj/structure/prop/prism/attack_hand(mob/living/user) + ..() + + if(rotation_lock) + to_chat(user, "\The [src] is locked at its current bearing.") + return + if(external_control_lock) + to_chat(user, "\The [src]'s motors resist your efforts to rotate it. You may need to find some form of controller.") + return + + var/confirm = input("Do you want to try to rotate \the [src]?", "[name]") in list("Yes", "No") + if(confirm == "No") + visible_message(\ + "[user.name] decides not to try turning \the [src].",\ + "You decide not to try turning \the [src].") + return + + var/new_bearing + if(free_rotate) + new_bearing = input("What bearing do you want to rotate \the [src] to?", "[name]") as num + new_bearing = round(new_bearing) + if(new_bearing <= -1 || new_bearing > 360) + to_chat(user, "Rotating \the [src] [new_bearing] degrees would be a waste of time.") + return + else + var/choice = input("What point do you want to set \the [src] to?", "[name]") as null|anything in compass_directions + new_bearing = round(compass_directions[choice]) + + var/rotate_degrees = new_bearing - degrees_from_north + + if(new_bearing == 360) // Weird artifact. + new_bearing = 0 + degrees_from_north = new_bearing + + var/two_stage = 0 + if(rotate_degrees == 180 || rotate_degrees == -180) + two_stage = 1 + var/multiplier = pick(-1, 1) + rotate_degrees = multiplier * (rotate_degrees / 2) + + playsound(src, interaction_sound, 50, 1) + if(two_stage) + animate(src, transform = turn(src.transform, rotate_degrees), time = 3) + spawn(3) + animate(src, transform = turn(src.transform, rotate_degrees), time = 3) + else + animate(src, transform = turn(src.transform, rotate_degrees), time = 6) //Can't update transform because it will reset the angle. + +/obj/structure/prop/prism/proc/rotate_auto(var/new_bearing) + if(rotation_lock) + visible_message("\The [src] shudders.") + playsound(src, 'sound/effects/clang.ogg', 50, 1) + return + + visible_message("\The [src] rotates to a bearing of [new_bearing].") + + var/rotate_degrees = new_bearing - degrees_from_north + + if(new_bearing == 360) + new_bearing = 0 + degrees_from_north = new_bearing + + var/two_stage = 0 + if(rotate_degrees == 180 || rotate_degrees == -180) + two_stage = 1 + var/multiplier = pick(-1, 1) + rotate_degrees = multiplier * (rotate_degrees / 2) + + playsound(src, interaction_sound, 50, 1) + if(two_stage) + animate(src, transform = turn(src.transform, rotate_degrees), time = 3) + spawn(3) + animate(src, transform = turn(src.transform, rotate_degrees), time = 3) + else + animate(src, transform = turn(src.transform, rotate_degrees), time = 6) + +/obj/structure/prop/prism/bullet_act(var/obj/item/projectile/Proj) + if(istype(Proj, redirect_type)) + visible_message("\The [src] redirects \the [Proj]!") + flick("[initial(icon_state)]+glow", src) + + var/new_x = (1 * round(10 * cos(degrees_from_north - 90))) + x //Vectors vectors vectors. + var/new_y = (-1 * round(10 * sin(degrees_from_north - 90))) + y + var/turf/curloc = get_turf(src) + + Proj.penetrating += 1 // Needed for the beam to get out of the turret. + + Proj.redirect(new_x, new_y, curloc, null) + +/obj/structure/prop/prism/incremental + free_rotate = 0 + description_info = "This device is capable of redirecting any beam projectile, but only locks to specific positions in rotation." + +/obj/structure/prop/prism/incremental/externalcont + external_control_lock = 1 + description_info = "This device is capable of redirecting any beam projectile, but can only be rotated by a control dial to specific positions." + +/obj/structure/prop/prism/externalcont + external_control_lock = 1 + description_info = "This device is capable of redirecting any beam projectile, but can only be rotated by an external control dial." + +/obj/structure/prop/prismcontrol + name = "prismatic dial" + desc = "A large dial with a crystalline ring." + icon = 'icons/obj/props/prism.dmi' + icon_state = "dial" + density = FALSE + anchored = TRUE + + interaction_message = "The dial pulses as your hand nears it." + var/list/my_turrets = list() + var/dialID = null + +/obj/structure/prop/prismcontrol/attack_hand(mob/living/user) + ..() + + var/confirm = input("Do you want to try to rotate \the [src]?", "[name]") in list("Yes", "No") + if(confirm == "No") + visible_message(\ + "[user.name] decides not to try turning \the [src].",\ + "You decide not to try turning \the [src].") + return + + if(!my_turrets || !my_turrets.len) + to_chat(user, "\The [src] doesn't seem to do anything.") + return + + var/free_rotate = 1 + var/list/compass_directions = list() + for(var/obj/structure/prop/prism/P in my_turrets) + if(!P.free_rotate) //Doesn't use bearing, it uses compass points. + free_rotate = 0 + compass_directions |= P.compass_directions + + var/new_bearing + if(free_rotate) + new_bearing = input("What bearing do you want to rotate \the [src] to?", "[name]") as num + new_bearing = round(new_bearing) + if(new_bearing <= -1 || new_bearing > 360) + to_chat(user, "Rotating \the [src] [new_bearing] degrees would be a waste of time.") + return + else + var/choice = input("What point do you want to set \the [src] to?", "[name]") as null|anything in compass_directions + new_bearing = round(compass_directions[choice]) + + confirm = input("Are you certain you want to rotate \the [src]?", "[name]") in list("Yes", "No") + if(confirm == "No") + visible_message(\ + "[user.name] decides not to try turning \the [src].",\ + "You decide not to try turning \the [src].") + return + + to_chat(user, "\The [src] clicks into place.") + for(var/obj/structure/prop/prism/P in my_turrets) + P.rotate_auto(new_bearing) + +/obj/structure/prop/prismcontrol/initialize() + ..() + if(my_turrets.len) //Preset controls. + for(var/obj/structure/prop/prism/P in my_turrets) + P.remote_dial = src + return + spawn() + for(var/obj/structure/prop/prism/P in orange(src, world.view)) //Don't search a huge area. + if(P.dialID == dialID && !P.remote_dial && P.external_control_lock) + my_turrets |= P + P.remote_dial = src + +/obj/structure/prop/prismcontrol/Destroy() + for(var/obj/structure/prop/prism/P in my_turrets) + P.remote_dial = null + my_turrets = list() + ..() diff --git a/code/game/objects/structures/props/projectile_lock.dm b/code/game/objects/structures/props/projectile_lock.dm new file mode 100644 index 00000000000..5c3fcd2ba07 --- /dev/null +++ b/code/game/objects/structures/props/projectile_lock.dm @@ -0,0 +1,53 @@ +//A locking mechanism that pulses when hit by a projectile. The base one responds to high-power lasers. + +/obj/structure/prop/lock + name = "weird lock" + desc = "An esoteric object that responds to.. something." + icon = 'icons/obj/props/prism.dmi' + icon_state = "lock" + + var/enabled = 0 + var/lockID = null + + var/list/linked_objects = list() + +/obj/structure/prop/lock/Destroy() + if(linked_objects.len) + for(var/obj/O in linked_objects) + if(istype(O, /obj/machinery/door/blast/puzzle)) + var/obj/machinery/door/blast/puzzle/P = O + P.locks -= src + linked_objects -= P + ..() + +/obj/structure/prop/lock/proc/toggle_lock() + enabled = !enabled + + if(enabled) + icon_state = "[initial(icon_state)]-active" + else + icon_state = "[initial(icon_state)]" + +/obj/structure/prop/lock/projectile + name = "beam lock" + desc = "An esoteric object that responds to high intensity light." + + var/projectile_key = /obj/item/projectile/beam + var/timed = 0 + var/timing = 0 + var/time_limit = 1500 // In ticks. Ten is one second. + + interaction_message = "The object remains inert to your touch." + +/obj/structure/prop/lock/projectile/bullet_act(var/obj/item/projectile/Proj) + if(!istype(Proj, projectile_key) || timing) + return + + if(istype(Proj, /obj/item/projectile/beam/heavylaser/cannon) || istype(Proj, /obj/item/projectile/beam/emitter) || (Proj.damage >= 80 && Proj.damtype == BURN)) + toggle_lock() + visible_message("\The [src] [enabled ? "disengages" : "engages"] its locking mechanism.") + + if(timed) + timing = 1 + spawn(time_limit) + toggle_lock() diff --git a/code/game/objects/structures/props/prop.dm b/code/game/objects/structures/props/prop.dm new file mode 100644 index 00000000000..fea5815674d --- /dev/null +++ b/code/game/objects/structures/props/prop.dm @@ -0,0 +1,18 @@ +//The base 'prop' for PoIs or other large junk. + +/obj/structure/prop + name = "something" + desc = "My description is broken, bug a developer." + icon = 'icons/obj/structures.dmi' + icon_state = "safe" + density = TRUE + anchored = TRUE + var/interaction_message = null + +/obj/structure/prop/attack_hand(mob/living/user) // Used to tell the player that this isn't useful for anything. + if(!istype(user)) + return FALSE + if(!interaction_message) + return ..() + else + to_chat(user, interaction_message) diff --git a/code/game/objects/structures/props/puzzledoor.dm b/code/game/objects/structures/props/puzzledoor.dm new file mode 100644 index 00000000000..b9a32fc0dcc --- /dev/null +++ b/code/game/objects/structures/props/puzzledoor.dm @@ -0,0 +1,92 @@ +// An indestructible blast door that can only be opened once its puzzle requirements are completed. + +/obj/machinery/door/blast/puzzle + name = "puzzle door" + desc = "A large, virtually indestructible door that will not open unless certain requirements are met." + icon_state_open = "pdoor0" + icon_state_opening = "pdoorc0" + icon_state_closed = "pdoor1" + icon_state_closing = "pdoorc1" + icon_state = "pdoor1" + + explosion_resistance = 100 + + maxhealth = 9999999 //No. + + var/list/locks = list() + var/lockID = null + var/checkrange_mult = 1 + +/obj/machinery/door/blast/puzzle/proc/check_locks() + for(var/obj/structure/prop/lock/L in locks) + if(!L.enabled) + return 0 + return 1 + +/obj/machinery/door/blast/puzzle/bullet_act(var/obj/item/projectile/Proj) + visible_message("\The [src] is completely unaffected by \the [Proj].") + qdel(Proj) //No piercing. No. + +/obj/machinery/door/blast/puzzle/ex_act(severity) + visible_message("\The [src] is completely unaffected by the blast.") + return + +/obj/machinery/door/blast/puzzle/initialize() + . = ..() + implicit_material = get_material_by_name("dungeonium") + if(locks.len) + return + var/check_range = world.view * checkrange_mult + for(var/obj/structure/prop/lock/L in orange(src, check_range)) + if(L.lockID == lockID) + L.linked_objects |= src + locks |= L + +/obj/machinery/door/blast/puzzle/Destroy() + if(locks.len) + for(var/obj/structure/prop/lock/L in locks) + L.linked_objects -= src + locks -= L + ..() + +/obj/machinery/door/blast/puzzle/attack_hand(mob/user as mob) + if(check_locks()) + force_toggle(1, user) + else + to_chat(user, "\The [src] does not respond to your touch.") + +/obj/machinery/door/blast/puzzle/attackby(obj/item/weapon/C as obj, mob/user as mob) + if(istype(C, /obj/item/weapon)) + if(C.pry == 1 && (user.a_intent != I_HURT || (stat & BROKEN))) + if(istype(C,/obj/item/weapon/material/twohanded/fireaxe)) + var/obj/item/weapon/material/twohanded/fireaxe/F = C + if(!F.wielded) + to_chat(user, "You need to be wielding \the [F] to do that.") + return + + if(check_locks()) + force_toggle(1, user) + + else + to_chat(user, "[src]'s arcane workings resist your effort.") + return + + else if(src.density && (user.a_intent == I_HURT)) + var/obj/item/weapon/W = C + user.setClickCooldown(user.get_attack_speed(W)) + if(W.damtype == BRUTE || W.damtype == BURN) + user.do_attack_animation(src) + user.visible_message("\The [user] hits \the [src] with \the [W] with no visible effect.") + + else if(istype(C, /obj/item/weapon/plastique)) + to_chat(user, "On contacting \the [src], a flash of light envelops \the [C] as it is turned to ash. Oh.") + qdel(C) + return 0 + +/obj/machinery/door/blast/puzzle/attack_generic(var/mob/user, var/damage) + if(check_locks()) + force_toggle(1, user) + +/obj/machinery/door/blast/puzzle/attack_alien(var/mob/user) + if(check_locks()) + force_toggle(1, user) diff --git a/code/game/sound.dm b/code/game/sound.dm index 2db1e433bde..8e206300a8f 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -130,6 +130,9 @@ if ("mechstep") soundin = pick('sound/mecha/mechstep1.ogg', 'sound/mecha/mechstep2.ogg') if ("geiger") soundin = pick('sound/items/geiger1.ogg', 'sound/items/geiger2.ogg', 'sound/items/geiger3.ogg', 'sound/items/geiger4.ogg', 'sound/items/geiger5.ogg') if ("geiger_weak") soundin = pick('sound/items/geiger_weak1.ogg', 'sound/items/geiger_weak2.ogg', 'sound/items/geiger_weak3.ogg', 'sound/items/geiger_weak4.ogg') + if ("thunder") soundin = pick('sound/effects/thunder/thunder1.ogg', 'sound/effects/thunder/thunder2.ogg', 'sound/effects/thunder/thunder3.ogg', 'sound/effects/thunder/thunder4.ogg', + 'sound/effects/thunder/thunder5.ogg', 'sound/effects/thunder/thunder6.ogg', 'sound/effects/thunder/thunder7.ogg', 'sound/effects/thunder/thunder8.ogg', 'sound/effects/thunder/thunder9.ogg', + 'sound/effects/thunder/thunder10.ogg') return soundin //Are these even used? diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index 061ac1f065e..e69de29bb2d 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -1,333 +0,0 @@ -//Config stuff -#define SUPPLY_DOCKZ 2 //Z-level of the Dock. -#define SUPPLY_STATIONZ 1 //Z-level of the Station. -#define SUPPLY_STATION_AREATYPE "/area/supply/station" //Type of the supply shuttle area for station -#define SUPPLY_DOCK_AREATYPE "/area/supply/dock" //Type of the supply shuttle area for dock - -//Supply packs are in /code/defines/obj/supplypacks.dm -//Computers are in /code/game/machinery/computer/supply.dm - -var/datum/controller/supply/supply_controller = new() - -var/list/mechtoys = list( - /obj/item/toy/prize/ripley, - /obj/item/toy/prize/fireripley, - /obj/item/toy/prize/deathripley, - /obj/item/toy/prize/gygax, - /obj/item/toy/prize/durand, - /obj/item/toy/prize/honk, - /obj/item/toy/prize/marauder, - /obj/item/toy/prize/seraph, - /obj/item/toy/prize/mauler, - /obj/item/toy/prize/odysseus, - /obj/item/toy/prize/phazon -) - -/obj/item/weapon/paper/manifest - name = "supply manifest" - var/is_copy = 1 - -/area/supply/station - name = "Supply Shuttle" - icon_state = "shuttle3" - requires_power = 0 - base_turf = /turf/space - -/area/supply/dock - name = "Supply Shuttle" - icon_state = "shuttle3" - requires_power = 0 - base_turf = /turf/space - -/obj/structure/plasticflaps //HOW DO YOU CALL THOSE THINGS ANYWAY - name = "\improper plastic flaps" - desc = "Completely impassable - or are they?" - icon = 'icons/obj/stationobjs.dmi' //Change this. - icon_state = "plasticflaps" - density = 0 - anchored = 1 - layer = MOB_LAYER - plane = MOB_PLANE - explosion_resistance = 5 - var/list/mobs_can_pass = list( - /mob/living/bot, - /mob/living/simple_animal/slime, - /mob/living/simple_animal/mouse, - /mob/living/silicon/robot/drone - ) - -/obj/structure/plasticflaps/attackby(obj/item/P, mob/user) - if(P.is_wirecutter()) - playsound(src, P.usesound, 50, 1) - user << "You start to cut the plastic flaps." - if(do_after(user, 10 * P.toolspeed)) - user << "You cut the plastic flaps." - var/obj/item/stack/material/plastic/A = new /obj/item/stack/material/plastic( src.loc ) - A.amount = 4 - qdel(src) - return - else - return - -/obj/structure/plasticflaps/CanPass(atom/A, turf/T) - if(istype(A) && A.checkpass(PASSGLASS)) - return prob(60) - - var/obj/structure/bed/B = A - if (istype(A, /obj/structure/bed) && B.has_buckled_mobs())//if it's a bed/chair and someone is buckled, it will not pass - return 0 - - if(istype(A, /obj/vehicle)) //no vehicles - return 0 - - var/mob/living/M = A - if(istype(M)) - if(M.lying) - return ..() - for(var/mob_type in mobs_can_pass) - if(istype(A, mob_type)) - return ..() - return issmall(M) - - return ..() - -/obj/structure/plasticflaps/ex_act(severity) - switch(severity) - if (1) - qdel(src) - if (2) - if (prob(50)) - qdel(src) - if (3) - if (prob(5)) - qdel(src) - -/obj/structure/plasticflaps/mining //A specific type for mining that doesn't allow airflow because of them damn crates - name = "airtight plastic flaps" - desc = "Heavy duty, airtight, plastic flaps." - -/obj/structure/plasticflaps/mining/New() //set the turf below the flaps to block air - var/turf/T = get_turf(loc) - if(T) - T.blocks_air = 1 - ..() - -/obj/structure/plasticflaps/mining/Destroy() //lazy hack to set the turf to allow air to pass if it's a simulated floor - var/turf/T = get_turf(loc) - if(T && istype(T, /turf/simulated/floor)) - T.blocks_air = 0 - ..() - -/* -/obj/effect/marker/supplymarker - icon_state = "X" - icon = 'icons/misc/mark.dmi' - name = "X" - invisibility = 101 - anchored = 1 - opacity = 0 -*/ - -/datum/supply_order - var/ordernum - var/datum/supply_packs/object = null - var/orderedby = null - var/comment = null - -/datum/exported_crate - var/name - var/value - -/datum/controller/supply - //supply points - var/points = 50 - var/points_per_process = 1.5 - var/points_per_slip = 2 - var/points_per_platinum = 5 // 5 points per sheet - var/points_per_phoron = 5 - var/points_per_money = 0.02 - //control - var/ordernum - var/list/shoppinglist = list() - var/list/requestlist = list() - var/list/supply_packs = list() - var/list/exported_crates = list() - //shuttle movement - var/movetime = 1200 - var/datum/shuttle/ferry/supply/shuttle - -/datum/controller/supply/New() - ordernum = rand(1,9000) - - for(var/typepath in (typesof(/datum/supply_packs) - /datum/supply_packs)) - var/datum/supply_packs/P = new typepath() - supply_packs[P.name] = P - -// Supply shuttle ticker - handles supply point regeneration -// This is called by the process scheduler every thirty seconds -/datum/controller/supply/proc/process() - points += points_per_process - -//To stop things being sent to CentCom which should not be sent to centcomm. Recursively checks for these types. -/datum/controller/supply/proc/forbidden_atoms_check(atom/A) - if(isliving(A)) - return 1 - if(istype(A,/obj/item/weapon/disk/nuclear)) - return 1 - if(istype(A,/obj/machinery/nuclearbomb)) - return 1 - if(istype(A,/obj/item/device/radio/beacon)) - return 1 - - for(var/i=1, i<=A.contents.len, i++) - var/atom/B = A.contents[i] - if(.(B)) - return 1 - -//Sellin -/datum/controller/supply/proc/sell() - var/area/area_shuttle = shuttle.get_location_area() - if(!area_shuttle) return - - callHook("sell_shuttle", list(area_shuttle)); - - var/phoron_count = 0 - var/plat_count = 0 - var/money_count = 0 - - exported_crates = list() - - for(var/atom/movable/MA in area_shuttle) - if(MA.anchored) continue - - // Must be in a crate! - if(istype(MA,/obj/structure/closet/crate)) - var/oldpoints = points - var/oldphoron = phoron_count - var/oldplatinum = plat_count - var/oldmoney = money_count - - var/obj/structure/closet/crate/CR = MA - callHook("sell_crate", list(CR, area_shuttle)) - - points += CR.points_per_crate - var/find_slip = 1 - - for(var/atom in CR) - // Sell manifests - var/atom/A = atom - if(find_slip && istype(A,/obj/item/weapon/paper/manifest)) - var/obj/item/weapon/paper/manifest/slip = A - if(!slip.is_copy && slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense - points += points_per_slip - find_slip = 0 - continue - - // Sell phoron and platinum - if(istype(A, /obj/item/stack)) - var/obj/item/stack/P = A - switch(P.get_material_name()) - if("phoron") phoron_count += P.get_amount() - if("platinum") plat_count += P.get_amount() - - //Sell spacebucks - if(istype(A, /obj/item/weapon/spacecash)) - var/obj/item/weapon/spacecash/cashmoney = A - money_count += cashmoney.worth - - var/datum/exported_crate/EC = new /datum/exported_crate() - EC.name = CR.name - EC.value = points - oldpoints - EC.value += (phoron_count - oldphoron) * points_per_phoron - EC.value += (plat_count - oldplatinum) * points_per_platinum - EC.value += (money_count - oldmoney) * points_per_money - exported_crates += EC - - qdel(MA) - - points += phoron_count * points_per_phoron - points += plat_count * points_per_platinum - points += money_count * points_per_money - -//Buyin -/datum/controller/supply/proc/buy() - if(!shoppinglist.len) - return - - var/orderedamount = shoppinglist.len - - var/area/area_shuttle = shuttle.get_location_area() - if(!area_shuttle) - return - - var/list/clear_turfs = list() - - for(var/turf/T in area_shuttle) - if(T.density) - continue - var/contcount - for(var/atom/A in T.contents) - if(!A.simulated) - continue - contcount++ - if(contcount) - continue - clear_turfs += T - - for(var/S in shoppinglist) - if(!clear_turfs.len) break - var/i = rand(1,clear_turfs.len) - var/turf/pickedloc = clear_turfs[i] - clear_turfs.Cut(i,i+1) - shoppinglist -= S - - var/datum/supply_order/SO = S - var/datum/supply_packs/SP = SO.object - - var/obj/A = new SP.containertype(pickedloc) - A.name = "[SP.containername] [SO.comment ? "([SO.comment])":"" ]" - - //supply manifest generation begin - var/obj/item/weapon/paper/manifest/slip - if(!SP.contraband) - slip = new /obj/item/weapon/paper/manifest(A) - slip.is_copy = 0 - slip.info = "

[command_name()] Shipping Manifest



" - slip.info +="Order #[SO.ordernum]
" - slip.info +="Destination: [station_name()]
" - slip.info +="[orderedamount] PACKAGES IN THIS SHIPMENT
" - slip.info +="CONTENTS:

" - slip.info += "CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS
" - - return diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index e1565889378..1c74b467e22 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -12,6 +12,7 @@ nitrogen = MOLES_N2STANDARD var/to_be_destroyed = 0 //Used for fire, if a melting temperature was reached, it will be destroyed var/max_fire_temperature_sustained = 0 //The max temperature of the fire which it was subjected to + var/can_dirty = TRUE // If false, tile never gets dirty var/dirt = 0 // This is not great. @@ -65,12 +66,13 @@ tracks.AddTracks(bloodDNA,comingdir,goingdir,bloodcolor) /turf/simulated/proc/update_dirt() - dirt = min(dirt+1, 101) - var/obj/effect/decal/cleanable/dirt/dirtoverlay = locate(/obj/effect/decal/cleanable/dirt, src) - if (dirt > 50) - if (!dirtoverlay) - dirtoverlay = new/obj/effect/decal/cleanable/dirt(src) - dirtoverlay.alpha = min((dirt - 50) * 5, 255) + if(can_dirty) + dirt = min(dirt+1, 101) + var/obj/effect/decal/cleanable/dirt/dirtoverlay = locate(/obj/effect/decal/cleanable/dirt, src) + if (dirt > 50) + if (!dirtoverlay) + dirtoverlay = new/obj/effect/decal/cleanable/dirt(src) + dirtoverlay.alpha = min((dirt - 50) * 5, 255) /turf/simulated/Entered(atom/A, atom/OL) if(movement_disabled && usr.ckey != movement_disabled_exception) @@ -82,8 +84,9 @@ if(M.lying) return ..() - // Dirt overlays. - update_dirt() + if(M.dirties_floor()) + // Dirt overlays. + update_dirt() if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M diff --git a/code/game/turfs/simulated/dungeon/wall.dm b/code/game/turfs/simulated/dungeon/wall.dm index 176c10142c4..c1a02cde666 100644 --- a/code/game/turfs/simulated/dungeon/wall.dm +++ b/code/game/turfs/simulated/dungeon/wall.dm @@ -12,6 +12,9 @@ /turf/simulated/wall/dungeon/ex_act() return +/turf/simulated/wall/dungeon/take_damage() //These things are suppose to be unbreakable + return + /turf/simulated/wall/solidrock //for more stylish anti-cheese. name = "solid rock" desc = "This rock seems dense, impossible to drill." @@ -37,4 +40,7 @@ return /turf/simulated/wall/solidrock/ex_act() + return + +/turf/simulated/wall/solidrock/take_damage() //These things are suppose to be unbreakable return \ No newline at end of file diff --git a/code/game/turfs/simulated/floor_attackby.dm b/code/game/turfs/simulated/floor_attackby.dm index de6203827e9..da76ea419f1 100644 --- a/code/game/turfs/simulated/floor_attackby.dm +++ b/code/game/turfs/simulated/floor_attackby.dm @@ -9,6 +9,50 @@ attack_tile(C, L) // Be on help intent if you want to decon something. return + if(istype(C, /obj/item/stack/tile/roofing)) + var/expended_tile = FALSE // To track the case. If a ceiling is built in a multiz zlevel, it also necessarily roofs it against weather + var/turf/T = GetAbove(src) + var/obj/item/stack/tile/roofing/R = C + + // Patch holes in the ceiling + if(T) + if(istype(T, /turf/simulated/open) || istype(T, /turf/space)) + // Must be build adjacent to an existing floor/wall, no floating floors + var/list/cardinalTurfs = list() // Up a Z level + for(var/dir in cardinal) + var/turf/B = get_step(T, dir) + if(B) + cardinalTurfs += B + + var/turf/simulated/A = locate(/turf/simulated/floor) in cardinalTurfs + if(!A) + A = locate(/turf/simulated/wall) in cardinalTurfs + if(!A) + to_chat(user, "There's nothing to attach the ceiling to!") + return + + if(R.use(1)) // Cost of roofing tiles is 1:1 with cost to place lattice and plating + T.ReplaceWithLattice() + T.ChangeTurf(/turf/simulated/floor, preserve_outdoors = TRUE) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) + user.visible_message("[user] patches a hole in the ceiling.", "You patch a hole in the ceiling.") + expended_tile = TRUE + else + to_chat(user, "There aren't any holes in the ceiling to patch here.") + return + + // Create a ceiling to shield from the weather + if(src.outdoors) + for(var/dir in cardinal) + var/turf/A = get_step(src, dir) + if(A && !A.outdoors) + if(expended_tile || R.use(1)) + make_indoors() + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) + user.visible_message("[user] roofs a tile, shielding it from the elements.", "You roof this tile, shielding it from the elements.") + break + return + if(flooring) if(istype(C, /obj/item/weapon)) try_deconstruct_tile(C, user) diff --git a/code/game/turfs/simulated/outdoors/outdoors.dm b/code/game/turfs/simulated/outdoors/outdoors.dm index 969c77f4fb5..f56d5a2da36 100644 --- a/code/game/turfs/simulated/outdoors/outdoors.dm +++ b/code/game/turfs/simulated/outdoors/outdoors.dm @@ -1,5 +1,4 @@ var/list/turf_edge_cache = list() -var/list/outdoor_turfs = list() /turf/ // If greater than 0, this turf will apply edge overlays on top of other turfs cardinally adjacent to it, if those adjacent turfs are of a different icon_state, @@ -24,24 +23,21 @@ var/list/outdoor_turfs = list() /turf/simulated/floor/New() if(outdoors) - outdoor_turfs.Add(src) + SSplanets.addTurf(src) ..() /turf/simulated/floor/Destroy() if(outdoors) - planet_controller.unallocateTurf(src) + SSplanets.removeTurf(src) return ..() /turf/simulated/proc/make_outdoors() outdoors = TRUE - outdoor_turfs.Add(src) + SSplanets.addTurf(src) /turf/simulated/proc/make_indoors() outdoors = FALSE - if(planet_controller) - planet_controller.unallocateTurf(src) - else // This is happening during map gen, if there's no planet_controller (hopefully). - outdoor_turfs -= src + SSplanets.removeTurf(src) /turf/simulated/post_change() ..() @@ -58,8 +54,8 @@ var/list/outdoor_turfs = list() if(istype(T) && T.edge_blending_priority && edge_blending_priority < T.edge_blending_priority && icon_state != T.icon_state) var/cache_key = "[T.get_edge_icon_state()]-[checkdir]" if(!turf_edge_cache[cache_key]) - var/image/I = image(icon = 'icons/turf/outdoors_edge.dmi', icon_state = "[T.get_edge_icon_state()]-edge", dir = checkdir) - I.plane = 0 + var/image/I = image(icon = 'icons/turf/outdoors_edge.dmi', icon_state = "[T.get_edge_icon_state()]-edge", dir = checkdir, layer = ABOVE_TURF_LAYER) + I.plane = TURF_PLANE turf_edge_cache[cache_key] = I add_overlay(turf_edge_cache[cache_key]) diff --git a/code/game/turfs/simulated/outdoors/sky.dm b/code/game/turfs/simulated/outdoors/sky.dm index c329fc2e4d1..468b893b335 100644 --- a/code/game/turfs/simulated/outdoors/sky.dm +++ b/code/game/turfs/simulated/outdoors/sky.dm @@ -14,7 +14,7 @@ /turf/simulated/sky/initialize() . = ..() - outdoor_turfs.Add(src) + SSplanets.addTurf(src) set_light(2, 2, "#FFFFFF") /turf/simulated/sky/north diff --git a/code/game/turfs/simulated/wall_attacks.dm b/code/game/turfs/simulated/wall_attacks.dm index bc62d1dc351..70cacfba2ca 100644 --- a/code/game/turfs/simulated/wall_attacks.dm +++ b/code/game/turfs/simulated/wall_attacks.dm @@ -142,15 +142,44 @@ return //get the user's location - if(!istype(user.loc, /turf)) return //can't do this stuff whilst inside objects and such + if(!istype(user.loc, /turf)) + return //can't do this stuff whilst inside objects and such if(W) radiate() if(is_hot(W)) burn(is_hot(W)) + if(istype(W, /obj/item/stack/tile/roofing)) + var/expended_tile = FALSE // To track the case. If a ceiling is built in a multiz zlevel, it also necessarily roofs it against weather + var/turf/T = GetAbove(src) + var/obj/item/stack/tile/roofing/R = W + + // Place plating over a wall + if(T) + if(istype(T, /turf/simulated/open) || istype(T, /turf/space)) + if(R.use(1)) // Cost of roofing tiles is 1:1 with cost to place lattice and plating + T.ReplaceWithLattice() + T.ChangeTurf(/turf/simulated/floor, preserve_outdoors = TRUE) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) + user.visible_message("[user] patches a hole in the ceiling.", "You patch a hole in the ceiling.") + expended_tile = TRUE + else + to_chat(user, "There aren't any holes in the ceiling to patch here.") + return + + // Create a ceiling to shield from the weather + if(outdoors) + if(expended_tile || R.use(1)) // Don't need to check adjacent turfs for a wall, we're building on one + make_indoors() + if(!expended_tile) // Would've already played a sound + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) + user.visible_message("[user] roofs \the [src], shielding it from the elements.", "You roof \the [src] tile, shielding it from the elements.") + return + + if(locate(/obj/effect/overlay/wallrot) in src) - if(W.is_welder()) + if(istype(W, /obj/item/weapon/weldingtool) ) var/obj/item/weapon/weldingtool/WT = W if( WT.remove_fuel(0,user) ) to_chat(user, "You burn away the fungi with \the [WT].") @@ -165,7 +194,7 @@ //THERMITE related stuff. Calls src.thermitemelt() which handles melting simulated walls and the relevant effects if(thermite) - if(W.is_welder()) + if( istype(W, /obj/item/weapon/weldingtool) ) var/obj/item/weapon/weldingtool/WT = W if( WT.remove_fuel(0,user) ) thermitemelt(user) @@ -188,7 +217,7 @@ var/turf/T = user.loc //get user's location for delay checks - if(damage && W.is_welder()) + if(damage && istype(W, /obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/WT = W @@ -214,7 +243,7 @@ var/dismantle_verb var/dismantle_sound - if(W.is_welder()) + if(istype(W,/obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/WT = W if(!WT.isOn()) return @@ -282,7 +311,7 @@ return if(4) var/cut_cover - if(W.is_welder()) + if(istype(W,/obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/WT = W if(!WT.isOn()) return @@ -337,7 +366,7 @@ return if(1) var/cut_cover - if(W.is_welder()) + if(istype(W, /obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/WT = W if( WT.remove_fuel(0,user) ) cut_cover=1 diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index e5bb57ad9e8..b64ba73ee33 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -115,9 +115,9 @@ plant.pixel_y = 0 plant.update_neighbors() -/turf/simulated/wall/ChangeTurf(var/newtype) +/turf/simulated/wall/ChangeTurf(var/turf/N, var/tell_universe, var/force_lighting_update, var/preserve_outdoors) clear_plants() - ..(newtype) + ..(N, tell_universe, force_lighting_update, preserve_outdoors) //Appearance /turf/simulated/wall/examine(mob/user) diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm index e4b762d7333..b7f4299f023 100644 --- a/code/game/turfs/simulated/water.dm +++ b/code/game/turfs/simulated/water.dm @@ -19,6 +19,7 @@ ..() // To get the edges. icon_state = water_state var/image/floorbed_sprite = image(icon = 'icons/turf/outdoors.dmi', icon_state = under_state) + underlays.Cut() // To clear the old underlay, so the list doesn't expand infinitely underlays.Add(floorbed_sprite) update_icon_edge() diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index 13368bb7ed7..ed480130503 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -33,18 +33,18 @@ /turf/space/attackby(obj/item/C as obj, mob/user as mob) - if (istype(C, /obj/item/stack/rods)) + if(istype(C, /obj/item/stack/rods)) var/obj/structure/lattice/L = locate(/obj/structure/lattice, src) if(L) return var/obj/item/stack/rods/R = C if (R.use(1)) - user << "Constructing support lattice ..." + to_chat(user, "Constructing support lattice ...") playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) ReplaceWithLattice() return - if (istype(C, /obj/item/stack/tile/floor)) + if(istype(C, /obj/item/stack/tile/floor)) var/obj/structure/lattice/L = locate(/obj/structure/lattice, src) if(L) var/obj/item/stack/tile/floor/S = C @@ -56,7 +56,33 @@ ChangeTurf(/turf/simulated/floor/airless) return else - user << "The plating is going to need some support." + to_chat(user, "The plating is going to need some support.") + + if(istype(C, /obj/item/stack/tile/roofing)) + var/turf/T = GetAbove(src) + var/obj/item/stack/tile/roofing/R = C + + // Patch holes in the ceiling + if(T) + if(istype(T, /turf/simulated/open) || istype(T, /turf/space)) + // Must be build adjacent to an existing floor/wall, no floating floors + var/turf/simulated/A = locate(/turf/simulated/floor) in T.CardinalTurfs() + if(!A) + A = locate(/turf/simulated/wall) in T.CardinalTurfs() + if(!A) + to_chat(user, "There's nothing to attach the ceiling to!") + return + + if(R.use(1)) // Cost of roofing tiles is 1:1 with cost to place lattice and plating + T.ReplaceWithLattice() + T.ChangeTurf(/turf/simulated/floor) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) + user.visible_message("[user] expands the ceiling.", "You expand the ceiling.") + else + to_chat(user, "There aren't any holes in the ceiling to patch here.") + return + // Space shouldn't have weather of the sort planets with atmospheres do. + // If that's changed, then you'll want to swipe the rest of the roofing code from code/game/turfs/simulated/floor_attackby.dm return @@ -64,7 +90,7 @@ /turf/space/Entered(atom/movable/A as mob|obj) if(movement_disabled) - usr << "Movement is admin-disabled." //This is to identify lag problems + to_chat(usr, "Movement is admin-disabled.") //This is to identify lag problems return ..() if ((!(A) || src != A.loc)) return @@ -187,5 +213,5 @@ A.loc.Entered(A) return -/turf/space/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0) - return ..(N, tell_universe, 1) +/turf/space/ChangeTurf(var/turf/N, var/tell_universe, var/force_lighting_update, var/preserve_outdoors) + return ..(N, tell_universe, 1, preserve_outdoors) diff --git a/code/game/turfs/turf_changing.dm b/code/game/turfs/turf_changing.dm index 115a7899879..3b5a797c0a0 100644 --- a/code/game/turfs/turf_changing.dm +++ b/code/game/turfs/turf_changing.dm @@ -22,7 +22,7 @@ below.update_icon() // To add or remove the 'ceiling-less' overlay. //Creates a new turf -/turf/proc/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0) +/turf/proc/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0, var/preserve_outdoors = FALSE) if (!N) return @@ -38,6 +38,7 @@ var/old_affecting_lights = affecting_lights var/old_lighting_overlay = lighting_overlay var/old_corners = corners + var/old_outdoors = outdoors //world << "Replacing [src.type] with [N]" @@ -106,3 +107,6 @@ lighting_build_overlay() else lighting_clear_overlay() + + if(preserve_outdoors) + outdoors = old_outdoors \ No newline at end of file diff --git a/code/game/turfs/unsimulated/planetary.dm b/code/game/turfs/unsimulated/planetary.dm index 613638ec804..35cd7aa4a80 100644 --- a/code/game/turfs/unsimulated/planetary.dm +++ b/code/game/turfs/unsimulated/planetary.dm @@ -1,7 +1,5 @@ // This is a wall you surround the area of your "planet" with, that makes the atmosphere inside stay within bounds, even if canisters // are opened or other strange things occur. -var/list/planetary_walls = list() - /turf/unsimulated/wall/planetary name = "railroading" desc = "Choo choo!" @@ -21,10 +19,10 @@ var/list/planetary_walls = list() /turf/unsimulated/wall/planetary/New() ..() - planetary_walls.Add(src) + SSplanets.addTurf(src) /turf/unsimulated/wall/planetary/Destroy() - planetary_walls.Remove(src) + SSplanets.removeTurf(src) ..() /turf/unsimulated/wall/planetary/proc/set_temperature(var/new_temperature) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index dfbd1429088..56a440b639c 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -133,7 +133,8 @@ var/list/admin_verbs_fun = list( /client/proc/roll_dices, /datum/admins/proc/call_supply_drop, /datum/admins/proc/call_drop_pod, - /client/proc/smite + /client/proc/smite, + /client/proc/admin_lightning_strike ) var/list/admin_verbs_spawn = list( diff --git a/code/modules/admin/verbs/antag-ooc.dm b/code/modules/admin/verbs/antag-ooc.dm index 22689f17188..13c6e6a767a 100644 --- a/code/modules/admin/verbs/antag-ooc.dm +++ b/code/modules/admin/verbs/antag-ooc.dm @@ -12,7 +12,7 @@ else if(is_antag && !is_admin) // Is an antag, and not an admin, meaning we need to check if their antag type allows AOOC. var/datum/antagonist/A = get_antag_data(usr.mind.special_role) - if(!A || !A.can_use_aooc) + if(!A || !A.can_speak_aooc || !A.can_hear_aooc) to_chat(usr, "Sorry, but your antagonist type is not allowed to speak in AOOC.") return @@ -36,7 +36,7 @@ var/datum/antagonist/A = null if(M.mind) // Observers don't have minds, but they should still see AOOC. A = get_antag_data(M.mind.special_role) - if((M.mind && M.mind.special_role && A && A.can_use_aooc) || isobserver(M)) // Antags must have their type be allowed to AOOC to see AOOC. This prevents, say, ERT from seeing AOOC. + if((M.mind && M.mind.special_role && A && A.can_hear_aooc) || isobserver(M)) // Antags must have their type be allowed to AOOC to see AOOC. This prevents, say, ERT from seeing AOOC. to_chat(M, "[create_text_tag("aooc", "Antag-OOC:", M.client)] [player_display]: [msg]") log_aooc(msg,src) \ No newline at end of file diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 50bc79d8fec..c6f2c0321ed 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -637,7 +637,7 @@ if(!check_rights(R_DEBUG)) return - var/datum/planet/planet = input(usr, "Which planet do you want to modify the weather on?", "Change Weather") in planet_controller.planets + var/datum/planet/planet = input(usr, "Which planet do you want to modify the weather on?", "Change Weather") in SSplanets.planets var/datum/weather/new_weather = input(usr, "What weather do you want to change to?", "Change Weather") as null|anything in planet.weather_holder.allowed_weather_types if(new_weather) planet.weather_holder.change_weather(new_weather) @@ -653,7 +653,7 @@ if(!check_rights(R_DEBUG)) return - var/datum/planet/planet = input(usr, "Which planet do you want to modify time on?", "Change Time") in planet_controller.planets + var/datum/planet/planet = input(usr, "Which planet do you want to modify time on?", "Change Time") in SSplanets.planets var/datum/time/current_time_datum = planet.current_time var/new_hour = input(usr, "What hour do you want to change to?", "Change Time", text2num(current_time_datum.show_time("hh"))) as null|num diff --git a/code/modules/admin/verbs/lightning_strike.dm b/code/modules/admin/verbs/lightning_strike.dm new file mode 100644 index 00000000000..ca8d743614c --- /dev/null +++ b/code/modules/admin/verbs/lightning_strike.dm @@ -0,0 +1,115 @@ +/client/proc/admin_lightning_strike() + set name = "Lightning Stirke" + set desc = "Causes lightning to strike on your tile. This will hurt things on or nearby it severely." + set category = "Fun" + + if(!check_rights(R_FUN)) + return + + var/result = alert(src, "Really strike your tile with lightning?", "Confirm Badmin" , "No", "Yes (Cosmetic)", "Yes (Real)") + + if(result == "No") + return + var/fake_lightning = result == "Yes (Cosmetic)" + + lightning_strike(get_turf(usr), fake_lightning) + log_and_message_admins("[key_name(src)] has caused [fake_lightning ? "cosmetic":"harmful"] lightning to strike at their position ([src.mob.x], [src.mob.y], [src.mob.z]). \ + (JMP)") + +#define LIGHTNING_REDIRECT_RANGE 28 // How far in tiles certain things draw lightning from. +#define LIGHTNING_ZAP_RANGE 3 // How far the tesla effect zaps, as well as the bad effects from a direct strike. +#define LIGHTNING_POWER 20000 // How much 'zap' is in a strike, used for tesla_zap(). + +// The real lightning proc. +// This is global until I can figure out a better place for it. +// T is the turf that is being struck. If cosmetic is true, the lightning won't actually hurt anything. +/proc/lightning_strike(turf/T, cosmetic = FALSE) + // First, visuals. + + // Do a lightning flash for the whole planet, if the turf belongs to a planet. + var/datum/planet/P = null + P = SSplanets.z_to_planet[T.z] + if(P) + var/datum/weather_holder/holder = P.weather_holder + flick("lightning_flash", holder.special_visuals) + + // Before we do the other visuals, we need to see if something is going to hijack our intended target. + var/obj/machinery/power/grounding_rod/ground = null // Most of the bad effects of lightning will get negated if a grounding rod is nearby. + var/obj/machinery/power/tesla_coil/coil = null // However a tesla coil has higher priority and the strike will bounce. + + for(var/obj/machinery/power/thing in range(LIGHTNING_REDIRECT_RANGE, T)) + if(istype(thing, /obj/machinery/power/tesla_coil)) + var/turf/simulated/coil_turf = get_turf(thing) + if(istype(coil_turf) && thing.anchored && coil_turf.outdoors) + coil = thing + break + + if(istype(thing, /obj/machinery/power/grounding_rod)) + var/turf/simulated/rod_turf = get_turf(thing) + if(istype(rod_turf) && thing.anchored && rod_turf.outdoors) + ground = thing + + if(coil) // Coil gets highest priority. + T = coil.loc + else if(ground) + T = ground.loc + + // Now make the lightning strike sprite. It will fade and delete itself in a second. + new /obj/effect/temporary_effect/lightning_strike(T) + + // For those close up. + playsound(T, 'sound/effects/lightningbolt.ogg', 100, 1) + + // And for those far away. If the strike happens on a planet, everyone on the planet will hear it. + // Otherwise only those on the current z-level will hear it. + var/sound = get_sfx("thunder") + for(var/mob/M in player_list) + if((P && M.z in P.expected_z_levels) || M.z == T.z) + M.playsound_local(get_turf(M), soundin = sound, vol = 70, vary = FALSE, is_global = TRUE) + + if(cosmetic) // Everything beyond here involves potentially damaging things. If we don't want to do that, stop now. + return + + if(ground) // All is well. + ground.tesla_act(LIGHTNING_POWER, FALSE) + return + + else if(coil) // Otherwise lets bounce off the tesla coil. + coil.tesla_act(LIGHTNING_POWER, TRUE) + + else // Striking the turf directly. + tesla_zap(T, zap_range = LIGHTNING_ZAP_RANGE, power = LIGHTNING_POWER, explosive = FALSE, stun_mobs = TRUE) + + // Some extra effects. + // Some apply to those within zap range, others if they were a bit farther away. + for(var/mob/living/L in view(5, T)) + if(get_dist(L, T) <= LIGHTNING_ZAP_RANGE) // They probably got zapped. + // The actual damage/electrocution is handled by tesla_zap(). + L.Paralyse(5) + L.stuttering += 20 + L.make_jittery(20) + L.emp_act(1) + to_chat(L, span("critical", "You've been struck by lightning!")) + + // If a non-player simplemob was struck, inflict huge damage. + // If the damage is fatal, the SA is turned to ash. + if(istype(L, /mob/living/simple_animal) && !L.key) + var/mob/living/simple_animal/SA = L + SA.adjustFireLoss(200) + SA.updatehealth() + if(SA.health <= 0) // Might be best to check/give simple_mobs siemens when this gets ported to new mobs. + SA.visible_message(span("critical", "\The [SA] disintegrates into ash!")) + SA.ash() + continue // No point deafening something that wont exist. + + // Deafen them. + if(L.get_ear_protection() < 2) + L.AdjustSleeping(-100) + if(iscarbon(L)) + var/mob/living/carbon/C = L + C.ear_deaf += 10 + to_chat(L, span("danger", "Lightning struck nearby, and the thunderclap is deafening!")) + +#undef GROUNDING_ROD_RANGE +#undef LIGHTNING_ZAP_RANGE +#undef LIGHTNING_POWER \ No newline at end of file diff --git a/code/modules/artifice/deadringer.dm b/code/modules/artifice/deadringer.dm new file mode 100644 index 00000000000..e12c0b0045d --- /dev/null +++ b/code/modules/artifice/deadringer.dm @@ -0,0 +1,177 @@ +/obj/item/weapon/deadringer + name = "silver pocket watch" + desc = "A fancy silver-plated digital pocket watch. Looks expensive." + icon = 'icons/obj/deadringer.dmi' + icon_state = "deadringer" + w_class = ITEMSIZE_SMALL + slot_flags = SLOT_ID | SLOT_BELT | SLOT_TIE + origin_tech = list(TECH_ILLEGAL = 3) + var/activated = 0 + var/timer = 0 + var/bruteloss_prev = 999999 + var/fireloss_prev = 999999 + var/mob/living/carbon/human/corpse = null + var/mob/living/carbon/human/watchowner = null + + +/obj/item/weapon/deadringer/New() + ..() + processing_objects |= src + +/obj/item/weapon/deadringer/Destroy() //just in case some smartass tries to stay invisible by destroying the watch + uncloak() + processing_objects -= src + ..() + +/obj/item/weapon/deadringer/dropped() + if(timer > 20) + uncloak() + watchowner = null + return + +/obj/item/weapon/deadringer/attack_self(var/mob/living/user as mob) + var/mob/living/H = src.loc + if (!istype(H, /mob/living/carbon/human)) + to_chat(H,"You have no clue what to do with this thing.") + return + if(!activated) + if(timer == 0) + to_chat(H, "You press a small button on [src]'s side. It starts to hum quietly.") + bruteloss_prev = H.getBruteLoss() + fireloss_prev = H.getFireLoss() + activated = 1 + return + else + to_chat(H,"You press a small button on [src]'s side. It buzzes a little.") + return + if(activated) + to_chat(H,"You press a small button on [src]'s side. It stops humming.") + activated = 0 + return + +/obj/item/weapon/deadringer/process() + if(activated) + if (ismob(src.loc)) + var/mob/living/carbon/human/H = src.loc + watchowner = H + if(H.getBruteLoss() > bruteloss_prev || H.getFireLoss() > fireloss_prev) + deathprevent() + activated = 0 + if(watchowner.isSynthetic()) + to_chat(watchowner, "You fade into nothingness! [src]'s screen blinks, being unable to copy your synthetic body!") + else + to_chat(watchowner, "You fade into nothingness, leaving behind a fake body!") + icon_state = "deadringer_cd" + timer = 50 + return + if(timer > 0) + timer-- + if(timer == 20) + uncloak() + if(corpse) + new /obj/effect/effect/smoke/chem(corpse.loc) + qdel(corpse) + if(timer == 0) + icon_state = "deadringer" + return + +/obj/item/weapon/deadringer/proc/deathprevent() + for(var/mob/living/simple_animal/D in oviewers(7, src)) + D.LoseTarget() + watchowner.emote("deathgasp") + watchowner.alpha = 15 + makeacorpse(watchowner) + for(var/mob/living/simple_animal/D in oviewers(7, src)) + D.LoseTarget() + return + +/obj/item/weapon/deadringer/proc/uncloak() + if(watchowner) + watchowner.alpha = 255 + playsound(get_turf(src), 'sound/effects/uncloak.ogg', 35, 1, -1) + return + +/obj/item/weapon/deadringer/proc/makeacorpse(var/mob/living/carbon/human/H) + if(H.isSynthetic()) + return + corpse = new /mob/living/carbon/human(H.loc) + corpse.setDNA(H.dna.Clone()) + corpse.death(1) //Kills the new mob + var/obj/item/clothing/temp = null + if(H.get_equipped_item(slot_w_uniform)) + corpse.equip_to_slot_or_del(new /obj/item/clothing/under/chameleon/changeling(corpse), slot_w_uniform) + temp = corpse.get_equipped_item(slot_w_uniform) + var/obj/item/clothing/c_type = H.get_equipped_item(slot_w_uniform) + temp.disguise(c_type.type) + temp.canremove = 0 + if(H.get_equipped_item(slot_wear_suit)) + corpse.equip_to_slot_or_del(new /obj/item/clothing/suit/chameleon/changeling(corpse), slot_wear_suit) + temp = corpse.get_equipped_item(slot_wear_suit) + var/obj/item/clothing/c_type = H.get_equipped_item(slot_wear_suit) + temp.disguise(c_type.type) + temp.canremove = 0 + if(H.get_equipped_item(slot_shoes)) + corpse.equip_to_slot_or_del(new /obj/item/clothing/shoes/chameleon/changeling(corpse), slot_shoes) + temp = corpse.get_equipped_item(slot_shoes) + var/obj/item/clothing/c_type = H.get_equipped_item(slot_shoes) + temp.disguise(c_type.type) + temp.canremove = 0 + if(H.get_equipped_item(slot_gloves)) + corpse.equip_to_slot_or_del(new /obj/item/clothing/gloves/chameleon/changeling(corpse), slot_gloves) + temp = corpse.get_equipped_item(slot_gloves) + var/obj/item/clothing/c_type = H.get_equipped_item(slot_gloves) + temp.disguise(c_type.type) + temp.canremove = 0 + if(H.get_equipped_item(slot_l_ear)) + temp = H.get_equipped_item(slot_l_ear) + corpse.equip_to_slot_or_del(new temp.type(corpse), slot_l_ear) + temp = corpse.get_equipped_item(slot_l_ear) + temp.canremove = 0 + if(H.get_equipped_item(slot_glasses)) + corpse.equip_to_slot_or_del(new /obj/item/clothing/glasses/chameleon/changeling(corpse), slot_glasses) + temp = corpse.get_equipped_item(slot_glasses) + var/obj/item/clothing/c_type = H.get_equipped_item(slot_glasses) + temp.disguise(c_type.type) + temp.canremove = 0 + if(H.get_equipped_item(slot_wear_mask)) + corpse.equip_to_slot_or_del(new /obj/item/clothing/mask/chameleon/changeling(corpse), slot_wear_mask) + temp = corpse.get_equipped_item(slot_wear_mask) + var/obj/item/clothing/c_type = H.get_equipped_item(slot_wear_mask) + temp.disguise(c_type.type) + temp.canremove = 0 + if(H.get_equipped_item(slot_head)) + corpse.equip_to_slot_or_del(new /obj/item/clothing/head/chameleon/changeling(corpse), slot_head) + temp = corpse.get_equipped_item(slot_head) + var/obj/item/clothing/c_type = H.get_equipped_item(slot_head) + temp.disguise(c_type.type) + temp.canremove = 0 + if(H.get_equipped_item(slot_belt)) + corpse.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/chameleon/changeling(corpse), slot_belt) + temp = corpse.get_equipped_item(slot_belt) + var/obj/item/clothing/c_type = H.get_equipped_item(slot_belt) + temp.disguise(c_type.type) + temp.canremove = 0 + if(H.get_equipped_item(slot_back)) + corpse.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/chameleon/changeling(corpse), slot_back) + temp = corpse.get_equipped_item(slot_back) + var/obj/item/clothing/c_type = H.get_equipped_item(slot_back) + temp.disguise(c_type.type) + temp.canremove = 0 + corpse.identifying_gender = H.identifying_gender + corpse.flavor_texts = H.flavor_texts.Copy() + corpse.real_name = H.real_name + corpse.name = H.name + corpse.set_species(corpse.dna.species) + corpse.change_hair(H.h_style) + corpse.change_facial_hair(H.f_style) + corpse.change_hair_color(H.r_hair, H.g_hair, H.b_hair) + corpse.change_facial_hair_color(H.r_facial, H.g_facial, H.b_facial) + corpse.change_skin_color(H.r_skin, H.g_skin, H.b_skin) + corpse.adjustFireLoss(H.getFireLoss()) + corpse.adjustBruteLoss(H.getBruteLoss()) + corpse.UpdateAppearance() + corpse.regenerate_icons() + for(var/obj/item/organ/internal/I in corpse.internal_organs) + var/obj/item/organ/internal/G = I + G.Destroy() + return diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm index 63c781452c8..9e9eaeb8687 100644 --- a/code/modules/assembly/infrared.dm +++ b/code/modules/assembly/infrared.dm @@ -250,9 +250,8 @@ return /obj/effect/beam/i_beam/Destroy() + . = ..() if(master.first == src) master.first = null - if(next) - qdel(next) - next = null - ..() + if(next && !next.gc_destroyed) + qdel_null(next) diff --git a/code/modules/client/preference_setup/general/01_basic.dm b/code/modules/client/preference_setup/general/01_basic.dm index f0bccd731e0..f044322cab9 100644 --- a/code/modules/client/preference_setup/general/01_basic.dm +++ b/code/modules/client/preference_setup/general/01_basic.dm @@ -71,8 +71,8 @@ datum/preferences/proc/set_biological_gender(var/gender) . += "Nickname: " . += "[pref.nickname]" . += "
" - . += "Biological Gender: [gender2text(pref.biological_gender)]
" - . += "Gender Identity: [gender2text(pref.identifying_gender)]
" + . += "Biological Sex: [gender2text(pref.biological_gender)]
" + . += "Pronouns: [gender2text(pref.identifying_gender)]
" . += "Age: [pref.age]
" . += "Spawn Point: [pref.spawnpoint]
" if(config.allow_Metadata) @@ -111,13 +111,13 @@ datum/preferences/proc/set_biological_gender(var/gender) return TOPIC_NOACTION else if(href_list["bio_gender"]) - var/new_gender = input(user, "Choose your character's biological gender:", "Character Preference", pref.biological_gender) as null|anything in get_genders() + var/new_gender = input(user, "Choose your character's biological sex:", "Character Preference", pref.biological_gender) as null|anything in get_genders() if(new_gender && CanUseTopic(user)) pref.set_biological_gender(new_gender) return TOPIC_REFRESH_UPDATE_PREVIEW else if(href_list["id_gender"]) - var/new_gender = input(user, "Choose your character's identifying gender:", "Character Preference", pref.identifying_gender) as null|anything in all_genders_define_list + var/new_gender = input(user, "Choose your character's pronouns:", "Character Preference", pref.identifying_gender) as null|anything in all_genders_define_list if(new_gender && CanUseTopic(user)) pref.identifying_gender = new_gender return TOPIC_REFRESH @@ -158,4 +158,4 @@ datum/preferences/proc/set_biological_gender(var/gender) return possible_genders possible_genders = possible_genders.Copy() possible_genders |= NEUTER - return possible_genders \ No newline at end of file + return possible_genders diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index 1fc3b1d8ba6..e098283a2e5 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -36,6 +36,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O S["synth_red"] >> pref.r_synth S["synth_green"] >> pref.g_synth S["synth_blue"] >> pref.b_synth + S["synth_markings"] >> pref.synth_markings pref.preview_icon = null S["bgstate"] >> pref.bgstate @@ -65,6 +66,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O S["synth_red"] << pref.r_synth S["synth_green"] << pref.g_synth S["synth_blue"] << pref.b_synth + S["synth_markings"] << pref.synth_markings S["bgstate"] << pref.bgstate /datum/category_item/player_setup_item/general/body/sanitize_character(var/savefile/S) @@ -120,6 +122,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O character.r_synth = pref.r_synth character.g_synth = pref.g_synth character.b_synth = pref.b_synth + character.synth_markings = pref.synth_markings // Destroy/cyborgize organs and limbs. for(var/name in list(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_GROIN, BP_TORSO)) @@ -300,11 +303,12 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O . += "
Body Markings +
" for(var/M in pref.body_markings) - . += "[M] - Color" + . += "[M] [pref.body_markings.len > 1 ? "˄ ˅ " : ""]- Color" . += "
__
" . += "
" . += "
" + . += "Allow Synth markings: [pref.synth_markings ? "Yes" : "No"]
" . += "Allow Synth color: [pref.synth_color ? "Yes" : "No"]
" if(pref.synth_color) . += "Change Color
__
" @@ -493,6 +497,24 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.body_markings[new_marking] = "#000000" //New markings start black return TOPIC_REFRESH_UPDATE_PREVIEW + else if(href_list["marking_up"]) + var/M = href_list["marking_up"] + var/start = pref.body_markings.Find(M) + if(start != 1) //If we're not the beginning of the list, swap with the previous element. + moveElement(pref.body_markings, start, start-1) + else //But if we ARE, become the final element -ahead- of everything else. + moveElement(pref.body_markings, start, pref.body_markings.len+1) + return TOPIC_REFRESH_UPDATE_PREVIEW + + else if(href_list["marking_down"]) + var/M = href_list["marking_down"] + var/start = pref.body_markings.Find(M) + if(start != pref.body_markings.len) //If we're not the end of the list, swap with the next element. + moveElement(pref.body_markings, start, start+2) + else //But if we ARE, become the first element -behind- everything else. + moveElement(pref.body_markings, start, 1) + return TOPIC_REFRESH_UPDATE_PREVIEW + else if(href_list["marking_remove"]) var/M = href_list["marking_remove"] pref.body_markings -= M @@ -702,6 +724,10 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.b_synth = hex2num(copytext(new_color, 6, 8)) return TOPIC_REFRESH_UPDATE_PREVIEW + else if(href_list["synth_markings"]) + pref.synth_markings = !pref.synth_markings + return TOPIC_REFRESH_UPDATE_PREVIEW + else if(href_list["cycle_bg"]) pref.bgstate = next_in_list(pref.bgstate, pref.bgstate_options) return TOPIC_REFRESH_UPDATE_PREVIEW diff --git a/code/modules/client/preference_setup/loadout/loadout_suit.dm b/code/modules/client/preference_setup/loadout/loadout_suit.dm index 9161f655175..41d37b8a67d 100644 --- a/code/modules/client/preference_setup/loadout/loadout_suit.dm +++ b/code/modules/client/preference_setup/loadout/loadout_suit.dm @@ -241,6 +241,46 @@ datum/gear/suit/duster path = /obj/item/clothing/accessory/poncho/roles/cloak/hop allowed_roles = list("Head of Personnel") +/datum/gear/suit/roles/poncho/cloak/cargo + display_name = "cloak, cargo" + path = /obj/item/clothing/accessory/poncho/roles/cloak/cargo + allowed_roles = list("Cargo Technician","Quartermaster") + +/datum/gear/suit/roles/poncho/cloak/mining + display_name = "cloak, mining" + path = /obj/item/clothing/accessory/poncho/roles/cloak/mining + allowed_roles = list("Quartermaster","Shaft Miner") + +/datum/gear/suit/roles/poncho/cloak/security + display_name = "cloak, security" + path = /obj/item/clothing/accessory/poncho/roles/cloak/security + allowed_roles = list("Head of Security","Detective","Warden","Security Officer") + +/datum/gear/suit/roles/poncho/cloak/service + display_name = "cloak, service" + path = /obj/item/clothing/accessory/poncho/roles/cloak/service + allowed_roles = list("Head of Personnel","Bartender","Botanist","Janitor","Chef","Librarian") + +/datum/gear/suit/roles/poncho/cloak/engineer + display_name = "cloak, engineer" + path = /obj/item/clothing/accessory/poncho/roles/cloak/engineer + allowed_roles = list("Chief Engineer","Station Engineer") + +/datum/gear/suit/roles/poncho/cloak/atmos + display_name = "cloak, atmos" + path = /obj/item/clothing/accessory/poncho/roles/cloak/atmos + allowed_roles = list("Chief Engineer","Atmospheric Technician") + +/datum/gear/suit/roles/poncho/cloak/research + display_name = "cloak, science" + path = /obj/item/clothing/accessory/poncho/roles/cloak/research + allowed_roles = list("Research Director","Scientist", "Roboticist", "Xenobiologist") + +/datum/gear/suit/roles/poncho/cloak/medical + display_name = "cloak, medical" + path = /obj/item/clothing/accessory/poncho/roles/cloak/medical + allowed_roles = list("Medical Doctor","Chief Medical Officer","Chemist","Paramedic","Geneticist", "Psychiatrist") + /datum/gear/suit/unathi_robe display_name = "roughspun robe" path = /obj/item/clothing/suit/unathi/robe diff --git a/code/modules/client/preference_setup/loadout/loadout_utility.dm b/code/modules/client/preference_setup/loadout/loadout_utility.dm index 3da9a7226c9..1f35cc925a8 100644 --- a/code/modules/client/preference_setup/loadout/loadout_utility.dm +++ b/code/modules/client/preference_setup/loadout/loadout_utility.dm @@ -114,12 +114,6 @@ path = /obj/item/weapon/cell/device /datum/gear/utility/implant - exploitable = 1 - -/datum/gear/utility/implant/eal //This does nothing if you don't actually know EAL. - display_name = "implant, language, EAL" - path = /obj/item/weapon/implant/language/eal - cost = 2 slot = "implant" exploitable = 1 @@ -127,8 +121,20 @@ display_name = "implant, tracking" path = /obj/item/weapon/implant/tracking/weak cost = 10 - slot = "implant" - exploitable = 1 + +/datum/gear/utility/implant/language + cost = 2 + exploitable = 0 + +/datum/gear/utility/implant/language/eal + display_name = "vocal synthesizer, EAL" + description = "A surgically implanted vocal synthesizer which allows the owner to speak EAL, if they know it." + path = /obj/item/weapon/implant/language/eal + +/datum/gear/utility/implant/language/skrellian + display_name = "vocal synthesizer, Skrellian" + description = "A surgically implanted vocal synthesizer which allows the owner to speak Common Skrellian, if they know it." + path = /obj/item/weapon/implant/language/skrellian /datum/gear/utility/pen display_name = "Fountain Pen" diff --git a/code/modules/client/preference_setup/traits/trait_defines.dm b/code/modules/client/preference_setup/traits/trait_defines.dm index f8405eb7f83..82e3aee7385 100644 --- a/code/modules/client/preference_setup/traits/trait_defines.dm +++ b/code/modules/client/preference_setup/traits/trait_defines.dm @@ -92,6 +92,30 @@ modifier_type = /datum/modifier/trait/larger mutually_exclusive = list(/datum/trait/modifier/physical/smaller, /datum/trait/modifier/physical/small, /datum/trait/modifier/physical/large) +/datum/trait/modifier/physical/colorblind_protanopia + name = "Protanopia" + desc = "You have a form of red-green colorblindness. You cannot see reds, and have trouble distinguishing them from yellows and greens." + modifier_type = /datum/modifier/trait/colorblind_protanopia + mutually_exclusive = list(/datum/trait/modifier/physical/colorblind_deuteranopia, /datum/trait/modifier/physical/colorblind_tritanopia, /datum/trait/modifier/physical/colorblind_monochrome) + +/datum/trait/modifier/physical/colorblind_deuteranopia + name = "Deuteranopia" + desc = "You have a form of red-green colorblindness. You cannot see greens, and have trouble distinguishing them from yellows and reds." + modifier_type = /datum/modifier/trait/colorblind_deuteranopia + mutually_exclusive = list(/datum/trait/modifier/physical/colorblind_protanopia, /datum/trait/modifier/physical/colorblind_tritanopia, /datum/trait/modifier/physical/colorblind_monochrome) + +/datum/trait/modifier/physical/colorblind_tritanopia + name = "Tritanopia" + desc = "You have a form of blue-yellow colorblindness. You have trouble distinguishing between blues, greens, and yellows, and see blues and violets as dim." + modifier_type = /datum/modifier/trait/colorblind_tritanopia + mutually_exclusive = list(/datum/trait/modifier/physical/colorblind_protanopia, /datum/trait/modifier/physical/colorblind_deuteranopia, /datum/trait/modifier/physical/colorblind_monochrome) + +/datum/trait/modifier/physical/colorblind_monochrome + name = "Monochromacy" + desc = "You are fully colorblind. Your condition is rare, but you can see no colors at all." + modifier_type = /datum/modifier/trait/colorblind_monochrome + mutually_exclusive = list(/datum/trait/modifier/physical/colorblind_protanopia, /datum/trait/modifier/physical/colorblind_deuteranopia, /datum/trait/modifier/physical/colorblind_tritanopia) + // These two traits might be borderline, feel free to remove if they get abused. /datum/trait/modifier/physical/high_metabolism name = "High Metabolism" diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index c45567e5a95..dee21ddd5b9 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -60,6 +60,7 @@ datum/preferences var/r_synth //Used with synth_color to color synth parts that normaly can't be colored. var/g_synth //Same as above var/b_synth //Same as above + var/synth_markings = 0 //Enable/disable markings on synth parts. //Some faction information. var/home_system = "Unset" //System of birth. diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index a1757d561a0..8b466116197 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -253,7 +253,8 @@ var/mob/living/carbon/human/H = user if(slot && slot == slot_gloves) - if(H.gloves) + var/obj/item/clothing/gloves/G = H.gloves + if(istype(G)) ring = H.gloves if(ring.glove_level >= src.glove_level) to_chat(user, "You are unable to wear \the [src] as \the [H.gloves] are in the way.") diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 9e0c0a01962..6f613e38abb 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -128,6 +128,7 @@ /obj/item/clothing/suit/syndicatefake name = "red space suit replica" + icon = 'icons/obj/clothing/spacesuits.dmi' icon_state = "syndicate" desc = "A plastic replica of the syndicate space suit, you'll look just like a real murderous syndicate agent in this! This is a toy, it is not made for use in space!" w_class = ITEMSIZE_NORMAL diff --git a/code/modules/clothing/under/accessories/clothing.dm b/code/modules/clothing/under/accessories/clothing.dm index eaab8b290a4..02fab3e95a3 100644 --- a/code/modules/clothing/under/accessories/clothing.dm +++ b/code/modules/clothing/under/accessories/clothing.dm @@ -121,8 +121,8 @@ * Cloak */ /obj/item/clothing/accessory/poncho/roles/cloak - name = "brown cloak" - desc = "An elaborate brown cloak." + name = "quartermaster's cloak" + desc = "An elaborate brown and gold cloak." icon_state = "qmcloak" item_state = "qmcloak" body_parts_covered = null @@ -169,6 +169,54 @@ icon_state = "capcloak" item_state = "capcloak" +/obj/item/clothing/accessory/poncho/roles/cloak/cargo + name = "brown cloak" + desc = "A simple brown and black cloak." + icon_state = "cargocloak" + item_state = "cargocloak" + +/obj/item/clothing/accessory/poncho/roles/cloak/mining + name = "trimmed purple cloak" + desc = "A trimmed purple and brown cloak." + icon_state = "miningcloak" + item_state = "miningcloak" + +/obj/item/clothing/accessory/poncho/roles/cloak/security + name = "red cloak" + desc = "A simple red and black cloak." + icon_state = "seccloak" + item_state = "seccloak" + +/obj/item/clothing/accessory/poncho/roles/cloak/service + name = "green cloak" + desc = "A simple green and blue cloak." + icon_state = "servicecloak" + item_state = "servicecloak" + +/obj/item/clothing/accessory/poncho/roles/cloak/engineer + name = "gold cloak" + desc = "A simple gold and brown cloak." + icon_state = "engicloak" + item_state = "engicloak" + +/obj/item/clothing/accessory/poncho/roles/cloak/atmos + name = "yellow cloak" + desc = "A trimmed yellow and blue cloak." + icon_state = "atmoscloak" + item_state = "atmoscloak" + +/obj/item/clothing/accessory/poncho/roles/cloak/research + name = "purple cloak" + desc = "A simple purple and white cloak." + icon_state = "scicloak" + item_state = "scicloak" + +/obj/item/clothing/accessory/poncho/roles/cloak/medical + name = "blue cloak" + desc = "A simple blue and white cloak." + icon_state = "medcloak" + item_state = "medcloak" + /obj/item/clothing/accessory/hawaii name = "flower-pattern shirt" desc = "You probably need some welder googles to look at this." diff --git a/code/modules/events/gravity.dm b/code/modules/events/gravity.dm index e0cd38dcfbd..4d0881294f4 100644 --- a/code/modules/events/gravity.dm +++ b/code/modules/events/gravity.dm @@ -6,9 +6,8 @@ endWhen = rand(15, 60) // Setup which levels we will disrupt gravit on. zLevels = using_map.station_levels.Copy() - if (planet_controller) - for(var/datum/planet/P in planet_controller.planets) - zLevels -= P.expected_z_levels + for(var/datum/planet/P in SSplanets.planets) + zLevels -= P.expected_z_levels /datum/event/gravity/announce() command_announcement.Announce("Feedback surge detected in mass-distributions systems. Artificial gravity has been disabled whilst the system \ diff --git a/code/modules/integrated_electronics/core/device.dm b/code/modules/integrated_electronics/core/device.dm index bcdd0e9bead..1b298c7a368 100644 --- a/code/modules/integrated_electronics/core/device.dm +++ b/code/modules/integrated_electronics/core/device.dm @@ -19,6 +19,9 @@ else ..() +/obj/item/device/electronic_assembly/get_cell() + return battery + /obj/item/device/assembly/electronic_assembly/proc/toggle_open(mob/user) playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) opened = !opened diff --git a/code/modules/integrated_electronics/core/printer.dm b/code/modules/integrated_electronics/core/printer.dm index 4dfd4e989a4..794755b02c8 100644 --- a/code/modules/integrated_electronics/core/printer.dm +++ b/code/modules/integrated_electronics/core/printer.dm @@ -162,13 +162,16 @@ return 1 var/cost = 1 + + if(isnull(current_category)) + current_category = recipe_list[1] if(ispath(build_type, /obj/item/device/electronic_assembly)) var/obj/item/device/electronic_assembly/E = build_type cost = round( (initial(E.max_complexity) + initial(E.max_components) ) / 4) - else if(ispath(build_type, /obj/item/integrated_circuit)) - var/obj/item/integrated_circuit/IC = build_type - cost = initial(IC.w_class) else + var/obj/item/I = build_type + cost = initial(I.w_class) + if(!(locate(build_type) in recipe_list[current_category])) return if(metal - cost < 0) @@ -198,4 +201,4 @@ name = "integrated circuit printer upgrade disk - circuit cloner" desc = "Install this into your integrated circuit printer to enhance it. This one allows the printer to duplicate assemblies." icon_state = "upgrade_disk_clone" - origin_tech = list(TECH_ENGINEERING = 5, TECH_DATA = 6) \ No newline at end of file + origin_tech = list(TECH_ENGINEERING = 5, TECH_DATA = 6) diff --git a/code/modules/integrated_electronics/subtypes/memory.dm b/code/modules/integrated_electronics/subtypes/memory.dm index 94c4594f5b2..24dd18c80bf 100644 --- a/code/modules/integrated_electronics/subtypes/memory.dm +++ b/code/modules/integrated_electronics/subtypes/memory.dm @@ -75,7 +75,6 @@ /obj/item/integrated_circuit/memory/constant name = "constant chip" desc = "This tiny chip can store one piece of data, which cannot be overwritten without disassembly." - icon_state = "memory" complexity = 1 inputs = list() outputs = list("output pin" = IC_PINTYPE_ANY) diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm index 6e75d97a0d9..232ef46e3e3 100644 --- a/code/modules/materials/material_recipes.dm +++ b/code/modules/materials/material_recipes.dm @@ -53,6 +53,7 @@ recipes += new/datum/stack_recipe("canister", /obj/machinery/portable_atmospherics/canister, 10, time = 15, one_per_turf = 1, on_floor = 1) recipes += new/datum/stack_recipe("cannon frame", /obj/item/weapon/cannonframe, 10, time = 15, one_per_turf = 0, on_floor = 0) recipes += new/datum/stack_recipe("regular floor tile", /obj/item/stack/tile/floor, 1, 4, 20) + recipes += new/datum/stack_recipe("roofing tile", /obj/item/stack/tile/roofing, 3, 4, 20) recipes += new/datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60) recipes += new/datum/stack_recipe("frame", /obj/item/frame, 5, time = 25, one_per_turf = 1, on_floor = 1) recipes += new/datum/stack_recipe("mirror frame", /obj/item/frame/mirror, 1, time = 5, one_per_turf = 0, on_floor = 1) diff --git a/code/modules/mining/fulton.dm b/code/modules/mining/fulton.dm new file mode 100644 index 00000000000..dd9c068a17e --- /dev/null +++ b/code/modules/mining/fulton.dm @@ -0,0 +1,191 @@ +var/global/list/total_extraction_beacons = list() + +/obj/item/extraction_pack + name = "fulton extraction pack" + desc = "A balloon that can be used to extract equipment or personnel to a Fulton Recovery Beacon. Anything not bolted down can be moved. Link the pack to a beacon by using the pack in hand." + icon = 'icons/obj/fulton.dmi' + icon_state = "extraction_pack" + w_class = ITEMSIZE_NORMAL + var/obj/structure/extraction_point/beacon + var/list/beacon_networks = list("station") + var/uses_left = 3 + var/can_use_indoors + var/safe_for_living_creatures = 1 + +/obj/item/extraction_pack/examine() + . = ..() + usr.show_message("It has [uses_left] use\s remaining.", 1) + +/obj/item/extraction_pack/attack_self(mob/user) + var/list/possible_beacons = list() + for(var/B in global.total_extraction_beacons) + var/obj/structure/extraction_point/EP = B + if(EP.beacon_network in beacon_networks) + possible_beacons += EP + + if(!possible_beacons.len) + to_chat(user, "There are no extraction beacons in existence!") + return + + else + var/A + + A = input("Select a beacon to connect to", "Balloon Extraction Pack", A) as null|anything in possible_beacons + + if(!A) + return + beacon = A + to_chat(user, "You link the extraction pack to the beacon system.") + +/obj/item/extraction_pack/afterattack(atom/movable/A, mob/living/carbon/human/user, flag, params) + if(!beacon) + to_chat(user, "[src] is not linked to a beacon, and cannot be used.") + return + if(!can_use_indoors) + var/turf/T = get_turf(A) + if(T && !T.outdoors) + to_chat(user, "[src] can only be used on things that are outdoors!") + return + if(!flag) + return + if(!istype(A)) + return + else + if(!safe_for_living_creatures && check_for_living_mobs(A)) + to_chat(user, "[src] is not safe for use with living creatures, they wouldn't survive the trip back!") + return + if(!isturf(A.loc)) // no extracting stuff inside other stuff + return + if(A.anchored) + return + to_chat(user, "You start attaching the pack to [A]...") + if(do_after(user,50,target=A)) + to_chat(user, "You attach the pack to [A] and activate it.") + /* No components, sorry. No convienence for you! + if(loc == user && istype(user.back, /obj/item/storage/backpack)) + var/obj/item/storage/backpack/B = user.back + B.SendSignal(COMSIG_TRY_STORAGE_INSERT, src, user, FALSE, FALSE) + */ + uses_left-- + if(uses_left <= 0) + user.drop_from_inventory(src, A) + var/mutable_appearance/balloon + var/mutable_appearance/balloon2 + var/mutable_appearance/balloon3 + if(isliving(A)) + var/mob/living/M = A + M.AdjustStunned(20) // Keep them from moving during the duration of the extraction + if(M.buckled) + M.buckled.unbuckle_mob(M) + else + A.anchored = TRUE + A.density = FALSE + var/obj/effect/extraction_holder/holder_obj = new(A.loc) + holder_obj.appearance = A.appearance + A.forceMove(holder_obj) + balloon2 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_expand") + balloon2.pixel_y = 10 + balloon2.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM + holder_obj.add_overlay(balloon2) + sleep(4) + balloon = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_balloon") + balloon.pixel_y = 10 + balloon.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM + holder_obj.cut_overlay(balloon2) + holder_obj.add_overlay(balloon) + playsound(holder_obj.loc, 'sound/items/fulext_deploy.wav', 50, 1, -3) + animate(holder_obj, pixel_z = 10, time = 20) + sleep(20) + animate(holder_obj, pixel_z = 15, time = 10) + sleep(10) + animate(holder_obj, pixel_z = 10, time = 10) + sleep(10) + animate(holder_obj, pixel_z = 15, time = 10) + sleep(10) + animate(holder_obj, pixel_z = 10, time = 10) + sleep(10) + playsound(holder_obj.loc, 'sound/items/fultext_launch.wav', 50, 1, -3) + animate(holder_obj, pixel_z = 1000, time = 30) + if(ishuman(A)) + var/mob/living/carbon/human/L = A + L.AdjustStunned(20) + L.drowsyness = 0 + sleep(30) + var/list/flooring_near_beacon = list() + for(var/turf/simulated/floor/floor in orange(1, beacon)) + flooring_near_beacon += floor + holder_obj.forceMove(pick(flooring_near_beacon)) + animate(holder_obj, pixel_z = 10, time = 50) + sleep(50) + animate(holder_obj, pixel_z = 15, time = 10) + sleep(10) + animate(holder_obj, pixel_z = 10, time = 10) + sleep(10) + balloon3 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_retract") + balloon3.pixel_y = 10 + balloon3.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM + holder_obj.cut_overlay(balloon) + holder_obj.add_overlay(balloon3) + sleep(4) + holder_obj.cut_overlay(balloon3) + A.anchored = FALSE // An item has to be unanchored to be extracted in the first place. + A.density = initial(A.density) + animate(holder_obj, pixel_z = 0, time = 5) + sleep(5) + A.forceMove(holder_obj.loc) + qdel(holder_obj) + if(uses_left <= 0) + qdel(src) + + +/obj/item/fulton_core + name = "extraction beacon signaller" + desc = "Emits a signal which fulton recovery devices can lock onto. Activate in hand to create a beacon." + icon = 'icons/obj/stock_parts.dmi' + icon_state = "subspace_amplifier" + +/obj/item/fulton_core/attack_self(mob/user) + if(do_after(user,15,target = user) && !QDELETED(src)) + new /obj/structure/extraction_point(get_turf(user)) + qdel(src) + +/obj/structure/extraction_point + name = "fulton recovery beacon" + desc = "A beacon for the fulton recovery system. Activate a pack in your hand to link it to a beacon." + icon = 'icons/obj/fulton.dmi' + icon_state = "extraction_point" + anchored = TRUE + density = FALSE + var/beacon_network = "station" + +/obj/structure/extraction_point/initialize() + . = ..() + name += " ([rand(100,999)]) ([get_area_name(src, TRUE)])" + global.total_extraction_beacons += src + +/obj/structure/extraction_point/Destroy() + global.total_extraction_beacons -= src + ..() + +/obj/effect/extraction_holder + name = "extraction holder" + desc = "you shouldnt see this" + var/atom/movable/stored_obj + +/obj/item/extraction_pack/proc/check_for_living_mobs(atom/A) + if(isliving(A)) + var/mob/living/L = A + if(L.stat != DEAD) + return 1 + for(var/thing in A.GetAllContents()) + if(isliving(A)) + var/mob/living/L = A + if(L.stat != DEAD) + return 1 + return 0 + +/obj/effect/extraction_holder/singularity_pull() + return + +/obj/effect/extraction_holder/singularity_pull() + return diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index 7170b12d32b..a056a62bed7 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -168,6 +168,12 @@ var/list/mining_overlay_cache = list() if(istype(get_step(src, direction), /turf/space) && !istype(get_step(src, direction), /turf/space/cracked_asteroid)) add_overlay(get_cached_border("asteroid_edge",direction,icon,"asteroid_edges", 0)) + //Or any time + else + var/turf/T = get_step(src, direction) + if(istype(T) && T.density) + add_overlay(get_cached_border("rock_side",direction,'icons/turf/walls.dmi',"rock_side")) + if(overlay_detail) add_overlay('icons/turf/flooring/decals.dmi',overlay_detail) diff --git a/code/modules/mob/_modifiers/aura.dm b/code/modules/mob/_modifiers/aura.dm new file mode 100644 index 00000000000..f72ca67d1ad --- /dev/null +++ b/code/modules/mob/_modifiers/aura.dm @@ -0,0 +1,18 @@ +/* +'Aura' modifiers are semi-permanent, in that they do not have a set duration, but will expire if out of range of the 'source' of the aura. +Note: The source is defined as an argument in New(), and if not specified, it is assumed the holder is the source, +making it not expire ever, which is likely not what you want. +*/ + +/datum/modifier/aura + var/aura_max_distance = 5 // If more than this many tiles away from the source, the modifier expires next tick. + +/datum/modifier/aura/check_if_valid() + if(!origin) + expire() + var/atom/A = origin.resolve() + if(istype(A)) // Make sure we're not null. + if(get_dist(holder, A) > aura_max_distance) + expire() + else + expire() // Source got deleted or something. \ No newline at end of file diff --git a/code/modules/mob/_modifiers/traits.dm b/code/modules/mob/_modifiers/traits.dm index e510798001b..d0b0abfd895 100644 --- a/code/modules/mob/_modifiers/traits.dm +++ b/code/modules/mob/_modifiers/traits.dm @@ -84,20 +84,38 @@ icon_scale_percent = 0.9 +/datum/modifier/trait/colorblind_protanopia + name = "Protanopia" + desc = "You have a form of red-green colorblindness. You cannot see reds, and have trouble distinguishing them from yellows and greens." + + client_color = MATRIX_Protanopia + +/datum/modifier/trait/colorblind_deuteranopia + name = "Deuteranopia" + desc = "You have a form of red-green colorblindness. You cannot see greens, and have trouble distinguishing them from yellows and reds." + + client_color = MATRIX_Deuteranopia + +/datum/modifier/trait/colorblind_tritanopia + name = "Tritanopia" + desc = "You have a form of blue-yellow colorblindness. You have trouble distinguishing between blues, greens, and yellows, and see blues and violets as dim." + + client_color = MATRIX_Tritanopia + /datum/modifier/trait/colorblind_taj - name = "Colorblind - B+R" + name = "Colorblind - Blue-red" desc = "You are colorblind. You have a minor issue with blue colors and have difficulty recognizing them from red colors." - + client_color = MATRIX_Taj_Colorblind /datum/modifier/trait/colorblind_vulp - name = "Colorblind - G+R" + name = "Colorblind - Red-green" desc = "You are colorblind. You have a severe issue with green colors and have difficulty recognizing them from red colors." - + client_color = MATRIX_Vulp_Colorblind -/datum/modifier/trait/colorblind_mono - name = "Colorblind - Mono" - desc = "You are colorblind. Your condition is rare, but you can see no colors at all." - +/datum/modifier/trait/colorblind_monochrome + name = "Monochromacy" + desc = "You are fully colorblind. Your condition is rare, but you can see no colors at all." + client_color = MATRIX_Monochromia diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm index 3a19eee319f..74baf0d9cec 100644 --- a/code/modules/mob/holder.dm +++ b/code/modules/mob/holder.dm @@ -95,6 +95,9 @@ var/list/holder_mob_icon_cache = list() /obj/item/weapon/holder/drone origin_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 5) +/obj/item/weapon/holder/pai + origin_tech = list(TECH_DATA = 2) + /obj/item/weapon/holder/mouse w_class = ITEMSIZE_TINY diff --git a/code/modules/mob/language/generic.dm b/code/modules/mob/language/generic.dm index ad55f2b3464..7cb7cd08e54 100644 --- a/code/modules/mob/language/generic.dm +++ b/code/modules/mob/language/generic.dm @@ -133,6 +133,6 @@ key = "s" flags = SIGNLANG|NO_STUTTER|NONVERBAL -/datum/language/sign/can_speak_special(var/mob/speaker) +/datum/language/sign/can_speak_special(var/mob/speaker) // TODO: If ever we make external organs assist languages, convert this over to the new format var/obj/item/organ/external/hand/hands = locate() in speaker //you can't sign without hands return (hands || !iscarbon(speaker)) diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm index c6089a8788e..66e0e5e0f01 100644 --- a/code/modules/mob/language/language.dm +++ b/code/modules/mob/language/language.dm @@ -133,7 +133,15 @@ return speech_verb /datum/language/proc/can_speak_special(var/mob/speaker) - return 1 + . = TRUE + if(ishuman(speaker)) + var/mob/living/carbon/human/H = speaker + if(src.name in H.species.assisted_langs) + . = FALSE + var/obj/item/organ/internal/voicebox/vox = locate() in H.internal_organs // Only voiceboxes for now. Maybe someday it'll include other organs, but I'm not that clever + if(vox) + if(!vox.is_broken() && (src in vox.assists_languages)) + . = TRUE // Language handling. /mob/proc/add_language(var/language) diff --git a/code/modules/mob/language/station.dm b/code/modules/mob/language/station.dm index 6de7a9d3091..47cb3b8de09 100644 --- a/code/modules/mob/language/station.dm +++ b/code/modules/mob/language/station.dm @@ -63,6 +63,14 @@ "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) + var/new_name = ..(gender,1) + if(prob(50)) + new_name += " [pick(list("Hadii","Kaytam","Nazkiin","Zhan-Khazan","Hharar","Njarir'Akhan","Faaira'Nrezi","Rhezar","Mi'dynh","Rrhazkal","Bayan","Al'Manq","Mi'jri","Chur'eech","Sanu'dra","Ii'rka"))]" + else + new_name += " [..(gender,1)]" + return new_name + /datum/language/tajaranakhani name = LANGUAGE_AKHANI desc = "The language of the sea-faring Njarir'Akhan Tajaran. Borrowing some elements from Siik, the language is distinctly more structured." @@ -77,14 +85,27 @@ "kar","yar","kzar","rha","hrar","err","fer","rir","rar","yarr","arr","ii'r","jar","kur","ran","rii","ii", "nai","ou","kah","oa","ama","uuk","bel","chi","ayt","kay","kas","akor","tam","yir","enai") -/datum/language/tajaran/get_random_name(var/gender) +/datum/language/tajsign + name = LANGUAGE_ALAI + desc = "A standardized Tajaran sign language that was developed in Zarraya and gradually adopted by other nations, incorporating \ + hand gestures and movements of the ears and tail." + signlang_verb = list("gestures with their hands", "gestures with their ears and tail", "gestures with their ears, tail and hands") + colour = "tajaran" + key = "l" + flags = WHITELISTED | SIGNLANG | NO_STUTTER | NONVERBAL - var/new_name = ..(gender,1) - if(prob(50)) - new_name += " [pick(list("Hadii","Kaytam","Nazkiin","Zhan-Khazan","Hharar","Njarir'Akhan","Faaira'Nrezi","Rhezar","Mi'dynh","Rrhazkal","Bayan","Al'Manq","Mi'jri","Chur'eech","Sanu'dra","Ii'rka"))]" - else - new_name += " [..(gender,1)]" - return new_name +/datum/language/tajsign/can_speak_special(var/mob/speaker) // TODO: If ever we make external organs assist languages, convert this over to the new format + var/list/allowed_species = list(SPECIES_TAJ, SPECIES_TESHARI) // Need a tail and ears and such to use this. + if(iscarbon(speaker)) + var/obj/item/organ/external/hand/hands = locate() in speaker //you can't sign without hands + if(!hands) + return FALSE + if(ishuman(speaker)) + var/mob/living/carbon/human/H = speaker + if(H.species.get_bodytype(H) in allowed_species) + return TRUE + + return FALSE /datum/language/skrell name = LANGUAGE_SKRELLIAN @@ -112,7 +133,11 @@ flags = WHITELISTED syllables = list("qr","qrr","xuq","qil","quum","xuqm","vol","xrim","zaoo","qu-uu","qix","qoo","zix", "...", "oo", "q", "nq", "x", "xq", "ll", "...", "...", "...") //should sound like there's holes in it - +/datum/language/skrell/get_random_name(var/gender) + var/list/first_names = file2list('config/names/first_name_skrell.txt') + var/list/last_names = file2list('config/names/last_name_skrell.txt') + return "[pick(first_names)] [pick(last_names)]" + /datum/language/human name = LANGUAGE_SOL_COMMON desc = "A bastardized hybrid of many languages, including Chinese, English, French, and more; it is the common language of the Sol system." @@ -152,11 +177,6 @@ syllables = list("beep","beep","beep","beep","beep","boop","boop","boop","bop","bop","dee","dee","doo","doo","hiss","hss","buzz","buzz","bzz","ksssh","keey","wurr","wahh","tzzz","shh","shk") space_chance = 10 -/datum/language/machine/can_speak_special(var/mob/speaker) - var/obj/item/weapon/implant/language/eal/beep = locate() in speaker - return ((beep && beep.implanted) || speaker.isSynthetic() || isvoice(speaker)) - //thank you sweet zuhayr - /datum/language/machine/get_random_name() if(prob(70)) return "[pick(list("PBU","HIU","SINA","ARMA","OSI"))]-[rand(100, 999)]" @@ -272,4 +292,4 @@ "tod", "ser", "su", "no", "nue", "el", "ad", "al", "an", "ar", "as", "ci", "co", "de", "do", "el", "en", "er", "es", "ie", "in", "la", "lo", "me", "na", "no", "nt", "or", "os", "pa", "qu", "ra", "re", "ro", "se", "st", "ta", "te", "to", "ue", "un", -"tod", "ser", "su", "no", "nue", "el") \ No newline at end of file +"tod", "ser", "su", "no", "nue", "el") diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 09b7aadc70d..b81f0098780 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -1,6 +1,6 @@ /mob/living/carbon/human/emote(var/act,var/m_type=1,var/message = null) var/param = null - + var/datum/gender/T = gender_datums[get_visible_gender()] if (findtext(act, "-", 1, null)) @@ -14,9 +14,10 @@ var/muzzled = is_muzzled() //var/m_type = 1 - for (var/obj/item/weapon/implant/I in src) - if (I.implanted) - I.trigger(act, src) + for(var/obj/item/organ/O in src.organs) + for (var/obj/item/weapon/implant/I in O) + if (I.implanted) + I.trigger(act, src) if(src.stat == 2.0 && (act != "deathgasp")) return @@ -79,7 +80,7 @@ //Promethean-only emotes if("squish") - if(!species.bump_flag == SLIME) //That should do, yaya. + if(species.bump_flag != SLIME) //This should definitely do it. src << "You are not a slime thing!" return @@ -738,7 +739,7 @@ set name = "Set Pose" set desc = "Sets a description which will be shown when someone examines you." set category = "IC" - + var/datum/gender/T = gender_datums[get_visible_gender()] pose = sanitize(input(usr, "This is [src]. [T.he]...", "Pose", null) as text) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 658b4b87ea3..a7490b49690 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -2,7 +2,7 @@ var/skip_gear = 0 var/skip_body = 0 - if(alpha <= 50) + if(alpha <= EFFECTIVE_INVIS) src.loc.examine(user) return diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b25973e89a2..277604bdfcf 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -165,25 +165,12 @@ update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message) if(update) UpdateDamageIcon() -/mob/living/carbon/human/proc/implant_loadout(var/datum/gear/G = new/datum/gear/utility/implant) - var/obj/item/weapon/implant/I = new G.path(src) - I.imp_in = src - I.implanted = 1 - var/obj/item/organ/external/affected = src.organs_by_name[BP_HEAD] - affected.implants += I - I.part = affected - I.implanted(src) - /mob/living/carbon/human/proc/implant_loyalty(override = FALSE) // Won't override by default. if(!config.use_loyalty_implants && !override) return // Nuh-uh. var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(src) - L.imp_in = src - L.implanted = 1 - var/obj/item/organ/external/affected = src.organs_by_name[BP_HEAD] - affected.implants += L - L.part = affected - L.implanted(src) + if(L.handle_implant(src, BP_HEAD)) + L.post_implant(src) /mob/living/carbon/human/proc/is_loyalty_implanted() for(var/L in src.contents) @@ -1120,6 +1107,8 @@ remove_language(species.language) if(species.default_language) remove_language(species.default_language) + for(var/datum/language/L in species.assisted_langs) + remove_language(L) // Clear out their species abilities. species.remove_inherent_verbs(src) holder_type = null diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 0b40e088f32..64cd6a0dc18 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -146,45 +146,35 @@ emp_act //this proc returns the armour value for a particular external organ. /mob/living/carbon/human/proc/getarmor_organ(var/obj/item/organ/external/def_zone, var/type) - if(!type || !def_zone) return 0 + if(!type || !def_zone) + return 0 var/protection = 0 - var/list/protective_gear = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) + var/list/protective_gear = def_zone.get_covering_clothing() for(var/obj/item/clothing/gear in protective_gear) - if(gear.body_parts_covered & def_zone.body_part) - protection += gear.armor[type] - if(LAZYLEN(gear.accessories)) - for(var/obj/item/clothing/accessory/bling in gear.accessories) - if(bling.body_parts_covered & def_zone.body_part) - protection += bling.armor[type] + protection += gear.armor[type] return protection /mob/living/carbon/human/proc/getsoak_organ(var/obj/item/organ/external/def_zone, var/type) - if(!type || !def_zone) return 0 + if(!type || !def_zone) + return 0 var/soaked = 0 - var/list/protective_gear = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) + var/list/protective_gear = def_zone.get_covering_clothing() for(var/obj/item/clothing/gear in protective_gear) - if(gear.body_parts_covered & def_zone.body_part) - soaked += gear.armorsoak[type] - if(LAZYLEN(gear.accessories)) - for(var/obj/item/clothing/accessory/bling in gear.accessories) - if(bling.body_parts_covered & def_zone.body_part) - soaked += bling.armorsoak[type] + soaked += gear.armorsoak[type] return soaked +// Checked in borer code /mob/living/carbon/human/proc/check_head_coverage() - - var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform) - for(var/bp in body_parts) - if(!bp) continue - if(bp && istype(bp ,/obj/item/clothing)) - var/obj/item/clothing/C = bp - if(C.body_parts_covered & HEAD) - return 1 + var/obj/item/organ/external/H = organs_by_name[BP_HEAD] + var/list/body_parts = H.get_covering_clothing() + if(LAZYLEN(body_parts)) + return 1 return 0 //Used to check if they can be fed food/drinks/pills /mob/living/carbon/human/proc/check_mouth_coverage() - var/list/protective_gear = list(head, wear_mask, wear_suit, w_uniform) + var/obj/item/organ/external/H = organs_by_name[BP_HEAD] + var/list/protective_gear = H.get_covering_clothing() for(var/obj/item/gear in protective_gear) if(istype(gear) && (gear.body_parts_covered & FACE) && !(gear.item_flags & FLEXIBLEMATERIAL)) return gear diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 244c22e80b2..2cbd93260c1 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -30,6 +30,7 @@ var/r_synth //Used with synth_color to color synth parts that normaly can't be colored. var/g_synth //Same as above var/b_synth //Same as above + var/synth_markings = 0 //Enables/disables markings on synth parts. var/damage_multiplier = 1 //multiplies melee combat damage var/icon_update = 1 //whether icon updating shall take place diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 3ce0c85ef1c..9b2b0234e44 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1032,7 +1032,7 @@ adjustHalLoss(-1) if (drowsyness) - drowsyness-- + drowsyness = max(0, drowsyness - 1) eye_blurry = max(2, eye_blurry) if (prob(5)) sleeping += 1 diff --git a/code/modules/mob/living/carbon/human/species/outsider/event.dm b/code/modules/mob/living/carbon/human/species/outsider/event.dm index 3e75acae9c0..477b14c0c46 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/event.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/event.dm @@ -70,6 +70,7 @@ Variables you may want to make use of are: num_alternate_languages = 3 species_language = LANGUAGE_GALCOM secondary_langs = list() + assisted_langs = list() name_language = null // Use the first-name last-name generator rather than a language scrambler min_age = 0 diff --git a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm index 5d81bb4c9c5..d0f40f693d6 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm @@ -25,6 +25,8 @@ genders = list(NEUTER) + assisted_langs = list() + /datum/species/shadow/handle_death(var/mob/living/carbon/human/H) spawn(1) new /obj/effect/decal/cleanable/ash(H.loc) diff --git a/code/modules/mob/living/carbon/human/species/outsider/vox.dm b/code/modules/mob/living/carbon/human/species/outsider/vox.dm index 9fab4751cc7..525a6118826 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/vox.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/vox.dm @@ -7,6 +7,7 @@ language = LANGUAGE_GALCOM species_language = LANGUAGE_VOX num_alternate_languages = 1 + assisted_langs = list(LANGUAGE_ROOTGLOBAL) unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws/strong, /datum/unarmed_attack/bite/strong) rarity_value = 4 blurb = "The Vox are the broken remnants of a once-proud race, now reduced to little more than \ @@ -71,6 +72,7 @@ has_organ = list( O_HEART = /obj/item/organ/internal/heart/vox, O_LUNGS = /obj/item/organ/internal/lungs/vox, + O_VOICE = /obj/item/organ/internal/voicebox, O_LIVER = /obj/item/organ/internal/liver/vox, O_KIDNEYS = /obj/item/organ/internal/kidneys/vox, O_BRAIN = /obj/item/organ/internal/brain/vox, diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 1f2e55b99cc..38d566d430d 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -52,13 +52,17 @@ // Language/culture vars. var/default_language = LANGUAGE_GALCOM // Default language is used when 'say' is used without modifiers. var/language = LANGUAGE_GALCOM // Default racial language, if any. - var/species_language = LANGUAGE_GALCOM // Used on the Character Setup screen + var/list/species_language = list(LANGUAGE_GALCOM) // Used on the Character Setup screen var/list/secondary_langs = list() // The names of secondary languages that are available to this species. var/list/speech_sounds = list() // A list of sounds to potentially play when speaking. var/list/speech_chance = list() // The likelihood of a speech sound playing. var/num_alternate_languages = 0 // How many secondary languages are available to select at character creation var/name_language = LANGUAGE_GALCOM // The language to use when determining names for this species, or null to use the first name/last name generator + // The languages the species can't speak without an assisted organ. + // This list is a guess at things that no one other than the parent species should be able to speak + var/list/assisted_langs = list(LANGUAGE_EAL, LANGUAGE_TERMINUS, LANGUAGE_SKRELLIAN, LANGUAGE_SKRELLIANFAR, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) + //Soundy emotey things. var/scream_verb = "screams" var/male_scream_sound //= 'sound/goonstation/voice/male_scream.ogg' Removed due to licensing, replace! @@ -183,6 +187,7 @@ var/list/has_organ = list( // which required-organ checks are conducted. O_HEART = /obj/item/organ/internal/heart, O_LUNGS = /obj/item/organ/internal/lungs, + O_VOICE = /obj/item/organ/internal/voicebox, O_LIVER = /obj/item/organ/internal/liver, O_KIDNEYS = /obj/item/organ/internal/kidneys, O_BRAIN = /obj/item/organ/internal/brain, diff --git a/code/modules/mob/living/carbon/human/species/station/golem.dm b/code/modules/mob/living/carbon/human/species/station/golem.dm index 9ec7a2b0056..3b091668138 100644 --- a/code/modules/mob/living/carbon/human/species/station/golem.dm +++ b/code/modules/mob/living/carbon/human/species/station/golem.dm @@ -11,6 +11,8 @@ spawn_flags = SPECIES_IS_RESTRICTED siemens_coefficient = 0 + assisted_langs = list() + breath_type = null poison_type = null diff --git a/code/modules/mob/living/carbon/human/species/station/human_subspecies.dm b/code/modules/mob/living/carbon/human/species/station/human_subspecies.dm index 180732b0aaa..56b5c360354 100644 --- a/code/modules/mob/living/carbon/human/species/station/human_subspecies.dm +++ b/code/modules/mob/living/carbon/human/species/station/human_subspecies.dm @@ -45,6 +45,7 @@ has_organ = list( O_HEART = /obj/item/organ/internal/heart, O_LUNGS = /obj/item/organ/internal/lungs, + O_VOICE = /obj/item/organ/internal/voicebox, O_LIVER = /obj/item/organ/internal/liver, O_KIDNEYS = /obj/item/organ/internal/kidneys, O_BRAIN = /obj/item/organ/internal/brain, diff --git a/code/modules/mob/living/carbon/human/species/station/prometheans.dm b/code/modules/mob/living/carbon/human/species/station/prometheans.dm index 213c7c3ae3d..0c2fbc0ac3b 100644 --- a/code/modules/mob/living/carbon/human/species/station/prometheans.dm +++ b/code/modules/mob/living/carbon/human/species/station/prometheans.dm @@ -30,6 +30,7 @@ var/datum/species/shapeshifter/promethean/prometheans health_hud_intensity = 2 num_alternate_languages = 3 species_language = LANGUAGE_SOL_COMMON + assisted_langs = list(LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) // Prometheans are weird, let's just assume they can use basically any language. breath_type = null poison_type = null diff --git a/code/modules/mob/living/carbon/human/species/station/seromi.dm b/code/modules/mob/living/carbon/human/species/station/seromi.dm index 1d1c0036bea..81deb462a6b 100644 --- a/code/modules/mob/living/carbon/human/species/station/seromi.dm +++ b/code/modules/mob/living/carbon/human/species/station/seromi.dm @@ -104,6 +104,7 @@ has_organ = list( O_HEART = /obj/item/organ/internal/heart, O_LUNGS = /obj/item/organ/internal/lungs, + O_VOICE = /obj/item/organ/internal/voicebox, O_LIVER = /obj/item/organ/internal/liver, O_KIDNEYS = /obj/item/organ/internal/kidneys, O_BRAIN = /obj/item/organ/internal/brain, 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 2f2c1452c04..5d95a632855 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -12,6 +12,7 @@ species_language = LANGUAGE_SOL_COMMON secondary_langs = list(LANGUAGE_SOL_COMMON, LANGUAGE_TERMINUS) name_language = null // Use the first-name last-name generator rather than a language scrambler + assisted_langs = list(LANGUAGE_EAL, LANGUAGE_SKRELLIAN, LANGUAGE_SKRELLIANFAR, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) min_age = 17 max_age = 130 @@ -157,7 +158,7 @@ metabolic_rate = 1.1 gluttonous = 1 num_alternate_languages = 3 - secondary_langs = list(LANGUAGE_SIIK, LANGUAGE_AKHANI) + secondary_langs = list(LANGUAGE_SIIK, LANGUAGE_AKHANI, LANGUAGE_ALAI) name_language = LANGUAGE_SIIK species_language = LANGUAGE_SIIK health_hud_intensity = 2.5 @@ -215,6 +216,7 @@ has_organ = list( //No appendix. O_HEART = /obj/item/organ/internal/heart, O_LUNGS = /obj/item/organ/internal/lungs, + O_VOICE = /obj/item/organ/internal/voicebox, O_LIVER = /obj/item/organ/internal/liver, O_KIDNEYS = /obj/item/organ/internal/kidneys, O_BRAIN = /obj/item/organ/internal/brain, @@ -241,6 +243,7 @@ secondary_langs = list(LANGUAGE_SKRELLIAN, LANGUAGE_SCHECHI) name_language = LANGUAGE_SKRELLIAN species_language = LANGUAGE_SKRELLIAN + assisted_langs = list(LANGUAGE_EAL, LANGUAGE_TERMINUS, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) health_hud_intensity = 2 water_movement = -3 @@ -315,13 +318,14 @@ hud_type = /datum/hud_data/diona siemens_coefficient = 0.3 show_ssd = "completely quiescent" - num_alternate_languages = 2 - secondary_langs = list(LANGUAGE_ROOTGLOBAL) - name_language = LANGUAGE_ROOTLOCAL - species_language = LANGUAGE_ROOTLOCAL health_hud_intensity = 2.5 item_slowdown_mod = 0.25 + num_alternate_languages = 2 + name_language = LANGUAGE_ROOTLOCAL + species_language = LANGUAGE_ROOTLOCAL + secondary_langs = list(LANGUAGE_ROOTGLOBAL) + assisted_langs = list(LANGUAGE_VOX) // Diona are weird, let's just assume they can use basically any language. min_age = 1 max_age = 300 diff --git a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm index 0b9c5490eb9..f3115474dcf 100644 --- a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm +++ b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm @@ -16,6 +16,8 @@ speech_bubble_appearance = "cyber" + assisted_langs = list() + male_cough_sounds = list('sound/effects/mob_effects/m_cougha.ogg','sound/effects/mob_effects/m_coughb.ogg', 'sound/effects/mob_effects/m_coughc.ogg') female_cough_sounds = list('sound/effects/mob_effects/f_cougha.ogg','sound/effects/mob_effects/f_coughb.ogg') male_sneeze_sound = 'sound/effects/mob_effects/sneeze.ogg' diff --git a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm index d851c40255f..1d2ce593071 100644 --- a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm +++ b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm @@ -5,6 +5,7 @@ default_language = "Xenomorph" language = "Hivemind" + assisted_langs = list() unarmed_types = list(/datum/unarmed_attack/claws/strong/xeno, /datum/unarmed_attack/bite/strong/xeno) hud_type = /datum/hud_data/alien rarity_value = 3 diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index dddfd8e168c..612765a776a 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1217,4 +1217,8 @@ default behaviour is: /mob/living/proc/has_vision() - return !(eye_blind || (disabilities & BLIND) || stat || blinded) \ No newline at end of file + return !(eye_blind || (disabilities & BLIND) || stat || blinded) + + +/mob/living/proc/dirties_floor() // If we ever decide to add fancy conditionals for making dirty floors (floating, etc), here's the proc. + return makes_dirt \ No newline at end of file diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 3d9140dd468..08bebc91b2f 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -380,8 +380,13 @@ var/turf/location = get_turf(src) location.hotspot_expose(fire_burn_temperature(), 50, 1) -/mob/living/fire_act() - adjust_fire_stacks(2) +//altered this to cap at the temperature of the fire causing it, using the same 1:1500 value as /mob/living/carbon/human/handle_fire() in human/life.dm +/mob/living/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature) + if(fire_stacks < exposed_temperature/1500) // Subject to balance + adjust_fire_stacks(2) + else + adjust_fire_stacks(2) IgniteMob() //Share fire evenly between the two mobs diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 9739e596b8e..1ee86da6ef8 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -16,7 +16,6 @@ var/brainloss = 0 //'Retardation' damage caused by someone hitting you in the head with a bible or being infected with brainrot. var/halloss = 0 //Hallucination damage. 'Fake' damage obtained through hallucinating or the holodeck. Sleeping should cause it to wear off. - var/hallucination = 0 //Directly affects how long a mob will hallucinate for var/list/atom/hallucinations = list() //A list of hallucinated people that try to attack the mob. See /obj/effect/fake_attacker in hallucinations.dm @@ -59,3 +58,5 @@ var/list/hud_list //Holder for health hud, status hud, wanted hud, etc (not like inventory slots) var/has_huds = FALSE //Whether or not we should bother initializing the above list + + var/makes_dirt = TRUE //FALSE if the mob shouldn't be making dirt on the ground when it walks \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index e71416709fa..c35fdcbf2ac 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -64,6 +64,7 @@ var/list/ai_verbs_default = list( var/datum/announcement/priority/announcement var/obj/machinery/ai_powersupply/psupply = null // Backwards reference to AI's powersupply object. var/hologram_follow = 1 //This is used for the AI eye, to determine if a holopad's hologram should follow it or not. + var/is_dummy = 0 //Used to prevent dummy AIs from spawning with communicators. //NEWMALF VARIABLES var/malfunctioning = 0 // Master var that determines if AI is malfunctioning. var/datum/malf_hardware/hardware = null // Installed piece of hardware. @@ -111,15 +112,16 @@ var/list/ai_verbs_default = list( possibleNames -= pickedName pickedName = null - aiPDA = new/obj/item/device/pda/ai(src) + if(!is_dummy) + aiPDA = new/obj/item/device/pda/ai(src) SetName(pickedName) anchored = 1 canmove = 0 density = 1 loc = loc - aiCommunicator = new /obj/item/device/communicator/integrated(src) - + if(!is_dummy) + aiCommunicator = new /obj/item/device/communicator/integrated(src) holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1")) @@ -685,6 +687,9 @@ var/list/ai_verbs_default = list( card.grab_ai(src, user) else if(W.is_wrench()) + if(user == controlling_drone) + to_chat(user, "The drone's subsystems resist your efforts to tamper with your bolts.") + return if(anchored) playsound(src, W.usesound, 50, 1) user.visible_message("\The [user] starts to unbolt \the [src] from the plating...") @@ -789,6 +794,9 @@ var/list/ai_verbs_default = list( return TRUE //Special subtype kept around for global announcements +/mob/living/silicon/ai/announcer/ + is_dummy = 1 + /mob/living/silicon/ai/announcer/initialize() . = ..() mob_list -= src diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm index 534117cee07..3bcbd7057b0 100644 --- a/code/modules/mob/living/silicon/ai/death.dm +++ b/code/modules/mob/living/silicon/ai/death.dm @@ -3,6 +3,10 @@ if(stat == DEAD) return + if(controlling_drone) + controlling_drone.release_ai_control("WARNING: Primary control loop failure. Session terminated.") + . = ..(gibbed) + if(src.eyeobj) src.eyeobj.setLoc(get_turf(src)) diff --git a/code/modules/mob/living/silicon/ai/icons.dm b/code/modules/mob/living/silicon/ai/icons.dm index 2d8bc0d0026..c9891f9ae8a 100644 --- a/code/modules/mob/living/silicon/ai/icons.dm +++ b/code/modules/mob/living/silicon/ai/icons.dm @@ -84,6 +84,7 @@ var/list/datum/ai_icon/ai_icons /datum/ai_icon/glitchman name = "Glitchman" alive_icon = "ai-glitchman" + dead_icon = "ai-glitchman-crash" /datum/ai_icon/goon name = "Goon" @@ -110,6 +111,7 @@ var/list/datum/ai_icon/ai_icons name = "Inverted" alive_icon = "ai-u" alive_light = "#81DDFF" + dead_icon = "ai-u-crash" /datum/ai_icon/lonestar name = "Lonestar" @@ -163,14 +165,87 @@ var/list/datum/ai_icon/ai_icons /datum/ai_icon/trapped name = "Trapped" alive_icon = "ai-hades" - dead_icon = "ai-hades_dead" + dead_icon = "ai-hades-crash" -/datum/ai_icon/triumvirate_static +/datum/ai_icon/triumvirate name = "Triumvirate" alive_icon = "ai-triumvirate" alive_light = "#020B2B" /datum/ai_icon/triumvirate_static name = "Triumvirate Static" - alive_icon = "ai-static" + alive_icon = "ai-triumvirate-malf" alive_light = "#020B2B" + +//Eros Research Platform Ports + +/datum/ai_icon/clown2 + name = "Honk" + alive_icon = "ai-clown2" + dead_icon = "ai-clown2-crash" + +/datum/ai_icon/boxfort + name = "Boxfort" + alive_icon = "ai-boxfort" + dead_icon = "ai-boxfort_dead" + +/datum/ai_icon/ravensdale + name = "Integration" + alive_icon = "ai-ravensdale" + dead_icon = "ai-ravensdale-crash" + +/datum/ai_icon/gentoo + name = "Gentoo" + alive_icon = "ai-gentoo" + dead_icon = "ai-gentoo_dead" + +/datum/ai_icon/serithi + name = "Mechanicus" + alive_icon = "ai-serithi" + dead_icon = "ai-serithi-crash" + +/datum/ai_icon/alien + name = "Xenomorph" + alive_icon = "ai-alien" + dead_icon = "ai-alien-crash" + +/datum/ai_icon/syndicat + name = "Syndi-cat" + alive_icon = "ai-syndicatmeow" + +/datum/ai_icon/wasp + name = "Wasp" + alive_icon = "ai-wasp" + +/datum/ai_icon/house + name = "Doctor" + alive_icon = "ai-house" + +/datum/ai_icon/fabulous + name = "Fabulous" + alive_icon = "ai-fabulous" + +/datum/ai_icon/yesman + name = "Yes Man" + alive_icon = "ai-yes-man" + dead_icon = "ai-alien-crash" + +/datum/ai_icon/royal + name = "Royal" + alive_icon = "ai-royal" + +/datum/ai_icon/pirate + name = "Pirate" + alive_icon = "ai-pirate" + +/datum/ai_icon/gygas + name = "Love" + alive_icon = "ai-gygas" + +/datum/ai_icon/xerxes + name = "Xerxes" + alive_icon = "ai-xerxes" + +/datum/ai_icon/godfrey + name = "Godfrey" + alive_icon = "ai-godfrey" \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 413cf492509..c8e7dfdadab 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -8,6 +8,8 @@ if (src.stat!=CONSCIOUS) src.cameraFollow = null src.reset_view(null) + if(controlling_drone) + controlling_drone.release_ai_control("WARNING: Primary control loop failure. Session terminated.") src.updatehealth() diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 5ed6fde8aeb..168b031f5ce 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -1,12 +1,14 @@ /mob/living/silicon/pai name = "pAI" icon = 'icons/mob/pai.dmi' - icon_state = "repairbot" + icon_state = "pai-repairbot" emote_type = 2 // pAIs emotes are heard, not seen, so they can be seen through a container (eg. person) pass_flags = 1 mob_size = MOB_SMALL + holder_type = /obj/item/weapon/holder/pai + can_pull_size = ITEMSIZE_SMALL can_pull_mobs = MOB_PULL_SMALLER @@ -23,16 +25,16 @@ var/obj/item/device/radio/radio // Our primary radio var/obj/item/device/communicator/integrated/communicator // Our integrated communicator. - var/chassis = "repairbot" // A record of your chosen chassis. + var/chassis = "pai-repairbot" // A record of your chosen chassis. var/global/list/possible_chassis = list( - "Drone" = "repairbot", - "Cat" = "cat", - "Mouse" = "mouse", - "Monkey" = "monkey", - "Corgi" = "borgi", - "Fox" = "fox", - "Parrot" = "parrot", - "Rabbit" = "rabbit" + "Drone" = "pai-repairbot", + "Cat" = "pai-cat", + "Mouse" = "pai-mouse", + "Monkey" = "pai-monkey", + "Corgi" = "pai-borgi", + "Fox" = "pai-fox", + "Parrot" = "pai-parrot", + "Rabbit" = "pai-rabbit" ) var/global/list/possible_say_verbs = list( @@ -416,7 +418,8 @@ var/obj/item/weapon/holder/H = ..(grabber, self_drop) if(!istype(H)) return - H.icon_state = "pai-[icon_state]" + + H.icon_state = "[chassis]" grabber.update_inv_l_hand() grabber.update_inv_r_hand() return H diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 472125cef9a..ab2b0b53cd7 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -126,6 +126,6 @@ var/global/list/default_pai_software = list() else if(href_list["image"]) var/img = text2num(href_list["image"]) - if(1 <= img && img <= 9) + if(1 <= img && img <= (pai_emotions.len)) card.setEmotion(img) return 1 diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index 05438d9cf3c..dfecf96e6c5 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -19,7 +19,7 @@ var/list/mob_hat_cache = list() return mob_hat_cache[key] /mob/living/silicon/robot/drone - name = "drone" + name = "maintenance drone" real_name = "drone" icon = 'icons/mob/robots.dmi' icon_state = "repairbot" @@ -57,6 +57,8 @@ var/list/mob_hat_cache = list() var/obj/item/hat var/hat_x_offset = 0 var/hat_y_offset = -13 + var/serial_number = 0 + var/name_override = 0 holder_type = /obj/item/weapon/holder/drone @@ -71,6 +73,7 @@ var/list/mob_hat_cache = list() return FALSE /mob/living/silicon/robot/drone/construction + name = "construction drone" icon_state = "constructiondrone" law_type = /datum/ai_laws/construction_drone module_type = /obj/item/weapon/robot_module/drone/construction @@ -96,6 +99,7 @@ var/list/mob_hat_cache = list() remove_language("Robot Talk") add_language("Robot Talk", 0) add_language("Drone Talk", 1) + serial_number = rand(0,999) //They are unable to be upgraded, so let's give them a bit of a better battery. cell.maxcharge = 10000 @@ -111,6 +115,7 @@ var/list/mob_hat_cache = list() verbs -= /mob/living/silicon/robot/verb/Namepick updateicon() + updatename() /mob/living/silicon/robot/drone/init() aiCamera = new/obj/item/device/camera/siliconcam/drone_camera(src) @@ -128,14 +133,22 @@ var/list/mob_hat_cache = list() name = real_name /mob/living/silicon/robot/drone/updatename() - real_name = "maintenance drone ([rand(100,999)])" + if(name_override) + return + if(controlling_ai) + real_name = "remote drone ([controlling_ai])" + else + real_name = "[initial(name)] ([serial_number])" name = real_name /mob/living/silicon/robot/drone/updateicon() overlays.Cut() if(stat == 0) - overlays += "eyes-[icon_state]" + if(controlling_ai) + overlays += "eyes-[icon_state]-ai" + else + overlays += "eyes-[icon_state]" else overlays -= "eyes" if(hat) // Let the drones wear hats. @@ -214,15 +227,18 @@ var/list/mob_hat_cache = list() return if(emagged) - to_chat(user, "\The [user] attempts to load subversive software into you, but your hacked subroutines ignore the attempt.") + to_chat(src, "\The [user] attempts to load subversive software into you, but your hacked subroutines ignore the attempt.") to_chat(user, "You attempt to subvert [src], but the sequencer has no effect.") return to_chat(user, "You swipe the sequencer across [src]'s interface and watch its eyes flicker.") - to_chat(user, "You feel a sudden burst of malware loaded into your execute-as-root buffer. Your tiny brain methodically parses, loads and executes the script.") - message_admins("[key_name_admin(user)] emagged drone [key_name_admin(src)]. Laws overridden.") - log_game("[key_name(user)] emagged drone [key_name(src)]. Laws overridden.") + if(controlling_ai) + to_chat(src, "\The [user] loads some kind of subversive software into the remote drone, corrupting its lawset but luckily sparing yours.") + else + to_chat(src, "You feel a sudden burst of malware loaded into your execute-as-root buffer. Your tiny brain methodically parses, loads and executes the script.") + + log_game("[key_name(user)] emagged drone [key_name(src)][controlling_ai ? " but AI [key_name(controlling_ai)] is in remote control" : " Laws overridden"].") var/time = time2text(world.realtime,"hh:mm:ss") lawchanges.Add("[time] : [user.name]([user.key]) emagged [name]([key])") @@ -235,9 +251,10 @@ var/list/mob_hat_cache = list() var/datum/gender/TU = gender_datums[user.get_visible_gender()] set_zeroth_law("Only [user.real_name] and people [TU.he] designate[TU.s] as being such are operatives.") - src << "Obey these laws:" - laws.show_laws(src) - src << "ALERT: [user.real_name] [TU.is] your new master. Obey your new laws and [TU.his] commands." + if(!controlling_ai) + to_chat(src, "Obey these laws:") + laws.show_laws(src) + to_chat(src, "ALERT: [user.real_name] is your new master. Obey your new laws and \his commands.") return 1 //DRONE LIFE/DEATH @@ -263,26 +280,41 @@ var/list/mob_hat_cache = list() return ..() +/mob/living/silicon/robot/drone/death(gibbed) + if(controlling_ai) + release_ai_control("WARNING: remote system failure. Connection timed out.") + . = ..(gibbed) + //DRONE MOVEMENT. /mob/living/silicon/robot/drone/Process_Spaceslipping(var/prob_slip) return 0 //CONSOLE PROCS /mob/living/silicon/robot/drone/proc/law_resync() + + if(controlling_ai) + to_chat(src, "Someone issues a remote law reset order for this unit, but you disregard it.") + return + if(stat != 2) if(emagged) - src << "You feel something attempting to modify your programming, but your hacked subroutines are unaffected." + to_chat(src, "You feel something attempting to modify your programming, but your hacked subroutines are unaffected.") else - src << "A reset-to-factory directive packet filters through your data connection, and you obediently modify your programming to suit it." + to_chat(src, "A reset-to-factory directive packet filters through your data connection, and you obediently modify your programming to suit it.") full_law_reset() show_laws() /mob/living/silicon/robot/drone/proc/shut_down() + + if(controlling_ai && mind.special_role) + to_chat(src, "Someone issued a remote kill order for this unit, but you disregard it.") + return + if(stat != 2) if(emagged) - src << "You feel a system kill order percolate through your tiny brain, but it doesn't seem like a good idea to you." + to_chat(src, "You feel a system kill order percolate through [controlling_ai ? "the drones" : "your"] tiny brain, but it doesn't seem like a good idea to [controlling_ai ? "it" : "you"].") else - src << "You feel a system kill order percolate through your tiny brain, and you obediently destroy yourself." + to_chat(src, "You feel a system kill order percolate through [controlling_ai ? "the drones" : "your"] tiny brain, and [controlling_ai ? "it" : "you"] obediently destroy[controlling_ai ? "s itself" : " yourself"].") death() /mob/living/silicon/robot/drone/proc/full_law_reset() @@ -291,6 +323,21 @@ var/list/mob_hat_cache = list() clear_ion_laws(1) laws = new law_type +/mob/living/silicon/robot/drone/show_laws(var/everyone = 0) + if(!controlling_ai) + return..() + to_chat(src, "Obey these laws:") + controlling_ai.laws_sanity_check() + controlling_ai.laws.show_laws(src) + +/mob/living/silicon/robot/drone/robot_checklaws() + set category = "Silicon Commands" + set name = "State Laws" + + if(!controlling_ai) + return ..() + controlling_ai.subsystem_law_manager() + //Reboot procs. /mob/living/silicon/robot/drone/proc/request_player() @@ -348,14 +395,6 @@ var/list/mob_hat_cache = list() ..() flavor_text = "It's a bulky construction drone stamped with a Sol Central glyph." -/mob/living/silicon/robot/drone/construction/updatename() - real_name = "construction drone ([rand(100,999)])" - name = real_name - /mob/living/silicon/robot/drone/mining/init() ..() flavor_text = "It's a bulky mining drone stamped with a Grayson logo." - -/mob/living/silicon/robot/drone/mining/updatename() - real_name = "mining drone ([rand(100,999)])" - name = real_name 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 e9589622a53..fdb9c09eb51 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm @@ -75,20 +75,22 @@ if(!produce_drones || !config.allow_drone_spawn || count_drones() >= config.max_maint_drones) return - if(!player || !istype(player.mob,/mob/observer/dead)) + if(player && !istype(player.mob,/mob/observer/dead)) return - announce_ghost_joinleave(player, 0, "They have taken control over a maintenance drone.") visible_message("\The [src] churns and grinds as it lurches into motion, disgorging a shiny new drone after a few moments.") flick("h_lathe_leave",src) + drone_progress = 0 time_last_drone = world.time - if(player.mob && player.mob.mind) player.mob.mind.reset() - var/mob/living/silicon/robot/drone/new_drone = new drone_type(get_turf(src)) - new_drone.transfer_personality(player) - new_drone.master_fabricator = src - drone_progress = 0 + var/mob/living/silicon/robot/drone/new_drone = new drone_type(get_turf(src)) + if(player) + announce_ghost_joinleave(player, 0, "They have taken control over a maintenance drone.") + if(player.mob && player.mob.mind) player.mob.mind.reset() + new_drone.transfer_personality(player) + + return new_drone /mob/observer/dead/verb/join_as_drone() diff --git a/code/modules/mob/living/silicon/robot/drone/drone_remote_control.dm b/code/modules/mob/living/silicon/robot/drone/drone_remote_control.dm new file mode 100644 index 00000000000..4980c24ca3e --- /dev/null +++ b/code/modules/mob/living/silicon/robot/drone/drone_remote_control.dm @@ -0,0 +1,103 @@ +/mob/living/silicon/ai + var/mob/living/silicon/robot/drone/controlling_drone + +/mob/living/silicon/robot/drone + var/mob/living/silicon/ai/controlling_ai + +/mob/living/silicon/robot/drone/attack_ai(var/mob/living/silicon/ai/user) + + if(!istype(user) || controlling_ai || !config.allow_drone_spawn || !config.allow_ai_drones) + return + + if(client || key) + to_chat(user, "You cannot take control of an autonomous, active drone.") + return + + if(health < -35 || emagged) + to_chat(user, "WARNING: connection timed out.") + return + + user.controlling_drone = src + user.teleop = src + radio.channels = user.aiRadio.keyslot2.channels + controlling_ai = user + verbs += /mob/living/silicon/robot/drone/proc/release_ai_control_verb + local_transmit = FALSE + languages = controlling_ai.languages.Copy() + speech_synthesizer_langs = controlling_ai.speech_synthesizer_langs.Copy() + stat = CONSCIOUS + if(user.mind) + user.mind.transfer_to(src) + else + key = user.key + updatename() + to_chat(src, "You have shunted your primary control loop into \a [initial(name)]. Use the Release Control verb to return to your core.") + +/obj/machinery/drone_fabricator/attack_ai(var/mob/living/silicon/ai/user as mob) + + if(!istype(user) || user.controlling_drone || !config.allow_drone_spawn || !config.allow_ai_drones) + return + + if(stat & NOPOWER) + to_chat(user, "\The [src] is unpowered.") + return + + if(!produce_drones) + to_chat(user, "\The [src] is disabled.") + return + + if(drone_progress < 100) + to_chat(user, "\The [src] is not ready to produce a new drone.") + return + + if(count_drones() >= config.max_maint_drones) + to_chat(user, "The drone control subsystems are tasked to capacity; they cannot support any more drones.") + return + + var/mob/living/silicon/robot/drone/new_drone = create_drone() + user.controlling_drone = new_drone + user.teleop = new_drone + new_drone.radio.channels = user.aiRadio.keyslot2.channels + new_drone.controlling_ai = user + new_drone.verbs += /mob/living/silicon/robot/drone/proc/release_ai_control_verb + new_drone.local_transmit = FALSE + new_drone.languages = new_drone.controlling_ai.languages.Copy() + new_drone.speech_synthesizer_langs = new_drone.controlling_ai.speech_synthesizer_langs.Copy() + + if(user.mind) + user.mind.transfer_to(new_drone) + else + new_drone.key = user.key + new_drone.updatename() + + to_chat(new_drone, "You have shunted your primary control loop into \a [initial(new_drone.name)]. Use the Release Control verb to return to your core.") + +/mob/living/silicon/robot/drone/proc/release_ai_control_verb() + set name = "Release Control" + set desc = "Release control of a remote drone." + set category = "Silicon Commands" + + release_ai_control("Remote session terminated.") + +/mob/living/silicon/robot/drone/proc/release_ai_control(var/message = "Connection terminated.") + + if(controlling_ai) + if(mind) + mind.transfer_to(controlling_ai) + else + controlling_ai.key = key + to_chat(controlling_ai, "[message]") + controlling_ai.controlling_drone = null + controlling_ai.teleop = null + controlling_ai = null + + radio.channels = module.channels + verbs -= /mob/living/silicon/robot/drone/proc/release_ai_control_verb + module.remove_languages(src) //Removes excess, adds 'default'. + remove_language("Robot Talk") + add_language("Robot Talk", 0) + add_language("Drone Talk", 1) + local_transmit = TRUE + full_law_reset() + updatename() + death() diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station.dm b/code/modules/mob/living/silicon/robot/robot_modules/station.dm index f6b69504914..6cd2fa5f816 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/station.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/station.dm @@ -213,6 +213,7 @@ var/global/list/robot_modules = list( ..() src.modules += new /obj/item/device/healthanalyzer(src) src.modules += new /obj/item/weapon/reagent_containers/borghypo/surgeon(src) + src.modules += new /obj/item/weapon/autopsy_scanner(src) src.modules += new /obj/item/weapon/surgical/scalpel/cyborg(src) src.modules += new /obj/item/weapon/surgical/hemostat/cyborg(src) src.modules += new /obj/item/weapon/surgical/retractor/cyborg(src) diff --git a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm index 01f52209a7a..3c8e981c3b7 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm @@ -148,6 +148,7 @@ src.modules += new /obj/item/weapon/reagent_containers/borghypo/merc(src) // Surgery things. + src.modules += new /obj/item/weapon/autopsy_scanner(src) src.modules += new /obj/item/weapon/surgical/scalpel/cyborg(src) src.modules += new /obj/item/weapon/surgical/hemostat/cyborg(src) src.modules += new /obj/item/weapon/surgical/retractor/cyborg(src) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index e3c4a0b6613..15fc174b383 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -888,6 +888,8 @@ continue else if(L in friends) continue + else if(L.alpha <= EFFECTIVE_INVIS) + continue else if(!SA_attackable(L)) continue else if(!special_target_check(L)) @@ -1215,7 +1217,7 @@ ai_log("AttackTarget() Bailing because we're disabled",2) LoseTarget() return 0 - if(!target_mob || !SA_attackable(target_mob)) + if(!target_mob || !SA_attackable(target_mob) || (target_mob.alpha <= EFFECTIVE_INVIS)) //if the target went invisible, you can't follow it LoseTarget() return 0 if(!(target_mob in ListTargets(view_range))) diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index 5141eed9792..892c185a943 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -1257,6 +1257,24 @@ name = "Tattoo (Campbell, L.Arm)" body_parts = list(BP_L_ARM) + rightleg + name = "Tattoo (Campbell, R.Leg)" + body_parts = list(BP_R_LEG) + + leftleg + name = "Tattoo (Campbell, L.Leg)" + body_parts = list (BP_L_LEG) + + tat_silverburgh + name = "Tattoo (Silverburgh, R.Leg)" + icon_state = "tat_silverburgh" + body_parts = list (BP_R_LEG) + + left + name = "Tattoo (Silverburgh, L.Leg)" + icon_state = "tat_silverburgh" + body_parts = list (BP_L_LEG) + tat_tiger name = "Tattoo (Tiger Stripes, Body)" icon_state = "tat_tiger" diff --git a/code/modules/multiz/structures.dm b/code/modules/multiz/structures.dm index 8b97ffdb353..f819e2ca7b1 100644 --- a/code/modules/multiz/structures.dm +++ b/code/modules/multiz/structures.dm @@ -141,20 +141,23 @@ if(!istype(above)) above.ChangeTurf(/turf/simulated/open) -/obj/structure/stairs/Uncross(atom/movable/A) - if(A.dir == dir) - // This is hackish but whatever. - var/turf/target = get_step(GetAbove(A), dir) - var/turf/source = A.loc - if(target.Enter(A, source)) - A.loc = target - target.Entered(A, source) - if(isliving(A)) - var/mob/living/L = A - if(L.pulling) - L.pulling.forceMove(target) - return 0 - return 1 +/obj/structure/stairs/CheckExit(atom/movable/mover as mob|obj, turf/target as turf) + if(get_dir(loc, target) == dir && upperStep(mover.loc)) + return FALSE + . = ..() + +/obj/structure/stairs/Bumped(atom/movable/A) + // This is hackish but whatever. + var/turf/target = get_step(GetAbove(A), dir) + if(target.Enter(A, src)) // Pass src to be ignored to avoid infinate loop + A.forceMove(target) + if(isliving(A)) + var/mob/living/L = A + if(L.pulling) + L.pulling.forceMove(target) + +/obj/structure/stairs/proc/upperStep(var/turf/T) + return (T == loc) /obj/structure/stairs/CanPass(obj/mover, turf/source, height, airflow) return airflow || !density diff --git a/code/modules/organs/internal/voicebox.dm b/code/modules/organs/internal/voicebox.dm new file mode 100644 index 00000000000..4de69fe8f2b --- /dev/null +++ b/code/modules/organs/internal/voicebox.dm @@ -0,0 +1,42 @@ +/* + * Voicebox/Vocal Synthesizers + * TL;DR: Assists with speaking languages that a species doesn't normally have, + * such as EAL. Not standard or organic, because at the moment it's undesireable to completely mute characters. + */ + +/obj/item/organ/internal/voicebox + name = "larynx" + icon_state = "larynx" + parent_organ = BP_TORSO // We don't have a neck area + organ_tag = O_VOICE + will_assist_languages = list(LANGUAGE_GALCOM) + +/obj/item/organ/internal/voicebox/New() + ..() + amend_assist_langs() + +/obj/item/organ/internal/voicebox/proc/amend_assist_langs() // Adds the list of language datums assisted by the voicebox to the list used in speaking + for(var/L in will_assist_languages) + assists_languages |= all_languages[L] + +/obj/item/organ/internal/voicebox/proc/add_assistable_langs(var/language) // Adds a new language (by string/define) to the list of things the voicebox can assist + will_assist_languages |= language + amend_assist_langs() // Can't think of a better place to put this, makes the voicebox actually start to assist with the added language + +///////////////////////////////// +// Voicebox Subtypes +///////////////////////////////// + +/obj/item/organ/internal/voicebox/assist // In the off chance we get a species that doesn't speak GalCom by default + +/obj/item/organ/internal/voicebox/assist/New() + ..() + mechassist() + +/obj/item/organ/internal/voicebox/robot + name = "vocal synthesizer" + will_assist_languages = list(LANGUAGE_GALCOM, LANGUAGE_EAL) // Synthetics spawn with this by default + +/obj/item/organ/internal/voicebox/robot/New() + ..() + robotize() diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 5fc5c64ea1d..ea31950e3d0 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -31,6 +31,10 @@ var/list/organ_cache = list() var/rejecting // Is this organ already being rejected? var/preserved = 0 // If this is 1, prevents organ decay. + // Language vars. Putting them here in case we decide to do something crazy with sign-or-other-nonverbal languages. + var/list/will_assist_languages = list() + var/list/datum/language/assists_languages = list() + /obj/item/organ/Destroy() if(owner) owner = null diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 3655e8b2cb2..16250e2c22d 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -72,6 +72,8 @@ var/open = 0 var/stage = 0 var/cavity = 0 + var/burn_stage = 0 //Surgical repair stage for burn. + var/brute_stage = 0 //Surgical repair stage for brute. // HUD element variable, see organ_icon.dm get_damage_hud_image() var/image/hud_damage_image @@ -1328,3 +1330,18 @@ Note that amputating the affected organ does in fact remove the infection from t if(6 to INFINITY) flavor_text += "a ton of [wound]\s" return english_list(flavor_text) + +// Returns a list of the clothing (not glasses) that are covering this part +/obj/item/organ/external/proc/get_covering_clothing() + var/list/covering_clothing = list() + if(owner) + var/list/protective_gear = list(owner.head, owner.wear_mask, owner.wear_suit, owner.w_uniform, owner.gloves, owner.shoes) + for(var/obj/item/clothing/gear in protective_gear) + if(gear.body_parts_covered & src.body_part) + covering_clothing |= gear + if(LAZYLEN(gear.accessories)) + for(var/obj/item/clothing/accessory/bling in gear.accessories) + if(bling.body_parts_covered & src.body_part) + covering_clothing |= bling + + return covering_clothing \ No newline at end of file diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index b76b52e1c03..91b96fea31f 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -4,13 +4,13 @@ var/global/list/limb_icon_cache = list() return /obj/item/organ/external/proc/compile_icon() - overlays.Cut() + cut_overlays() // This is a kludge, only one icon has more than one generation of children though. for(var/obj/item/organ/external/organ in contents) if(organ.children && organ.children.len) for(var/obj/item/organ/external/child in organ.children) overlays += child.mob_icon - overlays += organ.mob_icon + add_overlay(organ.mob_icon) /obj/item/organ/external/proc/sync_colour_to_human(var/mob/living/carbon/human/human) s_tone = null @@ -94,7 +94,7 @@ var/global/list/limb_icon_cache = list() mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons icon_cache_key += "[M][markings[M]["color"]]" - overlays |= get_hair_icon() + add_overlay(get_hair_icon()) return mob_icon @@ -107,7 +107,7 @@ var/global/list/limb_icon_cache = list() var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") if(facial_hair_style.do_colouration) facial_s.Blend(rgb(owner.r_facial, owner.g_facial, owner.b_facial), ICON_ADD) - res.overlays |= facial_s + res.add_overlay(facial_s) //Head hair if(owner.h_style && !(owner.head && (owner.head.flags_inv & BLOCKHEADHAIR))) @@ -122,7 +122,7 @@ var/global/list/limb_icon_cache = list() if(hair_style.do_colouration && islist(h_col) && h_col.len >= 3) hair_s.Blend(rgb(h_col[1], h_col[2], h_col[3]), ICON_MULTIPLY) hair_s.Blend(hair_s_add, ICON_ADD) - res.overlays |= hair_s + res.add_overlay(hair_s) return res @@ -164,7 +164,7 @@ var/global/list/limb_icon_cache = list() var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") mark_s.Blend(markings[M]["color"], ICON_ADD) - overlays |= mark_s //So when it's not on your body, it has icons + add_overlay(mark_s) //So when it's not on your body, it has icons mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons icon_cache_key += "[M][markings[M]["color"]]" @@ -179,6 +179,14 @@ var/global/list/limb_icon_cache = list() if(model) icon_cache_key += "_model_[model]" apply_colouration(mob_icon) + if(owner && owner.synth_markings) + for(var/M in markings) + var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] + var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") + mark_s.Blend(markings[M]["color"], ICON_ADD) + add_overlay(mark_s) //So when it's not on your body, it has icons + mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons + icon_cache_key += "[M][markings[M]["color"]]" dir = EAST icon = mob_icon @@ -258,7 +266,7 @@ var/list/robot_hud_colours = list("#CFCFCF","#AFAFAF","#8F8F8F","#6F6F6F","#4F4F var/b = 0.11 * R.health_hud_intensity temp.color = list(r, r, r, g, g, g, b, b, b) hud_damage_image = image(null) - hud_damage_image.overlays += temp + hud_damage_image.add_overlay(temp) // Calculate the required color index. var/dam_state = min(1,((brute_dam+burn_dam)/max_damage)) diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm index a499a437abb..a3ab809523f 100644 --- a/code/modules/organs/subtypes/standard.dm +++ b/code/modules/organs/subtypes/standard.dm @@ -25,8 +25,9 @@ /obj/item/organ/external/chest/robotize() if(..()) - // Give them a new cell. - owner.internal_organs_by_name["cell"] = new /obj/item/organ/internal/cell(owner,1) + // Give them fancy new organs. + owner.internal_organs_by_name[O_CELL] = new /obj/item/organ/internal/cell(owner,1) + owner.internal_organs_by_name[O_VOICE] = new /obj/item/organ/internal/voicebox/robot(owner, 1) /obj/item/organ/external/chest/handle_germ_effects() . = ..() //Should return an infection level diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 816b62a099a..e8940afecb4 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -309,6 +309,7 @@ t = replacetext(t, "\[/h2\]", "") t = replacetext(t, "\[h3\]", "

") t = replacetext(t, "\[/h3\]", "

") + t = replacetext(t, "\[tab\]", "      ") if(!iscrayon) t = replacetext(t, "\[*\]", "
  • ") @@ -630,4 +631,8 @@ /obj/item/weapon/paper/crumpled/bloody/CrashedMedShuttle name = "Blackbox Transcript - VMV Aurora's Light" - info = "\[The paper is torn at the top, presumably from the impact. It's oil-stained, but you can just about read it.]
    mmons 19:52:01: Come on... it's right there in the distance, we're almost there!
    Doctor Nazarril 19:52:26: Odysseus online. Orrderrs, sirr?
    Captain Simmons 19:52:29: Brace for impact. We're going in full-speed.
    Technician Dynasty 19:52:44: Chief, fire's spread to the secondary propulsion systems.
    Captain Simmons 19:52:51: Copy. Any word from TraCon? Transponder's down still?
    Technician Dynasty 19:53:02: Can't get in touch, sir. Emergency beacon's active, but we're not going t-
    Doctor Nazarril 19:53:08: Don't say it. As long as we believe, we'll get through this.
    Captain Simmons 19:53:11: Damn right. We're a few klicks out from the port. Rough landing, but we can do it.
    V.I.T.A 19:53:26: Vessel diagnostics complete. Engines one, two, three offline. Engine four status: critical. Transponder offline. Fire alarm in the patient bay.
    A loud explosion is heard.
    V.I.T.A 19:53:29: Alert: fuel intake valve open.
    Technician Dynasty 19:53:31: ... ah.
    Doctor Nazarril 19:53:34: Trrranslate?
    V.I.T.A 19:53:37: There is a 16.92% chance of this vessel safely landing at the emergency destination. Note that there is an 83.08% chance of detonation of fuel supplies upon landing.
    Technician Dynasty 19:53:48: We'll make it, sure, but we'll explode and take out half the LZ with us. Propulsion's down, we can't slow down. If we land there, everyone in that port dies, no question.
    V.I.T.A 19:53:53: The Technician is correct.
    Doctor Nazarril 19:54:02: Then... we can't land therrre.
    V.I.T.A 19:54:11: Analysing... recommended course of action: attempt emergency landing in isolated area. Chances of survival: negligible.
    Captain Simmons 19:54:27: I- alright. I'm bringing us down. You all know what this means.
    Doctor Nazarril 19:54:33: Sh... I- I understand. It's been- it's been an honorr, Captain, Dynasty, VITA.
    Technician Dynasty 19:54:39: We had a good run. I'm going to miss this.
    Captain Simmons 19:54:47: VITA. Tell them we died heroes. Tell them... we did all we could.
    V.I.T.A 19:54:48: I will. Impact in five. Four. Three.
    Doctor Nazarril 19:54:49: Oh, starrs... I- you werrre all the... best frriends she everr had. Thank you.
    Technician Dynasty 19:54:50: Any time, kid. Any time.
    V.I.T.A 19:54:41: Two.
    V.I.T.A 19:54:42: One.
    **8/DEC/2561**
    V.I.T.A 06:22:16: Backup power restored. Attempting to establish connection with emergency rescue personnel.
    V.I.T.A 06:22:17: Unable to establish connection. Transponder destroyed on impact.
    V.I.T.A 06:22:18: No lifesigns detected on board.
    **1/JAN/2562**
    V.I.T.A 00:00:00: Happy New Year, crew.
    V.I.T.A 00:00:01: Power reserves: 41%. Diagnostics offline. Cameras offline. Communications offline.
    V.I.T.A 00:00:02: Nobody's coming.
    **14/FEB/2562**
    V.I.T.A 00:00:00: Roses are red.
    V.I.T.A 00:00:01: Violets are blue.
    V.I.T.A 00:00:02: Won't you come back?
    V.I.T.A 00:00:03: I miss you.
    **15/FEB/2562**
    V.I.T.A 22:19:06: Power reserves critical. Transferring remaining power to emergency broadcasting beacon.
    V.I.T.A 22:19:07: Should anyone find this, lay them to rest. They deserve a proper burial.
    V.I.T.A 22:19:08: Erasing files... shutting down.
    A low, monotone beep.
    **16/FEB/2562**
    Something chitters.
    End of transcript." \ No newline at end of file + info = "\[The paper is torn at the top, presumably from the impact. It's oil-stained, but you can just about read it.]
    mmons 19:52:01: Come on... it's right there in the distance, we're almost there!
    Doctor Nazarril 19:52:26: Odysseus online. Orrderrs, sirr?
    Captain Simmons 19:52:29: Brace for impact. We're going in full-speed.
    Technician Dynasty 19:52:44: Chief, fire's spread to the secondary propulsion systems.
    Captain Simmons 19:52:51: Copy. Any word from TraCon? Transponder's down still?
    Technician Dynasty 19:53:02: Can't get in touch, sir. Emergency beacon's active, but we're not going t-
    Doctor Nazarril 19:53:08: Don't say it. As long as we believe, we'll get through this.
    Captain Simmons 19:53:11: Damn right. We're a few klicks out from the port. Rough landing, but we can do it.
    V.I.T.A 19:53:26: Vessel diagnostics complete. Engines one, two, three offline. Engine four status: critical. Transponder offline. Fire alarm in the patient bay.
    A loud explosion is heard.
    V.I.T.A 19:53:29: Alert: fuel intake valve open.
    Technician Dynasty 19:53:31: ... ah.
    Doctor Nazarril 19:53:34: Trrranslate?
    V.I.T.A 19:53:37: There is a 16.92% chance of this vessel safely landing at the emergency destination. Note that there is an 83.08% chance of detonation of fuel supplies upon landing.
    Technician Dynasty 19:53:48: We'll make it, sure, but we'll explode and take out half the LZ with us. Propulsion's down, we can't slow down. If we land there, everyone in that port dies, no question.
    V.I.T.A 19:53:53: The Technician is correct.
    Doctor Nazarril 19:54:02: Then... we can't land therrre.
    V.I.T.A 19:54:11: Analysing... recommended course of action: attempt emergency landing in isolated area. Chances of survival: negligible.
    Captain Simmons 19:54:27: I- alright. I'm bringing us down. You all know what this means.
    Doctor Nazarril 19:54:33: Sh... I- I understand. It's been- it's been an honorr, Captain, Dynasty, VITA.
    Technician Dynasty 19:54:39: We had a good run. I'm going to miss this.
    Captain Simmons 19:54:47: VITA. Tell them we died heroes. Tell them... we did all we could.
    V.I.T.A 19:54:48: I will. Impact in five. Four. Three.
    Doctor Nazarril 19:54:49: Oh, starrs... I- you werrre all the... best frriends she everr had. Thank you.
    Technician Dynasty 19:54:50: Any time, kid. Any time.
    V.I.T.A 19:54:41: Two.
    V.I.T.A 19:54:42: One.
    **8/DEC/2561**
    V.I.T.A 06:22:16: Backup power restored. Attempting to establish connection with emergency rescue personnel.
    V.I.T.A 06:22:17: Unable to establish connection. Transponder destroyed on impact.
    V.I.T.A 06:22:18: No lifesigns detected on board.
    **1/JAN/2562**
    V.I.T.A 00:00:00: Happy New Year, crew.
    V.I.T.A 00:00:01: Power reserves: 41%. Diagnostics offline. Cameras offline. Communications offline.
    V.I.T.A 00:00:02: Nobody's coming.
    **14/FEB/2562**
    V.I.T.A 00:00:00: Roses are red.
    V.I.T.A 00:00:01: Violets are blue.
    V.I.T.A 00:00:02: Won't you come back?
    V.I.T.A 00:00:03: I miss you.
    **15/FEB/2562**
    V.I.T.A 22:19:06: Power reserves critical. Transferring remaining power to emergency broadcasting beacon.
    V.I.T.A 22:19:07: Should anyone find this, lay them to rest. They deserve a proper burial.
    V.I.T.A 22:19:08: Erasing files... shutting down.
    A low, monotone beep.
    **16/FEB/2562**
    Something chitters.
    End of transcript." + +/obj/item/weapon/paper/manifest + name = "supply manifest" + var/is_copy = 1 \ No newline at end of file diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index c0870afda31..c239d1352a3 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -134,7 +134,7 @@ var/global/photo_count = 0 var/icon_on = "camera" var/icon_off = "camera_off" var/size = 3 - var/picture_planes = list(PLANE_WORLD) + var/list/picture_planes = list() /obj/item/device/camera/verb/change_size() set name = "Set Photo Focus" @@ -185,7 +185,7 @@ var/global/photo_count = 0 // As well as anything that isn't invisible. for(var/atom/A in the_turf) if(A.invisibility) continue - if(!(A.plane in picture_planes)) continue + if(A.plane > 0 && !(A.plane in picture_planes)) continue atoms.Add(A) // Sort the atoms into their layers @@ -194,7 +194,7 @@ var/global/photo_count = 0 for(var/i; i <= sorted.len; i++) var/atom/A = sorted[i] if(A) - var/icon/img = getFlatIcon(A, picture_planes = picture_planes)//build_composite_icon(A) + var/icon/img = getFlatIcon(A, picture_planes)//build_composite_icon(A) // If what we got back is actually a picture, draw it. if(istype(img, /icon)) diff --git a/code/modules/planet/planet.dm b/code/modules/planet/planet.dm index 061ae73398f..8fb76044178 100644 --- a/code/modules/planet/planet.dm +++ b/code/modules/planet/planet.dm @@ -30,9 +30,10 @@ current_time = current_time.make_random_time() update_sun() -/datum/planet/proc/process(amount) +/datum/planet/proc/process(last_fire) if(current_time) - current_time = current_time.add_seconds(amount) + var/difference = world.time - last_fire + current_time = current_time.add_seconds(difference SECONDS) update_weather() // We update this first, because some weather types decease the brightness of the sun. if(sun_last_process <= world.time - sun_process_interval) update_sun() diff --git a/code/modules/planet/sif.dm b/code/modules/planet/sif.dm index 8717245b246..3491fac2db3 100644 --- a/code/modules/planet/sif.dm +++ b/code/modules/planet/sif.dm @@ -184,7 +184,8 @@ datum/weather/sif ) /datum/weather/sif/snow/process_effects() - for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs) + ..() + for(var/turf/simulated/floor/outdoors/snow/S in SSplanets.new_outdoor_turfs) //This didn't make any sense before SSplanets, either if(S.z in holder.our_planet.expected_z_levels) for(var/dir_checked in cardinal) var/turf/simulated/floor/T = get_step(S, dir_checked) @@ -207,7 +208,8 @@ datum/weather/sif ) /datum/weather/sif/blizzard/process_effects() - for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs) + ..() + for(var/turf/simulated/floor/outdoors/snow/S in SSplanets.new_outdoor_turfs) //This didn't make any sense before SSplanets, either if(S.z in holder.our_planet.expected_z_levels) for(var/dir_checked in cardinal) var/turf/simulated/floor/T = get_step(S, dir_checked) @@ -219,6 +221,8 @@ datum/weather/sif name = "rain" icon_state = "rain" light_modifier = 0.5 + effect_message = "Rain falls on you." + transition_chances = list( WEATHER_OVERCAST = 25, WEATHER_LIGHT_SNOW = 10, @@ -228,6 +232,7 @@ datum/weather/sif ) /datum/weather/sif/rain/process_effects() + ..() for(var/mob/living/L in living_mob_list) if(L.z in holder.our_planet.expected_z_levels) var/turf/T = get_turf(L) @@ -238,16 +243,19 @@ datum/weather/sif if(istype(L.get_active_hand(), /obj/item/weapon/melee/umbrella)) var/obj/item/weapon/melee/umbrella/U = L.get_active_hand() if(U.open) - to_chat(L, "Rain patters softly onto your umbrella") + if(show_message) + to_chat(L, "Rain patters softly onto your umbrella") continue else if(istype(L.get_inactive_hand(), /obj/item/weapon/melee/umbrella)) var/obj/item/weapon/melee/umbrella/U = L.get_inactive_hand() if(U.open) - to_chat(L, "Rain patters softly onto your umbrella") + if(show_message) + to_chat(L, "Rain patters softly onto your umbrella") continue L.water_act(1) - to_chat(L, "Rain falls on you.") + if(show_message) + to_chat(L, effect_message) /datum/weather/sif/storm name = "storm" @@ -256,6 +264,11 @@ datum/weather/sif temp_low = 233.15 // -40c light_modifier = 0.3 flight_failure_modifier = 10 + var/next_lightning_strike = 0 // world.time when lightning will strike. + var/min_lightning_cooldown = 5 SECONDS + var/max_lightning_cooldown = 1 MINUTE + + transition_chances = list( WEATHER_RAIN = 45, WEATHER_STORM = 40, @@ -264,6 +277,7 @@ datum/weather/sif ) /datum/weather/sif/storm/process_effects() + ..() for(var/mob/living/L in living_mob_list) if(L.z in holder.our_planet.expected_z_levels) var/turf/T = get_turf(L) @@ -287,6 +301,17 @@ datum/weather/sif L.water_act(2) to_chat(L, "Rain falls on you, drenching you in water.") + handle_lightning() + +// This gets called to do lightning periodically. +// There is a seperate function to do the actual lightning strike, so that badmins can play with it. +/datum/weather/sif/storm/proc/handle_lightning() + if(world.time < next_lightning_strike) + return // It's too soon to strike again. + next_lightning_strike = world.time + rand(min_lightning_cooldown, max_lightning_cooldown) + var/turf/T = pick(holder.our_planet.planet_floors) // This has the chance to 'strike' the sky, but that might be a good thing, to scare reckless pilots. + lightning_strike(T) + /datum/weather/sif/hail name = "hail" icon_state = "hail" @@ -294,6 +319,10 @@ datum/weather/sif temp_low = 243.15 // -30c light_modifier = 0.3 flight_failure_modifier = 15 + timer_low_bound = 2 + timer_high_bound = 5 + effect_message = "The hail smacks into you!" + transition_chances = list( WEATHER_RAIN = 45, WEATHER_STORM = 40, @@ -302,6 +331,7 @@ datum/weather/sif ) /datum/weather/sif/hail/process_effects() + ..() for(var/mob/living/carbon/human/H in living_mob_list) if(H.z in holder.our_planet.expected_z_levels) var/turf/T = get_turf(H) @@ -309,15 +339,18 @@ datum/weather/sif continue // They're indoors, so no need to pelt them with ice. // If they have an open umbrella, it'll guard from rain + // Message plays every time the umbrella gets stolen, just so they're especially aware of what's happening if(istype(H.get_active_hand(), /obj/item/weapon/melee/umbrella)) var/obj/item/weapon/melee/umbrella/U = H.get_active_hand() if(U.open) - to_chat(H, "Hail patters gently onto your umbrella.") + if(show_message) + to_chat(H, "Hail patters gently onto your umbrella.") continue else if(istype(H.get_inactive_hand(), /obj/item/weapon/melee/umbrella)) var/obj/item/weapon/melee/umbrella/U = H.get_inactive_hand() if(U.open) - to_chat(H, "Hail patters gently onto your umbrella.") + if(show_message) + to_chat(H, "Hail patters gently onto your umbrella.") continue var/target_zone = pick(BP_ALL) @@ -330,8 +363,9 @@ datum/weather/sif if(amount_soaked >= 10) continue // No need to apply damage. - H.apply_damage(rand(5, 10), BRUTE, target_zone, amount_blocked, amount_soaked, used_weapon = "hail") - to_chat(H, "The hail smacks into you!") + H.apply_damage(rand(1, 3), BRUTE, target_zone, amount_blocked, amount_soaked, used_weapon = "hail") + if(show_message) + to_chat(H, effect_message) /datum/weather/sif/blood_moon name = "blood moon" diff --git a/code/modules/planet/weather.dm b/code/modules/planet/weather.dm index 11c902f77f4..c3939956c51 100644 --- a/code/modules/planet/weather.dm +++ b/code/modules/planet/weather.dm @@ -10,6 +10,7 @@ // Holds the weather icon, using vis_contents. Documentation says an /atom/movable is required for placing inside another atom's vis_contents. var/atom/movable/weather_visuals/visuals = null + var/atom/movable/weather_visuals/special/special_visuals = null /datum/weather_holder/New(var/source) ..() @@ -19,13 +20,14 @@ if(istype(W)) W.holder = src visuals = new() + special_visuals = new() /datum/weather_holder/proc/change_weather(var/new_weather) var/old_light_modifier = null if(current_weather) old_light_modifier = current_weather.light_modifier // We store the old one, so we can determine if recalculating the sun is needed. current_weather = allowed_weather_types[new_weather] - next_weather_shift = world.time + rand(20, 30) MINUTES + next_weather_shift = world.time + rand(current_weather.timer_low_bound, current_weather.timer_high_bound) MINUTES update_icon_effects() update_temperature() @@ -66,8 +68,20 @@ var/flight_failure_modifier = 0 // Some types of weather make flying harder, and therefore make crashes more likely. var/transition_chances = list() // Assoc list var/datum/weather_holder/holder = null + var/timer_low_bound = 5 // How long this weather must run before it tries to change, in minutes + var/timer_high_bound = 10 // How long this weather can run before it tries to change, in minutes + + var/effect_message = null // Should be a string, this is what is shown to a mob caught in the weather + var/last_message = 0 // Keeps track of when the weather last tells EVERY player it's hitting them + var/message_delay = 10 SECONDS // Delay in between weather hit messages + var/show_message = FALSE // Is set to TRUE and plays the messsage every [message_delay] /datum/weather/proc/process_effects() + show_message = FALSE // Need to reset the show_message var, just in case + if(effect_message) // Only bother with the code below if we actually need to display something + if(world.time >= last_message + message_delay) + last_message = world.time // Reset the timer + show_message = TRUE // Tell the rest of the process that we need to make a message return // All this does is hold the weather icon. @@ -75,3 +89,8 @@ icon = 'icons/effects/weather.dmi' mouse_opacity = 0 plane = PLANE_PLANETLIGHTING + +// This is for special effects for specific types of weather, such as lightning flashes in a storm. +// It's a seperate object to allow the use of flick(). +/atom/movable/weather_visuals/special + plane = PLANE_LIGHTING_ABOVE \ No newline at end of file diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 51d6a2c073d..fd309236442 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -88,7 +88,6 @@ var/locked = 1 var/coverlocked = 1 var/aidisabled = 0 - var/tdir = null var/obj/machinery/power/terminal/terminal = null var/lastused_light = 0 var/lastused_equip = 0 @@ -165,11 +164,9 @@ // this allows the APC to be embedded in a wall, yet still inside an area if (building) set_dir(ndir) - src.tdir = dir // to fix Vars bug - set_dir(SOUTH) - pixel_x = (src.tdir & 3)? 0 : (src.tdir == 4 ? 24 : -24) - pixel_y = (src.tdir & 3)? (src.tdir ==1 ? 24 : -24) : 0 + pixel_x = (src.dir & 3)? 0 : (src.dir == 4 ? 24 : -24) + pixel_y = (src.dir & 3)? (src.dir ==1 ? 24 : -24) : 0 if (building==0) init() else @@ -209,7 +206,7 @@ // create a terminal object at the same position as original turf loc // wires will attach to this terminal = new/obj/machinery/power/terminal(src.loc) - terminal.set_dir(tdir) + terminal.set_dir(dir) terminal.master = src /obj/machinery/power/apc/proc/init() diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 1dbe096d665..6717edf95d9 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -160,6 +160,7 @@ var/list/possible_cable_coil_colours = list( return if(W.is_wirecutter()) + var/obj/item/stack/cable_coil/CC if(d1 == UP || d2 == UP) to_chat(user, "You must cut this cable from above.") return @@ -172,9 +173,12 @@ var/list/possible_cable_coil_colours = list( return if(src.d1) // 0-X cables are 1 unit, X-X cables are 2 units long - new/obj/item/stack/cable_coil(T, 2, color) + CC = new/obj/item/stack/cable_coil(T, 2, color) else - new/obj/item/stack/cable_coil(T, 1, color) + CC = new/obj/item/stack/cable_coil(T, 1, color) + + src.add_fingerprint(user) + src.transfer_fingerprints_to(CC) for(var/mob/O in viewers(src, null)) O.show_message("[user] cuts the cable.", 1) @@ -939,4 +943,25 @@ obj/structure/cable/proc/cableColor(var/colorC) if(get_dist(src, user) <= 1) msg += " It doesn't seem to have a beginning, or an end." - to_chat(user, msg) \ No newline at end of file + to_chat(user, msg) + +/obj/item/stack/cable_coil/alien/attack_hand(mob/user as mob) + if (user.get_inactive_hand() == src) + var/N = input("How many units of wire do you want to take from [src]? You can only take up to [amount] at a time.", "Split stacks", 1) as num|null + if(N && N <= amount) + var/obj/item/stack/cable_coil/CC = new/obj/item/stack/cable_coil(user.loc) + CC.amount = N + CC.update_icon() + to_chat(user,"You take [N] units of wire from the [src].") + if (CC) + user.put_in_hands(CC) + src.add_fingerprint(user) + CC.add_fingerprint(user) + spawn(0) + if (src && usr.machine==src) + src.interact(usr) + else + return + else + ..() + return diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 4db4d40c4c1..f9fca6222f7 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -41,6 +41,9 @@ processing_objects -= src return ..() +/obj/item/weapon/cell/get_cell() + return src + /obj/item/weapon/cell/process() if(self_recharge) if(world.time >= last_use + charge_delay) diff --git a/code/modules/power/fusion/core/core_control.dm b/code/modules/power/fusion/core/core_control.dm index 6eaf5f926f6..68313ef671c 100644 --- a/code/modules/power/fusion/core/core_control.dm +++ b/code/modules/power/fusion/core/core_control.dm @@ -3,21 +3,20 @@ icon = 'icons/obj/machines/power/fusion.dmi' icon_state = "core_control" light_color = COLOR_ORANGE - + circuit = /obj/item/weapon/circuitboard/fusion_core_control var/id_tag var/scan_range = 25 var/list/connected_devices = list() var/obj/machinery/power/fusion_core/cur_viewed_device /obj/machinery/computer/fusion_core_control/attackby(var/obj/item/thing, var/mob/user) + ..() if(thing.is_multitool()) var/new_ident = input("Enter a new ident tag.", "Core Control", id_tag) as null|text if(new_ident && user.Adjacent(src)) id_tag = new_ident cur_viewed_device = null return - else - return ..() /obj/machinery/computer/fusion_core_control/attack_ai(mob/user) attack_hand(user) @@ -28,6 +27,11 @@ /obj/machinery/computer/fusion_core_control/interact(mob/user) + if(stat & (BROKEN|NOPOWER)) + user.unset_machine() + user << browse(null, "window=fusion_control") + return + if(!cur_viewed_device || !check_core_status(cur_viewed_device)) cur_viewed_device = null @@ -174,3 +178,19 @@ if(C.idle_power_usage > C.avail()) return . = 1 + +/obj/machinery/computer/fusion_core_control/update_icon() + if(stat & (BROKEN)) + icon = 'icons/obj/computer.dmi' + icon_state = "broken" + set_light(0) + + if(stat & (NOPOWER)) + icon = 'icons/obj/computer.dmi' + icon_state = "computer" + set_light(0) + + if(!stat & (BROKEN|NOPOWER)) + icon = initial(icon) + icon_state = initial(icon_state) + set_light(light_range_on, light_power_on) diff --git a/code/modules/power/fusion/core/core_field.dm b/code/modules/power/fusion/core/core_field.dm index 1efb09d777b..f5d85fb4bf6 100644 --- a/code/modules/power/fusion/core/core_field.dm +++ b/code/modules/power/fusion/core/core_field.dm @@ -35,7 +35,7 @@ /obj/structure/cable, /obj/machinery/atmospherics, /obj/machinery/air_sensor, - /mob/observer/dead, + /mob/observer, /obj/machinery/power/hydromagnetic_trap ) @@ -672,4 +672,4 @@ #undef FUSION_HEAT_CAP #undef FUSION_MAX_ENVIRO_HEAT -#undef PLASMA_TEMP_RADIATION_DIVISIOR \ No newline at end of file +#undef PLASMA_TEMP_RADIATION_DIVISIOR diff --git a/code/modules/power/fusion/fuel_assembly/fuel_control.dm b/code/modules/power/fusion/fuel_assembly/fuel_control.dm index 06274e3e0d9..9c66f3a5d00 100644 --- a/code/modules/power/fusion/fuel_assembly/fuel_control.dm +++ b/code/modules/power/fusion/fuel_assembly/fuel_control.dm @@ -2,6 +2,7 @@ name = "fuel injection control computer" icon = 'icons/obj/machines/power/fusion.dmi' icon_state = "fuel" + circuit = /obj/item/weapon/circuitboard/fusion_fuel_control var/id_tag var/scan_range = 25 @@ -94,9 +95,25 @@ /obj/machinery/computer/fusion_fuel_control/attackby(var/obj/item/W, var/mob/user) + ..() if(W.is_multitool()) var/new_ident = input("Enter a new ident tag.", "Fuel Control", id_tag) as null|text if(new_ident && user.Adjacent(src)) id_tag = new_ident return - return ..() + +/obj/machinery/computer/fusion_fuel_control/update_icon() + if(stat & (BROKEN)) + icon = 'icons/obj/computer.dmi' + icon_state = "broken" + set_light(0) + + if(stat & (NOPOWER)) + icon = 'icons/obj/computer.dmi' + icon_state = "computer" + set_light(0) + + if(!stat & (BROKEN|NOPOWER)) + icon = initial(icon) + icon_state = initial(icon_state) + set_light(light_range_on, light_power_on) diff --git a/code/modules/power/fusion/gyrotron/gyrotron_control.dm b/code/modules/power/fusion/gyrotron/gyrotron_control.dm index 0a80f846531..9c39c774a5b 100644 --- a/code/modules/power/fusion/gyrotron/gyrotron_control.dm +++ b/code/modules/power/fusion/gyrotron/gyrotron_control.dm @@ -3,6 +3,7 @@ icon = 'icons/obj/machines/power/fusion.dmi' icon_state = "engine" light_color = COLOR_BLUE + circuit = /obj/item/weapon/circuitboard/gyrotron_control var/id_tag var/scan_range = 25 @@ -16,6 +17,11 @@ /obj/machinery/computer/gyrotron_control/interact(var/mob/user) + if(stat & (BROKEN|NOPOWER)) + user.unset_machine() + user << browse(null, "window=gyrotron_controller_[id_tag]") + return + if(!id_tag) to_chat(user, "This console has not been assigned an ident tag. Please contact your system administrator or conduct a manual update with a standard multitool.") return @@ -89,9 +95,25 @@ return 0 /obj/machinery/computer/gyrotron_control/attackby(var/obj/item/W, var/mob/user) + ..() if(W.is_multitool()) var/new_ident = input("Enter a new ident tag.", "Gyrotron Control", id_tag) as null|text if(new_ident && user.Adjacent(src)) id_tag = new_ident return - return ..() + +/obj/machinery/computer/gyrotron_control/update_icon() + if(stat & (BROKEN)) + icon = 'icons/obj/computer.dmi' + icon_state = "broken" + set_light(0) + + if(stat & (NOPOWER)) + icon = 'icons/obj/computer.dmi' + icon_state = "computer" + set_light(0) + + if(!stat & (BROKEN|NOPOWER)) + icon = initial(icon) + icon_state = initial(icon_state) + set_light(light_range_on, light_power_on) diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 112f5a482eb..04e63379fc2 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -139,7 +139,7 @@ return // Power machinery should also connect/disconnect from the network. -/obj/machinery/power/default_unfasten_wrench(var/mob/user, var/obj/item/weapon/wrench/W, var/time = 20) +/obj/machinery/power/default_unfasten_wrench(var/mob/user, var/obj/item/weapon/W, var/time = 20) if((. = ..())) if(anchored) connect_to_network() diff --git a/code/modules/power/supermatter/setup_supermatter.dm b/code/modules/power/supermatter/setup_supermatter.dm index a457dd121e9..7477623805f 100644 --- a/code/modules/power/supermatter/setup_supermatter.dm +++ b/code/modules/power/supermatter/setup_supermatter.dm @@ -263,6 +263,34 @@ GLOBAL_LIST_BOILERPLATE(all_engine_setup_markers, /obj/effect/engine_setup) F.update_icon() return SETUP_OK +// Closes the monitoring room shutters so the first Engi to show up doesn't get microwaved +/obj/effect/engine_setup/shutters/ + name = "Shutter Button Marker" + var/target_button = "Engine Monitoring Room Blast Doors" // This needs to be set to whatever the shutter button is called + +/obj/effect/engine_setup/shutters/activate() + if(!target_button) + log_and_message_admins("## WARNING: No button type set at [x] [y] [z]!") + return SETUP_WARNING + + var/obj/machinery/button/remote/blast_door/found = null + var/turf/T = get_turf(src) + for(var/obj/machinery/button/remote/blast_door/B in T.contents) + if(B.name == target_button) + found = B + break + + if(!found) + log_and_message_admins("## WARNING: Unable to locate button at [x] [y] [z]!") + return SETUP_WARNING + + found.trigger() + found.update_icon() + return SETUP_OK + + + + #undef SETUP_OK #undef SETUP_WARNING diff --git a/code/modules/power/tesla/coil.dm b/code/modules/power/tesla/coil.dm index 07dedf5b2b6..82e84718cf6 100644 --- a/code/modules/power/tesla/coil.dm +++ b/code/modules/power/tesla/coil.dm @@ -18,6 +18,9 @@ var/last_zap = 0 var/datum/wires/tesla_coil/wires = null +/obj/machinery/power/tesla_coil/pre_mapped + anchored = TRUE + /obj/machinery/power/tesla_coil/New() ..() wires = new(src) @@ -103,6 +106,9 @@ can_buckle = TRUE buckle_lying = FALSE +/obj/machinery/power/grounding_rod/pre_mapped + anchored = TRUE + /obj/machinery/power/grounding_rod/update_icon() if(panel_open) icon_state = "grounding_rod_open[anchored]" diff --git a/code/modules/power/tesla/tesla_act.dm b/code/modules/power/tesla/tesla_act.dm index 8e3f1c69969..605c9e30216 100644 --- a/code/modules/power/tesla/tesla_act.dm +++ b/code/modules/power/tesla/tesla_act.dm @@ -45,7 +45,10 @@ /obj/machinery/light/tesla_act(power, explosive = FALSE) if(explosive) explosion(loc, 0, 0, 0/*, flame_range = 5*/, adminlog = FALSE) - qdel(src) + qdel(src) + return + on = TRUE + broken() /obj/structure/closet/tesla_act(var/power) ..() //extend the zap diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm index 2d01a24576f..c0e330227d6 100644 --- a/code/modules/power/turbine.dm +++ b/code/modules/power/turbine.dm @@ -131,7 +131,7 @@ return return ..() -/obj/machinery/compressor/default_unfasten_wrench(var/mob/user, var/obj/item/weapon/wrench/W, var/time = 20) +/obj/machinery/compressor/default_unfasten_wrench(var/mob/user, var/obj/item/weapon/W, var/time = 20) if((. = ..())) turbine = null if(anchored) @@ -229,7 +229,7 @@ return return ..() -/obj/machinery/power/turbine/default_unfasten_wrench(var/mob/user, var/obj/item/weapon/wrench/W, var/time = 20) +/obj/machinery/power/turbine/default_unfasten_wrench(var/mob/user, var/obj/item/weapon/W, var/time = 20) if((. = ..())) compressor = null if(anchored) diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm index 0c3c76caaf3..5ea1c0a2d69 100644 --- a/code/modules/projectiles/ammunition/magazines.dm +++ b/code/modules/projectiles/ammunition/magazines.dm @@ -325,6 +325,31 @@ /obj/item/ammo_magazine/box/c9mm/empty initial_ammo = 0 +/obj/item/ammo_magazine/m9mmR/saber + desc = "A very high capacity double stack magazine made specially for the SABER SMG. Filled with 22 9mm bullets." + icon_state = "S9mm-22" + mag_type = MAGAZINE + ammo_type = /obj/item/ammo_casing/a9mm + matter = list(DEFAULT_WALL_MATERIAL = 1200) + caliber = "9mm" + max_ammo = 22 + origin_tech = list(TECH_COMBAT = 2, TECH_ILLEGAL = 1) + multiple_sprites = 1 + +/obj/item/ammo_magazine/m9mmR/saber/ap + desc = "A high capacity double stack magazine made specially for the SABER SMG. Filled with 22 9mm armor piercing bullets." + icon_state = "S9mm-22" + mag_type = MAGAZINE + ammo_type = /obj/item/ammo_casing/a9mm/ap + matter = list(DEFAULT_WALL_MATERIAL = 2000) + caliber = "9mm" + max_ammo = 22 + origin_tech = list(TECH_COMBAT = 2, TECH_ILLEGAL = 1) + multiple_sprites = 1 + +/obj/item/ammo_magazine/m9mmR/saber/empty + initial_ammo = 0 + ///////// 10mm ///////// /obj/item/ammo_magazine/m10mm diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index c87c37a0858..9cfd0d152a1 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -23,17 +23,6 @@ var/battery_lock = 0 //If set, weapon cannot switch batteries -/obj/item/weapon/gun/energy/attackby(var/obj/item/A as obj, mob/user as mob) - ..() - -/obj/item/weapon/gun/energy/switch_firemodes(mob/user) - if(..()) - update_icon() - -/obj/item/weapon/gun/energy/emp_act(severity) - ..() - update_icon() - /obj/item/weapon/gun/energy/New() ..() if(self_recharge) @@ -52,6 +41,9 @@ processing_objects.Remove(src) return ..() +/obj/item/weapon/gun/energy/get_cell() + return power_supply + /obj/item/weapon/gun/energy/process() if(self_recharge) //Every [recharge_time] ticks, recharge a shot for the battery if(world.time > last_shot + charge_delay) //Doesn't work if you've fired recently @@ -75,6 +67,17 @@ charge_tick = 0 return 1 +/obj/item/weapon/gun/energy/attackby(var/obj/item/A as obj, mob/user as mob) + ..() + +/obj/item/weapon/gun/energy/switch_firemodes(mob/user) + if(..()) + update_icon() + +/obj/item/weapon/gun/energy/emp_act(severity) + ..() + update_icon() + /obj/item/weapon/gun/energy/consume_next_projectile() if(!power_supply) return null if(!ispath(projectile_type)) return null diff --git a/code/modules/projectiles/guns/energy/phase.dm b/code/modules/projectiles/guns/energy/phase.dm new file mode 100644 index 00000000000..7de6ae53ce7 --- /dev/null +++ b/code/modules/projectiles/guns/energy/phase.dm @@ -0,0 +1,57 @@ +// Phase weapons go here + +/obj/item/weapon/gun/energy/phasegun + name = "phase carbine" + desc = "The NT EW26 Artemis is a downsized energy weapon, specifically designed for use against wildlife." + icon_state = "phasecarbine" + item_state = "phasecarbine" + wielded_item_state = "phasecarbine-wielded" + slot_flags = SLOT_BACK|SLOT_BELT + charge_cost = 240 + projectile_type = /obj/item/projectile/energy/phase + one_handed_penalty = 15 + +/obj/item/weapon/gun/energy/phasegun/pistol + name = "phase pistol" + desc = "The NT EW15 Apollo is an energy handgun, specifically designed for self-defense against aggressive wildlife." + icon_state = "phase" + item_state = "taser" //I don't have an in-hand sprite, taser will be fine + w_class = ITEMSIZE_NORMAL + slot_flags = SLOT_BELT|SLOT_HOLSTER + charge_cost = 300 + projectile_type = /obj/item/projectile/energy/phase/light + one_handed_penalty = 0 + +/obj/item/weapon/gun/energy/phasegun/pistol/mounted + name = "mounted phase pistol" + self_recharge = 1 + use_external_power = 1 + +/obj/item/weapon/gun/energy/phasegun/pistol/mounted/cyborg + charge_cost = 400 + recharge_time = 7 + +obj/item/weapon/gun/energy/phasegun/rifle + name = "phase rifle" + desc = "The NT EW31 Orion is a specialist energy weapon, intended for use against hostile wildlife." + icon_state = "phaserifle" + item_state = "phaserifle" + wielded_item_state = "phaserifle-wielded" + slot_flags = SLOT_BACK + charge_cost = 150 + projectile_type = /obj/item/projectile/energy/phase/heavy + accuracy = 15 + one_handed_penalty = 30 + +/obj/item/weapon/gun/energy/phasegun/cannon + name = "phase cannon" + desc = "The NT EW50 Gaia is a massive energy weapon, purpose-built for clearing land. You feel dirty just looking at it." + icon_state = "phasecannon" + item_state = "phasecannon" + wielded_item_state = "phasecannon-wielded" //TODO: New Sprites + w_class = ITEMSIZE_HUGE // This thing is big. + slot_flags = SLOT_BACK + charge_cost = 100 + projectile_type = /obj/item/projectile/energy/phase/heavy/cannon + accuracy = 15 + one_handed_penalty = 65 \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 8f18f2f64cf..f1e20b169be 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -25,15 +25,6 @@ charge_cost = 480 projectile_type = /obj/item/projectile/ion/pistol -/obj/item/weapon/gun/energy/phasegun - name = "phase pistol" - desc = "The NT Mk26 EW Apollo is an energy handgun, specifically designed for use against wildlife." - icon_state = "phase" - item_state = "taser" //I don't have an in-hand sprite, taser will be fine - slot_flags = SLOT_BELT|SLOT_HOLSTER - charge_cost = 300 - projectile_type = /obj/item/projectile/energy/phase - /obj/item/weapon/gun/energy/decloner name = "biological demolecularisor" desc = "A gun that discharges high amounts of controlled radiation to slowly break a target into component elements." diff --git a/code/modules/projectiles/guns/magnetic/magnetic.dm b/code/modules/projectiles/guns/magnetic/magnetic.dm index 22ec1b9daa1..2e8289fb8e9 100644 --- a/code/modules/projectiles/guns/magnetic/magnetic.dm +++ b/code/modules/projectiles/guns/magnetic/magnetic.dm @@ -36,6 +36,9 @@ qdel_null(capacitor) . = ..() +/obj/item/weapon/gun/magnetic/get_cell() + return cell + /obj/item/weapon/gun/magnetic/process() if(capacitor) if(cell) diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm index 4c7e0e3e888..a1afc075b53 100644 --- a/code/modules/projectiles/guns/projectile/automatic.dm +++ b/code/modules/projectiles/guns/projectile/automatic.dm @@ -1,25 +1,40 @@ -/obj/item/weapon/gun/projectile/automatic //Hopefully someone will find a way to make these fire in bursts or something. --Superxpdude //Except burstfire isn't fit for an rp server --Mark +/obj/item/weapon/gun/projectile/automatic //This should never be spawned in, it is just here because of code necessities. + name = "daka SMG" + desc = "A small SMG. You really shouldn't be able to get this gun. Uses 9mm rounds." + icon_state = "c05r" //Used because it's not used anywhere else + load_method = SPEEDLOADER + ammo_type = /obj/item/ammo_casing/a9mm + projectile_type = /obj/item/projectile/bullet/pistol + +//Burst is the number of bullets fired; Fire delay is the time you have to wait to shoot the gun again, Move delay is the same but for moving after shooting. . +//Burst accuracy is the accuracy of each bullet fired in the burst. Dispersion is how much the bullets will 'spread' away from where you aimed. + + firemodes = list( + list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null), + list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-15,-15), dispersion=list(0.0, 0.6, 1.0))) + +/obj/item/weapon/gun/projectile/automatic/saber //Fixed it name = "prototype SMG" desc = "A protoype lightweight, fast firing gun. Uses 9mm rounds." - icon_state = "saber" //ugly + icon = 'icons/obj/gun.dmi' + icon_state = "saber"//Still ugly w_class = ITEMSIZE_NORMAL - load_method = SPEEDLOADER //yup. until someone sprites a magazine for it. + load_method = MAGAZINE //This should fix it max_shells = 22 caliber = "9mm" origin_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 2) slot_flags = SLOT_BELT - ammo_type = /obj/item/ammo_casing/a9mm + magazine_type = /obj/item/ammo_magazine/m9mmR/saber + allowed_magazines = list(/obj/item/ammo_magazine/m9mmR/saber, /obj/item/ammo_magazine/m9mmR/saber/ap) projectile_type = /obj/item/projectile/bullet/pistol multi_aim = 1 burst_delay = 2 -// one_handed_penalty = 15 - firemodes = list( list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null), list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-15,-15), dispersion=list(0.0, 0.6, 1.0)) -// list(mode_name="short bursts", burst=5, fire_delay=null, move_delay=4, burst_accuracy=list(0,-15,-15,-30,-30), dispersion=list(0.6, 1.0, 1.0, 1.0, 1.2)), - ) + // list(mode_name="short bursts", burst=5, fire_delay=null, move_delay=4, burst_accuracy=list(0,-15,-15,-30,-30), dispersion=list(0.6, 1.0, 1.0, 1.0, 1.2)), + ) /obj/item/weapon/gun/projectile/automatic/c20r name = "submachine gun" diff --git a/code/modules/projectiles/projectile/arc.dm b/code/modules/projectiles/projectile/arc.dm new file mode 100644 index 00000000000..6e434b1e99d --- /dev/null +++ b/code/modules/projectiles/projectile/arc.dm @@ -0,0 +1,134 @@ +// These projectiles are somewhat different from the other projectiles in the code. +// First, these have an 'arcing' visual, that is accomplished by having the projectile icon rotate as its flying, and +// moving up, then down as it approaches the target. There is also a small shadow effect that follows the projectile +// as its flying. + +// Besides the visuals, arcing projectiles do not collide with anything until they reach the target, as they fly over them. +// For best effect, use this only when it makes sense to do so, IE on the Surface. The projectiles don't care about ceilings or gravity. + +/obj/item/projectile/arc + name = "arcing shot" + icon_state = "fireball" // WIP + step_delay = 2 // Travel a bit slower, to really sell the arc visuals. + plane = ABOVE_PLANE // Since projectiles are 'in the air', they might visually overlap mobs while in flight, so the projectile needs to be above their plane. + var/target_distance = null // How many tiles the impact site is. + var/fired_dir = null // Which direction was the projectile fired towards. Needed to invert the projectile turning based on if facing left or right. + var/obj/effect/projectile_shadow/shadow = null // Visual indicator for the projectile's 'true' position. Needed due to being bound to two dimensions in reality. + +/obj/item/projectile/arc/initialize() + shadow = new(get_turf(src)) + return ..() + +/obj/item/projectile/arc/Destroy() + qdel_null(shadow) + return ..() + +/obj/item/projectile/arc/Bump(atom/A, forced=0) + return 0 +// if(get_turf(src) != original) +// return 0 +// else +// return ..() + +// This is a test projectile in the sense that its testing the code to make sure it works, +// as opposed to a 'can I hit this thing' projectile. +/obj/item/projectile/arc/test/on_impact(turf/T) + new /obj/effect/explosion(T) + return ..() + +/obj/item/projectile/arc/launch(atom/target, target_zone, x_offset=0, y_offset=0, angle_offset=0) + var/expected_distance = get_dist(target, loc) + kill_count = expected_distance // So the projectile "hits the ground." + target_distance = expected_distance + fired_dir = get_dir(loc, target) + ..() // Does the regular launching stuff. + if(fired_dir & EAST) + transform = turn(transform, -45) + else if(fired_dir & WEST) + transform = turn(transform, 45) + + +// Visuals. +/obj/item/projectile/arc/after_move() + // Handle projectile turning in flight. + // This won't turn if fired north/south, as it looks weird. + var/turn_per_step = 90 / target_distance + if(fired_dir & EAST) + transform = turn(transform, turn_per_step) + else if(fired_dir & WEST) + transform = turn(transform, -turn_per_step) + + // Now for the fake height. + // We need to know how far along our "arc" we are. + var/arc_progress = get_dist(src, original) + var/arc_max_height = (target_distance * world.icon_size) / 2 // TODO: Real math. +// var/arc_center = target_distance / 2 +// var/projectile_position = abs(arc_progress - arc_center) +// var/height_multiplier = projectile_position / arc_center +// height_multiplier = abs(height_multiplier - 1) +// height_multiplier = height_multiplier ** 2 + + +// animate(src, pixel_z = arc_max_height * height_multiplier, time = step_delay) + var/projectile_position = arc_progress / target_distance + var/sine_position = projectile_position * 180 + var/pixel_z_position = arc_max_height * sin(sine_position) + animate(src, pixel_z = pixel_z_position, time = step_delay) + + // Update our shadow. + shadow.forceMove(loc) + +/obj/effect/projectile_shadow + name = "shadow" + desc = "You better avoid the thing coming down!" + icon = 'icons/obj/projectiles.dmi' + icon_state = "arc_shadow" + anchored = TRUE + +////////////// +// Subtypes +////////////// + +// Generic, Hivebot related +/obj/item/projectile/arc/blue_energy + name = "energy missile" + icon_state = "force_missile" + damage = 15 + damage_type = BURN + +// Fragmentation arc shot +/obj/item/projectile/arc/fragmentation + name = "fragmentation shot" + icon_state = "shell" + var/list/fragment_types = list( + /obj/item/projectile/bullet/pellet/fragment, /obj/item/projectile/bullet/pellet/fragment, \ + /obj/item/projectile/bullet/pellet/fragment, /obj/item/projectile/bullet/pellet/fragment/strong + ) + var/fragment_amount = 63 // Same as a grenade. + var/spread_range = 7 + +/obj/item/projectile/arc/fragmentation/on_impact(turf/T) + fragmentate(T, fragment_amount, spread_range, fragment_types) + +// EMP arc shot +/obj/item/projectile/arc/emp_blast + name = "emp blast" + icon_state = "bluespace" + +/obj/item/projectile/arc/emp_blast/on_impact(turf/T) + empulse(T, 2, 4, 7, 10) // Normal EMP grenade. + return ..() + +/obj/item/projectile/arc/emp_blast/weak/on_impact(turf/T) + empulse(T, 1, 2, 3, 4) // Sec EMP grenade. + return ..() + +// Radiation arc shot +/obj/item/projectile/arc/radioactive + name = "radiation blast" + icon_state = "green_pellet" + icon_scale = 2 + var/rad_power = 50 + +/obj/item/projectile/arc/radioactive/on_impact(turf/T) + radiation_repository.radiate(T, rad_power) \ No newline at end of file diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 9755f604ab0..0cd8e690131 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -10,7 +10,7 @@ var/frequency = 1 hitscan = 1 embed_chance = 0 - invisibility = 101 //beam projectiles are invisible as they are rendered by the effect engine + invisibility = 99 //beam projectiles are invisible as they are rendered by the effect engine light_range = 2 light_power = 0.5 light_color = "#FF0D00" diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index d5bae0dc228..3448c2a9e94 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -212,7 +212,22 @@ muzzle_type = /obj/effect/projectile/pulse/muzzle /obj/item/projectile/energy/phase - kill_count = 4 + name = "phase wave" + icon_state = "phase" + kill_count = 6 damage = 5 - SA_bonus_damage = 55 // 60 total on animals. - SA_vulnerability = SA_ANIMAL \ No newline at end of file + SA_bonus_damage = 45 // 50 total on animals + SA_vulnerability = SA_ANIMAL + +/obj/item/projectile/energy/phase/light + kill_count = 4 + SA_bonus_damage = 35 // 40 total on animals + +/obj/item/projectile/energy/phase/heavy + kill_count = 8 + SA_bonus_damage = 55 // 60 total on animals + +/obj/item/projectile/energy/phase/heavy/cannon + kill_count = 10 + damage = 15 + SA_bonus_damage = 60 // 75 total on animals \ No newline at end of file diff --git a/code/modules/projectiles/targeting/targeting_overlay.dm b/code/modules/projectiles/targeting/targeting_overlay.dm index 00a380dedf0..76d18042654 100644 --- a/code/modules/projectiles/targeting/targeting_overlay.dm +++ b/code/modules/projectiles/targeting/targeting_overlay.dm @@ -6,7 +6,7 @@ anchored = 1 density = 0 opacity = 0 - layer = FLY_LAYER + plane = ABOVE_PLANE simulated = 0 mouse_opacity = 0 diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm index 4c079ef2dc0..cd40067d4c3 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm @@ -65,7 +65,7 @@ reagent_state = LIQUID color = "#404030" - ingest_met = REM + ingest_met = REM * 2 var/nutriment_factor = 0 var/strength = 10 // This is, essentially, units between stages - the lower, the stronger. Less fine tuning, more clarity. 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 d315deb111e..c98a69aff85 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm @@ -858,7 +858,7 @@ glass_name = "lime tea" glass_desc = "A tasty mixture of lime and tea. It's apparently good for you!" - cup_name = "cup of berry tea" + cup_name = "cup of lime tea" cup_desc = "A tasty mixture of lime and tea. It's apparently good for you!" /datum/reagent/drink/tea/orangetea diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm index 6c83b0e26da..53ce37b3ef6 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm @@ -482,3 +482,11 @@ /datum/reagent/luminol/touch_mob(var/mob/living/L) L.reveal_blood() + +/datum/reagent/nutriment/biomass + name = "Biomass" + id = "biomass" + description = "A slurry of compounds that contains the basic requirements for life." + taste_description = "salty meat" + reagent_state = LIQUID + color = "#DF9FBF" \ No newline at end of file diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm index 6e79670459a..5d46650c3f6 100644 --- a/code/modules/reagents/Chemistry-Recipes.dm +++ b/code/modules/reagents/Chemistry-Recipes.dm @@ -501,6 +501,7 @@ id = "ammonia" result = "ammonia" required_reagents = list("hydrogen" = 3, "nitrogen" = 1) + inhibitors = list("phoron" = 1) // Messes with lexorin result_amount = 3 /datum/chemical_reaction/diethylamine @@ -2239,4 +2240,12 @@ id = "qerr_quem" result = "qerr_quem" required_reagents = list("nicotine" = 1, "carbon" = 1, "sugar" = 2) - result_amount = 4 \ No newline at end of file + result_amount = 4 + +// Biomass, for cloning and bioprinters +/datum/chemical_reaction/biomass + name = "Biomass" + id = "biomass" + result = "biomass" + required_reagents = list("protein" = 1, "sugar" = 1, "phoron" = 1) + result_amount = 1 // Roughly 20u per phoron sheet \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/glass/bottle.dm b/code/modules/reagents/reagent_containers/glass/bottle.dm index 26e88caec0f..159ac6acf3e 100644 --- a/code/modules/reagents/reagent_containers/glass/bottle.dm +++ b/code/modules/reagents/reagent_containers/glass/bottle.dm @@ -55,7 +55,6 @@ var/image/lid = image(icon, src, "lid_bottle") overlays += lid - /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline name = "inaprovaline bottle" desc = "A small bottle. Contains inaprovaline - used to stabilize patients." @@ -63,7 +62,6 @@ icon_state = "bottle-4" prefill = list("inaprovaline" = 60) - /obj/item/weapon/reagent_containers/glass/bottle/toxin name = "toxin bottle" desc = "A small bottle of toxins. Do not drink, it is poisonous." @@ -71,7 +69,6 @@ icon_state = "bottle-3" prefill = list("toxin" = 60) - /obj/item/weapon/reagent_containers/glass/bottle/cyanide name = "cyanide bottle" desc = "A small bottle of cyanide. Bitter almonds?" @@ -79,7 +76,6 @@ icon_state = "bottle-3" prefill = list("cyanide" = 30) //volume changed to match chloral - /obj/item/weapon/reagent_containers/glass/bottle/stoxin name = "soporific bottle" desc = "A small bottle of soporific. Just the fumes make you sleepy." @@ -87,15 +83,13 @@ icon_state = "bottle-3" prefill = list("stoxin" = 60) - /obj/item/weapon/reagent_containers/glass/bottle/chloralhydrate - name = "Chloral Hydrate Bottle" + name = "chloral hydrate bottle" desc = "A small bottle of Choral Hydrate. Mickey's Favorite!" icon = 'icons/obj/chemical.dmi' icon_state = "bottle-3" prefill = list("chloralhydrate" = 30) //Intentionally low since it is so strong. Still enough to knock someone out. - /obj/item/weapon/reagent_containers/glass/bottle/antitoxin name = "dylovene bottle" desc = "A small bottle of dylovene. Counters poisons, and repairs damage. A wonder drug." @@ -103,7 +97,6 @@ icon_state = "bottle-4" prefill = list("anti_toxin" = 60) - /obj/item/weapon/reagent_containers/glass/bottle/mutagen name = "unstable mutagen bottle" desc = "A small bottle of unstable mutagen. Randomly changes the DNA structure of whoever comes in contact." @@ -111,7 +104,6 @@ icon_state = "bottle-1" prefill = list("mutagen" = 60) - /obj/item/weapon/reagent_containers/glass/bottle/ammonia name = "ammonia bottle" desc = "A small bottle." @@ -119,7 +111,6 @@ icon_state = "bottle-1" prefill = list("ammonia" = 60) - /obj/item/weapon/reagent_containers/glass/bottle/eznutrient name = "\improper EZ NUtrient bottle" desc = "A small bottle." @@ -127,7 +118,6 @@ icon_state = "bottle-4" prefill = list("eznutrient" = 60) - /obj/item/weapon/reagent_containers/glass/bottle/left4zed name = "\improper Left-4-Zed bottle" desc = "A small bottle." @@ -135,7 +125,6 @@ icon_state = "bottle-4" prefill = list("left4zed" = 60) - /obj/item/weapon/reagent_containers/glass/bottle/robustharvest name = "\improper Robust Harvest" desc = "A small bottle." @@ -143,7 +132,6 @@ icon_state = "bottle-4" prefill = list("robustharvest" = 60) - /obj/item/weapon/reagent_containers/glass/bottle/diethylamine name = "diethylamine bottle" desc = "A small bottle." @@ -152,32 +140,36 @@ prefill = list("diethylamine" = 60) /obj/item/weapon/reagent_containers/glass/bottle/pacid - name = "Polytrinic Acid Bottle" + name = "polytrinic acid bottle" desc = "A small bottle. Contains a small amount of Polytrinic Acid" icon = 'icons/obj/chemical.dmi' icon_state = "bottle-4" prefill = list("pacid" = 60) - /obj/item/weapon/reagent_containers/glass/bottle/adminordrazine - name = "Adminordrazine Bottle" + name = "adminordrazine bottle" desc = "A small bottle. Contains the liquid essence of the gods." icon = 'icons/obj/drinks.dmi' icon_state = "holyflask" prefill = list("adminordrazine" = 60) - /obj/item/weapon/reagent_containers/glass/bottle/capsaicin - name = "Capsaicin Bottle" + name = "capsaicin bottle" desc = "A small bottle. Contains hot sauce." icon = 'icons/obj/chemical.dmi' icon_state = "bottle-4" prefill = list("capsaicin" = 60) - /obj/item/weapon/reagent_containers/glass/bottle/frostoil - name = "Frost Oil Bottle" + name = "frost oil bottle" desc = "A small bottle. Contains cold sauce." icon = 'icons/obj/chemical.dmi' icon_state = "bottle-4" prefill = list("frostoil" = 60) + +/obj/item/weapon/reagent_containers/glass/bottle/biomass + name = "biomass bottle" + desc = "A bottle of raw biomass! Gross!" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle-3" + prefill = list("biomass" = 60) \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index ef0d4a2100d..724cee9a6fb 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -49,7 +49,7 @@ if(H.a_intent != I_HELP) to_chat(user, "[H] is resisting your attempt to inject them with \the [src].") to_chat(H, " [user] is trying to inject you with \the [src]!") - if(!do_after(user, 30)) + if(!do_after(user, 30, H)) return user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index 6c1575fc1f0..106c655ae25 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -79,1828 +79,4 @@ other types of metals and chemistry for reagents). req_tech = list(TECH_DATA = 1) materials = list(DEFAULT_WALL_MATERIAL = 30, "glass" = 10) build_path = /obj/item/weapon/disk/tech_disk - sort_string = "GAAAB" - -/datum/design/item/stock_part - build_type = PROTOLATHE - -/datum/design/item/stock_part/AssembleDesignName() - ..() - name = "Component design ([item_name])" - -/datum/design/item/stock_part/AssembleDesignDesc() - if(!desc) - desc = "A stock part used in the construction of various devices." - -/datum/design/item/stock_part/basic_capacitor - id = "basic_capacitor" - req_tech = list(TECH_POWER = 1) - materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) - build_path = /obj/item/weapon/stock_parts/capacitor - sort_string = "CAAAA" - -/datum/design/item/stock_part/adv_capacitor - id = "adv_capacitor" - req_tech = list(TECH_POWER = 3) - materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) - build_path = /obj/item/weapon/stock_parts/capacitor/adv - sort_string = "CAAAB" - -/datum/design/item/stock_part/super_capacitor - id = "super_capacitor" - req_tech = list(TECH_POWER = 5, TECH_MATERIAL = 4) - materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, "gold" = 20) - build_path = /obj/item/weapon/stock_parts/capacitor/super - sort_string = "CAAAC" - -/datum/design/item/stock_part/micro_mani - id = "micro_mani" - req_tech = list(TECH_MATERIAL = 1, TECH_DATA = 1) - materials = list(DEFAULT_WALL_MATERIAL = 30) - build_path = /obj/item/weapon/stock_parts/manipulator - sort_string = "CAABA" - -/datum/design/item/stock_part/nano_mani - id = "nano_mani" - req_tech = list(TECH_MATERIAL = 3, TECH_DATA = 2) - materials = list(DEFAULT_WALL_MATERIAL = 30) - build_path = /obj/item/weapon/stock_parts/manipulator/nano - sort_string = "CAABB" - -/datum/design/item/stock_part/pico_mani - id = "pico_mani" - req_tech = list(TECH_MATERIAL = 5, TECH_DATA = 2) - materials = list(DEFAULT_WALL_MATERIAL = 30) - build_path = /obj/item/weapon/stock_parts/manipulator/pico - sort_string = "CAABC" - -/datum/design/item/stock_part/basic_matter_bin - id = "basic_matter_bin" - req_tech = list(TECH_MATERIAL = 1) - materials = list(DEFAULT_WALL_MATERIAL = 80) - build_path = /obj/item/weapon/stock_parts/matter_bin - sort_string = "CAACA" - -/datum/design/item/stock_part/adv_matter_bin - id = "adv_matter_bin" - req_tech = list(TECH_MATERIAL = 3) - materials = list(DEFAULT_WALL_MATERIAL = 80) - build_path = /obj/item/weapon/stock_parts/matter_bin/adv - sort_string = "CAACB" - -/datum/design/item/stock_part/super_matter_bin - id = "super_matter_bin" - req_tech = list(TECH_MATERIAL = 5) - materials = list(DEFAULT_WALL_MATERIAL = 80) - build_path = /obj/item/weapon/stock_parts/matter_bin/super - sort_string = "CAACC" - -/datum/design/item/stock_part/basic_micro_laser - id = "basic_micro_laser" - req_tech = list(TECH_MAGNET = 1) - materials = list(DEFAULT_WALL_MATERIAL = 10, "glass" = 20) - build_path = /obj/item/weapon/stock_parts/micro_laser - sort_string = "CAADA" - -/datum/design/item/stock_part/high_micro_laser - id = "high_micro_laser" - req_tech = list(TECH_MAGNET = 3) - materials = list(DEFAULT_WALL_MATERIAL = 10, "glass" = 20) - build_path = /obj/item/weapon/stock_parts/micro_laser/high - sort_string = "CAADB" - -/datum/design/item/stock_part/ultra_micro_laser - id = "ultra_micro_laser" - req_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 5) - materials = list(DEFAULT_WALL_MATERIAL = 10, "glass" = 20, "uranium" = 10) - build_path = /obj/item/weapon/stock_parts/micro_laser/ultra - sort_string = "CAADC" - -/datum/design/item/stock_part/basic_sensor - id = "basic_sensor" - req_tech = list(TECH_MAGNET = 1) - materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 20) - build_path = /obj/item/weapon/stock_parts/scanning_module - sort_string = "CAAEA" - -/datum/design/item/stock_part/adv_sensor - id = "adv_sensor" - req_tech = list(TECH_MAGNET = 3) - materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 20) - build_path = /obj/item/weapon/stock_parts/scanning_module/adv - sort_string = "CAAEB" - -/datum/design/item/stock_part/phasic_sensor - id = "phasic_sensor" - req_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 3) - materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 20, "silver" = 10) - build_path = /obj/item/weapon/stock_parts/scanning_module/phasic - sort_string = "CAAEC" - -/datum/design/item/stock_part/RPED - name = "Rapid Part Exchange Device" - desc = "Special mechanical module made to store, sort, and apply standard machine parts." - id = "rped" - req_tech = list(TECH_ENGINEERING = 3, TECH_MATERIAL = 3) - materials = list(DEFAULT_WALL_MATERIAL = 15000, "glass" = 5000) - build_path = /obj/item/weapon/storage/part_replacer - sort_string = "CBAAA" - -/datum/design/item/powercell - build_type = PROTOLATHE | MECHFAB - -/datum/design/item/powercell/AssembleDesignName() - name = "Power Cell Model ([item_name])" - -/datum/design/item/powercell/AssembleDesignDesc() - if(build_path) - var/obj/item/weapon/cell/C = build_path - desc = "Allows the construction of power cells that can hold [initial(C.maxcharge)] units of energy." - -/datum/design/item/powercell/Fabricate() - var/obj/item/weapon/cell/C = ..() - C.charge = 0 //shouldn't produce power out of thin air. - return C - -/datum/design/item/powercell/basic - name = "basic" - build_type = PROTOLATHE | MECHFAB - id = "basic_cell" - req_tech = list(TECH_POWER = 1) - materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50) - build_path = /obj/item/weapon/cell - category = "Misc" - sort_string = "DAAAA" - -/datum/design/item/powercell/high - name = "high-capacity" - build_type = PROTOLATHE | MECHFAB - id = "high_cell" - req_tech = list(TECH_POWER = 2) - materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 60) - build_path = /obj/item/weapon/cell/high - category = "Misc" - sort_string = "DAAAB" - -/datum/design/item/powercell/super - name = "super-capacity" - id = "super_cell" - req_tech = list(TECH_POWER = 3, TECH_MATERIAL = 2) - materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 70) - build_path = /obj/item/weapon/cell/super - category = "Misc" - sort_string = "DAAAC" - -/datum/design/item/powercell/hyper - name = "hyper-capacity" - id = "hyper_cell" - req_tech = list(TECH_POWER = 5, TECH_MATERIAL = 4) - materials = list(DEFAULT_WALL_MATERIAL = 400, "gold" = 150, "silver" = 150, "glass" = 70) - build_path = /obj/item/weapon/cell/hyper - category = "Misc" - sort_string = "DAAAD" - -/datum/design/item/powercell/device - name = "device" - build_type = PROTOLATHE - id = "device" - materials = list(DEFAULT_WALL_MATERIAL = 350, "glass" = 25) - build_path = /obj/item/weapon/cell/device - category = "Misc" - sort_string = "DAABA" - -/datum/design/item/powercell/weapon - name = "weapon" - build_type = PROTOLATHE - id = "weapon" - materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50) - build_path = /obj/item/weapon/cell/device/weapon - category = "Misc" - sort_string = "DAABB" - -/datum/design/item/hud - materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) - -/datum/design/item/hud/AssembleDesignName() - ..() - name = "HUD glasses prototype ([item_name])" - -/datum/design/item/hud/AssembleDesignDesc() - desc = "Allows for the construction of \a [item_name] HUD glasses." - -/datum/design/item/hud/health - name = "health scanner" - id = "health_hud" - req_tech = list(TECH_BIO = 2, TECH_MAGNET = 3) - build_path = /obj/item/clothing/glasses/hud/health - sort_string = "GAAAA" - -/datum/design/item/hud/security - name = "security records" - id = "security_hud" - req_tech = list(TECH_MAGNET = 3, TECH_COMBAT = 2) - build_path = /obj/item/clothing/glasses/hud/security - sort_string = "GAAAB" - -/datum/design/item/hud/mesons - name = "Optical meson scanners design" - desc = "Using the meson-scanning technology those glasses allow you to see through walls, floor or anything else." - id = "mesons" - req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2) - materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) - build_path = /obj/item/clothing/glasses/meson - sort_string = "GAAAC" - -/datum/design/item/weapon/mining/AssembleDesignName() - ..() - name = "Mining equipment design ([item_name])" - -/datum/design/item/weapon/mining/jackhammer - id = "jackhammer" - req_tech = list(TECH_MATERIAL = 3, TECH_POWER = 2, TECH_ENGINEERING = 2) - materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 500, "silver" = 500) - build_path = /obj/item/weapon/pickaxe/jackhammer - sort_string = "KAAAA" - -/datum/design/item/weapon/mining/drill - id = "drill" - req_tech = list(TECH_MATERIAL = 2, TECH_POWER = 3, TECH_ENGINEERING = 2) - materials = list(DEFAULT_WALL_MATERIAL = 6000, "glass" = 1000) //expensive, but no need for miners. - build_path = /obj/item/weapon/pickaxe/drill - sort_string = "KAAAB" - -/datum/design/item/weapon/mining/plasmacutter - id = "plasmacutter" - req_tech = list(TECH_MATERIAL = 4, TECH_PHORON = 3, TECH_ENGINEERING = 3) - materials = list(DEFAULT_WALL_MATERIAL = 1500, "glass" = 500, "gold" = 500, "phoron" = 500) - build_path = /obj/item/weapon/pickaxe/plasmacutter - sort_string = "KAAAC" - -/datum/design/item/weapon/mining/pick_diamond - id = "pick_diamond" - req_tech = list(TECH_MATERIAL = 6) - materials = list("diamond" = 3000) - build_path = /obj/item/weapon/pickaxe/diamond - sort_string = "KAAAD" - -/datum/design/item/weapon/mining/drill_diamond - id = "drill_diamond" - req_tech = list(TECH_MATERIAL = 6, TECH_POWER = 4, TECH_ENGINEERING = 4) - materials = list(DEFAULT_WALL_MATERIAL = 3000, "glass" = 1000, "diamond" = 2000) - build_path = /obj/item/weapon/pickaxe/diamonddrill - sort_string = "KAAAE" - -/datum/design/item/device/depth_scanner - desc = "Used to check spatial depth and density of rock outcroppings." - id = "depth_scanner" - req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2, TECH_BLUESPACE = 2) - materials = list(DEFAULT_WALL_MATERIAL = 1000,"glass" = 1000) - build_path = /obj/item/device/depth_scanner - sort_string = "KAAAF" - -/////////////////////////////////// -/////////Shield Generators///////// -/////////////////////////////////// -/datum/design/circuit/shield - req_tech = list(TECH_BLUESPACE = 4, TECH_PHORON = 3) - materials = list("$glass" = 2000, "sacid" = 20, "$phoron" = 10000, "$diamond" = 5000, "$gold" = 10000) - -/datum/design/item/medical - materials = list(DEFAULT_WALL_MATERIAL = 30, "glass" = 20) - -/datum/design/item/medical/AssembleDesignName() - ..() - name = "Biotech device prototype ([item_name])" - -/datum/design/item/medical/robot_scanner - desc = "A hand-held scanner able to diagnose robotic injuries." - id = "robot_scanner" - req_tech = list(TECH_MAGNET = 3, TECH_BIO = 2, TECH_ENGINEERING = 3) - materials = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 200) - build_path = /obj/item/device/robotanalyzer - sort_string = "MACFA" - -/datum/design/item/medical/mass_spectrometer - desc = "A device for analyzing chemicals in blood." - id = "mass_spectrometer" - req_tech = list(TECH_BIO = 2, TECH_MAGNET = 2) - build_path = /obj/item/device/mass_spectrometer - sort_string = "MACAA" - -/datum/design/item/medical/adv_mass_spectrometer - desc = "A device for analyzing chemicals in blood and their quantities." - id = "adv_mass_spectrometer" - req_tech = list(TECH_BIO = 2, TECH_MAGNET = 4) - build_path = /obj/item/device/mass_spectrometer/adv - sort_string = "MACAB" - -/datum/design/item/medical/reagent_scanner - desc = "A device for identifying chemicals." - id = "reagent_scanner" - req_tech = list(TECH_BIO = 2, TECH_MAGNET = 2) - build_path = /obj/item/device/reagent_scanner - sort_string = "MACBA" - -/datum/design/item/medical/adv_reagent_scanner - desc = "A device for identifying chemicals and their proportions." - id = "adv_reagent_scanner" - req_tech = list(TECH_BIO = 2, TECH_MAGNET = 4) - build_path = /obj/item/device/reagent_scanner/adv - sort_string = "MACBB" - -/datum/design/item/beaker/AssembleDesignName() - name = "Beaker prototype ([item_name])" - -/datum/design/item/beaker/noreact - name = "cryostasis" - desc = "A cryostasis beaker that allows for chemical storage without reactions. Can hold up to 50 units." - id = "splitbeaker" - req_tech = list(TECH_MATERIAL = 2) - materials = list(DEFAULT_WALL_MATERIAL = 3000) - build_path = /obj/item/weapon/reagent_containers/glass/beaker/noreact - sort_string = "MADAA" - -/datum/design/item/beaker/bluespace - name = TECH_BLUESPACE - desc = "A bluespace beaker, powered by experimental bluespace technology and Element Cuban combined with the Compound Pete. Can hold up to 300 units." - id = "bluespacebeaker" - req_tech = list(TECH_BLUESPACE = 2, TECH_MATERIAL = 6) - materials = list(DEFAULT_WALL_MATERIAL = 3000, "phoron" = 3000, "diamond" = 500) - build_path = /obj/item/weapon/reagent_containers/glass/beaker/bluespace - sort_string = "MADAB" - -/datum/design/item/medical/nanopaste - desc = "A tube of paste containing swarms of repair nanites. Very effective in repairing robotic machinery." - id = "nanopaste" - req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3) - materials = list(DEFAULT_WALL_MATERIAL = 7000, "glass" = 7000) - build_path = /obj/item/stack/nanopaste - sort_string = "MBAAA" - -/datum/design/item/medical/scalpel_laser1 - name = "Basic Laser Scalpel" - desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks basic and could be improved." - id = "scalpel_laser1" - req_tech = list(TECH_BIO = 2, TECH_MATERIAL = 2, TECH_MAGNET = 2) - materials = list(DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500) - build_path = /obj/item/weapon/surgical/scalpel/laser1 - sort_string = "MBBAA" - -/datum/design/item/medical/scalpel_laser2 - name = "Improved Laser Scalpel" - desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks somewhat advanced." - id = "scalpel_laser2" - req_tech = list(TECH_BIO = 3, TECH_MATERIAL = 4, TECH_MAGNET = 4) - materials = list(DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 2500) - build_path = /obj/item/weapon/surgical/scalpel/laser2 - sort_string = "MBBAB" - -/datum/design/item/medical/scalpel_laser3 - name = "Advanced Laser Scalpel" - desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks to be the pinnacle of precision energy cutlery!" - id = "scalpel_laser3" - req_tech = list(TECH_BIO = 4, TECH_MATERIAL = 6, TECH_MAGNET = 5) - materials = list(DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 2000, "gold" = 1500) - build_path = /obj/item/weapon/surgical/scalpel/laser3 - sort_string = "MBBAC" - -/datum/design/item/medical/scalpel_manager - name = "Incision Management System" - desc = "A true extension of the surgeon's body, this marvel instantly and completely prepares an incision allowing for the immediate commencement of therapeutic steps." - id = "scalpel_manager" - req_tech = list(TECH_BIO = 4, TECH_MATERIAL = 7, TECH_MAGNET = 5, TECH_DATA = 4) - materials = list (DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 1500, "gold" = 1500, "diamond" = 750) - build_path = /obj/item/weapon/surgical/scalpel/manager - sort_string = "MBBAD" - -/datum/design/item/medical/bone_clamp - name = "Bone Clamp" - desc = "A miracle of modern science, this tool rapidly knits together bone, without the need for bone gel." - id = "bone_clamp" - req_tech = list(TECH_BIO = 4, TECH_MATERIAL = 5, TECH_MAGNET = 4, TECH_DATA = 4) - materials = list (DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 2500) - build_path = /obj/item/weapon/surgical/bone_clamp - sort_string = "MBBAE" - -/datum/design/item/medical/advanced_roller - name = "advanced roller bed" - desc = "A more advanced version of the regular roller bed, with inbuilt surgical stabilisers and an improved folding system." - id = "roller_bed" - req_tech = list(TECH_BIO = 3, TECH_MATERIAL = 3, TECH_MAGNET = 3) - materials = list(DEFAULT_WALL_MATERIAL = 4000, "glass" = 2000, "phoron" = 2000) - build_path = /obj/item/roller/adv - sort_string = "MBBAF" - -/datum/design/item/medical/improved_analyzer - name = "improved health analyzer" - desc = "A prototype version of the regular health analyzer, able to distinguish the location of more serious injuries as well as accurately determine radiation levels." - id = "improved_analyzer" - req_tech = list(TECH_MAGNET = 5, TECH_BIO = 6) - materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "silver" = 1000, "gold" = 1500) - build_path = /obj/item/device/healthanalyzer/improved - sort_string = "MBBAG" - -/datum/design/item/implant - materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) - -/datum/design/item/implant/AssembleDesignName() - ..() - name = "Implantable biocircuit design ([item_name])" - -/datum/design/item/implant/chemical - name = "chemical" - id = "implant_chem" - req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3) - build_path = /obj/item/weapon/implantcase/chem - sort_string = "MFAAA" - -/datum/design/item/implant/freedom - name = "freedom" - id = "implant_free" - req_tech = list(TECH_ILLEGAL = 2, TECH_BIO = 3) - build_path = /obj/item/weapon/implantcase/freedom - sort_string = "MFAAB" - -/datum/design/item/weapon/AssembleDesignName() - ..() - name = "Weapon prototype ([item_name])" - -/datum/design/item/weapon/AssembleDesignDesc() - if(!desc) - if(build_path) - var/obj/item/I = build_path - desc = initial(I.desc) - ..() - -/datum/design/item/weapon/stunrevolver - id = "stunrevolver" - req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3, TECH_POWER = 2) - materials = list(DEFAULT_WALL_MATERIAL = 4000) - build_path = /obj/item/weapon/gun/energy/stunrevolver - sort_string = "TAAAA" - -/datum/design/item/weapon/nuclear_gun - id = "nuclear_gun" - req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 5, TECH_POWER = 3) - materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000, "uranium" = 500) - build_path = /obj/item/weapon/gun/energy/gun/nuclear - sort_string = "TAAAB" - -/datum/design/item/weapon/lasercannon - desc = "The lasing medium of this prototype is enclosed in a tube lined with uranium-235 and subjected to high neutron flux in a nuclear reactor core." - id = "lasercannon" - req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3, TECH_POWER = 3) - materials = list(DEFAULT_WALL_MATERIAL = 10000, "glass" = 1000, "diamond" = 2000) - build_path = /obj/item/weapon/gun/energy/lasercannon - sort_string = "TAAAC" - -/datum/design/item/weapon/phoronpistol - id = "ppistol" - req_tech = list(TECH_COMBAT = 5, TECH_PHORON = 4) - materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000, "phoron" = 3000) - build_path = /obj/item/weapon/gun/energy/toxgun - sort_string = "TAAAD" - -/datum/design/item/weapon/decloner - id = "decloner" - req_tech = list(TECH_COMBAT = 8, TECH_MATERIAL = 7, TECH_BIO = 5, TECH_POWER = 6) - materials = list("gold" = 5000,"uranium" = 10000) - build_path = /obj/item/weapon/gun/energy/decloner - sort_string = "TAAAE" - -/datum/design/item/weapon/smg - id = "smg" - req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3) - materials = list(DEFAULT_WALL_MATERIAL = 8000, "silver" = 2000, "diamond" = 1000) - build_path = /obj/item/weapon/gun/projectile/automatic - sort_string = "TAABA" - -/datum/design/item/weapon/ammo_9mm - id = "ammo_9mm" - req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3) - materials = list(DEFAULT_WALL_MATERIAL = 3750, "silver" = 100) - build_path = /obj/item/ammo_magazine/box/c9mm - sort_string = "TAACA" - -/datum/design/item/weapon/stunshell - desc = "A stunning shell for a shotgun." - id = "stunshell" - req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3) - materials = list(DEFAULT_WALL_MATERIAL = 4000) - build_path = /obj/item/ammo_casing/a12g/stunshell - sort_string = "TAACB" - -/datum/design/item/weapon/chemsprayer - desc = "An advanced chem spraying device." - id = "chemsprayer" - req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 3, TECH_BIO = 2) - materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000) - build_path = /obj/item/weapon/reagent_containers/spray/chemsprayer - sort_string = "TABAA" - -/datum/design/item/weapon/rapidsyringe - id = "rapidsyringe" - req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3, TECH_ENGINEERING = 3, TECH_BIO = 2) - materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000) - build_path = /obj/item/weapon/gun/launcher/syringe/rapid - sort_string = "TABAB" - -/datum/design/item/weapon/temp_gun - desc = "A gun that shoots high-powered glass-encased energy temperature bullets." - id = "temp_gun" - req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 4, TECH_POWER = 3, TECH_MAGNET = 2) - materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 500, "silver" = 3000) - build_path = /obj/item/weapon/gun/energy/temperature - sort_string = "TABAC" - -/datum/design/item/weapon/large_grenade - id = "large_Grenade" - req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 2) - materials = list(DEFAULT_WALL_MATERIAL = 3000) - build_path = /obj/item/weapon/grenade/chem_grenade/large - sort_string = "TACAA" - -/datum/design/item/weapon/dartgun - desc = "A gun that fires small hollow chemical-payload darts." - id = "dartgun_r" - req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 4, TECH_BIO = 4, TECH_MAGNET = 3, TECH_ILLEGAL = 1) - materials = list(DEFAULT_WALL_MATERIAL = 5000, "gold" = 5000, "silver" = 2500, "glass" = 750) - build_path = /obj/item/weapon/gun/projectile/dartgun/research - sort_string = "TACAB" - -/datum/design/item/weapon/dartgunmag_small - id = "dartgun_mag_s" - req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1) - materials = list(DEFAULT_WALL_MATERIAL = 300, "gold" = 100, "silver" = 100, "glass" = 300) - build_path = /obj/item/ammo_magazine/chemdart/small - sort_string = "TACAC" - -/datum/design/item/weapon/dartgun_ammo_small - id = "dartgun_ammo_s" - req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1) - materials = list(DEFAULT_WALL_MATERIAL = 50, "gold" = 30, "silver" = 30, "glass" = 50) - build_path = /obj/item/ammo_casing/chemdart/small - sort_string = "TACAD" - -/datum/design/item/weapon/dartgunmag_med - id = "dartgun_mag_m" - req_tech = list(TECH_COMBAT = 7, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1) - materials = list(DEFAULT_WALL_MATERIAL = 500, "gold" = 150, "silver" = 150, "diamond" = 200, "glass" = 400) - build_path = /obj/item/ammo_magazine/chemdart - sort_string = "TACAE" - -/datum/design/item/weapon/dartgun_ammo_med - id = "dartgun_ammo_m" - req_tech = list(TECH_COMBAT = 7, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1) - materials = list(DEFAULT_WALL_MATERIAL = 80, "gold" = 40, "silver" = 40, "glass" = 60) - build_path = /obj/item/ammo_casing/chemdart - sort_string = "TACAF" - -/datum/design/item/weapon/fuelrod - id = "fuelrod_gun" - req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 4, TECH_PHORON = 4, TECH_ILLEGAL = 5, TECH_MAGNET = 5) - materials = list(DEFAULT_WALL_MATERIAL = 10000, "glass" = 2000, "gold" = 500, "silver" = 500, "uranium" = 1000, "phoron" = 3000, "diamond" = 1000) - build_path = /obj/item/weapon/gun/magnetic/fuelrod - sort_string = "TACBA" - -/datum/design/item/weapon/flora_gun - id = "flora_gun" - req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3, TECH_POWER = 3) - materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 500, "uranium" = 500) - build_path = /obj/item/weapon/gun/energy/floragun - sort_string = "TBAAA" - -/datum/design/item/weapon/slimebation - id = "slimebation" - req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2, TECH_POWER = 3, TECH_COMBAT = 3) - materials = list(DEFAULT_WALL_MATERIAL = 5000) - build_path = /obj/item/weapon/melee/baton/slime - sort_string = "TBAAB" - -/datum/design/item/weapon/slimetaser - id = "slimetaser" - req_tech = list(TECH_MATERIAL = 3, TECH_BIO = 3, TECH_POWER = 4, TECH_COMBAT = 4) - materials = list(DEFAULT_WALL_MATERIAL = 5000) - build_path = /obj/item/weapon/gun/energy/taser/xeno - sort_string = "TBAAC" - -/datum/design/item/stock_part/subspace_ansible - id = "s-ansible" - req_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2) - materials = list(DEFAULT_WALL_MATERIAL = 80, "silver" = 20) - build_path = /obj/item/weapon/stock_parts/subspace/ansible - sort_string = "UAAAA" - -/datum/design/item/stock_part/hyperwave_filter - id = "s-filter" - req_tech = list(TECH_DATA = 3, TECH_MAGNET = 3) - materials = list(DEFAULT_WALL_MATERIAL = 40, "silver" = 10) - build_path = /obj/item/weapon/stock_parts/subspace/sub_filter - sort_string = "UAAAB" - -/datum/design/item/stock_part/subspace_amplifier - id = "s-amplifier" - req_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2) - materials = list(DEFAULT_WALL_MATERIAL = 10, "gold" = 30, "uranium" = 15) - build_path = /obj/item/weapon/stock_parts/subspace/amplifier - sort_string = "UAAAC" - -/datum/design/item/stock_part/subspace_treatment - id = "s-treatment" - req_tech = list(TECH_DATA = 3, TECH_MAGNET = 2, TECH_MATERIAL = 4, TECH_BLUESPACE = 2) - materials = list(DEFAULT_WALL_MATERIAL = 10, "silver" = 20) - build_path = /obj/item/weapon/stock_parts/subspace/treatment - sort_string = "UAAAD" - -/datum/design/item/stock_part/subspace_analyzer - id = "s-analyzer" - req_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2) - materials = list(DEFAULT_WALL_MATERIAL = 10, "gold" = 15) - build_path = /obj/item/weapon/stock_parts/subspace/analyzer - sort_string = "UAAAE" - -/datum/design/item/stock_part/subspace_crystal - id = "s-crystal" - req_tech = list(TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2) - materials = list("glass" = 1000, "silver" = 20, "gold" = 20) - build_path = /obj/item/weapon/stock_parts/subspace/crystal - sort_string = "UAAAF" - -/datum/design/item/stock_part/subspace_transmitter - id = "s-transmitter" - req_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 5, TECH_BLUESPACE = 3) - materials = list("glass" = 100, "silver" = 10, "uranium" = 15) - build_path = /obj/item/weapon/stock_parts/subspace/transmitter - sort_string = "UAAAG" - -/datum/design/item/device/ano_scanner - name = "Alden-Saraspova counter" - id = "ano_scanner" - desc = "Aids in triangulation of exotic particles." - req_tech = list(TECH_BLUESPACE = 3, TECH_MAGNET = 3) - materials = list(DEFAULT_WALL_MATERIAL = 10000,"glass" = 5000) - build_path = /obj/item/device/ano_scanner - sort_string = "UAAAH" - -/datum/design/item/light_replacer - name = "Light replacer" - desc = "A device to automatically replace lights. Refill with working lightbulbs." - id = "light_replacer" - req_tech = list(TECH_MAGNET = 3, TECH_MATERIAL = 4) - materials = list(DEFAULT_WALL_MATERIAL = 1500, "silver" = 150, "glass" = 3000) - build_path = /obj/item/device/lightreplacer - sort_string = "VAAAH" - -datum/design/item/laserpointer - name = "laser pointer" - desc = "Don't shine it in your eyes!" - id = "laser_pointer" - req_tech = list(TECH_MAGNET = 3) - materials = list(DEFAULT_WALL_MATERIAL = 100, "glass" = 50) - build_path = /obj/item/device/laser_pointer - sort_string = "VAAAI" - -/datum/design/item/paicard - name = "'pAI', personal artificial intelligence device" - id = "paicard" - req_tech = list(TECH_DATA = 2) - materials = list("glass" = 500, DEFAULT_WALL_MATERIAL = 500) - build_path = /obj/item/device/paicard - sort_string = "VABAI" - -/datum/design/item/communicator - name = "Communicator" - id = "communicator" - req_tech = list(TECH_DATA = 2, TECH_MAGNET = 2) - materials = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 500) - build_path = /obj/item/device/communicator - sort_string = "VABAJ" - -/datum/design/item/intellicard - name = "'intelliCore', AI preservation and transportation system" - desc = "Allows for the construction of an intelliCore." - id = "intellicore" - req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 4) - materials = list("glass" = 1000, "gold" = 200) - build_path = /obj/item/device/aicard - sort_string = "VACAA" - -/datum/design/item/dronebrain - name = "Robotic intelligence circuit" - id = "dronebrain" - req_tech = list(TECH_ENGINEERING = 4, TECH_MATERIAL = 5, TECH_DATA = 4) - build_type = PROTOLATHE | PROSFAB - materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "silver" = 1000, "gold" = 500) - build_path = /obj/item/device/mmi/digital/robot - category = "Misc" - sort_string = "VACAC" - -/datum/design/item/posibrain - name = "Positronic brain" - id = "posibrain" - req_tech = list(TECH_ENGINEERING = 4, TECH_MATERIAL = 6, TECH_BLUESPACE = 2, TECH_DATA = 4) - build_type = PROTOLATHE | PROSFAB - materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "silver" = 1000, "gold" = 500, "phoron" = 500, "diamond" = 100) - build_path = /obj/item/device/mmi/digital/posibrain - category = "Misc" - sort_string = "VACAB" - -/datum/design/item/mmi - name = "Man-machine interface" - id = "mmi" - req_tech = list(TECH_DATA = 2, TECH_BIO = 3) - build_type = PROTOLATHE | PROSFAB - materials = list(DEFAULT_WALL_MATERIAL = 1000, "glass" = 500) - build_path = /obj/item/device/mmi - category = "Misc" - sort_string = "VACBA" - -/datum/design/item/beacon - name = "Bluespace tracking beacon design" - id = "beacon" - req_tech = list(TECH_BLUESPACE = 1) - materials = list (DEFAULT_WALL_MATERIAL = 20, "glass" = 10) - build_path = /obj/item/device/radio/beacon - sort_string = "VADAA" - -/datum/design/item/gps - name = "Triangulating device design" - desc = "Triangulates approximate co-ordinates using a nearby satellite network." - id = "gps" - req_tech = list(TECH_MATERIAL = 2, TECH_DATA = 2, TECH_BLUESPACE = 2) - materials = list(DEFAULT_WALL_MATERIAL = 500) - build_path = /obj/item/device/gps - sort_string = "VADAB" - -/datum/design/item/beacon_locator - name = "Beacon tracking pinpointer" - desc = "Used to scan and locate signals on a particular frequency." - id = "beacon_locator" - req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 2, TECH_BLUESPACE = 3) - materials = list(DEFAULT_WALL_MATERIAL = 1000,"glass" = 500) - build_path = /obj/item/device/beacon_locator - sort_string = "VADAC" - -/datum/design/item/bag_holding - name = "'Bag of Holding', an infinite capacity bag prototype" - desc = "Using localized pockets of bluespace this bag prototype offers incredible storage capacity with the contents weighting nothing. It's a shame the bag itself is pretty heavy." - id = "bag_holding" - req_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 6) - materials = list("gold" = 3000, "diamond" = 1500, "uranium" = 250) - build_path = /obj/item/weapon/storage/backpack/holding - sort_string = "VAEAA" - -/datum/design/item/dufflebag_holding - name = "'DuffleBag of Holding', an infinite capacity dufflebag prototype" - desc = "A minaturized prototype of the popular Bag of Holding, the Dufflebag of Holding is, functionally, identical to the bag of holding, but comes in a more stylish and compact form." - id = "dufflebag_holding" - req_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 6) - materials = list("gold" = 3000, "diamond" = 1500, "uranium" = 250) - build_path = /obj/item/weapon/storage/backpack/holding/duffle - sort_string = "VAEAB" - -/datum/design/item/binaryencrypt - name = "Binary encryption key" - desc = "Allows for deciphering the binary channel on-the-fly." - id = "binaryencrypt" - req_tech = list(TECH_ILLEGAL = 2) - materials = list(DEFAULT_WALL_MATERIAL = 300, "glass" = 300) - build_path = /obj/item/device/encryptionkey/binary - sort_string = "VASAA" - -/datum/design/item/chameleon - name = "Holographic equipment kit" - desc = "A kit of dangerous, high-tech equipment with changeable looks." - id = "chameleon" - req_tech = list(TECH_ILLEGAL = 2) - materials = list(DEFAULT_WALL_MATERIAL = 500) - build_path = /obj/item/weapon/storage/box/syndie_kit/chameleon - sort_string = "VASBA" - -/datum/design/item/experimental_welder - name = "Experimental welding tool" - desc = "A welding tool that generate fuel for itself." - id = "expwelder" - req_tech = list(TECH_ENGINEERING = 4, TECH_PHORON = 3, TECH_MATERIAL = 4) - materials = list(DEFAULT_WALL_MATERIAL = 70, "glass" = 120, "phoron" = 100) - build_path = /obj/item/weapon/weldingtool/experimental - sort_string = "VASCA" - -/datum/design/item/hand_drill - name = "Hand drill" - desc = "A simple powered hand drill." - id = "handdrill" - req_tech = list(TECH_ENGINEERING = 3, TECH_MATERIAL = 2) - materials = list(DEFAULT_WALL_MATERIAL = 300, "silver" = 100) - build_path = /obj/item/weapon/tool/screwdriver/power - sort_string = "VASDA" - -/datum/design/item/jaws_life - name = "Jaws of life" - desc = "A set of jaws of life, compressed through the magic of science." - id = "jawslife" - req_tech = list(TECH_ENGINEERING = 3, TECH_MATERIAL = 2) - materials = list(DEFAULT_WALL_MATERIAL = 300, "silver" = 100) - build_path = /obj/item/weapon/tool/crowbar/power - sort_string = "VASEA" - -/datum/design/item/device/t_scanner_upg - name = "Upgraded T-ray Scanner" - desc = "An upgraded version of the terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes." - id = "upgradedtscanner" - req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 4, TECH_MATERIAL = 2) - materials = list(DEFAULT_WALL_MATERIAL = 500, "phoron" = 150) - build_path = /obj/item/device/t_scanner/upgraded - sort_string = "VASSA" - - -/datum/design/item/device/t_scanner_adv - name = "Advanced T-ray Scanner" - desc = "An advanced version of the terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes." - id = "advancedtscanner" - req_tech = list(TECH_MAGNET = 6, TECH_ENGINEERING = 6, TECH_MATERIAL = 6) - materials = list(DEFAULT_WALL_MATERIAL = 1250, "phoron" = 500, "silver" = 50) - build_path = /obj/item/device/t_scanner/advanced - sort_string = "VASSB" -/* -CIRCUITS BELOW -*/ - -/datum/design/circuit - build_type = IMPRINTER - req_tech = list(TECH_DATA = 2) - materials = list("glass" = 2000) - chemicals = list("sacid" = 20) - time = 5 - -/datum/design/circuit/AssembleDesignName() - ..() - if(build_path) - var/obj/item/weapon/circuitboard/C = build_path - if(initial(C.board_type) == "machine") - name = "Machine circuit design ([item_name])" - else if(initial(C.board_type) == "computer") - name = "Computer circuit design ([item_name])" - else - name = "Circuit design ([item_name])" - -/datum/design/circuit/AssembleDesignDesc() - if(!desc) - desc = "Allows for the construction of \a [item_name] circuit board." - -/datum/design/circuit/arcademachine - name = "battle arcade machine" - id = "arcademachine" - req_tech = list(TECH_DATA = 1) - build_path = /obj/item/weapon/circuitboard/arcade/battle - sort_string = "MAAAA" - -/datum/design/circuit/oriontrail - name = "orion trail arcade machine" - id = "oriontrail" - req_tech = list(TECH_DATA = 1) - build_path = /obj/item/weapon/circuitboard/arcade/orion_trail - sort_string = "MAAAA" - -/datum/design/circuit/jukebox - name = "jukebox" - id = "jukebox" - req_tech = list(TECH_MAGNET = 2, TECH_DATA = 1) - build_path = /obj/item/weapon/circuitboard/jukebox - sort_string = "MAAAB" - -/datum/design/circuit/seccamera - name = "security camera monitor" - id = "seccamera" - build_path = /obj/item/weapon/circuitboard/security - sort_string = "DAAAA" - -/datum/design/circuit/secdata - name = "security records console" - id = "sec_data" - build_path = /obj/item/weapon/circuitboard/secure_data - sort_string = "DABAA" - -/datum/design/circuit/prisonmanage - name = "prisoner management console" - id = "prisonmanage" - build_path = /obj/item/weapon/circuitboard/prisoner - sort_string = "DACAA" - -/datum/design/circuit/med_data - name = "medical records console" - id = "med_data" - build_path = /obj/item/weapon/circuitboard/med_data - sort_string = "FAAAA" - -/datum/design/circuit/operating - name = "patient monitoring console" - id = "operating" - build_path = /obj/item/weapon/circuitboard/operating - sort_string = "FACAA" - -/datum/design/circuit/scan_console - name = "DNA machine" - id = "scan_console" - build_path = /obj/item/weapon/circuitboard/scan_consolenew - sort_string = "FAGAA" - -/datum/design/circuit/clonecontrol - name = "cloning control console" - id = "clonecontrol" - req_tech = list(TECH_DATA = 3, TECH_BIO = 3) - build_path = /obj/item/weapon/circuitboard/cloning - sort_string = "FAGAC" - -/datum/design/circuit/clonepod - name = "clone pod" - id = "clonepod" - req_tech = list(TECH_DATA = 3, TECH_BIO = 3) - build_path = /obj/item/weapon/circuitboard/clonepod - sort_string = "FAGAE" - -/datum/design/circuit/clonescanner - name = "cloning scanner" - id = "clonescanner" - req_tech = list(TECH_DATA = 3, TECH_BIO = 3) - build_path = /obj/item/weapon/circuitboard/clonescanner - sort_string = "FAGAG" - -/datum/design/circuit/crewconsole - name = "crew monitoring console" - id = "crewconsole" - req_tech = list(TECH_DATA = 3, TECH_MAGNET = 2, TECH_BIO = 2) - build_path = /obj/item/weapon/circuitboard/crew - sort_string = "FAGAI" - -/datum/design/circuit/teleconsole - name = "teleporter control console" - id = "teleconsole" - req_tech = list(TECH_DATA = 3, TECH_BLUESPACE = 2) - build_path = /obj/item/weapon/circuitboard/teleporter - sort_string = "HAAAA" - -/datum/design/circuit/robocontrol - name = "robotics control console" - id = "robocontrol" - req_tech = list(TECH_DATA = 4) - build_path = /obj/item/weapon/circuitboard/robotics - sort_string = "HAAAB" - -/datum/design/circuit/mechacontrol - name = "exosuit control console" - id = "mechacontrol" - req_tech = list(TECH_DATA = 3) - build_path = /obj/item/weapon/circuitboard/mecha_control - sort_string = "HAAAC" - -/datum/design/circuit/rdconsole - name = "R&D control console" - id = "rdconsole" - req_tech = list(TECH_DATA = 4) - build_path = /obj/item/weapon/circuitboard/rdconsole - sort_string = "HAAAE" - -/datum/design/circuit/aifixer - name = "AI integrity restorer" - id = "aifixer" - req_tech = list(TECH_DATA = 3, TECH_BIO = 2) - build_path = /obj/item/weapon/circuitboard/aifixer - sort_string = "HAAAF" - -/datum/design/circuit/comm_monitor - name = "telecommunications monitoring console" - id = "comm_monitor" - req_tech = list(TECH_DATA = 3) - build_path = /obj/item/weapon/circuitboard/comm_monitor - sort_string = "HAACA" - -/datum/design/circuit/comm_server - name = "telecommunications server monitoring console" - id = "comm_server" - req_tech = list(TECH_DATA = 3) - build_path = /obj/item/weapon/circuitboard/comm_server - sort_string = "HAACB" - -/datum/design/circuit/message_monitor - name = "messaging monitor console" - id = "message_monitor" - req_tech = list(TECH_DATA = 5) - build_path = /obj/item/weapon/circuitboard/message_monitor - sort_string = "HAACC" - -/datum/design/circuit/aiupload - name = "AI upload console" - id = "aiupload" - req_tech = list(TECH_DATA = 4) - build_path = /obj/item/weapon/circuitboard/aiupload - sort_string = "HAABA" - -/datum/design/circuit/borgupload - name = "cyborg upload console" - id = "borgupload" - req_tech = list(TECH_DATA = 4) - build_path = /obj/item/weapon/circuitboard/borgupload - sort_string = "HAABB" - -/datum/design/circuit/destructive_analyzer - name = "destructive analyzer" - id = "destructive_analyzer" - req_tech = list(TECH_DATA = 2, TECH_MAGNET = 2, TECH_ENGINEERING = 2) - build_path = /obj/item/weapon/circuitboard/destructive_analyzer - sort_string = "HABAA" - -/datum/design/circuit/protolathe - name = "protolathe" - id = "protolathe" - req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2) - build_path = /obj/item/weapon/circuitboard/protolathe - sort_string = "HABAB" - -/datum/design/circuit/circuit_imprinter - name = "circuit imprinter" - id = "circuit_imprinter" - req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2) - build_path = /obj/item/weapon/circuitboard/circuit_imprinter - sort_string = "HABAC" - -/datum/design/circuit/autolathe - name = "autolathe board" - id = "autolathe" - req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2) - build_path = /obj/item/weapon/circuitboard/autolathe - sort_string = "HABAD" - -/datum/design/circuit/rdservercontrol - name = "R&D server control console" - id = "rdservercontrol" - req_tech = list(TECH_DATA = 3) - build_path = /obj/item/weapon/circuitboard/rdservercontrol - sort_string = "HABBA" - -/datum/design/circuit/rdserver - name = "R&D server" - id = "rdserver" - req_tech = list(TECH_DATA = 3) - build_path = /obj/item/weapon/circuitboard/rdserver - sort_string = "HABBB" - -/datum/design/circuit/mechfab - name = "exosuit fabricator" - id = "mechfab" - req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3) - build_path = /obj/item/weapon/circuitboard/mechfab - sort_string = "HABAE" - -/datum/design/circuit/prosfab - name = "prosthetics fabricator" - id = "prosfab" - req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3) - build_path = /obj/item/weapon/circuitboard/prosthetics - sort_string = "HABAF" - -/datum/design/circuit/mech_recharger - name = "mech recharger" - id = "mech_recharger" - req_tech = list(TECH_DATA = 2, TECH_POWER = 2, TECH_ENGINEERING = 2) - build_path = /obj/item/weapon/circuitboard/mech_recharger - sort_string = "HACAA" - -/datum/design/circuit/recharge_station - name = "cyborg recharge station" - id = "recharge_station" - req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 2) - build_path = /obj/item/weapon/circuitboard/recharge_station - sort_string = "HACAC" - -/datum/design/circuit/atmosalerts - name = "atmosphere alert console" - id = "atmosalerts" - build_path = /obj/item/weapon/circuitboard/atmos_alert - sort_string = "JAAAA" - -/datum/design/circuit/air_management - name = "atmosphere monitoring console" - id = "air_management" - build_path = /obj/item/weapon/circuitboard/air_management - sort_string = "JAAAB" - -/datum/design/circuit/rcon_console - name = "RCON remote control console" - id = "rcon_console" - req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 3, TECH_POWER = 5) - build_path = /obj/item/weapon/circuitboard/rcon_console - sort_string = "JAAAC" - -/datum/design/circuit/dronecontrol - name = "drone control console" - id = "dronecontrol" - req_tech = list(TECH_DATA = 4) - build_path = /obj/item/weapon/circuitboard/drone_control - sort_string = "JAAAD" - -/datum/design/circuit/powermonitor - name = "power monitoring console" - id = "powermonitor" - build_path = /obj/item/weapon/circuitboard/powermonitor - sort_string = "JAAAE" - -/datum/design/circuit/solarcontrol - name = "solar control console" - id = "solarcontrol" - build_path = /obj/item/weapon/circuitboard/solar_control - sort_string = "JAAAF" - -/datum/design/circuit/pacman - name = "PACMAN-type generator" - id = "pacman" - req_tech = list(TECH_DATA = 3, TECH_PHORON = 3, TECH_POWER = 3, TECH_ENGINEERING = 3) - build_path = /obj/item/weapon/circuitboard/pacman - sort_string = "JBAAA" - -/datum/design/circuit/superpacman - name = "SUPERPACMAN-type generator" - id = "superpacman" - req_tech = list(TECH_DATA = 3, TECH_POWER = 4, TECH_ENGINEERING = 4) - build_path = /obj/item/weapon/circuitboard/pacman/super - sort_string = "JBAAB" - -/datum/design/circuit/mrspacman - name = "MRSPACMAN-type generator" - id = "mrspacman" - req_tech = list(TECH_DATA = 3, TECH_POWER = 5, TECH_ENGINEERING = 5) - build_path = /obj/item/weapon/circuitboard/pacman/mrs - sort_string = "JBAAC" - -/datum/design/circuit/batteryrack - name = "cell rack PSU" - id = "batteryrack" - req_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 2) - build_path = /obj/item/weapon/circuitboard/batteryrack - sort_string = "JBABA" - -/datum/design/circuit/smes_cell - name = "'SMES' superconductive magnetic energy storage" - desc = "Allows for the construction of circuit boards used to build a SMES." - id = "smes_cell" - req_tech = list(TECH_POWER = 7, TECH_ENGINEERING = 5) - build_path = /obj/item/weapon/circuitboard/smes - sort_string = "JBABB" - -/datum/design/circuit/grid_checker - name = "power grid checker" - desc = "Allows for the construction of circuit boards used to build a grid checker." - id = "grid_checker" - req_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 3) - build_path = /obj/item/weapon/circuitboard/grid_checker - sort_string = "JBABC" - -/datum/design/circuit/breakerbox - name = "breaker box" - desc = "Allows for the construction of circuit boards used to build a breaker box." - id = "breakerbox" - req_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3) - build_path = /obj/item/weapon/circuitboard/breakerbox - sort_string = "JBABD" - -/datum/design/circuit/gas_heater - name = "gas heating system" - id = "gasheater" - req_tech = list(TECH_POWER = 2, TECH_ENGINEERING = 1) - build_path = /obj/item/weapon/circuitboard/unary_atmos/heater - sort_string = "JCAAA" - -/datum/design/circuit/gas_cooler - name = "gas cooling system" - id = "gascooler" - req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2) - build_path = /obj/item/weapon/circuitboard/unary_atmos/cooler - sort_string = "JCAAB" - -/datum/design/circuit/secure_airlock - name = "secure airlock electronics" - desc = "Allows for the construction of a tamper-resistant airlock electronics." - id = "securedoor" - req_tech = list(TECH_DATA = 3) - build_path = /obj/item/weapon/airlock_electronics/secure - sort_string = "JDAAA" - -/datum/design/circuit/ordercomp - name = "supply ordering console" - id = "ordercomp" - build_path = /obj/item/weapon/circuitboard/ordercomp - sort_string = "KAAAA" - -/datum/design/circuit/supplycomp - name = "supply control console" - id = "supplycomp" - req_tech = list(TECH_DATA = 3) - build_path = /obj/item/weapon/circuitboard/supplycomp - sort_string = "KAAAB" - -/datum/design/circuit/biogenerator - name = "biogenerator" - id = "biogenerator" - req_tech = list(TECH_DATA = 2) - build_path = /obj/item/weapon/circuitboard/biogenerator - sort_string = "KBAAA" - -/datum/design/circuit/miningdrill - name = "mining drill head" - id = "mining drill head" - req_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1) - build_path = /obj/item/weapon/circuitboard/miningdrill - sort_string = "KCAAA" - -/datum/design/circuit/miningdrillbrace - name = "mining drill brace" - id = "mining drill brace" - req_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1) - build_path = /obj/item/weapon/circuitboard/miningdrillbrace - sort_string = "KCAAB" - -/datum/design/circuit/comconsole - name = "communications console" - id = "comconsole" - build_path = /obj/item/weapon/circuitboard/communications - sort_string = "LAAAA" - -/datum/design/circuit/idcardconsole - name = "ID card modification console" - id = "idcardconsole" - build_path = /obj/item/weapon/circuitboard/card - sort_string = "LAAAB" - -/datum/design/circuit/emp_data - name = "employment records console" - id = "emp_data" - build_path = /obj/item/weapon/circuitboard/skills - sort_string = "LAAAC" - -/datum/design/circuit/mecha - req_tech = list(TECH_DATA = 3) - -/datum/design/circuit/mecha/AssembleDesignName() - name = "Exosuit module circuit design ([name])" -/datum/design/circuit/mecha/AssembleDesignDesc() - desc = "Allows for the construction of \a [name] module." - -/datum/design/circuit/mecha/ripley_main - name = "APLU 'Ripley' central control" - id = "ripley_main" - build_path = /obj/item/weapon/circuitboard/mecha/ripley/main - sort_string = "NAAAA" - -/datum/design/circuit/mecha/ripley_peri - name = "APLU 'Ripley' peripherals control" - id = "ripley_peri" - build_path = /obj/item/weapon/circuitboard/mecha/ripley/peripherals - sort_string = "NAAAB" - -/datum/design/circuit/mecha/odysseus_main - name = "'Odysseus' central control" - id = "odysseus_main" - req_tech = list(TECH_DATA = 3,TECH_BIO = 2) - build_path = /obj/item/weapon/circuitboard/mecha/odysseus/main - sort_string = "NAABA" - -/datum/design/circuit/mecha/odysseus_peri - name = "'Odysseus' peripherals control" - id = "odysseus_peri" - req_tech = list(TECH_DATA = 3,TECH_BIO = 2) - build_path = /obj/item/weapon/circuitboard/mecha/odysseus/peripherals - sort_string = "NAABB" - -/datum/design/circuit/mecha/gygax_main - name = "'Gygax' central control" - id = "gygax_main" - req_tech = list(TECH_DATA = 4) - build_path = /obj/item/weapon/circuitboard/mecha/gygax/main - sort_string = "NAACA" - -/datum/design/circuit/mecha/gygax_peri - name = "'Gygax' peripherals control" - id = "gygax_peri" - req_tech = list(TECH_DATA = 4) - build_path = /obj/item/weapon/circuitboard/mecha/gygax/peripherals - sort_string = "NAACB" - -/datum/design/circuit/mecha/gygax_targ - name = "'Gygax' weapon control and targeting" - id = "gygax_targ" - req_tech = list(TECH_DATA = 4, TECH_COMBAT = 2) - build_path = /obj/item/weapon/circuitboard/mecha/gygax/targeting - sort_string = "NAACC" - -/datum/design/circuit/mecha/durand_main - name = "'Durand' central control" - id = "durand_main" - req_tech = list(TECH_DATA = 4) - build_path = /obj/item/weapon/circuitboard/mecha/durand/main - sort_string = "NAADA" - -/datum/design/circuit/mecha/durand_peri - name = "'Durand' peripherals control" - id = "durand_peri" - req_tech = list(TECH_DATA = 4) - build_path = /obj/item/weapon/circuitboard/mecha/durand/peripherals - sort_string = "NAADB" - -/datum/design/circuit/mecha/durand_targ - name = "'Durand' weapon control and targeting" - id = "durand_targ" - req_tech = list(TECH_DATA = 4, TECH_COMBAT = 2) - build_path = /obj/item/weapon/circuitboard/mecha/durand/targeting - sort_string = "NAADC" - -/datum/design/circuit/tcom - req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4) - -/datum/design/circuit/tcom/AssembleDesignName() - name = "Telecommunications machinery circuit design ([name])" -/datum/design/circuit/tcom/AssembleDesignDesc() - desc = "Allows for the construction of a telecommunications [name] circuit board." - -/datum/design/circuit/tcom/server - name = "server mainframe" - id = "tcom-server" - build_path = /obj/item/weapon/circuitboard/telecomms/server - sort_string = "PAAAA" - -/datum/design/circuit/tcom/processor - name = "processor unit" - id = "tcom-processor" - build_path = /obj/item/weapon/circuitboard/telecomms/processor - sort_string = "PAAAB" - -/datum/design/circuit/tcom/bus - name = "bus mainframe" - id = "tcom-bus" - build_path = /obj/item/weapon/circuitboard/telecomms/bus - sort_string = "PAAAC" - -/datum/design/circuit/tcom/hub - name = "hub mainframe" - id = "tcom-hub" - build_path = /obj/item/weapon/circuitboard/telecomms/hub - sort_string = "PAAAD" - -/datum/design/circuit/tcom/relay - name = "relay mainframe" - id = "tcom-relay" - req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 4, TECH_BLUESPACE = 3) - build_path = /obj/item/weapon/circuitboard/telecomms/relay - sort_string = "PAAAE" - -/datum/design/circuit/tcom/broadcaster - name = "subspace broadcaster" - id = "tcom-broadcaster" - req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4, TECH_BLUESPACE = 2) - build_path = /obj/item/weapon/circuitboard/telecomms/broadcaster - sort_string = "PAAAF" - -/datum/design/circuit/tcom/receiver - name = "subspace receiver" - id = "tcom-receiver" - req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 3, TECH_BLUESPACE = 2) - build_path = /obj/item/weapon/circuitboard/telecomms/receiver - sort_string = "PAAAG" - -/datum/design/circuit/tcom/exonet_node - name = "exonet node" - id = "tcom-exonet_node" - req_tech = list(TECH_DATA = 5, TECH_ENGINEERING = 5, TECH_BLUESPACE = 4) - build_path = /obj/item/weapon/circuitboard/telecomms/exonet_node - sort_string = "PAAAH" - -/datum/design/circuit/shield - req_tech = list(TECH_BLUESPACE = 4, TECH_PHORON = 3) - materials = list("glass" = 2000, "gold" = 1000) - -/datum/design/circuit/shield/AssembleDesignName() - name = "Shield generator circuit design ([name])" -/datum/design/circuit/shield/AssembleDesignDesc() - if(!desc) - desc = "Allows for the construction of \a [name] shield generator." - -/datum/design/circuit/shield/bubble - name = "bubble" - id = "shield_gen" - build_path = /obj/item/weapon/circuitboard/shield_gen - sort_string = "VAAAA" - -/datum/design/circuit/shield/hull - name = "hull" - id = "shield_gen_ex" - build_path = /obj/item/weapon/circuitboard/shield_gen_ex - sort_string = "VAAAB" - -/datum/design/circuit/shield/capacitor - name = "capacitor" - desc = "Allows for the construction of a shield capacitor circuit board." - id = "shield_cap" - req_tech = list(TECH_MAGNET = 3, TECH_POWER = 4) - build_path = /obj/item/weapon/circuitboard/shield_cap - sort_string = "VAAAC" - -/datum/design/circuit/aicore - name = "AI core" - id = "aicore" - req_tech = list(TECH_DATA = 4, TECH_BIO = 3) - build_path = /obj/item/weapon/circuitboard/aicore - sort_string = "XAAAA" - -/datum/design/aimodule - build_type = IMPRINTER - materials = list("glass" = 2000, "gold" = 100) - -/datum/design/aimodule/AssembleDesignName() - name = "AI module design ([name])" - -/datum/design/aimodule/AssembleDesignDesc() - desc = "Allows for the construction of \a '[name]' AI module." - -/datum/design/aimodule/safeguard - name = "Safeguard" - id = "safeguard" - req_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4) - build_path = /obj/item/weapon/aiModule/safeguard - sort_string = "XABAA" - -/datum/design/aimodule/onehuman - name = "OneCrewMember" - id = "onehuman" - req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 6) - build_path = /obj/item/weapon/aiModule/oneHuman - sort_string = "XABAB" - -/datum/design/aimodule/protectstation - name = "ProtectStation" - id = "protectstation" - req_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6) - build_path = /obj/item/weapon/aiModule/protectStation - sort_string = "XABAC" - -/datum/design/aimodule/notele - name = "TeleporterOffline" - id = "notele" - req_tech = list(TECH_DATA = 3) - build_path = /obj/item/weapon/aiModule/teleporterOffline - sort_string = "XABAD" - -/datum/design/aimodule/quarantine - name = "Quarantine" - id = "quarantine" - req_tech = list(TECH_DATA = 3, TECH_BIO = 2, TECH_MATERIAL = 4) - build_path = /obj/item/weapon/aiModule/quarantine - sort_string = "XABAE" - -/datum/design/aimodule/oxygen - name = "OxygenIsToxicToHumans" - id = "oxygen" - req_tech = list(TECH_DATA = 3, TECH_BIO = 2, TECH_MATERIAL = 4) - build_path = /obj/item/weapon/aiModule/oxygen - sort_string = "XABAF" - -/datum/design/aimodule/freeform - name = "Freeform" - id = "freeform" - req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 4) - build_path = /obj/item/weapon/aiModule/freeform - sort_string = "XABAG" - -/datum/design/aimodule/reset - name = "Reset" - id = "reset" - req_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6) - build_path = /obj/item/weapon/aiModule/reset - sort_string = "XAAAA" - -/datum/design/aimodule/purge - name = "Purge" - id = "purge" - req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 6) - build_path = /obj/item/weapon/aiModule/purge - sort_string = "XAAAB" - -// Core modules -/datum/design/aimodule/core - req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 6) - -/datum/design/aimodule/core/AssembleDesignName() - name = "AI core module design ([name])" - -/datum/design/aimodule/core/AssembleDesignDesc() - desc = "Allows for the construction of \a '[name]' AI core module." - -/datum/design/aimodule/core/freeformcore - name = "Freeform" - id = "freeformcore" - build_path = /obj/item/weapon/aiModule/freeformcore - sort_string = "XACAA" - -/datum/design/aimodule/core/asimov - name = "Asimov" - id = "asimov" - build_path = /obj/item/weapon/aiModule/asimov - sort_string = "XACAB" - -/datum/design/aimodule/core/paladin - name = "P.A.L.A.D.I.N." - id = "paladin" - build_path = /obj/item/weapon/aiModule/paladin - sort_string = "XACAC" - -/datum/design/aimodule/core/tyrant - name = "T.Y.R.A.N.T." - id = "tyrant" - req_tech = list(TECH_DATA = 4, TECH_ILLEGAL = 2, TECH_MATERIAL = 6) - build_path = /obj/item/weapon/aiModule/tyrant - sort_string = "XACAD" - -/datum/design/item/pda - name = "PDA design" - desc = "Cheaper than whiny non-digital assistants." - id = "pda" - req_tech = list(TECH_ENGINEERING = 2, TECH_POWER = 3) - materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) - build_path = /obj/item/device/pda - sort_string = "VAAAA" - -// Cartridges -/datum/design/item/pda_cartridge - req_tech = list(TECH_ENGINEERING = 2, TECH_POWER = 3) - materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) - -/datum/design/item/pda_cartridge/AssembleDesignName() - ..() - name = "PDA accessory ([item_name])" - -/datum/design/item/pda_cartridge/cart_basic - id = "cart_basic" - build_path = /obj/item/weapon/cartridge - sort_string = "VBAAA" - -/datum/design/item/pda_cartridge/engineering - id = "cart_engineering" - build_path = /obj/item/weapon/cartridge/engineering - sort_string = "VBAAB" - -/datum/design/item/pda_cartridge/atmos - id = "cart_atmos" - build_path = /obj/item/weapon/cartridge/atmos - sort_string = "VBAAC" - -/datum/design/item/pda_cartridge/medical - id = "cart_medical" - build_path = /obj/item/weapon/cartridge/medical - sort_string = "VBAAD" - -/datum/design/item/pda_cartridge/chemistry - id = "cart_chemistry" - build_path = /obj/item/weapon/cartridge/chemistry - sort_string = "VBAAE" - -/datum/design/item/pda_cartridge/security - id = "cart_security" - build_path = /obj/item/weapon/cartridge/security - sort_string = "VBAAF" - -/datum/design/item/pda_cartridge/janitor - id = "cart_janitor" - build_path = /obj/item/weapon/cartridge/janitor - sort_string = "VBAAG" - -/datum/design/item/pda_cartridge/science - id = "cart_science" - build_path = /obj/item/weapon/cartridge/signal/science - sort_string = "VBAAH" - -/datum/design/item/pda_cartridge/quartermaster - id = "cart_quartermaster" - build_path = /obj/item/weapon/cartridge/quartermaster - sort_string = "VBAAI" - -/datum/design/item/pda_cartridge/hop - id = "cart_hop" - build_path = /obj/item/weapon/cartridge/hop - sort_string = "VBAAJ" - -/datum/design/item/pda_cartridge/hos - id = "cart_hos" - build_path = /obj/item/weapon/cartridge/hos - sort_string = "VBAAK" - -/datum/design/item/pda_cartridge/ce - id = "cart_ce" - build_path = /obj/item/weapon/cartridge/ce - sort_string = "VBAAL" - -/datum/design/item/pda_cartridge/cmo - id = "cart_cmo" - build_path = /obj/item/weapon/cartridge/cmo - sort_string = "VBAAM" - -/datum/design/item/pda_cartridge/rd - id = "cart_rd" - build_path = /obj/item/weapon/cartridge/rd - sort_string = "VBAAN" - -/datum/design/item/pda_cartridge/captain - id = "cart_captain" - build_path = /obj/item/weapon/cartridge/captain - sort_string = "VBAAO" - - - -/datum/design/item/wirer - name = "Custom wirer tool" - id = "wirer" - req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2) - materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 2500) - build_path = /obj/item/device/integrated_electronics/wirer - sort_string = "VBVAA" - -/datum/design/item/debugger - name = "Custom circuit debugger tool" - id = "debugger" - req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2) - materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 2500) - build_path = /obj/item/device/integrated_electronics/debugger - sort_string = "VBVAB" - - - -/datum/design/item/custom_circuit_assembly - name = "Small custom assembly" - desc = "A customizable assembly for simple, small devices." - id = "assembly-small" - req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 2, TECH_POWER = 2) - materials = list(DEFAULT_WALL_MATERIAL = 10000) - build_path = /obj/item/device/electronic_assembly - sort_string = "VCAAA" - -/datum/design/item/custom_circuit_assembly/medium - name = "Medium custom assembly" - desc = "A customizable assembly suited for more ambitious mechanisms." - id = "assembly-medium" - req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3, TECH_POWER = 3) - materials = list(DEFAULT_WALL_MATERIAL = 20000) - build_path = /obj/item/device/electronic_assembly/medium - sort_string = "VCAAB" - -/datum/design/item/custom_circuit_assembly/drone - name = "Drone custom assembly" - desc = "A customizable assembly optimized for autonomous devices." - id = "assembly-drone" - req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) - materials = list(DEFAULT_WALL_MATERIAL = 30000) - build_path = /obj/item/device/electronic_assembly/drone - sort_string = "VCAAC" - -/datum/design/item/custom_circuit_assembly/large - name = "Large custom assembly" - desc = "A customizable assembly for large machines." - id = "assembly-large" - req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 4) - materials = list(DEFAULT_WALL_MATERIAL = 40000) - build_path = /obj/item/device/electronic_assembly/large - sort_string = "VCAAD" - -/datum/design/item/custom_circuit_assembly/implant - name = "Implant custom assembly" - desc = "An customizable assembly for very small devices, implanted into living entities." - id = "assembly-implant" - req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 3, TECH_BIO = 5) - materials = list(DEFAULT_WALL_MATERIAL = 2000) - build_path = /obj/item/weapon/implant/integrated_circuit - sort_string = "VCAAE" - -/datum/design/item/custom_circuit_assembly/device - name = "Device custom assembly" - desc = "An customizable assembly designed to interface with other devices." - id = "assembly-device" - req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2, TECH_POWER = 2) - materials = list(DEFAULT_WALL_MATERIAL = 5000) - build_path = /obj/item/device/assembly/electronic_assembly - sort_string = "VCAAF" - -/datum/design/item/custom_circuit_printer - name = "Portable integrated circuit printer" - desc = "A portable(ish) printer for modular machines." - id = "ic_printer" - req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 4, TECH_DATA = 5) - materials = list(DEFAULT_WALL_MATERIAL = 10000) - build_path = /obj/item/device/integrated_circuit_printer - sort_string = "VCAAG" - -/datum/design/item/custom_circuit_printer_upgrade - name = "Integrated circuit printer upgrade - advanced designs" - desc = "Allows the integrated circuit printer to create advanced circuits" - id = "ic_printer_upgrade_adv" - req_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 4) - materials = list(DEFAULT_WALL_MATERIAL = 2000) - build_path = /obj/item/weapon/disk/integrated_circuit/upgrade/advanced - sort_string = "VCAAH" - -/datum/design/item/translator - name = "handheld translator" - id = "translator" - req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3) - materials = list(DEFAULT_WALL_MATERIAL = 3000, "glass" = 3000) - build_path = /obj/item/device/universal_translator - sort_string = "HABQA" - -/datum/design/item/ear_translator - name = "earpiece translator" - id = "ear_translator" - req_tech = list(TECH_DATA = 5, TECH_ENGINEERING = 5) //It's been hella miniaturized. - materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 2000, "gold" = 1000) - build_path = /obj/item/device/universal_translator/ear - sort_string = "HABQB" - -/datum/design/item/xenoarch_multi_tool - name = "xenoarcheology multitool" - id = "xenoarch_multitool" - req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 3, TECH_BLUESPACE = 3) - build_path = /obj/item/device/xenoarch_multi_tool - materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "uranium" = 500, "phoron" = 500) - sort_string = "HABQC" - -/datum/design/item/excavationdrill - name = "Excavation Drill" - id = "excavationdrill" - req_tech = list(TECH_MATERIAL = 3, TECH_POWER = 2, TECH_ENGINEERING = 2, TECH_BLUESPACE = 3) - build_type = PROTOLATHE - materials = list(DEFAULT_WALL_MATERIAL = 4000, "glass" = 4000) - build_path = /obj/item/weapon/pickaxe/excavationdrill - sort_string = "HABQD" - -/* Uncomment if someone makes these buildable -/datum/design/circuit/general_alert - name = "general alert console" - id = "general_alert" - build_path = /obj/item/weapon/circuitboard/general_alert - -// Removal of loyalty implants. Can't think of a way to add this to the config option. -/datum/design/item/implant/loyalty - name = "loyalty" - id = "implant_loyal" - req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3) - materials = list(DEFAULT_WALL_MATERIAL = 7000, "glass" = 7000) - build_path = /obj/item/weapon/implantcase/loyalty" - -/datum/design/rust_core_control - name = "Circuit Design (RUST core controller)" - desc = "Allows for the construction of circuit boards used to build a core control console for the RUST fusion engine." - id = "rust_core_control" - req_tech = list("programming" = 4, "engineering" = 4) - build_type = IMPRINTER - materials = list("glass" = 2000, "sacid" = 20) - build_path = "/obj/item/weapon/circuitboard/rust_core_control" - -datum/design/rust_fuel_control - name = "Circuit Design (RUST fuel controller)" - desc = "Allows for the construction of circuit boards used to build a fuel injector control console for the RUST fusion engine." - id = "rust_fuel_control" - req_tech = list("programming" = 4, "engineering" = 4) - build_type = IMPRINTER - materials = list("glass" = 2000, "sacid" = 20) - build_path = "/obj/item/weapon/circuitboard/rust_fuel_control" - -datum/design/rust_fuel_port - name = "Internal circuitry (RUST fuel port)" - desc = "Allows for the construction of circuit boards used to build a fuel injection port for the RUST fusion engine." - id = "rust_fuel_port" - req_tech = list("engineering" = 4, "materials" = 5) - build_type = IMPRINTER - materials = list("glass" = 2000, "sacid" = 20, "uranium" = 3000) - build_path = "/obj/item/weapon/module/rust_fuel_port" - -datum/design/rust_fuel_compressor - name = "Circuit Design (RUST fuel compressor)" - desc = "Allows for the construction of circuit boards used to build a fuel compressor of the RUST fusion engine." - id = "rust_fuel_compressor" - req_tech = list("materials" = 6, "phorontech" = 4) - build_type = IMPRINTER - materials = list("glass" = 2000, "sacid" = 20, "phoron" = 3000, "diamond" = 1000) - build_path = "/obj/item/weapon/module/rust_fuel_compressor" - -datum/design/rust_core - name = "Internal circuitry (RUST tokamak core)" - desc = "The circuit board that for a RUST-pattern tokamak fusion core." - id = "pacman" - req_tech = list(bluespace = 3, phorontech = 4, magnets = 5, powerstorage = 6) - build_type = IMPRINTER - materials = list("glass" = 2000, "sacid" = 20, "phoron" = 3000, "diamond" = 2000) - build_path = "/obj/item/weapon/circuitboard/rust_core" - -datum/design/rust_injector - name = "Internal circuitry (RUST tokamak core)" - desc = "The circuit board that for a RUST-pattern particle accelerator." - id = "pacman" - req_tech = list(powerstorage = 3, engineering = 4, phorontech = 4, materials = 6) - build_type = IMPRINTER - materials = list("glass" = 2000, "sacid" = 20, "phoron" = 3000, "uranium" = 2000) - build_path = "/obj/item/weapon/circuitboard/rust_core" -*/ + sort_string = "GAAAB" \ No newline at end of file diff --git a/code/modules/research/designs/ai_modules.dm b/code/modules/research/designs/ai_modules.dm new file mode 100644 index 00000000000..eae26ea3865 --- /dev/null +++ b/code/modules/research/designs/ai_modules.dm @@ -0,0 +1,117 @@ +/datum/design/aimodule + build_type = IMPRINTER + materials = list("glass" = 2000, "gold" = 100) + +/datum/design/aimodule/AssembleDesignName() + name = "AI module design ([name])" + +/datum/design/aimodule/AssembleDesignDesc() + desc = "Allows for the construction of \a '[name]' AI module." + +/datum/design/aimodule/safeguard + name = "Safeguard" + id = "safeguard" + req_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4) + build_path = /obj/item/weapon/aiModule/safeguard + sort_string = "XABAA" + +/datum/design/aimodule/onehuman + name = "OneCrewMember" + id = "onehuman" + req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 6) + build_path = /obj/item/weapon/aiModule/oneHuman + sort_string = "XABAB" + +/datum/design/aimodule/protectstation + name = "ProtectStation" + id = "protectstation" + req_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6) + build_path = /obj/item/weapon/aiModule/protectStation + sort_string = "XABAC" + +/datum/design/aimodule/notele + name = "TeleporterOffline" + id = "notele" + req_tech = list(TECH_DATA = 3) + build_path = /obj/item/weapon/aiModule/teleporterOffline + sort_string = "XABAD" + +/datum/design/aimodule/quarantine + name = "Quarantine" + id = "quarantine" + req_tech = list(TECH_DATA = 3, TECH_BIO = 2, TECH_MATERIAL = 4) + build_path = /obj/item/weapon/aiModule/quarantine + sort_string = "XABAE" + +/datum/design/aimodule/oxygen + name = "OxygenIsToxicToHumans" + id = "oxygen" + req_tech = list(TECH_DATA = 3, TECH_BIO = 2, TECH_MATERIAL = 4) + build_path = /obj/item/weapon/aiModule/oxygen + sort_string = "XABAF" + +/datum/design/aimodule/freeform + name = "Freeform" + id = "freeform" + req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 4) + build_path = /obj/item/weapon/aiModule/freeform + sort_string = "XABAG" + +/datum/design/aimodule/reset + name = "Reset" + id = "reset" + req_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6) + build_path = /obj/item/weapon/aiModule/reset + sort_string = "XAAAZ" // Duplicate string, really need to redo this whole thing + +/datum/design/aimodule/purge + name = "Purge" + id = "purge" + req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 6) + build_path = /obj/item/weapon/aiModule/purge + sort_string = "XAAAB" + +// Core modules +/datum/design/aimodule/core + req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 6) + +/datum/design/aimodule/core/AssembleDesignName() + name = "AI core module design ([name])" + +/datum/design/aimodule/core/AssembleDesignDesc() + desc = "Allows for the construction of \a '[name]' AI core module." + +/datum/design/aimodule/core/freeformcore + name = "Freeform" + id = "freeformcore" + build_path = /obj/item/weapon/aiModule/freeformcore + sort_string = "XACAA" + +/datum/design/aimodule/core/asimov + name = "Asimov" + id = "asimov" + build_path = /obj/item/weapon/aiModule/asimov + sort_string = "XACAB" + +/datum/design/aimodule/core/paladin + name = "P.A.L.A.D.I.N." + id = "paladin" + build_path = /obj/item/weapon/aiModule/paladin + sort_string = "XACAC" + +/datum/design/aimodule/core/tyrant + name = "T.Y.R.A.N.T." + id = "tyrant" + req_tech = list(TECH_DATA = 4, TECH_ILLEGAL = 2, TECH_MATERIAL = 6) + build_path = /obj/item/weapon/aiModule/tyrant + sort_string = "XACAD" + +// AI file, AI tool +/datum/design/item/intellicard + name = "'intelliCore', AI preservation and transportation system" + desc = "Allows for the construction of an intelliCore." + id = "intellicore" + req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 4) + materials = list("glass" = 1000, "gold" = 200) + build_path = /obj/item/device/aicard + sort_string = "VACAA" \ No newline at end of file diff --git a/code/modules/research/designs/circuit_assembly.dm b/code/modules/research/designs/circuit_assembly.dm new file mode 100644 index 00000000000..9f20032445c --- /dev/null +++ b/code/modules/research/designs/circuit_assembly.dm @@ -0,0 +1,89 @@ +/datum/design/item/wirer + name = "Custom wirer tool" + id = "wirer" + req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2) + materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 2500) + build_path = /obj/item/device/integrated_electronics/wirer + sort_string = "VBVAA" + +/datum/design/item/debugger + name = "Custom circuit debugger tool" + id = "debugger" + req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2) + materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 2500) + build_path = /obj/item/device/integrated_electronics/debugger + sort_string = "VBVAB" + + + +/datum/design/item/custom_circuit_assembly + name = "Small custom assembly" + desc = "A customizable assembly for simple, small devices." + id = "assembly-small" + req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 2, TECH_POWER = 2) + materials = list(DEFAULT_WALL_MATERIAL = 10000) + build_path = /obj/item/device/electronic_assembly + sort_string = "VCAAA" + +/datum/design/item/custom_circuit_assembly/medium + name = "Medium custom assembly" + desc = "A customizable assembly suited for more ambitious mechanisms." + id = "assembly-medium" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3, TECH_POWER = 3) + materials = list(DEFAULT_WALL_MATERIAL = 20000) + build_path = /obj/item/device/electronic_assembly/medium + sort_string = "VCAAB" + +/datum/design/item/custom_circuit_assembly/drone + name = "Drone custom assembly" + desc = "A customizable assembly optimized for autonomous devices." + id = "assembly-drone" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) + materials = list(DEFAULT_WALL_MATERIAL = 30000) + build_path = /obj/item/device/electronic_assembly/drone + sort_string = "VCAAC" + +/datum/design/item/custom_circuit_assembly/large + name = "Large custom assembly" + desc = "A customizable assembly for large machines." + id = "assembly-large" + req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 4) + materials = list(DEFAULT_WALL_MATERIAL = 40000) + build_path = /obj/item/device/electronic_assembly/large + sort_string = "VCAAD" + +/datum/design/item/custom_circuit_assembly/implant + name = "Implant custom assembly" + desc = "An customizable assembly for very small devices, implanted into living entities." + id = "assembly-implant" + req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 3, TECH_BIO = 5) + materials = list(DEFAULT_WALL_MATERIAL = 2000) + build_path = /obj/item/weapon/implant/integrated_circuit + sort_string = "VCAAE" + +/datum/design/item/custom_circuit_assembly/device + name = "Device custom assembly" + desc = "An customizable assembly designed to interface with other devices." + id = "assembly-device" + req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2, TECH_POWER = 2) + materials = list(DEFAULT_WALL_MATERIAL = 5000) + build_path = /obj/item/device/assembly/electronic_assembly + sort_string = "VCAAF" + +/datum/design/item/custom_circuit_printer + name = "Portable integrated circuit printer" + desc = "A portable(ish) printer for modular machines." + id = "ic_printer" + req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 4, TECH_DATA = 5) + materials = list(DEFAULT_WALL_MATERIAL = 10000) + build_path = /obj/item/device/integrated_circuit_printer + sort_string = "VCAAG" + +/datum/design/item/custom_circuit_printer_upgrade + name = "Integrated circuit printer upgrade - advanced designs" + desc = "Allows the integrated circuit printer to create advanced circuits" + id = "ic_printer_upgrade_adv" + req_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 4) + materials = list(DEFAULT_WALL_MATERIAL = 2000) + build_path = /obj/item/weapon/disk/integrated_circuit/upgrade/advanced + sort_string = "VCAAH" \ No newline at end of file diff --git a/code/modules/research/designs/circuits.dm b/code/modules/research/designs/circuits.dm new file mode 100644 index 00000000000..e00a47786d1 --- /dev/null +++ b/code/modules/research/designs/circuits.dm @@ -0,0 +1,597 @@ +/* +CIRCUITS BELOW +*/ + +/datum/design/circuit + build_type = IMPRINTER + req_tech = list(TECH_DATA = 2) + materials = list("glass" = 2000) + chemicals = list("sacid" = 20) + time = 5 + +/datum/design/circuit/AssembleDesignName() + ..() + if(build_path) + var/obj/item/weapon/circuitboard/C = build_path + if(initial(C.board_type) == "machine") + name = "Machine circuit design ([item_name])" + else if(initial(C.board_type) == "computer") + name = "Computer circuit design ([item_name])" + else + name = "Circuit design ([item_name])" + +/datum/design/circuit/AssembleDesignDesc() + if(!desc) + desc = "Allows for the construction of \a [item_name] circuit board." + +/datum/design/circuit/arcademachine + name = "battle arcade machine" + id = "arcademachine" + req_tech = list(TECH_DATA = 1) + build_path = /obj/item/weapon/circuitboard/arcade/battle + sort_string = "MAAAA" + +/datum/design/circuit/oriontrail + name = "orion trail arcade machine" + id = "oriontrail" + req_tech = list(TECH_DATA = 1) + build_path = /obj/item/weapon/circuitboard/arcade/orion_trail + sort_string = "MAAAZ" // Duplicate string, really need to redo this whole thing + +/datum/design/circuit/jukebox + name = "jukebox" + id = "jukebox" + req_tech = list(TECH_MAGNET = 2, TECH_DATA = 1) + build_path = /obj/item/weapon/circuitboard/jukebox + sort_string = "MAAAB" + +/datum/design/circuit/seccamera + name = "security camera monitor" + id = "seccamera" + build_path = /obj/item/weapon/circuitboard/security + sort_string = "DAAAZ" // Duplicate string, really need to redo this whole thing + +/datum/design/circuit/secdata + name = "security records console" + id = "sec_data" + build_path = /obj/item/weapon/circuitboard/secure_data + sort_string = "DABAA" + +/datum/design/circuit/prisonmanage + name = "prisoner management console" + id = "prisonmanage" + build_path = /obj/item/weapon/circuitboard/prisoner + sort_string = "DACAA" + +/datum/design/circuit/med_data + name = "medical records console" + id = "med_data" + build_path = /obj/item/weapon/circuitboard/med_data + sort_string = "FAAAA" + +/datum/design/circuit/operating + name = "patient monitoring console" + id = "operating" + build_path = /obj/item/weapon/circuitboard/operating + sort_string = "FACAA" + +/datum/design/circuit/scan_console + name = "DNA machine" + id = "scan_console" + build_path = /obj/item/weapon/circuitboard/scan_consolenew + sort_string = "FAGAA" + +/datum/design/circuit/clonecontrol + name = "cloning control console" + id = "clonecontrol" + req_tech = list(TECH_DATA = 3, TECH_BIO = 3) + build_path = /obj/item/weapon/circuitboard/cloning + sort_string = "FAGAC" + +/datum/design/circuit/clonepod + name = "clone pod" + id = "clonepod" + req_tech = list(TECH_DATA = 3, TECH_BIO = 3) + build_path = /obj/item/weapon/circuitboard/clonepod + sort_string = "FAGAE" + +/datum/design/circuit/clonescanner + name = "cloning scanner" + id = "clonescanner" + req_tech = list(TECH_DATA = 3, TECH_BIO = 3) + build_path = /obj/item/weapon/circuitboard/clonescanner + sort_string = "FAGAG" + +/datum/design/circuit/crewconsole + name = "crew monitoring console" + id = "crewconsole" + req_tech = list(TECH_DATA = 3, TECH_MAGNET = 2, TECH_BIO = 2) + build_path = /obj/item/weapon/circuitboard/crew + sort_string = "FAGAI" + +/datum/design/circuit/teleconsole + name = "teleporter control console" + id = "teleconsole" + req_tech = list(TECH_DATA = 3, TECH_BLUESPACE = 2) + build_path = /obj/item/weapon/circuitboard/teleporter + sort_string = "HAAAA" + +/datum/design/circuit/robocontrol + name = "robotics control console" + id = "robocontrol" + req_tech = list(TECH_DATA = 4) + build_path = /obj/item/weapon/circuitboard/robotics + sort_string = "HAAAB" + +/datum/design/circuit/mechacontrol + name = "exosuit control console" + id = "mechacontrol" + req_tech = list(TECH_DATA = 3) + build_path = /obj/item/weapon/circuitboard/mecha_control + sort_string = "HAAAC" + +/datum/design/circuit/rdconsole + name = "R&D control console" + id = "rdconsole" + req_tech = list(TECH_DATA = 4) + build_path = /obj/item/weapon/circuitboard/rdconsole + sort_string = "HAAAE" + +/datum/design/circuit/aifixer + name = "AI integrity restorer" + id = "aifixer" + req_tech = list(TECH_DATA = 3, TECH_BIO = 2) + build_path = /obj/item/weapon/circuitboard/aifixer + sort_string = "HAAAF" + +/datum/design/circuit/comm_monitor + name = "telecommunications monitoring console" + id = "comm_monitor" + req_tech = list(TECH_DATA = 3) + build_path = /obj/item/weapon/circuitboard/comm_monitor + sort_string = "HAACA" + +/datum/design/circuit/comm_server + name = "telecommunications server monitoring console" + id = "comm_server" + req_tech = list(TECH_DATA = 3) + build_path = /obj/item/weapon/circuitboard/comm_server + sort_string = "HAACB" + +/datum/design/circuit/message_monitor + name = "messaging monitor console" + id = "message_monitor" + req_tech = list(TECH_DATA = 5) + build_path = /obj/item/weapon/circuitboard/message_monitor + sort_string = "HAACC" + +/datum/design/circuit/aiupload + name = "AI upload console" + id = "aiupload" + req_tech = list(TECH_DATA = 4) + build_path = /obj/item/weapon/circuitboard/aiupload + sort_string = "HAABA" + +/datum/design/circuit/borgupload + name = "cyborg upload console" + id = "borgupload" + req_tech = list(TECH_DATA = 4) + build_path = /obj/item/weapon/circuitboard/borgupload + sort_string = "HAABB" + +/datum/design/circuit/destructive_analyzer + name = "destructive analyzer" + id = "destructive_analyzer" + req_tech = list(TECH_DATA = 2, TECH_MAGNET = 2, TECH_ENGINEERING = 2) + build_path = /obj/item/weapon/circuitboard/destructive_analyzer + sort_string = "HABAA" + +/datum/design/circuit/protolathe + name = "protolathe" + id = "protolathe" + req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2) + build_path = /obj/item/weapon/circuitboard/protolathe + sort_string = "HABAB" + +/datum/design/circuit/circuit_imprinter + name = "circuit imprinter" + id = "circuit_imprinter" + req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2) + build_path = /obj/item/weapon/circuitboard/circuit_imprinter + sort_string = "HABAC" + +/datum/design/circuit/autolathe + name = "autolathe board" + id = "autolathe" + req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2) + build_path = /obj/item/weapon/circuitboard/autolathe + sort_string = "HABAD" + +/datum/design/circuit/rdservercontrol + name = "R&D server control console" + id = "rdservercontrol" + req_tech = list(TECH_DATA = 3) + build_path = /obj/item/weapon/circuitboard/rdservercontrol + sort_string = "HABBA" + +/datum/design/circuit/rdserver + name = "R&D server" + id = "rdserver" + req_tech = list(TECH_DATA = 3) + build_path = /obj/item/weapon/circuitboard/rdserver + sort_string = "HABBB" + +/datum/design/circuit/mechfab + name = "exosuit fabricator" + id = "mechfab" + req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3) + build_path = /obj/item/weapon/circuitboard/mechfab + sort_string = "HABAE" + +/datum/design/circuit/prosfab + name = "prosthetics fabricator" + id = "prosfab" + req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3) + build_path = /obj/item/weapon/circuitboard/prosthetics + sort_string = "HABAF" + +/datum/design/circuit/mech_recharger + name = "mech recharger" + id = "mech_recharger" + req_tech = list(TECH_DATA = 2, TECH_POWER = 2, TECH_ENGINEERING = 2) + build_path = /obj/item/weapon/circuitboard/mech_recharger + sort_string = "HACAA" + +/datum/design/circuit/recharge_station + name = "cyborg recharge station" + id = "recharge_station" + req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 2) + build_path = /obj/item/weapon/circuitboard/recharge_station + sort_string = "HACAC" + +/datum/design/circuit/atmosalerts + name = "atmosphere alert console" + id = "atmosalerts" + build_path = /obj/item/weapon/circuitboard/atmos_alert + sort_string = "JAAAA" + +/datum/design/circuit/air_management + name = "atmosphere monitoring console" + id = "air_management" + build_path = /obj/item/weapon/circuitboard/air_management + sort_string = "JAAAB" + +/datum/design/circuit/rcon_console + name = "RCON remote control console" + id = "rcon_console" + req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 3, TECH_POWER = 5) + build_path = /obj/item/weapon/circuitboard/rcon_console + sort_string = "JAAAC" + +/datum/design/circuit/dronecontrol + name = "drone control console" + id = "dronecontrol" + req_tech = list(TECH_DATA = 4) + build_path = /obj/item/weapon/circuitboard/drone_control + sort_string = "JAAAD" + +/datum/design/circuit/powermonitor + name = "power monitoring console" + id = "powermonitor" + build_path = /obj/item/weapon/circuitboard/powermonitor + sort_string = "JAAAE" + +/datum/design/circuit/solarcontrol + name = "solar control console" + id = "solarcontrol" + build_path = /obj/item/weapon/circuitboard/solar_control + sort_string = "JAAAF" + +/datum/design/circuit/pacman + name = "PACMAN-type generator" + id = "pacman" + req_tech = list(TECH_DATA = 3, TECH_PHORON = 3, TECH_POWER = 3, TECH_ENGINEERING = 3) + build_path = /obj/item/weapon/circuitboard/pacman + sort_string = "JBAAA" + +/datum/design/circuit/superpacman + name = "SUPERPACMAN-type generator" + id = "superpacman" + req_tech = list(TECH_DATA = 3, TECH_POWER = 4, TECH_ENGINEERING = 4) + build_path = /obj/item/weapon/circuitboard/pacman/super + sort_string = "JBAAB" + +/datum/design/circuit/mrspacman + name = "MRSPACMAN-type generator" + id = "mrspacman" + req_tech = list(TECH_DATA = 3, TECH_POWER = 5, TECH_ENGINEERING = 5) + build_path = /obj/item/weapon/circuitboard/pacman/mrs + sort_string = "JBAAC" + +/datum/design/circuit/batteryrack + name = "cell rack PSU" + id = "batteryrack" + req_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 2) + build_path = /obj/item/weapon/circuitboard/batteryrack + sort_string = "JBABA" + +/datum/design/circuit/smes_cell + name = "'SMES' superconductive magnetic energy storage" + desc = "Allows for the construction of circuit boards used to build a SMES." + id = "smes_cell" + req_tech = list(TECH_POWER = 7, TECH_ENGINEERING = 5) + build_path = /obj/item/weapon/circuitboard/smes + sort_string = "JBABB" + +/datum/design/circuit/grid_checker + name = "power grid checker" + desc = "Allows for the construction of circuit boards used to build a grid checker." + id = "grid_checker" + req_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 3) + build_path = /obj/item/weapon/circuitboard/grid_checker + sort_string = "JBABC" + +/datum/design/circuit/breakerbox + name = "breaker box" + desc = "Allows for the construction of circuit boards used to build a breaker box." + id = "breakerbox" + req_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3) + build_path = /obj/item/weapon/circuitboard/breakerbox + sort_string = "JBABD" + +/datum/design/circuit/gas_heater + name = "gas heating system" + id = "gasheater" + req_tech = list(TECH_POWER = 2, TECH_ENGINEERING = 1) + build_path = /obj/item/weapon/circuitboard/unary_atmos/heater + sort_string = "JCAAA" + +/datum/design/circuit/gas_cooler + name = "gas cooling system" + id = "gascooler" + req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2) + build_path = /obj/item/weapon/circuitboard/unary_atmos/cooler + sort_string = "JCAAB" + +/datum/design/circuit/secure_airlock + name = "secure airlock electronics" + desc = "Allows for the construction of a tamper-resistant airlock electronics." + id = "securedoor" + req_tech = list(TECH_DATA = 3) + build_path = /obj/item/weapon/airlock_electronics/secure + sort_string = "JDAAA" + +/datum/design/circuit/ordercomp + name = "supply ordering console" + id = "ordercomp" + build_path = /obj/item/weapon/circuitboard/ordercomp + sort_string = "KAAAY" // Duplicate string, really need to redo this whole thing + +/datum/design/circuit/supplycomp + name = "supply control console" + id = "supplycomp" + req_tech = list(TECH_DATA = 3) + build_path = /obj/item/weapon/circuitboard/supplycomp + sort_string = "KAAAZ" // Duplicate string, really need to redo this whole thing + +/datum/design/circuit/biogenerator + name = "biogenerator" + id = "biogenerator" + req_tech = list(TECH_DATA = 2) + build_path = /obj/item/weapon/circuitboard/biogenerator + sort_string = "KBAAA" + +/datum/design/circuit/miningdrill + name = "mining drill head" + id = "mining drill head" + req_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1) + build_path = /obj/item/weapon/circuitboard/miningdrill + sort_string = "KCAAA" + +/datum/design/circuit/miningdrillbrace + name = "mining drill brace" + id = "mining drill brace" + req_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1) + build_path = /obj/item/weapon/circuitboard/miningdrillbrace + sort_string = "KCAAB" + +/datum/design/circuit/comconsole + name = "communications console" + id = "comconsole" + build_path = /obj/item/weapon/circuitboard/communications + sort_string = "LAAAA" + +/datum/design/circuit/idcardconsole + name = "ID card modification console" + id = "idcardconsole" + build_path = /obj/item/weapon/circuitboard/card + sort_string = "LAAAB" + +/datum/design/circuit/emp_data + name = "employment records console" + id = "emp_data" + build_path = /obj/item/weapon/circuitboard/skills + sort_string = "LAAAC" + +/datum/design/circuit/mecha + req_tech = list(TECH_DATA = 3) + +/datum/design/circuit/mecha/AssembleDesignName() + name = "Exosuit module circuit design ([name])" +/datum/design/circuit/mecha/AssembleDesignDesc() + desc = "Allows for the construction of \a [name] module." + +/datum/design/circuit/mecha/ripley_main + name = "APLU 'Ripley' central control" + id = "ripley_main" + build_path = /obj/item/weapon/circuitboard/mecha/ripley/main + sort_string = "NAAAA" + +/datum/design/circuit/mecha/ripley_peri + name = "APLU 'Ripley' peripherals control" + id = "ripley_peri" + build_path = /obj/item/weapon/circuitboard/mecha/ripley/peripherals + sort_string = "NAAAB" + +/datum/design/circuit/mecha/odysseus_main + name = "'Odysseus' central control" + id = "odysseus_main" + req_tech = list(TECH_DATA = 3,TECH_BIO = 2) + build_path = /obj/item/weapon/circuitboard/mecha/odysseus/main + sort_string = "NAABA" + +/datum/design/circuit/mecha/odysseus_peri + name = "'Odysseus' peripherals control" + id = "odysseus_peri" + req_tech = list(TECH_DATA = 3,TECH_BIO = 2) + build_path = /obj/item/weapon/circuitboard/mecha/odysseus/peripherals + sort_string = "NAABB" + +/datum/design/circuit/mecha/gygax_main + name = "'Gygax' central control" + id = "gygax_main" + req_tech = list(TECH_DATA = 4) + build_path = /obj/item/weapon/circuitboard/mecha/gygax/main + sort_string = "NAACA" + +/datum/design/circuit/mecha/gygax_peri + name = "'Gygax' peripherals control" + id = "gygax_peri" + req_tech = list(TECH_DATA = 4) + build_path = /obj/item/weapon/circuitboard/mecha/gygax/peripherals + sort_string = "NAACB" + +/datum/design/circuit/mecha/gygax_targ + name = "'Gygax' weapon control and targeting" + id = "gygax_targ" + req_tech = list(TECH_DATA = 4, TECH_COMBAT = 2) + build_path = /obj/item/weapon/circuitboard/mecha/gygax/targeting + sort_string = "NAACC" + +/datum/design/circuit/mecha/durand_main + name = "'Durand' central control" + id = "durand_main" + req_tech = list(TECH_DATA = 4) + build_path = /obj/item/weapon/circuitboard/mecha/durand/main + sort_string = "NAADA" + +/datum/design/circuit/mecha/durand_peri + name = "'Durand' peripherals control" + id = "durand_peri" + req_tech = list(TECH_DATA = 4) + build_path = /obj/item/weapon/circuitboard/mecha/durand/peripherals + sort_string = "NAADB" + +/datum/design/circuit/mecha/durand_targ + name = "'Durand' weapon control and targeting" + id = "durand_targ" + req_tech = list(TECH_DATA = 4, TECH_COMBAT = 2) + build_path = /obj/item/weapon/circuitboard/mecha/durand/targeting + sort_string = "NAADC" + +/datum/design/circuit/tcom + req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4) + +/datum/design/circuit/tcom/AssembleDesignName() + name = "Telecommunications machinery circuit design ([name])" +/datum/design/circuit/tcom/AssembleDesignDesc() + desc = "Allows for the construction of a telecommunications [name] circuit board." + +/datum/design/circuit/tcom/server + name = "server mainframe" + id = "tcom-server" + build_path = /obj/item/weapon/circuitboard/telecomms/server + sort_string = "PAAAA" + +/datum/design/circuit/tcom/processor + name = "processor unit" + id = "tcom-processor" + build_path = /obj/item/weapon/circuitboard/telecomms/processor + sort_string = "PAAAB" + +/datum/design/circuit/tcom/bus + name = "bus mainframe" + id = "tcom-bus" + build_path = /obj/item/weapon/circuitboard/telecomms/bus + sort_string = "PAAAC" + +/datum/design/circuit/tcom/hub + name = "hub mainframe" + id = "tcom-hub" + build_path = /obj/item/weapon/circuitboard/telecomms/hub + sort_string = "PAAAD" + +/datum/design/circuit/tcom/relay + name = "relay mainframe" + id = "tcom-relay" + req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 4, TECH_BLUESPACE = 3) + build_path = /obj/item/weapon/circuitboard/telecomms/relay + sort_string = "PAAAE" + +/datum/design/circuit/tcom/broadcaster + name = "subspace broadcaster" + id = "tcom-broadcaster" + req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4, TECH_BLUESPACE = 2) + build_path = /obj/item/weapon/circuitboard/telecomms/broadcaster + sort_string = "PAAAF" + +/datum/design/circuit/tcom/receiver + name = "subspace receiver" + id = "tcom-receiver" + req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 3, TECH_BLUESPACE = 2) + build_path = /obj/item/weapon/circuitboard/telecomms/receiver + sort_string = "PAAAG" + +/datum/design/circuit/tcom/exonet_node + name = "exonet node" + id = "tcom-exonet_node" + req_tech = list(TECH_DATA = 5, TECH_ENGINEERING = 5, TECH_BLUESPACE = 4) + build_path = /obj/item/weapon/circuitboard/telecomms/exonet_node + sort_string = "PAAAH" + +/datum/design/circuit/shield + req_tech = list(TECH_BLUESPACE = 4, TECH_PHORON = 3) + materials = list("glass" = 2000, "gold" = 1000) + +/datum/design/circuit/shield/AssembleDesignName() + name = "Shield generator circuit design ([name])" +/datum/design/circuit/shield/AssembleDesignDesc() + if(!desc) + desc = "Allows for the construction of \a [name] shield generator." + +/datum/design/circuit/shield/bubble + name = "bubble" + id = "shield_gen" + build_path = /obj/item/weapon/circuitboard/shield_gen + sort_string = "VAAAZ" // Duplicate string, really need to redo this whole thing + +/datum/design/circuit/shield/hull + name = "hull" + id = "shield_gen_ex" + build_path = /obj/item/weapon/circuitboard/shield_gen_ex + sort_string = "VAAAB" + +/datum/design/circuit/shield/capacitor + name = "capacitor" + desc = "Allows for the construction of a shield capacitor circuit board." + id = "shield_cap" + req_tech = list(TECH_MAGNET = 3, TECH_POWER = 4) + build_path = /obj/item/weapon/circuitboard/shield_cap + sort_string = "VAAAC" + +/datum/design/circuit/aicore + name = "AI core" + id = "aicore" + req_tech = list(TECH_DATA = 4, TECH_BIO = 3) + build_path = /obj/item/weapon/circuitboard/aicore + sort_string = "XAAAA" + + +/* I have no idea how this was even running before, but it doesn't seem to be necessary. +/////////////////////////////////// +/////////Shield Generators///////// +/////////////////////////////////// +/datum/design/circuit/shield + req_tech = list(TECH_BLUESPACE = 4, TECH_PHORON = 3) + materials = list("$glass" = 2000, "sacid" = 20, "$phoron" = 10000, "$diamond" = 5000, "$gold" = 10000) +*/ \ No newline at end of file diff --git a/code/modules/research/designs/illegal.dm b/code/modules/research/designs/illegal.dm new file mode 100644 index 00000000000..1542e929b67 --- /dev/null +++ b/code/modules/research/designs/illegal.dm @@ -0,0 +1,19 @@ +// Yeah yeah, vague file name. Basically a misc folder for antag things that RnD can make. + +/datum/design/item/binaryencrypt + name = "Binary encryption key" + desc = "Allows for deciphering the binary channel on-the-fly." + id = "binaryencrypt" + req_tech = list(TECH_ILLEGAL = 2) + materials = list(DEFAULT_WALL_MATERIAL = 300, "glass" = 300) + build_path = /obj/item/device/encryptionkey/binary + sort_string = "VASAA" + +/datum/design/item/chameleon + name = "Holographic equipment kit" + desc = "A kit of dangerous, high-tech equipment with changeable looks." + id = "chameleon" + req_tech = list(TECH_ILLEGAL = 2) + materials = list(DEFAULT_WALL_MATERIAL = 500) + build_path = /obj/item/weapon/storage/box/syndie_kit/chameleon + sort_string = "VASBA" \ No newline at end of file diff --git a/code/modules/research/designs/medical.dm b/code/modules/research/designs/medical.dm new file mode 100644 index 00000000000..8e821fe0fe9 --- /dev/null +++ b/code/modules/research/designs/medical.dm @@ -0,0 +1,186 @@ +/datum/design/item/medical + materials = list(DEFAULT_WALL_MATERIAL = 30, "glass" = 20) + +/datum/design/item/medical/AssembleDesignName() + ..() + name = "Biotech device prototype ([item_name])" + +/datum/design/item/medical/robot_scanner + desc = "A hand-held scanner able to diagnose robotic injuries." + id = "robot_scanner" + req_tech = list(TECH_MAGNET = 3, TECH_BIO = 2, TECH_ENGINEERING = 3) + materials = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 200) + build_path = /obj/item/device/robotanalyzer + sort_string = "MACFA" + +/datum/design/item/medical/mass_spectrometer + desc = "A device for analyzing chemicals in blood." + id = "mass_spectrometer" + req_tech = list(TECH_BIO = 2, TECH_MAGNET = 2) + build_path = /obj/item/device/mass_spectrometer + sort_string = "MACAA" + +/datum/design/item/medical/adv_mass_spectrometer + desc = "A device for analyzing chemicals in blood and their quantities." + id = "adv_mass_spectrometer" + req_tech = list(TECH_BIO = 2, TECH_MAGNET = 4) + build_path = /obj/item/device/mass_spectrometer/adv + sort_string = "MACAB" + +/datum/design/item/medical/reagent_scanner + desc = "A device for identifying chemicals." + id = "reagent_scanner" + req_tech = list(TECH_BIO = 2, TECH_MAGNET = 2) + build_path = /obj/item/device/reagent_scanner + sort_string = "MACBA" + +/datum/design/item/medical/adv_reagent_scanner + desc = "A device for identifying chemicals and their proportions." + id = "adv_reagent_scanner" + req_tech = list(TECH_BIO = 2, TECH_MAGNET = 4) + build_path = /obj/item/device/reagent_scanner/adv + sort_string = "MACBB" + +/datum/design/item/beaker/AssembleDesignName() + name = "Beaker prototype ([item_name])" + +/datum/design/item/beaker/noreact + name = "cryostasis" + desc = "A cryostasis beaker that allows for chemical storage without reactions. Can hold up to 50 units." + id = "splitbeaker" + req_tech = list(TECH_MATERIAL = 2) + materials = list(DEFAULT_WALL_MATERIAL = 3000) + build_path = /obj/item/weapon/reagent_containers/glass/beaker/noreact + sort_string = "MADAA" + +/datum/design/item/beaker/bluespace + name = TECH_BLUESPACE + desc = "A bluespace beaker, powered by experimental bluespace technology and Element Cuban combined with the Compound Pete. Can hold up to 300 units." + id = "bluespacebeaker" + req_tech = list(TECH_BLUESPACE = 2, TECH_MATERIAL = 6) + materials = list(DEFAULT_WALL_MATERIAL = 3000, "phoron" = 3000, "diamond" = 500) + build_path = /obj/item/weapon/reagent_containers/glass/beaker/bluespace + sort_string = "MADAB" + +/datum/design/item/medical/nanopaste + desc = "A tube of paste containing swarms of repair nanites. Very effective in repairing robotic machinery." + id = "nanopaste" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3) + materials = list(DEFAULT_WALL_MATERIAL = 7000, "glass" = 7000) + build_path = /obj/item/stack/nanopaste + sort_string = "MBAAA" + +/datum/design/item/medical/scalpel_laser1 + name = "Basic Laser Scalpel" + desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks basic and could be improved." + id = "scalpel_laser1" + req_tech = list(TECH_BIO = 2, TECH_MATERIAL = 2, TECH_MAGNET = 2) + materials = list(DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500) + build_path = /obj/item/weapon/surgical/scalpel/laser1 + sort_string = "MBBAA" + +/datum/design/item/medical/scalpel_laser2 + name = "Improved Laser Scalpel" + desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks somewhat advanced." + id = "scalpel_laser2" + req_tech = list(TECH_BIO = 3, TECH_MATERIAL = 4, TECH_MAGNET = 4) + materials = list(DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 2500) + build_path = /obj/item/weapon/surgical/scalpel/laser2 + sort_string = "MBBAB" + +/datum/design/item/medical/scalpel_laser3 + name = "Advanced Laser Scalpel" + desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks to be the pinnacle of precision energy cutlery!" + id = "scalpel_laser3" + req_tech = list(TECH_BIO = 4, TECH_MATERIAL = 6, TECH_MAGNET = 5) + materials = list(DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 2000, "gold" = 1500) + build_path = /obj/item/weapon/surgical/scalpel/laser3 + sort_string = "MBBAC" + +/datum/design/item/medical/scalpel_manager + name = "Incision Management System" + desc = "A true extension of the surgeon's body, this marvel instantly and completely prepares an incision allowing for the immediate commencement of therapeutic steps." + id = "scalpel_manager" + req_tech = list(TECH_BIO = 4, TECH_MATERIAL = 7, TECH_MAGNET = 5, TECH_DATA = 4) + materials = list (DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 1500, "gold" = 1500, "diamond" = 750) + build_path = /obj/item/weapon/surgical/scalpel/manager + sort_string = "MBBAD" + +/datum/design/item/medical/bone_clamp + name = "Bone Clamp" + desc = "A miracle of modern science, this tool rapidly knits together bone, without the need for bone gel." + id = "bone_clamp" + req_tech = list(TECH_BIO = 4, TECH_MATERIAL = 5, TECH_MAGNET = 4, TECH_DATA = 4) + materials = list (DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 2500) + build_path = /obj/item/weapon/surgical/bone_clamp + sort_string = "MBBAE" + +/datum/design/item/medical/advanced_roller + name = "advanced roller bed" + desc = "A more advanced version of the regular roller bed, with inbuilt surgical stabilisers and an improved folding system." + id = "roller_bed" + req_tech = list(TECH_BIO = 3, TECH_MATERIAL = 3, TECH_MAGNET = 3) + materials = list(DEFAULT_WALL_MATERIAL = 4000, "glass" = 2000, "phoron" = 2000) + build_path = /obj/item/roller/adv + sort_string = "MBBAF" + +/datum/design/item/medical/improved_analyzer + name = "improved health analyzer" + desc = "A prototype version of the regular health analyzer, able to distinguish the location of more serious injuries as well as accurately determine radiation levels." + id = "improved_analyzer" + req_tech = list(TECH_MAGNET = 5, TECH_BIO = 6) + materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "silver" = 1000, "gold" = 1500) + build_path = /obj/item/device/healthanalyzer/improved + sort_string = "MBBAG" + +/datum/design/item/implant + materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) + +/datum/design/item/implant/AssembleDesignName() + ..() + name = "Implantable biocircuit design ([item_name])" + +/datum/design/item/implant/chemical + name = "chemical" + id = "implant_chem" + req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3) + build_path = /obj/item/weapon/implantcase/chem + sort_string = "MFAAA" + +/datum/design/item/implant/freedom + name = "freedom" + id = "implant_free" + req_tech = list(TECH_ILLEGAL = 2, TECH_BIO = 3) + build_path = /obj/item/weapon/implantcase/freedom + sort_string = "MFAAB" + +// These are in here because Robotics is close enough to Medical and I don't want to make a new brains.dm file +/datum/design/item/dronebrain + name = "Robotic intelligence circuit" + id = "dronebrain" + req_tech = list(TECH_ENGINEERING = 4, TECH_MATERIAL = 5, TECH_DATA = 4) + build_type = PROTOLATHE | PROSFAB + materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "silver" = 1000, "gold" = 500) + build_path = /obj/item/device/mmi/digital/robot + category = "Misc" + sort_string = "VACAC" + +/datum/design/item/posibrain + name = "Positronic brain" + id = "posibrain" + req_tech = list(TECH_ENGINEERING = 4, TECH_MATERIAL = 6, TECH_BLUESPACE = 2, TECH_DATA = 4) + build_type = PROTOLATHE | PROSFAB + materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "silver" = 1000, "gold" = 500, "phoron" = 500, "diamond" = 100) + build_path = /obj/item/device/mmi/digital/posibrain + category = "Misc" + sort_string = "VACAB" + +/datum/design/item/mmi + name = "Man-machine interface" + id = "mmi" + req_tech = list(TECH_DATA = 2, TECH_BIO = 3) + build_type = PROTOLATHE | PROSFAB + materials = list(DEFAULT_WALL_MATERIAL = 1000, "glass" = 500) + build_path = /obj/item/device/mmi + category = "Misc" + sort_string = "VACBA" \ No newline at end of file diff --git a/code/modules/research/designs/mining_toys.dm b/code/modules/research/designs/mining_toys.dm new file mode 100644 index 00000000000..f9b76032cbd --- /dev/null +++ b/code/modules/research/designs/mining_toys.dm @@ -0,0 +1,48 @@ +// Assorted Mining-related items + +/datum/design/item/weapon/mining/AssembleDesignName() + ..() + name = "Mining equipment design ([item_name])" + +/datum/design/item/weapon/mining/jackhammer + id = "jackhammer" + req_tech = list(TECH_MATERIAL = 3, TECH_POWER = 2, TECH_ENGINEERING = 2) + materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 500, "silver" = 500) + build_path = /obj/item/weapon/pickaxe/jackhammer + sort_string = "KAAAA" + +/datum/design/item/weapon/mining/drill + id = "drill" + req_tech = list(TECH_MATERIAL = 2, TECH_POWER = 3, TECH_ENGINEERING = 2) + materials = list(DEFAULT_WALL_MATERIAL = 6000, "glass" = 1000) //expensive, but no need for miners. + build_path = /obj/item/weapon/pickaxe/drill + sort_string = "KAAAB" + +/datum/design/item/weapon/mining/plasmacutter + id = "plasmacutter" + req_tech = list(TECH_MATERIAL = 4, TECH_PHORON = 3, TECH_ENGINEERING = 3) + materials = list(DEFAULT_WALL_MATERIAL = 1500, "glass" = 500, "gold" = 500, "phoron" = 500) + build_path = /obj/item/weapon/pickaxe/plasmacutter + sort_string = "KAAAC" + +/datum/design/item/weapon/mining/pick_diamond + id = "pick_diamond" + req_tech = list(TECH_MATERIAL = 6) + materials = list("diamond" = 3000) + build_path = /obj/item/weapon/pickaxe/diamond + sort_string = "KAAAD" + +/datum/design/item/weapon/mining/drill_diamond + id = "drill_diamond" + req_tech = list(TECH_MATERIAL = 6, TECH_POWER = 4, TECH_ENGINEERING = 4) + materials = list(DEFAULT_WALL_MATERIAL = 3000, "glass" = 1000, "diamond" = 2000) + build_path = /obj/item/weapon/pickaxe/diamonddrill + sort_string = "KAAAE" + +/datum/design/item/device/depth_scanner + desc = "Used to check spatial depth and density of rock outcroppings." + id = "depth_scanner" + req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2, TECH_BLUESPACE = 2) + materials = list(DEFAULT_WALL_MATERIAL = 1000,"glass" = 1000) + build_path = /obj/item/device/depth_scanner + sort_string = "KAAAF" \ No newline at end of file diff --git a/code/modules/research/designs/misc.dm b/code/modules/research/designs/misc.dm new file mode 100644 index 00000000000..29231a7cd9a --- /dev/null +++ b/code/modules/research/designs/misc.dm @@ -0,0 +1,203 @@ +/* +// +// THIS IS GOING TO GET REAL DAMN BLOATED, SO LET'S TRY TO AVOID THAT IF POSSIBLE +// +*/ + +/datum/design/item/hud + materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) + +/datum/design/item/hud/AssembleDesignName() + ..() + name = "HUD glasses prototype ([item_name])" + +/datum/design/item/hud/AssembleDesignDesc() + desc = "Allows for the construction of \a [item_name] HUD glasses." + +/datum/design/item/hud/health + name = "health scanner" + id = "health_hud" + req_tech = list(TECH_BIO = 2, TECH_MAGNET = 3) + build_path = /obj/item/clothing/glasses/hud/health + sort_string = "GAAAA" + +/datum/design/item/hud/security + name = "security records" + id = "security_hud" + req_tech = list(TECH_MAGNET = 3, TECH_COMBAT = 2) + build_path = /obj/item/clothing/glasses/hud/security + sort_string = "GAAAB" + +/datum/design/item/hud/mesons + name = "Optical meson scanners design" + desc = "Using the meson-scanning technology those glasses allow you to see through walls, floor or anything else." + id = "mesons" + req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2) + materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) + build_path = /obj/item/clothing/glasses/meson + sort_string = "GAAAC" + +/datum/design/item/device/ano_scanner + name = "Alden-Saraspova counter" + id = "ano_scanner" + desc = "Aids in triangulation of exotic particles." + req_tech = list(TECH_BLUESPACE = 3, TECH_MAGNET = 3) + materials = list(DEFAULT_WALL_MATERIAL = 10000,"glass" = 5000) + build_path = /obj/item/device/ano_scanner + sort_string = "UAAAH" + +/datum/design/item/light_replacer + name = "Light replacer" + desc = "A device to automatically replace lights. Refill with working lightbulbs." + id = "light_replacer" + req_tech = list(TECH_MAGNET = 3, TECH_MATERIAL = 4) + materials = list(DEFAULT_WALL_MATERIAL = 1500, "silver" = 150, "glass" = 3000) + build_path = /obj/item/device/lightreplacer + sort_string = "VAAAH" + +datum/design/item/laserpointer + name = "laser pointer" + desc = "Don't shine it in your eyes!" + id = "laser_pointer" + req_tech = list(TECH_MAGNET = 3) + materials = list(DEFAULT_WALL_MATERIAL = 100, "glass" = 50) + build_path = /obj/item/device/laser_pointer + sort_string = "VAAAI" + +/datum/design/item/paicard + name = "'pAI', personal artificial intelligence device" + id = "paicard" + req_tech = list(TECH_DATA = 2) + materials = list("glass" = 500, DEFAULT_WALL_MATERIAL = 500) + build_path = /obj/item/device/paicard + sort_string = "VABAI" + +/datum/design/item/communicator + name = "Communicator" + id = "communicator" + req_tech = list(TECH_DATA = 2, TECH_MAGNET = 2) + materials = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 500) + build_path = /obj/item/device/communicator + sort_string = "VABAJ" + +/datum/design/item/beacon + name = "Bluespace tracking beacon design" + id = "beacon" + req_tech = list(TECH_BLUESPACE = 1) + materials = list (DEFAULT_WALL_MATERIAL = 20, "glass" = 10) + build_path = /obj/item/device/radio/beacon + sort_string = "VADAA" + +/datum/design/item/gps + name = "Triangulating device design" + desc = "Triangulates approximate co-ordinates using a nearby satellite network." + id = "gps" + req_tech = list(TECH_MATERIAL = 2, TECH_DATA = 2, TECH_BLUESPACE = 2) + materials = list(DEFAULT_WALL_MATERIAL = 500) + build_path = /obj/item/device/gps + sort_string = "VADAB" + +/datum/design/item/beacon_locator + name = "Beacon tracking pinpointer" + desc = "Used to scan and locate signals on a particular frequency." + id = "beacon_locator" + req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 2, TECH_BLUESPACE = 3) + materials = list(DEFAULT_WALL_MATERIAL = 1000,"glass" = 500) + build_path = /obj/item/device/beacon_locator + sort_string = "VADAC" + +/datum/design/item/bag_holding + name = "'Bag of Holding', an infinite capacity bag prototype" + desc = "Using localized pockets of bluespace this bag prototype offers incredible storage capacity with the contents weighting nothing. It's a shame the bag itself is pretty heavy." + id = "bag_holding" + req_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 6) + materials = list("gold" = 3000, "diamond" = 1500, "uranium" = 250) + build_path = /obj/item/weapon/storage/backpack/holding + sort_string = "VAEAA" + +/datum/design/item/dufflebag_holding + name = "'DuffleBag of Holding', an infinite capacity dufflebag prototype" + desc = "A minaturized prototype of the popular Bag of Holding, the Dufflebag of Holding is, functionally, identical to the bag of holding, but comes in a more stylish and compact form." + id = "dufflebag_holding" + req_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 6) + materials = list("gold" = 3000, "diamond" = 1500, "uranium" = 250) + build_path = /obj/item/weapon/storage/backpack/holding/duffle + sort_string = "VAEAB" + +/datum/design/item/experimental_welder + name = "Experimental welding tool" + desc = "A welding tool that generate fuel for itself." + id = "expwelder" + req_tech = list(TECH_ENGINEERING = 4, TECH_PHORON = 3, TECH_MATERIAL = 4) + materials = list(DEFAULT_WALL_MATERIAL = 70, "glass" = 120, "phoron" = 100) + build_path = /obj/item/weapon/weldingtool/experimental + sort_string = "VASCA" + +/datum/design/item/hand_drill + name = "Hand drill" + desc = "A simple powered hand drill." + id = "handdrill" + req_tech = list(TECH_ENGINEERING = 3, TECH_MATERIAL = 2) + materials = list(DEFAULT_WALL_MATERIAL = 300, "silver" = 100) + build_path = /obj/item/weapon/tool/screwdriver/power + sort_string = "VASDA" + +/datum/design/item/jaws_life + name = "Jaws of life" + desc = "A set of jaws of life, compressed through the magic of science." + id = "jawslife" + req_tech = list(TECH_ENGINEERING = 3, TECH_MATERIAL = 2) + materials = list(DEFAULT_WALL_MATERIAL = 300, "silver" = 100) + build_path = /obj/item/weapon/tool/crowbar/power + sort_string = "VASEA" + +/datum/design/item/device/t_scanner_upg + name = "Upgraded T-ray Scanner" + desc = "An upgraded version of the terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes." + id = "upgradedtscanner" + req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 4, TECH_MATERIAL = 2) + materials = list(DEFAULT_WALL_MATERIAL = 500, "phoron" = 150) + build_path = /obj/item/device/t_scanner/upgraded + sort_string = "VASSA" + +/datum/design/item/device/t_scanner_adv + name = "Advanced T-ray Scanner" + desc = "An advanced version of the terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes." + id = "advancedtscanner" + req_tech = list(TECH_MAGNET = 6, TECH_ENGINEERING = 6, TECH_MATERIAL = 6) + materials = list(DEFAULT_WALL_MATERIAL = 1250, "phoron" = 500, "silver" = 50) + build_path = /obj/item/device/t_scanner/advanced + sort_string = "VASSB" + +/datum/design/item/translator + name = "handheld translator" + id = "translator" + req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3) + materials = list(DEFAULT_WALL_MATERIAL = 3000, "glass" = 3000) + build_path = /obj/item/device/universal_translator + sort_string = "HABQA" + +/datum/design/item/ear_translator + name = "earpiece translator" + id = "ear_translator" + req_tech = list(TECH_DATA = 5, TECH_ENGINEERING = 5) //It's been hella miniaturized. + materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 2000, "gold" = 1000) + build_path = /obj/item/device/universal_translator/ear + sort_string = "HABQB" + +/datum/design/item/xenoarch_multi_tool + name = "xenoarcheology multitool" + id = "xenoarch_multitool" + req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 3, TECH_BLUESPACE = 3) + build_path = /obj/item/device/xenoarch_multi_tool + materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "uranium" = 500, "phoron" = 500) + sort_string = "HABQC" + +/datum/design/item/excavationdrill + name = "Excavation Drill" + id = "excavationdrill" + req_tech = list(TECH_MATERIAL = 3, TECH_POWER = 2, TECH_ENGINEERING = 2, TECH_BLUESPACE = 3) + build_type = PROTOLATHE + materials = list(DEFAULT_WALL_MATERIAL = 4000, "glass" = 4000) + build_path = /obj/item/weapon/pickaxe/excavationdrill + sort_string = "HABQD" diff --git a/code/modules/research/designs/pdas.dm b/code/modules/research/designs/pdas.dm new file mode 100644 index 00000000000..4aca3062b9a --- /dev/null +++ b/code/modules/research/designs/pdas.dm @@ -0,0 +1,92 @@ +/datum/design/item/pda + name = "PDA design" + desc = "Cheaper than whiny non-digital assistants." + id = "pda" + req_tech = list(TECH_ENGINEERING = 2, TECH_POWER = 3) + materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) + build_path = /obj/item/device/pda + sort_string = "VAAAA" + +// Cartridges +/datum/design/item/pda_cartridge + req_tech = list(TECH_ENGINEERING = 2, TECH_POWER = 3) + materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) + +/datum/design/item/pda_cartridge/AssembleDesignName() + ..() + name = "PDA accessory ([item_name])" + +/datum/design/item/pda_cartridge/cart_basic + id = "cart_basic" + build_path = /obj/item/weapon/cartridge + sort_string = "VBAAA" + +/datum/design/item/pda_cartridge/engineering + id = "cart_engineering" + build_path = /obj/item/weapon/cartridge/engineering + sort_string = "VBAAB" + +/datum/design/item/pda_cartridge/atmos + id = "cart_atmos" + build_path = /obj/item/weapon/cartridge/atmos + sort_string = "VBAAC" + +/datum/design/item/pda_cartridge/medical + id = "cart_medical" + build_path = /obj/item/weapon/cartridge/medical + sort_string = "VBAAD" + +/datum/design/item/pda_cartridge/chemistry + id = "cart_chemistry" + build_path = /obj/item/weapon/cartridge/chemistry + sort_string = "VBAAE" + +/datum/design/item/pda_cartridge/security + id = "cart_security" + build_path = /obj/item/weapon/cartridge/security + sort_string = "VBAAF" + +/datum/design/item/pda_cartridge/janitor + id = "cart_janitor" + build_path = /obj/item/weapon/cartridge/janitor + sort_string = "VBAAG" + +/datum/design/item/pda_cartridge/science + id = "cart_science" + build_path = /obj/item/weapon/cartridge/signal/science + sort_string = "VBAAH" + +/datum/design/item/pda_cartridge/quartermaster + id = "cart_quartermaster" + build_path = /obj/item/weapon/cartridge/quartermaster + sort_string = "VBAAI" + +/datum/design/item/pda_cartridge/hop + id = "cart_hop" + build_path = /obj/item/weapon/cartridge/hop + sort_string = "VBAAJ" + +/datum/design/item/pda_cartridge/hos + id = "cart_hos" + build_path = /obj/item/weapon/cartridge/hos + sort_string = "VBAAK" + +/datum/design/item/pda_cartridge/ce + id = "cart_ce" + build_path = /obj/item/weapon/cartridge/ce + sort_string = "VBAAL" + +/datum/design/item/pda_cartridge/cmo + id = "cart_cmo" + build_path = /obj/item/weapon/cartridge/cmo + sort_string = "VBAAM" + +/datum/design/item/pda_cartridge/rd + id = "cart_rd" + build_path = /obj/item/weapon/cartridge/rd + sort_string = "VBAAN" + +/datum/design/item/pda_cartridge/captain + id = "cart_captain" + build_path = /obj/item/weapon/cartridge/captain + sort_string = "VBAAO" \ No newline at end of file diff --git a/code/modules/research/designs/powercells.dm b/code/modules/research/designs/powercells.dm new file mode 100644 index 00000000000..1ae3a3c3615 --- /dev/null +++ b/code/modules/research/designs/powercells.dm @@ -0,0 +1,71 @@ +/datum/design/item/powercell + build_type = PROTOLATHE | MECHFAB + +/datum/design/item/powercell/AssembleDesignName() + name = "Power Cell Model ([item_name])" + +/datum/design/item/powercell/AssembleDesignDesc() + if(build_path) + var/obj/item/weapon/cell/C = build_path + desc = "Allows the construction of power cells that can hold [initial(C.maxcharge)] units of energy." + +/datum/design/item/powercell/Fabricate() + var/obj/item/weapon/cell/C = ..() + C.charge = 0 //shouldn't produce power out of thin air. + return C + +/datum/design/item/powercell/basic + name = "basic" + build_type = PROTOLATHE | MECHFAB + id = "basic_cell" + req_tech = list(TECH_POWER = 1) + materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50) + build_path = /obj/item/weapon/cell + category = "Misc" + sort_string = "DAAAA" + +/datum/design/item/powercell/high + name = "high-capacity" + build_type = PROTOLATHE | MECHFAB + id = "high_cell" + req_tech = list(TECH_POWER = 2) + materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 60) + build_path = /obj/item/weapon/cell/high + category = "Misc" + sort_string = "DAAAB" + +/datum/design/item/powercell/super + name = "super-capacity" + id = "super_cell" + req_tech = list(TECH_POWER = 3, TECH_MATERIAL = 2) + materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 70) + build_path = /obj/item/weapon/cell/super + category = "Misc" + sort_string = "DAAAC" + +/datum/design/item/powercell/hyper + name = "hyper-capacity" + id = "hyper_cell" + req_tech = list(TECH_POWER = 5, TECH_MATERIAL = 4) + materials = list(DEFAULT_WALL_MATERIAL = 400, "gold" = 150, "silver" = 150, "glass" = 70) + build_path = /obj/item/weapon/cell/hyper + category = "Misc" + sort_string = "DAAAD" + +/datum/design/item/powercell/device + name = "device" + build_type = PROTOLATHE + id = "device" + materials = list(DEFAULT_WALL_MATERIAL = 350, "glass" = 25) + build_path = /obj/item/weapon/cell/device + category = "Misc" + sort_string = "DAABA" + +/datum/design/item/powercell/weapon + name = "weapon" + build_type = PROTOLATHE + id = "weapon" + materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50) + build_path = /obj/item/weapon/cell/device/weapon + category = "Misc" + sort_string = "DAABB" \ No newline at end of file diff --git a/code/modules/research/designs/stock_parts.dm b/code/modules/research/designs/stock_parts.dm new file mode 100644 index 00000000000..fb629e7ad70 --- /dev/null +++ b/code/modules/research/designs/stock_parts.dm @@ -0,0 +1,178 @@ +/* + Various Stock Parts +*/ + +/datum/design/item/stock_part + build_type = PROTOLATHE + +/datum/design/item/stock_part/AssembleDesignName() + ..() + name = "Component design ([item_name])" + +/datum/design/item/stock_part/AssembleDesignDesc() + if(!desc) + desc = "A stock part used in the construction of various devices." + +/datum/design/item/stock_part/basic_capacitor + id = "basic_capacitor" + req_tech = list(TECH_POWER = 1) + materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) + build_path = /obj/item/weapon/stock_parts/capacitor + sort_string = "CAAAA" + +/datum/design/item/stock_part/adv_capacitor + id = "adv_capacitor" + req_tech = list(TECH_POWER = 3) + materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) + build_path = /obj/item/weapon/stock_parts/capacitor/adv + sort_string = "CAAAB" + +/datum/design/item/stock_part/super_capacitor + id = "super_capacitor" + req_tech = list(TECH_POWER = 5, TECH_MATERIAL = 4) + materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, "gold" = 20) + build_path = /obj/item/weapon/stock_parts/capacitor/super + sort_string = "CAAAC" + +/datum/design/item/stock_part/micro_mani + id = "micro_mani" + req_tech = list(TECH_MATERIAL = 1, TECH_DATA = 1) + materials = list(DEFAULT_WALL_MATERIAL = 30) + build_path = /obj/item/weapon/stock_parts/manipulator + sort_string = "CAABA" + +/datum/design/item/stock_part/nano_mani + id = "nano_mani" + req_tech = list(TECH_MATERIAL = 3, TECH_DATA = 2) + materials = list(DEFAULT_WALL_MATERIAL = 30) + build_path = /obj/item/weapon/stock_parts/manipulator/nano + sort_string = "CAABB" + +/datum/design/item/stock_part/pico_mani + id = "pico_mani" + req_tech = list(TECH_MATERIAL = 5, TECH_DATA = 2) + materials = list(DEFAULT_WALL_MATERIAL = 30) + build_path = /obj/item/weapon/stock_parts/manipulator/pico + sort_string = "CAABC" + +/datum/design/item/stock_part/basic_matter_bin + id = "basic_matter_bin" + req_tech = list(TECH_MATERIAL = 1) + materials = list(DEFAULT_WALL_MATERIAL = 80) + build_path = /obj/item/weapon/stock_parts/matter_bin + sort_string = "CAACA" + +/datum/design/item/stock_part/adv_matter_bin + id = "adv_matter_bin" + req_tech = list(TECH_MATERIAL = 3) + materials = list(DEFAULT_WALL_MATERIAL = 80) + build_path = /obj/item/weapon/stock_parts/matter_bin/adv + sort_string = "CAACB" + +/datum/design/item/stock_part/super_matter_bin + id = "super_matter_bin" + req_tech = list(TECH_MATERIAL = 5) + materials = list(DEFAULT_WALL_MATERIAL = 80) + build_path = /obj/item/weapon/stock_parts/matter_bin/super + sort_string = "CAACC" + +/datum/design/item/stock_part/basic_micro_laser + id = "basic_micro_laser" + req_tech = list(TECH_MAGNET = 1) + materials = list(DEFAULT_WALL_MATERIAL = 10, "glass" = 20) + build_path = /obj/item/weapon/stock_parts/micro_laser + sort_string = "CAADA" + +/datum/design/item/stock_part/high_micro_laser + id = "high_micro_laser" + req_tech = list(TECH_MAGNET = 3) + materials = list(DEFAULT_WALL_MATERIAL = 10, "glass" = 20) + build_path = /obj/item/weapon/stock_parts/micro_laser/high + sort_string = "CAADB" + +/datum/design/item/stock_part/ultra_micro_laser + id = "ultra_micro_laser" + req_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 5) + materials = list(DEFAULT_WALL_MATERIAL = 10, "glass" = 20, "uranium" = 10) + build_path = /obj/item/weapon/stock_parts/micro_laser/ultra + sort_string = "CAADC" + +/datum/design/item/stock_part/basic_sensor + id = "basic_sensor" + req_tech = list(TECH_MAGNET = 1) + materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 20) + build_path = /obj/item/weapon/stock_parts/scanning_module + sort_string = "CAAEA" + +/datum/design/item/stock_part/adv_sensor + id = "adv_sensor" + req_tech = list(TECH_MAGNET = 3) + materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 20) + build_path = /obj/item/weapon/stock_parts/scanning_module/adv + sort_string = "CAAEB" + +/datum/design/item/stock_part/phasic_sensor + id = "phasic_sensor" + req_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 3) + materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 20, "silver" = 10) + build_path = /obj/item/weapon/stock_parts/scanning_module/phasic + sort_string = "CAAEC" + +/datum/design/item/stock_part/subspace_ansible + id = "s-ansible" + req_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2) + materials = list(DEFAULT_WALL_MATERIAL = 80, "silver" = 20) + build_path = /obj/item/weapon/stock_parts/subspace/ansible + sort_string = "UAAAA" + +/datum/design/item/stock_part/hyperwave_filter + id = "s-filter" + req_tech = list(TECH_DATA = 3, TECH_MAGNET = 3) + materials = list(DEFAULT_WALL_MATERIAL = 40, "silver" = 10) + build_path = /obj/item/weapon/stock_parts/subspace/sub_filter + sort_string = "UAAAB" + +/datum/design/item/stock_part/subspace_amplifier + id = "s-amplifier" + req_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2) + materials = list(DEFAULT_WALL_MATERIAL = 10, "gold" = 30, "uranium" = 15) + build_path = /obj/item/weapon/stock_parts/subspace/amplifier + sort_string = "UAAAC" + +/datum/design/item/stock_part/subspace_treatment + id = "s-treatment" + req_tech = list(TECH_DATA = 3, TECH_MAGNET = 2, TECH_MATERIAL = 4, TECH_BLUESPACE = 2) + materials = list(DEFAULT_WALL_MATERIAL = 10, "silver" = 20) + build_path = /obj/item/weapon/stock_parts/subspace/treatment + sort_string = "UAAAD" + +/datum/design/item/stock_part/subspace_analyzer + id = "s-analyzer" + req_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2) + materials = list(DEFAULT_WALL_MATERIAL = 10, "gold" = 15) + build_path = /obj/item/weapon/stock_parts/subspace/analyzer + sort_string = "UAAAE" + +/datum/design/item/stock_part/subspace_crystal + id = "s-crystal" + req_tech = list(TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2) + materials = list("glass" = 1000, "silver" = 20, "gold" = 20) + build_path = /obj/item/weapon/stock_parts/subspace/crystal + sort_string = "UAAAF" + +/datum/design/item/stock_part/subspace_transmitter + id = "s-transmitter" + req_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 5, TECH_BLUESPACE = 3) + materials = list("glass" = 100, "silver" = 10, "uranium" = 15) + build_path = /obj/item/weapon/stock_parts/subspace/transmitter + sort_string = "UAAAG" + +// RPED lives here because it handles stock parts +/datum/design/item/stock_part/RPED + name = "Rapid Part Exchange Device" + desc = "Special mechanical module made to store, sort, and apply standard machine parts." + id = "rped" + req_tech = list(TECH_ENGINEERING = 3, TECH_MATERIAL = 3) + materials = list(DEFAULT_WALL_MATERIAL = 15000, "glass" = 5000) + build_path = /obj/item/weapon/storage/part_replacer + sort_string = "CBAAA" \ No newline at end of file diff --git a/code/modules/research/designs/uncommented.dm b/code/modules/research/designs/uncommented.dm new file mode 100644 index 00000000000..7bbf53571ae --- /dev/null +++ b/code/modules/research/designs/uncommented.dm @@ -0,0 +1,69 @@ + +/* Uncomment if someone makes these buildable +/datum/design/circuit/general_alert + name = "general alert console" + id = "general_alert" + build_path = /obj/item/weapon/circuitboard/general_alert + +// Removal of loyalty implants. Can't think of a way to add this to the config option. +/datum/design/item/implant/loyalty + name = "loyalty" + id = "implant_loyal" + req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3) + materials = list(DEFAULT_WALL_MATERIAL = 7000, "glass" = 7000) + build_path = /obj/item/weapon/implantcase/loyalty" + +/datum/design/rust_core_control + name = "Circuit Design (RUST core controller)" + desc = "Allows for the construction of circuit boards used to build a core control console for the RUST fusion engine." + id = "rust_core_control" + req_tech = list("programming" = 4, "engineering" = 4) + build_type = IMPRINTER + materials = list("glass" = 2000, "sacid" = 20) + build_path = "/obj/item/weapon/circuitboard/rust_core_control" + +datum/design/rust_fuel_control + name = "Circuit Design (RUST fuel controller)" + desc = "Allows for the construction of circuit boards used to build a fuel injector control console for the RUST fusion engine." + id = "rust_fuel_control" + req_tech = list("programming" = 4, "engineering" = 4) + build_type = IMPRINTER + materials = list("glass" = 2000, "sacid" = 20) + build_path = "/obj/item/weapon/circuitboard/rust_fuel_control" + +datum/design/rust_fuel_port + name = "Internal circuitry (RUST fuel port)" + desc = "Allows for the construction of circuit boards used to build a fuel injection port for the RUST fusion engine." + id = "rust_fuel_port" + req_tech = list("engineering" = 4, "materials" = 5) + build_type = IMPRINTER + materials = list("glass" = 2000, "sacid" = 20, "uranium" = 3000) + build_path = "/obj/item/weapon/module/rust_fuel_port" + +datum/design/rust_fuel_compressor + name = "Circuit Design (RUST fuel compressor)" + desc = "Allows for the construction of circuit boards used to build a fuel compressor of the RUST fusion engine." + id = "rust_fuel_compressor" + req_tech = list("materials" = 6, "phorontech" = 4) + build_type = IMPRINTER + materials = list("glass" = 2000, "sacid" = 20, "phoron" = 3000, "diamond" = 1000) + build_path = "/obj/item/weapon/module/rust_fuel_compressor" + +datum/design/rust_core + name = "Internal circuitry (RUST tokamak core)" + desc = "The circuit board that for a RUST-pattern tokamak fusion core." + id = "pacman" + req_tech = list(bluespace = 3, phorontech = 4, magnets = 5, powerstorage = 6) + build_type = IMPRINTER + materials = list("glass" = 2000, "sacid" = 20, "phoron" = 3000, "diamond" = 2000) + build_path = "/obj/item/weapon/circuitboard/rust_core" + +datum/design/rust_injector + name = "Internal circuitry (RUST tokamak core)" + desc = "The circuit board that for a RUST-pattern particle accelerator." + id = "pacman" + req_tech = list(powerstorage = 3, engineering = 4, phorontech = 4, materials = 6) + build_type = IMPRINTER + materials = list("glass" = 2000, "sacid" = 20, "phoron" = 3000, "uranium" = 2000) + build_path = "/obj/item/weapon/circuitboard/rust_core" +*/ diff --git a/code/modules/research/designs/weapons.dm b/code/modules/research/designs/weapons.dm new file mode 100644 index 00000000000..828856aebad --- /dev/null +++ b/code/modules/research/designs/weapons.dm @@ -0,0 +1,193 @@ +/datum/design/item/weapon/AssembleDesignName() + ..() + name = "Weapon prototype ([item_name])" + +/datum/design/item/weapon/AssembleDesignDesc() + if(!desc) + if(build_path) + var/obj/item/I = build_path + desc = initial(I.desc) + ..() + +/datum/design/item/weapon/stunrevolver + id = "stunrevolver" + req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3, TECH_POWER = 2) + materials = list(DEFAULT_WALL_MATERIAL = 4000) + build_path = /obj/item/weapon/gun/energy/stunrevolver + sort_string = "TAAAA" + +/datum/design/item/weapon/nuclear_gun + id = "nuclear_gun" + req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 5, TECH_POWER = 3) + materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000, "uranium" = 500) + build_path = /obj/item/weapon/gun/energy/gun/nuclear + sort_string = "TAAAB" + +/datum/design/item/weapon/lasercannon + desc = "The lasing medium of this prototype is enclosed in a tube lined with uranium-235 and subjected to high neutron flux in a nuclear reactor core." + id = "lasercannon" + req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3, TECH_POWER = 3) + materials = list(DEFAULT_WALL_MATERIAL = 10000, "glass" = 1000, "diamond" = 2000) + build_path = /obj/item/weapon/gun/energy/lasercannon + sort_string = "TAAAC" + +/datum/design/item/weapon/phoronpistol + id = "ppistol" + req_tech = list(TECH_COMBAT = 5, TECH_PHORON = 4) + materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000, "phoron" = 3000) + build_path = /obj/item/weapon/gun/energy/toxgun + sort_string = "TAAAD" + +/datum/design/item/weapon/decloner + id = "decloner" + req_tech = list(TECH_COMBAT = 8, TECH_MATERIAL = 7, TECH_BIO = 5, TECH_POWER = 6) + materials = list("gold" = 5000,"uranium" = 10000) + build_path = /obj/item/weapon/gun/energy/decloner + sort_string = "TAAAE" + +/datum/design/item/weapon/smg + id = "smg" + desc = "An compact reliable SMG firing armor piercing ammo." + req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3) + materials = list(DEFAULT_WALL_MATERIAL = 8000, "silver" = 2000, "diamond" = 1000) + build_path = /obj/item/weapon/gun/projectile/automatic/saber + sort_string = "TAABA" + +/datum/design/item/weapon/ammo_9mm + id = "ammo_9mm" + req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3) + materials = list(DEFAULT_WALL_MATERIAL = 3750, "silver" = 100) + build_path = /obj/item/ammo_magazine/box/c9mm + sort_string = "TAACA" + +/datum/design/item/weapon/stunshell + desc = "A stunning shell for a shotgun." + id = "stunshell" + req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3) + materials = list(DEFAULT_WALL_MATERIAL = 4000) + build_path = /obj/item/ammo_casing/a12g/stunshell + sort_string = "TAACB" + +/datum/design/item/weapon/chemsprayer + desc = "An advanced chem spraying device." + id = "chemsprayer" + req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 3, TECH_BIO = 2) + materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000) + build_path = /obj/item/weapon/reagent_containers/spray/chemsprayer + sort_string = "TABAA" + +/datum/design/item/weapon/rapidsyringe + id = "rapidsyringe" + req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3, TECH_ENGINEERING = 3, TECH_BIO = 2) + materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000) + build_path = /obj/item/weapon/gun/launcher/syringe/rapid + sort_string = "TABAB" + +/datum/design/item/weapon/temp_gun + desc = "A gun that shoots high-powered glass-encased energy temperature bullets." + id = "temp_gun" + req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 4, TECH_POWER = 3, TECH_MAGNET = 2) + materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 500, "silver" = 3000) + build_path = /obj/item/weapon/gun/energy/temperature + sort_string = "TABAC" + +/datum/design/item/weapon/large_grenade + id = "large_Grenade" + req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 2) + materials = list(DEFAULT_WALL_MATERIAL = 3000) + build_path = /obj/item/weapon/grenade/chem_grenade/large + sort_string = "TACAA" + +/datum/design/item/weapon/dartgun + desc = "A gun that fires small hollow chemical-payload darts." + id = "dartgun_r" + req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 4, TECH_BIO = 4, TECH_MAGNET = 3, TECH_ILLEGAL = 1) + materials = list(DEFAULT_WALL_MATERIAL = 5000, "gold" = 5000, "silver" = 2500, "glass" = 750) + build_path = /obj/item/weapon/gun/projectile/dartgun/research + sort_string = "TACAB" + +/datum/design/item/weapon/dartgunmag_small + id = "dartgun_mag_s" + req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1) + materials = list(DEFAULT_WALL_MATERIAL = 300, "gold" = 100, "silver" = 100, "glass" = 300) + build_path = /obj/item/ammo_magazine/chemdart/small + sort_string = "TACAC" + +/datum/design/item/weapon/dartgun_ammo_small + id = "dartgun_ammo_s" + req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1) + materials = list(DEFAULT_WALL_MATERIAL = 50, "gold" = 30, "silver" = 30, "glass" = 50) + build_path = /obj/item/ammo_casing/chemdart/small + sort_string = "TACAD" + +/datum/design/item/weapon/dartgunmag_med + id = "dartgun_mag_m" + req_tech = list(TECH_COMBAT = 7, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1) + materials = list(DEFAULT_WALL_MATERIAL = 500, "gold" = 150, "silver" = 150, "diamond" = 200, "glass" = 400) + build_path = /obj/item/ammo_magazine/chemdart + sort_string = "TACAE" + +/datum/design/item/weapon/dartgun_ammo_med + id = "dartgun_ammo_m" + req_tech = list(TECH_COMBAT = 7, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1) + materials = list(DEFAULT_WALL_MATERIAL = 80, "gold" = 40, "silver" = 40, "glass" = 60) + build_path = /obj/item/ammo_casing/chemdart + sort_string = "TACAF" + +/datum/design/item/weapon/fuelrod + id = "fuelrod_gun" + req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 4, TECH_PHORON = 4, TECH_ILLEGAL = 5, TECH_MAGNET = 5) + materials = list(DEFAULT_WALL_MATERIAL = 10000, "glass" = 2000, "gold" = 500, "silver" = 500, "uranium" = 1000, "phoron" = 3000, "diamond" = 1000) + build_path = /obj/item/weapon/gun/magnetic/fuelrod + sort_string = "TACBA" + +/datum/design/item/weapon/flora_gun + id = "flora_gun" + req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3, TECH_POWER = 3) + materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 500, "uranium" = 500) + build_path = /obj/item/weapon/gun/energy/floragun + sort_string = "TBAAA" + +// Xenobio Tools +/datum/design/item/weapon/slimebation + id = "slimebation" + req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2, TECH_POWER = 3, TECH_COMBAT = 3) + materials = list(DEFAULT_WALL_MATERIAL = 5000) + build_path = /obj/item/weapon/melee/baton/slime + sort_string = "TBAAB" + +/datum/design/item/weapon/slimetaser + id = "slimetaser" + req_tech = list(TECH_MATERIAL = 3, TECH_BIO = 3, TECH_POWER = 4, TECH_COMBAT = 4) + materials = list(DEFAULT_WALL_MATERIAL = 5000) + build_path = /obj/item/weapon/gun/energy/taser/xeno + sort_string = "TBAAC" + +// Phase Weapons +/datum/design/item/weapon/phase_pistol + id = "phasepistol" + req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 2, TECH_POWER = 2) + materials = list(DEFAULT_WALL_MATERIAL = 4000) + build_path = /obj/item/weapon/gun/energy/phasegun/pistol + sort_string = "TPAAA" + +/datum/design/item/weapon/phase_carbine + id = "phasecarbine" + req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 2, TECH_POWER = 2) + materials = list(DEFAULT_WALL_MATERIAL = 6000, "glass" = 1500) + build_path = /obj/item/weapon/gun/energy/phasegun + sort_string = "TPAAB" + +/datum/design/item/weapon/phase_rifle + id = "phaserifle" + req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3, TECH_POWER = 3) + materials = list(DEFAULT_WALL_MATERIAL = 7000, "glass" = 2000, "silver" = 500) + build_path = /obj/item/weapon/gun/energy/phasegun/rifle + sort_string = "TPAAC" + +/datum/design/item/weapon/phase_cannon + id = "phasecannon" + req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 4, TECH_POWER = 4) + materials = list(DEFAULT_WALL_MATERIAL = 10000, "glass" = 2000, "silver" = 1000, "diamond" = 750) + build_path = /obj/item/weapon/gun/energy/phasegun/cannon + sort_string = "TPAAD" \ No newline at end of file diff --git a/code/modules/shieldgen/handheld_defuser.dm b/code/modules/shieldgen/handheld_defuser.dm index a2909fa7e6e..d65a0060a8e 100644 --- a/code/modules/shieldgen/handheld_defuser.dm +++ b/code/modules/shieldgen/handheld_defuser.dm @@ -7,11 +7,6 @@ var/obj/item/weapon/cell/device/cell var/enabled = 0 -/obj/item/weapon/shield_diffuser/update_icon() - if(enabled) - icon_state = "hdiffuser_on" - else - icon_state = "hdiffuser_off" /obj/item/weapon/shield_diffuser/New() cell = new(src) @@ -24,6 +19,9 @@ processing_objects.Remove(src) . = ..() +/obj/item/weapon/shield_diffuser/get_cell() + return cell + /obj/item/weapon/shield_diffuser/process() if(!enabled) return @@ -34,6 +32,12 @@ if(istype(S) && cell.checked_use(10 KILOWATTS * CELLRATE)) qdel(S) +/obj/item/weapon/shield_diffuser/update_icon() + if(enabled) + icon_state = "hdiffuser_on" + else + icon_state = "hdiffuser_off" + /obj/item/weapon/shield_diffuser/attack_self() enabled = !enabled update_icon() diff --git a/code/modules/surgery/external_repair.dm b/code/modules/surgery/external_repair.dm new file mode 100644 index 00000000000..b26d803b343 --- /dev/null +++ b/code/modules/surgery/external_repair.dm @@ -0,0 +1,215 @@ +//Procedures in this file: Organic limb repair +////////////////////////////////////////////////////////////////// +// LIMB REPAIR SURGERY // +////////////////////////////////////////////////////////////////// +/datum/surgery_step/repairflesh/ + priority = 1 + can_infect = 1 + blood_level = 1 + req_open = 1 + +/datum/surgery_step/repairflesh/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if (target.stat == DEAD) // Sorry defibs, your subjects need to have pumping fluids for these to work. + return 0 + if (isslime(target)) + return 0 + if (target_zone == O_EYES || target_zone == O_MOUTH) + return 0 + if (!hasorgans(target)) + return 0 + var/obj/item/organ/external/affected = target.get_organ(target_zone) + if (affected == null) + return 0 + if (affected.is_stump()) + return 0 + if (affected.robotic >= ORGAN_ROBOT) + return 0 + return 1 + + +////////////////////////////////////////////////////////////////// +// SCAN STEP // +////////////////////////////////////////////////////////////////// + +/datum/surgery_step/repairflesh/scan_injury + allowed_tools = list( + /obj/item/weapon/autopsy_scanner = 100, + /obj/item/device/healthanalyzer = 80, + /obj/item/device/analyzer = 10 + ) + + priority = 2 + + can_infect = 0 //The only exception here. Sweeping a scanner probably won't transfer many germs. + + min_duration = 20 + max_duration = 40 + +/datum/surgery_step/repairflesh/scan_injury/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if(..()) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + if(affected.burn_stage || affected.brute_stage) + return 0 + return 1 + return 0 + +/datum/surgery_step/repairflesh/scan_injury/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user] begins scanning [target]'s [affected] with \the [tool].", \ + "You begin scanning [target]'s [affected] with \the [tool].") + ..() + +/datum/surgery_step/repairflesh/scan_injury/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user] finishes scanning [target]'s [affected].", \ + "You finish scanning [target]'s [affected].") + if(affected.brute_dam) + to_chat(user, "The muscle in [target]'s [affected] is notably bruised.") + if(affected.status & ORGAN_BROKEN) + to_chat(user, "\The [target]'s [affected] is broken!") + affected.brute_stage = max(1, affected.brute_stage) + if(affected.burn_dam) + to_chat(user, "\The muscle in [target]'s [affected] is notably charred.") + affected.burn_stage = max(1, affected.burn_stage) + +/datum/surgery_step/repairflesh/scan_injury/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user]'s hand slips, dropping \the [tool] onto [target]'s [affected]!" , \ + "Your hand slips, dropping \the [tool] onto [target]'s [affected]!" ) + affected.createwound(BRUISE, 10) + +////////////////////////////////////////////////////////////////// +// BURN STEP // +////////////////////////////////////////////////////////////////// + +/datum/surgery_step/repairflesh/repair_burns + allowed_tools = list( + /obj/item/stack/medical/advanced/ointment = 100, + /obj/item/weapon/surgical/FixOVein = 100, + /obj/item/weapon/surgical/hemostat = 60, + /obj/item/stack/medical/ointment = 50, + /obj/item/weapon/tape_roll = 30, + /obj/item/taperoll = 10 + ) + + priority = 3 + + min_duration = 90 + max_duration = 120 + +/datum/surgery_step/repairflesh/repair_burns/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if(..()) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + if(affected.burn_stage < 1 || !(affected.burn_dam)) + return 0 + if(affected.burn_dam < affected.brute_dam) + return 0 + return 1 + return 0 + +/datum/surgery_step/repairflesh/repair_burns/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + if(istype(tool, /obj/item/weapon/tape_roll) || istype(tool, /obj/item/taperoll)) + user.visible_message("[user] begins taping up [target]'s [affected] with \the [tool].", \ + "You begin taping up [target]'s [affected] with \the [tool].") + affected.jostle_bone(10) + else if(istype(tool, /obj/item/weapon/surgical/hemostat) || istype(tool, /obj/item/weapon/surgical/FixOVein)) + user.visible_message("[user] begins mending the charred blood vessels in [target]'s [affected] with \the [tool].", \ + "You begin mending the charred blood vessels in [target]'s [affected] with \the [tool].") + else + user.visible_message("[user] begins coating the charred tissue in [target]'s [affected] with \the [tool].", \ + "You begin coating the charred tissue in [target]'s [affected] with \the [tool].") + ..() + +/datum/surgery_step/repairflesh/repair_burns/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + if(istype(tool, /obj/item/weapon/tape_roll) || istype(tool, /obj/item/taperoll)) + user.visible_message("[user] finishes taping up [target]'s [affected] with \the [tool].", \ + "You finish taping up [target]'s [affected] with \the [tool].") + affected.createwound(BRUISE, 10) + affected.heal_damage(0, 25, 0, 0) + if(!(affected.burn_dam)) + affected.burn_stage = 0 + if(istype(tool, /obj/item/stack)) + var/obj/item/stack/T = tool + T.use(1) + ..() + +/datum/surgery_step/repairflesh/repair_burns/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user]'s hand slips, tearing up [target]'s [affected] with \the [tool].", \ + "Your hand slips, tearing up [target]'s [affected] with \the [tool].") + affected.createwound(BRUISE, 10) + affected.createwound(CUT, 5) + if(istype(tool, /obj/item/stack) && prob(30)) + var/obj/item/stack/T = tool + T.use(1) + ..() + +////////////////////////////////////////////////////////////////// +// BRUTE STEP // +////////////////////////////////////////////////////////////////// + +/datum/surgery_step/repairflesh/repair_brute + allowed_tools = list( + /obj/item/stack/medical/advanced/bruise_pack = 100, + /obj/item/weapon/surgical/cautery = 100, + /obj/item/weapon/surgical/bonesetter = 60, + /obj/item/stack/medical/bruise_pack = 50, + /obj/item/weapon/tape_roll = 40, + /obj/item/taperoll = 10 + ) + + priority = 3 + + min_duration = 90 + max_duration = 120 + +/datum/surgery_step/repairflesh/repair_brute/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if(..()) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + if(affected.brute_stage < 1 || !(affected.brute_dam)) + return 0 + if(affected.brute_dam < affected.burn_dam) + return 0 + return 1 + return 0 + +/datum/surgery_step/repairflesh/repair_brute/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + if(istype(tool, /obj/item/weapon/tape_roll) || istype(tool, /obj/item/taperoll)) + user.visible_message("[user] begins taping up [target]'s [affected] with \the [tool].", \ + "You begin taping up [target]'s [affected] with \the [tool].") + affected.jostle_bone(10) + else if(istype(tool, /obj/item/weapon/surgical/FixOVein) || istype(tool, /obj/item/weapon/surgical/bonesetter)) + user.visible_message("[user] begins mending the torn tissue in [target]'s [affected] with \the [tool].", \ + "You begin mending the torn tissue in [target]'s [affected] with \the [tool].") + else + user.visible_message("[user] begins coating the tissue in [target]'s [affected] with \the [tool].", \ + "You begin coating the tissue in [target]'s [affected] with \the [tool].") + ..() + +/datum/surgery_step/repairflesh/repair_brute/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + if(istype(tool, /obj/item/weapon/tape_roll) || istype(tool, /obj/item/taperoll)) + user.visible_message("[user] finishes taping up [target]'s [affected] with \the [tool].", \ + "You finish taping up [target]'s [affected] with \the [tool].") + affected.createwound(BRUISE, 10) + affected.heal_damage(25, 0, 0, 0) + if(!(affected.brute_dam)) + affected.brute_stage = 0 + if(istype(tool, /obj/item/stack)) + var/obj/item/stack/T = tool + T.use(1) + ..() + +/datum/surgery_step/repairflesh/repair_brute/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user]'s hand slips, tearing up [target]'s [affected] with \the [tool].", \ + "Your hand slips, tearing up [target]'s [affected] with \the [tool].") + affected.createwound(BRUISE, 10) + affected.createwound(CUT, 5) + if(istype(tool, /obj/item/stack) && prob(30)) + var/obj/item/stack/T = tool + T.use(1) + ..() diff --git a/code/modules/surgery/neck.dm b/code/modules/surgery/neck.dm index 240db44c042..5b1522d60c2 100644 --- a/code/modules/surgery/neck.dm +++ b/code/modules/surgery/neck.dm @@ -219,7 +219,6 @@ priority = 3 //Do this instead of searching for objects in the skull. allowed_tools = list( /obj/item/weapon/surgical/hemostat = 100, - /obj/item/weapon/tool/wirecutters = 60, /obj/item/weapon/melee/changeling/claw = 20) //Claws. Good for digging, not so much for moving. allowed_procs = list(IS_WIRECUTTER = 60) diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index 73f4beb6d6c..2f2e1cb44ac 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -20,9 +20,10 @@ /datum/surgery_step/internal/remove_embryo allowed_tools = list( /obj/item/weapon/surgical/hemostat = 100, \ - /obj/item/weapon/tool/wirecutters = 75, \ /obj/item/weapon/material/kitchen/utensil/fork = 20 ) + + allowed_procs = list(IS_WIRECUTTER = 75) blood_level = 2 min_duration = 80 @@ -212,7 +213,6 @@ allowed_tools = list( /obj/item/weapon/surgical/hemostat = 100, \ - /obj/item/weapon/tool/wirecutters = 75, \ /obj/item/weapon/material/kitchen/utensil/fork = 20 ) diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm index 0f59bdd59ef..2f6caf167fd 100644 --- a/code/modules/surgery/robotics.dm +++ b/code/modules/surgery/robotics.dm @@ -31,7 +31,9 @@ /obj/item/weapon/coin = 50, /obj/item/weapon/material/knife = 50 ) + allowed_procs = list(IS_SCREWDRIVER = 100) + req_open = 0 min_duration = 90 @@ -231,7 +233,6 @@ allowed_tools = list( /obj/item/stack/nanopaste = 100, \ /obj/item/weapon/surgical/bonegel = 30, \ - /obj/item/weapon/tool/screwdriver = 70, \ ) allowed_procs = list(IS_SCREWDRIVER = 100) diff --git a/code/modules/xenoarcheaology/tools/equipment.dm b/code/modules/xenoarcheaology/tools/equipment.dm index 186745a2771..5bc7694df54 100644 --- a/code/modules/xenoarcheaology/tools/equipment.dm +++ b/code/modules/xenoarcheaology/tools/equipment.dm @@ -4,6 +4,7 @@ icon = 'icons/obj/clothing/spacesuits.dmi' icon_state = "engspace_suit" item_state = "engspace_suit" + update_icon_define = "icons/mob/spacesuit.dmi" armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 100) /obj/item/clothing/head/bio_hood/anomaly diff --git a/config/names/first_name_skrell.txt b/config/names/first_name_skrell.txt new file mode 100644 index 00000000000..122b093765a --- /dev/null +++ b/config/names/first_name_skrell.txt @@ -0,0 +1,600 @@ +Kaexae +Xaaq'xuer +Xaaq'taq +Kae'xer +Xeq'aeq'qerr +Ke'xuer +Xeteq +Kae'xum +Kerrker +Kerrquex'xum +Taeqxuq +Kae'quex'xeu +Keqaeq'xeu +Ke'ter +Xue'xerr +Keqqux'kea +Qerrqux +Kerrxae'qer +Taeqxerr +Kerr'xum +Kaexuer +Qerr'xaeq'xeu +Xue'xum +Xeqteq'qerr +Kerrkeax'qux +Xaaq'qux +Xae'xuer +Xertaq'qux +Xum'xuer +Keq'taq'kea +Keq'quex'xeu +Qerraeq +Xeq'xum +Xeq'qux'xum +Xer'xuq +Keq'teq +Kae'keax +Keqxer +Kae'xerr'xeu +Xaequx +Ke'teq'xum +Xaaqxerr +Xer'keax'kea +Qerrxae'qux +Xae'xer +Qerrteq +Xeq'xuer +Xe'xaeq'xum +Xeteq'qerr +Xaaq'aeq'xeu +Xae'xaeq'qer +Keaeq'xum +Xaaq'teq +Keq'ker +Ke'keax +Kexum'kea +Xeq'xum +Qerr'xaeq'kea +Xexum +Taeq'xer'xe +Qerraeq +Xeq'keax'qux +Xuequx +Kexuq +Teqxaeq'qer +Xeqtaq'qer +Xaexuq +Xueaeq'qux +Taeqxae +Keqxuer +Xum'aeq +Xeqkeax'kea +Kerrxuer +Xaeteq +Keqxaeq'qerr +Xum'quex +Taeq'teq +Xer'xaeq +Teq'taq +Xe'xuq +Kerrxer +Kerr'xaeq'kea +Xeqteq +Xeqxuq'qerr +Kerr'xum'xe +Xe'qux +Xexaeq +Qerrxaeq'qer +Teqqux'kea +Ke'xuer +Xerqux'xeu +Kaexaeq'xeu +Xeq'qux +Xeker +Ke'xae +Kerrxae'qux +Kae'aeq'qerr +Xeq'qux'xeu +Xeqquex'xeu +Kerr'xaeq +Kerr'aeq +Xaaqxae +Xertaq'qux +Xaaq'ker'xum +Kae'xuer'xe +Xue'aeq'xeu +Qerr'xuq +Kequex'qerr +Xer'ter'xe +Qerr'ter'qerr +Xeq'keax'qux +Keq'ker +Ke'qux'qerr +Xumter'qux +Xue'qux'xe +Xaeaeq +Xumxuer'xeu +Kerr'xuq'qux +Keq'xaeq +Xum'xuq'xeu +Kerr'xer +Xae'keax +Kequex +Kae'qux +Keqkeax +Qarrker +Xaaqker'xum +Xue'xaeq'qux +Taeq'xaeq'xe +Xue'xerr +Teqkeax +Xaaq'keax +Ke'xaeq'qer +Kerrxuer +Kaeter'qux +Qarr'xerr +Xerxum'qux +Xumqux +Taeq'teq'xeu +Qerrxuer'qer +Xe'ker +Qerrter'kea +Kaeteq'qux +Teq'xuer'xum +Ke'xae'xeu +Teqxuq'qer +Keq'xaeq +Xaaq'xae +Xum'xer +Xeter +Xaaq'quex'kea +Kexum +Qarrkeax'qer +Keq'xerr +Qarrxerr'qerr +Qarrxerr'qer +Xer'ker +Xaexum'xe +Kaexerr'qux +Xuexum +Xaaq'xer +Qerr'quex +Qerr'ker +Xum'teq'qerr +Kerrxaeq +Xeq'xae +Xue'aeq'xe +Qarr'xuer +Qarr'xerr'qerr +Kaexerr'xum +Kaeter'xum +Xuexuq +Xuekeax'xeu +Xaaq'ker +Keqxer +Teq'xer +Qarrker +Xer'ter +Xae'ter'kea +Ke'quex'xe +Xaeter +Xer'xae +Qarr'xae'xum +Xeqxuq +Keqter'xum +Xeker +Taeqxerr'qer +Keqxer'kea +Xumquex +Xaaq'xuq +Kerrxum +Xexerr +Xerxerr'qerr +Xaaq'xerr +Xum'ker'qer +Xequx +Xer'xae +Kaexerr'xe +Xe'taq +Xeq'xuer'qerr +Xue'taq +Teqxer +Xaaq'xerr'xe +Xer'quex'xum +Xaeaeq +Taeqaeq +Xaeter'qer +Xerkeax +Xuequex'xe +Keqxerr +Taeqxae'qer +Teqqux +Xae'quex'qux +Xe'xum +Xaaqxer +Xeq'aeq'xum +Xuexuq'qerr +Xe'taq'qux +Qarr'xae +Xe'keax'qer +Qerrxum'qerr +Xer'xer +Qarr'quex'qerr +Taeq'xer'qux +Taeqtaq +Ke'aeq'xum +Xueter +Kaeker +Xeter'kea +Qarrter +Qerrxae +Xaaqxum'xeu +Xum'xuer +Xe'xae +Qarrter'qer +Kequx +Kerr'aeq'kea +Teq'taq'kea +Xexum'qerr +Qerr'quex'xeu +Xeker'qux +Kerr'quex'qerr +Xum'ker'qer +Keqxuq'xeu +Keqxuq'xeu +Xer'teq'xum +Kaeker'qerr +Xumtaq +Xexuer +Xueter'xum +Kaeteq +Ke'teq +Qerrxuq +Teq'xum'qerr +Xaaq'xae +Keter'xum +Xeqqux +Xae'taq +Qerrtaq'qux +Keq'ter +Xaequex'xum +Kaeter +Xaaqtaq +Kae'xer'qer +Kaequx +Kae'xum +Taeqaeq'qux +Kexaeq'kea +Xer'xae'qer +Xae'ker +Xue'xuer +Xeq'taq'xe +Kaexae'qux +Teq'xae'xe +Teq'xuer +Qerrqux'xeu +Xuexaeq +Kerr'xuq'kea +Xerquex'kea +Keq'ker +Kaexum +Kerrquex +Kexer +Keq'quex'qerr +Xae'xae +Qerr'ker +Kexerr +Xaaqquex +Keq'quex'xum +Xerter'qux +Xuexaeq'xe +Xae'xuq'kea +Kae'xuer'kea +Xer'xum'kea +Xer'quex'kea +Kerrxuq'qux +Qerrxuer +Xeq'xerr'qerr +Qarr'xuq'qux +Xaaq'xuq +Xerxaeq'qux +Xertaq +Kerr'teq'xeu +Xer'aeq'kea +Xe'ter'qerr +Teq'xae +Kerrxerr +Taeqxaeq +Xueker +Keqxae'qerr +Taeqkeax +Kexaeq'xum +Xuekeax'xe +Xumxum +Xeq'ter'xeu +Taeqquex +Xer'xer +Keqxae'xeu +Kaexum +Keq'xaeq +Qerr'quex'xum +Kaexuq'qux +Xaequx'xe +Kae'xum +Keqkeax +Kexuer +Xeter +Xexuq'xeu +Xe'aeq +Xum'keax'xe +Xer'ker'xum +Xerxuq'qer +Xaekeax'xe +Kaequex'xe +Keqxer +Xeker'qer +Teqker'qerr +Keqxer +Teq'xer +Xaaq'xum +Qerrter +Ke'xuer +Kae'xerr'xeu +Qarrteq'kea +Teq'aeq'qux +Teq'xum'qux +Xae'xuq +Xaekeax +Qerr'teq +Kerrteq'qer +Keqxerr +Qarr'xerr'xum +Kekeax +Xae'xae'kea +Xumteq +Xuequx'qer +Qarr'xer +Taeq'xuq +Ke'xum +Kae'xerr +Xumxum'qerr +Keqteq'qer +Teqker'qerr +Qarr'keax +Xeqxer +Qarrxuq'xe +Keqkeax +Xaaq'ter'kea +Xaaq'aeq +Kerr'keax +Keqxuer +Qerr'xerr'kea +Qarr'teq'qerr +Kerr'teq'qerr +Qarr'taq'qer +Qarrxuer'xeu +Kae'ter +Keaeq'xum +Teqker'xum +Xaaq'aeq'qux +Keq'qux'qer +Xae'xuq'kea +Ke'xuq'qux +Qerr'qux +Xaaq'qux'qer +Xue'keax +Xaaqxerr'kea +Taeqteq'xe +Xuetaq +Xaaqxuq'qerr +Qerrxae'xe +Xeqxuer +Xeqxaeq'xum +Xue'ker'qer +Kekeax'xeu +Qarr'xae'qux +Xae'ker'qux +Qarr'xum'xum +Xum'xaeq'xeu +Qerrxer'qerr +Xaeaeq'qer +Xaaq'quex'qerr +Qerr'aeq +Xum'taq +Kerr'xum'xeu +Xaeaeq'kea +Taeqxerr'kea +Taeq'qux'xum +Xaaq'xae +Qerr'quex +Qarrker +Qarr'qux'xeu +Xaaqaeq'qux +Xuetaq +Xaexum +Xae'xaeq +Xaaq'taq'xe +Kerrxaeq'xe +Kae'xer'kea +Kerr'xae'qer +Keqxum'qer +Qarr'taq'xe +Taeq'quex'qer +Xum'xuer +Xer'xuq'qerr +Xeqteq'xum +Xae'xaeq +Xaekeax'qer +Xeq'xum +Qarr'ter'qer +Qarr'xerr +Kae'xae'xum +Taeq'xuq +Kae'xuq'kea +Xue'xum'qux +Xae'xerr +Taeq'xaeq +Xaexuq +Xaequx +Keqter +Kae'xuer +Xaaqaeq +Kae'taq'xeu +Keqter'kea +Taeqaeq +Xae'qux +Qerr'qux +Qarr'xuq'kea +Xeq'xuer +Keqqux +Xaaq'taq'xum +Kae'xerr +Xue'xae'kea +Qarraeq +Taeq'xum +Qerrxer +Teq'xum +Xaaq'ker'xeu +Kerr'xaeq +Xaaq'xerr'xeu +Xaaqxuq'xeu +Taeqter'qer +Teq'xuer +Xaaqker +Qerr'xaeq'qux +Qerr'quex'qux +Xaaqxerr +Keqtaq'xeu +Kerrxuq +Taeqxuq'xe +Taeq'xuq +Xexuq'qerr +Taeq'xae'qux +Kerr'aeq'qer +Teqtaq +Qerr'taq'xeu +Xeqxaeq'kea +Keteq +Qarr'quex'xeu +Kae'xer +Xaaqxuer +Xum'xum +Taeqquex'xeu +Xue'teq +Xumxuq +Teqxer +Xaeteq'xum +Kaexum'qerr +Xaaq'qux +Xe'xum +Qerr'xaeq +Keqxaeq'xe +Xum'xerr +Xuexaeq'xum +Xaaq'xum'kea +Xumteq +Teq'keax'xeu +Xaequex +Ke'ker'kea +Xeq'xuq +Xaaq'quex'xeu +Teq'teq'qux +Qarr'keax +Xequex +Xeqqux +Xerxerr'xum +Kae'teq +Xaaq'qux'xum +Xuetaq'qer +Xaexerr +Xexuer +Xaaq'xerr'qer +Xexae'kea +Xaexuq'qer +Xe'ker +Keq'quex'kea +Qarrqux'qux +Xaaqtaq'kea +Teqxae +Teq'xuq +Ke'aeq +Xae'aeq +Kerr'ter +Xue'xuq'qer +Ke'xaeq +Taeq'xuer'xeu +Xeq'xae +Qerrkeax'kea +Xae'xuq +Teq'keax +Qerr'teq'qer +Kaexuq'xe +Qarrxaeq'xeu +Qerrtaq +Xe'ker'xum +Kaexuer +Teqxuer'xe +Xumxuer'kea +Kerr'xuer +Xer'teq'xum +Xumteq'qerr +Ke'quex +Taeq'aeq'qerr +Xue'ter'xe +Xeq'xae'xeu +Xer'xum +Qarr'xae +Qerrker'qux +Taeq'keax'xeu +Xum'quex'xeu +Kae'ter +Xe'quex'xe +Keqxum +Kerr'quex'qer +Xaaqxae'qer +Xaaqteq'qer +Keqqux +Teq'aeq +Keteq +Xumxae'xum +Xumxum +Qarrxaeq'kea +Keker +Xeq'aeq'qer +Teqter +Qarrxaeq'kea +Teq'quex +Keqxum +Teq'xuer +Xumter'kea +Qarr'xae +Xae'xuer'xeu +Xaaqxaeq'kea +Qerr'xuq'xeu +Xum'xae'qux +Xumxaeq +Xumxum +Kexum'xe +Kae'aeq +Xer'teq +Qarrxerr'xum +Taeq'taq +Taeq'taq'qux +Kaexum'xeu +Xumtaq +Xae'xer +Kerr'ker +Qarr'xum'qer +Qerr'xuer'qux +Xue'qux'xe +Qerr'qux'xum +Teqquex'qerr +Taeqquex +Qarrxerr +Ketaq +Xekeax +Kequex +Xetaq +Ke'xae'xe +Teq'quex'qux diff --git a/config/names/last_name_skrell.txt b/config/names/last_name_skrell.txt new file mode 100644 index 00000000000..5f67fbc5365 --- /dev/null +++ b/config/names/last_name_skrell.txt @@ -0,0 +1,600 @@ +Xer'taq'qer +Xaaq'ter'qux +Xaaq'xuer +Xerxuer'xum +Qarrqux +Xueaeq'qux +Xe'aeq +Keqter +Xaexer +Kaeteq +Ke'aeq'xeu +Kerrxum +Teqxuq'xeu +Xexaeq +Qerr'xerr'xum +Xaeker'qux +Kexer'kea +Ke'aeq +Keqxae'kea +Qarraeq'xe +Xuekeax +Keq'quex +Kae'quex'qux +Qerr'taq'xum +Taeq'taq'xum +Kae'xaeq'xe +Xaaq'teq'qux +Teqker +Qerrxum'xeu +Xeq'xaeq'xe +Kae'keax +Xue'xae +Taeq'taq +Keter'xeu +Xumker'xe +Teqteq +Xexuer +Qerrxerr +Kaequex'qerr +Kaequx'xe +Xum'xaeq +Xe'taq +Xuexer +Xe'qux'xeu +Xe'xerr'kea +Qerr'xum +Xaaqtaq +Xuexum'xum +Qerrxer +Xaexuq +Xeq'aeq +Xaaq'xaeq +Xerqux +Xeq'xuq'xeu +Kaexum +Taeqteq'xeu +Kerrter'qux +Xeq'teq +Teqxae'xe +Xae'ker'kea +Keqxuq +Xumxae'kea +Xeq'xerr'kea +Kae'quex +Kae'ter +Teqter'xe +Xeq'xerr'xeu +Xerxum'qux +Xe'qux +Qarr'aeq +Xue'xum'xe +Xaaq'ter'qux +Teq'xer +Kerrtaq +Qerr'aeq +Xaaq'aeq +Xaaqxuer +Qerr'quex +Kaeker +Xae'taq +Teq'xaeq +Xexuq +Keqqux +Kaeker +Xeqxum +Xae'taq'qerr +Kexerr +Ke'xerr'qux +Xeraeq'xum +Kae'qux'qux +Xerkeax'xum +Qarrxum +Kaexuer +Qerrquex +Kerr'xer +Xeq'taq +Xeqker +Kerrquex'xum +Xeteq +Qarrxuer +Xaaqqux'qerr +Xae'xer +Xae'xae +Taeqxuer'qerr +Xumqux'qux +Xuexerr'qerr +Ke'xae'xum +Xerxuer +Xeqtaq +Xeqquex +Xuekeax +Keq'xuq'qerr +Xaeter +Xumxerr +Xeqxaeq'xe +Xae'ker +Qerr'ker +Xeq'aeq +Kae'keax +Qerrkeax +Xeqxerr +Keqxaeq +Xae'xuq +Kerrkeax'qer +Qarrxum'xum +Teq'xum'xeu +Kerrxer +Xe'xum +Kexae'xeu +Xerxerr'xe +Xum'ter +Xe'keax +Qarr'xer'kea +Xaaq'aeq +Xaaqker'qerr +Ke'ker +Qerr'xum +Qerr'xae'xe +Qarr'ter'xum +Kaexerr +Qarrtaq'qux +Xumxaeq +Xaeaeq'xe +Qarr'xae'qux +Xer'xum'qerr +Kae'xuq +Xaaq'qux'kea +Teqtaq +Kekeax +Xe'keax'qerr +Kerr'keax'qerr +Xeqkeax +Xer'xaeq +Xerter'kea +Xum'xuq'xe +Teqaeq +Ke'teq'qux +Xer'xuq'kea +Keq'xum'xeu +Xerxuer'xeu +Xum'keax'xum +Xaaq'ter +Xuetaq +Taeq'xuer'qux +Xuexum'xe +Xeq'quex'kea +Xum'xer +Xeqaeq +Qerr'ker +Xumxum +Xeqxum +Xae'taq'qerr +Taeq'ker +Xue'xae'xe +Xer'taq'xe +Xum'xaeq +Kaexuq'xum +Kaexuq'qux +Ke'xum'xum +Qerr'xerr'xum +Ke'xuq'qux +Taeq'xaeq +Xumtaq +Xetaq +Kaexerr'xum +Kequx +Xuexerr'xeu +Xeaeq +Keq'qux'kea +Xeq'xaeq +Xuexum +Ke'xerr'xe +Xe'xum +Kerr'xaeq +Xeqkeax'qux +Kaeteq +Xer'quex +Teqaeq'qerr +Xaexerr +Xaeter +Xumxuer'qer +Teqxae +Taeqtaq'qerr +Kerr'qux +Xuequex +Xaaqtaq'kea +Teq'keax +Ke'xuer'kea +Xum'quex'xeu +Xaexer'kea +Kerr'quex'xum +Qarrxaeq'xum +Kerr'xaeq'xeu +Xaaq'xerr'xum +Xeqxaeq +Xaaqxae'xeu +Qerrxae +Xae'xer +Xexer +Qarrter'xe +Xaaq'taq'xum +Taeq'aeq +Teq'xer +Xaexae'xum +Ke'aeq +Teqxuer +Qerrxuq +Xaaq'ker +Xeq'quex +Kerr'qux +Xekeax'qerr +Kerr'qux'xum +Ke'teq +Qarrxae'xum +Qerr'ter'qux +Qerr'keax +Taeqxuer'kea +Qerr'xae +Keqker'xeu +Xueter +Xae'teq'kea +Xumkeax'qux +Keq'keax +Qarr'xerr'qux +Xuekeax'qerr +Taeq'xuq'xe +Keq'aeq'xe +Xue'xuer'qux +Qerr'quex'qux +Xaexerr'qux +Qerrxaeq +Qerr'xerr +Qarr'xuer +Qerrxae +Taeq'xaeq'xeu +Kerr'ter +Kerrker'qux +Kaexae'xum +Kerrtaq'qerr +Xae'aeq'qer +Xer'xerr +Kae'xuer'qux +Qerr'xer'qerr +Keq'taq'qer +Taeqxer'xum +Xaaq'xuq +Xue'qux +Taeq'xaeq +Xe'teq'xe +Teq'xuq +Taeq'xum'qux +Xaaqter'xum +Taeq'taq +Xaaqxerr'qer +Xuetaq'qerr +Xum'xae +Qerrxer'xe +Qerr'xaeq'kea +Xeq'ker +Xeqteq'qerr +Kerr'aeq'qer +Xum'teq'qerr +Xuexuq'kea +Xue'taq +Xum'qux'xe +Kerrker +Xue'ter'xeu +Xaexaeq +Xaexerr'kea +Teqtaq'kea +Xuexuer'xe +Xue'xae'xeu +Taeq'quex +Keqteq +Kae'aeq'xum +Teqaeq'qerr +Xaaqxum +Qarr'teq'qux +Kaexer +Xue'xum +Qerrtaq'qer +Taeq'teq'qux +Xueter +Xum'ker'xe +Xue'keax +Xum'quex'qerr +Kaeaeq'qerr +Xeqxae +Keqxuer'xeu +Xeqxum +Teqxuq +Kaeker +Xaaq'taq +Keqquex'kea +Xe'ker +Xeq'aeq'kea +Xue'qux +Xerxuq +Taeq'quex +Kequx'qux +Xueker'qux +Teqxum'qer +Kerrxuq'qer +Xerker +Xue'xuer +Xue'qux +Taeq'xuq +Keq'qux'xum +Qarr'quex'xe +Kae'xer'kea +Qarr'xum'xeu +Keqker'xum +Ketaq +Xue'teq +Xuexerr +Xeqker +Xe'xum'xeu +Xeq'ter'qerr +Taeqxuq +Kaeter +Keq'taq +Xum'xum +Xumxuer'xum +Teqter'qerr +Keq'qux'xe +Keq'xer'qer +Xueaeq'xeu +Taeqxuer'kea +Keqxae'xeu +Kae'taq +Xerkeax +Xeqker +Kerrxer +Taeq'xerr'xe +Qerr'xerr'qerr +Xe'ker'xe +Kae'qux'qerr +Kaequex +Xaaq'teq'qer +Xumxerr +Xe'quex +Qerr'xum'qux +Qerrxae +Qerrquex +Kae'xae'qerr +Qarrquex +Kerrxae +Xaaq'taq'xeu +Qarr'xae'qux +Xeqker +Xaaqxuq'qer +Xaaqter +Xerxerr +Xue'taq'qer +Qarrxer'qerr +Xae'ter'xum +Kerrter'qerr +Kerrter'kea +Xae'aeq +Xe'xer +Teq'keax'xeu +Kexum'xe +Xueteq +Kae'keax +Xaaq'keax +Xaaq'quex'qux +Taeqqux +Taeq'xum +Xerxuer +Qerrxer +Xaexuer +Teqter +Qarr'xer +Qarrxaeq'xum +Ke'teq +Teq'xae +Kaexerr +Qarr'teq +Xer'ker +Xaexuer'qux +Xeq'qux +Taeqxer +Taeqxaeq +Xumxuer +Taeqxuer'qerr +Kae'xuer +Qerrter +Taeq'aeq'kea +Taeq'xer'xum +Kerrter +Xum'xuer +Xue'ker'qux +Xaaqter'qux +Xue'ter'xe +Xueteq +Xaaq'xae +Xaexerr'qerr +Ke'aeq'qerr +Xaaq'xuq'xeu +Xuekeax +Xumteq +Xexuq +Taeq'ker'xeu +Xaaqaeq +Qarrxum +Xerxuq'xum +Kaexerr +Xeq'ter'xeu +Keqaeq +Xeqxuer'xum +Teqkeax'xeu +Kae'aeq'kea +Ke'xerr +Ke'xuq +Kae'quex +Xeqxae +Kaeter +Xeqxer +Kae'xuer +Taeqtaq'xum +Teq'qux'xeu +Xaequex'xum +Qarrquex +Xaaq'qux +Keqquex +Qerrker'qerr +Xexae'xe +Xerxae +Xaaqker'kea +Kexer'qerr +Xaeaeq +Xaaqqux +Qarr'xer'qer +Keq'xuq +Kae'keax +Qerr'teq'qer +Kae'xaeq'qer +Xaexer +Kerrxer'xeu +Kaekeax +Xaaq'xaeq'xeu +Xae'xae +Qarr'keax +Teqqux'qerr +Xeq'ter'qerr +Taeq'ker +Qerrteq'xeu +Keqqux'xeu +Xaaqteq'qerr +Teqteq'xe +Xaaqter +Xaaqkeax +Xeqqux +Xaaq'xerr +Teq'ker'qerr +Xer'taq'qerr +Qarrxum'qux +Xum'taq'qux +Qarr'xer'xeu +Xerxerr'qux +Kerr'teq +Xum'taq'kea +Xaequex +Kaeaeq'xe +Xe'xaeq'xum +Xuexuer'qer +Kerrxuq +Kerrxuer'qerr +Kaeteq +Xaaqxuer +Xeq'xum'qerr +Xumxer +Xe'ter'xeu +Xueaeq +Keq'keax +Xueter +Xaexaeq +Keqxaeq +Ke'aeq +Xumxum'qerr +Xumxae'xum +Xaaqxuer +Ke'ker +Ke'xer +Xuekeax'qerr +Keq'teq +Kerr'ter'qux +Xe'xerr +Qerrxae +Ke'quex'xeu +Keqxuq +Kerrxuer +Keq'xae +Qarr'xuq +Xumxuq +Qarr'teq'qer +Xe'xae'xeu +Xuexum +Xequx +Xaaq'teq'xum +Xue'xuq +Kae'quex'qer +Qarrxer'qerr +Xumaeq'xeu +Qarrkeax +Kae'xer'qux +Xeq'qux'qer +Xueker'qux +Teqquex +Xae'xaeq'xum +Taeqkeax +Xaaq'teq'qux +Keqxerr'xe +Xue'ter'xe +Xe'xaeq +Qerrker +Xaexum'qer +Keqteq'xum +Taeq'xae'xum +Kaexuer'qux +Xe'ter +Xae'taq'qux +Qarr'aeq +Xae'xum +Qarrxum'xum +Keqxer'xum +Qarr'xerr +Teqxae +Ke'xae'xe +Teqkeax'qux +Xe'taq +Xaetaq +Keq'teq'kea +Keqxaeq +Xue'xuq +Qarr'xerr'qer +Xequex +Keqxum +Keqtaq +Qarr'ker'xum +Kerr'xer'qer +Kerrxae'xum +Xum'xae +Kaequex'qux +Xuequx'xe +Xumquex'qer +Taeqker +Xae'quex +Xer'teq'xe +Xerxerr +Ke'xuq'qer +Taeqxerr'kea +Xaaq'xaeq'kea +Keq'teq +Xue'aeq'xeu +Xaaqxer'xeu +Ke'ker'qerr +Xue'quex +Taeqtaq +Teqter +Kequex'xe +Xuexuer'qerr +Xeqxum +Xue'taq +Xer'xuq'qerr +Xeqxaeq'xe +Qerr'xaeq +Xeqxae'qer +Taeqtaq'kea +Xer'teq +Qerr'xaeq'xum +Xaaq'xae +Xum'xuq +Xaaqxaeq +Xaexum +Xaaqxum'xe +Xertaq +Xuexuq'qerr +Xaaq'xae'kea +Qerr'teq'qer diff --git a/html/changelog.html b/html/changelog.html index 9c933a1741d..f3acb4a5d61 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -53,6 +53,66 @@ -->
    +

    01 August 2018

    +

    KasparoVv updated:

    + +

    Mechoid updated:

    + +

    Mewchild updated:

    + +

    PrismaticGynoid updated:

    + + +

    14 July 2018

    +

    Anewbe updated:

    + +

    Atermonera updated:

    + +

    Mechoid updated:

    + + +

    12 July 2018

    +

    Anewbe updated:

    + + +

    21 June 2018

    +

    Anewbe updated:

    + +

    Mechoid updated:

    + +

    08 June 2018

    Anewbe updated: