mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-10 00:43:14 +00:00
## About The Pull Request Removes all arbitrary energy and power units in the codebase. Everything is replaced with the joule and watt, with 1 = 1 joule, or 1 watt if you are going to multiply by time. This is a visible change, where all arbitrary energy units you see in the game will get proper prefixed units of energy. With power cells being converted to the joule, charging one joule of a power cell will require one joule of energy. The grid will now store energy, instead of power. When an energy usage is described as using the watt, a power to energy conversion based on the relevant subsystem's timing (usually multiplying by seconds_per_tick or applying power_to_energy()) is needed before adding or removing from the grid. Power usages that are described as the watt is really anything you would scale by time before applying the load. If it's described as a joule, no time conversion is needed. Players will still read the grid as power, having no visible change. Machines that dynamically use power with the use_power() proc will directly drain from the grid (and apc cell if there isn't enough) instead of just tallying it up on the dynamic power usages for the area. This should be more robust at conserving energy as the surplus is updated on the go, preventing charging cells from nothing. APCs no longer consume power for the dynamic power usage channels. APCs will consume power for static power usages. Because static power usages are added up without checking surplus, static power consumption will be applied before any machine processes. This will give a more truthful surplus for dynamic power consumers. APCs will display how much power it is using for charging the cell. APC cell charging applies power in its own channel, which gets added up to the total. This will prevent invisible power usage you see when looking at the power monitoring console. After testing in MetaStation, I found roundstart power consumption to be around 406kW after all APCs get fully charged. During the roundstart APC charge rush, the power consumption can get as high as over 2MW (up to 25kW per roundstart APC charging) as long as there's that much available. Because of the absurd potential power consumption of charging APCs near roundstart, I have changed how APCs decide to charge. APCs will now charge only after all other machines have processed in the machines processing subsystem. This will make sure APC charging won't disrupt machines taking from the grid, and should stop APCs getting their power drained due to others demanding too much power while charging. I have removed the delays for APC charging too, so they start charging immediately whenever there's excess power. It also stops them turning red when a small amount of cell gets drained (airlocks opening and shit during APC charge rush), as they immediately become fully charged (unless too much energy got drained somehow) before changing icon. Engineering SMES now start at 100% charge instead of 75%. I noticed cells were draining earlier than usual after these changes, so I am making them start maxed to try and combat that. These changes will fix all conservation of energy issues relating to charging powercells. ## Why It's Good For The Game Closes #73438 Closes #75789 Closes #80634 Closes #82031 Makes it much easier to interface with the power system in the codebase. It's more intuitive. Removes a bunch of conservation of energy issues, making energy and power much more meaningful. It will help the simulation remain immersive as players won't encounter energy duplication so easily. Arbitrary energy units getting replaced with the joule will also tell people more meaningful information when reading it. APC charging will feel more snappy. ## Changelog 🆑 fix: Fixes conservation of energy issues relating to charging powercells. qol: APCs will display how much power they are using to charge their cell. This is accounted for in the power monitoring console. qol: All arbitrary power cell energy units you see are replaced with prefixed joules. balance: As a consequence of the conservation of energy issues getting fixed, the power consumption for charging cells is now very significant. balance: APCs only use surplus power from the grid after every machine processes when charging, preventing APCs from causing others to discharge while charging. balance: Engineering SMES start at max charge to combat the increased energy loss due to conservation of energy fixes. /🆑 --------- Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com> Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
458 lines
17 KiB
Plaintext
458 lines
17 KiB
Plaintext
/*
|
|
Map Template Holodeck
|
|
|
|
Holodeck finds the location of mapped_start_area and loads offline_program in it on LateInitialize. It then passes its program templates to Holodeck.js in the form of program_cache and emag_programs. when a user selects a program the
|
|
ui calls load_program() with the id of the selected program.
|
|
load_program() -> map_template/load() on map_template/holodeck.
|
|
|
|
holodeck map templates:
|
|
1. have an update_blacklist that doesnt allow placing on non holofloors (except for engine floors so you can repair it)
|
|
2. has should_place_on_top = FALSE, so that the baseturfs list doesnt pull a kilostation oom crash
|
|
3. has returns_created = TRUE, so that SSatoms gives the map template a list of spawned atoms
|
|
all the fancy flags and shit are added to holodeck objects in finish_spawn()
|
|
|
|
Easiest way to add new holodeck programs:
|
|
1. Define new map template datums in code/modules/holodeck/holodeck_map_templates, make sure they have the access flags
|
|
of the holodeck you want them to be able to load, for the onstation holodeck the flag is STATION_HOLODECK.
|
|
2. Create the new map templates in _maps/templates (remember theyre 9x10, and make sure they have area/noop or else it will fuck with linked)
|
|
all turfs in holodeck programs MUST be of type /turf/open/floor/holofloor, OR /turf/open/floor/engine, or they will block future programs!
|
|
|
|
Note: if youre looking at holodeck code because you want to see how returns_created is handled so that templates return a list of atoms
|
|
created from them: make sure you handle that list correctly! Either copy them by value and delete them or reference it and handle qdel'ing
|
|
and clear when youre done! if you dont i will use :newspaper2: on you
|
|
*/
|
|
|
|
#define HOLODECK_CD (2 SECONDS)
|
|
#define HOLODECK_DMG_CD (5 SECONDS)
|
|
|
|
/// typecache for turfs that should be considered ok during floorchecks.
|
|
/// A linked turf being anything not in this typecache will cause the holodeck to perform an emergency shutdown.
|
|
GLOBAL_LIST_INIT(typecache_holodeck_linked_floorcheck_ok, typecacheof(list(/turf/open/floor/holofloor, /turf/closed)))
|
|
|
|
/obj/machinery/computer/holodeck
|
|
name = "holodeck control console"
|
|
desc = "A computer used to control a nearby holodeck."
|
|
icon_screen = "holocontrol"
|
|
|
|
//new vars
|
|
///what area type this holodeck loads into. linked turns into the nearest instance of this area
|
|
var/area/mapped_start_area = /area/station/holodeck/rec_center
|
|
|
|
///the currently used map template
|
|
var/datum/map_template/holodeck/template
|
|
|
|
///bottom left corner of the loading room, used for placing
|
|
var/turf/bottom_left
|
|
|
|
///if TRUE the holodeck is busy spawning another simulation and should immediately stop loading the newest one
|
|
var/spawning_simulation = FALSE
|
|
|
|
//old vars
|
|
|
|
///the area that this holodeck loads templates into, used for power and deleting holo objects that leave it
|
|
var/area/station/holodeck/linked
|
|
|
|
///what program is loaded right now or is about to be loaded
|
|
var/program = "holodeck_offline"
|
|
var/last_program
|
|
|
|
///the default program loaded by this holodeck when spawned and when deactivated
|
|
var/offline_program = "holodeck_offline"
|
|
|
|
///stores all of the unrestricted holodeck map templates that this computer has access to
|
|
var/list/program_cache
|
|
///stores all of the restricted holodeck map templates that this computer has access to
|
|
var/list/emag_programs
|
|
|
|
///subtypes of this (but not this itself) are loadable programs
|
|
var/program_type = /datum/map_template/holodeck
|
|
|
|
///every holo object created by the holodeck goes in here to track it
|
|
var/list/spawned = list()
|
|
var/list/effects = list() //like above, but for holo effects
|
|
|
|
///special locs that can mess with derez'ing holo spawned objects
|
|
var/list/special_locs = list(
|
|
/obj/item/clothing/head/mob_holder,
|
|
)
|
|
|
|
///TRUE if the holodeck is using extra power because of a program, FALSE otherwise
|
|
var/active = FALSE
|
|
///increases the holodeck cooldown if TRUE, causing the holodeck to take longer to allow loading new programs
|
|
var/damaged = FALSE
|
|
|
|
//creates the timer that determines if another program can be manually loaded
|
|
COOLDOWN_DECLARE(holodeck_cooldown)
|
|
|
|
/obj/machinery/computer/holodeck/Initialize(mapload)
|
|
..()
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/obj/machinery/computer/holodeck/LateInitialize()//from here linked is populated and the program list is generated. its also set to load the offline program
|
|
linked = GLOB.areas_by_type[mapped_start_area]
|
|
if(!linked)
|
|
log_mapping("[src] at [AREACOORD(src)] has no matching holodeck area.")
|
|
qdel(src)
|
|
return
|
|
|
|
bottom_left = locate(linked.x, linked.y, src.z)
|
|
if(!bottom_left)
|
|
log_mapping("[src] at [AREACOORD(src)] has an invalid holodeck area.")
|
|
qdel(src)
|
|
return
|
|
|
|
var/area/computer_area = get_area(src)
|
|
if(istype(computer_area, /area/station/holodeck))
|
|
log_mapping("Holodeck computer cannot be in a holodeck, This would cause circular power dependency.")
|
|
qdel(src)
|
|
return
|
|
|
|
// the following is necessary for power reasons
|
|
if(!offline_program)
|
|
stack_trace("Holodeck console created without an offline program")
|
|
qdel(src)
|
|
return
|
|
|
|
linked.linked = src
|
|
var/area/my_area = get_area(src)
|
|
if(my_area)
|
|
linked.energy_usage = my_area.energy_usage
|
|
else
|
|
linked.energy_usage = list(AREA_USAGE_LEN)
|
|
|
|
COOLDOWN_START(src, holodeck_cooldown, HOLODECK_CD)
|
|
generate_program_list()
|
|
load_program(offline_program,TRUE)
|
|
|
|
///adds all programs that this holodeck has access to, and separates the restricted and unrestricted ones
|
|
/obj/machinery/computer/holodeck/proc/generate_program_list()
|
|
for(var/typekey in subtypesof(program_type))
|
|
var/datum/map_template/holodeck/program = typekey
|
|
var/list/info_this = list("id" = initial(program.template_id), "name" = initial(program.name))
|
|
if(initial(program.restricted))
|
|
LAZYADD(emag_programs, list(info_this))
|
|
else
|
|
LAZYADD(program_cache, list(info_this))
|
|
|
|
/obj/machinery/computer/holodeck/ui_interact(mob/user, datum/tgui/ui)
|
|
. = ..()
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "Holodeck", name)
|
|
ui.open()
|
|
|
|
/obj/machinery/computer/holodeck/ui_data(mob/user)
|
|
var/list/data = list()
|
|
|
|
data["default_programs"] = program_cache
|
|
if(obj_flags & EMAGGED)
|
|
data["emagged"] = TRUE
|
|
data["emag_programs"] = emag_programs
|
|
data["program"] = program
|
|
data["can_toggle_safety"] = issilicon(user) || isAdminGhostAI(user)
|
|
return data
|
|
|
|
/obj/machinery/computer/holodeck/ui_act(action, params)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
. = TRUE
|
|
|
|
switch(action)
|
|
if("load_program")
|
|
var/program_to_load = params["id"]
|
|
|
|
var/list/checked = program_cache.Copy()
|
|
if (obj_flags & EMAGGED)
|
|
checked |= emag_programs
|
|
var/valid = FALSE //dont tell security about this
|
|
|
|
//checks if program_to_load is any one of the loadable programs, if it isnt then it rejects it
|
|
for(var/list/check_list as anything in checked)
|
|
if(check_list["id"] == program_to_load)
|
|
valid = TRUE
|
|
break
|
|
if(!valid)
|
|
return FALSE
|
|
//load the map_template that program_to_load represents
|
|
if(program_to_load)
|
|
load_program(program_to_load)
|
|
if("safety")
|
|
if (!(obj_flags & EMAGGED) && !issilicon(usr))
|
|
return
|
|
if((obj_flags & EMAGGED) && program)
|
|
emergency_shutdown()
|
|
nerf(obj_flags & EMAGGED,FALSE)
|
|
obj_flags ^= EMAGGED
|
|
say("Safeties reset. Restarting...")
|
|
usr.log_message("disabled Holodeck safeties.", LOG_GAME)
|
|
|
|
///this is what makes the holodeck not spawn anything on broken tiles (space and non engine plating / non holofloors)
|
|
/datum/map_template/holodeck/update_blacklist(turf/placement, list/input_blacklist)
|
|
for(var/turf/possible_blacklist as anything in get_affected_turfs(placement))
|
|
if (possible_blacklist.holodeck_compatible)
|
|
continue
|
|
input_blacklist[possible_blacklist] = TRUE
|
|
|
|
///loads the template whose id string it was given ("offline_program" loads datum/map_template/holodeck/offline)
|
|
/obj/machinery/computer/holodeck/proc/load_program(map_id, force = FALSE, add_delay = TRUE)
|
|
if (program == map_id)
|
|
return
|
|
|
|
if (!is_operational)//load_program is called once with a timer (in toggle_power) we dont want this to load anything if its off
|
|
map_id = offline_program
|
|
force = TRUE
|
|
|
|
if (!force && (!COOLDOWN_FINISHED(src, holodeck_cooldown) || spawning_simulation))
|
|
say("ERROR. Recalibrating projection apparatus.")
|
|
return
|
|
|
|
if(spawning_simulation)
|
|
return
|
|
|
|
if (add_delay)
|
|
COOLDOWN_START(src, holodeck_cooldown, (damaged ? HOLODECK_CD + HOLODECK_DMG_CD : HOLODECK_CD))
|
|
if (damaged && floorcheck())
|
|
damaged = FALSE
|
|
|
|
spawning_simulation = TRUE
|
|
active = (map_id != offline_program)
|
|
update_use_power(active + IDLE_POWER_USE)
|
|
program = map_id
|
|
|
|
clear_projection()
|
|
|
|
template = SSmapping.holodeck_templates[map_id]
|
|
template.load(bottom_left) //this is what actually loads the holodeck simulation into the map
|
|
|
|
if(template.restricted)
|
|
usr.log_message("loaded a restricted Holodeck program: [program].", LOG_GAME)
|
|
message_admins("[ADMIN_LOOKUPFLW(usr)] loaded a restricted Holodeck program: [program].")
|
|
|
|
spawned = template.created_atoms //populate the spawned list with the atoms belonging to the holodeck
|
|
|
|
if(istype(template, /datum/map_template/holodeck/thunderdome1218) && !SSshuttle.shuttle_purchase_requirements_met[SHUTTLE_UNLOCK_MEDISIM])
|
|
say("Special note from \"1218 AD\" developer: I see you too are interested in the REAL dark ages of humanity! I've made this program also unlock some interesting shuttle designs on any communication console around. Have fun!")
|
|
SSshuttle.shuttle_purchase_requirements_met[SHUTTLE_UNLOCK_MEDISIM] = TRUE
|
|
|
|
nerf(!(obj_flags & EMAGGED))
|
|
finish_spawn()
|
|
|
|
///To be used on destroy, mainly to prevent sleeping inside well, destroy. Missing a lot of the things contained in load_program
|
|
/obj/machinery/computer/holodeck/proc/reset_to_default()
|
|
if (program == offline_program)
|
|
return
|
|
|
|
program = offline_program
|
|
clear_projection()
|
|
|
|
template = SSmapping.holodeck_templates[offline_program]
|
|
INVOKE_ASYNC(template, TYPE_PROC_REF(/datum/map_template, load), bottom_left) //this is what actually loads the holodeck simulation into the map
|
|
|
|
/obj/machinery/computer/holodeck/proc/clear_projection()
|
|
//clear the items from the previous program
|
|
for(var/holo_atom in spawned)
|
|
derez(holo_atom)
|
|
|
|
for(var/obj/effect/holodeck_effect/holo_effect as anything in effects)
|
|
effects -= holo_effect
|
|
holo_effect.deactivate(src)
|
|
|
|
//makes sure that any time a holoturf is inside a baseturf list (e.g. if someone put a wall over it) its set to the OFFLINE turf
|
|
//so that you cant bring turfs from previous programs into other ones (like putting the plasma burn turf into lounge for example)
|
|
for(var/turf/closed/holo_turf in linked)
|
|
holo_turf.replace_baseturf(/turf/open/floor/holofloor, /turf/open/floor/holofloor/plating)
|
|
|
|
///finalizes objects in the spawned list
|
|
/obj/machinery/computer/holodeck/proc/finish_spawn()
|
|
for(var/atom/holo_atom as anything in spawned)
|
|
if(QDELETED(holo_atom))
|
|
spawned -= holo_atom
|
|
continue
|
|
finalize_spawned(holo_atom)
|
|
spawning_simulation = FALSE
|
|
|
|
/obj/machinery/computer/holodeck/proc/finalize_spawned(atom/holo_atom)
|
|
RegisterSignal(holo_atom, COMSIG_QDELETING, PROC_REF(remove_from_holo_lists))
|
|
holo_atom.flags_1 |= HOLOGRAM_1
|
|
|
|
if(isholoeffect(holo_atom))//activates holo effects and transfers them from the spawned list into the effects list
|
|
var/obj/effect/holodeck_effect/holo_effect = holo_atom
|
|
effects += holo_effect
|
|
spawned -= holo_effect
|
|
var/atom/holo_effect_product = holo_effect.activate(src)//change name
|
|
if(istype(holo_effect_product))
|
|
spawned += holo_effect_product // we want mobs or objects spawned via holoeffects to be tracked as objects
|
|
RegisterSignal(holo_effect_product, COMSIG_QDELETING, PROC_REF(remove_from_holo_lists))
|
|
if(islist(holo_effect_product))
|
|
for(var/atom/atom_product as anything in holo_effect_product)
|
|
spawned += atom_product
|
|
RegisterSignal(atom_product, COMSIG_QDELETING, PROC_REF(remove_from_holo_lists))
|
|
return
|
|
|
|
if(isobj(holo_atom))
|
|
var/obj/holo_object = holo_atom
|
|
holo_object.resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
|
|
|
if(isstructure(holo_object))
|
|
holo_object.obj_flags |= NO_DECONSTRUCTION
|
|
return
|
|
|
|
if(ismachinery(holo_object))
|
|
var/obj/machinery/holo_machine = holo_object
|
|
holo_machine.obj_flags |= NO_DECONSTRUCTION
|
|
holo_machine.power_change()
|
|
|
|
if(istype(holo_machine, /obj/machinery/button))
|
|
var/obj/machinery/button/holo_button = holo_machine
|
|
holo_button.setup_device()
|
|
|
|
/**
|
|
* A separate proc for objects that weren't loaded by the template nor spawned by holo effects
|
|
* yet need to be added to the list of spawned objects. (e.g. holographic fishes)
|
|
*/
|
|
/obj/machinery/computer/holodeck/proc/add_to_spawned(atom/holo_atom)
|
|
spawned |= holo_atom
|
|
if(!(obj_flags & EMAGGED) && isitem(holo_atom))
|
|
var/obj/item/to_be_nerfed = holo_atom
|
|
to_be_nerfed.damtype = STAMINA
|
|
finalize_spawned(holo_atom)
|
|
|
|
///this qdels holoitems that should no longer exist for whatever reason
|
|
/obj/machinery/computer/holodeck/proc/derez(atom/movable/holo_atom, silent = TRUE, forced = FALSE)
|
|
spawned -= holo_atom
|
|
if(!holo_atom)
|
|
return
|
|
UnregisterSignal(holo_atom, COMSIG_QDELETING)
|
|
var/turf/target_turf = get_turf(holo_atom)
|
|
for(var/atom/movable/atom_contents as anything in holo_atom) //make sure that things inside of a holoitem are moved outside before destroying it
|
|
if(atom_contents.flags_1 & HOLOGRAM_1) //hologram in hologram is fine
|
|
continue
|
|
atom_contents.forceMove(target_turf)
|
|
|
|
if(istype(holo_atom, /obj/item/clothing/under))
|
|
var/obj/item/clothing/under/holo_clothing = holo_atom
|
|
holo_clothing.dump_attachments()
|
|
|
|
if(!silent)
|
|
visible_message(span_notice("[holo_atom] fades away!"))
|
|
|
|
if(is_type_in_list(holo_atom.loc, special_locs))
|
|
qdel(holo_atom.loc)
|
|
qdel(holo_atom)
|
|
|
|
/obj/machinery/computer/holodeck/proc/remove_from_holo_lists(datum/to_remove, _forced)
|
|
SIGNAL_HANDLER
|
|
spawned -= to_remove
|
|
UnregisterSignal(to_remove, COMSIG_QDELETING)
|
|
|
|
/obj/machinery/computer/holodeck/process(seconds_per_tick)
|
|
if(damaged && SPT_PROB(5, seconds_per_tick))
|
|
for(var/turf/holo_turf in linked)
|
|
if(SPT_PROB(2.5, seconds_per_tick))
|
|
do_sparks(2, 1, holo_turf)
|
|
return
|
|
. = ..()
|
|
if(!. || program == offline_program)//we dont need to scan the holodeck if the holodeck is offline
|
|
return
|
|
|
|
if(!floorcheck()) //if any turfs in the floor of the holodeck are broken
|
|
emergency_shutdown()
|
|
damaged = TRUE
|
|
visible_message("The holodeck overloads!")
|
|
for(var/turf/holo_turf in linked)
|
|
if(prob(30))
|
|
do_sparks(2, 1, holo_turf)
|
|
SSexplosions.lowturf += holo_turf
|
|
holo_turf.hotspot_expose(1000,500,1)
|
|
|
|
if(!(obj_flags & EMAGGED))
|
|
for(var/item in spawned)
|
|
if(!(get_turf(item) in linked))
|
|
derez(item)
|
|
for(var/obj/effect/holodeck_effect/holo_effect as anything in effects)
|
|
holo_effect.tick()
|
|
update_mode_power_usage(ACTIVE_POWER_USE, active_power_usage + spawned.len * 3 + effects.len * 5)
|
|
|
|
/obj/machinery/computer/holodeck/proc/toggle_power(toggleOn = FALSE)
|
|
if(active == toggleOn)
|
|
return
|
|
|
|
if(toggleOn)
|
|
if(last_program && (last_program != offline_program))
|
|
addtimer(CALLBACK(src, PROC_REF(load_program), last_program, TRUE), 25)
|
|
active = TRUE
|
|
else
|
|
last_program = program
|
|
load_program(offline_program, TRUE)
|
|
active = FALSE
|
|
|
|
/obj/machinery/computer/holodeck/power_change()
|
|
. = ..()
|
|
INVOKE_ASYNC(src, PROC_REF(toggle_power), !machine_stat)
|
|
|
|
///shuts down the holodeck and force loads the offline_program
|
|
/obj/machinery/computer/holodeck/proc/emergency_shutdown()
|
|
last_program = program
|
|
active = FALSE
|
|
load_program(offline_program, TRUE)
|
|
|
|
///returns TRUE if all floors of the holodeck are present, returns FALSE if any are broken or removed
|
|
/obj/machinery/computer/holodeck/proc/floorcheck()
|
|
for(var/turf/holo_floor in linked)
|
|
if (is_type_in_typecache(holo_floor, GLOB.typecache_holodeck_linked_floorcheck_ok))
|
|
continue
|
|
return FALSE
|
|
return TRUE
|
|
|
|
///changes all weapons in the holodeck to do stamina damage if set
|
|
/obj/machinery/computer/holodeck/proc/nerf(nerf_this, is_loading = TRUE)
|
|
if (!nerf_this && is_loading)
|
|
return
|
|
for(var/obj/item/to_be_nerfed in spawned)
|
|
to_be_nerfed.damtype = nerf_this ? STAMINA : initial(to_be_nerfed.damtype)
|
|
for(var/obj/effect/holodeck_effect/holo_effect as anything in effects)
|
|
holo_effect.safety(nerf_this)
|
|
|
|
/obj/machinery/computer/holodeck/emag_act(mob/user, obj/item/card/emag/emag_card)
|
|
if(obj_flags & EMAGGED)
|
|
return FALSE
|
|
if(!LAZYLEN(emag_programs))
|
|
balloon_alert(user, "no card swipe port!")
|
|
return FALSE
|
|
playsound(src, SFX_SPARKS, 75, TRUE)
|
|
obj_flags |= EMAGGED
|
|
if (user)
|
|
balloon_alert(user, "safety protocols destroyed") // im gonna keep this once since this perfectly describes it, and the to_chat is just flavor
|
|
to_chat(user, span_warning("You vastly increase projector power and override the safety and security protocols."))
|
|
user.log_message("emagged the Holodeck Control Console.", LOG_GAME)
|
|
message_admins("[ADMIN_LOOKUPFLW(user)] emagged the Holodeck Control Console.")
|
|
|
|
say("Warning. Automatic shutoff and derezzing protocols have been corrupted. Please call Nanotrasen maintenance and do not use the simulator.")
|
|
nerf(!(obj_flags & EMAGGED),FALSE)
|
|
return TRUE
|
|
|
|
/obj/machinery/computer/holodeck/emp_act(severity)
|
|
. = ..()
|
|
if(. & EMP_PROTECT_SELF)
|
|
return
|
|
emergency_shutdown()
|
|
|
|
/obj/machinery/computer/holodeck/ex_act(severity, target)
|
|
emergency_shutdown()
|
|
return ..()
|
|
|
|
/obj/machinery/computer/holodeck/Destroy()
|
|
reset_to_default()
|
|
if(linked)
|
|
linked.linked = null
|
|
linked.energy_usage = list(AREA_USAGE_LEN)
|
|
return ..()
|
|
|
|
/obj/machinery/computer/holodeck/blob_act(obj/structure/blob/B)
|
|
emergency_shutdown()
|
|
return ..()
|
|
|
|
#undef HOLODECK_CD
|
|
#undef HOLODECK_DMG_CD
|