# Conflicts:
#	code/modules/ninja/suit/ninjaDrainAct.dm
This commit is contained in:
zerothebigboy
2021-05-02 22:47:39 -04:00
448 changed files with 310031 additions and 306315 deletions
+1 -1
View File
@@ -428,7 +428,7 @@
output += "<option value='[j]'>[j]</option>"
for(var/j in GLOB.nonhuman_positions)
output += "<option value='[j]'>[j]</option>"
for(var/j in list(ROLE_TRAITOR, ROLE_CHANGELING, ROLE_OPERATIVE, ROLE_REV, ROLE_CULTIST, ROLE_WIZARD))
for(var/j in list(ROLE_TRAITOR, ROLE_CHANGELING, ROLE_OPERATIVE, ROLE_REV, ROLE_CULTIST, ROLE_WIZARD, ROLE_HERETIC))
output += "<option value='[j]'>[j]</option>"
output += "</select></td></tr></table>"
output += "<b>Reason:<br></b><textarea name='dbbanreason' cols='50'></textarea><br>"
+2 -2
View File
@@ -93,7 +93,7 @@ GLOBAL_PROTECT(admin_verbs_ban)
GLOBAL_LIST_INIT(admin_verbs_sounds, list(/client/proc/play_local_sound, /client/proc/play_sound, /client/proc/manual_play_web_sound, /client/proc/set_round_end_sound))
GLOBAL_PROTECT(admin_verbs_sounds)
GLOBAL_LIST_INIT(admin_verbs_fun, list(
/client/proc/cmd_admin_dress,
/client/proc/cmd_select_equipment,
/client/proc/cmd_admin_gib_self,
/client/proc/drop_bomb,
/client/proc/set_dynex_scale,
@@ -232,7 +232,7 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
/client/proc/play_local_sound,
/client/proc/play_sound,
/client/proc/set_round_end_sound,
/client/proc/cmd_admin_dress,
/client/proc/cmd_select_equipment,
/client/proc/cmd_admin_gib_self,
/client/proc/drop_bomb,
/client/proc/drop_dynex_bomb,
+4
View File
@@ -101,6 +101,10 @@ GLOBAL_VAR(antag_prototypes)
out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]<br>"
out += "Assigned role: [assigned_role]. <a href='?src=[REF(src)];role_edit=1'>Edit</a><br>"
out += "Faction and special role: <b><font color='red'>[special_role]</font></b><br>"
var/datum/component/activity/activity = current.GetComponent(/datum/component/activity)
if(activity)
out += "Activity level: [activity.activity_level]<br>"
out += "Hasn't changed areas in approximately [activity.not_moved_counter] seconds"
var/special_statuses = get_special_statuses()
if(length(special_statuses))
+196
View File
@@ -0,0 +1,196 @@
/client/proc/open_outfit_editor(datum/outfit/target)
var/datum/outfit_editor/ui = new(usr, target)
ui.ui_interact(usr)
#define OUTFIT_EDITOR_NAME "Outfit-O-Tron 9000"
/datum/outfit_editor
var/client/owner
var/dummy_key
var/datum/outfit/drip
/datum/outfit_editor/New(user, datum/outfit/target)
owner = CLIENT_FROM_VAR(user)
if(ispath(target))
drip = new /datum/outfit
drip.copy_from(new target)
else if(istype(target))
drip = target
else
drip = new /datum/outfit
drip.name = "New Outfit"
/datum/outfit_editor/ui_state(mob/user)
return GLOB.admin_state
/datum/outfit_editor/ui_status(mob/user, datum/ui_state/state)
if(QDELETED(drip))
return UI_CLOSE
return ..()
/datum/outfit_editor/ui_close(mob/user)
clear_human_dummy(dummy_key)
qdel(src)
/datum/outfit_editor/proc/init_dummy()
dummy_key = "outfit_editor_[owner]"
generate_dummy_lookalike(dummy_key, owner.mob)
unset_busy_human_dummy(dummy_key)
/datum/outfit_editor/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "OutfitEditor", OUTFIT_EDITOR_NAME)
ui.open()
ui.set_autoupdate(FALSE)
/datum/outfit_editor/proc/entry(data)
if(ispath(data, /obj/item))
var/obj/item/item = data
return list(
"path" = item,
"name" = initial(item.name),
"desc" = initial(item.desc),
// at this point initializing the item is probably faster tbh
"sprite" = icon2base64(icon(initial(item.icon), initial(item.icon_state))),
)
return data
/datum/outfit_editor/proc/serialize_outfit()
var/list/outfit_slots = drip.get_json_data()
. = list()
for(var/key in outfit_slots)
var/val = outfit_slots[key]
. += list("[key]" = entry(val))
/datum/outfit_editor/ui_data(mob/user)
var/list/data = list()
data["outfit"] = serialize_outfit()
data["saveable"] = !GLOB.custom_outfits.Find(drip)
if(!dummy_key)
init_dummy()
var/icon/dummysprite = get_flat_human_icon(null,
dummy_key = dummy_key,
showDirs = list(SOUTH),
outfit_override = drip)
data["dummy64"] = icon2base64(dummysprite)
return data
/datum/outfit_editor/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
if(..())
return
. = TRUE
var/slot = params["slot"]
switch(action)
if("click")
choose_item(slot)
if("ctrlClick")
choose_any_item(slot)
if("clear")
if(drip.vars.Find(slot))
drip.vars[slot] = null
if("rename")
var/newname = stripped_input(owner, "What do you want to name this outfit?", OUTFIT_EDITOR_NAME)
if(newname)
drip.name = newname
if("save")
GLOB.custom_outfits |= drip
SStgui.update_user_uis(owner.mob)
if("delete")
GLOB.custom_outfits -= drip
SStgui.update_user_uis(owner.mob)
if("vv")
owner.debug_variables(drip)
/datum/outfit_editor/proc/set_item(slot, obj/item/choice)
if(!choice)
return
if(!ispath(choice))
alert(owner, "Invalid item", OUTFIT_EDITOR_NAME, "oh no")
return
if(initial(choice.icon_state) == null) //hacky check copied from experimentor code
var/msg = "Warning: This item's icon_state is null, indicating it is very probably not actually a usable item."
if(alert(owner, msg, OUTFIT_EDITOR_NAME, "Use it anyway", "Cancel") != "Use it anyway")
return
if(drip.vars.Find(slot))
drip.vars[slot] = choice
/datum/outfit_editor/proc/choose_any_item(slot)
var/obj/item/choice = pick_closest_path(FALSE)
if(!choice)
return
set_item(slot, choice)
//this proc will try to give a good selection of items that the user can choose from
//it does *not* give a selection of all items that can fit in a slot because lag;
//most notably the hand and pocket slots because they accept pretty much anything
//also stuff that fits in the belt and back slots are scattered pretty much all over the place
/datum/outfit_editor/proc/choose_item(slot)
var/list/options = list()
switch(slot)
if("head")
options = typesof(/obj/item/clothing/head)
if("glasses")
options = typesof(/obj/item/clothing/glasses)
if("ears")
options = typesof(/obj/item/radio/headset)
if("neck")
options = typesof(/obj/item/clothing/neck)
if("mask")
options = typesof(/obj/item/clothing/mask)
if("uniform")
options = typesof(/obj/item/clothing/under)
if("suit")
options = typesof(/obj/item/clothing/suit)
if("gloves")
options = typesof(/obj/item/clothing/gloves)
if("suit_store")
var/obj/item/clothing/suit/suit = drip.suit
if(suit)
suit = new suit //initial() doesn't like lists
options = suit.allowed
if(!options.len) //nothing will happen, but don't let the user think it's broken
to_chat(owner, "<span class='warning'>No options available for the current suit.</span>")
if("belt")
options = typesof(/obj/item/storage/belt)
if("id")
options = typesof(/obj/item/card/id)
if("l_hand")
choose_any_item(slot)
if("back")
options = typesof(/obj/item/storage/backpack)
if("r_hand")
choose_any_item(slot)
if("l_pocket")
choose_any_item(slot)
if("shoes")
options = typesof(/obj/item/clothing/shoes)
if("r_pocket")
choose_any_item(slot)
if(length(options))
set_item(slot, tgui_input_list(owner, "Choose an item", OUTFIT_EDITOR_NAME, options))
#undef OUTFIT_EDITOR_NAME
+73
View File
@@ -0,0 +1,73 @@
/client/proc/outfit_manager()
set category = "Debug"
set name = "Outfit Manager"
if(!check_rights(R_DEBUG))
return
var/datum/outfit_manager/ui = new(usr)
ui.ui_interact(usr)
/datum/outfit_manager
var/client/owner
/datum/outfit_manager/New(user)
owner = CLIENT_FROM_VAR(user)
/datum/outfit_manager/ui_state(mob/user)
return GLOB.admin_state
/datum/outfit_manager/ui_close(mob/user)
qdel(src)
/datum/outfit_manager/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "OutfitManager")
ui.open()
/datum/outfit_manager/proc/entry(datum/outfit/outfit)
var/vv = FALSE
var/datum/outfit/varedit/varoutfit = outfit
if(istype(varoutfit))
vv = length(varoutfit.vv_values)
return list(
"name" = "[outfit.name] [vv ? "(VV)" : ""]",
"ref" = REF(outfit),
)
/datum/outfit_manager/ui_data(mob/user)
var/list/data = list()
var/list/outfits = list()
for(var/datum/outfit/custom_outfit in GLOB.custom_outfits)
outfits += list(entry(custom_outfit))
data["outfits"] = outfits
return data
/datum/outfit_manager/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
if(..())
return
. = TRUE
switch(action)
if("new")
owner.open_outfit_editor(new /datum/outfit)
if("load")
owner.holder.load_outfit(owner.mob)
if("copy")
var/datum/outfit/outfit = tgui_input_list(owner, "Pick an outfit to copy from", "Outfit Manager", subtypesof(/datum/outfit))
if(ispath(outfit))
owner.open_outfit_editor(new outfit)
var/datum/outfit/target_outfit = locate(params["outfit"])
if(!istype(target_outfit))
return
switch(action) //wow we're switching through action again this is horrible optimization smh
if("edit")
owner.open_outfit_editor(target_outfit)
if("save")
owner.holder.save_outfit(owner.mob, target_outfit)
if("delete")
owner.holder.delete_outfit(owner.mob, target_outfit)
+32
View File
@@ -0,0 +1,32 @@
GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
/datum/admins/proc/save_outfit(mob/admin, datum/outfit/O)
O.save_to_file(admin)
SStgui.update_user_uis(admin)
/datum/admins/proc/delete_outfit(mob/admin, datum/outfit/O)
GLOB.custom_outfits -= O
qdel(O)
to_chat(admin,"<span class='notice'>Outfit deleted.</span>")
SStgui.update_user_uis(admin)
/datum/admins/proc/load_outfit(mob/admin)
var/outfit_file = input("Pick outfit json file:", "File") as null|file
if(!outfit_file)
return
var/filedata = file2text(outfit_file)
var/json = json_decode(filedata)
if(!json)
to_chat(admin,"<span class='warning'>JSON decode error.</span>")
return
var/otype = text2path(json["outfit_type"])
if(!ispath(otype,/datum/outfit))
to_chat(admin,"<span class='warning'>Malformed/Outdated file.</span>")
return
var/datum/outfit/O = new otype
if(!O.load_from(json))
to_chat(admin,"<span class='warning'>Malformed/Outdated file.</span>")
return
GLOB.custom_outfits += O
SStgui.update_user_uis(admin)
+6
View File
@@ -870,6 +870,12 @@
else
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=changeling;jobban4=[REF(M)]'>Changeling</a></td>"
//Heretic
if(jobban_isbanned(M, ROLE_HERETIC) || isbanned_dept)
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=heretic;jobban4=[REF(M)]'><font color=red>Heretic</font></a></td>"
else
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=heretic;jobban4=[REF(M)]'>Heretic</a></td>"
//Nuke Operative
if(jobban_isbanned(M, ROLE_OPERATIVE) || isbanned_dept)
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=operative;jobban4=[REF(M)]'><font color=red>Nuke Operative</font></a></td>"
+29 -48
View File
@@ -308,10 +308,10 @@
var/list/areas_with_LS = list()
var/list/areas_with_intercom = list()
var/list/areas_with_camera = list()
var/list/station_areas_blacklist = typecacheof(list(/area/holodeck/rec_center, /area/shuttle, /area/engine/supermatter, /area/science/test_area, /area/space, /area/solar, /area/mine, /area/ruin, /area/asteroid))
var/list/station_areas_blacklist = typecacheof(list(/area/holodeck/rec_center, /area/shuttle, /area/engineering/supermatter, /area/science/test_area, /area/space, /area/solars, /area/mine, /area/ruin, /area/asteroid))
if(SSticker.current_state == GAME_STATE_STARTUP)
to_chat(usr, "Game still loading, please hold!")
to_chat(usr, "Game still loading, please hold!", confidential = TRUE)
return
var/log_message
@@ -326,8 +326,11 @@
for(var/area/A in world)
if(on_station)
var/turf/picked = safepick(get_area_turfs(A.type))
if(picked && is_station_level(picked.z))
var/list/area_turfs = get_area_turfs(A.type)
if (!length(area_turfs))
continue
var/turf/picked = pick(area_turfs)
if(is_station_level(picked.z))
if(!(A.type in areas_all) && !is_type_in_typecache(A, station_areas_blacklist))
areas_all.Add(A.type)
else if(!(A.type in areas_all))
@@ -481,74 +484,52 @@
set name = "Test Areas (ALL)"
cmd_admin_areatest(FALSE)
/client/proc/cmd_admin_dress(mob/M in GLOB.mob_list)
set category = "Admin.Events"
set name = "Select equipment"
if(!(ishuman(M) || isobserver(M)))
alert("Invalid mob")
return
var/dresscode = robust_dress_shop()
if(!dresscode)
return
var/delete_pocket
var/mob/living/carbon/human/H
if(isobserver(M))
H = M.change_mob_type(/mob/living/carbon/human, null, null, TRUE)
else
H = M
if(alert("Drop Items in Pockets? No will delete them.", "Robust quick dress shop", "Yes", "No") == "No")
delete_pocket = TRUE
SSblackbox.record_feedback("tally", "admin_verb", 1, "Select Equipment") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
for (var/obj/item/I in H.get_equipped_items(delete_pocket))
qdel(I)
if(dresscode != "Naked")
H.equipOutfit(dresscode)
H.regenerate_icons()
log_admin("[key_name(usr)] changed the equipment of [key_name(H)] to [dresscode].")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] changed the equipment of [ADMIN_LOOKUPFLW(H)] to [dresscode].</span>")
/client/proc/robust_dress_shop()
var/list/outfits = list("Cancel","Naked","Custom","As Job...")
var/list/paths = subtypesof(/datum/outfit) - typesof(/datum/outfit/job)
var/list/baseoutfits = list("Naked","Custom","As Job...", "As Plasmaman...")
var/list/outfits = list()
var/list/paths = subtypesof(/datum/outfit) - typesof(/datum/outfit/job) - typesof(/datum/outfit/plasmaman)
for(var/path in paths)
var/datum/outfit/O = path //not much to initalize here but whatever
if(initial(O.can_be_admin_equipped))
outfits[initial(O.name)] = path
outfits[initial(O.name)] = path
var/dresscode = input("Select outfit", "Robust quick dress shop") as null|anything in outfits
var/dresscode = input("Select outfit", "Robust quick dress shop") as null|anything in baseoutfits + sortList(outfits)
if (isnull(dresscode))
return
if (outfits[dresscode])
dresscode = outfits[dresscode]
if(dresscode == "Cancel")
return
if (dresscode == "As Job...")
var/list/job_paths = subtypesof(/datum/outfit/job)
var/list/job_outfits = list()
for(var/path in job_paths)
var/datum/outfit/O = path
if(initial(O.can_be_admin_equipped))
job_outfits[initial(O.name)] = path
job_outfits[initial(O.name)] = path
dresscode = input("Select job equipment", "Robust quick dress shop") as null|anything in job_outfits
dresscode = input("Select job equipment", "Robust quick dress shop") as null|anything in sortList(job_outfits)
dresscode = job_outfits[dresscode]
if(isnull(dresscode))
return
if (dresscode == "As Plasmaman...")
var/list/plasmaman_paths = typesof(/datum/outfit/plasmaman)
var/list/plasmaman_outfits = list()
for(var/path in plasmaman_paths)
var/datum/outfit/O = path
plasmaman_outfits[initial(O.name)] = path
dresscode = input("Select plasmeme equipment", "Robust quick dress shop") as null|anything in sortList(plasmaman_outfits)
dresscode = plasmaman_outfits[dresscode]
if(isnull(dresscode))
return
if (dresscode == "Custom")
var/list/custom_names = list()
for(var/datum/outfit/D in GLOB.custom_outfits)
custom_names[D.name] = D
var/selected_name = input("Select outfit", "Robust quick dress shop") as null|anything in custom_names
var/selected_name = input("Select outfit", "Robust quick dress shop") as null|anything in sortList(custom_names)
dresscode = custom_names[selected_name]
if(isnull(dresscode))
return
+2
View File
@@ -48,6 +48,8 @@
if(C.prefs.toggles & SOUND_PRAYERS)
if(usr.job == "Chaplain")
SEND_SOUND(C, sound('sound/effects/pray.ogg'))
else
SEND_SOUND(C, sound('sound/effects/ding.ogg'))
to_chat(usr, "<span class='info'>You pray to the gods: \"[msg_tmp]\"</span>", confidential = TRUE)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Prayer") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+49 -2
View File
@@ -879,8 +879,6 @@ Traitors and the like can also be revived with the previous role mostly intact.
message_admins("[ADMIN_LOOKUPFLW(usr)] [N.timing ? "activated" : "deactivated"] a nuke at [ADMIN_VERBOSEJMP(N)].")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Nuke", "[N.timing]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
/client/proc/create_outfits()
set category = "Debug"
set name = "Create Custom Outfit"
@@ -1547,6 +1545,55 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
msg += "</UL></BODY></HTML>"
src << browse(msg.Join(), "window=Player_playtime_check")
/obj/effect/temp_visual/fireball
icon = 'icons/obj/wizard.dmi'
icon_state = "fireball"
name = "fireball"
desc = "Get out of the way!"
layer = FLY_LAYER
randomdir = FALSE
duration = 9
pixel_z = 270
/obj/effect/temp_visual/fireball/Initialize()
. = ..()
animate(src, pixel_z = 0, time = duration)
/obj/effect/temp_visual/target
icon = 'icons/mob/actions/actions_items.dmi'
icon_state = "sniper_zoom"
layer = BELOW_MOB_LAYER
light_range = 2
duration = 9
/obj/effect/temp_visual/target/ex_act()
return
/obj/effect/temp_visual/target/Initialize(mapload, list/flame_hit)
. = ..()
INVOKE_ASYNC(src, .proc/fall, flame_hit)
/obj/effect/temp_visual/target/proc/fall(list/flame_hit)
var/turf/T = get_turf(src)
playsound(T,'sound/magic/fleshtostone.ogg', 80, 1)
new /obj/effect/temp_visual/fireball(T)
sleep(duration)
if(ismineralturf(T))
var/turf/closed/mineral/M = T
M.gets_drilled()
playsound(T, "explosion", 80, 1)
new /obj/effect/hotspot(T)
T.hotspot_expose(700, 50, 1)
for(var/mob/living/L in T.contents)
if(istype(L, /mob/living/simple_animal/hostile/megafauna/dragon))
continue
if(islist(flame_hit) && !flame_hit[L])
L.adjustFireLoss(40)
to_chat(L, "<span class='userdanger'>You're hit by the drake's fire breath!</span>")
flame_hit[L] = TRUE
else
L.adjustFireLoss(10) //if we've already hit them, do way less damage
/datum/admins/proc/cmd_show_exp_panel(client/client_to_check)
if(!check_rights(R_ADMIN))
return
+1 -1
View File
@@ -349,7 +349,7 @@
return
SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Egalitarian Station"))
for(var/obj/machinery/door/airlock/W in GLOB.machines)
if(is_station_level(W.z) && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison))
if(is_station_level(W.z) && !istype(get_area(W), /area/command) && !istype(get_area(W), /area/commons) && !istype(get_area(W), /area/service) && !istype(get_area(W), /area/command/heads_quarters) && !istype(get_area(W), /area/security/prison))
W.req_access = list()
message_admins("[key_name_admin(holder)] activated Egalitarian Station mode")
priority_announce("CentCom airlock control override activated. Please take this time to get acquainted with your coworkers.", null, "commandreport")
+227
View File
@@ -0,0 +1,227 @@
/client/proc/cmd_select_equipment(mob/target in GLOB.mob_list)
set category = "Admin.Events"
set name = "Select equipment"
var/datum/select_equipment/ui = new(usr, target)
ui.ui_interact(usr)
/*
* This is the datum housing the select equipment UI.
*
* You may notice some oddities about the way outfits are passed to the UI and vice versa here.
* That's because it handles both outfit typepaths (for normal outfits) *and* outfit objects (for custom outfits).
*
* Custom outfits need to be objects as they're created in runtime.
* "Then just handle the normal outfits as objects too and simplify the handling" - you may say.
* There are about 300 outfit types at the time of writing this. Initializing all of these to objects would be a huge waste.
*
*/
/datum/select_equipment
var/client/user
var/mob/target_mob
var/dummy_key
//static list to share all the outfit typepaths between all instances of this datum.
var/static/list/cached_outfits
//a typepath if the selected outfit is a normal outfit;
//an object if the selected outfit is a custom outfit
var/datum/outfit/selected_outfit = /datum/outfit
//serializable string for the UI to keep track of which outfit is selected
var/selected_identifier = "/datum/outfit"
/datum/select_equipment/New(_user, mob/target)
user = CLIENT_FROM_VAR(_user)
if(!ishuman(target) && !isobserver(target))
alert("Invalid mob")
return
target_mob = target
/datum/select_equipment/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "SelectEquipment", "Select Equipment")
ui.open()
ui.set_autoupdate(FALSE)
/datum/select_equipment/ui_state(mob/user)
return GLOB.admin_state
/datum/select_equipment/ui_status(mob/user, datum/ui_state/state)
if(QDELETED(target_mob))
return UI_CLOSE
return ..()
/datum/select_equipment/ui_close(mob/user)
clear_human_dummy(dummy_key)
qdel(src)
/datum/select_equipment/proc/init_dummy()
dummy_key = "selectequipmentUI_[target_mob]"
generate_dummy_lookalike(dummy_key, target_mob)
unset_busy_human_dummy(dummy_key)
return
/**
* Packs up data about an outfit as an assoc list to send to the UI as an outfit entry.
*
* Args:
* * category (string) - The tab it will be under
*
* * identifier (typepath or ref) - This will sent this back to ui_act to preview or spawn in an outfit.
* * Must be unique between all entries.
*
* * name (string) - Will be the text on the button
*
* * priority (bool)(optional) - If True, the UI will sort the entry to the top, right below favorites.
*
* * custom_entry (bool)(optional) - Send the identifier with a "ref" keyword instead of "path",
* * for the UI to tell apart custom outfits from normal ones.
*
* Returns (list) An outfit entry
*/
/datum/select_equipment/proc/outfit_entry(category, identifier, name, priority=FALSE, custom_entry=FALSE)
if(custom_entry)
return list("category" = category, "ref" = identifier, "name" = name, "priority" = priority)
return list("category" = category, "path" = identifier, "name" = name, "priority" = priority)
/datum/select_equipment/proc/make_outfit_entries(category="General", list/outfit_list)
var/list/entries = list()
for(var/path as anything in outfit_list)
var/datum/outfit/outfit = path
entries += list(outfit_entry(category, path, initial(outfit.name)))
return entries
//GLOB.custom_outfits lists outfit *objects* so we'll need to do some custom handling for it
/datum/select_equipment/proc/make_custom_outfit_entries(list/outfit_list)
var/list/entries = list()
for(var/datum/outfit/outfit as anything in outfit_list)
entries += list(outfit_entry("Custom", REF(outfit), outfit.name, custom_entry=TRUE)) //it's either this or special handling on the UI side
return entries
/datum/select_equipment/ui_data(mob/user)
var/list/data = list()
if(!dummy_key)
init_dummy()
var/icon/dummysprite = get_flat_human_icon(null,
dummy_key = dummy_key,
outfit_override = selected_outfit,
no_anim = TRUE)
data["icon64"] = icon2base64(dummysprite)
data["name"] = target_mob
var/datum/preferences/prefs = user?.client?.prefs
data["favorites"] = list()
if(prefs)
data["favorites"] = prefs.favorite_outfits
var/list/custom
custom += make_custom_outfit_entries(GLOB.custom_outfits)
data["custom_outfits"] = custom
data["current_outfit"] = selected_identifier
return data
/datum/select_equipment/ui_static_data(mob/user)
var/list/data = list()
if(!cached_outfits)
cached_outfits = list()
cached_outfits += list(outfit_entry("General", /datum/outfit, "Naked", priority=TRUE))
cached_outfits += make_outfit_entries("General", subtypesof(/datum/outfit) - typesof(/datum/outfit/job) - typesof(/datum/outfit/plasmaman))
cached_outfits += make_outfit_entries("Jobs", typesof(/datum/outfit/job))
cached_outfits += make_outfit_entries("Plasmamen Outfits", typesof(/datum/outfit/plasmaman))
data["outfits"] = cached_outfits
return data
/datum/select_equipment/proc/resolve_outfit(text)
var/path = text2path(text)
if(ispath(path, /datum/outfit))
return path
else //don't bail yet - could be a custom outfit
var/datum/outfit/custom_outfit = locate(text)
if(istype(custom_outfit))
return custom_outfit
/datum/select_equipment/ui_act(action, params)
if(..())
return
. = TRUE
switch(action)
if("preview")
var/datum/outfit/new_outfit = resolve_outfit(params["path"])
if(ispath(new_outfit)) //got a typepath - that means we're dealing with a normal outfit
selected_identifier = new_outfit //these are keyed by type
//by the way, no, they can't be keyed by name because many of them have duplicate names
else if(istype(new_outfit)) //got an initialized object - means it's a custom outfit
selected_identifier = REF(new_outfit) //and the outfit will be keyed by its ref (cause its type will always be /datum/outfit)
else //we got nothing and should bail
return
selected_outfit = new_outfit
if("applyoutfit")
var/datum/outfit/new_outfit = resolve_outfit(params["path"])
if(new_outfit && ispath(new_outfit)) //initialize it
new_outfit = new new_outfit
if(!istype(new_outfit))
return
user.admin_apply_outfit(target_mob, new_outfit)
if("customoutfit")
user.outfit_manager()
if("togglefavorite")
var/datum/outfit/outfit_path = resolve_outfit(params["path"])
if(!ispath(outfit_path)) //we do *not* want custom outfits (i.e objects) here, they're not even persistent
return
if(user.prefs.favorite_outfits.Find(outfit_path)) //already there, remove it
user.prefs.favorite_outfits -= outfit_path
else //not there, add it
user.prefs.favorite_outfits += outfit_path
user.prefs.save_preferences()
/client/proc/admin_apply_outfit(mob/target, dresscode)
if(!ishuman(target) && !isobserver(target))
alert("Invalid mob")
return
if(!dresscode)
return
var/delete_pocket
var/mob/living/carbon/human/human_target
if(isobserver(target))
human_target = target.change_mob_type(/mob/living/carbon/human, delete_old_mob = TRUE)
else
human_target = target
if(human_target.l_store || human_target.r_store || human_target.s_store) //saves a lot of time for admins and coders alike
if(alert("Drop Items in Pockets? No will delete them.", "Robust quick dress shop", "Yes", "No") == "No")
delete_pocket = TRUE
SSblackbox.record_feedback("tally", "admin_verb", 1, "Select Equipment") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
for(var/obj/item/item in human_target.get_equipped_items(delete_pocket))
qdel(item)
if(dresscode != "Naked")
human_target.equipOutfit(dresscode)
human_target.regenerate_icons()
log_admin("[key_name(usr)] changed the equipment of [key_name(human_target)] to [dresscode].")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] changed the equipment of [ADMIN_LOOKUPFLW(human_target)] to [dresscode].</span>")
return dresscode
@@ -111,6 +111,7 @@ GLOBAL_LIST_EMPTY(antagonists)
var/datum/skill_modifier/job/M = GLOB.skill_modifiers[GET_SKILL_MOD_ID(A, type)]
if(istype(M))
M.name = "[name] Training"
owner.AddComponent(/datum/component/activity)
SEND_SIGNAL(owner.current, COMSIG_MOB_ANTAG_ON_GAIN, src)
/datum/antagonist/proc/is_banned(mob/M)
@@ -141,6 +142,7 @@ GLOBAL_LIST_EMPTY(antagonists)
var/datum/team/team = get_team()
if(team)
team.remove_member(owner)
// we don't remove the activity component on purpose--no real point to it
qdel(src)
/datum/antagonist/proc/greet()
@@ -511,8 +511,7 @@
/obj/item/abductor/baton/proc/StunAttack(mob/living/L,mob/living/user)
L.lastattacker = user.real_name
L.lastattackerckey = user.ckey
L.set_last_attacker(user)
L.adjustStaminaLoss(35) //because previously it took 5-6 hits to actually "incapacitate" someone for the purposes of the sleep inducement
L.DefaultCombatKnockdown(140)
@@ -88,7 +88,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
/mob/camera/blob/proc/is_valid_turf(turf/T)
var/area/A = get_area(T)
if((A && !A.blob_allowed) || !T || !is_station_level(T.z) || isspaceturf(T))
if((A && !(A.area_flags & BLOBS_ALLOWED)) || !T || !is_station_level(T.z) || isspaceturf(T))
return FALSE
return TRUE
@@ -131,7 +131,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
var/area/Ablob = get_area(T)
if(!Ablob.blob_allowed)
if(!(Ablob.area_flags & BLOBS_ALLOWED))
continue
if(!(ROLE_BLOB in L.faction))
@@ -144,7 +144,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
for(var/area/A in GLOB.sortedAreas)
if(!(A.type in GLOB.the_station_areas))
continue
if(!A.blob_allowed)
if(!(A.area_flags & BLOBS_ALLOWED))
continue
A.color = blobstrain.color
A.name = "blob"
+1 -1
View File
@@ -211,7 +211,7 @@
to_chat(src, "<span class='userdanger'>You have no core and are about to die! May you rest in peace.</span>")
return
var/area/A = get_area(T)
if(isspaceturf(T) || A && !A.blob_allowed)
if(isspaceturf(T) || A && !(A.area_flags & BLOBS_ALLOWED))
to_chat(src, "<span class='warning'>You cannot relocate your core here!</span>")
return
if(!can_buy(80))
@@ -25,7 +25,7 @@
if(owner_overmind)
overmind = owner_overmind
var/area/Ablob = get_area(src)
if(Ablob.blob_allowed) //Is this area allowed for winning as blob?
if(Ablob.area_flags & BLOBS_ALLOWED) //Is this area allowed for winning as blob?
overmind.blobs_legit += src
GLOB.blobs += src //Keep track of the blob in the normal list either way
setDir(pick(GLOB.cardinals))
@@ -12,24 +12,34 @@
/obj/effect/proc_holder/changeling/biodegrade/sting_action(mob/living/carbon/human/user)
var/used = FALSE // only one form of shackles removed per use
if(!user.restrained() && isopenturf(user.loc))
if(!user.restrained() && !user.legcuffed && isopenturf(user.loc))
to_chat(user, "<span class='warning'>We are already free!</span>")
return 0
return FALSE
if(user.handcuffed)
var/obj/O = user.get_item_by_slot(SLOT_HANDCUFFED)
if(!istype(O))
return 0
return FALSE
user.visible_message("<span class='warning'>[user] vomits a glob of acid on [user.p_their()] [O]!</span>", \
"<span class='warning'>We vomit acidic ooze onto our restraints!</span>")
addtimer(CALLBACK(src, .proc/dissolve_handcuffs, user, O), 30)
used = TRUE
if(user.legcuffed)
var/obj/O = user.get_item_by_slot(SLOT_LEGCUFFED)
if(!istype(O))
return FALSE
user.visible_message("<span class='warning'>[user] vomits a glob of acid on [user.p_their()] [O]!</span>", \
"<span class='warning'>We vomit acidic ooze onto our restraints!</span>")
addtimer(CALLBACK(src, .proc/dissolve_legcuffs, user, O), 30)
used = TRUE
if(user.wear_suit && user.wear_suit.breakouttime && !used)
var/obj/item/clothing/suit/S = user.get_item_by_slot(SLOT_WEAR_SUIT)
if(!istype(S))
return 0
return FALSE
user.visible_message("<span class='warning'>[user] vomits a glob of acid across the front of [user.p_their()] [S]!</span>", \
"<span class='warning'>We vomit acidic ooze onto our straight jacket!</span>")
addtimer(CALLBACK(src, .proc/dissolve_straightjacket, user, S), 30)
@@ -39,7 +49,7 @@
if(istype(user.loc, /obj/structure/closet) && !used)
var/obj/structure/closet/C = user.loc
if(!istype(C))
return 0
return FALSE
C.visible_message("<span class='warning'>[C]'s hinges suddenly begin to melt and run!</span>")
to_chat(user, "<span class='warning'>We vomit acidic goop onto the interior of [C]!</span>")
addtimer(CALLBACK(src, .proc/open_closet, user, C), 70)
@@ -48,7 +58,7 @@
if(istype(user.loc, /obj/structure/spider/cocoon) && !used)
var/obj/structure/spider/cocoon/C = user.loc
if(!istype(C))
return 0
return FALSE
C.visible_message("<span class='warning'>[src] shifts and starts to fall apart!</span>")
to_chat(user, "<span class='warning'>We secrete acidic enzymes from our skin and begin melting our cocoon...</span>")
addtimer(CALLBACK(src, .proc/dissolve_cocoon, user, C), 25) //Very short because it's just webs
@@ -62,6 +72,12 @@
new /obj/effect/decal/cleanable/greenglow(O.drop_location())
qdel(O)
/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_legcuffs(mob/living/carbon/human/user, obj/O)
if(O && user.legcuffed == O)
user.visible_message("<span class='warning'>[O] dissolve[O.gender==PLURAL?"":"s"] into a puddle of sizzling goop.</span>")
new /obj/effect/decal/cleanable/greenglow(O.drop_location())
qdel(O)
/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_straightjacket(mob/living/carbon/human/user, obj/S)
if(S && user.wear_suit == S)
user.visible_message("<span class='warning'>[S] dissolves into a puddle of sizzling goop.</span>")
@@ -4,7 +4,7 @@
/obj/effect/proc_holder/changeling/strained_muscles
name = "Strained Muscles"
desc = "We evolve the ability to reduce the acid buildup in our muscles, allowing us to move much faster."
helptext = "The strain will make us tired, and we will rapidly become fatigued. Standard weight restrictions, like hardsuits, still apply. Cannot be used in lesser form."
helptext = "The strain will make us tired, and we will rapidly become fatigued. Standard weight restrictions, like hardsuits, still apply. Our chemical generation is drastically slowed while this is active. Cannot be used in lesser form."
dna_cost = 1
req_human = 1
var/stacks = 0 //Increments every 5 seconds; damage increases over time
@@ -14,12 +14,15 @@
action_background_icon_state = "bg_ling"
/obj/effect/proc_holder/changeling/strained_muscles/sting_action(mob/living/carbon/user)
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
active = !active
if(active)
to_chat(user, "<span class='notice'>Our muscles tense and strengthen.</span>")
changeling.chem_recharge_slowdown += 0.8 // stacking this with other abilities will cause you to actively lose chemicals
else
user.remove_movespeed_modifier(/datum/movespeed_modifier/strained_muscles)
to_chat(user, "<span class='notice'>Our muscles relax.</span>")
changeling.chem_recharge_slowdown -= 0.8
if(stacks >= 10)
to_chat(user, "<span class='danger'>We collapse in exhaustion.</span>")
user.DefaultCombatKnockdown(60)
@@ -30,6 +33,7 @@
return TRUE
/obj/effect/proc_holder/changeling/strained_muscles/proc/muscle_loop(mob/living/carbon/user)
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
while(active)
user.add_movespeed_modifier(/datum/movespeed_modifier/strained_muscles)
if(user.stat != CONSCIOUS || user.staminaloss >= 90)
@@ -37,6 +41,7 @@
to_chat(user, "<span class='notice'>Our muscles relax without the energy to strengthen them.</span>")
user.DefaultCombatKnockdown(40)
user.remove_movespeed_modifier(/datum/movespeed_modifier/strained_muscles)
changeling.chem_recharge_slowdown -= 0.8
break
stacks++
@@ -8,7 +8,7 @@
desc = "A resilient shield made out of brass.. It feels warm to the touch."
var/clockwork_desc = "A powerful shield of ratvarian making. It absorbs blocked attacks to charge devastating bashes."
armor = list("melee" = 80, "bullet" = 70, "laser" = -10, "energy" = -20, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
shield_flags = SHIELD_FLAGS_DEFAULT
shield_flags = SHIELD_FLAGS_DEFAULT | SHIELD_KINETIC_STRONG | SHIELD_ENERGY_WEAK
max_integrity = 300 //High integrity, extremely strong against melee / bullets, but still quite easy to destroy with lasers and energy
repair_material = /obj/item/stack/tile/brass
var/dam_absorbed = 0
@@ -37,7 +37,7 @@
lastWarning = world.time
to_chat(src, "<span class='warning'>This turf is consecrated and can't be crossed!</span>")
return
if(istype(get_area(T), /area/chapel))
if(istype(get_area(T), /area/service/chapel))
if((world.time - lastWarning) >= 30)
lastWarning = world.time
to_chat(src, "<span class='warning'>The Chapel is hallowed ground under a heretical deity, and can't be accessed!</span>")
@@ -24,7 +24,8 @@
/datum/clockwork_scripture/create_object/stargazer/check_special_requirements()
var/area/A = get_area(invoker)
if(A.outdoors || A.map_name == "Space" || !A.blob_allowed)
var/turf/T = get_turf(invoker)
if(!is_station_level(invoker.z) || isspaceturf(T) || !(A.area_flags & VALID_TERRITORY))
to_chat(invoker, "<span class='danger'>Stargazers can't be built off-station.</span>")
return
return ..()
@@ -34,7 +34,7 @@
return FALSE
var/area/A = get_area(invoker)
var/turf/T = get_turf(invoker)
if(!T || !is_station_level(T.z) || istype(A, /area/shuttle) || !A.blob_allowed)
if(!is_station_level(T.z) || isspaceturf(T) || !(A.area_flags & VALID_TERRITORY) || isshuttleturf(T))
to_chat(invoker, "<span class='warning'>You must be on the station to activate the Ark!</span>")
return FALSE
if(GLOB.clockwork_gateway_activated)
@@ -87,7 +87,7 @@
if(!M || !M.current)
continue
if(ishuman(M.current))
M.current.add_overlay(mutable_appearance('icons/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER))
M.current.add_overlay(mutable_appearance('icons/effects/genetics.dmi', "servitude", -ANTAG_LAYER))
var/turf/T = get_turf(src)
var/list/open_turfs = list()
for(var/turf/open/OT in orange(1, T))
@@ -52,7 +52,7 @@
break
if(has_starlight && anchored)
var/area/A = get_area(src)
if(A.outdoors || A.map_name == "Space" || !A.blob_allowed)
if(A.outdoors || A.map_name == "Space" || !(A.area_flags & VALID_TERRITORY))
has_starlight = FALSE
if(old_status != has_starlight)
if(has_starlight)
@@ -139,7 +139,7 @@
current.throw_alert("clockinfo", /obj/screen/alert/clockwork/infodump)
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
if(G && G.active && ishuman(current))
current.add_overlay(mutable_appearance('icons/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER))
current.add_overlay(mutable_appearance('icons/effects/genetics.dmi', "servitude", -ANTAG_LAYER))
/datum/antagonist/clockcult/remove_innate_effects(mob/living/mob_override)
var/mob/living/current = owner.current
+1 -2
View File
@@ -385,8 +385,7 @@
qdel(src)
return
log_combat(user, M, "used a cult spell on", source.name, "")
M.lastattacker = user.real_name
M.lastattackerckey = user.ckey
M.set_last_attacker(user)
/obj/item/melee/blood_magic/afterattack(atom/target, mob/living/carbon/user, proximity)
. = ..()
+2 -2
View File
@@ -332,7 +332,7 @@
var/mob/living/carbon/human/H = cultist
new /obj/effect/temp_visual/cult/sparks(get_turf(H), H.dir)
var/istate = pick("halo1","halo2","halo3","halo4","halo5","halo6")
H.add_overlay(mutable_appearance('icons/effects/32x64.dmi', istate, -BODY_FRONT_LAYER))
H.add_overlay(mutable_appearance('icons/effects/32x64.dmi', istate, -ANTAG_LAYER))
/datum/team/cult/proc/setup_objectives()
//SAC OBJECTIVE , todo: move this to objective internals
@@ -419,7 +419,7 @@
var/sanity = 0
while(summon_spots.len < SUMMON_POSSIBILITIES && sanity < 100)
var/area/summon = pick(GLOB.sortedAreas - summon_spots)
if(summon && is_station_level(summon.z) && summon.valid_territory)
if(summon && is_station_level(summon.z) && !(summon.area_flags & VALID_TERRITORY))
summon_spots += summon
sanity++
update_explanation_text()
+1 -1
View File
@@ -148,7 +148,7 @@ This file contains the cult dagger and rune list code
to_chat(user, "<span class='cult'>There is already a rune here.</span>")
return FALSE
var/area/A = get_area(T)
if((!is_station_level(T.z) && !is_mining_level(T.z)) || (A && !A.blob_allowed))
if((!is_station_level(T.z) && !is_mining_level(T.z)) || !(A?.area_flags & VALID_TERRITORY))
to_chat(user, "<span class='warning'>The veil is not weak enough here.</span>")
return FALSE
return TRUE
@@ -69,7 +69,7 @@
/datum/action/innate/heretic_shatter/Activate()
if(do_after(holder,10, target = holder))
var/turf/safe_turf = find_safe_turf(zlevels = sword.z, extended_safety_checks = TRUE)
do_teleport(holder,safe_turf,forceMove = TRUE)
do_teleport(holder,safe_turf,forceMove = TRUE,channel=TELEPORT_CHANNEL_MAGIC)
to_chat(holder,"<span class='warning'>You feel a gust of energy flow through your body... the Rusted Hills heard your call...</span>")
qdel(sword)
@@ -178,7 +178,7 @@
/datum/eldritch_knowledge/summon/stalker
name = "Lonely Ritual"
gain_text = "I was able to combine my greed and desires to summon an eldritch beast I had never seen before. An ever shapeshifting mass of flesh, it knew well my goals."
desc = "You can now summon a Stalker by transmutating a pair of eyes, a candle, a pen and a piece of paper. Stalkers can shapeshift into harmless animals to get close to the victim."
desc = "You can now summon a Stalker by transmutating a kitchen knife, a candle, a pen and a piece of paper. Stalkers can shapeshift into harmless animals to get close to the victim."
cost = 1
required_atoms = list(/obj/item/kitchen/knife,/obj/item/candle,/obj/item/pen,/obj/item/paper)
mob_to_summon = /mob/living/simple_animal/hostile/eldritch/stalker
+14 -3
View File
@@ -1,6 +1,6 @@
//Revenants: based off of wraiths from Goon
//"Ghosts" that are invisible and move like ghosts, cannot take damage while invisible
//Don't hear deadchat and are NOT normal ghosts
//Can hear deadchat, but are NOT normal ghosts and do NOT have x-ray vision
//Admin-spawn or random event
#define INVISIBILITY_REVENANT 50
@@ -63,6 +63,7 @@
var/essence_regenerating = TRUE //If the revenant regenerates essence or not
var/essence_regen_amount = 5 //How much essence regenerates
var/essence_accumulated = 0 //How much essence the revenant has stolen
var/essence_excess = 0 //How much stolen essence available for unlocks
var/revealed = FALSE //If the revenant can take damage from normal sources.
var/unreveal_time = 0 //How long the revenant is revealed for, is about 2 seconds times this var.
var/unstun_time = 0 //How long the revenant is stunned for, is about 2 seconds times this var.
@@ -76,6 +77,7 @@
/mob/living/simple_animal/revenant/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_SIXTHSENSE, INNATE_TRAIT)
AddSpell(new /obj/effect/proc_holder/spell/targeted/night_vision/revenant(null))
AddSpell(new /obj/effect/proc_holder/spell/targeted/telepathy/revenant(null))
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/defile(null))
@@ -138,6 +140,7 @@
. = ..()
. += "Current essence: [essence]/[essence_regen_cap]E"
. += "Stolen essence: [essence_accumulated]E"
. += "Unused stolen essence: [essence_excess]E)"
. += "Stolen perfect souls: [perfectsouls]"
/mob/living/simple_animal/revenant/update_health_hud()
@@ -304,16 +307,24 @@
return FALSE
return TRUE
/mob/living/simple_animal/revenant/proc/unlock(essence_cost)
if(essence_excess < essence_cost)
return FALSE
essence_excess -= essence_cost
update_action_buttons_icon()
return TRUE
/mob/living/simple_animal/revenant/proc/change_essence_amount(essence_amt, silent = FALSE, source = null)
if(!src)
return
if(essence + essence_amt <= 0)
if(essence + essence_amt < 0)
return
essence = max(0, essence+essence_amt)
update_action_buttons_icon()
update_health_hud()
if(essence_amt > 0)
essence_accumulated = max(0, essence_accumulated+essence_amt)
essence_excess = max(0, essence_excess+essence_amt)
update_action_buttons_icon()
if(!silent)
if(essence_amt > 0)
to_chat(src, "<span class='revennotice'>Gained [essence_amt]E[source ? " from [source]":""].</span>")
@@ -61,6 +61,8 @@
to_chat(src, "<span class='revenminor'>You begin siphoning essence from [target]'s soul.</span>")
if(target.stat != DEAD)
to_chat(target, "<span class='warning'>You feel a horribly unpleasant draining sensation as your grip on life weakens...</span>")
if(target.stat == SOFT_CRIT)
target.Stun(46)
reveal(46)
stun(46)
target.visible_message("<span class='warning'>[target] suddenly rises slightly into the air, [target.p_their()] skin turning an ashy gray.</span>")
@@ -144,7 +146,7 @@
if(user.inhibited)
return FALSE
if(locked)
if(user.essence <= unlock_amount)
if(user.essence_excess <= unlock_amount)
return FALSE
if(user.essence <= cast_amount)
return FALSE
@@ -158,7 +160,7 @@
locked = FALSE
return TRUE
if(locked)
if(!user.castcheck(-unlock_amount))
if(!user.unlock(unlock_amount))
charge_counter = charge_max
return FALSE
name = "[initial(name)] ([cast_amount]E)"
@@ -185,6 +187,7 @@
range = 5
stun = 30
cast_amount = 40
unlock_amount = 25
var/shock_range = 2
var/shock_damage = 15
action_icon_state = "overload_lights"
@@ -197,7 +200,7 @@
/obj/effect/proc_holder/spell/aoe_turf/revenant/overload/proc/overload(turf/T, mob/user)
for(var/obj/machinery/light/L in T)
if(!L.on)
return
continue
L.visible_message("<span class='warning'><b>\The [L] suddenly flares brightly and begins to spark!</span>")
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(4, 0, L)
@@ -226,7 +229,7 @@
range = 4
stun = 20
reveal = 40
unlock_amount = 75
unlock_amount = 10
cast_amount = 30
action_icon_state = "defile"
@@ -277,7 +280,7 @@
charge_max = 200
range = 4
cast_amount = 60
unlock_amount = 200
unlock_amount = 125
action_icon_state = "malfunction"
//A note to future coders: do not replace this with an EMP because it will wreck malf AIs and everyone will hate you.
@@ -324,7 +327,7 @@
charge_max = 200
range = 3
cast_amount = 50
unlock_amount = 200
unlock_amount = 75
action_icon_state = "blight"
/obj/effect/proc_holder/spell/aoe_turf/revenant/blight/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
@@ -7,7 +7,21 @@
earliest_start = 1 HOURS
min_players = 20
/datum/round_event_control/slaughter/canSpawnEvent()
weight = initial(src.weight)
var/list/allowed_turf_typecache = typecacheof(/turf/open) - typecacheof(/turf/open/space)
var/list/allowed_z_cache = list()
for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION))
allowed_z_cache[num2text(z)] = TRUE
for(var/obj/effect/decal/cleanable/C in world)
if(!C.loc || QDELETED(C))
continue
if(!C.can_bloodcrawl_in())
continue
if(!SSpersistence.IsValidDebrisLocation(C.loc, allowed_turf_typecache, allowed_z_cache, C.type, FALSE))
continue
weight += 0.03
return ..()
/datum/round_event/ghost_role/slaughter
minimum_required = 1
+47 -31
View File
@@ -261,19 +261,26 @@
S.DisIntegrate(src)
return TRUE
/obj/machinery/door/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
var/isonshuttle = istype(get_area(src), /area/shuttle)
for(var/turf/T in range(1, src))
var/area/A = get_area(T)
if(isspaceturf(T) || (!isonshuttle && (istype(A, /area/shuttle) || istype(A, /area/space))) || (isonshuttle && !istype(A, /area/shuttle)))
to_chat(S, "<span class='warning'>Destroying this object has the potential to cause a hull breach. Aborting.</span>")
S.target = null
/obj/machinery/door/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
var/is_on_shuttle = istype(get_area(src), /area/shuttle)
for(var/turf/turf_in_range in range(1, src))
var/area/turf_area = get_area(turf_in_range)
//Check for dangerous pressure differences
// if (turf_in_range.return_turf_delta_p() > DANGEROUS_DELTA_P)
// to_chat(actor, "<span class='warning'>Destroying this object has the potential to cause an explosive pressure release. Aborting.</span>")
// actor.target = null
// return TRUE
//Check if breaking this door will expose the station to space/planetary atmos
if(isspaceturf(turf_in_range) || (!is_on_shuttle && (istype(turf_area, /area/shuttle) || istype(turf_area, /area/space))) || (is_on_shuttle && !istype(turf_area, /area/shuttle)))
to_chat(actor, "<span class='warning'>Destroying this object has the potential to cause a hull breach. Aborting.</span>")
actor.target = null
return FALSE
else if(istype(A, /area/engine/supermatter))
to_chat(S, "<span class='warning'>Disrupting the containment of a supermatter crystal would not be to our benefit. Aborting.</span>")
S.target = null
//Check if this door is important in supermatter containment
else if(istype(turf_area, /area/engineering/supermatter))
to_chat(actor, "<span class='warning'>Disrupting the containment of a supermatter crystal would not be to our benefit. Aborting.</span>")
actor.target = null
return FALSE
S.DisIntegrate(src)
actor.DisIntegrate(src)
return TRUE
/obj/machinery/camera/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
@@ -342,31 +349,40 @@
to_chat(S, "<span class='warning'>This bluespace source will be important to us later. Aborting.</span>")
return FALSE
/turf/closed/wall/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
var/isonshuttle = istype(loc, /area/shuttle)
for(var/turf/T in range(1, src))
var/area/A = get_area(T)
if(isspaceturf(T) || (!isonshuttle && (istype(A, /area/shuttle) || istype(A, /area/space))) || (isonshuttle && !istype(A, /area/shuttle)))
to_chat(S, "<span class='warning'>Destroying this object has the potential to cause a hull breach. Aborting.</span>")
S.target = null
/turf/closed/wall/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
var/is_on_shuttle = istype(loc, /area/shuttle)
for(var/turf/turf_in_range in range(1, src))
var/area/turf_area = get_area(turf_in_range)
// if (turf_in_range.return_turf_delta_p() > DANGEROUS_DELTA_P)
// to_chat(actor, "<span class='warning'>Destroying this object has the potential to cause an explosive pressure release. Aborting.</span>")
// actor.target = null
// return TRUE
if(isspaceturf(turf_in_range) || (!is_on_shuttle && (istype(turf_area, /area/shuttle) || istype(turf_area, /area/space))) || (is_on_shuttle && !istype(turf_area, /area/shuttle)))
to_chat(actor, "<span class='warning'>Destroying this object has the potential to cause a hull breach. Aborting.</span>")
actor.target = null
return TRUE
else if(istype(A, /area/engine/supermatter))
to_chat(S, "<span class='warning'>Disrupting the containment of a supermatter crystal would not be to our benefit. Aborting.</span>")
S.target = null
else if(istype(turf_area, /area/engineering/supermatter))
to_chat(actor, "<span class='warning'>Disrupting the containment of a supermatter crystal would not be to our benefit. Aborting.</span>")
actor.target = null
return TRUE
return ..()
/obj/structure/window/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
var/isonshuttle = istype(get_area(src), /area/shuttle)
for(var/turf/T in range(1, src))
var/area/A = get_area(T)
if(isspaceturf(T) || (!isonshuttle && (istype(A, /area/shuttle) || istype(A, /area/space))) || (isonshuttle && !istype(A, /area/shuttle)))
to_chat(S, "<span class='warning'>Destroying this object has the potential to cause a hull breach. Aborting.</span>")
S.target = null
/obj/structure/window/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
var/is_on_shuttle = istype(get_area(src), /area/shuttle)
for(var/t in RANGE_TURFS(1, src))
var/turf/turf_in_range = t
var/area/turf_area = get_area(turf_in_range)
// if (turf_in_range.return_turf_delta_p() > DANGEROUS_DELTA_P)
// to_chat(actor, "<span class='warning'>Destroying this object has the potential to cause an explosive pressure release. Aborting.</span>")
// actor.target = null
// return TRUE
if(isspaceturf(turf_in_range) || (!is_on_shuttle && (istype(turf_area, /area/shuttle) || istype(turf_area, /area/space))) || (is_on_shuttle && !istype(turf_area, /area/shuttle)))
to_chat(actor, "<span class='warning'>Destroying this object has the potential to cause a hull breach. Aborting.</span>")
actor.target = null
return TRUE
else if(istype(A, /area/engine/supermatter))
to_chat(S, "<span class='warning'>Disrupting the containment of a supermatter crystal would not be to our benefit. Aborting.</span>")
S.target = null
else if(istype(turf_area, /area/engineering/supermatter))
to_chat(actor, "<span class='warning'>Disrupting the containment of a supermatter crystal would not be to our benefit. Aborting.</span>")
actor.target = null
return TRUE
return ..()
@@ -1,30 +1,7 @@
/datum/traitor_class/human/assassin
/datum/traitor_class/human/subterfuge/assassin
name = "Donk Co Operative"
employer = "Donk Corporation"
weight = 0
weight = 6
chaos = 1
threat = 2
/datum/traitor_class/human/assassin/forge_single_objective(datum/antagonist/traitor/T)
.=1
var/permakill_prob = 20
var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
permakill_prob = max(0,mode.threat_level-50)
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = T.owner
destroy_objective.find_target()
T.add_objective(destroy_objective)
else if(prob(permakill_prob))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
else
var/datum/objective/assassinate/once/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
assassin_prob = 70
@@ -1,12 +1,12 @@
/datum/traitor_class/human/freeform
name = "Waffle Co Agent"
employer = "Waffle Company"
weight = 0 // should not spawn in unless admins bus something in the traitor panel with setting traitor classes
weight = 5
chaos = 0
/datum/traitor_class/human/freeform/forge_objectives(datum/antagonist/traitor/T)
var/datum/objective/escape/O = new
O.explanation_text = "You have no explicit goals! While we don't approve of mindless slaughter, you may antagonize nanotrasen any way you wish! Make sure to escape alive and not in custody, though!"
var/datum/objective/freedom/O = new
O.explanation_text = "You have no explicit goals! While we don't approve of mindless slaughter, you may antagonize nanotrasen any way you wish! Don't get captured or killed, but if you've done nothing, you'll be in trouble!"
O.owner = T.owner
T.add_objective(O)
return
@@ -13,8 +13,12 @@
T.assign_exchange_role(SSticker.mode.exchange_blue)
objective_count += 1 //Exchange counts towards number of objectives
var/toa = CONFIG_GET(number/traitor_objectives_amount)
var/attempts = 0
for(var/i = objective_count, i < toa, i++)
forge_single_objective(T)
var/success = FALSE
while(!success && attempts < max(toa*10, 100))
success = forge_single_objective(T)
attempts += 1
if(!(locate(/datum/objective/escape) in T.objectives))
var/datum/objective/escape/escape_objective = new
escape_objective.owner = T.owner
@@ -1,12 +1,11 @@
/datum/traitor_class/human/subterfuge
name = "MI13 Operative"
employer = "MI13"
weight = 36
weight = 25
chaos = -5
var/assassin_prob = 25
/datum/traitor_class/human/subterfuge/forge_single_objective(datum/antagonist/traitor/T)
.=1
var/assassin_prob = 30
var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
@@ -16,24 +15,31 @@
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
return TRUE
else
var/list/weights = list()
weights["sabo"] = length(subtypesof(/datum/sabotage_objective))
weights["steal"] = length(subtypesof(/datum/objective_item/steal))
var/datum/objective/sabotage/sabotage_objective = new
sabotage_objective.owner = T.owner
if(sabotage_objective.find_target())
weights["sabo"] = length(subtypesof(/datum/objective_item/steal))
var/datum/objective/steal/steal_objective = new
steal_objective.owner = T.owner
if(steal_objective.find_target())
weights["steal"] = length(subtypesof(/datum/objective_item/steal))
weights["download"] = !(locate(/datum/objective/download) in T.objectives || (T.owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
switch(pickweight(weights))
if("sabo")
var/datum/objective/sabotage/sabotage_objective = new
sabotage_objective.owner = T.owner
sabotage_objective.find_target()
T.add_objective(sabotage_objective)
qdel(steal_objective)
return TRUE
if("steal")
var/datum/objective/steal/steal_objective = new
steal_objective.owner = T.owner
steal_objective.find_target()
T.add_objective(steal_objective)
qdel(sabotage_objective)
return TRUE
if("download")
var/datum/objective/download/download_objective = new
download_objective.owner = T.owner
download_objective.gen_amount_goal()
T.add_objective(download_objective)
return TRUE
return FALSE
@@ -7,7 +7,8 @@ GLOBAL_LIST_EMPTY(traitor_classes)
var/chaos = 0
var/threat = 0
var/TC = 20
/// Minimum players for this to randomly roll via get_random_traitor_class().
var/processing = FALSE
/// Minimum players for this to randomly roll via get_random_traitor_kind().
var/min_players = 0
var/list/uplink_filters
@@ -43,4 +44,6 @@ GLOBAL_LIST_EMPTY(traitor_classes)
/datum/traitor_class/proc/clean_up_traitor(datum/antagonist/traitor/T)
// Any effects that need to be cleaned up if traitor class is being swapped.
/datum/traitor_class/proc/on_process(/datum/antagonist/traitor/T)
// only for processing traitor classes; runs once an SSprocessing tick
@@ -26,6 +26,8 @@
if(traitor_kind)
traitor_kind.remove_innate_effects(owner.current)
traitor_kind.clean_up_traitor(src)
if(traitor_kind.processing)
STOP_PROCESSING(SSprocessing, src)
swap_from_old = TRUE
traitor_kind = GLOB.traitor_classes[kind]
traitor_kind.apply_innate_effects(owner.current)
@@ -33,11 +35,16 @@
for(var/O in objectives)
qdel(O)
traitor_kind.forge_objectives(src)
if(traitor_kind.processing)
START_PROCESSING(SSprocessing, src)
if(swap_from_old)
traitor_kind.finalize_traitor(src)
traitor_kind.greet(src)
owner.announce_objectives()
/datum/antagonist/traitor/process()
traitor_kind.on_process(src)
/proc/get_random_traitor_kind(var/list/blacklist = list())
var/chaos_weight = 0
if(istype(SSticker.mode,/datum/game_mode/dynamic))
@@ -385,14 +385,10 @@
/obj/item/warpwhistle/attack_self(mob/living/carbon/user)
if(!istype(user) || on_cooldown)
return
var/turf/T = get_turf(user)
var/area/A = get_area(user)
if(!T || !A || A.noteleport)
to_chat(user, "<span class='warning'>You play \the [src], yet no sound comes out of it... Looks like it won't work here.</span>")
return
on_cooldown = TRUE
last_user = user
playsound(T,'sound/magic/warpwhistle.ogg', 200, 1)
var/turf/T = get_turf(user)
playsound(T,'sound/magic/warpwhistle.ogg', 200, TRUE)
ADD_TRAIT(user, TRAIT_MOBILITY_NOMOVE, src)
ADD_TRAIT(user, TRAIT_MOBILITY_NOUSE, src)
ADD_TRAIT(user, TRAIT_MOBILITY_NOPICKUP, src)
@@ -400,6 +396,10 @@
new /obj/effect/temp_visual/tornado(T)
sleep(20)
if(interrupted(user))
REMOVE_TRAIT(user, TRAIT_MOBILITY_NOMOVE, src)
REMOVE_TRAIT(user, TRAIT_MOBILITY_NOUSE, src)
REMOVE_TRAIT(user, TRAIT_MOBILITY_NOPICKUP, src)
user.update_mobility()
return
user.invisibility = INVISIBILITY_MAXIMUM
user.status_flags |= GODMODE
@@ -427,8 +427,7 @@
if(interrupted(user))
return
on_cooldown = 2
sleep(40)
on_cooldown = 0
addtimer(VARSET_CALLBACK(src, on_cooldown, 0), 4 SECONDS)
/obj/item/warpwhistle/Destroy()
if(on_cooldown == 1 && last_user) //Flute got dunked somewhere in the teleport
-23
View File
@@ -213,29 +213,6 @@
for(var/obj/item/organ/genital/G in internal_organs)
if(!CHECK_BITFIELD(G.genital_flags, CAN_CLIMAX_WITH)) //Skip things like wombs and testicles
continue
var/mob/living/partner
var/check_target
var/list/worn_stuff = get_equipped_items()
if(G.is_exposed(worn_stuff))
if(pulling) //Are we pulling someone? Priority target, we can't be making option menus for this, has to be quick
if(isliving(pulling)) //Don't fuck objects
check_target = pulling
if(pulledby && !check_target) //prioritise pulled over pulledby
if(isliving(pulledby))
check_target = pulledby
//Now we should have a partner, or else we have to come alone
if(check_target)
if(iscarbon(check_target)) //carbons can have clothes
var/mob/living/carbon/C = check_target
if(C.exposed_genitals.len || C.is_groin_exposed() || C.is_chest_exposed()) //Are they naked enough?
partner = C
else //A cat is fine too
partner = check_target
if(partner) //Did they pass the clothing checks?
mob_climax_partner(G, partner, mb_time = 0) //Instant climax due to forced
continue //You've climaxed once with this organ, continue on
//not exposed OR if no partner was found while exposed, climax alone
mob_climax_outside(G, mb_time = 0) //removed climax timer for sudden, forced orgasms
//Now all genitals that could climax, have.
//Since this was a forced climax, we do not need to continue with the other stuff
-64
View File
@@ -262,70 +262,6 @@
/obj/item/assembly/flash/armimplant/proc/cooldown()
overheat = FALSE
/obj/item/assembly/flash/shield
name = "strobe shield"
desc = "A shield with a built in, high intensity light capable of blinding and disorienting suspects. Takes regular handheld flashes as bulbs."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "flashshield"
item_state = "flashshield"
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
slot_flags = ITEM_SLOT_BACK
force = 10
throwforce = 5
throw_speed = 2
throw_range = 3
w_class = WEIGHT_CLASS_BULKY
custom_materials = list(/datum/material/glass=7500, /datum/material/iron=1000)
attack_verb = list("shoved", "bashed")
block_chance = 50
armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 70)
/obj/item/assembly/flash/shield/flash_recharge(interval=10)
if(times_used >= 4)
burn_out()
return FALSE
return TRUE
/obj/item/assembly/flash/shield/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/assembly/flash/handheld))
var/obj/item/assembly/flash/handheld/flash = W
if(flash.crit_fail)
to_chat(user, "No sense replacing it with a broken bulb.")
return
else
to_chat(user, "You begin to replace the bulb.")
if(do_after(user, 20, target = src))
if(flash.crit_fail || !flash || QDELETED(flash))
return
crit_fail = FALSE
times_used = 0
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
update_icon()
flash.crit_fail = TRUE
flash.update_icon()
return
..()
/obj/item/assembly/flash/shield/update_icon(flash = FALSE)
icon_state = "flashshield"
item_state = "flashshield"
if(crit_fail)
icon_state = "riot"
item_state = "riot"
else if(flash)
icon_state = "flashshield_flash"
item_state = "flashshield_flash"
addtimer(CALLBACK(src, /atom/.proc/update_icon), 5)
if(holder)
holder.update_icon()
/obj/item/assembly/flash/shield/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
activate()
return ..()
//ported from tg - check to make sure it can't appear where it's not supposed to.
/obj/item/assembly/flash/hypnotic
desc = "A modified flash device, programmed to emit a sequence of subliminal flashes that can send a vulnerable target into a hypnotic trance."
@@ -345,6 +345,14 @@
InsertAll("", each, GLOB.alldirs)
..()
/datum/asset/spritesheet/decals
name = "decals"
/datum/asset/spritesheet/decals/register()
for(var/each in list('icons/turf/decals.dmi'))
InsertAll("", each, GLOB.alldirs)
..()
/datum/asset/spritesheet/supplypods
name = "supplypods"
@@ -0,0 +1,86 @@
GLOBAL_LIST_EMPTY(bluespace_pipe_networks)
/obj/machinery/atmospherics/pipe/bluespace
name = "bluespace pipe"
desc = "Transmits gas across large distances of space. Developed using bluespace technology."
icon = 'icons/obj/atmospherics/pipes/bluespace.dmi'
icon_state = "map"
pipe_state = "bluespace"
dir = SOUTH
initialize_directions = SOUTH
device_type = UNARY
can_buckle = FALSE
construction_type = /obj/item/pipe/bluespace
var/bluespace_network_name
/obj/machinery/atmospherics/pipe/bluespace/New()
icon_state = "pipe"
if(bluespace_network_name) // in case someone maps one in for some reason
if(!GLOB.bluespace_pipe_networks[bluespace_network_name])
GLOB.bluespace_pipe_networks[bluespace_network_name] = list()
GLOB.bluespace_pipe_networks[bluespace_network_name] |= src
..()
/obj/machinery/atmospherics/pipe/bluespace/on_construction()
. = ..()
if(bluespace_network_name)
if(!GLOB.bluespace_pipe_networks[bluespace_network_name])
GLOB.bluespace_pipe_networks[bluespace_network_name] = list()
GLOB.bluespace_pipe_networks[bluespace_network_name] |= src
/obj/machinery/atmospherics/pipe/bluespace/Destroy()
if(GLOB.bluespace_pipe_networks[bluespace_network_name])
GLOB.bluespace_pipe_networks[bluespace_network_name] -= src
for(var/p in GLOB.bluespace_pipe_networks[bluespace_network_name])
var/obj/machinery/atmospherics/pipe/bluespace/P = p
QDEL_NULL(P.parent)
P.build_network()
return ..()
/obj/machinery/atmospherics/pipe/bluespace/examine(user)
. = ..()
. += "<span class='notice'>This one is connected to the \"[html_encode(bluespace_network_name)]\" network.</span>"
/obj/machinery/atmospherics/pipe/bluespace/SetInitDirections()
initialize_directions = dir
/obj/machinery/atmospherics/pipe/bluespace/pipeline_expansion()
return ..() + GLOB.bluespace_pipe_networks[bluespace_network_name] - src
/obj/machinery/atmospherics/pipe/bluespace/hide()
update_icon()
/obj/machinery/atmospherics/pipe/bluespace/update_icon(showpipe)
underlays.Cut()
var/turf/T = loc
if(level == 2 || !T.intact)
showpipe = TRUE
plane = GAME_PLANE
else
showpipe = FALSE
plane = FLOOR_PLANE
if(!showpipe)
return //no need to update the pipes if they aren't showing
var/connected = 0 //Direction bitset
for(var/i in 1 to device_type) //adds intact pieces
if(nodes[i])
var/obj/machinery/atmospherics/node = nodes[i]
var/image/img = get_pipe_underlay("pipe_intact", get_dir(src, node), node.pipe_color)
underlays += img
connected |= img.dir
for(var/direction in GLOB.cardinals)
if((initialize_directions & direction) && !(connected & direction))
underlays += get_pipe_underlay("pipe_exposed", direction)
/obj/machinery/atmospherics/pipe/bluespace/paint()
return FALSE
/obj/machinery/atmospherics/pipe/bluespace/proc/get_pipe_underlay(state, dir, color = null)
if(color)
. = getpipeimage('icons/obj/atmospherics/components/binary_devices.dmi', state, dir, color)
else
. = getpipeimage('icons/obj/atmospherics/components/binary_devices.dmi', state, dir)
@@ -17,7 +17,7 @@
/datum/blackmarket_item/New()
if(isnull(price))
price = rand(price_min, price_max)
price = round(rand(price_min, price_max), 5)
if(isnull(stock))
stock = rand(stock_min, stock_max)
@@ -51,5 +51,30 @@
item = /obj/item/clothing/head/chameleon/broken
price_min = 100
price_max = 200
stock_max = 2
availability_prob = 70
stock_min = 3
stock_max = 7
availability_prob = 100
/datum/blackmarket_item/clothing/earmuffs
name = "Earmuffs"
desc = "Protect your precious ears from security's flashbangs with this handy device."
item = /obj/item/clothing/ears/earmuffs
price_min = 100
price_max = 200
stock_min = 3
stock_max = 7
availability_prob = 100
/* commented out until someone wants to port the actual boots
* i am unsure they are in accordance with server design ideals
/datum/blackmarket_item/clothing/rocket_boots
name = "Rocket Boots"
desc = "We found a pair of jump boots and overclocked the hell out of them. No liability for grevious harm to or with a body."
item = /obj/item/clothing/shoes/bhop/rocket
price_min = 1500
price_max = 3000
stock_max = 1
availability_prob = 30
*/
@@ -14,11 +14,11 @@
name = "Box of Donk Pockets"
desc = "A well packaged box containing the favourite snack of every spacefarer."
item = /obj/item/storage/box/donkpockets
stock_min = 2
stock_max = 5
price_min = 325
price_max = 400
availability_prob = 80
stock_min = 5
stock_max = 10
price_min = 250
price_max = 350
availability_prob = 100
/datum/blackmarket_item/consumable/suspicious_pills
name = "Bottle of Suspicious Pills"
@@ -46,13 +46,43 @@
stock_max = 35
price_min = 10
price_max = 60
availability_prob = 50
availability_prob = 70
/datum/blackmarket_item/consumable/pumpup
name = "Shoddy Stimulants"
desc = "Feel the energy inside each needle!"
item = /obj/item/reagent_containers/hypospray/medipen/stimpack
stock_max = 5
price_min = 50
price_max = 150
availability_prob = 90
price_min = 80
price_max = 170
availability_prob = 70
/datum/blackmarket_item/consumable/stray_drink
name = "A random drink"
desc = "A surprise drink direcly from the counter. No refunds if the glass breaks." // it will always break if it's launched at the station
item = /obj/item/reagent_containers/food/drinks/drinkingglass
stock_min = 10
stock_max = 15
price_min = 100
price_max = 200
availability_prob = 100
// add new drinks here
var/list/counter = list(
/datum/reagent/consumable/ethanol/gintonic,
/datum/reagent/consumable/ethanol/cuba_libre,
/datum/reagent/consumable/ethanol/martini,
/datum/reagent/consumable/ethanol/b52,
/datum/reagent/consumable/ethanol/manhattan,
/datum/reagent/consumable/ethanol/bahama_mama,
/datum/reagent/consumable/ethanol/syndicatebomb,
/datum/reagent/consumable/ethanol/quadruple_sec
)
// i found no other way to fill a glass with a random reagent at runtime. and i definitely was not going to do the same done in bottle.dm
/datum/blackmarket_item/consumable/stray_drink/spawn_item(loc)
var/obj/item/reagent_containers/food/drinks/drinkingglass/drink = new item(loc)
var/picked = pick(counter)
drink.list_reagents = list()
drink.list_reagents[picked] = 50
drink.add_initial_reagents()
return drink
@@ -10,6 +10,15 @@
stock_max = 6
availability_prob = 80
/datum/blackmarket_item/misc/clear_pda
name = "Clear PDA"
desc = "Show off your style with this limited edition clear PDA!."
item = /obj/item/pda/clear
price_min = 250
price_max = 600
stock_max = 4
availability_prob = 50
/datum/blackmarket_item/misc/shoulder_holster
name = "Shoulder holster"
desc = "Yeehaw, hardboiled friends! This holster is the first step in your dream of becoming a detective and being allowed to shoot real guns!"
@@ -37,11 +46,11 @@
name = "Strange Seeds"
desc = "An Exotic Variety of seed that can contain anything from glow to acid."
item = /obj/item/seeds/random
price_min = 320
price_max = 360
price_min = 450
price_max = 650
stock_min = 2
stock_max = 5
availability_prob = 50
availability_prob = 100
/datum/blackmarket_item/misc/smugglers_satchel
name = "Smuggler's Satchel"
@@ -51,3 +60,14 @@
price_max = 1000
stock_max = 2
availability_prob = 30
/datum/blackmarket_item/misc/internals_box
name = "Internals Box"
desc = "The same one Nanotrasen gives you before starting the shift. Totally not stolen from a dead space-man floating in space."
item = /obj/item/storage/box/survival
price_min = 250
price_max = 350
stock_min = 3
stock_max = 6
availability_prob = 100
@@ -59,7 +59,7 @@
name = "Thermite Bottle"
desc = "30 units of Thermite to assist in creating a quick access point or get away!"
item = /obj/item/reagent_containers/glass/bottle/thermite
price_min = 500
price_min = 750
price_max = 1500
stock_max = 3
availability_prob = 30
@@ -68,7 +68,18 @@
name = "Science Goggles"
desc = "These glasses scan the contents of containers and projects their contents to the user in an easy-to-read format."
item = /obj/item/clothing/glasses/science
price_min = 150
price_max = 200
stock_max = 3
availability_prob = 50
price_min = 200
price_max = 300
stock_min = 3
stock_max = 7
availability_prob = 100
/datum/blackmarket_item/tool/meson_goggles
name = "Meson Goggles"
desc = "These let you see through walls and inspect other structures."
item = /obj/item/clothing/glasses/meson
price_min = 200
price_max = 300
stock_min = 3
stock_max = 7
availability_prob = 100
@@ -28,14 +28,32 @@
item = /obj/item/spear/bonespear
price_min = 200
price_max = 300
stock_max = 3
availability_prob = 60
stock_max = 0
availability_prob = 0
/datum/blackmarket_item/weapon/emp_grenade
name = "EMP Grenade"
desc = "Use this grenade for SHOCKING results!"
item = /obj/item/grenade/empgrenade
price_min = 100
price_max = 400
price_min = 300
price_max = 600
stock_max = 2
availability_prob = 50
availability_prob = 20
/datum/blackmarket_item/weapon/smoke_grenade
name = "Smoke Grenade"
desc = "Used for obcuring a large area with thick smoke."
item = /obj/item/grenade/smokebomb
price_min = 100
price_max = 300
stock_max = 3
availability_prob = 40
/datum/blackmarket_item/weapon/derringer
name = ".38 Derringer"
desc = "Compact safety! Now at a premium!"
item = /obj/item/gun/ballistic/derringer
price_min = 500
price_max = 1500
stock_max = 3
availability_prob = 30
@@ -1,5 +1,6 @@
/obj/item/blackmarket_uplink
name = "Black Market Uplink"
desc = "A mishmash of a subspace amplifier, a radio, and an analyzer. Somehow able to access the black market, with a variable inventory in limited stock at inflated prices. No refunds, customer responsible for pick-ups."
icon = 'icons/obj/blackmarket.dmi'
icon_state = "uplink"
// UI variables.
+1 -1
View File
@@ -23,7 +23,7 @@
name = "Strobe Shield"
description = "One of our Emergency Response Agents thinks there's vampires in a local station. Send him something to help with his fear of the dark and protect him, too."
reward = 3000
wanted_types = list(/obj/item/assembly/flash/shield)
wanted_types = list(/obj/item/shield/riot/flash)
/datum/bounty/item/security/sechuds
name = "Sec HUDs"
@@ -75,7 +75,7 @@
cost = 250
unit_name = "heart"
export_types = list(/obj/item/organ/heart)
exclude_types = list(/obj/item/organ/heart/cursed, /obj/item/organ/heart/cybernetic)
exclude_types = list(/obj/item/organ/heart/cursed, /obj/item/organ/heart/cybernetic/tier2, /obj/item/organ/heart/cybernetic/tier3)
/datum/export/organs/tongue
cost = 75
@@ -92,29 +92,30 @@
cost = 50 //can be replaced
unit_name = "stomach"
export_types = list(/obj/item/organ/stomach)
exclude_types = list(/obj/item/organ/stomach/cybernetic/tier2, /obj/item/organ/stomach/cybernetic/tier3)
/datum/export/organs/lungs
cost = 150
unit_name = "lungs"
export_types = list(/obj/item/organ/lungs)
exclude_types = list(/obj/item/organ/lungs/cybernetic, /obj/item/organ/lungs/cybernetic/upgraded)
export_types = list(/obj/item/organ/lungs,)
exclude_types = list(/obj/item/organ/lungs/cybernetic/tier2, /obj/item/organ/lungs/cybernetic/tier3)
/datum/export/organs/liver
cost = 175
unit_name = "liver"
export_types = list(/obj/item/organ/liver)
exclude_types = list(/obj/item/organ/liver/cybernetic, /obj/item/organ/liver/cybernetic/upgraded)
exclude_types = list(/obj/item/organ/liver/cybernetic/tier2, /obj/item/organ/liver/cybernetic/tier3)
/datum/export/organs/cybernetic
cost = 225
unit_name = "cybernetic organ"
export_types = list(/obj/item/organ/liver/cybernetic, /obj/item/organ/lungs/cybernetic, /obj/item/organ/eyes/robotic, /obj/item/organ/heart/cybernetic)
exclude_types = list(/obj/item/organ/lungs/cybernetic/upgraded, /obj/item/organ/liver/cybernetic/upgraded)
export_types = list(/obj/item/organ/liver/cybernetic/tier2, /obj/item/organ/lungs/cybernetic/tier2, /obj/item/organ/eyes/robotic/shield, /obj/item/organ/eyes/robotic/glow, /obj/item/organ/stomach/cybernetic/tier2, /obj/item/organ/heart/cybernetic/tier2)
exclude_types = list(/obj/item/organ/liver/cybernetic/tier3, /obj/item/organ/lungs/cybernetic/tier3, /obj/item/organ/eyes/robotic/xray, /obj/item/organ/eyes/robotic/thermals, /obj/item/organ/stomach/cybernetic/tier3, /obj/item/organ/heart/cybernetic/tier3)
/datum/export/organs/upgraded
cost = 275
unit_name = "upgraded cybernetic organ"
export_types = list(/obj/item/organ/lungs/cybernetic/upgraded, /obj/item/organ/liver/cybernetic/upgraded)
export_types = list(/obj/item/organ/liver/cybernetic/tier3, /obj/item/organ/lungs/cybernetic/tier3, /obj/item/organ/eyes/robotic/xray, /obj/item/organ/eyes/robotic/thermals, /obj/item/organ/stomach/cybernetic/tier3, /obj/item/organ/heart/cybernetic/tier3)
/datum/export/organs/tail // yeah have fun pulling this off someone without catching a bwoink
cost = 500
+2 -2
View File
@@ -16,7 +16,7 @@
/datum/export/weapon/riot_shield
cost = 70
unit_name = "flash shield"
export_types = list(/obj/item/assembly/flash/shield)
export_types = list(/obj/item/shield/riot/flash)
/datum/export/weapon/tele_shield
cost = 100
@@ -138,7 +138,7 @@
export_types = list(/obj/item/gun/energy/xray)
/datum/export/weapon/ioncarbine
cost = 200
cost = 200
unit_name = "ion carbine"
export_types = list(/obj/item/gun/energy/ionrifle/carbine)
+3 -3
View File
@@ -20,7 +20,7 @@
var/printed_beacons = 0 //number of beacons printed. Used to determine beacon names.
var/list/meme_pack_data
var/obj/item/supplypod_beacon/beacon //the linked supplypod beacon
var/area/landingzone = /area/quartermaster/storage //where we droppin boys
var/area/landingzone = /area/cargo/storage //where we droppin boys
var/podType = /obj/structure/closet/supplypod
var/cooldown = 0 //cooldown to prevent printing supplypod beacon spam
var/locked = TRUE //is the console locked? unlock with ID
@@ -177,9 +177,9 @@
LZ = get_turf(beacon)
beacon.update_status(SP_LAUNCH)
else if (!usingBeacon)//find a suitable supplypod landing zone in cargobay
landingzone = GLOB.areas_by_type[/area/quartermaster/storage]
landingzone = GLOB.areas_by_type[/area/cargo/storage]
if (!landingzone)
WARNING("[src] couldnt find a Quartermaster/Storage (aka cargobay) area on the station, and as such it has set the supplypod landingzone to the area it resides in.")
WARNING("[src] couldnt find \"/area/cargo/storage\" (aka cargobay) area on the station, and as such it has set the supplypod landingzone to the area it resides in.")
landingzone = get_area(src)
for(var/turf/open/floor/T in landingzone.contents)//uses default landing zone
if(is_blocked_turf(T))
+5 -1
View File
@@ -15,13 +15,17 @@
var/special_enabled = FALSE
var/DropPodOnly = FALSE //only usable by the Bluespace Drop Pod via the express cargo console
var/admin_spawned = FALSE //Can only an admin spawn this crate?
// this might be all in all unnecessary with current code if some changes are made
var/goody = PACK_GOODY_NONE //Small items can be grouped into a single crate.They also come in a closet/lockbox instead of a full crate, so the 700 min doesn't apply
var/can_private_buy = TRUE //Can it be purchased privately by each crewmember?
/datum/supply_pack/proc/generate(atom/A, datum/bank_account/paying_account)
var/obj/structure/closet/crate/C
if(paying_account)
C = new /obj/structure/closet/crate/secure/owned(A, paying_account)
if(ispath(crate_type, /obj/structure/closet/secure_closet/goodies)) // lets ensure private orders don't come in crates when the original one comes in lockers
C = new /obj/structure/closet/secure_closet/goodies/owned(A, paying_account) // that would lead to infinite money exploits
else
C = new /obj/structure/closet/crate/secure/owned(A, paying_account)
C.name = "[crate_name] - Purchased by [paying_account.account_holder]"
else
C = new crate_type(A)
+32
View File
@@ -232,3 +232,35 @@
desc = "Contains one hellgun, an old pattern of laser gun infamous for its ability to horribly disfigure targets with burns. Technically violates the Space Geneva Convention when used on humanoids."
cost = 1500
contains = list(/obj/item/gun/energy/laser/hellgun)
/datum/supply_pack/security/armory/derringerclassic
name = "Holdout Crate"
crate_name = "dented crate"
desc = "Hey kid.. c'mere. Boss says we need to offload these, to any buyer, no questions asked. You pay us, we give you three of these guns, no strings attached. Locks are to ensure they get to PAYING customers."
cost = 2000
contraband = TRUE
can_private_buy = TRUE
contains = list(/obj/item/storage/fancy/cigarettes/derringer/smuggled,
/obj/item/storage/fancy/cigarettes/derringer/smuggled,
/obj/item/storage/fancy/cigarettes/derringer/smuggled,
/obj/item/storage/wallet)
/datum/supply_pack/security/armory/esoteric_arms
name = "Esoteric Armory Shipment"
desc = "Well.. you're an agent of taste, I can tell that much. For the right price.. we could see our way clear to send you one of our more... unique weapons."
hidden = TRUE
cost = 10000
can_private_buy = TRUE
crate_name = "dusty crate"
var/num_contained = 1
contains = list(/obj/item/gun/ballistic/shotgun/leveraction,
/obj/item/storage/fancy/cigarettes/derringer/gold,
/obj/item/gun/ballistic/revolver/nagant,
/obj/item/gun/ballistic/automatic/pistol/APS,
/obj/item/gun/ballistic/revolver/golden)
/datum/supply_pack/security/armory/esoteric_arms/fill(obj/structure/closet/crate/C)
var/list/L = contains.Copy()
for(var/i in 1 to num_contained)
var/item = pick_n_take(L)
new item(C)
+1
View File
@@ -81,3 +81,4 @@
desc = "Contains one standard epinephrine medipen and one standard emergency first-aid kit medipen. For when you want to prepare for the worst."
cost = 500
contains = list(/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/hypospray/medipen/ekit)
+11 -23
View File
@@ -14,73 +14,61 @@
//////////////////////////////////////////////////////////////////////////////
/datum/supply_pack/materials/cardboard50
goody = PACK_GOODY_PUBLIC
crate_type = /obj/structure/closet/secure_closet/goodies
name = "50 Cardboard Sheets"
desc = "Create a bunch of boxes."
cost = 300 //thrice their export value
contains = list(/obj/item/stack/sheet/cardboard/fifty)
/datum/supply_pack/materials/glass50
goody = PACK_GOODY_PUBLIC
crate_type = /obj/structure/closet/secure_closet/goodies
name = "50 Glass Sheets"
desc = "Let some nice light in with fifty glass sheets!"
cost = 300 //double their export value
contains = list(/obj/item/stack/sheet/glass/fifty)
/datum/supply_pack/materials/metal50
goody = PACK_GOODY_PUBLIC
crate_type = /obj/structure/closet/secure_closet/goodies
name = "50 Metal Sheets"
desc = "Any construction project begins with a good stack of fifty metal sheets!"
cost = 300 //double their export value
contains = list(/obj/item/stack/sheet/metal/fifty)
/datum/supply_pack/materials/plasteel20
goody = PACK_GOODY_PUBLIC
crate_type = /obj/structure/closet/secure_closet/goodies
name = "20 Plasteel Sheets"
desc = "Reinforce the station's integrity with twenty plasteel sheets!"
cost = 4000
contains = list(/obj/item/stack/sheet/plasteel/twenty)
/datum/supply_pack/materials/plastic50
goody = PACK_GOODY_PUBLIC
crate_type = /obj/structure/closet/secure_closet/goodies
name = "50 Plastic Sheets"
desc = "Build a limitless amount of toys with fifty plastic sheets!"
cost = 200 // double their export
contains = list(/obj/item/stack/sheet/plastic/twenty)
/datum/supply_pack/materials/sandstone30
goody = PACK_GOODY_PUBLIC
crate_type = /obj/structure/closet/secure_closet/goodies
name = "30 Sandstone Blocks"
desc = "Neither sandy nor stoney, these thirty blocks will still get the job done."
cost = 150 // five times their export
contains = list(/obj/item/stack/sheet/mineral/sandstone/thirty)
/datum/supply_pack/materials/wood50
goody = PACK_GOODY_PUBLIC
name = "50 Wood Planks"
desc = "Turn cargo's boring metal groundwork into beautiful panelled flooring and much more with fifty wooden planks!"
/datum/supply_pack/materials/wood20
crate_type = /obj/structure/closet/secure_closet/goodies
name = "20 Wood Planks"
desc = "Turn cargo's boring metal groundwork into beautiful panelled flooring and much more with twenty wooden planks!"
cost = 400 // 6-7 planks shy from having equal import/export prices
contains = list(/obj/item/stack/sheet/mineral/wood/twenty)
/datum/supply_pack/materials/rcdammo
goody = PACK_GOODY_PUBLIC
crate_type = /obj/structure/closet/secure_closet/goodies
name = "Large RCD ammo Single-Pack"
desc = "A single large compressed RCD matter pack, to help with any holes or projects people might be working on."
cost = 600
contains = list(/obj/item/rcd_ammo/large)
/datum/supply_pack/materials/rawlumber
name = "50 Towercap Logs"
desc = "Raw logs from towercaps. Contains fifty logs."
cost = 1000
contains = list(/obj/item/grown/log)
crate_name = "lumber crate"
/datum/supply_pack/materials/rawlumber/generate()
. = ..()
for(var/i in 1 to 49)
new /obj/item/grown/log(.)
//////////////////////////////////////////////////////////////////////////////
///////////////////////////// Canisters //////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
+1 -1
View File
@@ -370,7 +370,7 @@
//////////////////////////////////////////////////////////////////////////////
/datum/supply_pack/misc/carpet
goody = PACK_GOODY_PUBLIC
crate_type = /obj/structure/closet/secure_closet/goodies
name = "Classic Carpet Single-Pack"
desc = "Plasteel floor tiles getting on your nerves? This 50 units stack of extra soft carpet will tie any room together."
cost = 200
+8 -10
View File
@@ -80,15 +80,15 @@
/datum/supply_pack/security/russianclothing
name = "Russian Surplus Clothing"
desc = "An old russian crate full of surplus armor that they used to use! Has two sets of bulletproff armor, a few union suits and some warm hats!"
desc = "An old russian crate full of surplus armor that they used to use! Has two sets of bulletproof armor, a few union suits and some warm hats!"
contraband = TRUE
cost = 5750 // Its basicly sec suits, good boots/gloves
contains = list(/obj/item/clothing/suit/armor/navyblue/russian,
/obj/item/clothing/suit/armor/navyblue/russian,
contains = list(/obj/item/clothing/under/syndicate/rus_army,
/obj/item/clothing/under/syndicate/rus_army,
/obj/item/clothing/shoes/combat,
/obj/item/clothing/shoes/combat,
/obj/item/clothing/head/ushanka,
/obj/item/clothing/head/ushanka,
/obj/item/clothing/head/helmet/rus_helmet,
/obj/item/clothing/head/helmet/rus_helmet,
/obj/item/clothing/suit/armor/bulletproof,
/obj/item/clothing/suit/armor/bulletproof,
/obj/item/clothing/head/helmet/alt,
@@ -98,23 +98,21 @@
/obj/item/clothing/mask/gas,
/obj/item/clothing/mask/gas)
crate_name = "surplus russian clothing"
crate_type = /obj/structure/closet/crate/internals
/datum/supply_pack/security/russian_partisan
name = "Russian Partisan Gear"
desc = "An old russian partisan equipment crate, comes with a full russian outfit, a loaded surplus rifle and a second magazine."
contraband = TRUE
access = FALSE
cost = 6500
contains = list(/obj/item/clothing/suit/armor/navyblue/russian,
/obj/item/clothing/shoes/combat,
/obj/item/clothing/head/ushanka,
/obj/item/clothing/head/helmet/rus_helmet,
/obj/item/clothing/suit/armor/bulletproof,
/obj/item/clothing/head/helmet/alt,
/obj/item/clothing/gloves/tackler/combat/insulated,
/obj/item/clothing/under/syndicate/rus_army,
/obj/item/clothing/mask/gas)
crate_name = "surplus russian gear"
crate_type = /obj/structure/closet/crate/internals
/datum/supply_pack/security/russian_partisan/fill(obj/structure/closet/crate/C)
..()
@@ -241,7 +239,7 @@
access = FALSE
access_any = list(ACCESS_SECURITY, ACCESS_FORENSICS_LOCKERS)
contains = list(/obj/item/ammo_box/c38/dumdum)
crate_name = ".38 match crate"
crate_name = ".38 dumdum crate"
/datum/supply_pack/security/match
name = ".38 Match Grade Speedloader"
+1 -1
View File
@@ -171,7 +171,7 @@
/datum/supply_pack/service/replacementdb
name = "Replacement Defensive Bar Shotgun"
desc = "Someone stole the Bartender's twin-barreled possession? Give them another one at a significant markup. Comes with one unused double-barrel shotgun, shells not included. Requires bartender access to open."
desc = "Someone stole the Bartender's twin-barreled possession? Give them another one at a significant markup. Comes with one unused double-barrel shotgun, additional shells not included. Requires bartender access to open."
cost = 2200
access = ACCESS_BAR
contraband = TRUE
+24 -19
View File
@@ -54,7 +54,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/tip_delay = 500 //tip delay in milliseconds
//Antag preferences
var/list/be_special = list() //Special role selection
var/list/be_special = list() //Special role selection. ROLE_SYNDICATE being missing means they will never be antag!
var/tmp/old_be_special = 0 //Bitflag version of be_special, used to update old savefiles and nothing more
//If it's 0, that's good, if it's anything but 0, the owner of this prefs file's antag choices were,
//autocorrected this round, not that you'd need to check that.
@@ -148,11 +148,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
//Job preferences 2.0 - indexed by job title , no key or value implies never
var/list/job_preferences = list()
// Want randomjob if preferences already filled - Donkie
// Want randomjob if preferences already filled - Donkie
var/joblessrole = BERANDOMJOB //defaults to 1 for fewer assistants
// 0 = character settings, 1 = game preferences
var/current_tab = 0
var/current_tab = SETTINGS_TAB
var/unlock_content = 0
@@ -227,6 +227,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/persistent_scars = TRUE
///If we want to broadcast deadchat connect/disconnect messages
var/broadcast_login_logout = TRUE
///What outfit typepaths we've favorited in the SelectEquipment menu
var/list/favorite_outfits = list()
/// We have 5 slots for persistent scars, if enabled we pick a random one to load (empty by default) and scars at the end of the shift if we survived as our original person
var/list/scars_list = list("1" = "", "2" = "", "3" = "", "4" = "", "5" = "")
/// Which of the 5 persistent scar slots we randomly roll to load for this round, if enabled. Actually rolled in [/datum/preferences/proc/load_character(slot)]
@@ -274,13 +276,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
update_preview_icon(current_tab)
var/list/dat = list("<center>")
dat += "<a href='?_src_=prefs;preference=tab;tab=0' [current_tab == 0 ? "class='linkOn'" : ""]>Character Settings</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=2' [current_tab == 2 ? "class='linkOn'" : ""]>Character Appearance</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=3' [current_tab == 3 ? "class='linkOn'" : ""]>Character Speech</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=4' [current_tab == 4 ? "class='linkOn'" : ""]>Loadout</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=1' [current_tab == 1 ? "class='linkOn'" : ""]>Game Preferences</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=5' [current_tab == 5 ? "class='linkOn'" : ""]>Content Preferences</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=6' [current_tab == 6 ? "class='linkOn'" : ""]>Keybindings</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=[SETTINGS_TAB]' [current_tab == SETTINGS_TAB ? "class='linkOn'" : ""]>Character Settings</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=[APPEARANCE_TAB]' [current_tab == APPEARANCE_TAB ? "class='linkOn'" : ""]>Character Appearance</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=[SPEECH_TAB]' [current_tab == SPEECH_TAB ? "class='linkOn'" : ""]>Character Speech</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=[LOADOUT_TAB]' [current_tab == LOADOUT_TAB ? "class='linkOn'" : ""]>Loadout</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=[GAME_PREFERENCES_TAB]' [current_tab == GAME_PREFERENCES_TAB ? "class='linkOn'" : ""]>Game Preferences</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=[CONTENT_PREFERENCES_TAB]' [current_tab == CONTENT_PREFERENCES_TAB ? "class='linkOn'" : ""]>Content Preferences</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=[KEYBINDINGS_TAB]' [current_tab == KEYBINDINGS_TAB ? "class='linkOn'" : ""]>Keybindings</a>"
if(!path)
dat += "<div class='notice'>Please create an account to save your preferences</div>"
@@ -290,7 +292,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<HR>"
switch(current_tab)
if (0) // Character Settings#
if(SETTINGS_TAB) // Character Settings#
if(path)
var/savefile/S = new /savefile(path)
if(S)
@@ -366,7 +368,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</tr></table>"
//Character Appearance
if(2)
if(APPEARANCE_TAB)
if(path)
var/savefile/S = new /savefile(path)
if(S)
@@ -670,7 +672,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td>"
dat += "</tr></table>"
if(3)
if(SPEECH_TAB)
if(path)
var/savefile/S = new /savefile(path)
if(S)
@@ -700,7 +702,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td>"
dat += "</tr></table>"
if (1) // Game Preferences
if(GAME_PREFERENCES_TAB) // Game Preferences
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>General Settings</h2>"
dat += "<b>UI Style:</b> <a href='?_src_=prefs;task=input;preference=ui'>[UI_style]</a><br>"
@@ -851,6 +853,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
for (var/i in GLOB.special_roles)
if(i == ROLE_NO_ANTAGONISM)
dat += "<b>DISABLE ALL ANTAGONISM</b> <a href='?_src_=prefs;preference=be_special;be_special_type=[i]'>[(i in be_special) ? "YES" : "NO"]</a><br>"
continue
if(jobban_isbanned(user, i))
dat += "<b>Be [capitalize(i)]:</b> <a href='?_src_=prefs;jobbancheck=[i]'>BANNED</a><br>"
else
@@ -863,12 +868,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(days_remaining)
dat += "<b>Be [capitalize(i)]:</b> <font color=red> \[IN [days_remaining] DAYS]</font><br>"
else
dat += "<b>Be [i == ROLE_SYNDICATE ? "Antag": capitalize(i)]:</b> <a href='?_src_=prefs;preference=be_special;be_special_type=[i]'>[(i in be_special) ? "Enabled" : "Disabled"]</a><br>"
dat += "<b>Be [capitalize(i)]:</b> <a href='?_src_=prefs;preference=be_special;be_special_type=[i]'>[(i in be_special) ? "Enabled" : "Disabled"]</a><br>"
dat += "<b>Midround Antagonist:</b> <a href='?_src_=prefs;preference=allow_midround_antag'>[(toggles & MIDROUND_ANTAG) ? "Enabled" : "Disabled"]</a><br>"
dat += "<br>"
if(4)
if(LOADOUT_TAB)
//calculate your gear points from the chosen item
gear_points = CONFIG_GET(number/initial_gear_points)
var/list/chosen_gear = loadout_data["SAVE_[loadout_slot]"]
@@ -987,7 +992,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td><td><font size=2><i>[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description] Progress: [min(progress_made, unlockable.progress_required)]/[unlockable.progress_required]</i></font></td></tr>"
dat += "</table>"
if(5) // Content preferences
if(CONTENT_PREFERENCES_TAB) // Content preferences
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>Fetish content prefs</h2>"
dat += "<b>Arousal:</b><a href='?_src_=prefs;preference=arousable'>[arousable == TRUE ? "Enabled" : "Disabled"]</a><BR>"
@@ -1011,7 +1016,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Automatic Wagging:</b> <a href='?_src_=prefs;preference=auto_wag'>[(cit_toggles & NO_AUTO_WAG) ? "Disabled" : "Enabled"]</a><br>"
dat += "</tr></table>"
dat += "<br>"
if(6) // Custom keybindings
if(KEYBINDINGS_TAB) // Custom keybindings
dat += "<b>Keybindings:</b> <a href='?_src_=prefs;preference=hotkeys'>[(hotkeys) ? "Hotkeys" : "Input"]</a><br>"
dat += "Keybindings mode controls how the game behaves with tab and map/input focus.<br>If it is on <b>Hotkeys</b>, the game will always attempt to force you to map focus, meaning keypresses are sent \
directly to the map instead of the input. You will still be able to use the command bar, but you need to tab to do it every time you click on the game map.<br>\
@@ -2718,7 +2723,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
save_character()
if("tab")
if (href_list["tab"])
if(href_list["tab"])
current_tab = text2num(href_list["tab"])
if(href_list["preference"] == "gear")
if(href_list["clear_loadout"])
+19 -1
View File
@@ -5,7 +5,7 @@
// You do not need to raise this if you are adding new values that have sane defaults.
// Only raise this value when changing the meaning/format/name/layout of an existing value
// where you would want the updater procs below to run
#define SAVEFILE_VERSION_MAX 48
#define SAVEFILE_VERSION_MAX 50
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
@@ -288,6 +288,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
if(current_version < 48) //unlockable loadout items but we need to clear bad data from a mistake
S["unlockable_loadout"] = list()
if(current_version < 50)
var/list/L
S["be_special"] >> L
if(islist(L))
L -= ROLE_SYNDICATE
S["be_special"] << L
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
if(!ckey)
return
@@ -378,6 +385,15 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["auto_ooc"] >> auto_ooc
S["no_tetris_storage"] >> no_tetris_storage
//favorite outfits
S["favorite_outfits"] >> favorite_outfits
var/list/parsed_favs = list()
for(var/typetext in favorite_outfits)
var/datum/outfit/path = text2path(typetext)
if(ispath(path)) //whatever typepath fails this check probably doesn't exist anymore
parsed_favs += path
favorite_outfits = uniqueList(parsed_favs)
//try to fix any outdated data if necessary
if(needs_update >= 0)
@@ -427,6 +443,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
no_tetris_storage = sanitize_integer(no_tetris_storage, 0, 1, initial(no_tetris_storage))
key_bindings = sanitize_islist(key_bindings, list())
modless_key_bindings = sanitize_islist(modless_key_bindings, list())
favorite_outfits = SANITIZE_LIST(favorite_outfits)
verify_keybindings_valid() // one of these days this will runtime and you'll be glad that i put it in a different proc so no one gets their saves wiped
@@ -528,6 +545,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["pda_skin"], pda_skin)
WRITE_FILE(S["key_bindings"], key_bindings)
WRITE_FILE(S["modless_key_bindings"], modless_key_bindings)
WRITE_FILE(S["favorite_outfits"], favorite_outfits)
//citadel code
WRITE_FILE(S["screenshake"], screenshake)
+4
View File
@@ -3,6 +3,10 @@
set desc = "Authorizes your account in the panic bunker of any servers connected to this function."
set category = "OOC"
if(prefs.db_flags & DB_FLAG_AGE_CONFIRMATION_INCOMPLETE)
to_chat(src, "<span class='danger'>You are not age verified.</span>")
return
if(autobunker_last_try + 5 SECONDS > world.time)
to_chat(src, "<span class='danger'>Function on cooldown, try again in 5 seconds.</span>")
return
+2 -3
View File
@@ -83,8 +83,7 @@
standard_outfit_options = list()
for(var/path in subtypesof(/datum/outfit/job))
var/datum/outfit/O = path
if(initial(O.can_be_admin_equipped))
standard_outfit_options[initial(O.name)] = path
standard_outfit_options[initial(O.name)] = path
sortTim(standard_outfit_options, /proc/cmp_text_asc)
outfit_options = standard_outfit_options
@@ -277,7 +276,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/under/chameleon)
item_state = "bl_suit"
desc = "It's a plain jumpsuit. It has a small dial on the wrist."
sensor_mode = SENSOR_OFF //Hey who's this guy on the Syndicate Shuttle??
random_sensor = FALSE
sensor_flags = NONE
resistance_flags = NONE
can_adjust = FALSE
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
+3 -5
View File
@@ -233,7 +233,7 @@
/obj/item/clothing/examine(mob/user)
. = ..()
if(damaged_clothes == CLOTHING_SHREDDED)
. += "<span class='warning'><b>It is completely shredded and requires mending before it can be worn again!</b></span>"
. += "<span class='warning'><b>It is completely shredded and requires mending!</b></span>"
return
for(var/zone in damage_by_parts)
var/pct_damage_part = damage_by_parts[zone] / limb_integrity * 100
@@ -437,12 +437,10 @@ BLIND // can't see anything
damaged_clothes = CLOTHING_SHREDDED
body_parts_covered = NONE
name = "shredded [initial(name)]"
slot_flags = NONE
update_clothes_damaged_state()
update_clothes_damaged_state(CLOTHING_SHREDDED)
if(ismob(loc))
var/mob/M = loc
M.visible_message("<span class='danger'>[M]'s [src.name] falls off, completely shredded!</span>", "<span class='warning'><b>Your [src.name] falls off, completely shredded!</b></span>", vision_distance = COMBAT_MESSAGE_RANGE)
M.dropItemToGround(src)
M.visible_message("<span class='danger'>[M]'s [src.name] is completely shredded!</span>", "<span class='userdanger'>Your [src.name] is completely shredded!</span>", vision_distance = COMBAT_MESSAGE_RANGE)
else
..()
@@ -358,6 +358,12 @@
..()
user.cure_blind("blindfold_[REF(src)]")
/obj/item/clothing/glasses/fakeblindfold
name = "thin blindfold"
desc = "Covers the eyes, but not thick enough to obscure vision. Mostly for aesthetic."
icon_state = "blindfoldwhite"
item_state = "blindfoldwhite"
/obj/item/clothing/glasses/sunglasses/blindfold/white
name = "blind personnel blindfold"
desc = "Indicates that the wearer suffers from blindness."
+32 -2
View File
@@ -78,10 +78,40 @@
speech_args[SPEECH_MESSAGE] = trim(message)
/obj/item/clothing/mask/joy
name = "joy mask"
desc = "Express your happiness or hide your sorrows with this laughing face with crying tears of joy cutout."
name = "Emotional Mask"
desc = "Express your happiness or hide your sorrows with this modular cutout."
icon_state = "joy"
clothing_flags = ALLOWINTERNALS
mutantrace_variation = STYLE_MUZZLE
actions_types = list(/datum/action/item_action/adjust)
var/static/list/joymask_designs = list()
/obj/item/clothing/mask/joy/Initialize(mapload)
. = ..()
joymask_designs = list(
"Joy" = image(icon = src.icon, icon_state = "joy"),
"Flushed" = image(icon = src.icon, icon_state = "flushed"),
"Pensive" = image(icon = src.icon, icon_state = "pensive"),
"Angry" = image(icon = src.icon, icon_state = "angry"),
)
/obj/item/clothing/mask/joy/ui_action_click(mob/user)
if(!istype(user) || user.incapacitated())
return
var/static/list/options = list("Joy" = "joy", "Flushed" = "flushed", "Pensive" = "pensive","Angry" ="angry")
var/choice = show_radial_menu(user, src, joymask_designs, custom_check = FALSE, radius = 36, require_near = TRUE)
if(src && choice && !user.incapacitated() && in_range(user,src))
icon_state = options[choice]
user.update_inv_wear_mask()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
to_chat(user, "<span class='notice'>Your Joy mask now has a [choice] Emotion!</span>")
return 1
/obj/item/clothing/mask/pig
name = "pig mask"
+1 -1
View File
@@ -145,7 +145,7 @@
/obj/item/clothing/suit/armor/riot
name = "riot suit"
desc = "A suit of semi-flexible polycarbonate body armor with heavy padding to protect against melee attacks. Helps the wearer resist shoving in close quarters."
icon_state = "riot"
icon_state = "swat"
item_state = "swat_suit"
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+104 -25
View File
@@ -7,11 +7,14 @@
slot_flags = ITEM_SLOT_ICLOTHING
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
mutantrace_variation = STYLE_DIGITIGRADE|USE_TAUR_CLIP_MASK
limb_integrity = 30
limb_integrity = 120
var/fitted = FEMALE_UNIFORM_FULL // For use in alternate clothing styles for women
var/has_sensor = HAS_SENSORS // For the crew computer
var/random_sensor = TRUE
var/sensor_flags = SENSOR_RANDOM
var/sensor_mode = NO_SENSORS
var/sensor_mode_intended = NO_SENSORS //if sensors become damaged and are repaired later, it will revert to the user's intended preferences
var/sensormaxintegrity = 200 //if this is zero, then our sensors can only be destroyed by shredded clothing
var/sensordamage = 0 //how much damage did our sensors take?
var/can_adjust = TRUE
var/adjusted = NORMAL_STYLE
var/alt_covers_chest = FALSE // for adjusted/rolled-down jumpsuits, FALSE = exposes chest and arms, TRUE = exposes arms only
@@ -31,30 +34,76 @@
. += accessory_overlay
/obj/item/clothing/under/attackby(obj/item/I, mob/user, params)
if((has_sensor == BROKEN_SENSORS) && istype(I, /obj/item/stack/cable_coil))
if(damaged_clothes)
to_chat(user,"<span class='warning'>You should repair the damage done to [src] first.</span>")
if((sensordamage || (has_sensor < HAS_SENSORS && has_sensor != NO_SENSORS)) && istype(I, /obj/item/stack/cable_coil))
if(damaged_clothes == CLOTHING_SHREDDED)
to_chat(user,"<span class='warning'>[src] is too damaged to have its suit sensors repaired! Repair it first.</span>")
return 0
var/obj/item/stack/cable_coil/C = I
I.use_tool(src, user, 0, 1)
has_sensor = HAS_SENSORS
sensordamage = 0
sensor_mode = sensor_mode_intended
to_chat(user,"<span class='notice'>You repair the suit sensors on [src] with [C].</span>")
return 1
if(!attach_accessory(I, user))
return ..()
/obj/item/clothing/under/take_damage_zone(def_zone, damage_amount, damage_type, armour_penetration)
..()
if(sensormaxintegrity == 0 || has_sensor == NO_SENSORS || sensordamage >= sensormaxintegrity) return //sensors are invincible if max integrity is 0
var/damage_dealt = take_damage(damage_amount * 0.1, damage_type, armour_penetration, FALSE) * 10 // only deal 10% of the damage to the general integrity damage, then multiply it by 10 so we know how much to deal to limb
sensordamage += damage_dealt
var/integ = has_sensor
var/newinteg = sensorintegrity()
if(newinteg != integ)
if(newinteg < integ && iscarbon(src.loc)) //the first check is to see if for some inexplicable reason the attack healed our suit sensors
var/mob/living/carbon/C = src.loc
switch(newinteg)
if(DAMAGED_SENSORS_VITALS)
to_chat(C,"<span class='warning'>Your tracking beacon on your suit sensors have shorted out!</span>")
if(DAMAGED_SENSORS_LIVING)
to_chat(C,"<span class='warning'>Your vital tracker on your suit sensors have shorted out!</span>")
if(BROKEN_SENSORS)
to_chat(C,"<span class='userdanger'>Your suit sensors have shorted out completely!</span>")
updatesensorintegrity(newinteg)
/obj/item/clothing/under/proc/sensorintegrity()
var/percentage = sensordamage/sensormaxintegrity //calculate the percentage of how much damage taken
if(percentage < SENSOR_INTEGRITY_COORDS) return HAS_SENSORS
else if(percentage < SENSOR_INTEGRITY_VITALS) return DAMAGED_SENSORS_VITALS
else if(percentage < SENSOR_INTEGRITY_BINARY) return DAMAGED_SENSORS_LIVING
else return BROKEN_SENSORS
/obj/item/clothing/under/proc/updatesensorintegrity(integ = HAS_SENSORS)
if(sensormaxintegrity == 0 || has_sensor == NO_SENSORS) return //sanity check
has_sensor = integ
switch(has_sensor)
if(HAS_SENSORS)
sensor_mode = sensor_mode_intended
if(DAMAGED_SENSORS_VITALS)
if(sensor_mode > SENSOR_VITALS) sensor_mode = SENSOR_VITALS
if(DAMAGED_SENSORS_LIVING)
if(sensor_mode > SENSOR_LIVING) sensor_mode = SENSOR_LIVING
if(BROKEN_SENSORS)
sensor_mode = NO_SENSORS
/obj/item/clothing/under/update_clothes_damaged_state()
..()
if(ismob(loc))
var/mob/M = loc
M.update_inv_w_uniform()
if(has_sensor > NO_SENSORS)
if(has_sensor > NO_SENSORS && damaged_clothes == CLOTHING_SHREDDED)
has_sensor = BROKEN_SENSORS
sensordamage = sensormaxintegrity
/obj/item/clothing/under/New()
if(random_sensor)
if(sensor_flags & SENSOR_RANDOM)
//make the sensor mode favor higher levels, except coords.
sensor_mode = pick(SENSOR_OFF, SENSOR_LIVING, SENSOR_LIVING, SENSOR_VITALS, SENSOR_VITALS, SENSOR_VITALS, SENSOR_COORDS, SENSOR_COORDS)
sensor_mode_intended = sensor_mode
..()
/obj/item/clothing/under/equipped(mob/user, slot)
@@ -143,9 +192,14 @@
. += "Alt-click on [src] to wear it normally."
else
. += "Alt-click on [src] to wear it casually."
if (has_sensor == BROKEN_SENSORS)
. += "Its sensors appear to be shorted out."
else if(has_sensor > NO_SENSORS)
switch(has_sensor)
if(BROKEN_SENSORS)
. += "<span class='warning'>Its sensors appear to be shorted out completely. It can be repaired using cable.</span>"
if(DAMAGED_SENSORS_LIVING)
. += "<span class='warning'>Its sensors appear to have its tracking beacon and vital tracker broken. It can be repaired using cable.</span>"
if(DAMAGED_SENSORS_VITALS)
. += "<span class='warning'>Its sensors appear to have its tracking beacon broken. It can be repaired using cable.</span>"
if(has_sensor > NO_SENSORS)
switch(sensor_mode)
if(SENSOR_OFF)
. += "Its sensors appear to be disabled."
@@ -167,12 +221,12 @@
return
if (!can_use(M))
return
if(src.has_sensor == LOCKED_SENSORS)
to_chat(usr, "The controls are locked.")
return 0
if(src.has_sensor == BROKEN_SENSORS)
to_chat(usr, "The sensors have shorted out!")
return 0
if(src.sensor_flags & SENSOR_LOCKED)
to_chat(usr, "The controls are locked.")
return 0
if(src.has_sensor <= NO_SENSORS)
to_chat(usr, "This suit does not have any sensors.")
return 0
@@ -182,18 +236,34 @@
if(get_dist(usr, src) > 1)
to_chat(usr, "<span class='warning'>You have moved too far away!</span>")
return
sensor_mode = modes.Find(switchMode) - 1
sensor_mode_intended = modes.Find(switchMode) - 1
if (src.loc == usr)
switch(sensor_mode)
switch(sensor_mode_intended)
if(0)
to_chat(usr, "<span class='notice'>You disable your suit's remote sensing equipment.</span>")
sensor_mode = sensor_mode_intended
if(1)
to_chat(usr, "<span class='notice'>Your suit will now only report whether you are alive or dead.</span>")
sensor_mode = sensor_mode_intended
if(2)
to_chat(usr, "<span class='notice'>Your suit will now only report your exact vital lifesigns.</span>")
if(src.has_sensor == DAMAGED_SENSORS_LIVING)
to_chat(usr, "<span class='warning'>Your suit's vital tracker is broken, so it will only report whether you are alive or dead.</span>")
sensor_mode = SENSOR_LIVING
else
to_chat(usr, "<span class='notice'>Your suit will now only report your exact vital lifesigns.</span>")
sensor_mode = sensor_mode_intended
if(3)
to_chat(usr, "<span class='notice'>Your suit will now report your exact vital lifesigns as well as your coordinate position.</span>")
switch(src.has_sensor)
if(DAMAGED_SENSORS_LIVING)
to_chat(usr, "<span class='warning'>Your suit's tracking beacon and vital tracker is broken, so it will only report whether you are alive or dead.</span>")
sensor_mode = SENSOR_LIVING
if(DAMAGED_SENSORS_VITALS)
to_chat(usr, "<span class='warning'>Your suit's tracking beacon is broken, so it will only report your vital lifesigns.</span>")
sensor_mode = SENSOR_VITALS
if(HAS_SENSORS)
to_chat(usr, "<span class='notice'>Your suit will now report your exact vital lifesigns as well as your coordinate position.</span>")
sensor_mode = sensor_mode_intended
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
@@ -210,19 +280,28 @@
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
if(has_sensor == LOCKED_SENSORS)
to_chat(user, "The controls are locked.")
return
if(has_sensor == BROKEN_SENSORS)
to_chat(user, "The sensors have shorted out!")
return
if(src.has_sensor == BROKEN_SENSORS)
to_chat(usr, "The sensors have shorted out!")
return 0
if(src.sensor_flags & SENSOR_LOCKED)
to_chat(usr, "The controls are locked.")
return 0
if(has_sensor <= NO_SENSORS)
to_chat(user, "This suit does not have any sensors.")
return
sensor_mode = SENSOR_COORDS
sensor_mode_intended = SENSOR_COORDS
to_chat(user, "<span class='notice'>Your suit will now report your exact vital lifesigns as well as your coordinate position.</span>")
switch(src.has_sensor)
if(DAMAGED_SENSORS_LIVING)
to_chat(usr, "<span class='warning'>Your suit's tracking beacon and vital tracker is broken, so it will only report whether you are alive or dead.</span>")
sensor_mode = SENSOR_LIVING
if(DAMAGED_SENSORS_VITALS)
to_chat(usr, "<span class='warning'>Your suit's tracking beacon is broken, so it will only report your vital lifesigns.</span>")
sensor_mode = SENSOR_VITALS
if(HAS_SENSORS)
to_chat(usr, "<span class='notice'>Your suit will now report your exact vital lifesigns as well as your coordinate position.</span>")
sensor_mode = sensor_mode_intended
if(ishuman(user))
var/mob/living/carbon/human/H = user
@@ -59,7 +59,7 @@
item_state = "captain_envirosuit"
armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95, "wound" = 15)
sensor_mode = SENSOR_COORDS
random_sensor = FALSE
sensor_flags = NONE
/obj/item/clothing/under/plasmaman/mime
name = "mime envirosuit"
@@ -5,7 +5,7 @@
item_state = "security_envirosuit"
armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95, "wound" = 10)
sensor_mode = SENSOR_COORDS
random_sensor = FALSE
sensor_flags = NONE
/obj/item/clothing/under/plasmaman/security/warden
name = "warden plasma envirosuit"
+1 -1
View File
@@ -5,7 +5,7 @@
item_state = "b_suit"
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 15)
sensor_mode = SENSOR_COORDS
random_sensor = FALSE
sensor_flags = NONE
/obj/item/clothing/under/rank/captain/util
name = "command utility uniform"
+1 -1
View File
@@ -12,7 +12,7 @@
strip_delay = 50
alt_covers_chest = TRUE
sensor_mode = SENSOR_COORDS
random_sensor = FALSE
sensor_flags = NONE
/obj/item/clothing/under/rank/security/officer
name = "security jumpsuit"
+4 -4
View File
@@ -23,16 +23,15 @@
name = "prison jumpsuit"
desc = "It's standardised Nanotrasen prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position."
icon_state = "prisoner"
item_state = "o_suit"
has_sensor = LOCKED_SENSORS
item_state = "prisoner"
sensor_mode = SENSOR_COORDS
random_sensor = FALSE
sensor_flags = SENSOR_LOCKED
/obj/item/clothing/under/rank/prisoner/skirt
name = "prison jumpskirt"
desc = "It's standardised Nanotrasen prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position."
icon_state = "prisoner_skirt"
item_state = "o_suit"
item_state = "prisoner_skirt"
body_parts_covered = CHEST|GROIN|ARMS
can_adjust = FALSE
fitted = FEMALE_UNIFORM_TOP
@@ -166,6 +165,7 @@
/obj/item/clothing/under/misc/gear_harness
name = "gear harness"
desc = "A simple, inconspicuous harness replacement for a jumpsuit."
limb_integrity = 180
icon_state = "gear_harness"
item_state = "gear_harness"
can_adjust = TRUE
+9 -6
View File
@@ -19,18 +19,21 @@
var/list/safe_area_types = typecacheof(list(
/area/ai_monitored/turret_protected/ai,
/area/ai_monitored/turret_protected/ai_upload,
/area/engine,
/area/solar,
/area/engineering,
/area/solars,
/area/holodeck,
/area/shuttle)
/area/shuttle,
/area/maintenance,
/area/science/test_area)
)
//Subtypes from the above that actually should explode.
var/list/unsafe_area_subtypes = typecacheof(list(/area/engine/break_room))
var/list/unsafe_area_subtypes = typecacheof(list(/area/engineering/break_room))
allowed_areas = make_associative(GLOB.the_station_areas) - safe_area_types + unsafe_area_subtypes
return safepick(typecache_filter_list(GLOB.sortedAreas,allowed_areas))
var/list/possible_areas = typecache_filter_list(GLOB.sortedAreas,allowed_areas)
if (length(possible_areas))
return pick(possible_areas)
/datum/round_event/anomaly/setup()
impact_area = findEventArea()
+70 -59
View File
@@ -7,6 +7,10 @@
earliest_start = 30 MINUTES
gamemode_blacklist = list("nuclear")
#define PIRATES_ROGUES "Rogues"
// #define PIRATES_SILVERSCALES "Silverscales"
// #define PIRATES_DUTCHMAN "Flying Dutchman"
/datum/round_event_control/pirates/preRunEvent()
if (!SSmapping.empty_space)
return EVENT_CANT_RUN
@@ -15,31 +19,54 @@
/datum/round_event/pirates
startWhen = 60 //2 minutes to answer
var/datum/comm_message/threat_message
var/datum/comm_message/threat_msg
var/payoff = 0
var/payoff_min = 1000
var/paid_off = FALSE
var/pirate_type
var/ship_template
var/ship_name = "Space Privateers Association"
var/shuttle_spawned = FALSE
/datum/round_event/pirates/setup()
ship_name = pick(strings(PIRATE_NAMES_FILE, "ship_names"))
pirate_type = PIRATES_ROGUES //pick(PIRATES_ROGUES, PIRATES_SILVERSCALES, PIRATES_DUTCHMAN)
switch(pirate_type)
if(PIRATES_ROGUES)
ship_name = pick(strings(PIRATE_NAMES_FILE, "rogue_names"))
// if(PIRATES_SILVERSCALES)
// ship_name = pick(strings(PIRATE_NAMES_FILE, "silverscale_names"))
// if(PIRATES_DUTCHMAN)
// ship_name = "Flying Dutchman"
/datum/round_event/pirates/announce(fake)
priority_announce("A business proposition has been downloaded and printed out at all communication consoles.", "Incoming Business Proposition", "commandreport")
priority_announce("Incoming subspace communication. Secure channel opened at all communication consoles.", "Incoming Message", "commandreport")
if(fake)
return
threat_message = new
threat_msg = new
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
payoff = round(D.account_balance * 0.80)
threat_message.title = "Business proposition"
threat_message.content = "This is [ship_name]. Pay up [payoff] credits or you'll walk the plank."
threat_message.possible_answers = list("We'll pay.","No way.")
threat_message.answer_callback = CALLBACK(src,.proc/answered)
SScommunications.send_message(threat_message,unique = TRUE)
payoff = max(payoff_min, FLOOR(D.account_balance * 0.80, 1000))
switch(pirate_type)
if(PIRATES_ROGUES)
ship_template = /datum/map_template/shuttle/pirate/default
threat_msg.title = "Sector protection offer"
threat_msg.content = "Hey, pal, this is the [ship_name]. Can't help but notice you're rocking a wild and crazy shuttle there with NO INSURANCE! Crazy. What if something happened to it, huh?! We've done a quick evaluation on your rates in this sector and we're offering [payoff] to cover for your shuttle in case of any disaster."
threat_msg.possible_answers = list("Purchase Insurance.","Reject Offer.")
// if(PIRATES_SILVERSCALES)
// ship_template = /datum/map_template/shuttle/pirate/silverscale
// threat_msg.title = "Tribute to high society"
// threat_msg.content = "This is the [ship_name]. The Silver Scales wish for some tribute from your plebeian lizards. [payoff] credits should do the trick."
// threat_msg.possible_answers = list("We'll pay.","Tribute? Really? Go away.")
// if(PIRATES_DUTCHMAN)
// ship_template = /datum/map_template/shuttle/pirate/dutchman
// threat_msg.title = "Business proposition"
// threat_msg.content = "Ahoy! This be the [ship_name]. Cough up [payoff] credits or you'll walk the plank."
// threat_msg.possible_answers = list("We'll pay.","We will not be extorted.")
threat_msg.answer_callback = CALLBACK(src,.proc/answered)
SScommunications.send_message(threat_msg,unique = TRUE)
/datum/round_event/pirates/proc/answered()
if(threat_message && threat_message.answered == 1)
if(threat_msg?.answered == 1)
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
if(D.adjust_money(-payoff))
@@ -48,11 +75,17 @@
return
else
priority_announce("Trying to cheat us? You'll regret this!",sender_override = ship_name)
else if(threat_msg?.answered == 2)
priority_announce("You won't pay? Fine then, we'll take those credits by force!",sender_override = ship_name)
if(!shuttle_spawned)
priority_announce("You won't listen to reason? Then we'll take what's yours or die trying!",sender_override = ship_name)
spawn_shuttle()
else
priority_announce("Too late to beg for mercy!",sender_override = ship_name)
/datum/round_event/pirates/start()
if(threat_msg && !threat_msg.answered)
threat_msg.possible_answers = list("Too late")
threat_msg.answered = 1
if(!paid_off && !shuttle_spawned)
spawn_shuttle()
@@ -62,10 +95,7 @@
var/list/candidates = pollGhostCandidates("Do you wish to be considered for pirate crew?", ROLE_TRAITOR)
shuffle_inplace(candidates)
if(!SSmapping.empty_space)
SSmapping.empty_space = SSmapping.add_new_zlevel("Empty Area For Pirates", list(ZTRAIT_LINKAGE = SELFLOOPING))
var/datum/map_template/shuttle/pirate/default/ship = new
var/datum/map_template/shuttle/pirate/ship = new ship_template
var/x = rand(TRANSITIONEDGE,world.maxx - TRANSITIONEDGE - ship.width)
var/y = rand(TRANSITIONEDGE,world.maxy - TRANSITIONEDGE - ship.height)
var/z = SSmapping.empty_space.z_value
@@ -75,6 +105,7 @@
if(!ship.load(T))
CRASH("Loading pirate ship failed!")
for(var/turf/A in ship.get_affected_turfs(T))
for(var/obj/effect/mob_spawn/human/pirate/spawner in A)
if(candidates.len > 0)
@@ -84,7 +115,8 @@
announce_to_ghosts(M)
else
announce_to_ghosts(spawner)
priority_announce("Unidentified ship detected near the station.")
priority_announce("Unidentified armed ship detected near the station.")
//Shuttle equipment
@@ -145,7 +177,7 @@
new /obj/effect/temp_visual/emp(get_turf(S))
/obj/machinery/shuttle_scrambler/proc/dump_loot(mob/user)
if(credits_stored) // Prevents spamming empty holochips
if(credits_stored) // Prevents spamming empty holochips
new /obj/item/holochip(drop_location(), credits_stored)
to_chat(user,"<span class='notice'>You retrieve the siphoned credits!</span>")
credits_stored = 0
@@ -161,10 +193,8 @@
STOP_PROCESSING(SSobj,src)
/obj/machinery/shuttle_scrambler/update_icon_state()
if(active)
icon_state = "dominator-blue"
else
icon_state = "dominator"
icon_state = active ? "dominator-blue" : "dominator"
return ..()
/obj/machinery/shuttle_scrambler/Destroy()
toggle_off()
@@ -175,7 +205,6 @@
shuttleId = "pirateship"
icon_screen = "syndishuttle"
icon_keyboard = "syndie_key"
resistance_flags = INDESTRUCTIBLE
light_color = LIGHT_COLOR_RED
possible_destinations = "pirateship_away;pirateship_home;pirateship_custom"
@@ -183,7 +212,6 @@
name = "pirate shuttle navigation computer"
desc = "Used to designate a precise transit location for the pirate shuttle."
shuttleId = "pirateship"
resistance_flags = INDESTRUCTIBLE
lock_override = CAMERA_LOCK_STATION
shuttlePortId = "pirateship_custom"
x_offset = 9
@@ -193,41 +221,20 @@
/obj/docking_port/mobile/pirate
name = "pirate shuttle"
id = "pirateship"
var/engines_cooling = FALSE
var/engine_cooldown = 3 MINUTES
/obj/docking_port/mobile/pirate/getStatusText()
. = ..()
if(engines_cooling)
return "[.] - Engines cooling."
/obj/docking_port/mobile/pirate/initiate_docking(obj/docking_port/stationary/new_dock, movement_direction, force=FALSE)
. = ..()
if(. == DOCKING_SUCCESS && !is_reserved_level(new_dock.z))
engines_cooling = TRUE
addtimer(CALLBACK(src,.proc/reset_cooldown),engine_cooldown,TIMER_UNIQUE)
/obj/docking_port/mobile/pirate/proc/reset_cooldown()
engines_cooling = FALSE
/obj/docking_port/mobile/pirate/canMove()
if(engines_cooling)
return FALSE
return ..()
rechargeTime = 3 MINUTES
/obj/machinery/suit_storage_unit/pirate
suit_type = /obj/item/clothing/suit/space
helmet_type = /obj/item/clothing/head/helmet/space
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/jetpack/void
// storage_type = /obj/item/tank/internals/oxygen
/obj/machinery/loot_locator
name = "Booty Locator"
desc = "This sophisticated machine scans the nearby space for items of value."
icon = 'icons/obj/machines/research.dmi'
icon_state = "tdoppler"
resistance_flags = INDESTRUCTIBLE
density = TRUE
var/cooldown = 300
var/next_use = 0
@@ -261,23 +268,20 @@
name = "cargo hold pad"
icon = 'icons/obj/telescience.dmi'
icon_state = "lpad-idle-o"
resistance_flags = INDESTRUCTIBLE
var/idle_state = "lpad-idle-o"
var/warmup_state = "lpad-idle"
var/sending_state = "lpad-beam"
var/cargo_hold_id
/obj/machinery/piratepad/multitool_act(mob/living/user, obj/item/I)
if(I.tool_behaviour == TOOL_MULTITOOL)
/obj/machinery/piratepad/multitool_act(mob/living/user, obj/item/multitool/I)
. = ..()
if (istype(I))
to_chat(user, "<span class='notice'>You register [src] in [I]s buffer.</span>")
I.buffer = src
return TRUE
/obj/machinery/computer/piratepad_control
name = "cargo hold control terminal"
resistance_flags = INDESTRUCTIBLE
ui_x = 600
ui_y = 230
var/status_report = "Ready for delivery."
var/obj/machinery/piratepad/pad
var/warmup_time = 100
@@ -291,8 +295,9 @@
..()
return INITIALIZE_HINT_LATELOAD
/obj/machinery/computer/piratepad_control/multitool_act(mob/living/user, obj/item/I)
if(I.tool_behaviour == TOOL_MULTITOOL && istype(I.buffer,/obj/machinery/piratepad))
/obj/machinery/computer/piratepad_control/multitool_act(mob/living/user, obj/item/multitool/I)
. = ..()
if (istype(I) && istype(I.buffer,/obj/machinery/piratepad))
to_chat(user, "<span class='notice'>You link [src] with [I.buffer] in [I] buffer.</span>")
pad = I.buffer
return TRUE
@@ -322,7 +327,8 @@
return data
/obj/machinery/computer/piratepad_control/ui_act(action, params)
if(..())
. = ..()
if(.)
return
if(!pad)
return
@@ -341,6 +347,7 @@
/obj/machinery/computer/piratepad_control/proc/recalc()
if(sending)
return
status_report = "Predicted value: "
var/value = 0
var/datum/export_report/ex = new
@@ -386,11 +393,13 @@
for(var/datum/export/E in ex.total_amount)
total_report.total_amount[E] += ex.total_amount[E]
total_report.total_value[E] += ex.total_value[E]
// playsound(loc, 'sound/machines/wewewew.ogg', 70, TRUE)
points += value
if(!value)
status_report += "Nothing"
pad.visible_message("<span class='notice'>[pad] activates!</span>")
flick(pad.sending_state,pad)
pad.icon_state = pad.idle_state
@@ -400,16 +409,18 @@
if(sending)
return
sending = TRUE
status_report = "Sending..."
status_report = "Sending... "
pad.visible_message("<span class='notice'>[pad] starts charging up.</span>")
pad.icon_state = pad.warmup_state
sending_timer = addtimer(CALLBACK(src,.proc/send),warmup_time, TIMER_STOPPABLE)
/obj/machinery/computer/piratepad_control/proc/stop_sending()
/obj/machinery/computer/piratepad_control/proc/stop_sending(custom_report)
if(!sending)
return
sending = FALSE
status_report = "Idle"
status_report = "Ready for delivery."
if(custom_report)
status_report = custom_report
pad.icon_state = pad.idle_state
deltimer(sending_timer)
+3 -4
View File
@@ -8,15 +8,14 @@
announceWhen = 50
endWhen = 20
var/list/area/areasToOpen = list()
var/list/potential_areas = list(/area/bridge,
/area/engine,
var/list/potential_areas = list(/area/command,
/area/engineering,
/area/medical,
/area/security,
/area/quartermaster,
/area/cargo,
/area/science)
var/severity = 1
/datum/round_event/grey_tide/setup()
announceWhen = rand(50, 60)
endWhen = rand(20, 30)
+2 -2
View File
@@ -71,12 +71,12 @@
var/list/safe_area_types = typecacheof(list(
/area/ai_monitored/turret_protected/ai,
/area/ai_monitored/turret_protected/ai_upload,
/area/engine,
/area/engineering,
/area/shuttle)
)
///Subtypes from the above that actually should explode.
var/list/unsafe_area_subtypes = typecacheof(list(/area/engine/break_room))
var/list/unsafe_area_subtypes = typecacheof(list(/area/engineering/break_room))
allowed_areas = make_associative(GLOB.the_station_areas) - safe_area_types + unsafe_area_subtypes
var/list/possible_areas = typecache_filter_list(GLOB.sortedAreas,allowed_areas)
if (length(possible_areas))
+10 -9
View File
@@ -25,7 +25,7 @@
supernova.power_mod = 0
/datum/round_event/supernova/announce()
var/message = "Our tachyon-doppler array has detected a supernova in your vicinity. Peak flux from the supernova estimated to be [round(power,0.1)] times current solar flux. [power > 4 ? "Short burts of radiation may be possible, so please prepare accordingly." : ""]"
var/message = "Our tachyon-doppler array has detected a supernova in your vicinity. Peak flux from the supernova estimated to be [round(power,0.1)] times current solar flux. [power > 1 ? "Short burts of radiation may be possible, so please prepare accordingly." : ""]"
if(prob(power * 25))
priority_announce(message)
else
@@ -47,12 +47,11 @@
/datum/round_event/supernova/tick()
var/midpoint = round((endWhen-startWhen)/2)
switch(activeFor)
if(startWhen to midpoint)
supernova.power_mod = min(supernova.power_mod*1.2, power)
if(endWhen-10 to endWhen)
supernova.power_mod /= 4
if(prob(round(supernova.power_mod / 2)) && storm_count < 4 && !SSweather.get_weather_by_type(/datum/weather/rad_storm))
if(activeFor < midpoint)
supernova.power_mod = min(supernova.power_mod*1.2, power)
if(activeFor > endWhen-10)
supernova.power_mod /= 4
if(prob(round(supernova.power_mod)) && prob(5) && storm_count < 5 && !SSweather.get_weather_by_type(/datum/weather/rad_storm))
SSweather.run_weather(/datum/weather/rad_storm/supernova)
storm_count++
@@ -63,5 +62,7 @@
/datum/weather/rad_storm/supernova
weather_duration_lower = 50
weather_duration_upper = 100
telegraph_duration = 100
radiation_intensity = 50
telegraph_duration = 200
radiation_intensity = 1000
weather_sound = null
telegraph_message = "<span class='userdanger'>The air begins to grow very warm!</span>"
@@ -278,6 +278,19 @@
visible_message("[src] finishes cooking!")
new /obj/item/reagent_containers/food/snacks/meat/steak/goliath(loc)
qdel(src)
/obj/item/reagent_containers/food/snacks/meat/slab/dragon
name = "ash drake meat"
desc = "Meat from an ash drake. It's probably not a good idea to eat this raw."
list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/toxin = 5, /datum/reagent/consumable/cooking_oil = 3)
icon_state = "goliathmeat"
tastes = list("meat" = 1)
foodtype = RAW | MEAT | TOXIC
/obj/item/reagent_containers/food/snacks/meat/slab/dragon/burn()
visible_message("[src] finishes cooking!")
new /obj/item/reagent_containers/food/snacks/meat/steak/dragon(loc)
qdel(src)
/obj/item/reagent_containers/food/snacks/meat/slab/meatwheat
name = "meatwheat clump"
@@ -395,6 +408,16 @@
trash = null
tastes = list("meat" = 1, "rock" = 1)
foodtype = MEAT
/obj/item/reagent_containers/food/snacks/meat/steak/dragon
name = "dragon steak"
desc = "Spicy."
resistance_flags = LAVA_PROOF | FIRE_PROOF
icon_state = "goliathsteak"
list_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/capsaicin = 3)
trash = null
tastes = list("meat" = 1, "fire" = 1)
foodtype = MEAT
/obj/item/reagent_containers/food/snacks/meat/steak/gondola
name = "gondola steak"
+1
View File
@@ -118,6 +118,7 @@
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/replicapod)
reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.1)
seed_flags = null
/obj/item/reagent_containers/food/snacks/grown/cabbage
seed = /obj/item/seeds/cabbage
+1
View File
@@ -12,6 +12,7 @@
default_priority = 90
icon_state = "eal"
chooseable_roundstart = TRUE
/datum/language/machine/get_random_name()
if(prob(70))
+1
View File
@@ -6,6 +6,7 @@
exclaim_verb = "poofs loudly"
whisper_verb = "puffs quietly"
key = "y"
flags = TONGUELESS_SPEECH
sentence_chance = 0
default_priority = 80
syllables = list("poof", "pff", "pFfF", "piff", "puff", "pooof", "pfffff", "piffpiff", "puffpuff", "poofpoof", "pifpafpofpuf")
+1
View File
@@ -6,6 +6,7 @@
ask_verb = "inquires"
exclaim_verb = "declares"
key = "h"
flags = TONGUELESS_SPEECH
space_chance = 20
syllables = list(
"fii", "sii", "rii", "rel", "maa", "ala", "san", "tol", "tok", "dia", "eres",
@@ -5,7 +5,8 @@
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
requires_power = FALSE
has_gravity = STANDARD_GRAVITY
valid_territory = FALSE
area_flags = BLOBS_ALLOWED | UNIQUE_AREA
flags_1 = CAN_BE_DIRTY_1
//Survival Capsule
/obj/item/survivalcapsule
@@ -58,9 +58,7 @@
if(9)
new /obj/item/gun/magic/wand/book/healing(src)
if(10)
new /obj/item/reagent_containers/glass/bottle/ichor/red(src)
new /obj/item/reagent_containers/glass/bottle/ichor/blue(src)
new /obj/item/reagent_containers/glass/bottle/ichor/green(src)
new /obj/item/guardiancreator(src)
/obj/structure/closet/crate/necropolis/tendril/weapon_armor/PopulateContents()
var/loot = rand(1,11)
@@ -197,9 +195,7 @@
if(28)
new /obj/item/gun/magic/wand/book/healing(src)
if(29)
new /obj/item/reagent_containers/glass/bottle/ichor/red(src)
new /obj/item/reagent_containers/glass/bottle/ichor/blue(src)
new /obj/item/reagent_containers/glass/bottle/ichor/green(src)
new /obj/item/guardiancreator(src)
//KA modkit design discs
/obj/item/disk/design_disk/modkit_disc
@@ -989,7 +985,18 @@
switch(random)
if(1)
to_chat(user, "<span class='danger'>Your appearance morphs to that of a very small humanoid ash dragon! You get to look like a freak without the cool abilities.</span>")
H.dna.features = list("mcolor" = "A02720", "tail_lizard" = "Dark Tiger", "tail_human" = "None", "snout" = "Sharp", "horns" = "Curled", "ears" = "None", "wings" = "None", "frills" = "None", "spines" = "Long", "body_markings" = "Dark Tiger Body", "legs" = "Digitigrade")
H.dna.features["mcolor"] = "A02720"
H.dna.features["tail_lizard"] = "Dark Tiger"
H.dna.features["tail_human"] = "None"
H.dna.features["mam_snout"] = "Sharp"
H.dna.features["horns"] = "Curled"
H.dna.features["ears"] = "None"
H.dna.features["wings"] = "None"
H.dna.features["frills"] = "None"
H.dna.features["spines"] = "Long"
H.dna.features["body_markings"] = "Dark Tiger Body"
H.dna.features["legs"] = "Digitigrade"
H.dna.features["taur_body"] = "None"
H.left_eye_color = "fee5a3"
H.right_eye_color = "fee5a3"
H.set_species(/datum/species/lizard)
@@ -1102,14 +1109,12 @@
/obj/structure/closet/crate/necropolis/bubblegum/PopulateContents()
new /obj/item/clothing/suit/space/hostile_environment(src)
new /obj/item/clothing/head/helmet/space/hostile_environment(src)
var/loot = rand(1,3)
var/loot = rand(1,2)
switch(loot)
if(1)
new /obj/item/mayhem(src)
if(2)
new /obj/item/book/granter/spell/asura(src)
if(3)
new /obj/item/guardiancreator(src)
/obj/structure/closet/crate/necropolis/bubblegum/crusher
name = "bloody bubblegum chest"
+107 -40
View File
@@ -16,29 +16,36 @@
singular_name = "ore chunk"
var/points = 0 //How many points this ore gets you from the ore redemption machine
var/refined_type = null //What this ore defaults to being refined into
var/mine_experience = 5 //How much experience do you get for mining this ore?
novariants = TRUE // Ore stacks handle their icon updates themselves to keep the illusion that there's more going
var/list/stack_overlays
var/scan_state = "" //Used by mineral turfs for their scan overlay.
var/spreadChance = 0 //Also used by mineral turfs for spreading veins
/obj/item/stack/ore/update_overlays()
. = ..()
var/difference = min(ORESTACK_OVERLAYS_MAX, amount) - (LAZYLEN(stack_overlays)+1)
if(difference == 0)
if(!difference)
return
else if(difference < 0 && LAZYLEN(stack_overlays)) //amount < stack_overlays, remove excess.
if (LAZYLEN(stack_overlays)-difference <= 0)
if(difference < 0 && LAZYLEN(stack_overlays)) //amount < stack_overlays, remove excess.
if(LAZYLEN(stack_overlays)-difference <= 0)
stack_overlays = null
else
stack_overlays.len += difference
else if(difference > 0) //amount > stack_overlays, add some.
return
stack_overlays.len += difference
else //amount > stack_overlays, add some.
for(var/i in 1 to difference)
var/mutable_appearance/newore = mutable_appearance(icon, icon_state)
newore.pixel_x = rand(-8,8)
newore.pixel_y = rand(-8,8)
LAZYADD(stack_overlays, newore)
if (stack_overlays)
if(stack_overlays)
. += stack_overlays
/obj/item/stack/ore/welder_act(mob/living/user, obj/item/I)
..()
if(!refined_type)
return TRUE
@@ -65,11 +72,16 @@
/obj/item/stack/ore/uranium
name = "uranium ore"
icon_state = "Uranium ore"
item_state = "Uranium ore"
// inhand_icon_state = "Uranium ore"
singular_name = "uranium ore chunk"
points = 30
// material_flags = MATERIAL_NO_EFFECTS
custom_materials = list(/datum/material/uranium=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/mineral/uranium
mine_experience = 6
scan_state = "rock_Uranium"
spreadChance = 5
// merge_type = /obj/item/stack/ore/uranium
/obj/item/stack/ore/iron
name = "iron ore"
@@ -79,6 +91,10 @@
points = 1
custom_materials = list(/datum/material/iron=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/metal
mine_experience = 1
scan_state = "rock_Iron"
spreadChance = 20
// merge_type = /obj/item/stack/ore/metal
/obj/item/stack/ore/glass
name = "sand pile"
@@ -89,10 +105,13 @@
custom_materials = list(/datum/material/glass=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/glass
w_class = WEIGHT_CLASS_TINY
mine_experience = 0 //its sand
// merge_type = /obj/item/stack/ore/glass
GLOBAL_LIST_INIT(sand_recipes, list(\
new/datum/stack_recipe("sandstone", /obj/item/stack/sheet/mineral/sandstone, 1, 1, 50),\
))
new /datum/stack_recipe("sandstone", /obj/item/stack/sheet/mineral/sandstone, 1, 1, 50)
))
/obj/item/stack/ore/glass/get_main_recipes()
. = ..()
@@ -111,7 +130,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
return ..()
var/mob/living/carbon/human/poorsod = M
visible_message("<span class='danger'>[user] throws the sand at [poorsod]'s face!</span>")
if(ishuman(user))
if(ishuman(user) && prob(80))
var/mob/living/carbon/human/sayer = user
sayer.forcesay("POCKET SAAND!!")
eyesand(poorsod)
@@ -133,7 +152,6 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
C.forcesay("*scream")
qdel(src)
/obj/item/stack/ore/glass/ex_act(severity, target)
if (severity == EXPLODE_NONE)
return
@@ -144,15 +162,21 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
icon_state = "volcanic_sand"
icon_state = "volcanic_sand"
singular_name = "volcanic ash pile"
mine_experience = 0
// merge_type = /obj/item/stack/ore/glass/basalt
/obj/item/stack/ore/plasma
name = "plasma ore"
icon_state = "Plasma ore"
item_state = "Plasma ore"
icon_state = "Plasma ore"
singular_name = "plasma ore chunk"
points = 15
custom_materials = list(/datum/material/plasma=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/mineral/plasma
mine_experience = 5
scan_state = "rock_Plasma"
spreadChance = 8
// merge_type = /obj/item/stack/ore/plasma
/obj/item/stack/ore/plasma/welder_act(mob/living/user, obj/item/I)
to_chat(user, "<span class='warning'>You can't hit a high enough temperature to smelt [src] properly!</span>")
@@ -164,8 +188,12 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
item_state = "Silver ore"
singular_name = "silver ore chunk"
points = 16
mine_experience = 3
custom_materials = list(/datum/material/silver=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/mineral/silver
scan_state = "rock_Silver"
spreadChance = 5
// merge_type = /obj/item/stack/ore/silver
/obj/item/stack/ore/gold
name = "gold ore"
@@ -173,8 +201,12 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
icon_state = "Gold ore"
singular_name = "gold ore chunk"
points = 18
mine_experience = 5
custom_materials = list(/datum/material/gold=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/mineral/gold
scan_state = "rock_Gold"
spreadChance = 5
// merge_type = /obj/item/stack/ore/gold
/obj/item/stack/ore/diamond
name = "diamond ore"
@@ -184,6 +216,9 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
points = 50
custom_materials = list(/datum/material/diamond=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/mineral/diamond
mine_experience = 10
scan_state = "rock_Diamond"
// merge_type = /obj/item/stack/ore/diamond
/obj/item/stack/ore/bananium
name = "bananium ore"
@@ -193,6 +228,9 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
points = 60
custom_materials = list(/datum/material/bananium=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/mineral/bananium
mine_experience = 15
scan_state = "rock_Bananium"
// merge_type = /obj/item/stack/ore/bananium
/obj/item/stack/ore/titanium
name = "titanium ore"
@@ -202,6 +240,10 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
points = 50
custom_materials = list(/datum/material/titanium=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/mineral/titanium
mine_experience = 3
scan_state = "rock_Titanium"
spreadChance = 5
// merge_type = /obj/item/stack/ore/titanium
/obj/item/stack/ore/slag
name = "slag"
@@ -209,6 +251,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
icon_state = "slag"
item_state = "slag"
singular_name = "slag chunk"
// merge_type = /obj/item/stack/ore/slag
/obj/item/gibtonite
name = "gibtonite ore"
@@ -235,7 +278,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
/obj/item/gibtonite/attackby(obj/item/I, mob/user, params)
if(!wires && istype(I, /obj/item/assembly/igniter))
user.visible_message("[user] attaches [I] to [src].", "<span class='notice'>You attach [I] to [src].</span>")
user.visible_message("<span class='notice'>[user] attaches [I] to [src].</span>", "<span class='notice'>You attach [I] to [src].</span>")
wires = new /datum/wires/explosive/gibtonite(src)
attacher = key_name(user)
qdel(I)
@@ -255,7 +298,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
primed = FALSE
if(det_timer)
deltimer(det_timer)
user.visible_message("The chain reaction was stopped! ...The ore's quality looks diminished.", "<span class='notice'>You stopped the chain reaction. ...The ore's quality looks diminished.</span>")
user.visible_message("<span class='notice'>The chain reaction stopped! ...The ore's quality looks diminished.</span>", "<span class='notice'>You stopped the chain reaction. ...The ore's quality looks diminished.</span>")
icon_state = "Gibtonite ore"
quality = GIBTONITE_QUALITY_LOW
return
@@ -269,34 +312,29 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
/obj/item/gibtonite/bullet_act(obj/item/projectile/P)
GibtoniteReaction(P.firer)
return ..()
. = ..()
/obj/item/gibtonite/ex_act()
GibtoniteReaction(null, 1)
/obj/item/gibtonite/proc/GibtoniteReaction(mob/user, triggered_by = 0)
if(!primed)
primed = TRUE
playsound(src,'sound/effects/hit_on_shattered_glass.ogg',50,1)
playsound(src,'sound/effects/hit_on_shattered_glass.ogg',50,TRUE)
icon_state = "Gibtonite active"
var/turf/bombturf = get_turf(src)
var/notify_admins = 0
var/notify_admins = FALSE
if(z != 5)//Only annoy the admins ingame if we're triggered off the mining zlevel
notify_admins = 1
notify_admins = TRUE
if(notify_admins)
if(triggered_by == 1)
message_admins("An explosion has triggered a [name] to detonate at [ADMIN_VERBOSEJMP(bombturf)].")
else if(triggered_by == 2)
message_admins("A signal has triggered a [name] to detonate at [ADMIN_VERBOSEJMP(bombturf)]. Igniter attacher: [ADMIN_LOOKUPFLW(attacher)]")
else
message_admins("[ADMIN_LOOKUPFLW(attacher)] has triggered a [name] to detonate at [ADMIN_VERBOSEJMP(bombturf)].")
if(triggered_by == 1)
log_game("An explosion has primed a [name] for detonation at [AREACOORD(bombturf)]")
message_admins("An explosion has triggered a [name] to detonate at [ADMIN_VERBOSEJMP(bombturf)].")
else if(triggered_by == 2)
log_game("A signal has primed a [name] for detonation at [AREACOORD(bombturf)]. Igniter attacher: [key_name(attacher)].")
if(notify_admins)
message_admins("A signal has triggered a [name] to detonate at [ADMIN_VERBOSEJMP(bombturf)]. Igniter attacher: [ADMIN_LOOKUPFLW(attacher)]")
var/bomb_message = "A signal has primed a [name] for detonation at [AREACOORD(bombturf)]. Igniter attacher: [key_name(attacher)]."
log_game(bomb_message)
GLOB.bombers += bomb_message
else
user.visible_message("<span class='warning'>[user] strikes \the [src], causing a chain reaction!</span>", "<span class='danger'>You strike \the [src], causing a chain reaction.</span>")
log_game("[key_name(user)] has primed a [name] for detonation at [AREACOORD(bombturf)]")
@@ -313,10 +351,10 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
explosion(src,0,1,3,adminlog = notify_admins)
qdel(src)
/obj/item/stack/ore/Initialize()
/obj/item/stack/ore/Initialize(mapload, new_amount, merge = TRUE)
. = ..()
pixel_x = rand(0,16)-8
pixel_y = rand(0,8)-8
pixel_x = initial(pixel_x) + rand(0, 16) - 8
pixel_y = initial(pixel_y) + rand(0, 8) - 8
/obj/item/stack/ore/ex_act(severity, target)
if (!severity || severity >= 2)
@@ -350,8 +388,8 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
. = ..()
coinflip = pick(sideslist)
icon_state = "coin_[coinflip]"
pixel_x = rand(0,16)-8
pixel_y = rand(0,8)-8
pixel_x = initial(pixel_x) + rand(0, 16) - 8
pixel_y = initial(pixel_y) + rand(0, 8) - 8
/obj/item/coin/set_custom_materials(list/materials, multiplier = 1)
. = ..()
@@ -377,6 +415,8 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
user.visible_message("<span class='suicide'>\the [src] lands on [coinflip]! [user] promptly falls over, dead!</span>")
user.adjustOxyLoss(200)
user.death(0)
// user.set_suicide(TRUE)
user.suicide_log()
else
user.visible_message("<span class='suicide'>\the [src] lands on [coinflip]! [user] keeps on living!</span>")
@@ -386,11 +426,12 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
/obj/item/coin/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/CC = W
if(string_attached)
to_chat(user, "<span class='warning'>There already is a string attached to this coin!</span>")
return
if (W.use_tool(src, user, 0, 1, skill_gain_mult = BARE_USE_TOOL_MULT))
if (CC.use(1))
add_overlay("coin_string_overlay")
string_attached = 1
to_chat(user, "<span class='notice'>You attach a string to the coin.</span>")
@@ -412,6 +453,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
..()
/obj/item/coin/wirecutter_act(mob/living/user, obj/item/I)
..()
if(!string_attached)
return TRUE
@@ -430,13 +472,13 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
flick("coin_[coinflip]_flip", src)
coinflip = pick(sideslist)
icon_state = "coin_[coinflip]"
playsound(user.loc, 'sound/items/coinflip.ogg', 50, 1)
playsound(user.loc, 'sound/items/coinflip.ogg', 50, TRUE)
var/oldloc = loc
sleep(15)
if(loc == oldloc && user && !user.incapacitated())
user.visible_message("[user] has flipped [src]. It lands on [coinflip].", \
"<span class='notice'>You flip [src]. It lands on [coinflip].</span>", \
"<span class='italics'>You hear the clattering of loose change.</span>")
user.visible_message("<span class='notice'>[user] flips [src]. It lands on [coinflip].</span>", \
"<span class='notice'>You flip [src]. It lands on [coinflip].</span>", \
"<span class='hear'>You hear the clattering of loose change.</span>")
return TRUE//did the coin flip? useful for suicide_act
/obj/item/coin/gold
@@ -486,4 +528,29 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
/obj/item/coin/iron
/obj/item/coin/gold/debug
custom_materials = list(/datum/material/gold = 400)
desc = "If you got this somehow, be aware that it will dust you. Almost certainly."
/obj/item/coin/gold/debug/attack_self(mob/user)
if(cooldown < world.time)
if(string_attached) //does the coin have a wire attached
to_chat(user, "<span class='warning'>The coin won't flip very well with something attached!</span>" )
return FALSE//do not flip the coin
cooldown = world.time + 15
flick("coin_[coinflip]_flip", src)
coinflip = pick(sideslist)
icon_state = "coin_[coinflip]"
playsound(user.loc, 'sound/items/coinflip.ogg', 50, TRUE)
var/oldloc = loc
sleep(15)
if(loc == oldloc && user && !user.incapacitated())
user.visible_message("<span class='notice'>[user] flips [src]. It lands on [coinflip].</span>", \
"<span class='notice'>You flip [src]. It lands on [coinflip].</span>", \
"<span class='hear'>You hear the clattering of loose change.</span>")
SSeconomy.fire()
// to_chat(user,"<span class='bounty'>[SSeconomy.inflation_value()] is the inflation value.</span>")
to_chat(user, "<span class='bounty'>Luckily, economical inflation is not yet included. So no, you cannot predict the market with this.</span>")
return TRUE//did the coin flip? useful for suicide_act
#undef ORESTACK_OVERLAYS_MAX
@@ -27,7 +27,7 @@
age = rand(AGE_MIN,AGE_MAX)
/datum/preferences/proc/update_preview_icon(current_tab)
var/equip_job = (current_tab != 2)
var/equip_job = (current_tab != APPEARANCE_TAB)
// Determine what job is marked as 'High' priority, and dress them up as such.
var/datum/job/previewJob = get_highest_job()
@@ -46,7 +46,7 @@
mannequin.add_overlay(mutable_appearance('modular_citadel/icons/ui/backgrounds.dmi', bgstate, layer = SPACE_LAYER))
copy_to(mannequin, initial_spawn = TRUE)
if(current_tab == 3)
if(current_tab == LOADOUT_TAB)
//give it its loadout if not on the appearance tab
SSjob.equip_loadout(parent.mob, mannequin, FALSE, bypass_prereqs = TRUE, can_drop = FALSE)
else
@@ -514,6 +514,20 @@
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/human/triple_kitsune
name = "Triple Kitsune Tails"
icon_state = "3sune"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/human/triple_kitsune
name = "Triple Kitsune Tails"
icon_state = "3sune"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/human/tentacle
name = "Tentacle"
icon_state = "tentacle"
@@ -965,6 +979,16 @@
icon_state = "9sune"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/mam_tails/triple_kitsune
name = "Triple Kitsune Tails"
icon_state = "3sune"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/mam_tails_animated/triple_kitsune
name = "Triple Kitsune Tails"
icon_state = "3sune"
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/mam_tails/tentacle
name = "Tentacle"
icon_state = "tentacle"
@@ -905,6 +905,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
mob_eye.observers |= src
mob_eye.hud_used.show_hud(mob_eye.hud_used.hud_version, src)
observetarget = mob_eye
mob_eye.investigate_log("was observed by [src] as a ghost.", INVESTIGATE_GHOST)
/mob/dead/observer/verb/register_pai_candidate()
set category = "Ghost"
@@ -297,6 +297,11 @@
icon = 'icons/obj/surgery.dmi'
icon_state = "posibrain-ipc"
/obj/item/organ/brain/slime
name = "slime nucleus"
desc = "A slimey membranous mass from a slimeperson."
icon_state = "brain-s"
////////////////////////////////////TRAUMAS////////////////////////////////////////
@@ -1,7 +1,7 @@
/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone)
SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMAGE, damage, damagetype, def_zone)
var/hit_percent = (100-blocked)/100
if(!forced && hit_percent <= 0)
return 0
+44 -4
View File
@@ -24,7 +24,12 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
/mob/living/carbon/human/dummy/proc/wipe_state()
delete_equipment()
icon_render_key = null
cut_overlays()
cut_overlays(TRUE)
/mob/living/carbon/human/dummy/setup_human_dna()
create_dna(src)
randomize_human(src)
dna.initialize_dna(skip_index = TRUE) //Skip stuff that requires full round init.
//Inefficient pooling/caching way.
GLOBAL_LIST_EMPTY(human_dummy_list)
@@ -42,13 +47,48 @@ GLOBAL_LIST_EMPTY(dummy_mob_list)
D = new
GLOB.human_dummy_list[slotkey] = D
GLOB.dummy_mob_list += D
else
D.regenerate_icons() //they were cut in wipe_state()
D.in_use = TRUE
return D
/proc/unset_busy_human_dummy(slotnumber)
if(!slotnumber)
/proc/generate_dummy_lookalike(slotkey, mob/target)
if(!istype(target))
return generate_or_wait_for_human_dummy(slotkey)
var/mob/living/carbon/human/dummy/copycat = generate_or_wait_for_human_dummy(slotkey)
if(iscarbon(target))
var/mob/living/carbon/carbon_target = target
carbon_target.dna.transfer_identity(copycat, transfer_SE = TRUE)
if(ishuman(target))
var/mob/living/carbon/human/human_target = target
human_target.copy_clothing_prefs(copycat)
copycat.updateappearance(icon_update=TRUE, mutcolor_update=TRUE, mutations_overlay_update=TRUE)
else
//even if target isn't a carbon, if they have a client we can make the
//dummy look like what their human would look like based on their prefs
target?.client?.prefs?.copy_to(copycat, icon_updates=TRUE, roundstart_checks=FALSE)
return copycat
/proc/unset_busy_human_dummy(slotkey)
if(!slotkey)
return
var/mob/living/carbon/human/dummy/D = GLOB.human_dummy_list[slotnumber]
var/mob/living/carbon/human/dummy/D = GLOB.human_dummy_list[slotkey]
if(istype(D))
D.wipe_state()
D.in_use = FALSE
/proc/clear_human_dummy(slotkey)
if(!slotkey)
return
var/mob/living/carbon/human/dummy/dummy = GLOB.human_dummy_list[slotkey]
GLOB.human_dummy_list -= slotkey
if(istype(dummy))
GLOB.dummy_mob_list -= dummy
qdel(dummy)
@@ -14,10 +14,7 @@
//initialize limbs first
create_bodyparts()
//initialize dna. for spawned humans; overwritten by other code
create_dna(src)
randomize_human(src)
dna.initialize_dna()
setup_human_dna()
if(dna.species)
set_species(dna.species.type)
@@ -36,6 +33,11 @@
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /atom.proc/clean_blood)
GLOB.human_list += src
/mob/living/carbon/human/proc/setup_human_dna()
//initialize dna. for spawned humans; overwritten by other code
create_dna(src)
randomize_human(src)
dna.initialize_dna()
/mob/living/carbon/human/ComponentInitialize()
. = ..()
@@ -176,3 +176,9 @@
/mob/living/carbon/human/get_biological_state()
return dna.species.get_biological_state()
///copies over clothing preferences like underwear to another human
/mob/living/carbon/human/proc/copy_clothing_prefs(mob/living/carbon/human/destination)
destination.underwear = underwear
destination.undershirt = undershirt
destination.socks = socks
@@ -47,6 +47,7 @@
owner.cut_overlays() //we dont show our normal sprite, we show a puddle sprite
var/obj/effect/puddle_effect = new puddle_into_effect(get_turf(owner), owner.dir)
puddle_effect.color = mutcolor
puddle_effect.transform = H.transform //copy mob size for consistent meltdown appearance
H.Stun(in_transformation_duration, ignore_canstun = TRUE) //cant move while transforming
//series of traits that make up the puddle behaviour
@@ -75,6 +76,7 @@
puddle_overlay.color = mutcolor
tracked_overlay = puddle_overlay
owner.add_overlay(puddle_overlay)
owner.update_antag_overlays()
transforming = FALSE
UpdateButtonIcon()
@@ -89,6 +91,7 @@
H.cut_overlay(tracked_overlay)
var/obj/effect/puddle_effect = new puddle_from_effect(get_turf(owner), owner.dir)
puddle_effect.color = tracked_overlay.color
puddle_effect.transform = H.transform //copy mob size for consistent transform size
H.Stun(out_transformation_duration, ignore_canstun = TRUE)
sleep(out_transformation_duration)
REMOVE_TRAIT(H, TRAIT_PARALYSIS_L_ARM, SLIMEPUDDLE_TRAIT)
@@ -106,5 +109,6 @@
is_puddle = FALSE
if(squeak)
squeak.RemoveComponent()
H.regenerate_icons()
transforming = FALSE
UpdateButtonIcon()

Some files were not shown because too many files have changed in this diff Show More