Merge branch 'master' of https://github.com/PolarisSS13/Polaris into is_tool

This commit is contained in:
Anewbe
2018-08-02 22:35:14 -05:00
262 changed files with 7022 additions and 3130 deletions

View File

@@ -4,7 +4,7 @@
#define TRANSITIONEDGE 7 // Distance from edge to move to another z-level. #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_LIGHTING 20
#define INVISIBILITY_LEVEL_ONE 35 #define INVISIBILITY_LEVEL_ONE 35
#define INVISIBILITY_LEVEL_TWO 45 #define INVISIBILITY_LEVEL_TWO 45
@@ -21,6 +21,9 @@
#define SEE_INVISIBLE_MINIMUM 5 #define SEE_INVISIBLE_MINIMUM 5
#define INVISIBILITY_MAXIMUM 100 #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 // For the client FPS pref and anywhere else
#define MAX_CLIENT_FPS 200 #define MAX_CLIENT_FPS 200

View File

@@ -177,6 +177,9 @@
#define O_LIVER "liver" #define O_LIVER "liver"
#define O_KIDNEYS "kidneys" #define O_KIDNEYS "kidneys"
#define O_APPENDIX "appendix" #define O_APPENDIX "appendix"
#define O_VOICE "voicebox"
// Non-Standard organs
#define O_PLASMA "plasma vessel" #define O_PLASMA "plasma vessel"
#define O_HIVE "hive node" #define O_HIVE "hive node"
#define O_NUTRIENT "nutrient vessel" #define O_NUTRIENT "nutrient vessel"

View File

@@ -50,6 +50,7 @@
#define LANGUAGE_MINBUS "Minbus" #define LANGUAGE_MINBUS "Minbus"
#define LANGUAGE_EVENT1 "Occursus" #define LANGUAGE_EVENT1 "Occursus"
#define LANGUAGE_AKHANI "Akhani" #define LANGUAGE_AKHANI "Akhani"
#define LANGUAGE_ALAI "Alai"
// Language flags. // Language flags.
#define WHITELISTED 1 // Language is available if the speaker is whitelisted. #define WHITELISTED 1 // Language is available if the speaker is whitelisted.

View File

@@ -30,6 +30,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define INIT_ORDER_DEFAULT 0 #define INIT_ORDER_DEFAULT 0
#define INIT_ORDER_LIGHTING 0 #define INIT_ORDER_LIGHTING 0
#define INIT_ORDER_AIR -1 #define INIT_ORDER_AIR -1
#define INIT_ORDER_PLANETS -4
#define INIT_ORDER_OVERLAY -6 #define INIT_ORDER_OVERLAY -6
#define INIT_ORDER_XENOARCH -20 #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_AIRFLOW 30
#define FIRE_PRIORITY_AIR 35 #define FIRE_PRIORITY_AIR 35
#define FIRE_PRIORITY_DEFAULT 50 #define FIRE_PRIORITY_DEFAULT 50
#define FIRE_PRIORITY_PLANETS 75
#define FIRE_PRIORITY_MACHINES 100 #define FIRE_PRIORITY_MACHINES 100
#define FIRE_PRIORITY_OVERLAYS 500 #define FIRE_PRIORITY_OVERLAYS 500

View File

@@ -1073,47 +1073,7 @@ var/global/list/common_tools = list(
if(istype(I, /obj/item/device/assembly/signaler)) if(istype(I, /obj/item/device/assembly/signaler))
return TRUE return TRUE
return 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) proc/is_hot(obj/item/W as obj)
switch(W.type) switch(W.type)
if(/obj/item/weapon/weldingtool) if(/obj/item/weapon/weldingtool)

View File

@@ -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

View File

@@ -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() /datum/controller/process/supply/setup()
name = "supply controller" name = "supply controller"
schedule_interval = 300 // every 30 seconds schedule_interval = 300 // every 30 seconds
/datum/controller/process/supply/doWork() /datum/controller/process/supply/doWork()
supply_controller.process() 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 = "<h3>[command_name()] Shipping Manifest</h3><hr><br>"
slip.info +="Order #[SO.ordernum]<br>"
slip.info +="Destination: [station_name()]<br>"
slip.info +="[orderedamount] PACKAGES IN THIS SHIPMENT<br>"
slip.info +="CONTENTS:<br><ul>"
//spawn the stuff, finish generating the manifest while you're at it
if(SP.access)
if(isnum(SP.access))
A.req_access = list(SP.access)
else if(islist(SP.access))
var/list/L = SP.access // access var is a plain var, we need a list
A.req_access = L.Copy()
else
log_debug("<span class='danger'>Supply pack with invalid access restriction [SP.access] encountered!</span>")
var/list/contains
if(istype(SP,/datum/supply_packs/randomised))
var/datum/supply_packs/randomised/SPR = SP
contains = list()
if(SPR.contains.len)
for(var/j=1,j<=SPR.num_contained,j++)
contains += pick(SPR.contains)
else
contains = SP.contains
for(var/typepath in contains)
if(!typepath)
continue
var/number_of_items = max(1, contains[typepath])
for(var/j = 1 to number_of_items)
var/atom/B2 = new typepath(A)
if(slip)
slip.info += "<li>[B2.name]</li>" //add the item to the manifest
//manifest finalisation
if(slip)
slip.info += "</ul><br>"
slip.info += "CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS<hr>"
return

View File

@@ -60,6 +60,7 @@ var/list/gamemode_cache = list()
var/humans_need_surnames = 0 var/humans_need_surnames = 0
var/allow_random_events = 0 // enables random events mid-round when set to 1 var/allow_random_events = 0 // enables random events mid-round when set to 1
var/allow_ai = 1 // allow ai job var/allow_ai = 1 // allow ai job
var/allow_ai_drones = 0 // allow ai controlled drones
var/hostedby = null var/hostedby = null
var/respawn = 1 var/respawn = 1
var/guest_jobban = 1 var/guest_jobban = 1
@@ -400,6 +401,9 @@ var/list/gamemode_cache = list()
if ("allow_ai") if ("allow_ai")
config.allow_ai = 1 config.allow_ai = 1
if ("allow_ai_drones")
config.allow_ai_drones = 1
// if ("authentication") // if ("authentication")
// config.enable_authentication = 1 // config.enable_authentication = 1

View File

@@ -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("<span class='danger'>Initializing planetary weather.</span>", 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("<span class='danger'>Z[Z] is shared by more than one planet!</span>", 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)

View File

@@ -133,8 +133,5 @@
if("Vote") if("Vote")
debug_variables(vote) debug_variables(vote)
feedback_add_details("admin_verb", "DVote") 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.") message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.")
return return

View File

@@ -84,10 +84,8 @@
for(var/mob/living/silicon/robot/robot in mob_list) for(var/mob/living/silicon/robot/robot in mob_list)
// No combat/syndicate cyborgs, no drones. // 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[robot.name] = "[robot.modtype] [robot.braintype]"
bot[robot.name] = "[robot.modtype] [robot.braintype]"
if(heads.len > 0) if(heads.len > 0)

View File

@@ -20,9 +20,9 @@ var/decl/observ/turf_changed/turf_changed_event = new()
* Turf Changed Handling * * 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_density = density
var/old_opacity = opacity var/old_opacity = opacity
. = ..() . = ..(N, tell_universe, force_lighting_update, preserve_outdoors)
if(.) if(.)
turf_changed_event.raise_event(src, old_density, density, old_opacity, opacity) turf_changed_event.raise_event(src, old_density, density, old_opacity, opacity)

View File

@@ -144,7 +144,7 @@ var/global/list/PDA_Manifest = list()
for(var/mob/living/silicon/robot/robot in mob_list) for(var/mob/living/silicon/robot/robot in mob_list)
// No combat/syndicate cyborgs, no drones. // 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 continue
bot[++bot.len] = list("name" = robot.real_name, "rank" = "[robot.modtype] [robot.braintype]", "active" = "Active") bot[++bot.len] = list("name" = robot.real_name, "rank" = "[robot.modtype] [robot.braintype]", "active" = "Active")

View File

@@ -79,7 +79,9 @@
Think through your actions and make the roleplay immersive! <b>Please remember all \ Think through your actions and make the roleplay immersive! <b>Please remember all \
rules aside from those without explicit exceptions apply to antagonists.</b>" rules aside from those without explicit exceptions apply to antagonists.</b>"
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() /datum/antagonist/New()
..() ..()

View File

@@ -36,7 +36,7 @@
and it otherwise has no bearing on your round.</span>" and it otherwise has no bearing on your round.</span>"
player.current.verbs |= /mob/living/proc/write_ambition player.current.verbs |= /mob/living/proc/write_ambition
if(can_use_aooc) if(can_speak_aooc)
player.current.client.verbs += /client/proc/aooc player.current.client.verbs += /client/proc/aooc
// Handle only adding a mind and not bothering with gear etc. // Handle only adding a mind and not bothering with gear etc.

View File

@@ -25,7 +25,8 @@ var/datum/antagonist/ert/ert
initial_spawn_req = 5 initial_spawn_req = 5
initial_spawn_target = 7 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) /datum/antagonist/ert/create_default(var/mob/source)
var/mob/living/carbon/human/M = ..() var/mob/living/carbon/human/M = ..()

View File

@@ -24,7 +24,7 @@ var/datum/antagonist/trader/traders
initial_spawn_req = 5 initial_spawn_req = 5
initial_spawn_target = 7 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) /datum/antagonist/trader/create_default(var/mob/source)
var/mob/living/carbon/human/M = ..() var/mob/living/carbon/human/M = ..()

View File

@@ -13,6 +13,7 @@ var/datum/antagonist/traitor/infiltrator/infiltrators
welcome_text = "To speak on your team's private channel, use :t." 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") protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director")
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
can_speak_aooc = TRUE
/datum/antagonist/traitor/infiltrator/New() /datum/antagonist/traitor/infiltrator/New()
..() ..()

View File

@@ -17,7 +17,7 @@ var/datum/antagonist/renegade/renegades
Think through your actions and make the roleplay immersive! <b>Please remember all \ Think through your actions and make the roleplay immersive! <b>Please remember all \
rules aside from those without explicit exceptions apply to antagonists.</b>" rules aside from those without explicit exceptions apply to antagonists.</b>"
flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE 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 = 8
hard_cap_round = 12 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) 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() /datum/antagonist/renegade/New()
..() ..()
renegades = src renegades = src

View File

@@ -15,4 +15,4 @@ var/datum/antagonist/thug/thugs
Think through your actions and make the roleplay immersive! <b>Please remember all \ Think through your actions and make the roleplay immersive! <b>Please remember all \
rules aside from those with explicit exceptions apply to antagonists.</b>" rules aside from those with explicit exceptions apply to antagonists.</b>"
flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE
can_use_aooc = FALSE can_speak_aooc = FALSE

View File

@@ -5,7 +5,7 @@ var/datum/antagonist/traitor/traitors
id = MODE_TRAITOR id = MODE_TRAITOR
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director") protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director")
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE 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 /datum/antagonist/traitor/auto
id = MODE_AUTOTRAITOR id = MODE_AUTOTRAITOR

View File

@@ -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') 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 base_turf = /turf/space
area/space/atmosalert() /area/space/atmosalert()
return return
/area/space/fire_alert() /area/space/fire_alert()
@@ -451,20 +451,6 @@ area/space/atmosalert()
icon_state = "cave" icon_state = "cave"
sound_env = SMALL_ENCLOSED sound_env = SMALL_ENCLOSED
/area/planet/clown /area/planet/clown
name = "\improper Clown Planet" name = "\improper Clown Planet"
icon_state = "honk" icon_state = "honk"
@@ -906,9 +892,6 @@ area/space/atmosalert()
/area/maintenance/substation/security // Security, Brig, Permabrig, etc. /area/maintenance/substation/security // Security, Brig, Permabrig, etc.
name = "Security Substation" name = "Security Substation"
//Hallway //Hallway
/area/hallway/primary/ /area/hallway/primary/
@@ -1115,7 +1098,7 @@ area/space/atmosalert()
name = "\improper Research Server Room" name = "\improper Research Server Room"
icon_state = "server" icon_state = "server"
//Crew //Civilian
/area/crew_quarters /area/crew_quarters
name = "\improper Dormitories" name = "\improper Dormitories"
@@ -1978,6 +1961,24 @@ area/space/atmosalert()
name = "\improper Vacant Office" name = "\improper Vacant Office"
icon_state = "security" 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 /area/quartermaster
name = "\improper Quartermasters" name = "\improper Quartermasters"
icon_state = "quart" icon_state = "quart"
@@ -2011,23 +2012,20 @@ area/space/atmosalert()
name = "\improper Cargo Mining Dock" name = "\improper Cargo Mining Dock"
icon_state = "mining" icon_state = "mining"
/area/janitor/ /area/supply/station
name = "\improper Custodial Closet" name = "Supply Shuttle"
icon_state = "janitor" icon_state = "shuttle3"
requires_power = 0
base_turf = /turf/space
/area/hydroponics /area/supply/dock
name = "\improper Hydroponics" name = "Supply Shuttle"
icon_state = "hydro" icon_state = "shuttle3"
requires_power = 0
base_turf = /turf/space
/area/hydroponics/cafegarden // SCIENCE
name = "\improper Cafeteria Garden"
icon_state = "cafe_garden"
/area/hydroponics/garden
name = "\improper Garden"
icon_state = "garden"
//rnd (Research and Development
/area/rnd/research /area/rnd/research
name = "\improper Research and Development" name = "\improper Research and Development"
icon_state = "research" icon_state = "research"

