initial commit - cross reference with 5th port - obviously has compile errors
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
/proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0, var/atom/newloc = null, var/nerf = 0)
|
||||
if(!original)
|
||||
return null
|
||||
var/obj/O
|
||||
|
||||
if(sameloc)
|
||||
O = new original.type(original.loc)
|
||||
else
|
||||
O = new original.type(newloc)
|
||||
|
||||
if(perfectcopy && O && original)
|
||||
var/global/list/forbidden_vars = list("type","loc","locs","vars", "parent","parent_type", "verbs","ckey","key","power_supply","contents","reagents","stat","x","y","z","group")
|
||||
|
||||
for(var/V in original.vars - forbidden_vars)
|
||||
if(istype(original.vars[V],/list))
|
||||
var/list/L = original.vars[V]
|
||||
O.vars[V] = L.Copy()
|
||||
else if(istype(original.vars[V],/datum))
|
||||
continue // this would reference the original's object, that will break when it is used or deleted.
|
||||
else
|
||||
O.vars[V] = original.vars[V]
|
||||
|
||||
if(istype(O))
|
||||
O.burn_state = FIRE_PROOF // holoitems do not burn
|
||||
if(nerf && istype(O,/obj/item))
|
||||
var/obj/item/I = O
|
||||
I.damtype = STAMINA // thou shalt not
|
||||
if(istype(O,/obj/machinery))
|
||||
var/obj/machinery/M = O
|
||||
M.power_change()
|
||||
O.update_icon()
|
||||
return O
|
||||
|
||||
|
||||
/area/proc/copy_contents_to(var/area/A , var/platingRequired = 0, var/nerf_weapons = 0 )
|
||||
//Takes: Area. Optional: If it should copy to areas that don't have plating
|
||||
//Returns: Nothing.
|
||||
//Notes: Attempts to move the contents of one area to another area.
|
||||
// Movement based on lower left corner. Tiles that do not fit
|
||||
// into the new area will not be moved.
|
||||
|
||||
if(!A || !src) return 0
|
||||
|
||||
var/list/turfs_src = get_area_turfs(src.type)
|
||||
var/list/turfs_trg = get_area_turfs(A.type)
|
||||
|
||||
var/src_min_x = 99999
|
||||
var/src_min_y = 99999
|
||||
var/list/refined_src = new/list()
|
||||
|
||||
for (var/turf/T in turfs_src)
|
||||
src_min_x = min(src_min_x,T.x)
|
||||
src_min_y = min(src_min_y,T.y)
|
||||
for (var/turf/T in turfs_src)
|
||||
refined_src[T] = "[T.x - src_min_x].[T.y - src_min_y]"
|
||||
|
||||
var/trg_min_x = 99999
|
||||
var/trg_min_y = 99999
|
||||
var/list/refined_trg = new/list()
|
||||
|
||||
for (var/turf/T in turfs_trg)
|
||||
trg_min_x = min(trg_min_x,T.x)
|
||||
trg_min_y = min(trg_min_y,T.y)
|
||||
for (var/turf/T in turfs_trg)
|
||||
refined_trg["[T.x - trg_min_x].[T.y - trg_min_y]"] = T
|
||||
|
||||
var/list/toupdate = new/list()
|
||||
|
||||
var/copiedobjs = list()
|
||||
|
||||
for (var/turf/T in refined_src)
|
||||
//var/datum/coords/C_src = refined_src[T]
|
||||
var/coordstring = refined_src[T]
|
||||
var/turf/B = refined_trg[coordstring]
|
||||
if(!istype(B))
|
||||
continue
|
||||
|
||||
if(platingRequired)
|
||||
if(istype(B, /turf/open/space))
|
||||
continue
|
||||
|
||||
var/old_dir1 = T.dir
|
||||
var/old_icon_state1 = T.icon_state
|
||||
var/old_icon1 = T.icon
|
||||
|
||||
var/turf/X = new T.type(B)
|
||||
X.setDir(old_dir1)
|
||||
X.icon = old_icon1
|
||||
X.icon_state = old_icon_state1
|
||||
|
||||
for(var/obj/O in T)
|
||||
var/obj/O2 = DuplicateObject(O , 1, newloc = X, nerf=nerf_weapons)
|
||||
if(!O2) continue
|
||||
copiedobjs += O2.GetAllContents()
|
||||
|
||||
for(var/mob/M in T)
|
||||
if(istype(M, /mob/camera)) continue // If we need to check for more mobs, I'll add a variable
|
||||
var/mob/SM = DuplicateObject(M , 1, newloc = X)
|
||||
copiedobjs += SM.GetAllContents()
|
||||
|
||||
var/global/list/forbidden_vars = list("type","stat","loc","locs","vars", "parent", "parent_type","verbs","ckey","key","x","y","z","contents", "luminosity")
|
||||
for(var/V in T.vars - forbidden_vars)
|
||||
if(V == "air")
|
||||
var/turf/open/O1 = X
|
||||
var/turf/open/O2 = T
|
||||
O1.air.copy_from(O2.air)
|
||||
continue
|
||||
X.vars[V] = T.vars[V]
|
||||
toupdate += X
|
||||
|
||||
if(toupdate.len)
|
||||
for(var/turf/T1 in toupdate)
|
||||
T1.CalculateAdjacentTurfs()
|
||||
SSair.add_to_active(T1,1)
|
||||
|
||||
|
||||
return copiedobjs
|
||||
@@ -0,0 +1,102 @@
|
||||
/area/holodeck
|
||||
name = "Holodeck"
|
||||
icon_state = "Holodeck"
|
||||
luminosity = 1
|
||||
lighting_use_dynamic = 0
|
||||
|
||||
var/obj/machinery/computer/holodeck/linked
|
||||
var/restricted = 0 // if true, program goes on emag list
|
||||
|
||||
/*
|
||||
Power tracking: Use the holodeck computer's power grid
|
||||
Asserts are to avoid the inevitable infinite loops
|
||||
*/
|
||||
|
||||
/area/holodeck/powered(var/chan)
|
||||
if(!master.requires_power)
|
||||
return 1
|
||||
if(master.always_unpowered)
|
||||
return 0
|
||||
if(!linked)
|
||||
return 0
|
||||
var/area/A = get_area(linked)
|
||||
ASSERT(!istype(A,/area/holodeck))
|
||||
return A.powered(chan)
|
||||
|
||||
/area/holodeck/usage(var/chan)
|
||||
if(!linked)
|
||||
return 0
|
||||
var/area/A = get_area(linked)
|
||||
ASSERT(!istype(A,/area/holodeck))
|
||||
return A.usage(chan)
|
||||
|
||||
/area/holodeck/addStaticPower(value, powerchannel)
|
||||
if(!linked)
|
||||
return
|
||||
var/area/A = get_area(linked)
|
||||
ASSERT(!istype(A,/area/holodeck))
|
||||
return A.addStaticPower(value,powerchannel)
|
||||
|
||||
/area/holodeck/use_power(var/amount, var/chan)
|
||||
if(!linked)
|
||||
return 0
|
||||
var/area/A = get_area(linked)
|
||||
ASSERT(!istype(A,/area/holodeck))
|
||||
return A.use_power(amount,chan)
|
||||
|
||||
|
||||
/*
|
||||
This is the standard holodeck. It is intended to allow you to
|
||||
blow off steam by doing stupid things like laying down, throwing
|
||||
spheres at holes, or bludgeoning people.
|
||||
*/
|
||||
/area/holodeck/rec_center
|
||||
name = "\improper Recreational Holodeck"
|
||||
|
||||
/area/holodeck/rec_center/offline
|
||||
name = "Holodeck - Offline"
|
||||
|
||||
/area/holodeck/rec_center/court
|
||||
name = "Holodeck - Empty Court"
|
||||
|
||||
/area/holodeck/rec_center/dodgeball
|
||||
name = "Holodeck - Dodgeball Court"
|
||||
|
||||
/area/holodeck/rec_center/basketball
|
||||
name = "Holodeck - Basketball Court"
|
||||
|
||||
/area/holodeck/rec_center/thunderdome
|
||||
name = "Holodeck - Thunderdome Court"
|
||||
|
||||
/area/holodeck/rec_center/beach
|
||||
name = "Holodeck - Beach"
|
||||
|
||||
/area/holodeck/rec_center/lounge
|
||||
name = "Holodeck - Lounge"
|
||||
|
||||
/area/holodeck/rec_center/medical
|
||||
name = "Holodeck - Emergency Medical"
|
||||
|
||||
/area/holodeck/rec_center/pet_lounge
|
||||
name = "Holodeck - Pet Playground"
|
||||
|
||||
/area/holodeck/rec_center/winterwonderland
|
||||
name = "Holodeck - Winter Wonderland"
|
||||
|
||||
// Bad programs
|
||||
|
||||
/area/holodeck/rec_center/burn
|
||||
name = "Holodeck - Atmospheric Burn Test"
|
||||
restricted = 1
|
||||
|
||||
/area/holodeck/rec_center/wildlife
|
||||
name = "Holodeck - Wildlife Simulation"
|
||||
restricted = 1
|
||||
|
||||
/area/holodeck/rec_center/bunker
|
||||
name = "Holodeck - Holdout Bunker"
|
||||
restricted = 1
|
||||
|
||||
/area/holodeck/rec_center/anthophila
|
||||
name = "Holodeck - Anthophila"
|
||||
restricted = 1
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
Holodeck Update
|
||||
|
||||
The on-station holodeck area is of type [holodeck_type].
|
||||
All subtypes of [program_type] are loaded into the program cache or emag programs list.
|
||||
If init_program is null, a random program will be loaded on startup.
|
||||
If you don't wish this, set it to the offline program or another of your choosing.
|
||||
|
||||
You can use this to add holodecks with minimal code:
|
||||
1) Define new areas for the holodeck programs
|
||||
2) Map them
|
||||
3) Create a new control console that uses those areas
|
||||
|
||||
Non-mapped areas should be skipped but you should probably comment them out anyway.
|
||||
The base of program_type will always be ignored; only subtypes will be loaded.
|
||||
*/
|
||||
|
||||
/obj/machinery/computer/holodeck
|
||||
name = "holodeck control console"
|
||||
desc = "A computer used to control a nearby holodeck."
|
||||
icon_screen = "holocontrol"
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 50
|
||||
var/area/holodeck/linked
|
||||
var/area/holodeck/program
|
||||
var/area/holodeck/last_program
|
||||
var/area/offline_program = /area/holodeck/rec_center/offline
|
||||
|
||||
var/list/program_cache = list()
|
||||
var/list/emag_programs = list()
|
||||
|
||||
// Splitting this up allows two holodecks of the same size
|
||||
// to use the same source patterns. Y'know, if you want to.
|
||||
var/holodeck_type = /area/holodeck/rec_center // locate(this) to get the target holodeck
|
||||
var/program_type = /area/holodeck/rec_center // subtypes of this (but not this itself) are loadable programs
|
||||
|
||||
// set this if you want it to start with some particular program.
|
||||
var/init_program = null
|
||||
// or this to get anything
|
||||
var/random_program = 0
|
||||
|
||||
var/active = 0
|
||||
var/damaged = 0
|
||||
var/list/spawned = list()
|
||||
var/list/effects = list()
|
||||
var/last_change = 0
|
||||
|
||||
/obj/machinery/computer/holodeck/New()
|
||||
|
||||
if(ispath(holodeck_type,/area))
|
||||
linked = locate(holodeck_type)
|
||||
if(ispath(offline_program,/area))
|
||||
offline_program = locate(offline_program)
|
||||
// the following is necessary for power reasons
|
||||
var/area/AS = get_area(src)
|
||||
if(istype(AS,/area/holodeck))
|
||||
world.log << "### MAPPING ERROR"
|
||||
world.log << "Holodeck computer cannot be in a holodeck."
|
||||
world.log << "This would cause circular power dependency."
|
||||
qdel(src) // todo handle constructed computers
|
||||
return
|
||||
else
|
||||
linked.linked = src // todo detect multiple/constructed computers
|
||||
|
||||
if(ticker && ticker.current_state >= GAME_STATE_PLAYING)
|
||||
initialize()
|
||||
..()
|
||||
|
||||
/obj/machinery/computer/holodeck/initialize()
|
||||
program_cache = list()
|
||||
emag_programs = list()
|
||||
for(var/typekey in subtypesof(program_type))
|
||||
var/area/holodeck/A = locate(typekey)
|
||||
if(!A || A == offline_program) continue
|
||||
if(A.contents.len == 0) continue // not loaded
|
||||
if(A.restricted)
|
||||
emag_programs += A
|
||||
else
|
||||
program_cache += A
|
||||
if(typekey == init_program)
|
||||
load_program(A,force=1)
|
||||
if(random_program && program_cache.len && init_program == null)
|
||||
load_program(pick(program_cache),force=1)
|
||||
else if(!program)
|
||||
load_program(offline_program)
|
||||
|
||||
/obj/machinery/computer/holodeck/power_change()
|
||||
..()
|
||||
toggle_power(!stat)
|
||||
|
||||
/obj/machinery/computer/holodeck/proc/toggle_power(toggleOn = 0)
|
||||
if(active == toggleOn) return
|
||||
|
||||
if(toggleOn)
|
||||
if(last_program && last_program != offline_program)
|
||||
load_program(last_program, delay = 1)
|
||||
active = 1
|
||||
else
|
||||
last_program = program
|
||||
load_program(offline_program,force=1)
|
||||
active = 0
|
||||
|
||||
/obj/machinery/computer/holodeck/proc/emergency_shutdown()
|
||||
last_program = program
|
||||
load_program(offline_program,1)
|
||||
active = 0
|
||||
|
||||
/obj/machinery/computer/holodeck/process()
|
||||
if(damaged)
|
||||
if(prob(10))
|
||||
for(var/turf/T in linked)
|
||||
if(prob(5))
|
||||
var/datum/effect_system/spark_spread/s = new
|
||||
s.set_up(2, 1, T)
|
||||
s.start()
|
||||
return
|
||||
|
||||
if(!..() || !active)
|
||||
return
|
||||
|
||||
if(!floorcheck())
|
||||
emergency_shutdown()
|
||||
damaged = 1
|
||||
for(var/mob/M in urange(10,src))
|
||||
M.show_message("The holodeck overloads!")
|
||||
|
||||
for(var/turf/T in linked)
|
||||
if(prob(30))
|
||||
var/datum/effect_system/spark_spread/s = new
|
||||
s.set_up(2, 1, T)
|
||||
s.start()
|
||||
T.ex_act(3)
|
||||
T.hotspot_expose(1000,500,1)
|
||||
|
||||
if(!emagged)
|
||||
for(var/item in spawned)
|
||||
if(!(get_turf(item) in linked))
|
||||
derez(item, 0)
|
||||
for(var/obj/effect/holodeck_effect/HE in effects)
|
||||
HE.tick()
|
||||
|
||||
active_power_usage = 50 + spawned.len * 3 + effects.len * 5
|
||||
|
||||
/obj/machinery/computer/holodeck/proc/floorcheck()
|
||||
for(var/turf/T in linked)
|
||||
if(!T.intact || istype(T,/turf/open/space))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/machinery/computer/holodeck/Topic(href, list/href_list)
|
||||
if(..())
|
||||
return
|
||||
if(!Adjacent(usr) && !istype(usr, /mob/living/silicon))
|
||||
return
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
if(href_list["loadarea"])
|
||||
var/areapath = text2path(href_list["loadarea"])
|
||||
if(!ispath(areapath, /area/holodeck))
|
||||
return
|
||||
var/area/holodeck/area = locate(areapath)
|
||||
if(!istype(area))
|
||||
return
|
||||
if(area == offline_program || (area in program_cache) || (emagged && (area in emag_programs)))
|
||||
load_program(area)
|
||||
else if("safety" in href_list)
|
||||
var/safe = text2num(href_list["safety"])
|
||||
emagged = !safe
|
||||
if(!program)
|
||||
return
|
||||
if(safe && (program in emag_programs))
|
||||
emergency_shutdown()
|
||||
nerf(safe)
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/computer/holodeck/proc/nerf(active)
|
||||
for(var/obj/item/I in spawned)
|
||||
I.damtype = (active? STAMINA : initial(I.damtype) )
|
||||
for(var/obj/effect/holodeck_effect/HE in effects)
|
||||
HE.safety(active)
|
||||
|
||||
/obj/machinery/computer/holodeck/emag_act(mob/user as mob)
|
||||
if(!emagged)
|
||||
if(!emag_programs.len)
|
||||
user << "[src] does not seem to have a card swipe port. It must be an inferior model."
|
||||
return
|
||||
playsound(loc, 'sound/effects/sparks4.ogg', 75, 1)
|
||||
emagged = 1
|
||||
user << "<span class='warning'>You vastly increase projector power and override the safety and security protocols.</span>"
|
||||
user << "Warning. Automatic shutoff and derezing protocols have been corrupted. Please call Nanotrasen maintenance and do not use the simulator."
|
||||
log_game("[key_name(user)] emagged the Holodeck Control Console")
|
||||
updateUsrDialog()
|
||||
nerf(!emagged)
|
||||
|
||||
/obj/machinery/computer/holodeck/Destroy()
|
||||
emergency_shutdown()
|
||||
..()
|
||||
|
||||
/obj/machinery/computer/holodeck/emp_act(severity)
|
||||
emergency_shutdown()
|
||||
..()
|
||||
|
||||
/obj/machinery/computer/holodeck/ex_act(severity, target)
|
||||
emergency_shutdown()
|
||||
..()
|
||||
|
||||
/obj/machinery/computer/holodeck/blob_act(obj/effect/blob/B)
|
||||
emergency_shutdown()
|
||||
..()
|
||||
@@ -0,0 +1,119 @@
|
||||
/obj/machinery/computer/holodeck/attack_hand(var/mob/user as mob)
|
||||
user.set_machine(src)
|
||||
|
||||
var/dat = "<h3>Current Loaded Programs</h3>"
|
||||
dat += "<a href='?src=\ref[src];loadarea=[offline_program.type]'>Power Off</a><br>"
|
||||
for(var/area/A in program_cache)
|
||||
dat += "<a href='?src=\ref[src];loadarea=[A.type]'>[A.name]</a><br>"
|
||||
if(emagged && emag_programs.len)
|
||||
dat += "<span class='warning'>SUPERVISOR ACCESS - SAFETY PROTOCOLS DISABLED - CAUTION: EMITTER ANOMALY</span><br>"
|
||||
for(var/area/A in emag_programs)
|
||||
dat += "<a href='?src=\ref[src];loadarea=[A.type]'>[A.name]</a><br>"
|
||||
|
||||
var/datum/browser/popup = new(user, "computer", name, 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/holodeck/attack_ai(var/mob/user as mob)
|
||||
var/dat = "<h3>Current Loaded Programs</h3>"
|
||||
|
||||
dat += "<a href='?src=\ref[src];loadarea=[offline_program.type]'>Power Off</a><br>"
|
||||
for(var/area/A in program_cache)
|
||||
dat += "<a href='?src=\ref[src];loadarea=[A.type]'>[A.name]</a><br>"
|
||||
|
||||
if(emag_programs.len)
|
||||
dat += "<br>"
|
||||
if(emagged)
|
||||
dat += "Safety protocol: <span class='bad'>Offline</span> <a href='?\ref[src];safety=1'>Engage</a><br>"
|
||||
for(var/area/A in emag_programs)
|
||||
dat += "<a href='?src=\ref[src];loadarea=[A.type]'>[A.name]</a><br>"
|
||||
else
|
||||
dat += "Safety protocol: <span class='good'>Online</span> <a href='?\ref[src];safety=0'>Disengage</a><br>"
|
||||
|
||||
var/datum/browser/popup = new(user, "computer", name, 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
|
||||
/obj/machinery/computer/holodeck/proc/load_program(var/area/A, var/force = 0, var/delay = 0)
|
||||
if(stat)
|
||||
A = offline_program
|
||||
force = 1
|
||||
delay = 0
|
||||
if(program == A)
|
||||
return
|
||||
if(world.time < (last_change + 25 + (damaged?500:0)) && !force)
|
||||
if(delay)
|
||||
sleep(25)
|
||||
else
|
||||
if(world.time < (last_change + 15))//To prevent super-spam clicking, reduced process size and annoyance -Sieve
|
||||
return
|
||||
if(get_dist(usr,src) <= 3)
|
||||
usr << "<span class='warning'>ERROR. Recalibrating projection apparatus.</span>"
|
||||
return
|
||||
|
||||
last_change = world.time
|
||||
active = (A != offline_program)
|
||||
use_power = active+1
|
||||
|
||||
for(var/obj/effect/holodeck_effect/HE in effects)
|
||||
HE.deactivate(src)
|
||||
|
||||
for(var/item in spawned)
|
||||
derez(item, forced=force)
|
||||
|
||||
program = A
|
||||
// note nerfing does not yet work on guns, should
|
||||
// should also remove/limit/filter reagents?
|
||||
// this is an exercise left to others I'm afraid. -Sayu
|
||||
spawned = A.copy_contents_to(linked, 1, nerf_weapons = !emagged)
|
||||
for(var/obj/machinery/M in spawned)
|
||||
M.flags |= NODECONSTRUCT
|
||||
for(var/obj/structure/S in spawned)
|
||||
S.flags |= NODECONSTRUCT
|
||||
effects = list()
|
||||
|
||||
spawn(30)
|
||||
var/list/added = list()
|
||||
for(var/obj/effect/holodeck_effect/HE in spawned)
|
||||
effects += HE
|
||||
spawned -= HE
|
||||
var/atom/x = HE.activate(src)
|
||||
if(istype(x) || islist(x))
|
||||
spawned += x // holocarp are not forever
|
||||
added += x
|
||||
for(var/obj/machinery/M in added)
|
||||
M.flags |= NODECONSTRUCT
|
||||
for(var/obj/structure/S in added)
|
||||
S.flags |= NODECONSTRUCT
|
||||
|
||||
/obj/machinery/computer/holodeck/proc/derez(var/obj/obj, var/silent = 1, var/forced = 0)
|
||||
// Emagging a machine creates an anomaly in the derez systems.
|
||||
if(obj && src.emagged && !src.stat && !forced)
|
||||
if((ismob(obj) || istype(obj.loc,/mob)) && prob(50))
|
||||
spawn(50) .(obj,silent) // may last a disturbingly long time
|
||||
return
|
||||
spawned.Remove(obj)
|
||||
|
||||
if(!obj)
|
||||
return
|
||||
var/turf/T = get_turf(obj)
|
||||
for(var/atom/movable/AM in obj.contents) // these should be derezed if they were generated
|
||||
AM.loc = T // otherwise make sure they are dropped
|
||||
|
||||
if(istype(obj))
|
||||
var/mob/M = obj.loc
|
||||
if(ismob(M))
|
||||
M.unEquip(obj, 1) //Holoweapons should always drop.
|
||||
|
||||
for(var/mob/M in obj.contents)
|
||||
M.loc = obj.loc
|
||||
silent = 0
|
||||
|
||||
if(!silent)
|
||||
var/obj/oldobj = obj
|
||||
visible_message("The [oldobj.name] fades away!")
|
||||
qdel(obj)
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
The holodeck activates these shortly after the program loads,
|
||||
and deactivates them immediately before changing or disabling the holodeck.
|
||||
|
||||
These remove snowflake code for special holodeck functions.
|
||||
*/
|
||||
/obj/effect/holodeck_effect
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
icon_state = "x2"
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
|
||||
/obj/effect/holodeck_effect/proc/activate(var/obj/machinery/computer/holodeck/HC)
|
||||
return
|
||||
|
||||
/obj/effect/holodeck_effect/proc/deactivate(var/obj/machinery/computer/holodeck/HC)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
// Called by the holodeck computer as long as the program is running
|
||||
/obj/effect/holodeck_effect/proc/tick(var/obj/machinery/computer/holodeck/HC)
|
||||
return
|
||||
|
||||
/obj/effect/holodeck_effect/proc/safety(var/active)
|
||||
return
|
||||
|
||||
|
||||
// Generates a holodeck-tracked card deck
|
||||
/obj/effect/holodeck_effect/cards
|
||||
icon = 'icons/obj/toy.dmi'
|
||||
icon_state = "deck_nanotrasen_full"
|
||||
var/obj/item/toy/cards/deck/D
|
||||
|
||||
/obj/effect/holodeck_effect/cards/activate(var/obj/machinery/computer/holodeck/HC)
|
||||
D = new(loc)
|
||||
safety(!HC.emagged)
|
||||
D.holo = HC
|
||||
return D
|
||||
|
||||
/obj/effect/holodeck_effect/cards/safety(active)
|
||||
if(!D)
|
||||
return
|
||||
if(active)
|
||||
D.card_hitsound = null
|
||||
D.card_force = 0
|
||||
D.card_throwforce = 0
|
||||
D.card_throw_speed = 3
|
||||
D.card_throw_range = 7
|
||||
D.card_attack_verb = list("attacked")
|
||||
else
|
||||
D.card_hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
D.card_force = 5
|
||||
D.card_throwforce = 10
|
||||
D.card_throw_speed = 3
|
||||
D.card_throw_range = 7
|
||||
D.card_attack_verb = list("attacked", "sliced", "diced", "slashed", "cut")
|
||||
|
||||
|
||||
/obj/effect/holodeck_effect/sparks/activate(var/obj/machinery/computer/holodeck/HC)
|
||||
var/turf/T = get_turf(src)
|
||||
if(T)
|
||||
var/datum/effect_system/spark_spread/s = new
|
||||
s.set_up(3, 1, T)
|
||||
s.start()
|
||||
T.temperature = 5000
|
||||
T.hotspot_expose(50000,50000,1)
|
||||
|
||||
|
||||
|
||||
/obj/effect/holodeck_effect/mobspawner
|
||||
var/mobtype = /mob/living/simple_animal/hostile/carp/holocarp
|
||||
var/mob/mob = null
|
||||
|
||||
/obj/effect/holodeck_effect/mobspawner/activate(var/obj/machinery/computer/holodeck/HC)
|
||||
if(islist(mobtype))
|
||||
mobtype = pick(mobtype)
|
||||
mob = new mobtype(loc)
|
||||
|
||||
// these vars are not really standardized but all would theoretically create stuff on death
|
||||
for(var/v in list("butcher_results","corpse","weapon1","weapon2") & mob.vars)
|
||||
mob.vars[v] = null
|
||||
return mob
|
||||
|
||||
/obj/effect/holodeck_effect/mobspawner/deactivate(var/obj/machinery/computer/holodeck/HC)
|
||||
if(mob)
|
||||
HC.derez(mob)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/holodeck_effect/mobspawner/pet
|
||||
mobtype = list(
|
||||
/mob/living/simple_animal/butterfly, /mob/living/simple_animal/chick/holo,
|
||||
/mob/living/simple_animal/pet/cat, /mob/living/simple_animal/pet/cat/kitten,
|
||||
/mob/living/simple_animal/pet/dog/corgi, /mob/living/simple_animal/pet/dog/corgi/puppy,
|
||||
/mob/living/simple_animal/pet/dog/pug, /mob/living/simple_animal/pet/fox)
|
||||
|
||||
/obj/effect/holodeck_effect/mobspawner/bee
|
||||
mobtype = /mob/living/simple_animal/hostile/poison/bees/toxin
|
||||
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
Items, Structures, Machines
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// Items
|
||||
//
|
||||
|
||||
/obj/item/weapon/holo
|
||||
damtype = STAMINA
|
||||
|
||||
/obj/item/weapon/holo/esword
|
||||
name = "holographic energy sword"
|
||||
desc = "May the force be with you. Sorta"
|
||||
icon_state = "sword0"
|
||||
force = 3.0
|
||||
throw_speed = 2
|
||||
throw_range = 5
|
||||
throwforce = 0
|
||||
w_class = 2.0
|
||||
hitsound = "swing_hit"
|
||||
armour_penetration = 50
|
||||
var/active = 0
|
||||
|
||||
/obj/item/weapon/holo/esword/green/New()
|
||||
item_color = "green"
|
||||
|
||||
/obj/item/weapon/holo/esword/red/New()
|
||||
item_color = "red"
|
||||
|
||||
/obj/item/weapon/holo/esword/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance)
|
||||
if(active)
|
||||
return ..()
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/holo/esword/attack(target as mob, mob/user as mob)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/holo/esword/New()
|
||||
item_color = pick("red","blue","green","purple")
|
||||
|
||||
/obj/item/weapon/holo/esword/attack_self(mob/living/user as mob)
|
||||
active = !active
|
||||
if (active)
|
||||
force = 30
|
||||
icon_state = "sword[item_color]"
|
||||
w_class = 4
|
||||
hitsound = 'sound/weapons/blade1.ogg'
|
||||
playsound(user, 'sound/weapons/saberon.ogg', 20, 1)
|
||||
user << "<span class='warning'>[src] is now active.</span>"
|
||||
else
|
||||
force = 3
|
||||
icon_state = "sword0"
|
||||
w_class = 2
|
||||
hitsound = "swing_hit"
|
||||
playsound(user, 'sound/weapons/saberoff.ogg', 20, 1)
|
||||
user << "<span class='warning'>[src] can now be concealed.</span>"
|
||||
return
|
||||
|
||||
//BASKETBALL OBJECTS
|
||||
|
||||
/obj/item/toy/beach_ball/holoball
|
||||
name = "basketball"
|
||||
icon = 'icons/obj/basketball.dmi'
|
||||
icon_state = "basketball"
|
||||
item_state = "basketball"
|
||||
desc = "Here's your chance, do your dance at the Space Jam."
|
||||
w_class = 4 //Stops people from hiding it in their bags/pockets
|
||||
|
||||
/obj/item/toy/beach_ball/holoball/dodgeball
|
||||
name = "dodgeball"
|
||||
icon_state = "dodgeball"
|
||||
item_state = "dodgeball"
|
||||
desc = "Used for playing the most violent and degrading of childhood games."
|
||||
|
||||
/obj/item/toy/beach_ball/holoball/dodgeball/throw_impact(atom/hit_atom)
|
||||
..()
|
||||
if((ishuman(hit_atom)))
|
||||
var/mob/living/carbon/M = hit_atom
|
||||
playsound(src, 'sound/items/dodgeball.ogg', 50, 1)
|
||||
M.apply_damage(10, STAMINA)
|
||||
if(prob(5))
|
||||
M.Weaken(3)
|
||||
visible_message("<span class='danger'>[M] is knocked right off \his feet!</span>")
|
||||
|
||||
//
|
||||
// Structures
|
||||
//
|
||||
|
||||
/obj/structure/holohoop
|
||||
name = "basketball hoop"
|
||||
desc = "Boom, shakalaka!"
|
||||
icon = 'icons/obj/basketball.dmi'
|
||||
icon_state = "hoop"
|
||||
anchored = 1
|
||||
density = 1
|
||||
|
||||
/obj/structure/holohoop/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
|
||||
if(get_dist(src,user)<2)
|
||||
if(user.drop_item(src))
|
||||
visible_message("<span class='warning'> [user] dunks [W] into \the [src]!</span>")
|
||||
|
||||
/obj/structure/holohoop/attack_hand(mob/user)
|
||||
if(user.pulling && user.a_intent == "grab" && isliving(user.pulling))
|
||||
var/mob/living/L = user.pulling
|
||||
if(user.grab_state < GRAB_AGGRESSIVE)
|
||||
user << "<span class='warning'>You need a better grip to do that!</span>"
|
||||
return
|
||||
L.loc = src.loc
|
||||
L.Weaken(5)
|
||||
visible_message("<span class='danger'>[user] dunks [L] into \the [src]!</span>")
|
||||
user.stop_pulling()
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/structure/holohoop/CanPass(atom/movable/mover, turf/target, height=0)
|
||||
if (istype(mover,/obj/item) && mover.throwing)
|
||||
var/obj/item/I = mover
|
||||
if(istype(I, /obj/item/projectile))
|
||||
return
|
||||
if(prob(50))
|
||||
I.loc = src.loc
|
||||
visible_message("<span class='warning'> Swish! \the [I] lands in \the [src].</span>")
|
||||
else
|
||||
visible_message("<span class='danger'> \the [I] bounces off of \the [src]'s rim!</span>")
|
||||
return 0
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Machines
|
||||
//
|
||||
|
||||
/obj/machinery/readybutton
|
||||
name = "ready declaration device"
|
||||
desc = "This device is used to declare ready. If all devices in an area are ready, the event will begin!"
|
||||
icon = 'icons/obj/monitors.dmi'
|
||||
icon_state = "auth_off"
|
||||
var/ready = 0
|
||||
var/area/currentarea = null
|
||||
var/eventstarted = 0
|
||||
|
||||
anchored = 1.0
|
||||
use_power = 1
|
||||
idle_power_usage = 2
|
||||
active_power_usage = 6
|
||||
power_channel = ENVIRON
|
||||
|
||||
/obj/machinery/readybutton/attack_ai(mob/user as mob)
|
||||
user << "The station AI is not to interact with these devices"
|
||||
return
|
||||
|
||||
/obj/machinery/readybutton/attack_paw(mob/user as mob)
|
||||
user << "<span class='warning'>You are too primitive to use this device!</span>"
|
||||
return
|
||||
|
||||
/obj/machinery/readybutton/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
|
||||
user << "The device is a solid button, there's nothing you can do with it!"
|
||||
|
||||
/obj/machinery/readybutton/attack_hand(mob/user as mob)
|
||||
if(user.stat || stat & (NOPOWER|BROKEN))
|
||||
user << "<span class='warning'>This device is not powered!</span>"
|
||||
return
|
||||
|
||||
currentarea = get_area(src.loc)
|
||||
if(!currentarea)
|
||||
qdel(src)
|
||||
|
||||
if(eventstarted)
|
||||
usr << "<span class='warning'>The event has already begun!</span>"
|
||||
return
|
||||
|
||||
ready = !ready
|
||||
|
||||
update_icon()
|
||||
|
||||
var/numbuttons = 0
|
||||
var/numready = 0
|
||||
for(var/obj/machinery/readybutton/button in currentarea)
|
||||
numbuttons++
|
||||
if (button.ready)
|
||||
numready++
|
||||
|
||||
if(numbuttons == numready)
|
||||
begin_event()
|
||||
|
||||
/obj/machinery/readybutton/update_icon()
|
||||
if(ready)
|
||||
icon_state = "auth_on"
|
||||
else
|
||||
icon_state = "auth_off"
|
||||
|
||||
/obj/machinery/readybutton/proc/begin_event()
|
||||
|
||||
eventstarted = 1
|
||||
|
||||
for(var/obj/structure/window/W in currentarea)
|
||||
if(W.flags&NODECONSTRUCT) // Just in case: only holo-windows
|
||||
qdel(W)
|
||||
|
||||
for(var/mob/M in currentarea)
|
||||
M << "FIGHT!"
|
||||
@@ -0,0 +1,103 @@
|
||||
/turf/open/floor/holofloor
|
||||
icon_state = "floor"
|
||||
thermal_conductivity = 0
|
||||
broken_states = list("engine")
|
||||
burnt_states = list("engine")
|
||||
|
||||
/turf/open/floor/holofloor/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
return // HOLOFLOOR DOES NOT GIVE A FUCK
|
||||
|
||||
/turf/open/floor/holofloor/plating
|
||||
name = "Holodeck Projector Floor"
|
||||
icon_state = "engine"
|
||||
|
||||
/turf/open/floor/holofloor/plating/burnmix
|
||||
name = "Burn-mix Floor"
|
||||
initial_gas_mix = "o2=2500;plasma=5000;TEMP=370"
|
||||
|
||||
/turf/open/floor/holofloor/grass
|
||||
gender = PLURAL
|
||||
name = "lush grass"
|
||||
icon_state = "grass"
|
||||
|
||||
/turf/open/floor/holofloor/beach
|
||||
name = "sand"
|
||||
icon = 'icons/misc/beach.dmi'
|
||||
icon_state = "sand"
|
||||
|
||||
/turf/open/floor/holofloor/beach/coast_t
|
||||
name = "coastline"
|
||||
icon_state = "sandwater_t"
|
||||
|
||||
/turf/open/floor/holofloor/beach/coast_b
|
||||
name = "coastline"
|
||||
icon_state = "sandwater_b"
|
||||
|
||||
/turf/open/floor/holofloor/beach/water
|
||||
name = "water"
|
||||
icon_state = "water"
|
||||
|
||||
/turf/open/floor/holofloor/asteroid
|
||||
name = "Asteroid"
|
||||
icon_state = "asteroid0"
|
||||
|
||||
/turf/open/floor/holofloor/asteroid/New()
|
||||
icon_state = "asteroid[pick(0,1,2,3,4,5,6,7,8,9,10,11,12)]"
|
||||
..()
|
||||
|
||||
/turf/open/floor/holofloor/space
|
||||
name = "Space"
|
||||
icon = 'icons/turf/space.dmi'
|
||||
icon_state = "0"
|
||||
|
||||
/turf/open/floor/holofloor/space/New()
|
||||
icon_state = SPACE_ICON_STATE // so realistic
|
||||
..()
|
||||
|
||||
/turf/open/floor/holofloor/hyperspace
|
||||
name = "Hyperspace"
|
||||
icon = 'icons/turf/space.dmi'
|
||||
icon_state = "speedspace_ew_1"
|
||||
|
||||
/turf/open/floor/holofloor/hyperspace/New()
|
||||
icon_state = "speedspace_ew_[(x + 5*y + (y%2+1)*7)%15+1]"
|
||||
..()
|
||||
|
||||
/turf/open/floor/holofloor/hyperspace/ns/New()
|
||||
..()
|
||||
icon_state = "speedspace_ns_[(x + 5*y + (y%2+1)*7)%15+1]"
|
||||
|
||||
/turf/open/floor/holofloor/carpet
|
||||
name = "Carpet"
|
||||
desc = "Electrically inviting."
|
||||
icon = 'icons/turf/floors/carpet.dmi'
|
||||
icon_state = "carpet"
|
||||
floor_tile = /obj/item/stack/tile/carpet
|
||||
broken_states = list("damaged")
|
||||
smooth = SMOOTH_TRUE
|
||||
canSmoothWith = null
|
||||
|
||||
/turf/open/floor/holofloor/carpet/New()
|
||||
..()
|
||||
addtimer(src, "update_icon", 1)
|
||||
|
||||
/turf/open/floor/holofloor/carpet/update_icon()
|
||||
if(!..())
|
||||
return 0
|
||||
if(intact)
|
||||
queue_smooth(src)
|
||||
|
||||
/turf/open/floor/holofloor/snow
|
||||
name = "snow"
|
||||
desc = "Looks cold."
|
||||
icon = 'icons/turf/snow.dmi'
|
||||
icon_state = "snow"
|
||||
slowdown = 2
|
||||
|
||||
/turf/open/floor/holofloor/snow/cold
|
||||
initial_gas_mix = "o2=22;n2=82;TEMP=180"
|
||||
|
||||
/turf/open/floor/holofloor/asteroid
|
||||
name = "asteroid sand"
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
icon_state = "asteroid"
|
||||
Reference in New Issue
Block a user