Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into ninjasarecum
# Conflicts: # code/modules/ninja/suit/ninjaDrainAct.dm
This commit is contained in:
@@ -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>"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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)
|
||||
. = ..()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 //////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"])
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
default_priority = 90
|
||||
|
||||
icon_state = "eal"
|
||||
chooseable_roundstart = TRUE
|
||||
|
||||
/datum/language/machine/get_random_name()
|
||||
if(prob(70))
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user