View File

@@ -5,12 +5,14 @@
var/list/languages var/list/languages
var/identifying_gender var/identifying_gender
var/list/flavour_texts 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 name = newName
dna = newDNA dna = newDNA
speciesName = newSpecies speciesName = newSpecies
languages = newLanguages languages = newLanguages
identifying_gender = newIdentifying_Gender identifying_gender = newIdentifying_Gender
flavour_texts = newFlavour ? newFlavour.Copy() : null flavour_texts = newFlavour ? newFlavour.Copy() : null
genMods = newGenMods ? newGenMods.Copy() : null

View File

@@ -78,7 +78,7 @@
src << "<span class='notice'>We can now re-adapt, reverting our evolution so that we may start anew, if needed.</span>" src << "<span class='notice'>We can now re-adapt, reverting our evolution so that we may start anew, if needed.</span>"
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) absorbDNA(newDNA)
if(T.mind && T.mind.changeling) if(T.mind && T.mind.changeling)

View File

@@ -48,6 +48,13 @@
src.UpdateAppearance() src.UpdateAppearance()
domutcheck(src, null) domutcheck(src, null)
changeling_update_languages(changeling.absorbed_languages) 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 src.verbs -= /mob/proc/changeling_transform
spawn(10) spawn(10)

View File

@@ -31,7 +31,7 @@
return TRUE return TRUE
/obj/item/weapon/spell/proc/within_range(var/atom/target, var/max_range = 7) // Beyond 7 is off the screen. /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 TRUE
return FALSE return FALSE

View File

@@ -21,11 +21,13 @@
if(!AM.loc) //Don't teleport HUD telements to us. if(!AM.loc) //Don't teleport HUD telements to us.
return return
if(AM.anchored) if(AM.anchored)
user << "<span class='warning'>\The [hit_atom] is firmly secured and anchored, you can't move it!</span>" to_chat(user, "<span class='warning'>\The [hit_atom] is firmly secured and anchored, you can't move it!</span>")
return return
if(!within_range(hit_atom) && !check_for_scepter()) if(!within_range(hit_atom) && !check_for_scepter())
user << "<span class='warning'>\The [hit_atom] is too far away.</span>" to_chat(user, "<span class='warning'>\The [hit_atom] is too far away.</span>")
return return
//Teleporting an item. //Teleporting an item.
if(istype(hit_atom, /obj/item)) if(istype(hit_atom, /obj/item))
var/obj/item/I = hit_atom var/obj/item/I = hit_atom
@@ -47,7 +49,7 @@
//Now let's try to teleport a living mob. //Now let's try to teleport a living mob.
else if(istype(hit_atom, /mob/living)) else if(istype(hit_atom, /mob/living))
var/mob/living/L = hit_atom var/mob/living/L = hit_atom
L << "<span class='danger'>You are teleported towards \the [user].</span>" to_chat(L, "<span class='danger'>You are teleported towards \the [user].</span>")
var/datum/effect/effect/system/spark_spread/s1 = new /datum/effect/effect/system/spark_spread 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 var/datum/effect/effect/system/spark_spread/s2 = new /datum/effect/effect/system/spark_spread
s1.set_up(2, 1, user) s1.set_up(2, 1, user)
@@ -60,7 +62,7 @@
spawn(1 SECOND) spawn(1 SECOND)
if(!user.Adjacent(L)) if(!user.Adjacent(L))
user << "<span class='warning'>\The [L] is out of your reach.</span>" to_chat(user, "<span class='warning'>\The [L] is out of your reach.</span>")
qdel(src) qdel(src)
return return

View File

@@ -149,5 +149,7 @@
feedback_set_details("religion_book","[new_book_style]") feedback_set_details("religion_book","[new_book_style]")
return 1 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) /datum/job/chaplain/equip_preview(var/mob/living/carbon/human/H, var/alt_title)
return equip(H, alt_title, FALSE) return equip(H, alt_title, FALSE)
*/

View File

@@ -378,7 +378,8 @@ var/global/datum/controller/occupations/job_master
H.amend_exploitable(G.path) H.amend_exploitable(G.path)
if(G.slot == "implant") if(G.slot == "implant")
H.implant_loadout(G) var/obj/item/weapon/implant/I = G.spawn_item(H)
I.implant_loadout(H)
continue continue
if(G.slot && !(G.slot in custom_equip_slots)) if(G.slot && !(G.slot in custom_equip_slots))

View File

@@ -13,27 +13,29 @@
idle_power_usage = 40 idle_power_usage = 40
active_power_usage = 300 active_power_usage = 300
var/stored_matter = 0 var/obj/item/weapon/reagent_containers/container = null // This is the beaker that holds all of the biomass
var/max_stored_matter = 0
var/print_delay = 100 var/print_delay = 100
var/base_print_delay = 100 // For Adminbus reasons
var/printing var/printing
var/loaded_dna //Blood sample for DNA hashing. var/loaded_dna //Blood sample for DNA hashing.
// These should be subtypes of /obj/item/organ // 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( var/list/products = list(
"Heart" = list(/obj/item/organ/internal/heart, 25), "Heart" = list(/obj/item/organ/internal/heart, 20),
"Lungs" = list(/obj/item/organ/internal/lungs, 25), "Lungs" = list(/obj/item/organ/internal/lungs, 20),
"Kidneys" = list(/obj/item/organ/internal/kidneys,20), "Kidneys" = list(/obj/item/organ/internal/kidneys,20),
"Eyes" = list(/obj/item/organ/internal/eyes, 20), "Eyes" = list(/obj/item/organ/internal/eyes, 20),
"Liver" = list(/obj/item/organ/internal/liver, 25), "Liver" = list(/obj/item/organ/internal/liver, 20),
"Arm, Left" = list(/obj/item/organ/external/arm, 65), "Arm, Left" = list(/obj/item/organ/external/arm, 40),
"Arm, Right" = list(/obj/item/organ/external/arm/right, 65), "Arm, Right" = list(/obj/item/organ/external/arm/right, 40),
"Leg, Left" = list(/obj/item/organ/external/leg, 65), "Leg, Left" = list(/obj/item/organ/external/leg, 40),
"Leg, Right" = list(/obj/item/organ/external/leg/right, 65), "Leg, Right" = list(/obj/item/organ/external/leg/right, 40),
"Foot, Left" = list(/obj/item/organ/external/foot, 40), "Foot, Left" = list(/obj/item/organ/external/foot, 20),
"Foot, Right" = list(/obj/item/organ/external/foot/right, 40), "Foot, Right" = list(/obj/item/organ/external/foot/right, 20),
"Hand, Left" = list(/obj/item/organ/external/hand, 40), "Hand, Left" = list(/obj/item/organ/external/hand, 20),
"Hand, Right" = list(/obj/item/organ/external/hand/right, 40) "Hand, Right" = list(/obj/item/organ/external/hand/right, 20)
) )
/obj/machinery/organ_printer/attackby(var/obj/item/O, var/mob/user) /obj/machinery/organ_printer/attackby(var/obj/item/O, var/mob/user)
@@ -57,25 +59,27 @@
/obj/machinery/organ_printer/New() /obj/machinery/organ_printer/New()
..() ..()
component_parts = list() 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)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src) component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
RefreshParts() RefreshParts()
/obj/machinery/organ_printer/examine(var/mob/user) /obj/machinery/organ_printer/examine(var/mob/user)
. = ..() . = ..()
to_chat(user, "<span class='notice'>It is loaded with [stored_matter]/[max_stored_matter] matter units.</span>") var/biomass = get_biomass_volume()
if(biomass)
to_chat(user, "<span class='notice'>It is loaded with [biomass] units of biomass.</span>")
else
to_chat(user, "<span class='notice'>It is not loaded with any biomass.</span>")
/obj/machinery/organ_printer/RefreshParts() /obj/machinery/organ_printer/RefreshParts()
print_delay = initial(print_delay) // Print Delay updating
max_stored_matter = 0 print_delay = base_print_delay
for(var/obj/item/weapon/stock_parts/matter_bin/bin in component_parts)
max_stored_matter += bin.rating * 100
for(var/obj/item/weapon/stock_parts/manipulator/manip in component_parts) for(var/obj/item/weapon/stock_parts/manipulator/manip in component_parts)
print_delay -= (manip.rating-1)*10 print_delay -= (manip.rating-1)*10
print_delay = max(0,print_delay) print_delay = max(0,print_delay)
. = ..() . = ..()
/obj/machinery/organ_printer/attack_hand(mob/user) /obj/machinery/organ_printer/attack_hand(mob/user)
@@ -91,6 +95,14 @@
to_chat(user, "<span class='notice'>\The [src] is busy!</span>") to_chat(user, "<span class='notice'>\The [src] is busy!</span>")
return 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, "<span class='warning'>\The [src] can't operate without a reagent reservoir!</span>")
/obj/machinery/organ_printer/proc/printing_menu(mob/user)
var/choice = input("What would you like to print?") as null|anything in products var/choice = input("What would you like to print?") as null|anything in products
if(!choice || printing || (stat & (BROKEN|NOPOWER))) if(!choice || printing || (stat & (BROKEN|NOPOWER)))
@@ -99,7 +111,7 @@
if(!can_print(choice)) if(!can_print(choice))
return return
stored_matter -= products[choice][2] container.reagents.remove_reagent("biomass", products[choice][2])
use_power = 2 use_power = 2
printing = 1 printing = 1
@@ -118,9 +130,42 @@
print_organ(choice) 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) /obj/machinery/organ_printer/proc/can_print(var/choice)
if(stored_matter < products[choice][2]) var/biomass = get_biomass_volume()
visible_message("<span class='notice'>\The [src] displays a warning: 'Not enough matter. [stored_matter] stored and [products[choice][2]] needed.'</span>") if(biomass < products[choice][2])
visible_message("<span class='notice'>\The [src] displays a warning: 'Not enough biomass. [biomass] stored and [products[choice][2]] needed.'</span>")
return 0 return 0
if(!loaded_dna || !loaded_dna["donor"]) if(!loaded_dna || !loaded_dna["donor"])
@@ -162,6 +207,59 @@
/obj/item/weapon/stock_parts/matter_bin = 2, /obj/item/weapon/stock_parts/matter_bin = 2,
/obj/item/weapon/stock_parts/manipulator = 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("<span class='info'>\The [src] dings, then spits out \a [O].</span>")
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, "<span class='info'>You scan the blood sample into the bioprinter.</span>")
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, "<span class='warning'>\The [src] already has a container loaded!</span>")
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 /obj/item/weapon/circuitboard/roboprinter
name = "roboprinter circuit" name = "roboprinter circuit"
build_path = /obj/machinery/organ_printer/robot build_path = /obj/machinery/organ_printer/robot
@@ -224,53 +322,4 @@
return return
return ..() return ..()
// END ROBOT ORGAN PRINTER // 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("<span class='info'>\The [src] dings, then spits out \a [O].</span>")
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, "<span class='warning'>\The [src] is too full.</span>")
return
stored_matter += amount_per_slab
user.drop_item()
to_chat(user, "<span class='info'>\The [src] processes \the [W]. Levels of stored biomass now: [stored_matter]</span>")
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, "<span class='info'>You scan the blood sample into the bioprinter.</span>")
return
return ..()
// END FLESH ORGAN PRINTER

View File

