Merge pull request #13015 from SuperSayu/Holodecker

Holodeck Upgrades [MAP]
This commit is contained in:
Razharas
2015-11-16 04:51:49 +03:00
22 changed files with 1229 additions and 863 deletions
+111
View File
@@ -0,0 +1,111 @@
/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 = -1 // 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/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.dir = 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.contents + O2
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
copiedobjs += DuplicateObject(M , 1, newloc = X)
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)
X.vars[V] = T.vars[V]
toupdate += X
if(toupdate.len)
for(var/turf/simulated/T1 in toupdate)
T1.CalculateAdjacentTurfs()
SSair.add_to_active(T1,1)
return copiedobjs
+97
View File
@@ -0,0 +1,97 @@
/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"
// 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
+210
View File
@@ -0,0 +1,210 @@
/*
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 typesof(program_type) - 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/simulated/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 ultra_range(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/space))
return 0
return 1
/obj/machinery/computer/holodeck/Topic(href, list/href_list)
if(..())
return
if(Adjacent(usr) || istype(usr, /mob/living/silicon))
usr.set_machine(src)
src.add_fingerprint(usr)
if(href_list["loadarea"])
var/typepath = text2path(href_list["loadarea"])
if(ispath(typepath,/area))
var/area/target = locate(typepath)
if(istype(target))
load_program(target)
else
world.log << "area not ready: [typepath]"
else
world.log << "bad area argument: [href_list["loadarea"]]"
else if("safety" in href_list)
var/oe = emagged
emagged = !text2num(href_list["safety"])
if(oe == emagged) return
if(program && !stat)
if(!emagged && program.restricted)
load_program(offline_program)
else
nerf(!emagged)
src.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(src.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")
src.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()
emergency_shutdown()
..()
+109
View File
@@ -0,0 +1,109 @@
/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)
effects = list()
spawn(30)
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
/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)
+87
View File
@@ -0,0 +1,87 @@
/*
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 = 101
proc/activate(var/obj/machinery/computer/holodeck/HC)
return
proc/deactivate(var/obj/machinery/computer/holodeck/HC)
qdel(src)
return
// Called by the holodeck computer as long as the program is running
proc/tick(var/obj/machinery/computer/holodeck/HC)
return
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)
+220
View File
@@ -0,0 +1,220 @@
/*
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"
flags = NOSHIELD
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/IsShield()
if(active)
return 1
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>", 3)
//
// Structures
//
/obj/structure/stool/bed/chair/holo/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/wrench))
user << "It's holographic! There's no taking it apart."
return
..()
/obj/structure/stool/bed/chair/holo/comfy
name = "comfy chair"
desc = "It looks comfy."
icon_state = "comfychair"
color = rgb(255,113,0)
/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 (istype(W, /obj/item/weapon/grab) && get_dist(src,user)<2)
var/obj/item/weapon/grab/G = W
if(G.state < GRAB_AGGRESSIVE)
user << "<span class='warning'>You need a better grip to do that!</span>"
return
G.affecting.loc = src.loc
G.affecting.Weaken(5)
visible_message("<span class='danger'>[G.assailant] dunks [G.affecting] into \the [src]!</span>", 3)
qdel(W)
return
else if (istype(W, /obj/item) && get_dist(src,user)<2)
user.drop_item(src)
visible_message("<span class='warning'> [user] dunks [W] into \the [src]!</span>", 3)
return
/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>", 3)
else
visible_message("<span class='danger'> \the [I] bounces off of \the [src]'s rim!</span>", 3)
return 0
else
return ..(mover, target, height)
//
// 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/New()
..()
/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/holo/W in currentarea)
qdel(W)
for(var/mob/M in currentarea)
M << "FIGHT!"
+68
View File
@@ -0,0 +1,68 @@
/obj/structure/table/holo
name = "table"
frame = null
buildstackamount = 0
framestackamount = 0
canSmoothWith = null
/obj/structure/table/holo/glass
name = "glass table"
icon = 'icons/obj/smooth_structures/glass_table.dmi'
icon_state = "glass_table"
/obj/structure/table/holo/wood
name = "wood table"
icon = 'icons/obj/smooth_structures/wood_table.dmi'
icon_state = "wood_table"
canSmoothWith = list(/obj/structure/table/holo/wood, /obj/structure/table/holo/poker)
/obj/structure/table/holo/poker
name = "poker table"
icon = 'icons/obj/smooth_structures/poker_table.dmi'
icon_state = "poker_table"
canSmoothWith = list(/obj/structure/table/holo/wood, /obj/structure/table/holo/poker)
/obj/structure/table/holo/attack_paw(mob/user as mob)
return
/obj/structure/table/holo/attack_alien(mob/user as mob)
return
/obj/structure/table/holo/attack_animal(mob/living/simple_animal/user as mob)
return
/obj/structure/table/holo/attack_hand(mob/user as mob)
return
/obj/structure/table/holo/attack_hulk()
return
/obj/structure/table/holo/attackby(obj/item/I, mob/user, params)
if (istype(I, /obj/item/weapon/grab))
tablepush(I, user)
return
if (istype(I, /obj/item/weapon/storage/bag/tray))
var/obj/item/weapon/storage/bag/tray/T = I
if(T.contents.len > 0) // If the tray isn't empty
var/list/obj/item/oldContents = T.contents.Copy()
T.quick_empty()
for(var/obj/item/C in oldContents)
C.loc = src.loc
user.visible_message("[user] empties [I] on [src].")
return
// If the tray IS empty, continue on (tray will be placed on the table like other items)
if(isrobot(user))
return
if(!(I.flags & ABSTRACT)) //rip more parems rip in peace ;_;
if(user.drop_item())
I.Move(loc)
var/list/click_params = params2list(params)
//Center the icon where the user clicked.
if(!click_params || !click_params["icon-x"] || !click_params["icon-y"])
return
//Clamp it so that the icon never moves more than 16 pixels in either direction (thus leaving the table turf)
I.pixel_x = Clamp(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2)
I.pixel_y = Clamp(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2)
+80
View File
@@ -0,0 +1,80 @@
/turf/simulated/floor/holofloor
icon_state = "floor"
thermal_conductivity = 0
broken_states = list()
burnt_states = list()
/turf/simulated/floor/holofloor/attackby(obj/item/weapon/W as obj, mob/user as mob)
return // HOLOFLOOR DOES NOT GIVE A FUCK
/turf/simulated/floor/holofloor/plating
name = "Holodeck Projector Floor"
icon_state = "engine"
/turf/simulated/floor/holofloor/grass
gender = PLURAL
name = "lush grass"
icon_state = "grass"
/turf/simulated/floor/holofloor/beach
name = "sand"
icon = 'icons/misc/beach.dmi' // what
icon_state = "sand"
/turf/simulated/floor/holofloor/beach/coast
name = "coastline"
icon = 'icons/misc/beach2.dmi' // why
icon_state = "sandwater"
/turf/simulated/floor/holofloor/beach/water
name = "water"
icon_state = "water"
/turf/simulated/floor/holofloor/asteroid
name = "Asteroid"
icon_state = "asteroid0"
/turf/simulated/floor/holofloor/asteroid/New()
icon_state = "asteroid[pick(0,1,2,3,4,5,6,7,8,9,10,11,12)]"
..()
/turf/simulated/floor/holofloor/space
name = "Space"
icon = 'icons/turf/space.dmi'
icon_state = "0"
/turf/simulated/floor/holofloor/space/New()
icon_state = "[((x + y) ^ ~(x * y) + z) % 25]" // so realistic
..()
/turf/simulated/floor/holofloor/hyperspace
name = "Hyperspace"
icon = 'icons/turf/space.dmi'
icon_state = "speedspace_ew_1"
/turf/simulated/floor/holofloor/hyperspace/New()
icon_state = "speedspace_ew_[(x + 5*y + (y%2+1)*7)%15+1]"
..()
/turf/simulated/floor/holofloor/hyperspace/ns/New()
..()
icon_state = "speedspace_ns_[(x + 5*y + (y%2+1)*7)%15+1]"
/turf/simulated/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/simulated/floor/holofloor/carpet/New()
..()
spawn(1)
update_icon()
/turf/simulated/floor/holofloor/carpet/update_icon()
if(!..())
return 0
if(intact)
smooth_icon(src)
+44
View File
@@ -0,0 +1,44 @@
/obj/structure/window/holo
name = "reinforced window"
icon = 'icons/obj/structures.dmi'
icon_state = "rwindow"
desc = "A window. It has an electric hum to it."
density = 1
layer = 3.2//Just above doors
pressure_resistance = 4*ONE_ATMOSPHERE
anchored = 1.0
flags = ON_BORDER
maxhealth = 100
disassembled = 1 // prevents noise on destruction
/obj/structure/window/holo/New()
..()
for(var/O in contents)
qdel(O) // standard window code generates stuff no matter what we want
/obj/structure/window/holo/spawnfragments()
qdel(src)
return
/obj/structure/window/holo/attackby(var/obj/item/I, var/mob/user)
if(istype(I,/obj/item/weapon/screwdriver))
user << "You see no screws to unfasten!"
return
return ..()
/obj/structure/window/holo/hit(var/damage, var/sound_effect = 1)
. = ..()
spawn(50) // self-healing
health += damage
/obj/structure/window/holo/opaque
name = "tinted window"
opacity = 1
/obj/structure/window/holo/fulltile
dir = 5
maxhealth = 250
/obj/structure/window/holo/opaque/fulltile
dir = 5
maxhealth = 250
@@ -177,6 +177,10 @@
new /mob/living/simple_animal/chicken(src.loc)
qdel(src)
/mob/living/simple_animal/chick/holo/Life()
..()
amount_grown = 0
var/const/MAX_CHICKENS = 50
var/global/chicken_count = 0