mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-29 08:08:49 +01:00
Merge branch 'master' of https://github.com/tgstation/tgstation into gero_gero
# Conflicts: # icons/effects/96x96.dmi
This commit is contained in:
@@ -15,18 +15,7 @@
|
||||
unit_name = "solar panel control board"
|
||||
export_types = list(/obj/item/weapon/circuitboard/computer/solar_control)
|
||||
|
||||
|
||||
|
||||
/datum/export/swarmer
|
||||
cost = 2000
|
||||
unit_name = "deactivated alien deconstruction drone"
|
||||
export_types = list(/obj/item/device/unactivated_swarmer)
|
||||
|
||||
/datum/export/swarmer/applies_to(obj/O, contr = 0, emag = 0)
|
||||
if(!..())
|
||||
return FALSE
|
||||
|
||||
var/obj/item/device/unactivated_swarmer/S = O
|
||||
if(!S.crit_fail)
|
||||
return FALSE
|
||||
return TRUE
|
||||
export_types = list(/obj/item/device/deactivated_swarmer)
|
||||
|
||||
+206
-131
@@ -15,6 +15,9 @@
|
||||
The base of program_type will always be ignored; only subtypes will be loaded.
|
||||
*/
|
||||
|
||||
#define HOLODECK_CD 25
|
||||
#define HOLODECK_DMG_CD 500
|
||||
|
||||
/obj/machinery/computer/holodeck
|
||||
name = "holodeck control console"
|
||||
desc = "A computer used to control a nearby holodeck."
|
||||
@@ -26,109 +29,106 @@
|
||||
var/area/holodeck/last_program
|
||||
var/area/offline_program = /area/holodeck/rec_center/offline
|
||||
|
||||
var/list/program_cache = list()
|
||||
var/list/emag_programs = list()
|
||||
var/list/program_cache
|
||||
var/list/emag_programs
|
||||
|
||||
// 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/active = FALSE
|
||||
var/damaged = FALSE
|
||||
var/list/spawned = list()
|
||||
var/list/effects = list()
|
||||
var/last_change = 0
|
||||
|
||||
|
||||
var/current_cd = 0
|
||||
|
||||
/obj/machinery/computer/holodeck/Initialize(mapload)
|
||||
..()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/computer/holodeck/LateInitialize()
|
||||
if(ispath(holodeck_type,/area))
|
||||
var/list/possible = get_areas(holodeck_type,subtypes = FALSE)
|
||||
linked = pop(possible)
|
||||
if(ispath(offline_program,/area))
|
||||
var/list/possible = get_areas(offline_program,subtypes = FALSE)
|
||||
offline_program = pop(possible)
|
||||
// the following is necessary for power reasons
|
||||
if(!linked || !offline_program)
|
||||
log_world("No matching holodeck area found")
|
||||
qdel(src)
|
||||
return
|
||||
var/area/AS = get_area(src)
|
||||
if(istype(AS,/area/holodeck))
|
||||
log_world("### MAPPING ERROR")
|
||||
log_world("Holodeck computer cannot be in a holodeck.")
|
||||
log_world("This would cause circular power dependency.")
|
||||
qdel(src) // todo handle constructed computers
|
||||
return //l-lewd...
|
||||
else
|
||||
linked.linked = src // todo detect multiple/constructed computers
|
||||
if(ispath(holodeck_type, /area))
|
||||
linked = locate(holodeck_type) in GLOB.sortedAreas
|
||||
if(ispath(offline_program,/area))
|
||||
offline_program = locate(offline_program) in GLOB.sortedAreas
|
||||
// the following is necessary for power reasons
|
||||
if(!linked || !offline_program)
|
||||
log_world("No matching holodeck area found")
|
||||
qdel(src)
|
||||
return
|
||||
var/area/AS = get_area(src)
|
||||
if(istype(AS, /area/holodeck))
|
||||
log_world("### MAPPING ERROR")
|
||||
log_world("Holodeck computer cannot be in a holodeck.")
|
||||
log_world("This would cause circular power dependency.")
|
||||
qdel(src)
|
||||
return
|
||||
else
|
||||
linked.linked = src
|
||||
|
||||
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)
|
||||
generate_program_list()
|
||||
load_program(offline_program, FALSE, FALSE)
|
||||
|
||||
/obj/machinery/computer/holodeck/Destroy()
|
||||
emergency_shutdown()
|
||||
if(linked)
|
||||
linked.linked = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/holodeck/power_change()
|
||||
..()
|
||||
. = ..()
|
||||
toggle_power(!stat)
|
||||
|
||||
/obj/machinery/computer/holodeck/proc/toggle_power(toggleOn = 0)
|
||||
if(active == toggleOn) return
|
||||
/obj/machinery/computer/holodeck/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "holodeck", name, 400, 500, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
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/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
/obj/machinery/computer/holodeck/proc/emergency_shutdown()
|
||||
last_program = program
|
||||
load_program(offline_program,1)
|
||||
active = 0
|
||||
data["default_programs"] = program_cache
|
||||
if(emagged)
|
||||
data["emagged"] = TRUE
|
||||
data["emag_programs"] = emag_programs
|
||||
data["program"] = program
|
||||
data["can_toggle_safety"] = issilicon(user) || IsAdminGhost(user)
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/holodeck/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("load_program")
|
||||
var/program_to_load = text2path(params["type"])
|
||||
if(!ispath(program_to_load))
|
||||
return FALSE
|
||||
var/area/A = locate(program_to_load) in GLOB.sortedAreas
|
||||
if(A)
|
||||
load_program(A)
|
||||
if("safety")
|
||||
emagged = !emagged
|
||||
if(emagged && program && emag_programs[program.name])
|
||||
emergency_shutdown()
|
||||
nerf(emagged)
|
||||
|
||||
/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(damaged && prob(10))
|
||||
for(var/turf/T in linked)
|
||||
if(prob(5))
|
||||
do_sparks(2, 1, T)
|
||||
return
|
||||
|
||||
if(!..() || !active)
|
||||
return
|
||||
|
||||
if(!floorcheck())
|
||||
emergency_shutdown()
|
||||
damaged = 1
|
||||
damaged = TRUE
|
||||
for(var/mob/M in urange(10,src))
|
||||
M.show_message("The holodeck overloads!")
|
||||
|
||||
@@ -144,67 +144,24 @@
|
||||
for(var/item in spawned)
|
||||
if(!(get_turf(item) in linked))
|
||||
derez(item, 0)
|
||||
for(var/obj/effect/holodeck_effect/HE in effects)
|
||||
for(var/e in effects)
|
||||
var/obj/effect/holodeck_effect/HE = e
|
||||
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 || isspaceturf(T))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/machinery/computer/holodeck/Topic(href, list/href_list)
|
||||
if(..())
|
||||
/obj/machinery/computer/holodeck/emag_act(mob/user)
|
||||
if(emagged)
|
||||
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"])
|
||||
if(!issilicon(usr))
|
||||
return
|
||||
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)
|
||||
to_chat(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
|
||||
to_chat(user, "<span class='warning'>You vastly increase projector power and override the safety and security protocols.</span>")
|
||||
to_chat(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()
|
||||
if(linked)
|
||||
emergency_shutdown()
|
||||
linked.linked = null
|
||||
return ..()
|
||||
if(!LAZYLEN(emag_programs))
|
||||
to_chat(user, "[src] does not seem to have a card swipe port. It must be an inferior model.")
|
||||
return
|
||||
playsound(src, 'sound/effects/sparks4.ogg', 75, 1)
|
||||
emagged = TRUE
|
||||
to_chat(user, "<span class='warning'>You vastly increase projector power and override the safety and security protocols.</span>")
|
||||
to_chat(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")
|
||||
nerf(!emagged)
|
||||
|
||||
/obj/machinery/computer/holodeck/emp_act(severity)
|
||||
emergency_shutdown()
|
||||
@@ -216,4 +173,122 @@
|
||||
|
||||
/obj/machinery/computer/holodeck/blob_act(obj/structure/blob/B)
|
||||
emergency_shutdown()
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/holodeck/proc/generate_program_list()
|
||||
for(var/typekey in subtypesof(program_type))
|
||||
var/area/holodeck/A = locate(typekey) in GLOB.sortedAreas
|
||||
if(!A || A == offline_program || !A.contents.len)
|
||||
continue
|
||||
var/list/info_this = list()
|
||||
info_this["name"] = A.name
|
||||
info_this["type"] = A.type
|
||||
if(A.restricted)
|
||||
LAZYADD(emag_programs, list(info_this))
|
||||
else
|
||||
LAZYADD(program_cache, list(info_this))
|
||||
|
||||
/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/load_program, last_program, TRUE), 25)
|
||||
active = TRUE
|
||||
else
|
||||
last_program = program
|
||||
load_program(offline_program, TRUE)
|
||||
active = FALSE
|
||||
|
||||
/obj/machinery/computer/holodeck/proc/emergency_shutdown()
|
||||
last_program = program
|
||||
load_program(offline_program, TRUE)
|
||||
active = FALSE
|
||||
|
||||
/obj/machinery/computer/holodeck/proc/floorcheck()
|
||||
for(var/turf/T in linked)
|
||||
if(!T.intact || isspaceturf(T))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/holodeck/proc/nerf(active)
|
||||
for(var/obj/item/I in spawned)
|
||||
I.damtype = active ? STAMINA : initial(I.damtype)
|
||||
for(var/e in effects)
|
||||
var/obj/effect/holodeck_effect/HE = e
|
||||
HE.safety(active)
|
||||
|
||||
/obj/machinery/computer/holodeck/proc/load_program(area/A, force = FALSE, add_delay = TRUE)
|
||||
if(!is_operational())
|
||||
A = offline_program
|
||||
force = TRUE
|
||||
|
||||
if(program == A)
|
||||
return
|
||||
if(current_cd > world.time && !force)
|
||||
say("ERROR. Recalibrating projection apparatus.")
|
||||
return
|
||||
if(add_delay)
|
||||
current_cd = world.time + HOLODECK_CD
|
||||
if(damaged)
|
||||
current_cd += HOLODECK_DMG_CD
|
||||
active = (A != offline_program)
|
||||
use_power = active + IDLE_POWER_USE
|
||||
|
||||
for(var/e in effects)
|
||||
var/obj/effect/holodeck_effect/HE = e
|
||||
HE.deactivate(src)
|
||||
|
||||
for(var/item in spawned)
|
||||
derez(item, 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()
|
||||
|
||||
addtimer(CALLBACK(src, .proc/finish_spawn), 30)
|
||||
|
||||
/obj/machinery/computer/holodeck/proc/finish_spawn()
|
||||
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(obj/O, silent = TRUE, forced = FALSE)
|
||||
// Emagging a machine creates an anomaly in the derez systems.
|
||||
if(O && emagged && !stat && !forced)
|
||||
if((ismob(O) || ismob(O.loc)) && prob(50))
|
||||
addtimer(CALLBACK(src, .proc/derez, O, silent), 50) // may last a disturbingly long time
|
||||
return
|
||||
|
||||
spawned -= O
|
||||
if(!O)
|
||||
return
|
||||
var/turf/T = get_turf(O)
|
||||
for(var/atom/movable/AM in O) // these should be derezed if they were generated
|
||||
AM.forceMove(T)
|
||||
if(ismob(AM))
|
||||
silent = FALSE // otherwise make sure they are dropped
|
||||
|
||||
if(!silent)
|
||||
visible_message("[O] fades away!")
|
||||
qdel(O)
|
||||
|
||||
#undef HOLODECK_CD
|
||||
#undef HOLODECK_DMG_CD
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/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)
|
||||
to_chat(usr, "<span class='warning'>ERROR. Recalibrating projection apparatus.</span>")
|
||||
return
|
||||
|
||||
last_change = world.time
|
||||
active = (A != offline_program)
|
||||
use_power = active ? ACTIVE_POWER_USE : IDLE_POWER_USE
|
||||
|
||||
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) || ismob(obj.loc)) && 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
|
||||
if(ismob(AM))
|
||||
silent = FALSE // otherwise make sure they are dropped
|
||||
|
||||
if(!silent)
|
||||
visible_message("The [obj.name] fades away!")
|
||||
qdel(obj)
|
||||
@@ -106,6 +106,7 @@
|
||||
desc = "For grilling, broiling, charring, smoking, heating, roasting, toasting, simmering, searing, melting, and occasionally burning things."
|
||||
icon = 'icons/obj/hydroponics/equipment.dmi'
|
||||
icon_state = "bonfire"
|
||||
light_color = LIGHT_COLOR_FIRE
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
buckle_lying = 0
|
||||
@@ -113,6 +114,16 @@
|
||||
var/grill = FALSE
|
||||
var/fire_stack_strength = 5
|
||||
|
||||
/obj/structure/bonfire/dense
|
||||
density = TRUE
|
||||
|
||||
/obj/structure/bonfire/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover) && mover.checkpass(PASSTABLE))
|
||||
return TRUE
|
||||
if(mover.throwing)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/structure/bonfire/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/stack/rods) && !can_buckle && !grill)
|
||||
var/obj/item/stack/rods/R = W
|
||||
@@ -130,8 +141,7 @@
|
||||
R.use(1)
|
||||
grill = TRUE
|
||||
to_chat(user, "<span class='italics'>You add a grill to \the [src].")
|
||||
var/mutable_appearance/grill_overlay = mutable_appearance('icons/obj/hydroponics/equipment.dmi', "bonfire_grill")
|
||||
overlays += grill_overlay
|
||||
add_overlay("bonfire_grill")
|
||||
else
|
||||
return ..()
|
||||
if(W.is_hot())
|
||||
@@ -160,6 +170,8 @@
|
||||
var/obj/item/weapon/grown/log/L = new /obj/item/weapon/grown/log(src.loc)
|
||||
L.pixel_x += rand(1,4)
|
||||
L.pixel_y += rand(1,4)
|
||||
if(can_buckle || grill)
|
||||
new /obj/item/stack/rods(loc, 1)
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
else if(eye_blurry) //blurry eyes heal slowly
|
||||
adjust_blurriness(-1)
|
||||
|
||||
if (getBrainLoss() >= 60 && stat != DEAD)
|
||||
if (getBrainLoss() >= 60 && stat == CONSCIOUS)
|
||||
if(prob(3))
|
||||
if(prob(25))
|
||||
emote("drool")
|
||||
|
||||
@@ -97,7 +97,6 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
|
||||
desc = "Transmited over the signal is a strange message repeated in every language you know of, and some you don't too..." //the message is "nom nom nom"
|
||||
invisibility = 100
|
||||
|
||||
|
||||
//SWARMER AI
|
||||
//AI versions of the swarmer mini-antag
|
||||
//This is an Abstract Base, it re-enables AI, but does not give the swarmer any goals/targets
|
||||
@@ -107,7 +106,6 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
|
||||
weather_immunities = list("ash") //wouldn't be fun otherwise
|
||||
AIStatus = AI_ON
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/swarmer/ai/Initialize()
|
||||
. = ..()
|
||||
ToggleLight() //so you can see them eating you out of house and home/shooting you/stunlocking you for eternity
|
||||
@@ -262,16 +260,6 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
|
||||
check_friendly_fire = TRUE //you're supposed to protect the resource swarmers, you poop
|
||||
retreat_distance = 3
|
||||
minimum_distance = 3
|
||||
login_text_dump = {"
|
||||
<b>You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate.</b>
|
||||
<b>Clicking on any object will try to consume it, either deconstructing it into its components, destroying it, or integrating any materials it has into you if successful.</b>
|
||||
<b>Ctrl-Clicking on a mob will attempt to remove it from the area and place it in a safe environment for storage.</b>
|
||||
<b>Objectives:</b>
|
||||
1. Defend Resource Swarmers while they consume resources and replicate until there are no more resources left.
|
||||
2. Ensure that this location is fit for invasion at a later date; do not perform actions that would render it dangerous or inhospitable.
|
||||
3. Biological resources should not be harmed if possible, violent force can be applied should they fail to keep away.
|
||||
"}
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/swarmer/ai/ranged_combat/Aggro()
|
||||
..()
|
||||
@@ -285,16 +273,6 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
|
||||
health = 60
|
||||
maxHealth = 60
|
||||
ranged = FALSE
|
||||
login_text_dump = {"
|
||||
<b>You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate.</b>
|
||||
<b>Clicking on any object will try to consume it, either deconstructing it into its components, destroying it, or integrating any materials it has into you if successful.</b>
|
||||
<b>Ctrl-Clicking on a mob will attempt to remove it from the area and place it in a safe environment for storage.</b>
|
||||
<b>Objectives:</b>
|
||||
1. Defend Resource Swarmers while they consume resources and replicate until there are no more resources left.
|
||||
2. Ensure that this location is fit for invasion at a later date; do not perform actions that would render it dangerous or inhospitable.
|
||||
3. Biological resources should not be harmed if possible, violent force can be applied should they fail to keep away.
|
||||
"}
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/swarmer/ai/melee_combat/Aggro()
|
||||
..()
|
||||
|
||||
@@ -30,10 +30,9 @@
|
||||
spawned_mobs = null
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/spawner/Life()
|
||||
..()
|
||||
if(!stat)
|
||||
spawn_mob()
|
||||
/mob/living/simple_animal/hostile/spawner/handle_automated_action()
|
||||
. = ..()
|
||||
spawn_mob()
|
||||
|
||||
/mob/living/simple_animal/hostile/spawner/proc/spawn_mob()
|
||||
if(spawned_mobs.len >= max_mobs)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
/obj/item/weapon/gun/ballistic/update_icon()
|
||||
..()
|
||||
if(current_skin)
|
||||
icon_state = "[current_skin][suppressed ? "-suppressed" : ""][sawn_state ? "-sawn" : ""]"
|
||||
icon_state = "[unique_reskin[current_skin]][suppressed ? "-suppressed" : ""][sawn_state ? "-sawn" : ""]"
|
||||
else
|
||||
icon_state = "[initial(icon_state)][suppressed ? "-suppressed" : ""][sawn_state ? "-sawn" : ""]"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
icon_state = "deliverycloset"
|
||||
density = 1
|
||||
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
|
||||
var/giftwrapped = 0
|
||||
var/giftwrapped = FALSE
|
||||
var/sortTag = 0
|
||||
|
||||
/obj/structure/bigDelivery/attack_hand(mob/user)
|
||||
@@ -44,7 +44,7 @@
|
||||
var/obj/item/stack/wrapping_paper/WP = W
|
||||
if(WP.use(3))
|
||||
user.visible_message("[user] wraps the package in festive paper!")
|
||||
giftwrapped = 1
|
||||
giftwrapped = TRUE
|
||||
icon_state = "gift[icon_state]"
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need more paper!</span>")
|
||||
|
||||
@@ -1,49 +1,39 @@
|
||||
#define ASH_WALKER_SPAWN_THRESHOLD 2
|
||||
//The ash walker den consumes corpses or unconscious mobs to create ash walker eggs. For more info on those, check ghost_role_spawners.dm
|
||||
/mob/living/simple_animal/hostile/spawner/ash_walker
|
||||
name = "ash walker nest"
|
||||
desc = "A nest built around a necropolis tendril. The eggs seem to grow unnaturally fast..."
|
||||
icon = 'icons/mob/nest.dmi'
|
||||
/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker
|
||||
name = "necropolis tendril nest"
|
||||
desc = "A vile tendril of corruption. It's surrounded by a nest of rapidly growing eggs..."
|
||||
icon_state = "ash_walker_nest"
|
||||
icon_living = "ash_walker_nest"
|
||||
icon_dead = "ash_walker_nest"
|
||||
faction = list("ashwalker")
|
||||
health = 200
|
||||
maxHealth = 200
|
||||
loot = list(/obj/effect/gibspawner, /obj/item/device/assembly/signaler/anomaly)
|
||||
del_on_death = 1
|
||||
var/meat_counter
|
||||
var/obj/effect/light_emitter/tendril/emitted_light
|
||||
|
||||
/mob/living/simple_animal/hostile/spawner/ash_walker/Initialize()
|
||||
. = ..()
|
||||
emitted_light = new(loc)
|
||||
loot = list(/obj/effect/collapse)
|
||||
var/meat_counter = 6
|
||||
|
||||
/mob/living/simple_animal/hostile/spawner/ash_walker/Destroy()
|
||||
QDEL_NULL(emitted_light)
|
||||
. = ..()
|
||||
/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/death()
|
||||
new /obj/item/device/assembly/signaler/anomaly (get_step(loc, pick(GLOB.alldirs)))
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/spawner/ash_walker/Life()
|
||||
..()
|
||||
if(!stat)
|
||||
consume()
|
||||
spawn_mob()
|
||||
/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/handle_automated_action()
|
||||
consume()
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/spawner/ash_walker/proc/consume()
|
||||
for(var/mob/living/H in view(src,1)) //Only for corpse right next to/on same tile
|
||||
/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/proc/consume()
|
||||
for(var/mob/living/H in view(src, 1)) //Only for corpse right next to/on same tile
|
||||
if(H.stat)
|
||||
visible_message("<span class='warning'>Serrated tendrils eagerly pull [H] to [src], tearing the body apart as its blood seeps over the eggs.</span>")
|
||||
playsound(get_turf(src),'sound/magic/demon_consume.ogg', 100, 1)
|
||||
if(ismegafauna(H))
|
||||
meat_counter += 20
|
||||
else
|
||||
meat_counter ++
|
||||
for(var/obj/item/W in H)
|
||||
H.dropItemToGround(W)
|
||||
meat_counter++
|
||||
H.gib()
|
||||
adjustHealth(-maxHealth * 0.05)//restores 5% hp of tendril
|
||||
|
||||
/mob/living/simple_animal/hostile/spawner/ash_walker/spawn_mob()
|
||||
/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/spawn_mob()
|
||||
if(meat_counter >= ASH_WALKER_SPAWN_THRESHOLD)
|
||||
new /obj/effect/mob_spawn/human/ash_walker(get_step(src.loc, SOUTH))
|
||||
new /obj/effect/mob_spawn/human/ash_walker(get_step(loc, pick(GLOB.alldirs)))
|
||||
visible_message("<span class='danger'>One of the eggs swells to an unnatural size and tumbles free. It's ready to hatch!</span>")
|
||||
meat_counter -= ASH_WALKER_SPAWN_THRESHOLD
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
desc = "A massive stone gateway."
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "gate_full"
|
||||
flags = ON_BORDER
|
||||
appearance_flags = 0
|
||||
layer = TABLE_LAYER
|
||||
anchored = TRUE
|
||||
@@ -24,6 +25,7 @@
|
||||
|
||||
/obj/structure/necropolis_gate/Initialize()
|
||||
. = ..()
|
||||
setDir(SOUTH)
|
||||
var/turf/sight_blocker_turf = get_turf(src)
|
||||
if(sight_blocker_distance)
|
||||
for(var/i in 1 to sight_blocker_distance)
|
||||
@@ -32,6 +34,7 @@
|
||||
sight_blocker_turf = get_step(sight_blocker_turf, NORTH)
|
||||
if(sight_blocker_turf)
|
||||
sight_blocker = new (sight_blocker_turf) //we need to block sight in a different spot than most things do
|
||||
sight_blocker.pixel_y = initial(sight_blocker.pixel_y) - (32 * sight_blocker_distance)
|
||||
icon_state = "gate_bottom"
|
||||
top_overlay = mutable_appearance('icons/effects/96x96.dmi', "gate_top")
|
||||
top_overlay.layer = EDGED_TURF_LAYER
|
||||
@@ -53,9 +56,22 @@
|
||||
/obj/structure/necropolis_gate/singularity_pull()
|
||||
return 0
|
||||
|
||||
/obj/structure/necropolis_gate/CanPass(atom/movable/mover, turf/target, height=0)
|
||||
if(get_dir(loc, target) == dir)
|
||||
return !density
|
||||
return 1
|
||||
|
||||
/obj/structure/necropolis_gate/CheckExit(atom/movable/O, target)
|
||||
if(get_dir(O.loc, target) == dir)
|
||||
return !density
|
||||
return 1
|
||||
|
||||
/obj/structure/opacity_blocker
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "nothing"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "gate_blocker"
|
||||
layer = EDGED_TURF_LAYER
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
mouse_opacity = 0
|
||||
opacity = TRUE
|
||||
|
||||
@@ -94,6 +110,7 @@
|
||||
break
|
||||
sight_blocker_turf = get_step(sight_blocker_turf, NORTH)
|
||||
if(sight_blocker_turf)
|
||||
sight_blocker.pixel_y = initial(sight_blocker.pixel_y) - (32 * sight_blocker_distance)
|
||||
sight_blocker.forceMove(sight_blocker_turf)
|
||||
sleep(2.5)
|
||||
playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 30, TRUE, frequency = 15000)
|
||||
|
||||
Reference in New Issue
Block a user