@@ -23,7 +23,7 @@
break break
return selected return selected
#define CLONE_BIOMASS 150 #define CLONE_BIOMASS 60
/obj/machinery/clonepod /obj/machinery/clonepod
name = "cloning pod" name = "cloning pod"
@@ -33,17 +33,18 @@
circuit = /obj/item/weapon/circuitboard/clonepod circuit = /obj/item/weapon/circuitboard/clonepod
icon = 'icons/obj/cloning.dmi' icon = 'icons/obj/cloning.dmi'
icon_state = "pod_0" 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/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/heal_rate = 1
var/notoxin = 0
var/locked = 0 var/locked = 0
var/obj/machinery/computer/cloning/connected = null //So we remember the connected clone machine. 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/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/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/eject_wait = 0 // Don't eject them as soon as they are created fuckkk
var/biomass = CLONE_BIOMASS * 3
var/list/containers = list() // Beakers for our liquid biomass
var/container_limit = 3 // How many beakers can the machine hold?
/obj/machinery/clonepod/New() /obj/machinery/clonepod/New()
..() ..()
@@ -71,8 +72,6 @@
to_chat(user, "Current clone cycle is [round(completion)]% complete.") to_chat(user, "Current clone cycle is [round(completion)]% complete.")
return return
//Clonepod
//Start growing a human clone in the pod! //Start growing a human clone in the pod!
/obj/machinery/clonepod/proc/growclone(var/datum/dna2/record/R) /obj/machinery/clonepod/proc/growclone(var/datum/dna2/record/R)
if(mess || attempting) if(mess || attempting)
@@ -98,6 +97,9 @@
if(istype(modifier_type, /datum/modifier/no_clone)) if(istype(modifier_type, /datum/modifier/no_clone))
return 0 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!! attempting = 1 //One at a time!!
locked = 1 locked = 1
@@ -164,6 +166,7 @@
for(var/datum/language/L in R.languages) for(var/datum/language/L in R.languages)
H.add_language(L.name) H.add_language(L.name)
H.flavor_texts = R.flavor.Copy() H.flavor_texts = R.flavor.Copy()
H.suiciding = 0 H.suiciding = 0
attempting = 0 attempting = 0
@@ -171,16 +174,6 @@
//Grow clones to maturity then kick them out. FREELOADERS //Grow clones to maturity then kick them out. FREELOADERS
/obj/machinery/clonepod/process() /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("<span class = 'notice'>[src] sucks in and processes the nearby biomass.</span>")
if(stat & NOPOWER) //Autoeject if power is lost if(stat & NOPOWER) //Autoeject if power is lost
if(occupant) if(occupant)
locked = 0 locked = 0
@@ -250,11 +243,14 @@
else else
locked = 0 locked = 0
to_chat(user, "System unlocked.") to_chat(user, "System unlocked.")
else if(istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat)) else if(istype(W,/obj/item/weapon/reagent_containers/glass))
to_chat(user, "<span class='notice'>\The [src] processes \the [W].</span>") if(LAZYLEN(containers) >= container_limit)
biomass += 50 to_chat(user, "<span class='warning'>\The [src] has too many containers loaded!</span>")
user.drop_item() else if(do_after(user, 1 SECOND))
qdel(W) 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 return
else if(W.is_wrench()) else if(W.is_wrench())
if(locked && (anchored || occupant)) if(locked && (anchored || occupant))
@@ -271,7 +267,7 @@
user.visible_message("[user] secures [src] to the floor.", "You secure [src] to the floor.") user.visible_message("[user] secures [src] to the floor.", "You secure [src] to the floor.")
else else
user.visible_message("[user] unsecures [src] from the floor.", "You unsecure [src] from the floor.") 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 var/obj/item/device/multitool/M = W
M.connecting = src M.connecting = src
to_chat(user, "<span class='notice'>You load connection data from [src] to [M].</span>") to_chat(user, "<span class='notice'>You load connection data from [src] to [M].</span>")
@@ -308,10 +304,6 @@
heal_level = rating * 10 - 20 heal_level = rating * 10 - 20
heal_rate = round(rating / 4) heal_rate = round(rating / 4)
if(rating >= 8)
notoxin = 1
else
notoxin = 0
/obj/machinery/clonepod/verb/eject() /obj/machinery/clonepod/verb/eject()
set name = "Eject Cloner" set name = "Eject Cloner"
@@ -348,10 +340,66 @@
domutcheck(occupant) //Waiting until they're out before possible transforming. domutcheck(occupant) //Waiting until they're out before possible transforming.
occupant = null occupant = null
biomass -= CLONE_BIOMASS
update_icon() update_icon()
return 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() /obj/machinery/clonepod/proc/malfunction()
if(occupant) if(occupant)
connected_message("Critical Error!") connected_message("Critical Error!")
@@ -406,6 +454,12 @@
else if(mess) else if(mess)
icon_state = "pod_g" 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 //Health Tracker Implant
/obj/item/weapon/implant/health /obj/item/weapon/implant/health
@@ -479,7 +533,7 @@
/obj/item/weapon/disk/data/examine(mob/user) /obj/item/weapon/disk/data/examine(mob/user)
..(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 return
/* /*

View File

@@ -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) if(!istype(transfer) || locate(/mob/living/silicon/ai) in src)
return return
if(transfer.controlling_drone)
transfer.controlling_drone.release_ai_control("Unit control lost. Core transfer completed.")
transfer.aiRestorePowerRoutine = 0 transfer.aiRestorePowerRoutine = 0
transfer.control_disabled = 0 transfer.control_disabled = 0
transfer.aiRadio.disabledAi = 0 transfer.aiRadio.disabledAi = 0

View File

@@ -67,7 +67,7 @@
user.drop_item() user.drop_item()
W.loc = src W.loc = src
diskette = W diskette = W
user << "You insert [W]." to_chat(user, "You insert [W].")
updateUsrDialog() updateUsrDialog()
return return
else if(istype(W, /obj/item/device/multitool)) else if(istype(W, /obj/item/device/multitool))
@@ -77,7 +77,7 @@
pods += P pods += P
P.connected = src P.connected = src
P.name = "[initial(P.name)] #[pods.len]" P.name = "[initial(P.name)] #[pods.len]"
user << "<span class='notice'>You connect [P] to [src].</span>" to_chat(user, "<span class='notice'>You connect [P] to [src].</span>")
else if (menu == 4 && (istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda))) else if (menu == 4 && (istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda)))
if(check_access(W)) if(check_access(W))
@@ -116,7 +116,7 @@
var/pods_list_ui[0] var/pods_list_ui[0]
for(var/obj/machinery/clonepod/pod in pods) 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) if(pods)
data["pods"] = pods_list_ui data["pods"] = pods_list_ui
@@ -244,7 +244,7 @@
//Look for that player! They better be dead! //Look for that player! They better be dead!
if(istype(C)) if(istype(C))
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs. //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." temp = "Error: No clone pods detected."
else else
var/obj/machinery/clonepod/pod = pods[1] 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 pod = input(usr,"Select a cloning pod to use", "Pod selection") as anything in pods
if(pod.occupant) if(pod.occupant)
temp = "Error: Clonepod is currently occupied." temp = "Error: Clonepod is currently occupied."
else if(pod.biomass < CLONE_BIOMASS) else if(pod.get_biomass() < CLONE_BIOMASS)
temp = "Error: Not enough biomass." temp = "Error: Not enough biomass."
else if(pod.mess) else if(pod.mess)
temp = "Error: Clonepod malfunction." temp = "Error: Clonepod malfunction."
else if(!config.revival_cloning) else if(!config.revival_cloning)
temp = "Error: Unable to initiate cloning cycle." temp = "Error: Unable to initiate cloning cycle."
else if(pod.growclone(C)) else if(pod.growclone(C))
temp = "Initiating cloning cycle..." temp = "Initiating cloning cycle..."
records.Remove(C) records.Remove(C)

View File

@@ -28,6 +28,9 @@
var/obj/machinery/computer3/laptop/stored_computer = null 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() /obj/item/device/laptop/verb/open_computer()
set name = "Open Laptop" set name = "Open Laptop"
set category = "Object" set category = "Object"

View File

@@ -47,6 +47,7 @@
var/check_synth = 0 //if active, will shoot at anything not an AI or cyborg 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/check_all = 0 //If active, will fire on anything, including synthetics.
var/ailock = 0 // AI cannot use this 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!) 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 lethal = 1
installation = /obj/item/weapon/gun/energy/laser 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 /obj/machinery/porta_turret/ai_defense
name = "defense turret" name = "defense turret"
desc = "This variant appears to be much more durable." desc = "This variant appears to be much more durable."
@@ -552,6 +558,9 @@ var/list/turret_icons
if(!L) if(!L)
return TURRET_NOT_TARGET 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. if(!emagged && issilicon(L) && check_all == 0) // Don't target silica, unless told to neutralize everything.
return TURRET_NOT_TARGET return TURRET_NOT_TARGET

View File

@@ -41,35 +41,12 @@ obj/machinery/recharger
return return
if(istype(G, /obj/item/weapon/gun/energy)) if(istype(G, /obj/item/weapon/gun/energy))
var/obj/item/weapon/gun/energy/E = G var/obj/item/weapon/gun/energy/E = G
if(!E.power_supply)
to_chat(user, "<span class='notice'>Your gun has no power cell.</span>")
return
if(E.self_recharge) if(E.self_recharge)
to_chat(user, "<span class='notice'>Your gun has no recharge port.</span>") to_chat(user, "<span class='notice'>Your gun has no recharge port.</span>")
return 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 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, "<span class='warning'>The assembly doesn't have a power cell.</span>")
return
if(istype(G, /obj/item/weapon/weldingtool/electric))
var/obj/item/weapon/weldingtool/electric/welder = G
if(!welder.power_supply)
to_chat(user, "<span class='notice'>Your welder has no power cell.</span>")
return
user.drop_item() user.drop_item()
G.loc = src G.loc = src
@@ -109,71 +86,8 @@ obj/machinery/recharger
update_use_power(1) update_use_power(1)
icon_state = icon_state_idle icon_state = icon_state_idle
else else
if(istype(charging, /obj/item/weapon/gun/energy)) var/obj/item/weapon/cell/C = charging.get_cell()
var/obj/item/weapon/gun/energy/E = charging if(istype(C))
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
if(!C.fully_charged()) if(!C.fully_charged())
icon_state = icon_state_charging icon_state = icon_state_charging
C.give(active_power_usage*CELLRATE) C.give(active_power_usage*CELLRATE)
@@ -181,48 +95,17 @@ obj/machinery/recharger
else else
icon_state = icon_state_charged icon_state = icon_state_charged
update_use_power(1) 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) /obj/machinery/recharger/emp_act(severity)
if(stat & (NOPOWER|BROKEN) || !anchored) if(stat & (NOPOWER|BROKEN) || !anchored)
..(severity) ..(severity)
return return
if(istype(charging, /obj/item/weapon/gun/energy)) if(charging)
var/obj/item/weapon/gun/energy/E = charging var/obj/item/weapon/cell/C = charging.get_cell()
if(E.power_supply) if(istype(C))
E.power_supply.emp_act(severity) 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) ..(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. /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 else
icon_state = icon_state_idle icon_state = icon_state_idle
/obj/machinery/recharger/wallcharger /obj/machinery/recharger/wallcharger
name = "wall recharger" name = "wall recharger"
icon = 'icons/obj/stationobjs.dmi' icon = 'icons/obj/stationobjs.dmi'

View File

@@ -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 //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() /obj/effect/decal/cleanable/mucus/mapped/New()
...() ..()
virus2 = new /datum/disease2/disease virus2 = new /datum/disease2/disease
virus2.makerandom() virus2.makerandom()

View File

@@ -46,4 +46,21 @@
/obj/effect/temporary_effect/shuttle_landing/initialize() /obj/effect/temporary_effect/shuttle_landing/initialize()
flick("shuttle_warning", src) // flick() forces the animation to always begin at the start. 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 <i>shocked</i> you must be, to see this text. You must have <i>lightning</i> reflexes. \
The humor in this description is just so <i>electrifying</i>."
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)
. = ..() . = ..()

View File

@@ -31,6 +31,7 @@ GLOBAL_LIST_BOILERPLATE(all_portals, /obj/effect/portal)
return return
/obj/effect/portal/New() /obj/effect/portal/New()
..() // Necessary for the list boilerplate to work
spawn(300) spawn(300)
qdel(src) qdel(src)
return return

View File

@@ -1254,7 +1254,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(isnull(cartridge)) if(isnull(cartridge))
to_chat(usr, "<span class='notice'>There's no cartridge to eject.</span>") to_chat(usr, "<span class='notice'>There's no cartridge to eject.</span>")
return return
cartridge.forceMove(get_turf(src)) cartridge.forceMove(get_turf(src))
if(ismob(loc)) if(ismob(loc))
@@ -1382,7 +1382,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
to_chat(user, "<span class='notice'>Blood type: [C:blood_DNA[blood]]\nDNA: [blood]</span>") to_chat(user, "<span class='notice'>Blood type: [C:blood_DNA[blood]]\nDNA: [blood]</span>")
if(4) if(4)
user.visible_message("<span class='warning'>\The [user] has analyzed [C]'s radiation levels!</span>", 1) user.visible_message("<span class='warning'>\The [user] has analyzed [C]'s radiation levels!</span>", "<span class='notice'>You have analyzed [C]'s radiation levels!</span>")
to_chat(user, "<span class='notice'>Analyzing Results for [C]:</span>") to_chat(user, "<span class='notice'>Analyzing Results for [C]:</span>")
if(C.radiation) if(C.radiation)
to_chat(user, "<span class='notice'>Radiation Level: [C.radiation]</span>") to_chat(user, "<span class='notice'>Radiation Level: [C.radiation]</span>")

View File

@@ -64,20 +64,24 @@
add_attack_logs(user,carded_ai,"Purged from AI Card") add_attack_logs(user,carded_ai,"Purged from AI Card")
flush = 1 flush = 1
carded_ai.suiciding = 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) 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.adjustOxyLoss(2)
carded_ai.updatehealth() carded_ai.updatehealth()
sleep(10) sleep(10)
flush = 0 flush = 0
if (href_list["radio"]) if (href_list["radio"])
carded_ai.aiRadio.disabledAi = text2num(href_list["radio"]) carded_ai.aiRadio.disabledAi = text2num(href_list["radio"])
carded_ai << "<span class='warning'>Your Subspace Transceiver has been [carded_ai.aiRadio.disabledAi ? "disabled" : "enabled"]!</span>" to_chat(carded_ai, "<span class='warning'>Your Subspace Transceiver has been [carded_ai.aiRadio.disabledAi ? "disabled" : "enabled"]!</span>")
user << "<span class='notice'>You [carded_ai.aiRadio.disabledAi ? "disable" : "enable"] the AI's Subspace Transceiver.</span>" to_chat(user, "<span class='notice'>You [carded_ai.aiRadio.disabledAi ? "disable" : "enable"] the AI's Subspace Transceiver.</span>")
if (href_list["wireless"]) if (href_list["wireless"])
carded_ai.control_disabled = text2num(href_list["wireless"]) carded_ai.control_disabled = text2num(href_list["wireless"])
carded_ai << "<span class='warning'>Your wireless interface has been [carded_ai.control_disabled ? "disabled" : "enabled"]!</span>" to_chat(carded_ai, "<span class='warning'>Your wireless interface has been [carded_ai.control_disabled ? "disabled" : "enabled"]!</span>")
user << "<span class='notice'>You [carded_ai.control_disabled ? "disable" : "enable"] the AI's wireless interface.</span>" to_chat(user, "<span class='notice'>You [carded_ai.control_disabled ? "disable" : "enable"] the AI's wireless interface.</span>")
if(carded_ai.control_disabled && carded_ai.controlling_drone)
carded_ai.controlling_drone.release_ai_control("Unit control terminated at intellicore port.")
update_icon() update_icon()
return 1 return 1
@@ -94,12 +98,12 @@
icon_state = "aicard" icon_state = "aicard"
/obj/item/device/aicard/proc/grab_ai(var/mob/living/silicon/ai/ai, var/mob/living/user) /obj/item/device/aicard/proc/grab_ai(var/mob/living/silicon/ai/ai, var/mob/living/user)
if(!ai.client) if(!ai.client && !ai.controlling_drone)
user << "<span class='danger'>ERROR:</span> AI [ai.name] is offline. Unable to transfer." to_chat(user, "<span class='danger'>ERROR:</span> AI [ai.name] is offline. Unable to transfer.")
return 0 return 0
if(carded_ai) if(carded_ai)
user << "<span class='danger'>Transfer failed:</span> Existing AI found on remote device. Remove existing AI to install a new one." to_chat(user, "<span class='danger'>Transfer failed:</span> Existing AI found on remote device. Remove existing AI to install a new one.")
return 0 return 0
if(!user.IsAdvancedToolUser() && isanimal(user)) if(!user.IsAdvancedToolUser() && isanimal(user))
@@ -108,7 +112,9 @@
return 0 return 0
user.visible_message("\The [user] starts transferring \the [ai] into \the [src]...", "You start transferring \the [ai] into \the [src]...") user.visible_message("\The [user] starts transferring \the [ai] into \the [src]...", "You start transferring \the [ai] into \the [src]...")
ai << "<span class='danger'>\The [user] is transferring you into \the [src]!</span>" to_chat(ai, "<span class='danger'>\The [user] is transferring you into \the [src]!</span>")
if(ai.controlling_drone)
to_chat(ai.controlling_drone, "<span class='danger'>\The [user] is transferring you into \the [src]!</span>")
if(do_after(user, 100)) if(do_after(user, 100))
if(istype(ai.loc, /turf/)) if(istype(ai.loc, /turf/))
@@ -124,11 +130,13 @@
ai.control_disabled = 1 ai.control_disabled = 1
ai.aiRestorePowerRoutine = 0 ai.aiRestorePowerRoutine = 0
carded_ai = ai carded_ai = ai
if(ai.controlling_drone)
ai.controlling_drone.release_ai_control("Unit control lost.")
if(ai.client) 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) if(user.client)
user << "<span class='notice'><b>Transfer successful:</b></span> [ai.name] extracted from current device and placed within mobile core." to_chat(ai, "<span class='notice'><b>Transfer successful:</b></span> [ai.name] extracted from current device and placed within mobile core.")
ai.canmove = 1 ai.canmove = 1
update_icon() update_icon()

View File

@@ -69,17 +69,16 @@
im_list_ui[++im_list_ui.len] = list("address" = I["address"], "to_address" = I["to_address"], "im" = I["im"]) im_list_ui[++im_list_ui.len] = list("address" = I["address"], "to_address" = I["to_address"], "im" = I["im"])
//Weather reports. //Weather reports.
if(planet_controller) for(var/datum/planet/planet in SSplanets.planets)
for(var/datum/planet/planet in planet_controller.planets) if(planet.weather_holder && planet.weather_holder.current_weather)
if(planet.weather_holder && planet.weather_holder.current_weather) var/list/W = list(
var/list/W = list( "Planet" = planet.name,
"Planet" = planet.name, "Time" = planet.current_time.show_time("hh:mm"),
"Time" = planet.current_time.show_time("hh:mm"), "Weather" = planet.weather_holder.current_weather.name,
"Weather" = planet.weather_holder.current_weather.name, "Temperature" = planet.weather_holder.temperature - T0C,
"Temperature" = planet.weather_holder.temperature - T0C, "High" = planet.weather_holder.current_weather.temp_high - T0C,
"High" = planet.weather_holder.current_weather.temp_high - T0C, "Low" = planet.weather_holder.current_weather.temp_low - T0C)
"Low" = planet.weather_holder.current_weather.temp_low - T0C) weather[++weather.len] = W
weather[++weather.len] = W
injection = "<div>Test</div>" injection = "<div>Test</div>"

View File

@@ -41,6 +41,9 @@
processing_objects -= src processing_objects -= src
return ..() return ..()
/obj/item/device/flashlight/get_cell()
return cell
/obj/item/device/flashlight/verb/toggle() /obj/item/device/flashlight/verb/toggle()
set name = "Toggle Flashlight Brightness" set name = "Toggle Flashlight Brightness"
set category = "Object" set category = "Object"

View File

@@ -10,44 +10,162 @@
var/insults = 0 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!") 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)
if(user.client.prefs.muted & MUTE_IC) if(user.client.prefs.muted & MUTE_IC)
src << "<span class='warning'>You cannot speak in IC (muted).</span>" to_chat(user, "<span class='warning'>You cannot speak in IC (muted).</span>")
return return 0
if(!ishuman(user)) if(!(ishuman(user) || user.isSynthetic()))
user << "<span class='warning'>You don't know how to use this!</span>" to_chat(user, "<span class='warning'>You don't know how to use this!</span>")
return return 0
if(user.silent) if(user.silent)
return return 0
if(spamcheck) if(spamcheck)
user << "<span class='warning'>\The [src] needs to recharge!</span>" to_chat(user, "<span class='warning'>\The [src] needs to recharge!</span>")
return return 0
return 1
var/message = sanitize(input(user, "Shout a message?", "Megaphone", null) as text) /obj/item/device/megaphone/proc/do_broadcast(var/mob/living/user, var/message)
if(!message)
return
message = capitalize(message)
if ((src.loc == user && usr.stat == 0)) if ((src.loc == user && usr.stat == 0))
if(emagged) if(emagged)
if(insults) if(insults)
for(var/mob/O in (viewers(user))) user.audible_message("<B>[user]</B> broadcasts, <FONT size=3>\"[pick(insultmsg)]\"</FONT>")
O.show_message("<B>[user]</B> broadcasts, <FONT size=3>\"[pick(insultmsg)]\"</FONT>",2) // 2 stands for hearable message
insults-- insults--
else else
user << "<span class='warning'>*BZZZZzzzzzt*</span>" to_chat(user, "<span class='warning'>*BZZZZzzzzzt*</span>")
else else
for(var/mob/O in (viewers(user))) user.audible_message("<B>[user]</B> broadcasts, <FONT size=3>\"[message]\"</FONT>")
O.show_message("<B>[user]</B> broadcasts, <FONT size=3>\"[message]\"</FONT>",2) // 2 stands for hearable message
spamcheck = 1 spamcheck = 1
spawn(20) spawn(20)
spamcheck = 0 spamcheck = 0
return 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) /obj/item/device/megaphone/emag_act(var/remaining_charges, var/mob/user)
if(!emagged) if(!emagged)
user << "<span class='warning'>You overload \the [src]'s voice synthesizer.</span>" to_chat(user, "<span class='warning'>You overload \the [src]'s voice synthesizer.</span>")
emagged = 1 emagged = 1
insults = rand(1, 3)//to prevent dickflooding insults = rand(1, 3)//to prevent caps spam.
return 1 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, "<span class='notice'>\The [src] emits a <font face='comic sans ms' color='#ff69b4'>silly</font> sound.</span>")
if(!("#ff69b4" in color_options))
color_options = list("#ff69b4")
broadcast_color = "#ff69b4"
if(insults <= 0)
insults = rand(1,3)
to_chat(user, "<span class='warning'>You re-scramble \the [src]'s voice synthesizer.</span>")
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("<B>[user]</B> broadcasts, <FONT size=[broadcast_size] face='[broadcast_font]' color='[broadcast_color]'>\"[pick(insultmsg)]\"</FONT>")
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("<span class='critical'>*BZZZZzzzzzt*</span>")
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("<span class='warning'>\The [src] sparks violently!</span>")
spawn(30)
explosion(get_turf(src), -1, -1, 1, 3, adminlog = 1)
qdel(src)
return
else
user.audible_message("<B>[user]</B> broadcasts, <FONT size=[broadcast_size] face='[broadcast_font]' color='[broadcast_color]'>\"[message]\"</FONT>")
spamcheck = 1
spawn(20)
spamcheck = 0
return

View File

@@ -38,6 +38,9 @@ var/global/list/active_radio_jammers = list()
qdel_null(power_source) qdel_null(power_source)
return ..() return ..()
/obj/item/device/radio_jammer/get_cell()
return power_source
/obj/item/device/radio_jammer/proc/turn_off(mob/user) /obj/item/device/radio_jammer/proc/turn_off(mob/user)
if(user) if(user)
to_chat(user,"<span class='warning'>\The [src] deactivates.</span>") to_chat(user,"<span class='warning'>\The [src] deactivates.</span>")

View File

@@ -52,8 +52,9 @@
/obj/structure/largecrate/animal/crashedshuttle /obj/structure/largecrate/animal/crashedshuttle
name = "SCP" name = "SCP"
/obj/structure/largecrate/animal/crashedshuttle/initialize() /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 = 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" name += " delivery crate"
return ..() return ..()

View File

@@ -199,3 +199,9 @@
throw_range = 20 throw_range = 20
flags = 0 flags = 0
no_variants = FALSE 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"

View File

@@ -1042,6 +1042,50 @@
name = "tuxedo cat plushie" name = "tuxedo cat plushie"
icon_state = "tuxedocat" 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 /obj/item/toy/plushie/therapy/red
name = "red therapy doll" name = "red therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is red." desc = "A toy for therapeutic and recreational purposes. This one is red."

View File

@@ -153,7 +153,7 @@
return 0 return 0
if(build_turf) if(build_turf)
T.ChangeTurf(build_turf) T.ChangeTurf(build_turf, preserve_outdoors = TRUE)
else if(build_other) else if(build_other)
new build_other(T) new build_other(T)
else else

View File

@@ -167,21 +167,24 @@
if(!istype(M)) if(!istype(M))
return 0 return 0
if (user.a_intent == I_HELP)
return ..()
if(target_name != M.name) if(target_name != M.name)
target_name = M.name target_name = M.name
src.wdata = list() src.wdata = list()
src.chemtraces = list() src.chemtraces = list()
src.timeofdeath = null src.timeofdeath = null
user << "<span class='notice'>A new patient has been registered. Purging data for previous patient.</span>" to_chat(user, "<span class='notice'>A new patient has been registered. Purging data for previous patient.</span>")
src.timeofdeath = M.timeofdeath src.timeofdeath = M.timeofdeath
var/obj/item/organ/external/S = M.get_organ(user.zone_sel.selecting) var/obj/item/organ/external/S = M.get_organ(user.zone_sel.selecting)
if(!S) if(!S)
usr << "<span class='warning'>You can't scan this body part.</span>" to_chat(user, "<span class='warning'>You can't scan this body part.</span>")
return return
if(!S.open) if(!S.open)
usr << "<span class='warning'>You have to cut [S] open first!</span>" to_chat(user, "<span class='warning'>You have to cut [S] open first!</span>")
return return
M.visible_message("<span class='notice'>\The [user] scans the wounds on [M]'s [S.name] with [src]</span>") M.visible_message("<span class='notice'>\The [user] scans the wounds on [M]'s [S.name] with [src]</span>")

View File

@@ -21,12 +21,26 @@
/obj/item/weapon/implant/proc/activate() /obj/item/weapon/implant/proc/activate()
return return
// What does the implant do upon injection? // Moves the implant where it needs to go, and tells it if there's more to be done in post_implant
// return 0 if the implant fails (ex. Revhead and loyalty implant.) /obj/item/weapon/implant/proc/handle_implant(var/mob/source, var/target_zone = BP_TORSO)
// return 1 if the implant succeeds (ex. Nonrevhead and loyalty implant.) . = TRUE
/obj/item/weapon/implant/proc/implanted(var/mob/source) 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 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() /obj/item/weapon/implant/proc/get_data()
return "No information available" return "No information available"
@@ -49,6 +63,12 @@
icon_state = "implant_melted" icon_state = "implant_melted"
malfunction = MALFUNCTION_PERMANENT 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() /obj/item/weapon/implant/Destroy()
if(part) if(part)
part.implants.Remove(src) part.implants.Remove(src)
@@ -69,6 +89,11 @@
else else
..() ..()
//////////////////////////////
// Tracking Implant
//////////////////////////////
GLOBAL_LIST_BOILERPLATE(all_tracking_implants, /obj/item/weapon/implant/tracking) GLOBAL_LIST_BOILERPLATE(all_tracking_implants, /obj/item/weapon/implant/tracking)
/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) 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) processing_objects.Add(src)
return 1
/obj/item/weapon/implant/tracking/Destroy() /obj/item/weapon/implant/tracking/Destroy()
processing_objects.Remove(src) processing_objects.Remove(src)
@@ -142,7 +166,9 @@ Implant Specifics:<BR>"}
spawn(delay) spawn(delay)
malfunction-- malfunction--
//////////////////////////////
// Death Explosive Implant
//////////////////////////////
/obj/item/weapon/implant/dexplosive /obj/item/weapon/implant/dexplosive
name = "explosive" name = "explosive"
desc = "And boom goes the weasel." desc = "And boom goes the weasel."
@@ -177,7 +203,9 @@ Implant Specifics:<BR>"}
/obj/item/weapon/implant/dexplosive/islegal() /obj/item/weapon/implant/dexplosive/islegal()
return 0 return 0
//BS12 Explosive //////////////////////////////
// Explosive Implant
//////////////////////////////
/obj/item/weapon/implant/explosive /obj/item/weapon/implant/explosive
name = "explosive implant" name = "explosive implant"
desc = "A military grade micro bio-explosive. Highly dangerous." desc = "A military grade micro bio-explosive. Highly dangerous."
@@ -249,15 +277,13 @@ Implant Specifics:<BR>"}
if(t) if(t)
t.hotspot_expose(3500,125) 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") elevel = alert("What sort of explosion would you prefer?", "Implant Intent", "Localized Limb", "Destroy Body", "Full Explosion")
phrase = input("Choose activation phrase:") as text phrase = input("Choose activation phrase:") as text
var/list/replacechars = list("'" = "","\"" = "",">" = "","<" = "","(" = "",")" = "") var/list/replacechars = list("'" = "","\"" = "",">" = "","<" = "","(" = "",")" = "")
phrase = replace_characters(phrase, replacechars) phrase = replace_characters(phrase, replacechars)
usr.mind.store_memory("Explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', <B>say [src.phrase]</B> to attempt to activate.", 0, 0) usr.mind.store_memory("Explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', <B>say [src.phrase]</B> to attempt to activate.", 0, 0)
usr << "The implanted explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', <B>say [src.phrase]</B> to attempt to activate." usr << "The implanted explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', <B>say [src.phrase]</B> to attempt to activate."
listening_objects |= src
return 1
/obj/item/weapon/implant/explosive/emp_act(severity) /obj/item/weapon/implant/explosive/emp_act(severity)
if (malfunction) if (malfunction)
@@ -311,6 +337,9 @@ Implant Specifics:<BR>"}
explosion(get_turf(imp_in), -1, -1, 1, 3) explosion(get_turf(imp_in), -1, -1, 1, 3)
qdel(src) qdel(src)
//////////////////////////////
// Chemical Implant
//////////////////////////////
GLOBAL_LIST_BOILERPLATE(all_chem_implants, /obj/item/weapon/implant/chem) GLOBAL_LIST_BOILERPLATE(all_chem_implants, /obj/item/weapon/implant/chem)
/obj/item/weapon/implant/chem /obj/item/weapon/implant/chem
@@ -336,20 +365,17 @@ Can only be loaded while still in its original case.<BR>
the implant may become unstable and either pre-maturely inject the subject or simply break."} the implant may become unstable and either pre-maturely inject the subject or simply break."}
return dat return dat
/obj/item/weapon/implant/chem/New() /obj/item/weapon/implant/chem/New()
..() ..()
var/datum/reagents/R = new/datum/reagents(50) var/datum/reagents/R = new/datum/reagents(50)
reagents = R reagents = R
R.my_atom = src R.my_atom = src
/obj/item/weapon/implant/chem/trigger(emote, source as mob) /obj/item/weapon/implant/chem/trigger(emote, source as mob)
if(emote == "deathgasp") if(emote == "deathgasp")
src.activate(src.reagents.total_volume) src.activate(src.reagents.total_volume)
return return
/obj/item/weapon/implant/chem/activate(var/cause) /obj/item/weapon/implant/chem/activate(var/cause)
if((!cause) || (!src.imp_in)) return 0 if((!cause) || (!src.imp_in)) return 0
var/mob/living/carbon/R = src.imp_in 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) spawn(20)
malfunction-- malfunction--
//////////////////////////////
// Loyalty Implant
//////////////////////////////
/obj/item/weapon/implant/loyalty /obj/item/weapon/implant/loyalty
name = "loyalty implant" name = "loyalty implant"
desc = "Makes you loyal or such." desc = "Makes you loyal or such."
@@ -401,20 +430,24 @@ the implant may become unstable and either pre-maturely inject the subject or si
<b>Integrity:</b> Implant will last so long as the nanobots are inside the bloodstream."} <b>Integrity:</b> Implant will last so long as the nanobots are inside the bloodstream."}
return dat return dat
/obj/item/weapon/implant/loyalty/handle_implant(mob/M, target_zone = BP_TORSO)
/obj/item/weapon/implant/loyalty/implanted(mob/M) . = ..(M, target_zone)
if(!istype(M, /mob/living/carbon/human)) return 0 if(!istype(M, /mob/living/carbon/human))
. = FALSE
var/mob/living/carbon/human/H = M var/mob/living/carbon/human/H = M
var/datum/antagonist/antag_data = get_antag_data(H.mind.special_role) var/datum/antagonist/antag_data = get_antag_data(H.mind.special_role)
if(antag_data && (antag_data.flags & ANTAG_IMPLANT_IMMUNE)) 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!") 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 . = FALSE
else
clear_antag_roles(H.mind, 1)
H << "<span class='notice'>You feel a surge of loyalty towards [using_map.company_name].</span>"
return 1
/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, "<span class='notice'>You feel a surge of loyalty towards [using_map.company_name].</span>")
//////////////////////////////
// Adrenaline Implant
//////////////////////////////
/obj/item/weapon/implant/adrenalin /obj/item/weapon/implant/adrenalin
name = "adrenalin" name = "adrenalin"
desc = "Removes all stuns and knockdowns." 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 return
/obj/item/weapon/implant/adrenalin/post_implant(mob/source)
/obj/item/weapon/implant/adrenalin/implanted(mob/source)
source.mind.store_memory("A implant can be activated by using the pale emote, <B>say *pale</B> to attempt to activate.", 0, 0) source.mind.store_memory("A implant can be activated by using the pale emote, <B>say *pale</B> to attempt to activate.", 0, 0)
source << "The implanted freedom implant can be activated by using the pale emote, <B>say *pale</B> to attempt to activate." source << "The implanted freedom implant can be activated by using the pale emote, <B>say *pale</B> to attempt to activate."
listening_objects |= src
return 1
//////////////////////////////
// Death Alarm Implant
//////////////////////////////
/obj/item/weapon/implant/death_alarm /obj/item/weapon/implant/death_alarm
name = "death alarm implant" name = "death alarm implant"
desc = "An alarm which monitors host vital signs and transmits a radio message upon death." 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) spawn(20)
malfunction-- 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 mobname = source.real_name
processing_objects.Add(src) processing_objects.Add(src)
return 1
//////////////////////////////
// Compressed Matter Implant
//////////////////////////////
/obj/item/weapon/implant/compressed /obj/item/weapon/implant/compressed
name = "compressed matter implant" name = "compressed matter implant"
desc = "Based on compressed matter technology, can store a single item." 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 scanned.loc = t
qdel(src) 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") 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) if (source.mind)
source.mind.store_memory("Compressed matter implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate.", 0, 0) source.mind.store_memory("Compressed matter implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate.", 0, 0)
source << "The implanted compressed matter implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate." source << "The implanted compressed matter implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate."
listening_objects |= src
return 1
/obj/item/weapon/implant/compressed/islegal() /obj/item/weapon/implant/compressed/islegal()
return 0 return 0

View File

@@ -135,10 +135,9 @@
for (var/mob/O in viewers(M, null)) for (var/mob/O in viewers(M, null))
O.show_message("<span class='warning'>\The [M] has been implanted by \the [src].</span>", 1) O.show_message("<span class='warning'>\The [M] has been implanted by \the [src].</span>", 1)
if(imp.implanted(M)) if(imp.handle_implant(M, BP_TORSO))
imp.loc = M imp.post_implant(M)
imp.imp_in = M
imp.implanted = 1
implant_list -= imp implant_list -= imp
break break
return return

View File

@@ -56,16 +56,11 @@
add_attack_logs(user,M,"Implanted with [imp.name] using [name]") add_attack_logs(user,M,"Implanted with [imp.name] using [name]")
if(src.imp.implanted(M)) if(imp.handle_implant(M))
src.imp.loc = M imp.post_implant(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(ishuman(M))
var/mob/living/carbon/human/H = M
BITSET(H.hud_updateflag, IMPLOYAL_HUD) BITSET(H.hud_updateflag, IMPLOYAL_HUD)
src.imp = null src.imp = null

View File

@@ -16,7 +16,9 @@
/obj/item/weapon/implant/freedom/trigger(emote, mob/living/carbon/source as mob) /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) if (emote == src.activation_emote)
src.uses-- src.uses--
source << "You feel a faint click." source << "You feel a faint click."
@@ -46,13 +48,9 @@
W.layer = initial(W.layer) W.layer = initial(W.layer)
return return
/obj/item/weapon/implant/freedom/post_implant(mob/source)
/obj/item/weapon/implant/freedom/implanted(mob/living/carbon/source)
source.mind.store_memory("Freedom implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate.", 0, 0) source.mind.store_memory("Freedom implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate.", 0, 0)
source << "The implanted freedom implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate." source << "The implanted freedom implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate."
listening_objects |= src
return 1
/obj/item/weapon/implant/freedom/get_data() /obj/item/weapon/implant/freedom/get_data()
var/dat = {" var/dat = {"

View File

@@ -4,7 +4,26 @@
/obj/item/weapon/implant/language /obj/item/weapon/implant/language
name = "GalCom language implant" 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() /obj/item/weapon/implant/language/get_data()
var/dat = {" var/dat = {"
@@ -14,16 +33,19 @@
<b>Important Notes:</b> Affects hearing and speech.<BR> <b>Important Notes:</b> Affects hearing and speech.<BR>
<HR> <HR>
<b>Implant Details:</b><BR> <b>Implant Details:</b><BR>
<b>Function:</b> 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.<BR> <b>Function:</b> Allows a being otherwise incapable of speaking Galactic Common to produce the phonemes of the language.<BR>
<b>Special Features:</b> None.<BR> <b>Special Features:</b> None.<BR>
<b>Integrity:</b> Implant will function for expected life, barring physical damage."} <b>Integrity:</b> Implant will function for expected life, barring physical damage."}
return dat return dat
// EAL Implant
/obj/item/weapon/implant/language/eal /obj/item/weapon/implant/language/eal
name = "EAL language implant" 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 = {" var/dat = {"
<b>Implant Specifications:</b><BR> <b>Implant Specifications:</b><BR>
<b>Name:</b> Vey-Med L-2 Encoded Audio Language Implant<BR> <b>Name:</b> Vey-Med L-2 Encoded Audio Language Implant<BR>
@@ -31,7 +53,25 @@
<b>Important Notes:</b> Affects hearing and speech.<BR> <b>Important Notes:</b> Affects hearing and speech.<BR>
<HR> <HR>
<b>Implant Details:</b><BR> <b>Implant Details:</b><BR>
<b>Function:</b> Allows an organic to accurately process and speak Encoded Audio Language.<BR> <b>Function:</b> Allows an organic to accurately speak Encoded Audio Language.<BR>
<b>Special Features:</b> None.<BR>
<b>Integrity:</b> 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 = {"
<b>Implant Specifications:</b><BR>
<b>Name:</b> Vey-Med L-1 Galactic Common Implant<BR>
<b>Life:</b> 5 years<BR>
<b>Important Notes:</b> Affects hearing and speech.<BR>
<HR>
<b>Implant Details:</b><BR>
<b>Function:</b> Allows a being otherwise incapable of speaking Skrellian to produce the phonemes of the language.<BR>
<b>Special Features:</b> None.<BR> <b>Special Features:</b> None.<BR>
<b>Integrity:</b> Implant will function for expected life, barring physical damage."} <b>Integrity:</b> Implant will function for expected life, barring physical damage."}
return dat return dat

View File

@@ -11,15 +11,13 @@
..() ..()
return 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") 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, <B>say *[src.activation_emote]</B> to attempt to activate.", 0, 0) source.mind.store_memory("Uplink implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate.", 0, 0)
source << "The implanted uplink implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate." source << "The implanted uplink implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate."
listening_objects |= src
return 1
/obj/item/weapon/implant/uplink/trigger(emote, mob/source as mob) /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 if(hidden_uplink && usr == source) // Let's not have another people activate our uplink
hidden_uplink.check_trigger(source, emote, activation_emote) hidden_uplink.check_trigger(source, emote, activation_emote)
return return

View File

@@ -16,6 +16,7 @@ GLOBAL_LIST_BOILERPLATE(all_mops, /obj/item/weapon/mop)
/obj/item/weapon/mop/New() /obj/item/weapon/mop/New()
create_reagents(30) create_reagents(30)
..()
/obj/item/weapon/mop/afterattack(atom/A, mob/user, proximity) /obj/item/weapon/mop/afterattack(atom/A, mob/user, proximity)
if(!proximity) return if(!proximity) return

View File

@@ -4,6 +4,9 @@
icon = 'icons/policetape.dmi' icon = 'icons/policetape.dmi'
icon_state = "tape" icon_state = "tape"
w_class = ITEMSIZE_SMALL w_class = ITEMSIZE_SMALL
toolspeed = 3 //You can use it in surgery. It's stupid, but you can.
var/turf/start var/turf/start
var/turf/end var/turf/end
var/tape_type = /obj/item/tape var/tape_type = /obj/item/tape

View File

@@ -86,7 +86,6 @@
/obj/item/weapon/weldingtool, /obj/item/weapon/weldingtool,
/obj/item/weapon/tool/crowbar, /obj/item/weapon/tool/crowbar,
/obj/item/weapon/tool/wirecutters, /obj/item/weapon/tool/wirecutters,
/obj/item/device/t_scanner
) )
/obj/item/weapon/storage/belt/utility/chief /obj/item/weapon/storage/belt/utility/chief

View File

@@ -19,16 +19,19 @@
var/obj/item/weapon/cell/bcell = null var/obj/item/weapon/cell/bcell = null
var/hitcost = 240 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("<span class='suicide'>\The [user] is putting the live [name] in [TU.his] mouth! It looks like [TU.he] [TU.is] trying to commit suicide.</span>")
return (FIRELOSS)
/obj/item/weapon/melee/baton/New() /obj/item/weapon/melee/baton/New()
..() ..()
update_icon() update_icon()
return 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("<span class='suicide'>\The [user] is putting the live [name] in [TU.his] mouth! It looks like [TU.he] [TU.is] trying to commit suicide.</span>")
return (FIRELOSS)
/obj/item/weapon/melee/baton/MouseDrop(obj/over_object as obj) /obj/item/weapon/melee/baton/MouseDrop(obj/over_object as obj)
if(!canremove) if(!canremove)
return return

View File

@@ -5,8 +5,12 @@
icon_state = "taperoll" icon_state = "taperoll"
w_class = ITEMSIZE_TINY 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) /obj/item/weapon/tape_roll/attack(var/mob/living/carbon/human/H, var/mob/user)
if(istype(H)) if(istype(H))
if(user.a_intent == I_HELP)
return
var/can_place = 0 var/can_place = 0
if(istype(user, /mob/living/silicon/robot)) if(istype(user, /mob/living/silicon/robot))
can_place = 1 can_place = 1

View File

@@ -1,5 +1,5 @@
#define WELDER_FUEL_BURN_INTERVAL 13
#define WELDER_FUEL_BURN_INTERVAL 13
/* /*
* Welding Tool * Welding Tool
*/ */
@@ -63,7 +63,7 @@
/obj/item/weapon/weldingtool/attackby(obj/item/W as obj, mob/living/user as mob) /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) if(welding)
to_chat(user, "<span class='danger'>Stop welding first!</span>") to_chat(user, "<span class='danger'>Stop welding first!</span>")
return return
@@ -99,12 +99,15 @@
..() ..()
return return
/obj/item/weapon/weldingtool/process() /obj/item/weapon/weldingtool/process()
if(welding) if(welding)
++burned_fuel_for ++burned_fuel_for
if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL) if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL)
remove_fuel(1) remove_fuel(1)
if(get_fuel() < 1) if(get_fuel() < 1)
setWelding(0) setWelding(0)
@@ -118,6 +121,7 @@
if (istype(location, /turf)) if (istype(location, /turf))
location.hotspot_expose(700, 5) location.hotspot_expose(700, 5)
/obj/item/weapon/weldingtool/afterattack(obj/O as obj, mob/user as mob, proximity) /obj/item/weapon/weldingtool/afterattack(obj/O as obj, mob/user as mob, proximity)
if(!proximity) return if(!proximity) return
if (istype(O, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,O) <= 1) if (istype(O, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,O) <= 1)
@@ -146,6 +150,7 @@
location.hotspot_expose(700, 50, 1) location.hotspot_expose(700, 50, 1)
return return
/obj/item/weapon/weldingtool/attack_self(mob/user as mob) /obj/item/weapon/weldingtool/attack_self(mob/user as mob)
setWelding(!welding, usr) setWelding(!welding, usr)
return return
@@ -209,24 +214,6 @@
M.update_inv_l_hand() M.update_inv_l_hand()
M.update_inv_r_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, "<span class='warning'>You'll need to turn [src] on to patch the damage on [H]'s [S.name]!</span>")
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) /obj/item/weapon/weldingtool/MouseDrop(obj/over_object as obj)
if(!canremove) if(!canremove)
return return
@@ -349,9 +336,6 @@
/obj/item/weapon/weldingtool/is_hot() /obj/item/weapon/weldingtool/is_hot()
return isOn() return isOn()
/obj/item/weapon/weldingtool/is_welder()
return TRUE
/obj/item/weapon/weldingtool/largetank /obj/item/weapon/weldingtool/largetank
name = "industrial welding tool" name = "industrial welding tool"
desc = "A slightly larger welder with a larger tank." desc = "A slightly larger welder with a larger tank."
@@ -495,6 +479,9 @@
acti_sound = 'sound/effects/sparks4.ogg' acti_sound = 'sound/effects/sparks4.ogg'
deac_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() /obj/item/weapon/weldingtool/electric/New()
..() ..()
if(cell_type == null) if(cell_type == null)
@@ -505,17 +492,17 @@
power_supply = new /obj/item/weapon/cell/device(src) power_supply = new /obj/item/weapon/cell/device(src)
update_icon() update_icon()
/obj/item/weapon/weldingtool/electric/unloaded/New() /obj/item/weapon/weldingtool/electric/get_cell()
cell_type = null return power_supply
/obj/item/weapon/weldingtool/electric/examine(mob/user) /obj/item/weapon/weldingtool/electric/examine(mob/user)
if(get_dist(src, user) > 1) if(get_dist(src, user) > 1)
to_chat(user, desc) to_chat(user, desc)
else // The << need to stay, for some reason else // The << need to stay, for some reason
if(power_supply) 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 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() /obj/item/weapon/weldingtool/electric/get_fuel()
if(use_external_power) if(use_external_power)

