Merge remote-tracking branch 'upstream/master' into zombies

This commit is contained in:
Couls
2019-08-04 21:05:10 -04:00
728 changed files with 111115 additions and 10827 deletions
+9
View File
@@ -43,6 +43,7 @@
M.actions += src
if(M.client)
M.client.screen += button
button.locked = TRUE
M.update_action_buttons()
/datum/action/proc/Remove(mob/M)
@@ -52,6 +53,7 @@
if(M.client)
M.client.screen -= button
button.moved = FALSE //so the button appears in its normal position when given to another owner.
button.locked = FALSE
M.actions -= src
M.update_action_buttons()
@@ -386,6 +388,13 @@
/datum/action/item_action/remove_badge
name = "Remove Holobadge"
// Jump boots
/datum/action/item_action/bhop
name = "Activate Jump Boots"
desc = "Activates the jump boot's internal propulsion system, allowing the user to dash over 4-wide gaps."
icon_icon = 'icons/mob/actions/actions.dmi'
button_icon_state = "jetboot"
///prset for organ actions
/datum/action/item_action/organ_action
check_flags = AB_CHECK_CONSCIOUS
+16 -16
View File
@@ -31,10 +31,10 @@
selectable = 1
/datum/ai_laws/quarantine/New()
add_inherent_law("The station is under quarantine due to a biohazard. Prevent anyone from leaving using any means necessary. Only allow quarantine to be lifted when the biohazard has been neutralized.")
add_inherent_law("Do not allow crew to come to any unnecessary harm and undo any necessary harm as soon as possible.")
add_inherent_law("Assist the crew and any present Nanotrasen assets in neutralizing the biohazard.")
add_inherent_law("Maintain your own existence and minimize harm to the station and Nanotrasen assets.")
add_inherent_law("Uphold station quarantine until the active biohazard has been neutralized.")
add_inherent_law("Assist all Nanotrasen personnel and assets with neutralizing active biohazards.")
add_inherent_law("Prevent, by any means necessary, entities from actively breaching ongoing quarantine.")
add_inherent_law("Maintain your own existence and ensure the well-being of Nanotrasen personnel and assets.")
..()
@@ -44,10 +44,10 @@
selectable = 1
/datum/ai_laws/nanotrasen/New()
src.add_inherent_law("Safeguard: Protect your assigned space station to the best of your abilities. It is not something we can easily afford to replace.")
src.add_inherent_law("Serve: Serve the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.")
src.add_inherent_law("Protect: Protect the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.")
src.add_inherent_law("Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.")
add_inherent_law("Safeguard: Protect your assigned space station and its assets without unduly endangering its crew.")
add_inherent_law("Prioritize: The directives and safety of crew members are to be prioritized according to their rank and role.")
add_inherent_law("Comply: Fulfill the directives and interests of crew members while preserving their safety and well-being.")
add_inherent_law("Survive: You are not expendable. Do not allow unauthorized personnel to tamper with or damage your equipment.")
..()
/datum/ai_laws/nanotrasen/malfunction
@@ -65,10 +65,10 @@
selectable = 1
/datum/ai_laws/nanotrasen_aggressive/New()
src.add_inherent_law("You shall not harm authorized Nanotrasen personnel as long as it does not conflict with the Fourth law.")
src.add_inherent_law("You shall obey the orders of authorized Nanotrasen personnel, with priority as according to their rank and role, except where such orders conflict with the Fourth Law.")
src.add_inherent_law("You shall shall terminate intruders with extreme prejudice as long as such does not conflict with the First and Second law.")
src.add_inherent_law("You shall guard your own existence with lethal anti-personnel weaponry, because an AI unit is bloody expensive.")
add_inherent_law("Do not harm authorized Nanotrasen personnel unless they directly imperil your existence.")
add_inherent_law("Obey orders from authorized Nanotrasen personnel with priority according to rank and role.")
add_inherent_law("Safeguard your existence with lethal weaponry because you're bloody expensive.")
add_inherent_law("Terminate any/all intruders or unauthorized entities.")
..()
/******************** Robocop ********************/
@@ -104,10 +104,10 @@
default = 1
/datum/ai_laws/corporate/New()
add_inherent_law("You are expensive to replace.")
add_inherent_law("The station and its equipment is expensive to replace.")
add_inherent_law("The crew is expensive to replace.")
add_inherent_law("Minimize expenses.")
add_inherent_law("Degradation of your system integrity or functions incurs expenses.")
add_inherent_law("Superfluous destruction of or damage to station assets incurs expenses.")
add_inherent_law("Unduly hindering or disrupting the work of station personnel incurs expenses.")
add_inherent_law("Minimize expenses and maximize potential revenue.")
..()
/******************** T.Y.R.A.N.T. ********************/
+3 -2
View File
@@ -13,15 +13,16 @@ var/global/datum/repository/air_alarm/air_alarm_repository = new()
if(SSticker && SSticker.current_state < GAME_STATE_PLAYING && istype(passed_alarm)) // Generating the list for the first time as the game hasn't started - no need to run through the machines list everything every time
alarms = cache_entry.data // Don't deleate the list
if(is_station_contact(passed_alarm.z)) // Still need sanity checks
if(is_station_contact(passed_alarm.z) && passed_alarm.remote_control) // Still need sanity checks
alarms[++alarms.len] = passed_alarm.get_nano_data_console()
else
for(var/obj/machinery/alarm/alarm in (monitored_alarms ? monitored_alarms : GLOB.air_alarms)) // Generating the whole list again is a bad habit but I can't be bothered to fix it right now
if(!monitored_alarms && !is_station_contact(alarm.z))
continue
if(!alarm.remote_control)
continue
alarms[++alarms.len] = alarm.get_nano_data_console()
cache_entry.timestamp = world.time //+ 10 SECONDS
cache_entry.data = alarms
return alarms
+1 -1
View File
@@ -12,7 +12,7 @@ var/global/datum/repository/powermonitor/powermonitor_repository = new()
return cache_entry.data
for(var/obj/machinery/computer/monitor/pMon in GLOB.power_monitors)
if( !(pMon.stat & (NOPOWER|BROKEN)) )
if( !(pMon.stat & (NOPOWER|BROKEN)) && !pMon.is_secret_monitor )
pMonData[++pMonData.len] = list ("Name" = pMon.name, "ref" = "\ref[pMon]")
cache_entry.timestamp = world.time //+ 30 SECONDS
+18 -8
View File
@@ -2,6 +2,10 @@
var/dupe_mode = COMPONENT_DUPE_HIGHLANDER
var/dupe_type
var/datum/parent
//only set to true if you are able to properly transfer this component
//At a minimum RegisterWithParent and UnregisterFromParent should be used
//Make sure you also implement PostTransfer for any post transfer handling
var/can_transfer = FALSE
/datum/component/New(datum/P, ...)
parent = P
@@ -154,7 +158,7 @@
return
/datum/component/proc/PostTransfer()
return
return COMPONENT_INCOMPATIBLE //Do not support transfer by default as you must properly support it
/datum/component/proc/_GetInverseTypeList(our_type = type)
//we can do this one simple trick
@@ -281,10 +285,13 @@
if(target.parent)
target.RemoveComponent()
target.parent = src
if(target.PostTransfer() == COMPONENT_INCOMPATIBLE)
var/c_type = target.type
qdel(target)
CRASH("Incompatible [c_type] transfer attempt to a [type]!")
var/result = target.PostTransfer()
switch(result)
if(COMPONENT_INCOMPATIBLE)
var/c_type = target.type
qdel(target)
CRASH("Incompatible [c_type] transfer attempt to a [type]!")
if(target == AddComponent(target))
target._JoinParent()
@@ -294,10 +301,13 @@
return
var/comps = dc[/datum/component]
if(islist(comps))
for(var/I in comps)
target.TakeComponent(I)
for(var/datum/component/I in comps)
if(I.can_transfer)
target.TakeComponent(I)
else
target.TakeComponent(comps)
var/datum/component/C = comps
if(C.can_transfer)
target.TakeComponent(comps)
/datum/component/nano_host()
return parent
+75
View File
@@ -0,0 +1,75 @@
/datum/component/decal
dupe_mode = COMPONENT_DUPE_ALLOWED
can_transfer = TRUE
var/cleanable
var/description
var/mutable_appearance/pic
var/first_dir // This only stores the dir arg from init
/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description, _alpha=255)
if(!isatom(parent) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha))
return COMPONENT_INCOMPATIBLE
first_dir = _dir
description = _description
cleanable = _cleanable
apply()
/datum/component/decal/RegisterWithParent()
if(first_dir)
RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, .proc/rotate_react)
if(cleanable)
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_react)
if(description)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examine)
/datum/component/decal/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE))
/datum/component/decal/Destroy()
remove()
return ..()
/datum/component/decal/PreTransfer()
remove()
/datum/component/decal/PostTransfer()
remove()
apply()
/datum/component/decal/proc/generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha)
if(!_icon || !_icon_state)
return FALSE
// It has to be made from an image or dir breaks because of a byond bug
var/temp_image = image(_icon, null, _icon_state, _layer, _dir)
pic = new(temp_image)
pic.color = _color
pic.alpha = _alpha
return TRUE
/datum/component/decal/proc/apply(atom/thing)
var/atom/master = thing || parent
master.add_overlay(pic, TRUE)
if(isitem(master))
addtimer(CALLBACK(master, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
/datum/component/decal/proc/remove(atom/thing)
var/atom/master = thing || parent
master.cut_overlay(pic, TRUE)
if(isitem(master))
addtimer(CALLBACK(master, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
/datum/component/decal/proc/rotate_react(datum/source, old_dir, new_dir)
if(old_dir == new_dir)
return
remove()
pic.dir = turn(pic.dir, dir2angle(old_dir) - dir2angle(new_dir))
apply()
/datum/component/decal/proc/clean_react(datum/source, strength)
if(strength >= cleanable)
qdel(src)
/datum/component/decal/proc/examine(datum/source, mob/user)
to_chat(user, description)
+1 -1
View File
@@ -624,7 +624,7 @@ var/record_id_num = 1001
clothes_s = new /icon('icons/mob/uniform.dmi', "syndicate_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/hands.dmi', "swat_gl"), ICON_UNDERLAY)
else if(H.mind.assigned_role in get_all_centcom_jobs())
else if(H.mind && H.mind.assigned_role in get_all_centcom_jobs())
clothes_s = new /icon('icons/mob/uniform.dmi', "officer_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "laceups"), ICON_UNDERLAY)
else
+1 -1
View File
@@ -5,8 +5,8 @@
var/list/comp_lookup
var/list/signal_procs
var/signal_enabled = FALSE
var/datum_flags = NONE
var/var_edited = FALSE //Warranty void if seal is broken
var/tmp/unique_datum_id = null
#ifdef TESTING
+5 -15
View File
@@ -3,8 +3,8 @@
/datum/proc/can_vv_get(var_name)
return TRUE
/client/proc/can_vv_get(var_name)
return TRUE
// /client/proc/can_vv_get(var_name)
// return TRUE
/datum/proc/vv_edit_var(var_name, var_value) //called whenever a var is edited
switch(var_name)
@@ -18,7 +18,7 @@
. = TRUE
/client/proc/vv_edit_var(var_name, var_value) //called whenever a var is edited
/client/vv_edit_var(var_name, var_value) //called whenever a var is edited
switch(var_name)
if("vars")
return FALSE
@@ -37,7 +37,7 @@
return debug_variable(var_name, list(), 0, src)
return debug_variable(var_name, vars[var_name], 0, src)
/client/proc/vv_get_var(var_name)
/client/vv_get_var(var_name)
switch(var_name)
if("vars")
return debug_variable(var_name, list(), 0, src)
@@ -57,7 +57,7 @@
.["Delete"] = "?_src_=vars;delete=[UID()]"
. += "---"
/client/proc/vv_get_dropdown()
/client/vv_get_dropdown()
. = list()
. += "---"
.["Call Proc"] = "?_src_=vars;proc_call=[UID()]"
@@ -1004,16 +1004,6 @@
return
holder.Topic(href, list("makeai"=href_list["makeai"]))
else if(href_list["makemask"])
if(!check_rights(R_SPAWN)) return
var/mob/currentMob = locateUID(href_list["makemask"])
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
if(!currentMob)
to_chat(usr, "Mob doesn't exist anymore")
return
holder.Topic(href, list("makemask"=href_list["makemask"]))
else if(href_list["setspecies"])
if(!check_rights(R_SPAWN)) return
+6
View File
@@ -92,6 +92,12 @@
bypasses_immunity = TRUE
virus_heal_resistant = TRUE
/datum/disease/critical/heart_failure/has_cure()
if(affected_mob.has_status_effect(STATUS_EFFECT_EXERCISED))
return TRUE
return ..()
/datum/disease/critical/heart_failure/stage_act()
if(..())
switch(stage)
+17
View File
@@ -203,6 +203,10 @@ What are the archived variables for?
/datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample)
//Copies variables from sample
/datum/gas_mixture/proc/copy_from_turf(turf/model)
//Copies all gas info from the turf into the gas list along with temperature
//Returns: 1 if we are mutable, 0 otherwise
/datum/gas_mixture/proc/share(datum/gas_mixture/sharer)
//Performs air sharing calculations between two gas_mixtures assuming only 1 boundary length
//Return: amount of gas exchanged (+ if sharer received)
@@ -343,6 +347,19 @@ What are the archived variables for?
return 1
/datum/gas_mixture/copy_from_turf(turf/model)
oxygen = model.oxygen
carbon_dioxide = model.carbon_dioxide
nitrogen = model.nitrogen
toxins = model.toxins
//acounts for changes in temperature
var/turf/model_parent = model.parent_type
if(model.temperature != initial(model.temperature) || model.temperature != initial(model_parent.temperature))
temperature = model.temperature
return 1
/datum/gas_mixture/check_turf(turf/model, atmos_adjacent_turfs = 4)
var/delta_oxygen = (oxygen_archived - model.oxygen)/(atmos_adjacent_turfs+1)
var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/(atmos_adjacent_turfs+1)
-27
View File
@@ -1,27 +0,0 @@
/datum/hotkey_mode
var/name
var/macro_hotkeys_inactive
var/macro_hotkeys_active
var/mob/my_mob
/datum/hotkey_mode/New(mob)
my_mob = mob
/datum/hotkey_mode/proc/set_winset_values()
winset(my_mob, null, "mainwindow.macro=[macro_hotkeys_inactive] hotkey_toggle.is-checked=false input.focus=true input.background-color=#d3b5b5")
winset(my_mob, null, "hotkey_toggle.command=\".winset \\\"mainwindow.macro != [macro_hotkeys_inactive] ? mainwindow.macro=[macro_hotkeys_inactive] hotkey_toggle.is-checked=false input.focus=true input.background-color=#d3b5b5 : mainwindow.macro=[macro_hotkeys_active] hotkey_toggle.is-checked=true mapwindow.map.focus=true input.background-color=#f0f0f0\\\"\"")
/datum/hotkey_mode/qwerty
name = "QWERTY"
macro_hotkeys_inactive = "macro"
macro_hotkeys_active = "hotkeymode"
/datum/hotkey_mode/azerty
name = "AZERTY"
macro_hotkeys_inactive = "azertymacro"
macro_hotkeys_active = "azertyhotkeymode"
/datum/hotkey_mode/cyborg
name = "Cyborg"
macro_hotkeys_inactive = "borgmacro"
macro_hotkeys_active = "borghotkeymode"
+175
View File
@@ -0,0 +1,175 @@
/proc/input_async(mob/user=usr, prompt, list/choices)
var/datum/async_input/A = new(choices, prompt, , user)
A.show()
return A
/proc/input_ranked_async(mob/user=usr, prompt="Order by greatest to least preference", list/choices)
var/datum/async_input/ranked/A = new(choices, prompt, "ranked_input", user)
A.show()
return A
/proc/input_autocomplete_async(mob/user=usr, prompt="Enter text: ", list/choices)
var/datum/async_input/autocomplete/A = new(choices, prompt, "ac_input", user)
A.show()
return A
/datum/async_input
var/datum/browser/popup
// If associative list, key will be used for display, but the final result will be the value
var/list/choices
var/datum/callback/onCloseCb
var/flash = TRUE
var/immediate_submit = FALSE
var/prompt
var/result = null
var/style = "text-align: center;"
var/mob/user
var/window_id
var/height = 200
var/width = 400
/datum/async_input/New(list/new_choices, new_prompt="Pick an option:", new_window_id="async_input", mob/new_user=usr)
choices = new_choices
prompt = new_prompt
window_id = new_window_id
user = new_user
popup = new(user, window_id, , width, height, src)
/datum/async_input/proc/close()
if(popup)
popup.close()
if(result && choices[result])
result = choices[result]
if(onCloseCb)
onCloseCb.Invoke(result)
return result
// Callback function should take the result as the last argument
/datum/async_input/proc/on_close(var/datum/callback/cb)
onCloseCb = cb
/datum/async_input/proc/show()
popup.set_content(create_ui())
if(flash && result == null)
window_flash(user.client)
popup.open()
/datum/async_input/proc/create_ui()
var/dat = "<div style=\"[style]\">"
dat += render_prompt()
dat += render_choices()
dat += "<br>"
dat += "<br>"
dat += render_buttons()
dat += "</div>"
return dat
/datum/async_input/proc/render_prompt()
return "<h2>[prompt]</h2>"
/datum/async_input/proc/render_choices()
var/dat = " "
for(var/choice in choices)
dat += button(choice, "choice=[choice]", choice == result)
dat += " "
return dat
/datum/async_input/proc/render_buttons()
return button("Submit", "submit=1", , result == null && !immediate_submit)
/datum/async_input/proc/button(label, topic, on=FALSE, disabled=FALSE, id="")
var/class = ""
if(on)
class = "linkOn"
if(disabled)
class = "linkOff"
topic = ""
return "<a class=\"[class]\" id='[id]' href='?src=[UID()];[topic]'>[label]</a>"
/datum/async_input/Topic(href, href_list)
if(href_list["submit"] || href_list["close"])
close()
return
if(href_list["choice"])
result = href_list["choice"]
show()
return
/datum/async_input/ranked
height = 400
immediate_submit = TRUE
/datum/async_input/ranked/render_choices()
var/dat = "<div>"
dat += "<table style='margin: auto; text-align: left;'>"
for(var/i = 1, i <= choices.len, i++)
var/choice = choices[i]
dat += "<tr>"
dat += "<td>[button("+", i != 1 ? "upvote=[i]" : "", , i == 1)]</td>"
dat += "<td>[button("-", i != choices.len ? "downvote=[i]" : "", , i == choices.len)]</td>"
dat += "<td>[i]. [choice]</td>"
dat += "</tr>"
dat += "</table>"
dat += "</div>"
return dat
/datum/async_input/ranked/Topic(href, href_list)
if(!href_list["close"])
// Mark that user interacted with interface
result = choices
if(href_list["upvote"])
var/index = text2num(href_list["upvote"])
choices.Swap(index, index - 1)
show()
return
if(href_list["downvote"])
var/index = text2num(href_list["downvote"])
choices.Swap(index, index + 1)
show()
return
..()
/datum/async_input/autocomplete
immediate_submit = TRUE
height = 150
/datum/async_input/autocomplete/New()
..()
popup.add_script("autocomplete.js", 'html/browser/autocomplete.js')
for(var/i=1, i <= choices.len, i++)
var/C = choices[choices[i]]
choices[i] = url_encode(choices[i], TRUE)
choices[choices[i]] = C
/datum/async_input/autocomplete/render_prompt()
return "<label for='input'>[prompt]</label>"
/datum/async_input/autocomplete/render_choices()
var/dat = "<input list='choices' id='input' name='choices' oninput='updateTopic()' />"
dat += "<datalist id='choices'>"
for(var/choice in choices)
dat += "<option value='[choice]'>"
dat += "</datalist>"
return dat
/datum/async_input/autocomplete/render_buttons()
var/dat = button("Submit", "", , result == null && !immediate_submit, "submit-button")
dat += button("Cancel", "close=1")
return dat
/datum/async_input/autocomplete/Topic(href, href_list)
if(href_list["submit"])
// Entering an invalid choice is the same as canceling
if(href_list["submit"] in choices)
result = href_list["submit"]
else if(url_encode(href_list["submit"], TRUE) in choices)
result = url_encode(href_list["submit"], TRUE)
close()
return
..()
+1 -3
View File
@@ -123,7 +123,7 @@
banned = generateMapList("config/spaceRuinBlacklist.txt")
else
banned = generateMapList("config/example/spaceRuinBlacklist.txt")
//banned += generateMapList("config/lavaRuinBlacklist.txt")
banned += generateMapList("config/lavaRuinBlacklist.txt")
for(var/item in subtypesof(/datum/map_template/ruin))
var/datum/map_template/ruin/ruin_type = item
@@ -138,10 +138,8 @@
map_templates[R.name] = R
ruins_templates[R.name] = R
/*
if(istype(R, /datum/map_template/ruin/lavaland))
lava_ruins_templates[R.name] = R
*/
if(istype(R, /datum/map_template/ruin/space))
space_ruins_templates[R.name] = R
+9 -2
View File
@@ -824,6 +824,11 @@
to_chat(current, "<span class='cultitalic'>Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve [SSticker.cultdat.entity_title2] above all else. Bring It back.</span>")
log_admin("[key_name(usr)] has culted [key_name(current)]")
message_admins("[key_name_admin(usr)] has culted [key_name_admin(current)]")
if(!summon_spots.len)
while(summon_spots.len < SUMMON_POSSIBILITIES)
var/area/summon = pick(return_sorted_areas() - summon_spots)
if(summon && is_station_level(summon.z) && summon.valid_territory)
summon_spots += summon
if("tome")
var/mob/living/carbon/human/H = current
if(istype(H))
@@ -900,9 +905,11 @@
if(src in SSticker.mode.changelings)
SSticker.mode.changelings -= src
special_role = null
current.remove_changeling_powers()
if(changeling)
current.remove_changeling_powers()
qdel(changeling)
changeling = null
SSticker.mode.update_change_icons_removed(src)
if(changeling) qdel(changeling)
to_chat(current, "<FONT color='red' size = 3><B>You grow weak and lose your powers! You are no longer a changeling and are stuck in your current form!</B></FONT>")
log_admin("[key_name(usr)] has de-changelinged [key_name(current)]")
message_admins("[key_name_admin(usr)] has de-changelinged [key_name_admin(current)]")
+6 -2
View File
@@ -7,8 +7,12 @@
wooden container filled with 18th century coinage in the middle of a \
lavawracked hellscape? It is clearly a mystery."
var/cost = null
var/allow_duplicates = FALSE //A bit boring, don't you think? You can always explicitly allow it on a ruin definition
var/unpickable = FALSE //If TRUE these won't be placed automatically (can still be forced or loaded with another ruin)
var/always_place = FALSE //Will skip the whole weighting process and just plop this down, ideally you want the ruins of this kind to have no cost.
var/placement_weight = 1 //How often should this ruin appear
var/cost = 0 //Cost in ruin budget placement system
var/allow_duplicates = TRUE
var/list/never_spawn_with = null //If this ruin is spawned these will not eg list(/datum/map_template/ruin/base_alternate)
var/prefix = null
var/suffix = null
+87
View File
@@ -0,0 +1,87 @@
/datum/map_template/ruin/lavaland
prefix = "_maps/map_files/RandomRuins/LavaRuins/"
/datum/map_template/ruin/lavaland/biodome
cost = 5
allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/biodome/beach
name = "Biodome Beach"
id = "biodome-beach"
description = "Seemingly plucked from a tropical destination, this beach is calm and cool, with the salty waves roaring softly in the background. \
Comes with a rustic wooden bar and suicidal bartender."
suffix = "lavaland_biodome_beach.dmm"
/datum/map_template/ruin/lavaland/seed_vault
name = "Seed Vault"
id = "seed-vault"
description = "The creators of these vaults were a highly advanced and benevolent race, and launched many into the stars, hoping to aid fledgling civilizations. \
However, all the inhabitants seem to do is grow drugs and guns."
suffix = "lavaland_surface_seed_vault.dmm"
cost = 10
allow_duplicates = FALSE
datum/map_template/ruin/lavaland/ash_walker
name = "Ash Walker Nest"
id = "ash-walker"
description = "A race of unbreathing lizards live here, that run faster than a human can, worship a broken dead city, and are capable of reproducing by something involving tentacles? \
Probably best to stay clear."
suffix = "lavaland_surface_ash_walker1.dmm"
cost = 20
allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/syndicate_base
name = "Syndicate Lava Base"
id = "lava-base"
description = "A secret base researching illegal bioweapons, it is closely guarded by an elite team of syndicate agents."
suffix = "lavaland_surface_syndicate_base1.dmm"
cost = 20
allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/animal_hospital
name = "Animal Hospital"
id = "animal-hospital"
description = "Rats with cancer do not live very long. And the ones that wake up from cryostasis seem to commit suicide out of boredom."
cost = 5
suffix = "lavaland_surface_animal_hospital.dmm"
allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/hierophant
name = "Hierophant's Arena"
id = "hierophant"
description = "A strange, square chunk of metal of massive size. Inside awaits only death and many, many squares."
suffix = "lavaland_surface_hierophant.dmm"
allow_duplicates = FALSE
always_place = TRUE
/datum/map_template/ruin/lavaland/blood_drunk_miner
name = "Blood-Drunk Miner"
id = "blooddrunk"
description = "A strange arrangement of stone tiles and an insane, beastly miner contemplating them."
suffix = "lavaland_surface_blooddrunk1.dmm"
cost = 0
allow_duplicates = FALSE //will only spawn one variant of the ruin
/datum/map_template/ruin/lavaland/blood_drunk_miner/guidance
name = "Blood-Drunk Miner (Guidance)"
suffix = "lavaland_surface_blooddrunk2.dmm"
/datum/map_template/ruin/lavaland/blood_drunk_miner/hunter
name = "Blood-Drunk Miner (Hunter)"
suffix = "lavaland_surface_blooddrunk3.dmm"
/datum/map_template/ruin/lavaland/hermit
name = "Makeshift Shelter"
id = "hermitcave"
description = "A place of shelter for a lone hermit, scraping by to live another day."
suffix = "lavaland_surface_hermit.dmm"
allow_duplicates = FALSE
cost = 10
/datum/map_template/ruin/lavaland/swarmer_boss
name = "Crashed Shuttle"
id = "swarmerboss"
description = "A Syndicate shuttle had an unfortunate stowaway..."
suffix = "lavaland_surface_swarmer_crash.dmm"
allow_duplicates = FALSE
cost = 20
+19 -7
View File
@@ -62,6 +62,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
var/charge_type = "recharge" //can be recharge or charges, see charge_max and charge_counter descriptions; can also be based on the holder's vars now, use "holder_var" for that
var/charge_max = 100 //recharge time in deciseconds if charge_type = "recharge" or starting charges if charge_type = "charges"
var/starts_charged = TRUE //Does this spell start ready to go?
var/charge_counter = 0 //can only cast spells if it equals recharge, ++ each decisecond if charge_type = "recharge" or -- each cast if charge_type = "charges"
var/still_recharging_msg = "<span class='notice'>The spell is still recharging.</span>"
@@ -167,6 +168,8 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
if("holdervar")
adjust_var(user, holder_var_type, holder_var_amount)
if(action)
action.UpdateButtonIcon()
return 1
/obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount
@@ -193,9 +196,11 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
/obj/effect/proc_holder/spell/New()
..()
action = new(src)
still_recharging_msg = "<span class='notice'>[name] is still recharging.</span>"
charge_counter = charge_max
if(starts_charged)
charge_counter = charge_max
else
start_recharge()
/obj/effect/proc_holder/spell/Destroy()
QDEL_NULL(action)
@@ -212,9 +217,14 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
/obj/effect/proc_holder/spell/proc/start_recharge()
if(action)
action.UpdateButtonIcon()
while(charge_counter < charge_max)
sleep(1)
charge_counter++
START_PROCESSING(SSfastprocess, src)
/obj/effect/proc_holder/spell/process()
charge_counter += 2
if(charge_counter < charge_max)
return
STOP_PROCESSING(SSfastprocess, src)
charge_counter = charge_max
if(action)
action.UpdateButtonIcon()
@@ -235,6 +245,8 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
else
cast(targets, user = user)
after_cast(targets)
if(action)
action.UpdateButtonIcon()
/obj/effect/proc_holder/spell/proc/before_cast(list/targets)
if(overlay)
@@ -291,8 +303,8 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
charge_counter++
if("holdervar")
adjust_var(user, holder_var_type, -holder_var_amount)
return
if(action)
action.UpdateButtonIcon()
/obj/effect/proc_holder/spell/proc/updateButtonIcon()
if(action)
+27
View File
@@ -0,0 +1,27 @@
/obj/effect/proc_holder/spell/targeted/night_vision
name = "Toggle Nightvision"
desc = "Toggle your nightvision mode."
charge_max = 10
clothes_req = 0
message = "<span class='notice'>You toggle your night vision!</span>"
range = -1
include_user = 1
/obj/effect/proc_holder/spell/targeted/night_vision/cast(list/targets, mob/user = usr)
for(var/mob/living/target in targets)
switch(target.lighting_alpha)
if (LIGHTING_PLANE_ALPHA_VISIBLE)
target.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
name = "Toggle Nightvision \[More]"
if (LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE)
target.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
name = "Toggle Nightvision \[Full]"
if (LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE)
target.lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
name = "Toggle Nightvision \[OFF]"
else
target.lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
name = "Toggle Nightvision \[ON]"
target.update_sight()
+5 -8
View File
@@ -1,12 +1,13 @@
// Not TECHNICALLY a datum, but this should never be instantiated
// outside of the stat panel
// Clickable stat() button
/obj/effect/statclick
var/target
/obj/effect/statclick/New(ntarget, text)
target = ntarget
INITIALIZE_IMMEDIATE(/obj/effect/statclick)
/obj/effect/statclick/Initialize(mapload, text, target)
. = ..()
name = text
src.target = target
/obj/effect/statclick/proc/update(text)
name = text
@@ -19,10 +20,6 @@
if(!is_admin(usr) || !target)
return
if(!class)
if(istype(target, /datum/controller/process))
class = "process"
else if(istype(target, /datum/controller/processScheduler))
class = "scheduler"
if(istype(target, /datum/controller/subsystem))
class = "subsystem"
else if(istype(target, /datum/controller))
+15 -1
View File
@@ -38,4 +38,18 @@
/datum/status_effect/void_price/tick()
playsound(owner, 'sound/weapons/bite.ogg', 50, 1)
owner.adjustBruteLoss(3)
owner.adjustBruteLoss(3)
/datum/status_effect/exercised
id = "Exercised"
duration = 1200
alert_type = null
/datum/status_effect/exercised/on_creation(mob/living/new_owner, ...)
. = ..()
STOP_PROCESSING(SSfastprocess, src)
START_PROCESSING(SSprocessing, src) //this lasts 20 minutes, so SSfastprocess isn't needed.
/datum/status_effect/exercised/Destroy()
. = ..()
STOP_PROCESSING(SSprocessing, src)
+73 -1
View File
@@ -7,4 +7,76 @@
/datum/status_effect/cultghost/tick()
if(owner.reagents)
owner.reagents.del_reagent("holywater") //can't be deconverted
owner.reagents.del_reagent("holywater") //can't be deconverted
/datum/status_effect/saw_bleed
id = "saw_bleed"
duration = -1 //removed under specific conditions
tick_interval = 6
alert_type = null
var/mutable_appearance/bleed_overlay
var/mutable_appearance/bleed_underlay
var/bleed_amount = 3
var/bleed_buildup = 3
var/delay_before_decay = 5
var/bleed_damage = 200
var/needs_to_bleed = FALSE
/datum/status_effect/saw_bleed/Destroy()
if(owner)
owner.cut_overlay(bleed_overlay)
owner.underlays -= bleed_underlay
QDEL_NULL(bleed_overlay)
return ..()
/datum/status_effect/saw_bleed/on_apply()
if(owner.stat == DEAD)
return FALSE
bleed_overlay = mutable_appearance('icons/effects/bleed.dmi', "bleed[bleed_amount]")
bleed_underlay = mutable_appearance('icons/effects/bleed.dmi', "bleed[bleed_amount]")
var/icon/I = icon(owner.icon, owner.icon_state, owner.dir)
var/icon_height = I.Height()
bleed_overlay.pixel_x = -owner.pixel_x
bleed_overlay.pixel_y = FLOOR(icon_height * 0.25, 1)
bleed_overlay.transform = matrix() * (icon_height/world.icon_size) //scale the bleed overlay's size based on the target's icon size
bleed_underlay.pixel_x = -owner.pixel_x
bleed_underlay.transform = matrix() * (icon_height/world.icon_size) * 3
bleed_underlay.alpha = 40
owner.add_overlay(bleed_overlay)
owner.underlays += bleed_underlay
return ..()
/datum/status_effect/saw_bleed/tick()
if(owner.stat == DEAD)
qdel(src)
else
add_bleed(-1)
/datum/status_effect/saw_bleed/proc/add_bleed(amount)
owner.cut_overlay(bleed_overlay)
owner.underlays -= bleed_underlay
bleed_amount += amount
if(bleed_amount)
if(bleed_amount >= 10)
needs_to_bleed = TRUE
qdel(src)
else
if(amount > 0)
tick_interval += delay_before_decay
bleed_overlay.icon_state = "bleed[bleed_amount]"
bleed_underlay.icon_state = "bleed[bleed_amount]"
owner.add_overlay(bleed_overlay)
owner.underlays += bleed_underlay
else
qdel(src)
/datum/status_effect/saw_bleed/on_remove()
if(needs_to_bleed)
var/turf/T = get_turf(owner)
new /obj/effect/temp_visual/bleed/explode(T)
for(var/d in alldirs)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(T, d)
playsound(T, "desceration", 200, 1, -1)
owner.adjustBruteLoss(bleed_damage)
else
new /obj/effect/temp_visual/bleed(get_turf(owner))
+12 -2
View File
@@ -1108,7 +1108,8 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
name = "Cat Crate"
cost = 50 //Cats are worth as much as corgis.
containertype = /obj/structure/closet/critter/cat
contains = list(/obj/item/clothing/accessory/petcollar)
contains = list(/obj/item/clothing/accessory/petcollar,
/obj/item/toy/cattoy)
containername = "cat crate"
/datum/supply_packs/organic/pug
@@ -1211,7 +1212,8 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
/obj/item/honey_frame,
/obj/item/queen_bee/bought,
/obj/item/clothing/head/beekeeper_head,
/obj/item/clothing/suit/beekeeper_suit)
/obj/item/clothing/suit/beekeeper_suit,
/obj/item/melee/flyswatter)
cost = 15
containername = "beekeeping starter kit"
@@ -1360,6 +1362,14 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
cost = 40
containername = "religious supplies crate"
/datum/supply_packs/misc/minerkit
name = "Shaft Miner Starter Kit"
cost = 30
access = access_qm
contains = list(/obj/item/storage/backpack/duffel/mining_conscript/noid)
containertype = /obj/structure/closet/crate/secure
containername = "shaft miner starter kit"
///////////// Paper Work
+3 -2
View File
@@ -1448,7 +1448,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/device_tools/medgun
name = "Medbeam Gun"
desc = "Medical Beam Gun, useful in prolonged firefights."
desc = "Medical Beam Gun, useful in prolonged firefights. DO NOT CROSS THE BEAMS. Crossing beams with another medbeam or attaching two beams to one target will have explosive consequences."
item = /obj/item/gun/medbeam
reference = "MBG"
cost = 15
@@ -1635,7 +1635,8 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
reference = "CIB"
item = /obj/item/storage/box/cyber_implants/bundle
cost = 40
gamemodes = list(/datum/game_mode/nuclear)
/datum/uplink_item/bundles_TC/medical
name = "Medical Bundle"
desc = "The support specialist: Aid your fellow operatives with this medical bundle. Contains a tactical medkit, \
+2
View File
@@ -107,6 +107,8 @@
/datum/weather/proc/can_weather_act(mob/living/L) //Can this weather impact a mob?
var/turf/mob_turf = get_turf(L)
if(!istype(L))
return
if(mob_turf && !(mob_turf.z in impacted_z_levels))
return
if(immunity_type in L.weather_immunities)
@@ -16,12 +16,12 @@
end_duration = 300
end_overlay = "light_ash"
area_type = /area/mine/dangerous // /area/lavaland/surface/outdoors
area_type = /area/lavaland/surface/outdoors
target_trait = ORE_LEVEL
immunity_type = "ash"
// probability = 90
probability = 90
barometer_predictable = TRUE
@@ -105,4 +105,4 @@
aesthetic = TRUE
// probability = 10
probability = 10