mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-24 05:23:22 +01:00
Revenant Gameplay Enhancement (#11049)
This commit is contained in:
@@ -59,6 +59,7 @@
|
||||
#define LANGUAGE_CULT "Cult" // NOT CULTISTS!
|
||||
#define LANGUAGE_OCCULT "Occult"
|
||||
#define LANGUAGE_REVENANT "Revenant"
|
||||
#define LANGUAGE_REVENANT_RIFTSPEAK "Riftspeak"
|
||||
#define LANGUAGE_TERMINATOR "Hephaestus Darkcomms" // HKs.
|
||||
|
||||
// Lesser-form Languages
|
||||
|
||||
+11
-4
@@ -90,7 +90,7 @@
|
||||
return ..()
|
||||
|
||||
/datum/beam/proc/Draw()
|
||||
var/Angle = round(Get_Angle(origin.x ? origin : get_turf(origin), target.x ? target : get_turf(target)))
|
||||
var/Angle = round(Get_Angle(origin.z ? origin : get_turf(origin), target.z ? target : get_turf(target)))
|
||||
var/matrix/rot_matrix = matrix()
|
||||
rot_matrix.Turn(Angle)
|
||||
|
||||
@@ -183,6 +183,13 @@
|
||||
var/obj/effect/ebeam/B = beam
|
||||
B.color = COLOR_GRAY40
|
||||
|
||||
// this simplified datum will work with timed beams that are held
|
||||
/datum/beam/held/get_x_translation_vector()
|
||||
return (world.icon_size * target_oldloc.x) - (world.icon_size * origin_oldloc.x)
|
||||
|
||||
/datum/beam/held/get_y_translation_vector()
|
||||
return (world.icon_size * target_oldloc.y) - (world.icon_size * origin_oldloc.y)
|
||||
|
||||
/obj/effect/ebeam
|
||||
mouse_opacity = 0
|
||||
anchored = 1
|
||||
@@ -197,10 +204,10 @@
|
||||
owner = null
|
||||
return ..()
|
||||
|
||||
/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time = 3)
|
||||
/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time = 3, beam_datum_type=/datum/beam)
|
||||
if(time >= INFINITY)
|
||||
crash_with("Tried to create beam with infinite time!")
|
||||
return null
|
||||
var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time)
|
||||
var/datum/beam/newbeam = new beam_datum_type(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time)
|
||||
INVOKE_ASYNC(newbeam, /datum/beam/.proc/Start)
|
||||
return newbeam
|
||||
return newbeam
|
||||
@@ -0,0 +1,7 @@
|
||||
/datum/looping_sound/revenant_rift
|
||||
start_sound = list('sound/effects/psi/power_feedback.ogg' = 1)
|
||||
start_length = 8
|
||||
mid_sounds = list('sound/ambience/tension/horror.ogg' = 1)
|
||||
mid_length = 260
|
||||
end_sound = list('sound/effects/psi/power_feedback.ogg' = 1)
|
||||
volume = 80
|
||||
@@ -12,7 +12,22 @@ var/datum/antagonist/revenant/revenants = null
|
||||
hard_cap = 12
|
||||
hard_cap_round = 12
|
||||
|
||||
var/rifts_left = 3
|
||||
var/kill_count = 0
|
||||
var/obj/effect/portal/revenant/revenant_rift
|
||||
|
||||
/datum/antagonist/revenant/New()
|
||||
..()
|
||||
|
||||
revenants = src
|
||||
revenants = src
|
||||
|
||||
/datum/antagonist/revenant/proc/destroyed_rift()
|
||||
revenants.revenant_rift = null
|
||||
revenants.rifts_left--
|
||||
if(revenants.rifts_left <= 0)
|
||||
command_announcement.Announce("Aurora, we aren't detecting any more rift energy signatures. Mop up the rest of the invaders. Good work.", "Bluespace Breach Alert")
|
||||
|
||||
/proc/message_all_revenants(var/message)
|
||||
for(var/thing in human_mob_list)
|
||||
if(isrevenant(thing))
|
||||
to_chat(thing, message)
|
||||
@@ -40,6 +40,13 @@
|
||||
if(does_teleport)
|
||||
teleport(AM)
|
||||
|
||||
/obj/effect/portal/attackby(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/bluespace_neutralizer))
|
||||
user.visible_message("<b>[user]</b> collapses \the [src] with \the [I].", SPAN_NOTICE("You collapse \the [src] with \the [I]."))
|
||||
qdel(src)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/effect/portal/attack_hand(mob/user)
|
||||
set waitfor = FALSE
|
||||
|
||||
@@ -92,7 +99,7 @@
|
||||
if(next_spawn < world.time)
|
||||
visible_message(SPAN_WARNING("\The [src] spits something out!"))
|
||||
for(var/thing in spawn_things)
|
||||
var/spawn_path = text2path(thing)
|
||||
var/spawn_path = thing
|
||||
var/atom/spawned_thing = new spawn_path(get_turf(src))
|
||||
|
||||
if(istype(spawned_thing, /obj/item/stack))
|
||||
@@ -113,33 +120,137 @@
|
||||
/obj/effect/portal/spawner/metal
|
||||
num_of_spawns = 3
|
||||
spawn_things = list(
|
||||
"/obj/item/stack/material/steel" = 10,
|
||||
"/obj/item/stack/material/plasteel" = 5
|
||||
)
|
||||
/obj/item/stack/material/steel = 10,
|
||||
/obj/item/stack/material/plasteel = 5
|
||||
)
|
||||
|
||||
/obj/effect/portal/spawner/rare_metal
|
||||
num_of_spawns = 4
|
||||
spawn_things = list(
|
||||
"/obj/item/stack/material/gold" = 2,
|
||||
"/obj/item/stack/material/silver" = 2,
|
||||
"/obj/item/stack/material/uranium" = 2,
|
||||
"/obj/item/stack/material/diamond" = 1
|
||||
)
|
||||
/obj/item/stack/material/gold = 2,
|
||||
/obj/item/stack/material/silver = 2,
|
||||
/obj/item/stack/material/uranium = 2,
|
||||
/obj/item/stack/material/diamond = 1
|
||||
)
|
||||
|
||||
/obj/effect/portal/spawner/silver
|
||||
num_of_spawns = 3
|
||||
spawn_things = list(
|
||||
/obj/item/stack/material/silver = 3
|
||||
)
|
||||
|
||||
/obj/effect/portal/spawner/gold
|
||||
num_of_spawns = 3
|
||||
spawn_things = list(
|
||||
/obj/item/stack/material/gold = 3
|
||||
)
|
||||
|
||||
/obj/effect/portal/spawner/phoron
|
||||
num_of_spawns = 3
|
||||
spawn_things = list(
|
||||
"/obj/item/stack/material/phoron" = 3
|
||||
)
|
||||
/obj/item/stack/material/phoron = 3
|
||||
)
|
||||
|
||||
/obj/effect/portal/spawner/monkey_cube
|
||||
num_of_spawns = 1
|
||||
spawn_things = list(
|
||||
"/obj/item/reagent_containers/food/snacks/monkeycube" = 4
|
||||
)
|
||||
/obj/item/reagent_containers/food/snacks/monkeycube = 4
|
||||
)
|
||||
|
||||
/obj/effect/portal/spawner/cow // debug but funny so im keeping it
|
||||
num_of_spawns = 1
|
||||
spawn_things = list(
|
||||
"/mob/living/simple_animal/cow" = 1
|
||||
/mob/living/simple_animal/cow = 1
|
||||
)
|
||||
|
||||
#define COLOR_STAGE_FIVE "#163DFF"
|
||||
#define COLOR_STAGE_FOUR "#0099ff"
|
||||
#define COLOR_STAGE_THREE "#33eb33"
|
||||
#define COLOR_STAGE_TWO "#F0FF2B"
|
||||
#define COLOR_STAGE_ONE "#FF8D23"
|
||||
#define COLOR_STAGE_ZERO "#FF0000"
|
||||
|
||||
/obj/effect/portal/revenant
|
||||
name = "bluespace rift"
|
||||
desc = "A bluespace tear in space, reaching directly to another point within this region. This one looks like a one-way portal to here, don't come too close."
|
||||
desc_info = "This is a bluespace rift. It is a node wherein revenants can seep into this locale. To destroy it, you must bring a bluespace neutralizer near it."
|
||||
icon_state = "portal_g"
|
||||
|
||||
does_teleport = FALSE
|
||||
has_lifespan = FALSE
|
||||
|
||||
color = COLOR_STAGE_FIVE
|
||||
light_color = COLOR_STAGE_FIVE
|
||||
light_power = 6
|
||||
light_range = 8
|
||||
|
||||
var/last_color_level = 5
|
||||
var/health_timer = 10 MINUTES // you need to reduce the health by standing near it with a neutralizer
|
||||
var/datum/looping_sound/revenant_rift/soundloop
|
||||
|
||||
/obj/effect/portal/revenant/Initialize(mapload)
|
||||
. = ..()
|
||||
if(revenants.revenant_rift)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
var/turf/T = get_turf(src)
|
||||
log_and_message_admins("Revenant Bluespace Rift spawned at \the [get_area(T)]", null, T)
|
||||
revenants.revenant_rift = src
|
||||
soundloop = new(list(src), FALSE)
|
||||
soundloop.start()
|
||||
|
||||
/obj/effect/portal/revenant/Destroy()
|
||||
revenants.destroyed_rift()
|
||||
visible_message(FONT_LARGE(SPAN_DANGER("\The [src] collapses!")))
|
||||
new /obj/random/highvalue/no_crystal(src)
|
||||
new /obj/random/highvalue/no_crystal(src)
|
||||
for(var/thing in contents)
|
||||
var/obj/O = thing
|
||||
O.forceMove(get_turf(src))
|
||||
O.throw_at_random(FALSE, 3, THROWNOBJ_KNOCKBACK_SPEED)
|
||||
var/area/A = get_area(src)
|
||||
message_all_revenants(FONT_LARGE(SPAN_WARNING("The rift keeping us here has been destroyed in [A.name]!")))
|
||||
QDEL_NULL(soundloop)
|
||||
return ..()
|
||||
|
||||
/obj/effect/portal/revenant/attackby(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/bluespace_neutralizer))
|
||||
to_chat(user, SPAN_WARNING("You need to activate \the [I] and keep it near \the [src] to collapse it."))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/effect/portal/revenant/proc/reduce_health(var/amount = 1)
|
||||
health_timer -= amount
|
||||
if(health_timer <= 0)
|
||||
qdel(src)
|
||||
return
|
||||
update_icon()
|
||||
|
||||
/obj/effect/portal/revenant/update_icon()
|
||||
var/color_level = round((health_timer / 600) / 2) // this should give a value from 0 - 5
|
||||
if(color_level == last_color_level)
|
||||
return
|
||||
var/area/A = get_area(src)
|
||||
message_all_revenants(FONT_LARGE(SPAN_WARNING("The rift keeping us here is being attacked in [A.name]!")))
|
||||
last_color_level = color_level
|
||||
switch(color_level)
|
||||
if(0)
|
||||
color = COLOR_STAGE_ZERO
|
||||
if(1)
|
||||
color = COLOR_STAGE_ONE
|
||||
if(2)
|
||||
color = COLOR_STAGE_TWO
|
||||
if(3)
|
||||
color = COLOR_STAGE_THREE
|
||||
if(4)
|
||||
color = COLOR_STAGE_FOUR
|
||||
if(5)
|
||||
color = COLOR_STAGE_FIVE
|
||||
light_color = color
|
||||
update_light()
|
||||
|
||||
#undef COLOR_STAGE_FIVE
|
||||
#undef COLOR_STAGE_FOUR
|
||||
#undef COLOR_STAGE_THREE
|
||||
#undef COLOR_STAGE_TWO
|
||||
#undef COLOR_STAGE_ONE
|
||||
#undef COLOR_STAGE_ZERO
|
||||
@@ -0,0 +1,55 @@
|
||||
/obj/item/bluespace_neutralizer
|
||||
name = "bluespace neutralizer"
|
||||
desc = "A strange device, supposedly capable of pre-emptively shutting down bluespace portals."
|
||||
desc_info = "Click on it, or use it in-hand to activate it. Click on any portal-like structure to instantly close it. Stand near a bluespace rift while it's active to start the closing process."
|
||||
icon = 'icons/obj/contained_items/tools/neutralizer.dmi'
|
||||
icon_state = "neutralizer"
|
||||
contained_sprite = TRUE
|
||||
|
||||
var/tethered = FALSE // it needs to tether with the portal before it can start zapping
|
||||
var/last_zap = 0
|
||||
var/active = FALSE
|
||||
|
||||
/obj/item/bluespace_neutralizer/update_icon()
|
||||
icon_state = "neutralizer[active ? "-a" : ""]"
|
||||
|
||||
/obj/item/bluespace_neutralizer/attack_self(mob/user)
|
||||
if(!active && !revenants.revenant_rift)
|
||||
to_chat(user, SPAN_WARNING("\The [src] doesn't detect any large bluespace rifts in the region."))
|
||||
return
|
||||
toggle(user)
|
||||
|
||||
/obj/item/bluespace_neutralizer/proc/toggle(var/mob/user)
|
||||
active = !active
|
||||
if(active)
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
else
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
if(user)
|
||||
to_chat(user, SPAN_NOTICE("You turn \the [src] [active ? "on" : "off"]."))
|
||||
update_icon()
|
||||
|
||||
/obj/item/bluespace_neutralizer/process()
|
||||
if(active && !revenants.revenant_rift)
|
||||
toggle()
|
||||
return
|
||||
var/turf/our_turf = get_turf(src)
|
||||
if(!(our_turf.z == revenants.revenant_rift.z && get_dist(src, revenants.revenant_rift) < 5 && isInSight(src, revenants.revenant_rift)))
|
||||
tethered = FALSE
|
||||
return
|
||||
if(!tethered)
|
||||
visible_message(SPAN_DANGER("\The [src] tethers with \the [revenants.revenant_rift]!"))
|
||||
last_zap = world.time
|
||||
tethered = TRUE
|
||||
Beam(revenants.revenant_rift, icon_state="n_beam", icon = 'icons/effects/beam.dmi', time=2, maxdistance=5, beam_datum_type=/datum/beam/held)
|
||||
playsound(get_turf(src), 'sound/magic/Charge.ogg', 70, TRUE, extrarange = 30)
|
||||
return
|
||||
revenants.revenant_rift.reduce_health(world.time - last_zap)
|
||||
last_zap = world.time
|
||||
Beam(revenants.revenant_rift, icon_state="lightning[rand(1,12)]", icon = 'icons/effects/effects.dmi', time=2, maxdistance=5, beam_datum_type=/datum/beam/held)
|
||||
playsound(get_turf(src), 'sound/magic/LightningShock.ogg', 50, TRUE, extrarange = 30)
|
||||
|
||||
/obj/item/bluespace_neutralizer/Destroy()
|
||||
if(active)
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
return ..()
|
||||
@@ -1108,6 +1108,21 @@
|
||||
/obj/item/anomaly_core = 0.5
|
||||
)
|
||||
|
||||
/obj/random/highvalue/no_crystal
|
||||
problist = list(
|
||||
/obj/item/clothing/suit/armor/reactive = 0.5,
|
||||
/obj/item/clothing/glasses/thermal = 0.5,
|
||||
/obj/item/gun/projectile/automatic/rifle/shotgun = 0.5,
|
||||
/obj/random/sword = 0.5,
|
||||
/obj/item/gun/energy/lawgiver = 0.5,
|
||||
/obj/item/melee/energy/axe = 0.5,
|
||||
/obj/item/gun/projectile/automatic/terminator = 0.5,
|
||||
/obj/item/rig/military = 0.5,
|
||||
/obj/item/rig/unathi/fancy = 0.5,
|
||||
/obj/item/rig/vaurca/minimal = 0.5,
|
||||
/obj/item/anomaly_core = 0.5
|
||||
)
|
||||
|
||||
/obj/random/junk
|
||||
name = "random trash"
|
||||
desc = "This is toss."
|
||||
|
||||
@@ -17,6 +17,13 @@
|
||||
var/spawn_index = 1 // used to add a numerical identifier to the revenant. increases by 1 per spawn
|
||||
var/has_fired = FALSE
|
||||
|
||||
var/first_rift_done = FALSE
|
||||
|
||||
/datum/ghostspawner/revenant/cant_spawn(mob/user)
|
||||
. = ..()
|
||||
if(!. && revenants.rifts_left <= 0)
|
||||
return "The final rift has been closed."
|
||||
|
||||
/datum/ghostspawner/revenant/spawn_mob(mob/user)
|
||||
var/turf/T = select_spawnlocation()
|
||||
var/mob/living/carbon/human/revenant/R
|
||||
@@ -34,8 +41,11 @@
|
||||
R.ckey = user.ckey
|
||||
|
||||
revenants.add_antagonist(R.mind, TRUE, TRUE, FALSE, TRUE, TRUE)
|
||||
if(R.client)
|
||||
to_chat(R, FONT_LARGE(SPAN_CULT("You can now speak with all revenants in the game world by using \"[R.client.prefs.language_prefixes[1]]rs\" before a message.")))
|
||||
if(!has_fired)
|
||||
INVOKE_ASYNC(src, .proc/play_ambience, R)
|
||||
INVOKE_ASYNC(src, .proc/check_rift)
|
||||
|
||||
return R
|
||||
|
||||
@@ -46,4 +56,30 @@
|
||||
continue
|
||||
M.playsound_simple(get_turf(M), 'sound/ambience/tension/tension.ogg', 75, FALSE)
|
||||
to_chat(M, FONT_LARGE(SPAN_CULT("A faint hum coming from the station walls fills your ears...")))
|
||||
has_fired = TRUE
|
||||
has_fired = TRUE
|
||||
|
||||
/datum/ghostspawner/revenant/proc/check_rift()
|
||||
if(revenants.revenant_rift || revenants.rifts_left <= 0)
|
||||
return
|
||||
var/kills_needed = ((initial(revenants.rifts_left) - revenants.rifts_left) + 1) * 5
|
||||
if(revenants.kill_count > kills_needed)
|
||||
var/turf/rift_turf
|
||||
var/list/possible_landmarks = list()
|
||||
for(var/thing in landmarks_list)
|
||||
var/obj/effect/landmark/landmark = thing
|
||||
if(landmark.name == "RevenantRift")
|
||||
possible_landmarks += landmark
|
||||
if(length(possible_landmarks))
|
||||
var/obj/effect/landmark/L = pick(possible_landmarks)
|
||||
rift_turf = get_turf(L)
|
||||
if(rift_turf)
|
||||
new /obj/effect/portal/revenant(rift_turf)
|
||||
if(!first_rift_done)
|
||||
command_announcement.Announce("Aurora, we're detecting energy signatures eerily similar to a bluespace rift breach inside your hull. [SScargo.shuttle ? "We're sending you a bluespace neutralizer via the cargo shuttle. " : ""]Locate the rift and shut it down.", "Bluespace Breach Alert")
|
||||
first_rift_done = TRUE
|
||||
if(SScargo.shuttle)
|
||||
var/turf/T = pick_area_turf(pick(SScargo.shuttle.shuttle_area), list(/proc/not_turf_contains_dense_objects))
|
||||
if(T)
|
||||
var/obj/structure/closet/crate/C = new /obj/structure/closet/crate(T)
|
||||
C.name += " (Neutralizer)"
|
||||
new /obj/item/bluespace_neutralizer(C)
|
||||
@@ -22,6 +22,7 @@
|
||||
var/list/partial_understanding // List of languages that can /somehwat/ understand it, format is: name = chance of understanding a word
|
||||
var/machine_understands = TRUE // Whether machines can parse and understand this language
|
||||
var/allow_accents = FALSE
|
||||
var/always_parse_language = FALSE // forces the language to parse for language keys even when a default is set
|
||||
|
||||
/datum/language/proc/get_random_name(var/gender, name_count=2, syllable_count=4, syllable_divisor=2)
|
||||
if(!syllables || !syllables.len)
|
||||
|
||||
@@ -104,4 +104,11 @@
|
||||
key = "c"
|
||||
syllables = list("grhhg", "ghrohg", "grgugh", "grrhh", "hghh", "rghghh", "gghhh", "ggrh", "aghrh")
|
||||
flags = RESTRICTED
|
||||
partial_understanding = list(LANGUAGE_TCB = 80)
|
||||
partial_understanding = list(LANGUAGE_TCB = 80)
|
||||
always_parse_language = TRUE
|
||||
|
||||
/datum/language/revenant/hivemind
|
||||
name = LANGUAGE_REVENANT_RIFTSPEAK
|
||||
desc = "A manner of speaking that allows revenants to talk to eachother no matter the distance."
|
||||
key = "rs"
|
||||
flags = RESTRICTED | HIVEMIND
|
||||
@@ -101,6 +101,7 @@
|
||||
if(player_is_antag(H.mind))
|
||||
var/datum/ghostspawner/revenant/R = SSghostroles.get_spawner(MODE_REVENANT)
|
||||
R.count = max(R.count - 1, 0)
|
||||
revenants.kill_count++
|
||||
INVOKE_ASYNC(src, .proc/spawn_gore, get_turf(H))
|
||||
H.set_death_time(ANIMAL, world.time)
|
||||
for(var/obj/item/I in H)
|
||||
@@ -108,6 +109,8 @@
|
||||
qdel(H)
|
||||
|
||||
/datum/species/revenant/proc/spawn_gore(var/turf/T)
|
||||
var/portal_type = pick(/obj/effect/portal/spawner/silver, /obj/effect/portal/spawner/gold, /obj/effect/portal/spawner/phoron)
|
||||
new portal_type(T)
|
||||
var/obj/effect/decal/cleanable/blood/gibs/G = new /obj/effect/decal/cleanable/blood/gibs(T)
|
||||
G.basecolor = blood_color
|
||||
G.fleshcolor = flesh_color
|
||||
@@ -119,6 +122,7 @@
|
||||
..()
|
||||
H.gender = NEUTER
|
||||
H.universal_understand = TRUE
|
||||
H.add_language(LANGUAGE_REVENANT_RIFTSPEAK)
|
||||
|
||||
/datum/species/revenant/get_random_name()
|
||||
return "Revenant"
|
||||
|
||||
@@ -184,7 +184,7 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
message = formalize_text(message)
|
||||
|
||||
//parse the language code and consume it
|
||||
if(!speaking)
|
||||
if(!speaking || speaking.always_parse_language)
|
||||
speaking = parse_language(message)
|
||||
if(speaking)
|
||||
message = copytext(message,2+length(speaking.key))
|
||||
|
||||
@@ -140,6 +140,14 @@
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/proc/isrevenant(A)
|
||||
if(ishuman(A))
|
||||
var/mob/living/carbon/human/H = A
|
||||
switch(H.get_species())
|
||||
if(SPECIES_REVENANT)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/proc/islesserform(A)
|
||||
if(istype(A, /mob/living/carbon/human))
|
||||
switch(A:get_species())
|
||||
|
||||
@@ -159,9 +159,12 @@
|
||||
return all_languages["Noise"]
|
||||
|
||||
if(length(message) >= 2 && is_language_prefix(prefix))
|
||||
var/language_prefix = lowertext(copytext(message, 2 ,3))
|
||||
var/language_prefix = lowertext(copytext(message, 2, 4))
|
||||
var/datum/language/L = language_keys[language_prefix]
|
||||
if (can_speak(L))
|
||||
if(!L)
|
||||
language_prefix = lowertext(copytext(message, 2, 3))
|
||||
L = language_keys[language_prefix]
|
||||
if(can_speak(L))
|
||||
return L
|
||||
|
||||
return null
|
||||
|
||||
@@ -143,4 +143,10 @@ datum/design/item/tool/advanced_light_replacer
|
||||
desc = "The infamously Idris Service Standard refers to this monstrous, self-stabilizing back-mounted utensil and service item holder, not anything professional."
|
||||
req_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 2)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 1500, MATERIAL_GLASS = 1500)
|
||||
build_path = /obj/item/storage/backpack/service
|
||||
build_path = /obj/item/storage/backpack/service
|
||||
|
||||
/datum/design/item/tool/bluespace_neutralizer
|
||||
desc = "A state of the art bluespace neutralizer, capable of shutting down any bluespace portal it gets used on. A special mode exists for severe interdimensional breaches, but this is highly unlikely to be necessary."
|
||||
req_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 2, TECH_BLUESPACE = 4)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 20000, MATERIAL_GLASS = 20000, MATERIAL_SILVER = 20000, MATERIAL_GOLD = 20000, MATERIAL_PHORON = 10000)
|
||||
build_path = /obj/item/bluespace_neutralizer
|
||||
Reference in New Issue
Block a user