View File

@@ -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) /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 return
/obj/proc/get_cell()
return

View File

@@ -16,6 +16,10 @@
starts_with = list(/obj/item/weapon/material/twohanded/fireaxe) 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 /obj/structure/closet/fireaxecabinet/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri
//..() //That's very useful, Erro //..() //That's very useful, Erro
@@ -115,6 +119,7 @@
if(src.locked) if(src.locked)
to_chat(user, "<span class='warning'>The cabinet won't budge!</span>") to_chat(user, "<span class='warning'>The cabinet won't budge!</span>")
return return
if(localopened) if(localopened)
if(fireaxe) if(fireaxe)
user.put_in_hands(fireaxe) user.put_in_hands(fireaxe)

View File

@@ -4,7 +4,8 @@
anchored = 1 anchored = 1
density = 1 density = 1
pixel_x = -16 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/base_state = null // Used for stumps.
var/health = 200 // Used for chopping down trees. var/health = 200 // Used for chopping down trees.
var/max_health = 200 var/max_health = 200
@@ -51,12 +52,12 @@
animate(transform=null, pixel_x=init_px, time=6, easing=ELASTIC_EASING) animate(transform=null, pixel_x=init_px, time=6, easing=ELASTIC_EASING)
// Used when the tree gets hurt. // 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) if(is_stump)
return return
// Bullets and lasers ruin some of the wood // 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) var/wood = initial(product_amount)
product_amount -= round(wood * (abs(amount)/max_health)) product_amount -= round(wood * (abs(amount)/max_health))
@@ -89,12 +90,16 @@
set_light(0) set_light(0)
/obj/structure/flora/tree/ex_act(var/severity) /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) /obj/structure/flora/tree/bullet_act(var/obj/item/projectile/Proj)
if(Proj.get_structure_damage()) if(Proj.get_structure_damage())
adjust_health(-Proj.get_structure_damage(), TRUE) 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() /obj/structure/flora/tree/get_description_interaction()
var/list/results = list() var/list/results = list()

View File

@@ -20,6 +20,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
/obj/structure/janitorialcart/New() /obj/structure/janitorialcart/New()
create_reagents(300) create_reagents(300)
..()
/obj/structure/janitorialcart/examine(mob/user) /obj/structure/janitorialcart/examine(mob/user)

View File

@@ -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 << "<span class='notice'>You start to cut the plastic flaps.</span>"
if(do_after(user, 10 * P.toolspeed))
user << "<span class='notice'>You cut the plastic flaps.</span>"
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
..()

View File

@@ -6,15 +6,6 @@
icon = 'icons/obj/abductor.dmi' icon = 'icons/obj/abductor.dmi'
density = TRUE density = TRUE
anchored = 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 /obj/structure/prop/alien/computer
name = "alien console" name = "alien console"

View File

@@ -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 = "<span class='notice'>The prismatic turret seems to be able to rotate.</span>"
/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, "<span class='warning'>\The [src] is locked at its current bearing.</span>")
return
if(external_control_lock)
to_chat(user, "<span class='warning'>\The [src]'s motors resist your efforts to rotate it. You may need to find some form of controller.</span>")
return
var/confirm = input("Do you want to try to rotate \the [src]?", "[name]") in list("Yes", "No")
if(confirm == "No")
visible_message(\
"<span class='notice'>[user.name] decides not to try turning \the [src].</span>",\
"<span class='notice'>You decide not to try turning \the [src].</span>")
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, "<span class='warning'>Rotating \the [src] [new_bearing] degrees would be a waste of time.</span>")
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("<span class='notice'>\The [src] shudders.</span>")
playsound(src, 'sound/effects/clang.ogg', 50, 1)
return
visible_message("<span class='notice'>\The [src] rotates to a bearing of [new_bearing].</span>")
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("<span class='danger'>\The [src] redirects \the [Proj]!</span>")
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 = "<span class='notice'>The dial pulses as your hand nears it.</span>"
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(\
"<span class='notice'>[user.name] decides not to try turning \the [src].</span>",\
"<span class='notice'>You decide not to try turning \the [src].</span>")
return
if(!my_turrets || !my_turrets.len)
to_chat(user, "<span class='notice'>\The [src] doesn't seem to do anything.</span>")
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, "<span class='warning'>Rotating \the [src] [new_bearing] degrees would be a waste of time.</span>")
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(\
"<span class='notice'>[user.name] decides not to try turning \the [src].</span>",\
"<span class='notice'>You decide not to try turning \the [src].</span>")
return
to_chat(user, "<span class='notice'>\The [src] clicks into place.</span>")
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()
..()

View File

@@ -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 = "<span class='notice'>The object remains inert to your touch.</span>"
/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("<span class='notice'>\The [src] [enabled ? "disengages" : "engages"] its locking mechanism.</span>")
if(timed)
timing = 1
spawn(time_limit)
toggle_lock()

View File

@@ -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)

View File

@@ -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("<span class='cult'>\The [src] is completely unaffected by \the [Proj].</span>")
qdel(Proj) //No piercing. No.
/obj/machinery/door/blast/puzzle/ex_act(severity)
visible_message("<span class='cult'>\The [src] is completely unaffected by the blast.</span>")
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, "<span class='notice'>\The [src] does not respond to your touch.</span>")
/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, "<span class='warning'>You need to be wielding \the [F] to do that.</span>")
return
if(check_locks())
force_toggle(1, user)
else
to_chat(user, "<span class='notice'>[src]'s arcane workings resist your effort.</span>")
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("<span class='danger'>\The [user] hits \the [src] with \the [W] with no visible effect.</span>")
else if(istype(C, /obj/item/weapon/plastique))
to_chat(user, "<span class='danger'>On contacting \the [src], a flash of light envelops \the [C] as it is turned to ash. Oh.</span>")
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)

View File

@@ -130,6 +130,9 @@
if ("mechstep") soundin = pick('sound/mecha/mechstep1.ogg', 'sound/mecha/mechstep2.ogg') 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") 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 ("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 return soundin
//Are these even used? //Are these even used?

View File

@@ -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 << "<span class='notice'>You start to cut the plastic flaps.</span>"
if(do_after(user, 10 * P.toolspeed))
user << "<span class='notice'>You cut the plastic flaps.</span>"
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 = "<h3>[command_name()] Shipping Manifest</h3><hr><br>"
slip.info +="Order #[SO.ordernum]<br>"
slip.info +="Destination: [station_name()]<br>"
slip.info +="[orderedamount] PACKAGES IN THIS SHIPMENT<br>"
slip.info +="CONTENTS:<br><ul>"
//spawn the stuff, finish generating the manifest while you're at it
if(SP.access)
if(isnum(SP.access))
A.req_access = list(SP.access)
else if(islist(SP.access))
var/list/L = SP.access // access var is a plain var, we need a list
A.req_access = L.Copy()
else
log_debug("<span class='danger'>Supply pack with invalid access restriction [SP.access] encountered!</span>")
var/list/contains
if(istype(SP,/datum/supply_packs/randomised))
var/datum/supply_packs/randomised/SPR = SP
contains = list()
if(SPR.contains.len)
for(var/j=1,j<=SPR.num_contained,j++)
contains += pick(SPR.contains)
else
contains = SP.contains
for(var/typepath in contains)
if(!typepath) continue
var/number_of_items = max(1, contains[typepath])
for(var/j = 1 to number_of_items)
var/atom/B2 = new typepath(A)
if(slip) slip.info += "<li>[B2.name]</li>" //add the item to the manifest
//manifest finalisation
if(slip)
slip.info += "</ul><br>"
slip.info += "CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS<hr>"
return

View File

@@ -12,6 +12,7 @@
nitrogen = MOLES_N2STANDARD nitrogen = MOLES_N2STANDARD
var/to_be_destroyed = 0 //Used for fire, if a melting temperature was reached, it will be destroyed 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/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 var/dirt = 0
// This is not great. // This is not great.
@@ -65,12 +66,13 @@
tracks.AddTracks(bloodDNA,comingdir,goingdir,bloodcolor) tracks.AddTracks(bloodDNA,comingdir,goingdir,bloodcolor)
/turf/simulated/proc/update_dirt() /turf/simulated/proc/update_dirt()
dirt = min(dirt+1, 101) if(can_dirty)
var/obj/effect/decal/cleanable/dirt/dirtoverlay = locate(/obj/effect/decal/cleanable/dirt, src) dirt = min(dirt+1, 101)
if (dirt > 50) var/obj/effect/decal/cleanable/dirt/dirtoverlay = locate(/obj/effect/decal/cleanable/dirt, src)
if (!dirtoverlay) if (dirt > 50)
dirtoverlay = new/obj/effect/decal/cleanable/dirt(src) if (!dirtoverlay)
dirtoverlay.alpha = min((dirt - 50) * 5, 255) dirtoverlay = new/obj/effect/decal/cleanable/dirt(src)
dirtoverlay.alpha = min((dirt - 50) * 5, 255)
/turf/simulated/Entered(atom/A, atom/OL) /turf/simulated/Entered(atom/A, atom/OL)
if(movement_disabled && usr.ckey != movement_disabled_exception) if(movement_disabled && usr.ckey != movement_disabled_exception)
@@ -82,8 +84,9 @@
if(M.lying) if(M.lying)
return ..() return ..()
// Dirt overlays. if(M.dirties_floor())
update_dirt() // Dirt overlays.
update_dirt()
if(istype(M, /mob/living/carbon/human)) if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M var/mob/living/carbon/human/H = M

View File

@@ -12,6 +12,9 @@
/turf/simulated/wall/dungeon/ex_act() /turf/simulated/wall/dungeon/ex_act()
return return
/turf/simulated/wall/dungeon/take_damage() //These things are suppose to be unbreakable
return
/turf/simulated/wall/solidrock //for more stylish anti-cheese. /turf/simulated/wall/solidrock //for more stylish anti-cheese.
name = "solid rock" name = "solid rock"
desc = "This rock seems dense, impossible to drill." desc = "This rock seems dense, impossible to drill."
@@ -37,4 +40,7 @@
return return
/turf/simulated/wall/solidrock/ex_act() /turf/simulated/wall/solidrock/ex_act()
return
/turf/simulated/wall/solidrock/take_damage() //These things are suppose to be unbreakable
return return

View File

@@ -9,6 +9,50 @@
attack_tile(C, L) // Be on help intent if you want to decon something. attack_tile(C, L) // Be on help intent if you want to decon something.
return 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, "<span class='warning'>There's nothing to attach the ceiling to!</span>")
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("<span class='notice'>[user] patches a hole in the ceiling.</span>", "<span class='notice'>You patch a hole in the ceiling.</span>")
expended_tile = TRUE
else
to_chat(user, "<span class='warning'>There aren't any holes in the ceiling to patch here.</span>")
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("<span class='notice'>[user] roofs a tile, shielding it from the elements.</span>", "<span class='notice'>You roof this tile, shielding it from the elements.</span>")
break
return
if(flooring) if(flooring)
if(istype(C, /obj/item/weapon)) if(istype(C, /obj/item/weapon))
try_deconstruct_tile(C, user) try_deconstruct_tile(C, user)

View File

@@ -1,5 +1,4 @@
var/list/turf_edge_cache = list() var/list/turf_edge_cache = list()
var/list/outdoor_turfs = list()
/turf/ /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, // 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() /turf/simulated/floor/New()
if(outdoors) if(outdoors)
outdoor_turfs.Add(src) SSplanets.addTurf(src)
..() ..()
/turf/simulated/floor/Destroy() /turf/simulated/floor/Destroy()
if(outdoors) if(outdoors)
planet_controller.unallocateTurf(src) SSplanets.removeTurf(src)
return ..() return ..()
/turf/simulated/proc/make_outdoors() /turf/simulated/proc/make_outdoors()
outdoors = TRUE outdoors = TRUE
outdoor_turfs.Add(src) SSplanets.addTurf(src)
/turf/simulated/proc/make_indoors() /turf/simulated/proc/make_indoors()
outdoors = FALSE outdoors = FALSE
if(planet_controller) SSplanets.removeTurf(src)
planet_controller.unallocateTurf(src)
else // This is happening during map gen, if there's no planet_controller (hopefully).
outdoor_turfs -= src
/turf/simulated/post_change() /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) 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]" var/cache_key = "[T.get_edge_icon_state()]-[checkdir]"
if(!turf_edge_cache[cache_key]) 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) 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 = 0 I.plane = TURF_PLANE
turf_edge_cache[cache_key] = I turf_edge_cache[cache_key] = I
add_overlay(turf_edge_cache[cache_key]) add_overlay(turf_edge_cache[cache_key])

View File

@@ -14,7 +14,7 @@
/turf/simulated/sky/initialize() /turf/simulated/sky/initialize()
. = ..() . = ..()
outdoor_turfs.Add(src) SSplanets.addTurf(src)
set_light(2, 2, "#FFFFFF") set_light(2, 2, "#FFFFFF")
/turf/simulated/sky/north /turf/simulated/sky/north

View File

@@ -142,15 +142,44 @@
return return
//get the user's location //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) if(W)
radiate() radiate()
if(is_hot(W)) if(is_hot(W))
burn(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("<span class='notice'>[user] patches a hole in the ceiling.</span>", "<span class='notice'>You patch a hole in the ceiling.</span>")
expended_tile = TRUE
else
to_chat(user, "<span class='warning'>There aren't any holes in the ceiling to patch here.</span>")
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("<span class='notice'>[user] roofs \the [src], shielding it from the elements.</span>", "<span class='notice'>You roof \the [src] tile, shielding it from the elements.</span>")
return
if(locate(/obj/effect/overlay/wallrot) in src) 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 var/obj/item/weapon/weldingtool/WT = W
if( WT.remove_fuel(0,user) ) if( WT.remove_fuel(0,user) )
to_chat(user, "<span class='notice'>You burn away the fungi with \the [WT].</span>") to_chat(user, "<span class='notice'>You burn away the fungi with \the [WT].</span>")
@@ -165,7 +194,7 @@
//THERMITE related stuff. Calls src.thermitemelt() which handles melting simulated walls and the relevant effects //THERMITE related stuff. Calls src.thermitemelt() which handles melting simulated walls and the relevant effects
if(thermite) if(thermite)
if(W.is_welder()) if( istype(W, /obj/item/weapon/weldingtool) )
var/obj/item/weapon/weldingtool/WT = W var/obj/item/weapon/weldingtool/WT = W
if( WT.remove_fuel(0,user) ) if( WT.remove_fuel(0,user) )
thermitemelt(user) thermitemelt(user)
@@ -188,7 +217,7 @@
var/turf/T = user.loc //get user's location for delay checks 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 var/obj/item/weapon/weldingtool/WT = W
@@ -214,7 +243,7 @@
var/dismantle_verb var/dismantle_verb
var/dismantle_sound var/dismantle_sound
if(W.is_welder()) if(istype(W,/obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W var/obj/item/weapon/weldingtool/WT = W
if(!WT.isOn()) if(!WT.isOn())
return return
@@ -282,7 +311,7 @@
return return
if(4) if(4)
var/cut_cover var/cut_cover
if(W.is_welder()) if(istype(W,/obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W var/obj/item/weapon/weldingtool/WT = W
if(!WT.isOn()) if(!WT.isOn())
return return
@@ -337,7 +366,7 @@
return return
if(1) if(1)
var/cut_cover var/cut_cover
if(W.is_welder()) if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W var/obj/item/weapon/weldingtool/WT = W
if( WT.remove_fuel(0,user) ) if( WT.remove_fuel(0,user) )
cut_cover=1 cut_cover=1

View File

@@ -115,9 +115,9 @@
plant.pixel_y = 0 plant.pixel_y = 0
plant.update_neighbors() 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() clear_plants()
..(newtype) ..(N, tell_universe, force_lighting_update, preserve_outdoors)
//Appearance //Appearance
/turf/simulated/wall/examine(mob/user) /turf/simulated/wall/examine(mob/user)

View File

@@ -19,6 +19,7 @@
..() // To get the edges. ..() // To get the edges.
icon_state = water_state icon_state = water_state
var/image/floorbed_sprite = image(icon = 'icons/turf/outdoors.dmi', icon_state = under_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) underlays.Add(floorbed_sprite)
update_icon_edge() update_icon_edge()

View File

@@ -33,18 +33,18 @@
/turf/space/attackby(obj/item/C as obj, mob/user as mob) /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) var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(L) if(L)
return return
var/obj/item/stack/rods/R = C var/obj/item/stack/rods/R = C
if (R.use(1)) if (R.use(1))
user << "<span class='notice'>Constructing support lattice ...</span>" to_chat(user, "<span class='notice'>Constructing support lattice ...</span>")
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
ReplaceWithLattice() ReplaceWithLattice()
return 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) var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(L) if(L)
var/obj/item/stack/tile/floor/S = C var/obj/item/stack/tile/floor/S = C
@@ -56,7 +56,33 @@
ChangeTurf(/turf/simulated/floor/airless) ChangeTurf(/turf/simulated/floor/airless)
return return
else else
user << "<span class='warning'>The plating is going to need some support.</span>" to_chat(user, "<span class='warning'>The plating is going to need some support.</span>")
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, "<span class='warning'>There's nothing to attach the ceiling to!</span>")
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("<span class='notice'>[user] expands the ceiling.</span>", "<span class='notice'>You expand the ceiling.</span>")
else
to_chat(user, "<span class='warning'>There aren't any holes in the ceiling to patch here.</span>")
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 return
@@ -64,7 +90,7 @@
/turf/space/Entered(atom/movable/A as mob|obj) /turf/space/Entered(atom/movable/A as mob|obj)
if(movement_disabled) if(movement_disabled)
usr << "<span class='warning'>Movement is admin-disabled.</span>" //This is to identify lag problems to_chat(usr, "<span class='warning'>Movement is admin-disabled.</span>") //This is to identify lag problems
return return
..() ..()
if ((!(A) || src != A.loc)) return if ((!(A) || src != A.loc)) return
@@ -187,5 +213,5 @@
A.loc.Entered(A) A.loc.Entered(A)
return return
/turf/space/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0) /turf/space/ChangeTurf(var/turf/N, var/tell_universe, var/force_lighting_update, var/preserve_outdoors)
return ..(N, tell_universe, 1) return ..(N, tell_universe, 1, preserve_outdoors)

View File

@@ -22,7 +22,7 @@
below.update_icon() // To add or remove the 'ceiling-less' overlay. below.update_icon() // To add or remove the 'ceiling-less' overlay.
//Creates a new turf //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) if (!N)
return return
@@ -38,6 +38,7 @@
var/old_affecting_lights = affecting_lights var/old_affecting_lights = affecting_lights
var/old_lighting_overlay = lighting_overlay var/old_lighting_overlay = lighting_overlay
var/old_corners = corners var/old_corners = corners
var/old_outdoors = outdoors
//world << "Replacing [src.type] with [N]" //world << "Replacing [src.type] with [N]"
@@ -106,3 +107,6 @@
lighting_build_overlay() lighting_build_overlay()
else else
lighting_clear_overlay() lighting_clear_overlay()
if(preserve_outdoors)
outdoors = old_outdoors

View File

@@ -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 // 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. // are opened or other strange things occur.
var/list/planetary_walls = list()
/turf/unsimulated/wall/planetary /turf/unsimulated/wall/planetary
name = "railroading" name = "railroading"
desc = "Choo choo!" desc = "Choo choo!"
@@ -21,10 +19,10 @@ var/list/planetary_walls = list()
/turf/unsimulated/wall/planetary/New() /turf/unsimulated/wall/planetary/New()
..() ..()
planetary_walls.Add(src) SSplanets.addTurf(src)
/turf/unsimulated/wall/planetary/Destroy() /turf/unsimulated/wall/planetary/Destroy()
planetary_walls.Remove(src) SSplanets.removeTurf(src)
..() ..()
/turf/unsimulated/wall/planetary/proc/set_temperature(var/new_temperature) /turf/unsimulated/wall/planetary/proc/set_temperature(var/new_temperature)

View File

@@ -133,7 +133,8 @@ var/list/admin_verbs_fun = list(
/client/proc/roll_dices, /client/proc/roll_dices,
/datum/admins/proc/call_supply_drop, /datum/admins/proc/call_supply_drop,
/datum/admins/proc/call_drop_pod, /datum/admins/proc/call_drop_pod,
/client/proc/smite /client/proc/smite,
/client/proc/admin_lightning_strike
) )
var/list/admin_verbs_spawn = list( var/list/admin_verbs_spawn = list(

View File

@@ -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. 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) 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, "<span class='warning'>Sorry, but your antagonist type is not allowed to speak in AOOC.</span>") to_chat(usr, "<span class='warning'>Sorry, but your antagonist type is not allowed to speak in AOOC.</span>")
return return
@@ -36,7 +36,7 @@
var/datum/antagonist/A = null var/datum/antagonist/A = null
if(M.mind) // Observers don't have minds, but they should still see AOOC. if(M.mind) // Observers don't have minds, but they should still see AOOC.
A = get_antag_data(M.mind.special_role) 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, "<span class='ooc'><span class='aooc'>[create_text_tag("aooc", "Antag-OOC:", M.client)] <EM>[player_display]:</EM> <span class='message'>[msg]</span></span></span>") to_chat(M, "<span class='ooc'><span class='aooc'>[create_text_tag("aooc", "Antag-OOC:", M.client)] <EM>[player_display]:</EM> <span class='message'>[msg]</span></span></span>")
log_aooc(msg,src) log_aooc(msg,src)

View File

@@ -637,7 +637,7 @@
if(!check_rights(R_DEBUG)) if(!check_rights(R_DEBUG))
return 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 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) if(new_weather)
planet.weather_holder.change_weather(new_weather) planet.weather_holder.change_weather(new_weather)
@@ -653,7 +653,7 @@
if(!check_rights(R_DEBUG)) if(!check_rights(R_DEBUG))
return 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/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 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

View File

@@ -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]). \
(<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[src.mob.x];Y=[src.mob.y];Z=[src.mob.z]'>JMP</a>)")
#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

View File

@@ -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,"<font color='blue'>You have no clue what to do with this thing.</font>")
return
if(!activated)
if(timer == 0)
to_chat(H, "<font color='blue'>You press a small button on [src]'s side. It starts to hum quietly.</font>")
bruteloss_prev = H.getBruteLoss()
fireloss_prev = H.getFireLoss()
activated = 1
return
else
to_chat(H,"<font color='blue'>You press a small button on [src]'s side. It buzzes a little.</font>")
return
if(activated)
to_chat(H,"<font color='blue'>You press a small button on [src]'s side. It stops humming.</font>")
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, "<font color='blue'>You fade into nothingness! [src]'s screen blinks, being unable to copy your synthetic body!</font>")
else
to_chat(watchowner, "<font color='blue'>You fade into nothingness, leaving behind a fake body!</font>")
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

View File

@@ -250,9 +250,8 @@
return return
/obj/effect/beam/i_beam/Destroy() /obj/effect/beam/i_beam/Destroy()
. = ..()
if(master.first == src) if(master.first == src)
master.first = null master.first = null
if(next) if(next && !next.gc_destroyed)
qdel(next) qdel_null(next)
next = null
..()

View File

@@ -71,8 +71,8 @@ datum/preferences/proc/set_biological_gender(var/gender)
. += "<b>Nickname:</b> " . += "<b>Nickname:</b> "
. += "<a href='?src=\ref[src];nickname=1'><b>[pref.nickname]</b></a>" . += "<a href='?src=\ref[src];nickname=1'><b>[pref.nickname]</b></a>"
. += "<br>" . += "<br>"
. += "<b>Biological Gender:</b> <a href='?src=\ref[src];bio_gender=1'><b>[gender2text(pref.biological_gender)]</b></a><br>" . += "<b>Biological Sex:</b> <a href='?src=\ref[src];bio_gender=1'><b>[gender2text(pref.biological_gender)]</b></a><br>"
. += "<b>Gender Identity:</b> <a href='?src=\ref[src];id_gender=1'><b>[gender2text(pref.identifying_gender)]</b></a><br>" . += "<b>Pronouns:</b> <a href='?src=\ref[src];id_gender=1'><b>[gender2text(pref.identifying_gender)]</b></a><br>"
. += "<b>Age:</b> <a href='?src=\ref[src];age=1'>[pref.age]</a><br>" . += "<b>Age:</b> <a href='?src=\ref[src];age=1'>[pref.age]</a><br>"
. += "<b>Spawn Point</b>: <a href='?src=\ref[src];spawnpoint=1'>[pref.spawnpoint]</a><br>" . += "<b>Spawn Point</b>: <a href='?src=\ref[src];spawnpoint=1'>[pref.spawnpoint]</a><br>"
if(config.allow_Metadata) if(config.allow_Metadata)
@@ -111,13 +111,13 @@ datum/preferences/proc/set_biological_gender(var/gender)
return TOPIC_NOACTION return TOPIC_NOACTION
else if(href_list["bio_gender"]) 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)) if(new_gender && CanUseTopic(user))
pref.set_biological_gender(new_gender) pref.set_biological_gender(new_gender)
return TOPIC_REFRESH_UPDATE_PREVIEW return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["id_gender"]) 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)) if(new_gender && CanUseTopic(user))
pref.identifying_gender = new_gender pref.identifying_gender = new_gender
return TOPIC_REFRESH return TOPIC_REFRESH
@@ -158,4 +158,4 @@ datum/preferences/proc/set_biological_gender(var/gender)
return possible_genders return possible_genders
possible_genders = possible_genders.Copy() possible_genders = possible_genders.Copy()
possible_genders |= NEUTER possible_genders |= NEUTER
return possible_genders return possible_genders

View File

@@ -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_red"] >> pref.r_synth
S["synth_green"] >> pref.g_synth S["synth_green"] >> pref.g_synth
S["synth_blue"] >> pref.b_synth S["synth_blue"] >> pref.b_synth
S["synth_markings"] >> pref.synth_markings
pref.preview_icon = null pref.preview_icon = null
S["bgstate"] >> pref.bgstate 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_red"] << pref.r_synth
S["synth_green"] << pref.g_synth S["synth_green"] << pref.g_synth
S["synth_blue"] << pref.b_synth S["synth_blue"] << pref.b_synth
S["synth_markings"] << pref.synth_markings
S["bgstate"] << pref.bgstate S["bgstate"] << pref.bgstate
/datum/category_item/player_setup_item/general/body/sanitize_character(var/savefile/S) /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.r_synth = pref.r_synth
character.g_synth = pref.g_synth character.g_synth = pref.g_synth
character.b_synth = pref.b_synth character.b_synth = pref.b_synth
character.synth_markings = pref.synth_markings
// Destroy/cyborgize organs and limbs. // 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)) 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
. += "<br><a href='?src=\ref[src];marking_style=1'>Body Markings +</a><br>" . += "<br><a href='?src=\ref[src];marking_style=1'>Body Markings +</a><br>"
for(var/M in pref.body_markings) for(var/M in pref.body_markings)
. += "[M] <a href='?src=\ref[src];marking_remove=[M]'>-</a> <a href='?src=\ref[src];marking_color=[M]'>Color</a>" . += "[M] [pref.body_markings.len > 1 ? "<a href='?src=\ref[src];marking_up=[M]'>&#708;</a> <a href='?src=\ref[src];marking_down=[M]'>&#709;</a> " : ""]<a href='?src=\ref[src];marking_remove=[M]'>-</a> <a href='?src=\ref[src];marking_color=[M]'>Color</a>"
. += "<font face='fixedsys' size='3' color='[pref.body_markings[M]]'><table style='display:inline;' bgcolor='[pref.body_markings[M]]'><tr><td>__</td></tr></table></font>" . += "<font face='fixedsys' size='3' color='[pref.body_markings[M]]'><table style='display:inline;' bgcolor='[pref.body_markings[M]]'><tr><td>__</td></tr></table></font>"
. += "<br>" . += "<br>"
. += "<br>" . += "<br>"
. += "<b>Allow Synth markings:</b> <a href='?src=\ref[src];synth_markings=1'><b>[pref.synth_markings ? "Yes" : "No"]</b></a><br>"
. += "<b>Allow Synth color:</b> <a href='?src=\ref[src];synth_color=1'><b>[pref.synth_color ? "Yes" : "No"]</b></a><br>" . += "<b>Allow Synth color:</b> <a href='?src=\ref[src];synth_color=1'><b>[pref.synth_color ? "Yes" : "No"]</b></a><br>"
if(pref.synth_color) if(pref.synth_color)
. += "<a href='?src=\ref[src];synth2_color=1'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(pref.r_synth, 2)][num2hex(pref.g_synth, 2)][num2hex(pref.b_synth, 2)]'><table style='display:inline;' bgcolor='#[num2hex(pref.r_synth, 2)][num2hex(pref.g_synth, 2)][num2hex(pref.b_synth, 2)]'><tr><td>__</td></tr></table></font> " . += "<a href='?src=\ref[src];synth2_color=1'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(pref.r_synth, 2)][num2hex(pref.g_synth, 2)][num2hex(pref.b_synth, 2)]'><table style='display:inline;' bgcolor='#[num2hex(pref.r_synth, 2)][num2hex(pref.g_synth, 2)][num2hex(pref.b_synth, 2)]'><tr><td>__</td></tr></table></font> "
@@ -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 pref.body_markings[new_marking] = "#000000" //New markings start black
return TOPIC_REFRESH_UPDATE_PREVIEW 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"]) else if(href_list["marking_remove"])
var/M = href_list["marking_remove"] var/M = href_list["marking_remove"]
pref.body_markings -= M 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)) pref.b_synth = hex2num(copytext(new_color, 6, 8))
return TOPIC_REFRESH_UPDATE_PREVIEW 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"]) else if(href_list["cycle_bg"])
pref.bgstate = next_in_list(pref.bgstate, pref.bgstate_options) pref.bgstate = next_in_list(pref.bgstate, pref.bgstate_options)
return TOPIC_REFRESH_UPDATE_PREVIEW return TOPIC_REFRESH_UPDATE_PREVIEW

View File

@@ -241,6 +241,46 @@ datum/gear/suit/duster
path = /obj/item/clothing/accessory/poncho/roles/cloak/hop path = /obj/item/clothing/accessory/poncho/roles/cloak/hop
allowed_roles = list("Head of Personnel") 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 /datum/gear/suit/unathi_robe
display_name = "roughspun robe" display_name = "roughspun robe"
path = /obj/item/clothing/suit/unathi/robe path = /obj/item/clothing/suit/unathi/robe

View File

@@ -114,12 +114,6 @@
path = /obj/item/weapon/cell/device path = /obj/item/weapon/cell/device
/datum/gear/utility/implant /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" slot = "implant"
exploitable = 1 exploitable = 1
@@ -127,8 +121,20 @@
display_name = "implant, tracking" display_name = "implant, tracking"
path = /obj/item/weapon/implant/tracking/weak path = /obj/item/weapon/implant/tracking/weak
cost = 10 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 /datum/gear/utility/pen
display_name = "Fountain Pen" display_name = "Fountain Pen"

View File

@@ -92,6 +92,30 @@
modifier_type = /datum/modifier/trait/larger modifier_type = /datum/modifier/trait/larger
mutually_exclusive = list(/datum/trait/modifier/physical/smaller, /datum/trait/modifier/physical/small, /datum/trait/modifier/physical/large) 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. // These two traits might be borderline, feel free to remove if they get abused.
/datum/trait/modifier/physical/high_metabolism /datum/trait/modifier/physical/high_metabolism
name = "High Metabolism" name = "High Metabolism"

View File

@@ -60,6 +60,7 @@ datum/preferences
var/r_synth //Used with synth_color to color synth parts that normaly can't be colored. var/r_synth //Used with synth_color to color synth parts that normaly can't be colored.
var/g_synth //Same as above var/g_synth //Same as above
var/b_synth //Same as above var/b_synth //Same as above
var/synth_markings = 0 //Enable/disable markings on synth parts.
//Some faction information. //Some faction information.
var/home_system = "Unset" //System of birth. var/home_system = "Unset" //System of birth.

View File

@@ -253,7 +253,8 @@
var/mob/living/carbon/human/H = user var/mob/living/carbon/human/H = user
if(slot && slot == slot_gloves) if(slot && slot == slot_gloves)
if(H.gloves) var/obj/item/clothing/gloves/G = H.gloves
if(istype(G))
ring = H.gloves ring = H.gloves
if(ring.glove_level >= src.glove_level) 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.") to_chat(user, "You are unable to wear \the [src] as \the [H.gloves] are in the way.")

View File

@@ -128,6 +128,7 @@
/obj/item/clothing/suit/syndicatefake /obj/item/clothing/suit/syndicatefake
name = "red space suit replica" name = "red space suit replica"
icon = 'icons/obj/clothing/spacesuits.dmi'
icon_state = "syndicate" 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!" 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 w_class = ITEMSIZE_NORMAL

View File

@@ -121,8 +121,8 @@
* Cloak * Cloak
*/ */
/obj/item/clothing/accessory/poncho/roles/cloak /obj/item/clothing/accessory/poncho/roles/cloak
name = "brown cloak" name = "quartermaster's cloak"
desc = "An elaborate brown cloak." desc = "An elaborate brown and gold cloak."
icon_state = "qmcloak" icon_state = "qmcloak"
item_state = "qmcloak" item_state = "qmcloak"
body_parts_covered = null body_parts_covered = null
@@ -169,6 +169,54 @@
icon_state = "capcloak" icon_state = "capcloak"
item_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 /obj/item/clothing/accessory/hawaii
name = "flower-pattern shirt" name = "flower-pattern shirt"
desc = "You probably need some welder googles to look at this." desc = "You probably need some welder googles to look at this."

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