Final merge

Merge branch 'development-2' into development

# Conflicts:
#	baystation12.dme
#	code/_helpers/icons.dm
#	code/controllers/master_controller.dm
#	code/game/machinery/Sleeper.dm
#	code/game/machinery/computer3/laptop.dm
#	code/game/machinery/doors/door.dm
#	code/game/machinery/floorlayer.dm
#	code/game/machinery/vending.dm
#	code/game/mecha/mech_fabricator.dm
#	code/game/objects/effects/decals/contraband.dm
#	code/game/objects/explosion.dm
#	code/game/objects/items/robot/robot_upgrades.dm
#	code/game/objects/items/weapons/melee/misc.dm
#	code/game/objects/items/weapons/storage/boxes.dm
#	code/game/objects/structures/crates_lockers/closets/secure/security.dm
#	code/game/objects/structures/window.dm
#	code/modules/clothing/spacesuits/rig/rig.dm
#	code/modules/clothing/suits/jobs.dm
#	code/modules/mob/freelook/update_triggers.dm
#	code/modules/mob/living/carbon/human/human_defense.dm
#	code/modules/mob/living/carbon/human/human_movement.dm
#	code/modules/mob/living/carbon/human/life.dm
#	code/modules/mob/living/carbon/human/species/species.dm
#	code/modules/mob/living/carbon/human/species/station/station.dm
#	code/modules/mob/living/living_defines.dm
#	code/modules/mob/mob_helpers.dm
#	code/modules/mob/mob_movement.dm
#	code/modules/projectiles/ammunition/boxes.dm
#	nano/templates/sleeper.tmpl
This commit is contained in:
skull132
2016-11-12 00:10:21 +02:00
187 changed files with 6193 additions and 1183 deletions

Binary file not shown.

View File

@@ -173,10 +173,10 @@ CREATE TABLE `ss13_characters_flavour` (
`robot_standard` text,
`robot_engineering` text,
`robot_construction` text,
`robot_surgeon` text,
`robot_crisis` text,
`robot_medical` text,
`robot_rescue` text,
`robot_miner` text,
`robot_janitor` text,
`robot_custodial` text,
`robot_service` text,
`robot_clerical` text,
`robot_security` text,

View File

@@ -136,7 +136,9 @@
#include "code\controllers\Processes\inactivity.dm"
#include "code\controllers\Processes\machinery.dm"
#include "code\controllers\Processes\mob.dm"
#include "code\controllers\Processes\modifier.dm"
#include "code\controllers\Processes\nanoui.dm"
#include "code\controllers\Processes\night_lighting.dm"
#include "code\controllers\Processes\obj.dm"
#include "code\controllers\Processes\scheduler.dm"
#include "code\controllers\Processes\Shuttle.dm"
@@ -555,6 +557,8 @@
#include "code\game\mecha\working\hoverpod.dm"
#include "code\game\mecha\working\ripley.dm"
#include "code\game\mecha\working\working.dm"
#include "code\game\modifiers\modifiers.dm"
#include "code\game\modifiers\modifiers_chem.dm"
#include "code\game\objects\buckling.dm"
#include "code\game\objects\empulse.dm"
#include "code\game\objects\explosion.dm"
@@ -991,6 +995,7 @@
#include "code\modules\awaymissions\trigger.dm"
#include "code\modules\awaymissions\zlevel.dm"
#include "code\modules\blob\blob.dm"
#include "code\modules\cargo\randomstock.dm"
#include "code\modules\cciaa\cciaa.dm"
#include "code\modules\cciaa\cciaa_items.dm"
#include "code\modules\client\client defines.dm"
@@ -1157,6 +1162,7 @@
#include "code\modules\events\spacevine.dm"
#include "code\modules\events\spider_infestation.dm"
#include "code\modules\events\spontaneous_appendicitis.dm"
#include "code\modules\events\supply_drop.dm"
#include "code\modules\events\vent_clog.dm"
#include "code\modules\events\viral_infection.dm"
#include "code\modules\events\wallrot.dm"
@@ -1688,6 +1694,7 @@
#include "code\modules\projectiles\guns\projectile\revolver.dm"
#include "code\modules\projectiles\guns\projectile\shotgun.dm"
#include "code\modules\projectiles\guns\projectile\sniper.dm"
#include "code\modules\projectiles\guns\projectile\svd.dm"
#include "code\modules\projectiles\projectile\animate.dm"
#include "code\modules\projectiles\projectile\beams.dm"
#include "code\modules\projectiles\projectile\bullets.dm"

View File

@@ -863,6 +863,7 @@ proc/sort_atoms_by_layer(var/list/atoms)
result.Swap(i, gap + i)
swapped = 1
return result
/*
generate_image function generates image of specified range and location
arguments tx, ty, tz are target coordinates (requred), range defines render distance to opposite corner (requred)
@@ -913,3 +914,15 @@ proc/generate_image(var/tx as num, var/ty as num, var/tz as num, var/range as nu
return cap
proc/percentage_to_colour(var/P)
//Takes a value between 0-1
//Returns a colour - pure green if 1, pure red if 0
//Inbetween values will gradiant through green, yellow, orange, red
var/green = min(1, P*2)*255
var/red = 255 - (min(1, (P-0.5)*2)*255)
//var/green = (max(0, P-0.5)*2)*255
//var/red = 255 - (min(1, P*2)*255)
return rgb(red,green,0)

View File

@@ -71,6 +71,32 @@ proc/isemptylist(list/list)
return 1
return 0
/proc/is_type_in_oview(var/type, var/dist = 0, var/center = src)
if (!ispath(type))
CRASH("Not a valid type in 'is_type_in_oview()'")
if (!isnum(dist))
CRASH("Not a valid dist in 'is_type_in_oview()'")
if (!isloc(center))
CRASH("Not a valid center in 'is_type_in_oview()'")
var/list/atoms = oview(dist, center)
for (var/A in atoms)
if (istype(A, type))
return 1
return 0
/proc/is_type_in_view(var/type, var/dist = 0, var/center = src)
if (!ispath(type))
CRASH("Not a valid type in 'is_type_in_view()'")
if (!isnum(dist))
CRASH("Not a valid dist in 'is_type_in_view()'")
if (!isloc(center))
CRASH("Not a valid center in 'is_type_in_view()'")
var/list/atoms = view(dist, center)
for (var/A in atoms)
if (istype(A, type))
return 1
return 0
/proc/instances_of_type_in_list(var/atom/A, var/list/L)
var/instances = 0
for(var/type in L)
@@ -122,23 +148,29 @@ proc/listclearnulls(list/list)
result = first ^ second
return result
//Pretends to pick an element based on its weight but really just seems to pick a random element.
//Picks a random element by weight from a list. The list must be correctly constructed in this format:
//mylist[myelement1] = myweight1
//mylist[myelement2] = myweight2
//The proc will return the element index, and not the weight.
/proc/pickweight(list/L)
var/total = 0
var/item
for (item in L)
if (!L[item])
if (isnull(L[item]))
//Change by nanako, a default weight will no longer overwrite an explicitly set weight of 0
//It will only use a default if no weight is defined
L[item] = 1
total += L[item]
total = rand(1, total)
total = rand() * total//Fix by nanako, allows it to handle noninteger weights
for (item in L)
total -=L [item]
total -= L[item]
if (total <= 0)
return item
return null
//Pick a random element from the list and remove it from the list.
/proc/pick_n_take(list/listfrom)
if (listfrom.len > 0)

View File

@@ -10,6 +10,11 @@ proc/worldtime2text(time = world.time, timeshift = 1)
if(!roundstart_hour) roundstart_hour = pick(2,7,12,17)
return timeshift ? time2text(time+(36000*roundstart_hour), "hh:mm") : time2text(time, "hh:mm")
proc/worldtime2ticks(time = world.time)
if(!roundstart_hour)
worldtime2text()
return ((roundstart_hour * 60 MINUTES) + time) % TICKS_IN_DAY
proc/worlddate2text()
return num2text(game_year) + "-" + time2text(world.timeofday, "MM-DD")

View File

@@ -25,6 +25,30 @@
return 0
return 1
// This proc will check if a neighboring tile in the stated direction "dir" is dense or not
// Will return 1 if it is dense and zero if not
/proc/check_neighbor_density(turf/T, var/dir)
if (!T.loc)
CRASH("The Turf has no location!")
switch (dir)
if (NORTH)
return !turf_clear(get_turf(locate(T.x, T.y+1, T.z)))
if (NORTHEAST)
return !turf_clear(get_turf(locate(T.x+1, T.y+1, T.z)))
if (EAST)
return !turf_clear(get_turf(locate(T.x+1, T.y, T.z)))
if (SOUTHEAST)
return !turf_clear(get_turf(locate(T.x+1, T.y-1, T.z)))
if (SOUTH)
return !turf_clear(get_turf(locate(T.x, T.y-1, T.z)))
if (SOUTHWEST)
return !turf_clear(get_turf(locate(T.x-1, T.y-1, T.z)))
if (WEST)
return !turf_clear(get_turf(locate(T.x-1, T.y, T.z)))
if (NORTHWEST)
return !turf_clear(get_turf(locate(T.x-1, T.y+1, T.z)))
else return
// Picks a turf without a mob from the given list of turfs, if one exists.
// If no such turf exists, picks any random turf from the given list of turfs.
/proc/pick_mobless_turf_if_exists(var/list/start_turfs)

View File

@@ -1394,3 +1394,23 @@ var/mob/dview/dview_mob = new
// call to generate a stack trace and print to runtime logs
/proc/crash_with(msg)
CRASH(msg)
/atom/proc/find_up_hierarchy(var/atom/target)
//This function will recurse up the hierarchy containing src, in search of the target
//It will stop when it reaches an area, as areas have no loc
var/x = 0//As a safety, we'll crawl up a maximum of ten layers
var/atom/a = src
while (x < 10)
x++
if (isnull(a))
return 0
if (a == target)//we found it!
return 1
if (istype(a, /area))
return 0//Can't recurse any higher than this.
a = a.loc
return 0//If we get here, we must be buried many layers deep in nested containers. Shouldn't happen

View File

@@ -192,8 +192,17 @@
L.resist()
if("mov_intent")
var/list/modifiers = params2list(params)
//This is here instead of outside the switch to save adding overhead. its not used for any other UI icons right now
//If its needed in future for other UI icons, then move it up to above the switch
if(iscarbon(usr))
var/mob/living/carbon/C = usr
if (modifiers["alt"])
C.set_walk_speed()
return
if(C.legcuffed)
C << "<span class='notice'>You are legcuffed! You cannot run until you get [C.legcuffed] removed!</span>"
C.m_intent = "walk" //Just incase
@@ -202,10 +211,9 @@
switch(usr.m_intent)
if("run")
usr.m_intent = "walk"
usr.hud_used.move_intent.icon_state = "walking"
if("walk")
usr.m_intent = "run"
usr.hud_used.move_intent.icon_state = "running"
update_move_icon(usr)
if("m_intent")
if(!usr.m_int)
switch(usr.m_intent)
@@ -504,3 +512,25 @@
usr.update_inv_l_hand(0)
usr.update_inv_r_hand(0)
return 1
//This updates the run/walk button on the hud
/obj/screen/proc/update_move_icon(var/mob/living/user)
switch(name)
if("mov_intent")
overlays.Cut()
switch(user.m_intent)
if("run")//When in run mode, the button will have a flashing coloured overlay which gives a visual indicator of stamina
icon_state = "running"
if (user.max_stamina != -1)//If max stamina is -1, this species doesnt use stamina. no overlay for them
var/image/holder = image('icons/mob/screen1.dmi', src, "run_overlay")
var/staminaportion = user.stamina / user.max_stamina
holder.color = percentage_to_colour(staminaportion)
holder.blend_mode = BLEND_MULTIPLY
overlays += holder
if("walk")
icon_state = "walking"

View File

@@ -107,6 +107,8 @@
last_task = 0
last_object = null
/datum/controller/process/proc/preStart()
/datum/controller/process/proc/started()
var/timeofhour = TimeOfHour
// Initialize last_slept so we can record timing information

View File

@@ -84,10 +84,16 @@ var/global/datum/controller/processScheduler/processScheduler
isRunning = 1
// tick_lag will have been set by now, so re-initialize these
scheduler_sleep_interval = world.tick_lag
callPreStart()
updateStartDelays()
spawn(0)
process()
/datum/controller/processScheduler/proc/callPreStart()
for (var/datum/controller/process/P in processes)
if (!P.disabled)
P.preStart()
/datum/controller/processScheduler/proc/process()
while(isRunning)
checkRunningProcesses()

View File

@@ -0,0 +1,22 @@
/datum/controller/process/modifier/setup()
name = "modifiers"
schedule_interval = 10
start_delay = 8
/datum/controller/process/modifier/started()
..()
if(!processing_modifiers)
processing_modifiers = list()
/datum/controller/process/modifier/doWork()
for(last_object in processing_modifiers)
var/datum/modifier/O = last_object
if(isnull(O.gcDestroyed))
O.process()
else
catchBadType(O)
processing_objects -= O
/datum/controller/process/modifier/statProcess()
..()
stat(null, "[processing_modifiers.len] modifiers")

View File

@@ -0,0 +1,89 @@
/datum/controller/process/night_lighting/
var/isactive = 0
var/firstrun = 1
var/list/area/lighting_areas = list(
/area/hallway/primary/fore,
/area/hallway/primary/starboard,
/area/hallway/primary/aft,
/area/hallway/primary/port,
/area/hallway/primary/central_one,
/area/hallway/primary/central_two,
/area/hallway/primary/central_three,
/area/hallway/secondary/exit,
/area/hallway/secondary/entry/fore,
/area/hallway/secondary/entry/port,
/area/hallway/secondary/entry/starboard,
/area/hallway/secondary/entry/aft,
/area/crew_quarters/sleep,
/area/crew_quarters/locker,
/area/crew_quarters/fitness,
/area/crew_quarters/bar,
/area/engineering/foyer,
/area/security/lobby,
/area/storage/tools,
/area/storage/primary
)
/datum/controller/process/night_lighting/setup()
name = "night lighting controller"
schedule_interval = 3600 // Every 5 minutes.
if (!config.night_lighting)
// Stop trying to delete processes. Not how it goes.
disabled = 1
/datum/controller/process/night_lighting/preStart()
switch (worldtime2ticks())
if (0 to MORNING_LIGHT_RESET)
deactivate()
if (NIGHT_LIGHT_ACTIVE to TICKS_IN_DAY)
activate()
/datum/controller/process/night_lighting/doWork()
switch (worldtime2ticks())
if (0 to MORNING_LIGHT_RESET)
if (isactive)
command_announcement.Announce("Good morning. The time is [worldtime2text()]. \n\nThe automated systems aboard the [station_name()] will now return the public hallway lighting levels to normal.", "Automated Lighting System", new_sound = 'sound/misc/bosuns_whistle.ogg')
deactivate()
if (NIGHT_LIGHT_ACTIVE to TICKS_IN_DAY)
if (!isactive)
command_announcement.Announce("Good evening. The time is [worldtime2text()]. \n\nThe automated systems aboard the [station_name()] will now dim lighting in the public hallways in order to accommodate the circadian rhythm of some species.", "Automated Lighting System", new_sound = 'sound/misc/bosuns_whistle.ogg')
activate()
else
if (isactive)
deactivate()
/datum/controller/process/night_lighting/proc/activate()
for (var/obj/machinery/power/apc/APC in get_apc_list())
APC.toggle_nightlight("on")
isactive = 1
SCHECK
/datum/controller/process/night_lighting/proc/deactivate()
for (var/obj/machinery/power/apc/APC in get_apc_list())
APC.toggle_nightlight("off")
isactive = 0
SCHECK
/datum/controller/process/night_lighting/proc/get_apc_list()
var/list/obj/machinery/power/apc/lighting_apcs = list()
for (var/A in all_areas)
var/area/B = A
if (!(B.type in lighting_areas))
continue
if (B.apc)
lighting_apcs += B.apc
SCHECK
return lighting_apcs

View File

@@ -145,8 +145,10 @@ var/list/gamemode_cache = list()
//Used for modifying movement speed for mobs.
//Unversal modifiers
var/run_speed = 0
var/walk_speed = 0
var/walk_delay_multiplier = 1
var/run_delay_multiplier = 1
var/vehicle_delay_multiplier = 1
//Mob specific modifiers. NOTE: These will affect different mob types in different ways
var/human_delay = 0
@@ -173,6 +175,8 @@ var/list/gamemode_cache = list()
var/gateway_delay = 18000 //How long the gateway takes before it activates. Default is half an hour.
var/ghost_interaction = 0
var/night_lighting = 0
var/comms_password = ""
var/enter_allowed = 1
@@ -615,6 +619,9 @@ var/list/gamemode_cache = list()
if("ghost_interaction")
config.ghost_interaction = 1
if("night_lighting")
config.night_lighting = 1
if("disable_player_mice")
config.disable_player_mice = 1
@@ -810,11 +817,17 @@ var/list/gamemode_cache = list()
if("limbs_can_break")
config.limbs_can_break = value
if("run_speed")
config.run_speed = value
if("walk_speed")
config.walk_speed = value
// These should never go to 0 or below. So, we clamp them.
if("walk_delay_multiplier")
config.walk_delay_multiplier = max(0.1, value)
if("run_delay_multiplier")
config.run_delay_multiplier = max(0.1, value)
if("vehicle_delay_multiplier")
config.vehicle_delay_multiplier = max(0.1, value)
if("human_delay")
config.human_delay = value
if("robot_delay")

View File

@@ -70,6 +70,17 @@ datum/controller/game_controller/proc/setup_objects()
var/obj/machinery/atmospherics/unary/vent_scrubber/T = U
T.broadcast_status()
//Spawn the contents of the cargo warehouse
sleep(-1)
spawn_cargo_stock()
// Create the mining ore distribution map.
// These values determine the specific area that the map is applied to.
// If you do not use the official Baycode asteroid map, you will need to change them.
asteroid_ore_map = new /datum/random_map/ore(null,13,32,5,217,223)
// Set up antagonists.
populate_antag_type_list()

View File

@@ -14,6 +14,12 @@
topic_commands_names.Add(A.name)
listclearnulls(topic_commands)
listclearnulls(topic_commands_names)
if (config.api_rate_limit_whitelist.len)
// To make the api_rate_limit_whitelist[addr] grabs actually work.
for (var/addr in config.api_rate_limit_whitelist)
config.api_rate_limit_whitelist[addr] = 1
return 1
/world/proc/api_do_auth_check(var/addr, var/auth, var/datum/topic_command/command)

View File

@@ -14,6 +14,8 @@
#define OUTDATED_MEMO 2
#define OUTDATED_NOTE 4
#define JS_SANITIZE(msg) list2params(list(json_encode(msg)))
/datum/server_greeting
// Hashes to figure out if we need to display the greeting message.
// These correspond to motd_hash and memo_hash on /datum/preferences for each client.
@@ -21,24 +23,19 @@
var/memo_hash = ""
// The stored strings of general subcomponents.
var/motd = ""
var/memo_list[] = list()
var/memo = ""
var/motd = "<center>No new announcements to showcase.</center>"
var/raw_data_user = ""
var/raw_data_staff = ""
// The near-final string to be displayed.
// Only one placeholder remains: <!--notifications-->.
var/user_data = ""
var/staff_data = ""
var/memo_list[] = list()
var/memo = "<center>No memos have been posted.</center>"
// Cached outdated information.
var/list/client_cache = list()
/datum/server_greeting/New()
..()
load_from_file()
prepare_data()
/*
* Populates variables from save file, and loads the raw HTML data.
* Needs to be called at least once for successful initialization.
@@ -52,51 +49,33 @@
if (F["memo"])
F["memo"] >> memo_list
raw_data_staff = file2text('html/templates/welcome_screen.html')
// This is a lazy way, but it disables the user from being able to see the memo button.
var/staff_button = "<li role=\"presentation\" id=\"memo-tab\"><a href=\"#memo\" aria-controls=\"memo\" role=\"tab\" data-toggle=\"tab\">Staff Memos</a></li>"
raw_data_user = replacetextEx(raw_data_staff, staff_button, "")
update_data()
/*
* Generates hashes, placeholders, and reparses var/memo.
* Then updates staff_data and user_data with the new contents.
* To be called after load_from_file or update_value.
* A helper to regenerate the hashes for all data fields.
* As well as to reparse the staff memo list.
* Separated for the sake of avoiding the duplication of code.
*/
/datum/server_greeting/proc/prepare_data()
if (!motd)
motd = "<center>No new announcements to showcase.</center>"
motd_hash = ""
else
/datum/server_greeting/proc/update_data()
if (motd)
motd_hash = md5(motd)
memo = ""
else
motd = initial(motd)
motd_hash = ""
if (memo_list.len)
memo = ""
for (var/ckey in memo_list)
var/data = {"
<p><b>[ckey]</b> wrote on [memo_list[ckey]["date"]]:<br>
[memo_list[ckey]["content"]]</p>
"}
var/data = {"<p><b>[ckey]</b> wrote on [memo_list[ckey]["date"]]:<br>
[memo_list[ckey]["content"]]</p>"}
memo += data
memo_hash = md5(memo)
else
memo = "<center>No memos have been posted.</center>"
memo = initial(memo)
memo_hash = ""
var/html_one = raw_data_staff
html_one = replacetextEx(html_one, "<!--motd-->", motd)
html_one = replacetextEx(html_one, "<!--memo-->", memo)
staff_data = html_one
var/html_two = raw_data_user
html_two = replacetextEx(html_two, "<!--motd-->", motd)
user_data = html_two
return
/*
* Helper to update the MoTD or memo contents.
* Args:
@@ -113,7 +92,6 @@
switch (change)
if ("motd")
motd = new_value
motd_hash = md5(new_value)
if ("memo_write")
memo_list[new_value[1]] = list("date" = time2text(world.realtime, "DD-MMM-YYYY"), "content" = new_value[2])
@@ -131,7 +109,7 @@
F["motd"] << motd
F["memo"] << memo_list
prepare_data()
update_data()
return 1
@@ -142,10 +120,13 @@
* Returns:
* - int
*/
/datum/server_greeting/proc/find_outdated_info(var/client/user)
/datum/server_greeting/proc/find_outdated_info(var/client/user, var/force_eval = 0)
if (!user || !user.prefs)
return 0
if (!force_eval && !isnull(client_cache[user]))
return client_cache[user]
var/outdated_info = 0
if (motd_hash && user.prefs.motd_hash != motd_hash)
@@ -157,53 +138,88 @@
if (user.prefs.notifications.len)
outdated_info |= OUTDATED_NOTE
client_cache[user] = outdated_info
return outdated_info
/*
* Composes the final message and displays it to the user.
* Also clears the user's notifications, should he have any.
* A proc used to open the server greeting window for a user.
* Args:
* - var/user client
* - var/outdated_info int
*/
/datum/server_greeting/proc/display_to_client(var/client/user, var/outdated_info = 0)
/datum/server_greeting/proc/display_to_client(var/client/user)
if (!user)
return
var/notifications = "<div class=\"row\"><div class=\"alert alert-info\">You do not have any notifications to show.</div></div>"
var/list/outdated_tabs = list()
user << browse('html/templates/welcome_screen.html', "window=greeting;size=640x500")
/*
* Sends data to the JS controllers used in the server greeting.
* Also updates the user's preferences, if any of the hashes were out of date.
* Args:
* - var/user client
* - var/outdated_info int
*/
/datum/server_greeting/proc/send_to_javascript(var/client/user)
if (!user)
return
// This is fine now, because it uses cached information.
var/outdated_info = server_greeting.find_outdated_info(user)
var/save_prefs = 0
var/list/data = list("div" = "", "content" = "", "update" = 1)
if (outdated_info & OUTDATED_NOTE)
outdated_tabs += "#note-tab"
user << output("#note-placeholder", "greeting.browser:RemoveElement")
data["div"] = "#note"
data["update"] = 1
notifications = ""
for (var/datum/client_notification/a in user.prefs.notifications)
notifications += a.get_html()
data["content"] = a.get_html()
user << output(JS_SANITIZE(data), "greeting.browser:AddContent")
if (!user.holder)
user << output("#memo-tab", "greeting.browser:RemoveElement")
else
if (outdated_info & OUTDATED_MEMO)
outdated_tabs += "#memo-tab"
data["update"] = 1
user.prefs.memo_hash = memo_hash
save_prefs = 1
else
data["update"] = 0
data["div"] = "#memo"
data["content"] = memo
user << output(JS_SANITIZE(data), "greeting.browser:AddContent")
if (outdated_info & OUTDATED_MOTD)
outdated_tabs += "#motd-tab"
data["update"] = 1
user.prefs.motd_hash = motd_hash
save_prefs = 1
else
data["update"] = 0
var/data = user_data
if (user.holder)
data = staff_data
data = replacetextEx(data, "<!--note-->", notifications)
if (outdated_tabs.len)
var/tab_string = json_encode(outdated_tabs)
data = replacetextEx(data, "var updated_tabs = \[\]", "var updated_tabs = [tab_string]")
user << browse(data, "window=welcome_screen;size=640x500")
data["div"] = "#motd"
data["content"] = motd
user << output(JS_SANITIZE(data), "greeting.browser:AddContent")
if (save_prefs)
user.prefs.handle_preferences_save(user)
/*
* Basically the Topic proc for the greeting datum.
*/
/datum/server_greeting/proc/handle_call(var/href_list, var/client/C)
if (!href_list || !href_list["command"] || !C)
return
switch (href_list["command"])
if ("request_data")
send_to_javascript(C)
#undef OUTDATED_NOTE
#undef OUTDATED_MEMO
#undef OUTDATED_MOTD

View File

@@ -89,11 +89,12 @@
attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed")
/obj/item/weapon/cane/concealed
w_class = 4
var/concealed_blade
/obj/item/weapon/cane/concealed/New()
..()
var/obj/item/weapon/material/butterfly/switchblade/temp_blade = new(src)
var/obj/item/weapon/canesword/temp_blade = new(src)
concealed_blade = temp_blade
temp_blade.attack_self()
@@ -111,7 +112,7 @@
else
..()
/obj/item/weapon/cane/concealed/attackby(var/obj/item/weapon/material/butterfly/W, var/mob/user)
/obj/item/weapon/cane/concealed/attackby(var/obj/item/weapon/canesword/W, var/mob/user)
if(!src.concealed_blade && istype(W))
user.visible_message("<span class='warning'>[user] has sheathed \a [W] into \his [src]!</span>", "You sheathe \the [W] into \the [src].")
user.drop_from_inventory(W)

View File

@@ -27,6 +27,7 @@ var/datum/antagonist/raider/raiders
/obj/item/clothing/under/captain_fly,
/obj/item/clothing/under/det,
/obj/item/clothing/under/brown,
/obj/item/clothing/under/syndicate/tracksuit
)
var/list/raider_shoes = list(
@@ -92,6 +93,7 @@ var/datum/antagonist/raider/raiders
/obj/item/weapon/gun/projectile/pistol,
/obj/item/weapon/gun/projectile/revolver,
/obj/item/weapon/gun/projectile/revolver/deckard,
/obj/item/weapon/gun/projectile/revolver/derringer,
/obj/item/weapon/gun/projectile/pirate,
/obj/item/weapon/gun/projectile/tanto
)

View File

@@ -1518,10 +1518,14 @@ area/space/atmosalert()
icon_state = "quartoffice"
/area/quartermaster/storage
name = "\improper Cargo Bay"
name = "\improper Cargo Warehouse"
icon_state = "quartstorage"
sound_env = LARGE_ENCLOSED
/area/quartermaster/loading
name = "\improper Cargo Bay"
icon_state = "quartloading"
/area/quartermaster/qm
name = "\improper Cargo - Quartermaster's Office"
icon_state = "quart"

View File

@@ -16,7 +16,7 @@
var/germ_level = GERM_LEVEL_AMBIENT // The higher the germ level, the more germ on the atom.
var/simulated = 1 //filter for actions - used by lighting overlays
var/fluorescent // Shows up under a UV light.
var/list/modifiers = list()
///Chemistry.
var/datum/reagents/reagents = null

View File

@@ -144,11 +144,9 @@
unload(0)
switch(severity)
if(2)
BITRESET(wires, rand(0,9))
BITRESET(wires, rand(0,9))
BITRESET(wires, rand(0,9))
wires.RandomCutAll(40)//Fix by nanako because the old code was throwing runtimes
if(3)
BITRESET(wires, rand(0,9))
wires.RandomCutAll(20)
..()
return

View File

@@ -606,6 +606,10 @@ About the new airlock wires panel:
flick("door_deny", src)
if(secured_wires)
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0)
if ("braced")
if (src.arePowerSystemsOn())
flick("door_deny", src)
playsound(src.loc, 'sound/machines/hydraulic_short.ogg', 50, 0)
return
/obj/machinery/door/airlock/attack_ai(mob/user as mob)
@@ -898,10 +902,21 @@ About the new airlock wires panel:
spawn(0) close(1)
else
user << "<span class='warning'>You need to be wielding \the [C] to do that.</span>"
else if(istype(C, /obj/item/weapon/melee/hammer) && !arePowerSystemsOn())
if(locked)
user << "<span class='notice'>The airlock's bolts prevent it from being forced.</span>"
else if( !welded && !operating )
if(density)
spawn(0) open(1)
else
spawn(0) close(1)
else
..()
return
/obj/machinery/door/airlock/phoron/attackby(C as obj, mob/user as mob)
if(C)
ignite(is_hot(C))
@@ -930,9 +945,9 @@ About the new airlock wires panel:
//if the door is unpowered then it doesn't make sense to hear the woosh of a pneumatic actuator
if(arePowerSystemsOn())
playsound(src.loc, open_sound_powered, 100, 1)
playsound(src.loc, open_sound_powered, 60, 1)
else
playsound(src.loc, open_sound_unpowered, 100, 1)
playsound(src.loc, open_sound_unpowered, 60, 1)
if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density)
src.closeOther.close()
@@ -943,7 +958,8 @@ About the new airlock wires panel:
if(!arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR))
return 0
if (bracer)
visible_message("<span class='notice'>[src]'s actuators whirr, but the door does not open.</span>")
do_animate("braced")
visible_message("<span class='warning'>[src]'s actuators whirr, but the door does not open.</span>")
return 0
if(locked || welded)
return 0

View File

@@ -103,8 +103,8 @@
// This only works on broken doors or doors without power. Also allows repair with Plasteel.
/obj/machinery/door/blast/attackby(obj/item/weapon/C as obj, mob/user as mob)
src.add_fingerprint(user)
if(istype(C, /obj/item/weapon/crowbar) || (istype(C, /obj/item/weapon/material/twohanded/fireaxe) && C:wielded == 1))
if(((stat & NOPOWER) || (stat & BROKEN)) && !( src.operating ))
if(istype(C, /obj/item/weapon/crowbar) || (istype(C, /obj/item/weapon/material/twohanded/fireaxe) && C:wielded == 1) || (istype(C, /obj/item/weapon/melee/hammer)))
if (((stat & NOPOWER) || (stat & BROKEN)) && !( src.operating ))
force_toggle()
else
usr << "<span class='notice'>[src]'s motors resist your effort.</span>"

View File

@@ -26,6 +26,7 @@
var/destroy_hits = 10 //How many strong hits it takes to destroy the door
var/min_force = 10 //minimum amount of force needed to damage the door with a melee weapon
var/hitsound = 'sound/weapons/smash.ogg' //sound door makes when hit with a weapon
var/hitsound_light = 'sound/effects/Glasshit.ogg'//Sound door makes when hit very gently
var/obj/item/stack/material/steel/repairing
var/block_air_zones = 1 //If set, air zones cannot merge across the door even when it is opened.
var/close_door_at = 0 //When to automatically close the door, if possible
@@ -53,9 +54,11 @@
/obj/machinery/door/attack_generic(var/mob/user, var/damage)
if(damage >= 10)
visible_message("<span class='danger'>\The [user] smashes into the [src]!</span>")
playsound(src.loc, hitsound, 60, 1)
take_damage(damage)
else
visible_message("<span class='notice'>\The [user] bonks \the [src] harmlessly.</span>")
playsound(src.loc, hitsound_light, 8, 1, -1)
user.do_attack_animation(src)
/obj/machinery/door/New()
@@ -244,7 +247,12 @@
tforce = 15 * (speed/5)
else
tforce = AM:throwforce * (speed/5)
playsound(src.loc, hitsound, 100, 1)
if (tforce > 0)
var/volume = 100
if (tforce < 20)//No more stupidly loud banging sound from throwing a piece of paper at a door
volume *= (tforce / 20)
playsound(src.loc, hitsound, volume, 1)
take_damage(tforce)
return

View File

@@ -250,7 +250,7 @@
user << "<span class='danger'>\The [src] is welded shut!</span>"
return
if(istype(C, /obj/item/weapon/crowbar) || istype(C,/obj/item/weapon/material/twohanded/fireaxe))
if(istype(C, /obj/item/weapon/crowbar) || istype(C,/obj/item/weapon/material/twohanded/fireaxe) || (istype(C, /obj/item/weapon/melee/hammer)))
if(operating)
return
@@ -269,7 +269,7 @@
"You start forcing \the [src] [density ? "open" : "closed"] with \the [C]!",\
"You hear metal strain.")
if(do_after(user,30))
if(istype(C, /obj/item/weapon/crowbar))
if(istype(C, /obj/item/weapon/crowbar) || (istype(C, /obj/item/weapon/melee/hammer)))
if(stat & (BROKEN|NOPOWER) || !density)
user.visible_message("<span class='danger'>\The [user] forces \the [src] [density ? "open" : "closed"] with \a [C]!</span>",\
"You force \the [src] [density ? "open" : "closed"] with \the [C]!",\

View File

@@ -70,7 +70,10 @@
var/dismantle = mode["dismantle"]
var/laying = mode["laying"]
var/collect = mode["collect"]
user << "<span class='notice'>\The [src] [!T?"don't ":""]has [!T?"":"[T.get_amount()] [T] "]tile\s, dismantle is [dismantle?"on":"off"], laying is [laying?"on":"off"], collect is [collect?"on":"off"].</span>"
var/number = 0
if (T)
number = T.get_amount()
user << "<span class='notice'>\The [src] has [number] tile\s, dismantle is [dismantle?"on":"off"], laying is [laying?"on":"off"], collect is [collect?"on":"off"].</span>"
/obj/machinery/floorlayer/proc/reset()
on=0
@@ -80,8 +83,11 @@
if(istype(new_turf, /turf/simulated/floor))
var/turf/simulated/floor/T = new_turf
if(!T.is_plating())
T.make_plating(!(T.broken || T.burnt))
return new_turf.is_plating()
if(!T.broken && !T.burnt)
new T.floor_type(T)
T.make_plating()
return !new_turf.intact
return 0
/obj/machinery/floorlayer/proc/TakeNewStack()
for(var/obj/item/stack/tile/tile in contents)
@@ -91,7 +97,12 @@
/obj/machinery/floorlayer/proc/SortStacks()
for(var/obj/item/stack/tile/tile1 in contents)
if (tile1 && tile1.get_amount() > 0)
if (!T || T.type == tile1.type)
T = tile1
if (tile1.get_amount() < tile1.max_amount)
for(var/obj/item/stack/tile/tile2 in contents)
if (tile2 != tile1 && tile2.type == tile1.type)
tile2.transfer_to(tile1)
/obj/machinery/floorlayer/proc/layFloor(var/turf/w_turf)

View File

@@ -125,6 +125,8 @@
update_icon()
/obj/machinery/iv_drip/attack_hand(mob/user as mob)
if (isAI(user))
return
if(src.beaker)
src.beaker.loc = get_turf(src)
src.beaker = null

View File

@@ -723,7 +723,7 @@
vend_power_usage = 85000 //85 kJ to heat a 250 mL cup of coffee
products = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 25,/obj/item/weapon/reagent_containers/food/drinks/tea = 25,/obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 25)
contraband = list(/obj/item/weapon/reagent_containers/food/drinks/ice = 10)
prices = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 3, /obj/item/weapon/reagent_containers/food/drinks/tea = 3, /obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 3)
prices = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 10, /obj/item/weapon/reagent_containers/food/drinks/tea = 10, /obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 12)
@@ -739,10 +739,10 @@
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 6, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 6, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 3,
/obj/item/weapon/reagent_containers/food/snacks/meatsnack = 2, /obj/item/weapon/reagent_containers/food/snacks/maps = 2, /obj/item/weapon/reagent_containers/food/snacks/nathisnack = 2)
contraband = list(/obj/item/weapon/reagent_containers/food/snacks/syndicake = 6)
prices = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 1,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 5,/obj/item/weapon/reagent_containers/food/snacks/chips = 1,
/obj/item/weapon/reagent_containers/food/snacks/sosjerky = 2,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 1,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 1,
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 1, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 2, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 4,
/obj/item/weapon/reagent_containers/food/snacks/meatsnack = 4, /obj/item/weapon/reagent_containers/food/snacks/maps = 5, /obj/item/weapon/reagent_containers/food/snacks/nathisnack = 6)
prices = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 5,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 10,/obj/item/weapon/reagent_containers/food/snacks/chips = 7,
/obj/item/weapon/reagent_containers/food/snacks/sosjerky = 10,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 2,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 5,
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 5, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 8, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 30,
/obj/item/weapon/reagent_containers/food/snacks/meatsnack = 12, /obj/item/weapon/reagent_containers/food/snacks/maps = 13, /obj/item/weapon/reagent_containers/food/snacks/nathisnack = 14)
/obj/machinery/vending/cola
@@ -756,10 +756,10 @@
/obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 10, /obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 10)
contraband = list(/obj/item/weapon/reagent_containers/food/drinks/cans/thirteenloko = 5, /obj/item/weapon/reagent_containers/food/snacks/liquidfood = 6)
prices = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 2,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 1)
prices = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola = 5,/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 6,/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 5,
/obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 2,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 5,
/obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 3,/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 6)
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
//This one's from bay12

View File

@@ -1,89 +1,22 @@
/obj/machinery/wish_granter
name = "Wish Granter"
desc = "You're not so sure about this, anymore..."
icon = 'icons/obj/device.dmi'
icon_state = "syndbeacon"
desc = "You are not so sure about this anymore..."
icon = 'icons/obj/machines/wishgranter.dmi' //thanks cakeisossim for the sprites
icon_state = "wishgranter"
use_power = 0
anchored = 1
density = 1
var/charges = 1
var/insisting = 0
/obj/machinery/wish_granter/attack_hand(var/mob/user as mob)
usr.set_machine(src)
if(charges <= 0)
user << "The Wish Granter lies silent."
return
else if(!istype(user, /mob/living/carbon/human))
user << "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's."
return
else if(is_special_character(user))
user << "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away."
else if (!insisting)
user << "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?"
insisting++
else
user << "You speak. [pick("I want the station to disappear","Humanity is corrupt, mankind must be destroyed","I want to be rich", "I want to rule the world","I want immortality.")]. The Wish Granter answers."
user << "Your head pounds for a moment, before your vision clears. You are the avatar of the Wish Granter, and your power is LIMITLESS! And it's all yours. You need to make sure no one can take it from you. No one can know, first."
charges--
insisting = 0
if (!(HULK in user.mutations))
user.mutations.Add(HULK)
if (!(LASER in user.mutations))
user.mutations.Add(LASER)
if (!(XRAY in user.mutations))
user.mutations.Add(XRAY)
user.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS)
user.see_in_dark = 8
user.see_invisible = SEE_INVISIBLE_LEVEL_TWO
if (!(COLD_RESISTANCE in user.mutations))
user.mutations.Add(COLD_RESISTANCE)
if (!(TK in user.mutations))
user.mutations.Add(TK)
if(!(HEAL in user.mutations))
user.mutations.Add(HEAL)
user.update_mutations()
user.mind.special_role = "Avatar of the Wish Granter"
var/datum/objective/silence/silence = new
silence.owner = user.mind
user.mind.objectives += silence
show_objectives(user.mind)
user << "You have a very bad feeling about this."
return
/obj/machinery/wish_granter_dark
name = "Wish Granter"
desc = "You're not so sure about this, anymore..."
icon = 'icons/obj/device.dmi'
icon_state = "syndbeacon"
light_color = "#458F94"
light_power = 3
light_range = 4
anchored = 1
density = 1
layer = 9
use_power = 0
var/chargesa = 1
var/insistinga = 0
/obj/machinery/wish_granter_dark/attack_hand(var/mob/living/carbon/human/user as mob)
/obj/machinery/wish_granter/attack_hand(var/mob/living/carbon/human/user as mob)
usr.set_machine(src)
if(chargesa <= 0)
@@ -118,10 +51,13 @@
if (!(COLD_RESISTANCE in user.mutations))
user.mutations.Add(COLD_RESISTANCE)
user << "\blue Your body feels warm."
if (!(TK in user.mutations))
user.mutations.Add(TK)
if(!(HEAL in user.mutations))
user.mutations.Add(HEAL)
if (!(XRAY in user.mutations))
user.mutations.Add(XRAY)
user.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS)
user.see_in_dark = 8
user.see_invisible = SEE_INVISIBLE_LEVEL_TWO
user << "\blue The walls suddenly disappear."
user.set_species("Shadow")
@@ -140,28 +76,38 @@
user.mind.special_role = "Avatar of the Wish Granter"
if("The station is corrupt, it must be destroyed")
user << "<B>Your wish is granted, but at a terrible cost...</B>"
user << "The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart."
user << "The Wish Granter punishes you for your wickedness, claiming your soul and slaving you to its own dark purposes."
user.mind.special_role = "Avatar of the Wish Granter"
var/datum/objective/hijack/hijack = new
hijack.owner = user.mind
user.mind.objectives += hijack
user << "<B>Your inhibitions are swept away, the bonds of loyalty broken, you are free to murder as you please!</B>"
user.hallucination += 10
user.adjustBrainLoss(30)
user.show_message("<b>[user]</b> screams!")
playsound(user, 'sound/hallucinations/wail.ogg', 40, 1)
sleep(30)
user << "<span class='warning'>Your mind is assaulted by endless horrors, your only desire is to end it, you must fulfill the Wish Granter's desires!</span>"
var/datum/objective/nuclear/nuclear = new
nuclear.owner = user.mind
user.mind.objectives += nuclear
var/obj_count = 1
for(var/datum/objective/OBJ in user.mind.objectives)
user << "<B>Objective #[obj_count]</B>: [OBJ.explanation_text]"
obj_count++
user.set_species("Shadow")
for(var/obj/machinery/nuclearbomb/N in world)
user << "<span class='warning'>[N.r_code]...!</span>"
user.mind.store_memory("<B>Nuclear Bomb Code</B>: [N.r_code]", 0, 0)
if("I want peace")
user << "<B>Your wish is granted...</B>"
user << "Everything lies silently and then the station, its crew and troubles are gone in a blink of light. You found peace at last."
user.sdisabilities += BLIND
user.sdisabilities += DEAF
user.mind.special_role = "Avatar of the Wish Granter"
chargesa = 1
/////For the Wishgranter///////////
/mob/living/carbon/proc/immortality()
set category = "Immortality"
set category = "Abilities"
set name = "Resurrection"
set desc = "Rise from your grave."
var/mob/living/carbon/C = usr
if(!C.stat)
@@ -169,7 +115,7 @@
return
C << "<span class='notice'>Death is not your end!</span>"
spawn(rand(800,1200))
spawn(rand(400,800))
if(C.stat == DEAD)
dead_mob_list -= C
living_mob_list += C

View File

@@ -88,6 +88,8 @@
var/power_alert_status = 0
var/damage_alert_status = 0
var/noexplode = 0//Used for cases where an exosuit is spawned and turned into wreckage
/obj/mecha/drain_power(var/drain_check)
if(drain_check)
@@ -125,7 +127,7 @@
if(loc)
loc.Exited(src)
if(prob(30))
if(!noexplode && prob(30))
explosion(get_turf(loc), 0, 0, 1, 3)
if(wreckage)
@@ -161,6 +163,7 @@
qdel(pr_inertial_movement)
qdel(pr_give_air)
qdel(pr_internal_damage)
qdel(pr_manage_warnings)
qdel(spark_system)
pr_int_temp_processor = null
pr_give_air = null
@@ -1915,6 +1918,50 @@
return 1
//Used by randomstock.dm in generating damaged exosuits.
//This does an individual check for each piece of equipment on the exosuit, and removes it if
//this probability passes a check
/obj/mecha/proc/lose_equipment(var/probability)
for(var/obj/item/mecha_parts/mecha_equipment/E in equipment)
if (prob(probability))
E.detach(loc)
qdel(E)
//Used by randomstock.dm in generating damaged exosuits.
//Does a random check for each possible type of internal damage, and adds it if it passes
//The probability should be somewhat low unless you just want to saturate it with damage
//Fire is excepted. We're not going to set the exosuit on fire while its in longterm storage
/obj/mecha/proc/random_internal_damage(var/probability)
if (prob(probability))
setInternalDamage(MECHA_INT_TEMP_CONTROL)
if (prob(probability))
setInternalDamage(MECHA_INT_SHORT_CIRCUIT)
if (prob(probability))
setInternalDamage(MECHA_INT_TANK_BREACH)
if (prob(probability))
setInternalDamage(MECHA_INT_CONTROL_LOST)
//Does a number of checks at probability, and alters some configuration values if succeeded
/obj/mecha/proc/misconfigure_systems(var/probability)
if (prob(probability))
internal_tank_valve = rand(0,10000)//Screw up the cabin air pressure.
//This will probably kill the pilot if they dont check it before climbing in
if (prob(probability))
state = 1//Enable maintenance mode. It won't move.
if (prob(probability))
use_internal_tank = !use_internal_tank//Flip internal tank mode on or off
if (prob(probability))
toggle_lights()//toggle the lights
if (prob(probability))//Some settings to screw up the radio
radio.broadcasting = !radio.broadcasting
if (prob(probability))
radio.listening = !radio.listening
if (prob(probability))
radio.set_frequency(rand(1200,1600))
if (prob(probability))
maint_access = 0//Disallow maintenance mode
//////////////////////////////////////////
//////// Mecha global iterators ////////
//////////////////////////////////////////
@@ -1939,6 +1986,9 @@
process(var/obj/mecha/mecha)
if (!mecha)
return
if (!mecha.power_alert_status && mecha.cell)//If we're in the fine status
if (mecha.cell.charge < (mecha.cell.maxcharge*0.3))//but power is below 30%
mecha.power_alert_status = 1//Switch to the alert status

View File

@@ -0,0 +1,452 @@
/*
//Temporary modifiers system, by Nanako
//This system is designed to allow making non-permanant, reversible changes to variables of any atom,
//Though the system will be primarily used for altering properties of mobs, it can work on anything.
//Intended uses are to allow equipment and items that modify a mob's various stats and attributes
//As well as to replace the badly designed chem effects system
This system works through a few main procs which should be overridden:
All overridden procs should contain a call to parent at the start, before any other code
Activate: This applies the effects. its here that you change any variables.
The author is also responsible here for storing any information necessary to later revert these changes
Deactivate: This proc removes the effects. The author is responsible for writing it to reverse the changes cleanly
If using a strength var or any other kind of dynamic determinor of effects
It is very important NOT to factor that in when deactivating, because it may be changed while active
Instead, factor it in while activating and save the delta of the changed values.
that is, how much you added/subtracted
Apply that saved value in reverse when deactivating.
Both activate and deactivate are stateful. Activate will not run if active is true.
Deactivate will not run if active is false
Process: Called once every second while the effect is active. Usually this will only see if its time
to recheck validity, but it can be overridden to add extra per-tick functionality.
When created, a status effect will take the following parameters in new
Mandatory:
1. Affected atom
2. Modifier type
3. Source atom (not mandatory if type is custom)
Optional:
4. Source data
5. Strength
6. Duration
7. Check interval
//The affected atom is mandatory, without something to affect the modifier cannot exist
//Modifier type is one of a selection of constants which determines the automated validity checking.
It does not enforce anything about the changes or other functionality. A valid option is mandatory
//Source object is the thing that this modifier is based on, or anchored to.
//It is used as a point of reference in validity checks. Usually mandatory but some types do not require it
//Source data provides additional information for validity, such as a maximum range from the source.
//Only required for certain types
//Strength can be passed in by the caller and used insetting or removing the variable changes.
//It is never required for anything and not incorporated in base behaviour
//Duration can be used for any type except custom. The modifier will cease to be valid
//this long after it is created
//Duration is decremented every proc until it falls below zero.
//This is used so that duration can be refreshed or increased before the modifier expires to prolong it
//Check interval is a time, in deciseconds, between validity checks. a >0 value is required here,
//the default is 300 (every 30 seconds),
//Check interval is used to generate a world time at which the next check will run
Please note that automated validity checking is primarily as a safety, to ensure things aren't left
when they shouldn't be. If you desire something removed in a timely manner, it's recommended to manually
call the effect's end proc from your code when you're done with it. For example, if a piece of equipment
applying a modifier is taken off.
Setting the check interval very low just to cause the effect to be removed quickly is bad practise
it should be avoided in favour of manual removal where possible
*/
//Modifier types
//These are needed globally and cannot be undefined
#define MODIFIER_EQUIPMENT 1
//The status effect remains valid as long as it is worn upon the affected mob.
//Worn here means it must be held in a valid equip slot, which does not include pockets, storage, or held in hands.
//The affected atom must be a mob
#define MODIFIER_ITEM 2
//The modifier remains valid as long as the item is in the target's contents,
//no matter how many layers deep, if it can be found by recursing up, it is valid
//This is essentially a more permissable version of equipment, and works when held, in backpacks, pockets, etc
//It can also be used on non-mob targets
#define MODIFIER_REAGENT 3
//The status effect remains valid as long as the dose of this chemical in a mob's reagents is above
//a specified dose value (specified in source data).
//The default of zero will keep it valid if the chemical is in them at all
//This checks for the reagent by type, in any of a mob's reagent holders - touching, blood, ingested
//Affected atom must be a mob
#define MODIFIER_AURA 4
//The modifier remains valid as long as the target's turf is within a range of the source's turf
//The range is defined in source data
//A range of zero is still valid if source and target are on the same turf. Sub-zero range is invalid
//Works on any affected atom
#define MODIFIER_TIMED 5
//The modifier remains valid as long as the duration has not expired.
//Note that a duration can be used on any time, this type is just one that does not
//check anything else but duration.
//Does not require or use a source atom
//Duration is mandatory for this type.
//Works on any atom
#define MODIFIER_CUSTOM 6
//The validity check will always return 1. The author is expected to override
//it with custom validity checking behaviour.
//Does not require or use a source atom
//Does not support duration
//Override Modes:
//An override parameter is passed in with New, which determines what to do if a modifier of
//the same type already exists on the target
#define MODIFIER_OVERRIDE_DENY 0
//The default. If a modifier of our type already exists, the new one is discarded. It will Qdel itself
//Without adding itself to any lists
#define MODIFIER_OVERRIDE_NEIGHBOR 1
//The new modifier ignores the existing one, and adds itself to the list alongside it
//This is not recommended but you may have a specific application
//Using the strength var and updating the effects is preferred if you want to stack multiples
//of the same type of modifier on one mob
#define MODIFIER_OVERRIDE_REPLACE 2
//Probably the most common nondefault and most useful. If an old modifier of the same type exists,
//Then the old one is first stopped without suspending, and deleted.
//Then the new one will add itself as normal
#define MODIFIER_OVERRIDE_REFRESH 3
//This mode will overwrite the variables of the old one with our new values
//It will also force it to remove and reapply its effects
//This is useful for applying a lingering modifier, by refreshing its duration
#define MODIFIER_OVERRIDE_STRENGTHEN 4
//Almost identical to refresh, but it will only apply if the new modifer has a higher strength value
//If the existing modifier's strength is higher than the new one, the new is discarded
#define MODIFIER_OVERRIDE_CUSTOM 5
//Calls a custom override function to be overwritten
//This is the main proc you should call to create a modifier on a target object
/datum/proc/add_modifier(var/typepath, var/_modifier_type, var/_source = null, var/_source_data = 0, var/_strength = 0, var/_duration = 0, var/_check_interval = 0, var/override = 0)
var/datum/modifier/D = new typepath(src, _modifier_type, _source, _source_data, _strength, _duration, _check_interval)
if (D && !D.gcDestroyed)
return D.handle_registration(override)
else
return null//The modifier must have failed creation and deleted itself
/datum/modifier
//Config
var/check_interval = 300//How often, in deciseconds, we will recheck the validity
var/atom/target = null
var/atom/source = null
var/modifier_type = 0
var/source_data = 0
var/strength = 0
var/duration = null
//A list of equip slots which are considered 'worn'.
//For equipment modifier type to be valid, the source object must be in a mob's contents
//and equipped to one of these whitelisted slots
//This list can be overridden if you want a custom slot whitelist
var/list/valid_equipment_slots = list(slot_back, slot_wear_mask, slot_handcuffed, slot_belt, \
slot_wear_id, slot_l_ear, slot_glasses, slot_gloves, slot_head, slot_shoes, slot_wear_suit, \
slot_w_uniform,slot_legcuffed, slot_r_ear, slot_legs, slot_tie)
//Operating Vars
var/active = 0//Whether or not the effects are currently applied
var/next_check = 0
var/last_tick = 0
//If creation of a modifier is successful, it will return a reference to itself
//If creation fails for any reason, it will return null as well as giving some debug output
/datum/modifier/New(var/atom/_target, var/_modifier_type, var/_source = null, var/_source_data = 0, var/_strength = 0, var/_duration = 0, var/_check_interval = 0)
..()
target = _target
modifier_type = _modifier_type
source = _source
source_data = _source_data
strength = _strength
last_tick = world.time
if (_duration)
duration = _duration
if (_check_interval)
check_interval = _check_interval
if (!target || !modifier_type)
return invalid_creation("No target and/or no modifier type was submitted")
switch (modifier_type)
if (MODIFIER_EQUIPMENT)
if (!istype(target, /mob))
return invalid_creation("Equipment type requires a mob target")
if (!source || !istype(source, /obj))
return invalid_creation("Equipment type requires an object source")
//TODO: Port equip slot var
if (MODIFIER_ITEM)
if (!source || !istype(source, /obj))
return invalid_creation("Item type requires a source")
if (MODIFIER_REAGENT)
if (!istype(target, /mob) || !istype(source, /datum/reagent))
return invalid_creation("Reagent type requires a mob target and a reagent source")
if (MODIFIER_AURA)
if (!source || !istype(source, /atom))
return invalid_creation("Aura type requires an atom source")
if (MODIFIER_TIMED)
if (!duration || duration <= 0)
return invalid_creation("Timed type requires a duration")
if (MODIFIER_CUSTOM)
//No code here, just to prevent else
else
return invalid_creation("Invalid or unrecognised modifier type")//Not a valid modifier type.
return 1
/datum/modifier/proc/handle_registration(var/override = 0)
var/datum/modifier/existing = null
for (var/datum/modifier/D in target.modifiers)
if (D.type == type)
existing = D
if (!existing)
processing_modifiers += src
target.modifiers += src
activate()
return src
else
return handle_override(override, existing)
/datum/modifier/proc/activate()
if (!gcDestroyed && !active && target)
active = 1
return 1
return 0
/datum/modifier/proc/deactivate()
active = 0
return 1
/datum/modifier/proc/process()
if (!active)
last_tick = world.time
return 0
if (!isnull(duration))duration -= world.time - last_tick
if (world.time > next_check)
last_tick = world.time
return check_validity()
last_tick = world.time
return 1
/datum/modifier/proc/check_validity()
next_check = world.time + check_interval
if (!target || target.gcDestroyed)
return validity_fail("Target is gone!")
if (modifier_type == MODIFIER_CUSTOM)
if (custom_validity())
return 1
else
return validity_fail("Custom failed")
if (!isnull(duration) && duration <= 0)
return validity_fail("Duration expired")
else if (modifier_type == MODIFIER_TIMED)
return 1
if (!source || source.gcDestroyed)//If we're not timed or custom, then we need a source. If our source is gone, we are invalid
return validity_fail("Source is gone and we need one")
switch (modifier_type)
if (MODIFIER_EQUIPMENT)
if (source.loc != target)
return validity_fail("Not in contents of mob")
var/obj/item/I = source
if (!I.equip_slot || !(I.equip_slot in valid_equipment_slots))
return validity_fail("Not equipped in the correct place")
//TODO: Port equip slot var. this cant be done properly without it. This is a temporary implementation
if (MODIFIER_ITEM)
if (!source.find_up_hierarchy(target))//If source is somewhere inside target, this will be true
return validity_fail("Not found in parent hierarchy")
if (MODIFIER_REAGENT)
var/totaldose = 0
if (!istype(source, /datum/reagent))//this shouldnt happen
return validity_fail("Source is not a reagent!")
var/ourtype = source.type
for (var/datum/reagent/R in target.reagents.reagent_list)
if (istype(R, ourtype))
totaldose += R.dose
if (istype(target, /mob/living))
var/mob/living/L = target
for (var/datum/reagent/R in L.ingested.reagent_list)
if (istype(R, ourtype))
totaldose += R.dose
if (istype(target, /mob/living/carbon))
var/mob/living/carbon/C = target
for (var/datum/reagent/R in C.bloodstr.reagent_list)
if (istype(R, ourtype))
totaldose += R.dose
for (var/datum/reagent/R in C.touching.reagent_list)
if (istype(R, ourtype))
totaldose += R.dose
if (totaldose < source_data)
return validity_fail("Dose is too low!")
if (MODIFIER_AURA)
if (!(get_turf(target) in range(source_data, get_turf(source))))
return validity_fail("Target not in range of source")
return 1
//Override this without a call to parent, for custom validity conditions
/datum/modifier/proc/custom_validity()
return 1
/datum/modifier/proc/validity_fail(var/reason)
//world << "MODIFIER VALIDITY FAIL: [reason]"
qdel(src)
return 0
/datum/modifier/proc/invalid_creation(var/reason)
log_debug("ERROR: [src] MODIFIER CREATION FAILED on [target]: [reason]")
qdel(src)
return 0
//called by any object to either pause or remove the proc.
/datum/modifier/proc/stop(var/instant = 0, var/suspend = 0)
//Instant var removes us from the lists immediately, instead of waiting til next frame when qdel goes through
if (instant)
if (target)
target.modifiers -= src
processing_modifiers -= src
if (suspend)
deactivate()
else
qdel(src)
//Suspends and immediately restarts the proc, thus reapplying its effects
/datum/modifier/proc/refresh()
deactivate()
activate()
/datum/modifier/Destroy()
if (active)
deactivate()
if (target)
target.modifiers -= src
processing_modifiers -= src
..()
//Handles overriding an existing modifier of the same type.
//This function should return either src or the existing, depending on whether or not src will be kept
/datum/modifier/proc/handle_override(var/override, var/datum/modifier/existing)
switch(override)
if (MODIFIER_OVERRIDE_DENY)
qdel(src)
return existing
if (MODIFIER_OVERRIDE_NEIGHBOR)
processing_modifiers += src
target.modifiers += src
return src
if (MODIFIER_OVERRIDE_REPLACE)
existing.stop()
processing_modifiers += src
target.modifiers += src
activate()
return src
if (MODIFIER_OVERRIDE_REFRESH)
existing.strength = strength
existing.duration = duration
existing.source = source
existing.source_data = source_data
if (existing.check_validity())
existing.refresh()
qdel(src)
return existing
else
qdel(src)
return null//this should only happen if you overwrote the existing with bad values.
//It will result in both existing and src being deleted
//The null return will allow the source to see this went wrong and remake the modifier
if (MODIFIER_OVERRIDE_STRENGTHEN)
if (strength > existing.strength)
existing.strength = strength
existing.duration = duration
existing.source = source
existing.source_data = source_data
if (existing.check_validity())
existing.refresh()
qdel(src)
return existing
qdel(src)
return null
qdel(src)
return existing
if (MODIFIER_OVERRIDE_CUSTOM)
return custom_override(existing)
else
qdel(src)
return existing
//This function should be completely overwritten, without a call to parent, to specify custom override
/datum/modifier/proc/custom_override(var/datum/modifier/existing)
qdel(src)
return existing

View File

@@ -0,0 +1,73 @@
//Stimulant modifier. Applied in varying strengths by hyperzine and caffienated drinks
//Increases sprinting speed, walk speed, and stamina regen
/datum/modifier/stimulant
var/sprint_speed_added = 0
var/regen_added = 0
var/delay_added = 0
/datum/modifier/stimulant/activate()
..()
if (isliving(target))
var/mob/living/L = target
sprint_speed_added = 0.2 * strength
L.sprint_speed_factor += sprint_speed_added
regen_added = L.stamina_recovery * 0.3 * strength
L.stamina_recovery += regen_added
delay_added = -1.5 * strength
L.move_delay_mod += delay_added
/datum/modifier/stimulant/deactivate()
..()
if (isliving(target))
var/mob/living/L = target
L.sprint_speed_factor -= sprint_speed_added
L.stamina_recovery -= regen_added
L.move_delay_mod -= delay_added
//Adrenaline, granted by synaptizine and inaprovaline, with different strengths for each
//Allows the body to endure more, increasing speed a little, stamina a lot, stamina regen a lot,
//and reducing sprint costs
//Synaptizine applies it at strength 1, inaprovaline applies it at strength 0.6
//Is applied using strengthen override mode, so synaptizine will replace inaprovaline if both are present
/datum/modifier/adrenaline
var/speed_added = 0
var/stamina_added = 0
var/cost_added = 0
var/regen_added = 0
/datum/modifier/adrenaline/activate()
..()
if (isliving(target))
var/mob/living/L = target
speed_added += 0.1*strength
L.sprint_speed_factor += speed_added
stamina_added = L.max_stamina * strength
L.max_stamina += stamina_added
cost_added = -0.35 * strength
L.sprint_cost_factor += cost_added
regen_added = max ((L.stamina_recovery * 0.7 * strength), 5)
L.stamina_recovery += regen_added
/datum/modifier/adrenaline/deactivate()
..()
if (isliving(target))
var/mob/living/L = target
L.stamina_recovery -= regen_added
L.max_stamina -= stamina_added
L.sprint_cost_factor -= cost_added
L.sprint_speed_factor -= speed_added

View File

@@ -1,4 +1,4 @@
// baystation12 posters
// aurora station posters
/datum/poster/bay_1
icon_state="bsposter1"
name = "Unlucky Space Explorer"
@@ -286,5 +286,45 @@
/datum/poster/bay_58
icon_state="bsposter58"
name = "space carp information poster"
desc = "This poster showcases an old spacer saying on the dangers of migrant space carp."
name = "space bear information poster"
desc = "This poster displays a picture of a legendary space bear."
/datum/poster/bay_59
icon_state = "bsposter59"
name = "ATLAS poster"
desc = "ATLAS: For all of Humanity."
/datum/poster/bay_60
icon_state = "bsposter60"
name = "N.S.S. Aurora"
desc = "This poster is a picture of the old, now defunct, N.S.S. Aurora. Commissioned in 2454 and decommissioned in the early days of 2458."
/datum/poster/bay_61
icon_state = "bsposter61"
name = "Xenobiology Safety Protocols"
desc = "This posters warms the crew about the dangers of xenobiology outbreaks."
/datum/poster/bay_62
icon_state = "bsposter62"
name = "Xenobiology Division"
desc = "This one depicts a green skrell research director doing autopsy on an alien lifeform."
/datum/poster/bay_63
icon_state = "bsposter63"
name = "Suit Sensors"
desc = "This particular one depicts a female doctor tending to an injured crewmember. It says; \"Remember to enable your suit sensors!\"."
/datum/poster/bay_64
icon_state = "bsposter64"
name = "Maintenance Drones"
desc = "This particular one depicts a maintenance drone. It reminders the crew to don't disturb them when they are doing repairs."
/datum/poster/bay_65
icon_state = "bsposter65"
name = "Importance of Plasma"
desc = "A corporate morale poster showing three forms of plasma. Teaching the very basics of this really important substance."
/datum/poster/bay_66
icon_state = "bsposter66"
name = "BFG 9000"
desc = "A picture of a big freakin' gun."

View File

@@ -3,8 +3,8 @@
proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = UP|DOWN)
src = null //so we don't abort once src is deleted
spawn(0)
var/power = max(0,devastation_range) * 2 + max(0,heavy_impact_range) + max(0,light_impact_range)
if(config.use_recursive_explosions)
var/power = devastation_range * 2 + heavy_impact_range + light_impact_range //The ranges add up, ie light 14 includes both heavy 7 and devestation 3. So this calculation means devestation counts for 4, heavy for 2 and light for 1 power, giving us a cap of 27 power.
explosion_rec(epicenter, power)
return
@@ -28,30 +28,73 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
var/far_dist = 0
far_dist += heavy_impact_range * 5
far_dist += devastation_range * 20
// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
// Stereo users will also hear the direction of the explosion!
// Calculate far explosion sound range. Only allow the sound effect for heavy/devastating explosions.
// 3/7/14 will calculate to 80 + 35
var/volume = 10 + (power * 20)
var/frequency = get_rand_frequency()
var/closedist = round(max_range + world.view - 2, 1)
//Whether or not this explosion causes enough vibration to send sound or shockwaves through the station
var/vibration = 1
if (istype(epicenter,/turf/space))
vibration = 0
for (var/turf/T in range(src, max_range))
if (!istype(T,/turf/space))
//If there is a nonspace tile within the explosion radius
//Then we can reverberate shockwaves through that, and allow it to be felt in a vacuum
vibration = 1
if (vibration)
for(var/mob/M in player_list)
// Double check for client
var/reception = 2//Whether the person can be shaken or hear sound
//2 = BOTH
//1 = shockwaves only
//0 = no effect
if(M && M.client)
var/turf/M_turf = get_turf(M)
if(M_turf && M_turf.z == epicenter.z)
var/dist = get_dist(M_turf, epicenter)
// If inside the blast radius + world.view - 2
if(dist <= round(max_range + world.view - 2, 1))
M.playsound_local(epicenter, get_sfx("explosion"), 100, 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound
if(M_turf && M_turf.z == epicenter.z)
if (istype(M_turf,/turf/space))
//If the person is standing in space, they wont hear
//But they may still feel the shaking
reception = 0
for (var/turf/T in range(M, 1))
if (!istype(T,/turf/space))
//If theyre touching the hull or on some extruding part of the station
reception = 1//They will get screenshake
break
if (!reception)
continue
var/dist = get_dist(M_turf, epicenter)
if (reception == 2 && (M.ear_deaf <= 0 || !M.ear_deaf))//Dont play sounds to deaf people
// If inside the blast radius + world.view - 2
if(dist <= closedist)
M.playsound_local(epicenter, get_sfx("explosion"), min(100, volume), 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound
//You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
else if(dist <= far_dist)
var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
else
volume = M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', volume, 1, frequency, usepressure = 0, falloff = 1000)
//Playsound local will return the final volume the sound is actually played at
//It will return 0 if the sound volume falls to 0 due to falloff or pressure
//Also return zero if sound playing failed for some other reason
//Deaf people will feel vibrations though
if (volume > 0)//Only shake camera if someone was close enough to hear it
shake_camera(M, min(60,max(2,(power*18) / dist)), min(3.5,((power*3) / dist)),0.05)
//Maximum duration is 6 seconds, and max strength is 3.5
//Becuse values higher than those just get really silly
var/close = range(world.view+round(devastation_range,1), epicenter)
// to all distanced mobs play a different sound
for(var/mob/M in world) if(M.z == epicenter.z) if(!(M in close))
// check if the mob can hear
if(M.ear_deaf <= 0 || !M.ear_deaf) if(!istype(M.loc,/turf/space))
M << 'sound/effects/explosionfar.ogg'
if(adminlog)
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[epicenter.x];Y=[epicenter.y];Z=[epicenter.z]'>JMP</a>)")
log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ")
@@ -104,7 +147,6 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
return 1
proc/secondaryexplosion(turf/epicenter, range)
for(var/turf/tile in range(range, epicenter))
tile.ex_act(2)

View File

@@ -243,6 +243,7 @@
// note this isn't called during the initial dressing of a player
/obj/item/proc/equipped(var/mob/user, var/slot)
layer = 20
equip_slot = slot
if(user.client) user.client.screen |= src
if(user.pulling == src) user.stop_pulling()
return
@@ -654,3 +655,47 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
/obj/item/proc/pwr_drain()
return 0 // Process Kill
//a proc that any worn thing can call to update its itemstate
//Should be cheaper than calling regenerate icons on the mob
/obj/item/proc/update_worn_icon()
if (!equip_slot || !istype(loc, /mob))
return
var/mob/M = loc
switch (equip_slot)
if (slot_back)
M.update_inv_back()
if (slot_wear_mask)
M.update_inv_wear_mask()
if (slot_l_hand)
M.update_inv_l_hand()
if (slot_r_hand)
M.update_inv_r_hand()
if (slot_belt)
M.update_inv_belt()
if (slot_wear_id)
M.update_inv_wear_id()
if (slot_l_ear)
M.update_inv_ears()
if (slot_r_ear)
M.update_inv_ears()
if (slot_glasses)
M.update_inv_glasses()
if (slot_gloves)
M.update_inv_gloves()
if (slot_head)
M.update_inv_head()
if (slot_shoes)
M.update_inv_shoes()
if (slot_wear_suit)
M.update_inv_wear_suit()
if (slot_w_uniform)
M.update_inv_w_uniform()
if (slot_l_store)
M.update_inv_pockets()
if (slot_r_store)
M.update_inv_pockets()
if (slot_s_store)
M.update_inv_s_store()

View File

@@ -343,6 +343,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
return id
/obj/item/device/pda/AltClick(var/mob/user)
if (ismob(src.loc))
verb_remove_id()
/obj/item/device/pda/MouseDrop(obj/over_object as obj, src_location, over_location)

View File

@@ -271,7 +271,15 @@
on = 0
update_icon()
/obj/item/device/flashlight/glowstick/attack_self(mob/user)
/obj/item/device/flashlight/glowstick/attack_self(var/mob/living/user)
if(((CLUMSY in user.mutations)) && prob(50))
user << "<span class='notice'>You break \the [src] apart, spilling its contents everywhere!</span>"
fuel = 0
new /obj/effect/decal/cleanable/greenglow(get_turf(user))
user.apply_effect((rand(15,30)),IRRADIATE,blocked = user.getarmor(null, "rad"))
qdel(src)
return
if(!fuel)
user << "<span class='notice'>\The [src] has already been used.</span>"

View File

@@ -1,6 +1,6 @@
#define STATUS_INACTIVE 0
#define STATUS_ACTIVE 1
#define STATUS_BROKEN 2
#define STATUS_BROKEN -1
#define LAYER_ATTACHED 3.2
#define LAYER_NORMAL 3
@@ -8,50 +8,75 @@
/obj/item/device/magnetic_lock
name = "magnetic door lock"
desc = "A large, ID locked device used for completely locking down airlocks."
icon = 'icons/obj/magnetic_locks/centcom.dmi'
icon_state = "inactive"
icon = 'icons/obj/magnetic_locks.dmi'
icon_state = "inactive_CENTCOM"
//icon_state = "inactive"
w_class = 3
req_access = list(103)
req_access = list(access_cent_specops)
health = 90
var/department = "CENTCOM"
var/status = 0
var/locked = 1
var/hacked = 0
var/constructionstate = 0
var/drainamount = 20
var/drain_per_second = 3
var/last_process_time = 0
var/obj/machinery/door/airlock/target_node1 = null
var/obj/machinery/door/airlock/target_node2 = null
var/obj/machinery/door/airlock/target = null
var/obj/item/weapon/cell/powercell
var/obj/item/weapon/cell/internal_cell
/obj/item/device/magnetic_lock/security
icon = 'icons/obj/magnetic_locks/security.dmi'
department = "Security"
req_access = list(1)
icon_state = "inactive_Security"
req_access = list(access_security)
/obj/item/device/magnetic_lock/engineering
icon = 'icons/obj/magnetic_locks/engineering.dmi'
department = "Engineering"
icon_state = "inactive_Engineering"
req_access = null
req_one_access = list(11, 24)
req_one_access = list(access_engine_equip, access_atmospherics)
/obj/item/device/magnetic_lock/New()
..()
powercell = new /obj/item/weapon/cell/high()
internal_cell = new /obj/item/weapon/cell/device()
/obj/item/device/magnetic_lock/examine()
..()
if (istext(department))
desc += " It is painted with [department] colors."
update_icon()
/obj/item/device/magnetic_lock/examine(mob/user)
..(user)
if (status == STATUS_BROKEN)
usr << "<span class='danger'>It looks broken!</span>"
user << "<span class='danger'>It looks broken!</span>"
else
if (powercell)
var/power = round(powercell.charge / powercell.maxcharge * 100)
usr << "\blue The powercell is at [power]% charge."
user << "<span class='notice'>The powercell is at [power]% charge.</span>"
else
usr << "\red It has no powercell to power it!"
var/int_power = round(internal_cell.charge / internal_cell.maxcharge * 100)
user << "<span class='warning'>It has no powercell to power it! Internal cell is at [int_power]% charge.</span>"
/obj/item/device/magnetic_lock/attack_hand(var/mob/user)
if (status == STATUS_ACTIVE)
ui_interact(user)
add_fingerprint(user)
if (constructionstate == 1 && powercell)
powercell.update_icon()
powercell.add_fingerprint(user)
user.put_in_active_hand(powercell)
user << "You remove \the [powercell]."
powercell = null
setconstructionstate(2)
else if (anchored)
if (!locked)
detach()
else
user << "<span class='warning'>\The [src] is locked in place!</span>"
else
..()
@@ -64,6 +89,24 @@
user << "<span class='danger'>[src] is broken beyond repair!</span>"
return
if (istype(I, /obj/item/weapon/card/id))
if (!constructionstate && !hacked)
if (check_access(I))
locked = !locked
playsound(src, 'sound/machines/ping.ogg', 30, 1)
var/msg = "[I] through \the [src] and it [locked ? "locks" : "unlocks"] with a beep."
var/pos_adj = "[user.name] swipes \his "
var/fp_adj = "You swipe your "
user.visible_message("<span class='warning'>[addtext(pos_adj, msg)]</span>", "<span class='notice'>[addtext(fp_adj, msg)]</span>")
update_icon()
else
playsound(src, 'sound/machines/buzz-sigh.ogg', 30, 1)
user << span("warning", "\The [src] buzzes as you swipe your [I].")
return
else
user << "<span class='danger'>You cannot swipe your [I] through [src] with it partially dismantled!</span>"
return
if (istype(I, /obj/item/weapon) && user.a_intent == "hurt")
if (I.force >= 8)
user.visible_message("<span class='danger'>[user] bashes [src] with [I]!</span>", "<span class='danger'>You strike [src] with [I], damaging it!</span>")
@@ -80,220 +123,283 @@
emagcard.uses--
visible_message("<span class='danger'>[src] sparks and falls off the door!</span>", "<span class='danger'>You emag [src], frying its circuitry[status == STATUS_ACTIVE ? " and making it drop onto the floor" : ""]!</span>")
setstatus(STATUS_BROKEN)
status = STATUS_BROKEN
if (target)
detach()
update_icon()
return
if (status == STATUS_ACTIVE && istype(I, /obj/item/weapon/card/id))
if (check_access(I) && !constructionstate)
user << "<span class='notice'>You swipe your [I] through [src], making it drop onto the floor with a thud.</span>"
setstatus(STATUS_INACTIVE)
return
else if (constructionstate)
user << "<span class='danger'>You cannot swipe your [I] through [src] with it partially dismantled!</span>"
return
if (iswelder(I))
var/obj/item/weapon/weldingtool/WT = I
if (WT.remove_fuel(2, user))
user.visible_message(span("notice", "[user] starts welding the metal shell of [src]."), span("notice", "You start [hacked ? "repairing" : "welding open"] the metal covering of [src]."))
playsound(loc, 'sound/items/Welder.ogg', 50, 1)
overlays += "overlay_welding"
if (do_after(user, 25, 1))
user << span("notice", "You are able to [hacked ? "repair" : "weld through"] the metal shell of [src].")
if (hacked) locked = 1
else locked = 0
hacked = !hacked
overlays -= "overlay_welding"
else
user << "<span class='danger'>A red light flashes on [src] as you swipe your [I] through it.</span>"
flick("deny",src)
overlays -= "overlay_welding"
update_icon()
return
if (istype(I, /obj/item/weapon/screwdriver))
user << "<span class='notice'>You unfasten and remove the plastic cover from [src], revealing a thick metal shell.</span>"
playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1)
if (iscrowbar(I))
if (!locked)
user << span("notice", "You pry the cover off [src].")
setconstructionstate(1)
else
user << span("notice", "You try to pry the cover off [src] but it doesn't budge.</span>")
return
if (1)
if (istype(I, /obj/item/weapon/screwdriver))
user << "<span class='notice'>You put the metal cover of back onto [src], and screw it tight.</span>"
playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1)
if (istype(I, /obj/item/weapon/cell))
if (powercell)
user << span("notice","There's already a powercell in \the [src].")
return
if (iscrowbar(I))
user << span("notice", "You wedge the cover back in place.")
setconstructionstate(0)
return
if (2)
if (isscrewdriver(I))
user << span("notice", "You unscrew and remove the wiring cover from \the [src].")
playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1)
setconstructionstate(3)
return
if (iscrowbar(I))
user << span("notice", "You wedge the cover back in place.")
setconstructionstate(0)
return
if (istype(I, /obj/item/weapon/cell))
if (!powercell)
user << span("notice","You place the [I] inside \the [src].")
user.drop_item()
I.loc = src
powercell = I
setconstructionstate(1)
return
if (istype(I, /obj/item/weapon/crowbar))
if (isnull(powercell))
user << "<span class='notice'>There is no powercell in \the [src].</span>"
return
user << "<span class='notice'>You remove \the [powercell] from \the [src].</span>"
if (loc == user)
powercell.forceMove(user.loc)
else
powercell.forceMove(loc)
powercell = null
return
if (istype(I, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = I
if (WT.remove_fuel(1, user))
user.visible_message("<span class='notice'>[user] starts welding through the metal shell of [src].</span>", "<span class='notice'>You start welding through the metal covering of [src]</span>")
playsound(loc, 'sound/items/Welder.ogg', 50, 1)
if (do_after(user, 25))
user << "<span class='notice'>You are able to weld through the metal shell of [src].</span>"
setconstructionstate(2)
return
if (2)
if (istype(I, /obj/item/weapon/crowbar))
user << "<span class='notice'>You pry off the metal covering from [src].</span>"
playsound(loc, 'sound/items/Crowbar.ogg', 50, 1)
setconstructionstate(3)
return
if (3)
if (istype(I, /obj/item/weapon/wirecutters))
user << "<span class='notice'>You cut the wires connecting the [src]'s magnets to their powersupply, [target ? "making the device fall off [target] and rendering it unusable." : "rendering the device unusable."]</span>"
if (iswirecutter(I))
user << span("notice", "You cut the wires connecting the [src]'s magnets to their internal powersupply, [target ? "making the device fall off [target] and rendering it unusable." : "rendering the device unusable."]")
playsound(loc, 'sound/items/Wirecutter.ogg', 50, 1)
setconstructionstate(4)
return
/obj/item/device/magnetic_lock/process()
if (powercell && powercell.charge > drainamount)
powercell.charge -= drainamount
else
if (powercell)
powercell.charge = 0
visible_message("<span class='danger'>[src] beeps loudly and falls off \the [target]; its powercell having run out of power.</span>")
setstatus(STATUS_INACTIVE)
/obj/item/device/magnetic_lock/proc/attachto(var/obj/machinery/door/airlock/newtarget, var/mob/user as mob)
if (status == STATUS_BROKEN)
user << "<span class='danger'>[src] is damaged beyond repair! It cannot be used!</span>"
if (isscrewdriver(I))
user << span("notice", "You replace and screw tight the wiring cover from \the [src].")
playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1)
setconstructionstate(2)
return
if (4)
if (iswirecutter(I))
user << span("notice", "You repair the wires connecting the [src]'s magnets to their internal powersupply")
setconstructionstate(3)
return
/obj/item/device/magnetic_lock/process()
var/obj/item/weapon/cell/C = powercell // both of these are for viewing ease
var/obj/item/weapon/cell/BU = internal_cell
var/delta_sec = (world.time - last_process_time) / 10
var/drainamount = drain_per_second * delta_sec
if (C)
if (C.charge > drainamount)
C.charge -= drainamount
var/int_diff = min(drainamount, BU.maxcharge - BU.charge)
if (C.charge > int_diff && BU.charge != BU.maxcharge)
if (int_diff < drainamount)
BU.charge = BU.maxcharge
C.charge -= int_diff
else
BU.charge += drainamount
C.charge -= drainamount
else if (BU.charge > (drainamount - C.charge))
var/diff = drainamount - C.charge
C.charge = 0
BU.charge -= diff
else
BU.charge = 0
visible_message(span("danger", "[src] beeps loudly and falls off \the [target]; its powercell having run out of power."))
detach(0)
else if (BU.charge > drainamount)
BU.charge -= drainamount
else
BU.charge = 0
visible_message(span("danger", "[src] beeps loudly and falls off \the [target]; its powercell having run out of power."))
detach(0)
last_process_time = world.time
/obj/item/device/magnetic_lock/proc/check_target(var/obj/machinery/door/airlock/newtarget, var/mob/user as mob)
if (status == STATUS_BROKEN)
user << span("danger", "[src] is damaged beyond repair! It cannot be used!")
return 0
if (hacked)
user << span("danger", "[src] buzzes; it can't be used until you repair it!")
return 0
if (!newtarget.density || newtarget.operating)
user << "<span class='danger'>[newtarget] must be closed before you can attach [src] to it!</span>"
return
user << span("danger", "[newtarget] must be closed before you can attach [src] to it!")
return 0
if (newtarget.p_open)
user << "<span class='danger'>You must close [newtarget]'s maintenance panel before attaching [src] to it!</span>"
return
user << span("danger", "You must close [newtarget]'s maintenance panel before attaching [src] to it!")
return 0
if (!user.Adjacent(newtarget))
user << span("danger", "You must stand next to [newtarget] while attaching it!")
return 0
return 1
/obj/item/device/magnetic_lock/proc/attachto(var/obj/machinery/door/airlock/newtarget, var/mob/user as mob)
if (!check_target(newtarget, user)) return
user.visible_message("<span class='notice'>[user] starts mounting [src] onto [newtarget].</span>", "<span class='notice'>You begin mounting [src] onto [newtarget].</span>")
if (do_after(user, 35, 1))
if (status == STATUS_BROKEN)
user << "<span class='danger'>[src] is damaged beyond repair! It cannot be used!</span>"
if (!check_target(newtarget, user)) return
if(!internal_cell.charge)
user << "<span class='warning'>\The [src] looks dead and out of power.</span>"
return
if (!newtarget.density)
user << "<span class='danger'>[newtarget] must be closed before you can attach [src] to it!</span>"
var/direction = get_dir(user, newtarget)
if ((direction in alldirs) && !(direction in cardinal))
direction = turn(direction, -45)
if (check_neighbor_density(get_turf(newtarget.loc), direction))
direction = turn(direction, 90)
if (check_neighbor_density(get_turf(newtarget.loc), direction))
user << "<span class='warning'>There is something in the way of \the [newtarget]!</span>"
return
if (newtarget.p_open)
user << "<span class='danger'>You must close [newtarget]'s maintenance panel before attaching [src] to it!</span>"
return
if (is_type_in_oview(/obj/machinery/door/airlock, 1, newtarget))
if (alert("Brace adjacent airlocks?",,"Yes", "No") == "Yes")
if (!check_target(newtarget, user)) return
for (var/obj/machinery/door/airlock/A in get_step(newtarget.loc, turn(direction, -90)))
if (istype(A, newtarget.type))
if (!check_target(A, user)) return
target_node1 = A
target_node1.bracer = src
break
for (var/obj/machinery/door/airlock/B in get_step(newtarget.loc, turn(direction, 90)))
if (istype(B, newtarget.type))
if (!check_target(B, user)) return
target_node2 = B
target_node2.bracer = src
break
user.visible_message("<span class='notice'>[user] attached [src] onto [newtarget] and flicks it on. The magnetic lock now seals [newtarget].</span>", "<span class='notice'>You attached [src] onto [newtarget] and switched on the magnetic lock.</span>")
user.drop_item()
setstatus(STATUS_ACTIVE, newtarget)
return
/obj/item/device/magnetic_lock/proc/setstatus(var/newstatus, var/obj/machinery/door/airlock/newtarget as obj)
switch (newstatus)
if (STATUS_INACTIVE)
if (status != STATUS_ACTIVE)
return
if (!target)
return
detach()
icon_state = "inactive"
status = newstatus
if (STATUS_ACTIVE)
if (status != STATUS_INACTIVE)
return
if (!newtarget)
return
forceMove(get_step(newtarget.loc, reverse_direction(direction)))
set_dir(reverse_direction(direction))
status = STATUS_ACTIVE
attach(newtarget)
icon_state = "active"
status = newstatus
if (STATUS_BROKEN)
spark()
if (target)
var/playflick = 1
if (constructionstate)
playflick = 0
detach(playflick)
icon_state = "broken"
status = newstatus
return
/obj/item/device/magnetic_lock/proc/setconstructionstate(var/newstate)
constructionstate = newstate
if (newstate == 0)
if (status == STATUS_ACTIVE)
icon_state = "active"
else
icon_state = "inactive"
else if (newstate == 2)
flick("deconstruct_2_anim", src)
if (!powercell && newstate == 1)
setconstructionstate(2)
return
else if (newstate == 4)
setstatus(STATUS_BROKEN)
else
icon_state = "deconstruct_[constructionstate]"
detach(playflick = 0)
update_icon()
constructionstate = newstate
update_icon()
/obj/item/device/magnetic_lock/proc/detach(var/playflick = 1)
if (target)
if (playflick)
spawn(-15) flick("release", src)
spawn(-15) flick("release_[department]", src)
adjustsprite(null)
status = STATUS_INACTIVE
set_dir(SOUTH)
update_icon()
layer = LAYER_NORMAL
target.bracer = null
processing_objects.Remove(src)
target = null
if (target_node1)
target_node1.bracer = null
target_node1 = null
if (target_node2)
target_node2.bracer = null
target_node2 = null
anchored = 0
processing_objects.Remove(src)
last_process_time = 0
/obj/item/device/magnetic_lock/proc/attach(var/obj/machinery/door/airlock/newtarget as obj)
adjustsprite(newtarget)
layer = LAYER_ATTACHED
flick("deploy", src)
newtarget.bracer = src
target = newtarget
last_process_time = world.time
processing_objects.Add(src)
anchored = 1
/obj/item/device/magnetic_lock/proc/adjustsprite(var/obj/target as obj)
if (target)
switch (get_dir(src, target))
spawn(-15)
flick("deploy_[department]", src)
update_icon()
/obj/item/device/magnetic_lock/update_icon()
if (status == STATUS_ACTIVE && target)
icon_state = "active_[department]"
switch (dir)
if (NORTH)
pixel_x = 0
pixel_y = 32
if (NORTHEAST)
pixel_x = 32
pixel_y = 32
if (EAST)
pixel_x = 32
pixel_y = 0
if (SOUTHEAST)
pixel_x = 32
pixel_y = -32
if (EAST)
pixel_x = -32
pixel_y = 0
if (SOUTH)
pixel_x = 0
pixel_y = -32
if (SOUTHWEST)
pixel_x = -32
pixel_y = -32
if (WEST)
pixel_x = -32
pixel_y = 0
if (NORTHWEST)
pixel_x = -32
pixel_y = 32
else
if (WEST)
pixel_x = 32
pixel_y = 0
else if (status >= STATUS_INACTIVE)
icon_state = "inactive_[department]"
pixel_x = 0
pixel_y = 0
else
icon_state = "broken_[department]"
pixel_x = 0
pixel_y = 0
update_overlays()
/obj/item/device/magnetic_lock/proc/update_overlays()
overlays.Cut()
switch (status)
if (STATUS_BROKEN)
icon_state = "broken"
return
if (STATUS_INACTIVE to STATUS_ACTIVE)
if (hacked)
overlays += "overlay_hacked"
else if (locked)
overlays += "overlay_locked"
else
overlays += "overlay_unlocked"
switch (constructionstate)
if (0)
return
if (1 to 4)
overlays += "overlay_deconstruct_[constructionstate]"
/obj/item/device/magnetic_lock/proc/takedamage(var/damage)
health -= damage
@@ -303,7 +409,8 @@
if (health <= 0)
visible_message("<span class='danger'>[src] sparks[target ? " and falls off of \the [target]!" : "!"] It is now completely unusable!</span>")
setstatus(STATUS_BROKEN)
status = STATUS_BROKEN
update_icon()
return
if (prob(50))

View File

@@ -169,7 +169,7 @@
valve_open = 0
if(deleted(tank_one) || deleted(tank_two))
if(deleted(tank_one) || deleted(tank_two) || !tank_one.air_contents || !tank_two.air_contents)
return
var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume

View File

@@ -161,3 +161,19 @@
R.emagged = 1
return 1
/obj/item/borg/upgrade/combat
name = "combat cyborg module"
desc = "Unlocks the combat cyborg module"
construction_cost = list(DEFAULT_WALL_MATERIAL=10000,"glass"=15000,"gold"= 5000,"diamond" = 1000)
icon_state = "cyborg_upgrade3"
require_module = 0
/obj/item/borg/upgrade/combat/action(var/mob/living/silicon/robot/R)
if(..()) return 0
if(R.crisis_override == 1)
return 0
R.crisis_override = 1
return 1

View File

@@ -128,6 +128,7 @@
/obj/item/weapon/grenade/flashbang/clusterbang/prime()
var/numspawned = rand(4,8)
var/again = 0
var/atom/A = loc
for(var/more = numspawned,more > 0,more--)
if(prob(35))
again++
@@ -135,15 +136,15 @@
for(,numspawned > 0, numspawned--)
spawn(0)
new /obj/item/weapon/grenade/flashbang/cluster(src.loc)//Launches flashbangs
new /obj/item/weapon/grenade/flashbang/cluster(A)//Launches flashbangs
playsound(src.loc, 'sound/weapons/armbomb.ogg', 75, 1, -3)
for(,again > 0, again--)
spawn(0)
new /obj/item/weapon/grenade/flashbang/clusterbang/segment(src.loc)//Creates a 'segment' that launches a few more flashbangs
new /obj/item/weapon/grenade/flashbang/clusterbang/segment(A)//Creates a 'segment' that launches a few more flashbangs
playsound(src.loc, 'sound/weapons/armbomb.ogg', 75, 1, -3)
spawn(1)
qdel(src)
return
/obj/item/weapon/grenade/flashbang/clusterbang/segment
desc = "A smaller segment of a clusterbang. Better run."
@@ -152,6 +153,7 @@
icon_state = "clusterbang_segment"
/obj/item/weapon/grenade/flashbang/clusterbang/segment/New()//Segments should never exist except part of the clusterbang, since these immediately 'do their thing' and asplode
icon_state = "clusterbang_segment_active"
active = 1
banglet = 1
@@ -168,13 +170,14 @@
for(var/more = numspawned,more > 0,more--)
if(prob(35))
numspawned --
var/atom/A = src.loc
for(,numspawned > 0, numspawned--)
spawn(0)
new /obj/item/weapon/grenade/flashbang/cluster(src.loc)
new /obj/item/weapon/grenade/flashbang/cluster(A)
playsound(src.loc, 'sound/weapons/armbomb.ogg', 75, 1, -3)
spawn(1)
qdel(src)
return
/obj/item/weapon/grenade/flashbang/cluster/New()//Same concept as the segments, so that all of the parts don't become reliant on the clusterbang
spawn(0)

View File

@@ -31,8 +31,10 @@
/obj/item/weapon/material/sword/rapier
name = "rapier"
desc = "A slender, fancy and sharply pointed sword."
icon = 'icons/obj/sword.dmi'
icon_state = "rapier"
item_state = "claymore"
item_state = "rapier"
contained_sprite = 1
slot_flags = SLOT_BELT
attack_verb = list("attacked", "stabbed", "prodded", "poked", "lunged")
@@ -61,3 +63,15 @@
icon_state = "sabre"
item_state = "katana"
slot_flags = SLOT_BELT
/obj/item/weapon/material/sword/axe
name = "battle axe"
desc = "A one handed battle axe, still a deadly weapon."
icon = 'icons/obj/sword.dmi'
icon_state = "axe"
item_state = "axe"
contained_sprite = 1
slot_flags = SLOT_BACK
attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut")
applies_material_colour = 0

View File

@@ -223,10 +223,21 @@
var/image/IM = image(I.icon,I.icon_state)
IM.overlays = I.overlays.Copy()
HS.overlays += IM
HS.name = "[I.name] on a spear"
qdel(src)
return
return ..()
//predefined materials for spears
/obj/item/weapon/material/twohanded/spear/steel/New(var/newloc)
..(newloc,"steel")
/obj/item/weapon/material/twohanded/spear/plasteel/New(var/newloc)
..(newloc,"plasteel")
/obj/item/weapon/material/twohanded/spear/diamond/New(var/newloc)
..(newloc,"diamond")
/obj/structure/headspear
name = "head on a spear"
desc = "How barbaric."

View File

@@ -51,3 +51,24 @@
viewers(user) << "\red <b>[user] is slicing \himself apart with the [src.name]! It looks like \he's trying to commit suicide.</b>"
return (BRUTELOSS|OXYLOSS)
*/
//This is essentially a crowbar and a baseball bat in one.
/obj/item/weapon/melee/hammer
name = "kneebreaker hammer"
desc = "A heavy hammer made of plasteel, the other end could be used to pry open doors."
icon = 'icons/obj/kneehammer.dmi'
icon_state = "kneehammer"
item_state = "kneehammer"
contained_sprite = 1
slot_flags = SLOT_BELT
force = 22
throwforce = 70
//This should do around 15 brute when you throw it, there's probably a better way to do it.
throw_speed = 1
throw_range = 5
attack_verb = list("smashed", "beaten", "slammed", "smacked", "struck", "battered", "bonked")
w_class = 3
origin_tech = "materials=3;syndicate=2"
sharp = 0
edge = 0
hitsound = 'sound/weapons/genhit3.ogg'

View File

@@ -198,7 +198,7 @@
/obj/item/device/flashlight,
/obj/item/device/pda,
/obj/item/device/radio/headset,
/obj/item/weapon/melee/energy/sword,
/obj/item/weapon/melee,
/obj/item/weapon/shield/energy,
/obj/item/weapon/pinpointer,
/obj/item/weapon/plastique,

View File

@@ -15,7 +15,8 @@
* Handcuff, mousetrap, and pillbottle boxes,
* Snap-pops and matchboxes,
* Replacement light boxes.
*
* Kitchen utensil box
* Random preserved snack box
* For syndicate call-ins see uplink_kits.dm
*/
@@ -323,6 +324,7 @@
new /obj/item/weapon/grenade/flashbang(src)
new /obj/item/weapon/grenade/flashbang(src)
/obj/item/weapon/storage/box/teargas
name = "box of pepperspray grenades"
desc = "A box containing 7 tear gas grenades. A gas mask is printed on the label.<br> WARNING: Exposure carries risk of serious injury or death. Keep away from persons with lung conditions."
@@ -337,7 +339,20 @@
new /obj/item/weapon/grenade/chem_grenade/teargas(src)
new /obj/item/weapon/grenade/chem_grenade/teargas(src)
/obj/item/weapon/storage/box/smokebombs
name = "box of smoke grenades"
desc = "A box full of smoke grenades, used by special law enforcement teams and military organisations. Provides cover, confusion, and distraction."
icon_state = "flashbang"
New()
..()
new /obj/item/weapon/grenade/smokebomb(src)
new /obj/item/weapon/grenade/smokebomb(src)
new /obj/item/weapon/grenade/smokebomb(src)
new /obj/item/weapon/grenade/smokebomb(src)
new /obj/item/weapon/grenade/smokebomb(src)
new /obj/item/weapon/grenade/smokebomb(src)
new /obj/item/weapon/grenade/smokebomb(src)
/obj/item/weapon/storage/box/emps
name = "box of emp grenades"
@@ -730,3 +745,57 @@
can_hold = list(/obj/item/organ, /obj/item/weapon/reagent_containers/food, /obj/item/weapon/reagent_containers/glass)
max_storage_space = 21
use_to_pickup = 1 // for picking up broken bulbs, not that most people will try
/obj/item/weapon/storage/box/kitchen
name = "kitchen supplies"
desc = "Contains an assortment of utensils and containers useful in the preparation of food and drinks."
/obj/item/weapon/storage/box/kitchen/New()
new /obj/item/weapon/material/knife(src)//Should always have a knife
var/list/utensils = list(/obj/item/weapon/material/kitchen/rollingpin,
/obj/item/weapon/reagent_containers/glass/beaker,
/obj/item/weapon/material/kitchen/utensil/fork,
/obj/item/weapon/reagent_containers/food/condiment/enzyme,
/obj/item/weapon/material/kitchen/utensil/spoon,
/obj/item/weapon/material/kitchen/utensil/knife,
/obj/item/weapon/reagent_containers/food/drinks/shaker)
for (var/i = 0,i<6,i++)
var/type = pick(utensils)
new type(src)
..()
/obj/item/weapon/storage/box/snack
name = "rations box"
desc = "Contains a random assortment of preserved foods. Guaranteed to remain edible* in room-temperature longterm storage for centuries!"
/obj/item/weapon/storage/box/snack/New()
var/list/snacks = list(
/obj/item/weapon/reagent_containers/food/snacks/koisbar,
/obj/item/weapon/reagent_containers/food/snacks/candy,
/obj/item/weapon/reagent_containers/food/snacks/candy_corn,
/obj/item/weapon/reagent_containers/food/snacks/chips,
/obj/item/weapon/reagent_containers/food/snacks/chocolatebar,
/obj/item/weapon/reagent_containers/food/snacks/chocolateegg,
/obj/item/weapon/reagent_containers/food/snacks/popcorn,
/obj/item/weapon/reagent_containers/food/snacks/sosjerky,
/obj/item/weapon/reagent_containers/food/snacks/no_raisin,
/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie,
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers,
/obj/item/weapon/reagent_containers/food/snacks/syndicake,
/obj/item/weapon/reagent_containers/food/snacks/fortunecookie,
/obj/item/weapon/reagent_containers/food/snacks/poppypretzel,
/obj/item/weapon/reagent_containers/food/snacks/cracker,
/obj/item/weapon/reagent_containers/food/snacks/liquidfood,
/obj/item/weapon/reagent_containers/food/snacks/skrellsnacks,
/obj/item/weapon/reagent_containers/food/snacks/tastybread,
/obj/item/weapon/reagent_containers/food/snacks/meatsnack,
/obj/item/weapon/reagent_containers/food/snacks/maps,
/obj/item/weapon/reagent_containers/food/snacks/nathisnack,
)
for (var/i = 0,i<7,i++)
var/type = pick(snacks)
new type(src)
..()

View File

@@ -131,6 +131,8 @@
/obj/item/weapon/storage/firstaid/surgery
name = "surgery kit"
desc = "Contains tools for surgery. Has precise foam fitting for safe transport."
icon_state = "purplefirstaid"
item_state = "firstaid-advanced"
/obj/item/weapon/storage/firstaid/surgery/New()
..()

View File

@@ -579,12 +579,12 @@
max_storage_space += I.get_storage_cost()
//Useful for spilling the contents of containers all over the floor
/obj/item/weapon/storage/proc/spill()
if (istype(loc, /turf))//If its not on the floor this might cause issues
var/turf/T = get_turf(src)
/obj/item/weapon/storage/proc/spill(var/dist = 2, var/turf/T = null)
if (!T || !istype(T, /turf))//If its not on the floor this might cause issues
T = get_turf(src)
for (var/obj/O in contents)
contents.Remove(O)
O.forceMove(T)
remove_from_storage(O, T)
O.tumble(2)

View File

@@ -14,6 +14,11 @@
max_storage_space = 14 //enough to hold all starting contents
origin_tech = list(TECH_COMBAT = 1)
attack_verb = list("robusted")
var/stunhit = 0
/obj/item/weapon/storage/toolbox/initialize()
spawn(3)
update_force()
/obj/item/weapon/storage/toolbox/emergency
name = "emergency toolbox"
@@ -79,3 +84,24 @@
new /obj/item/weapon/crowbar(src)
new /obj/item/weapon/wirecutters(src)
new /obj/item/device/multitool(src)
/obj/item/weapon/storage/toolbox/proc/update_force()
force = initial(force)
for (var/obj/item/I in contents)
force += I.w_class*1.5
/obj/item/weapon/storage/toolbox/handle_item_insertion(obj/item/W as obj, prevent_warning = 0)
if (..(W, prevent_warning))
update_force()
/obj/item/weapon/storage/toolbox/attack(mob/living/M as mob, mob/user as mob)
update_force()
..(M, user)
if (contents.len)
spill(3, get_turf(M))
playsound(M, 'sound/items/trayhit2.ogg', 100, 1) //sound playin' again
update_force()
user.visible_message(span("danger", "[user] smashes the [src] into [M], causing it to break open and strew its contents across the area"))

View File

@@ -184,3 +184,32 @@
slot_flags = null
baton_color = "#FFDF00"
/obj/item/weapon/melee/baton/stunrod
name = "stunrod"
desc = "A more-than-lethal weapon used to deal with high threat situations."
icon = 'icons/obj/stunrod.dmi'
icon_state = "stunrod"
item_state = "stunrod"
force = 20
baton_color = "#75ACFF"
origin_tech = "combat=4,illegal=2"
contained_sprite = 1
/obj/item/weapon/melee/baton/stunrod/New()
..()
bcell = new/obj/item/weapon/cell/high(src)
update_icon()
return
/obj/item/weapon/melee/baton/stunrod/update_icon() //this is needed due to how contained sprites work
if(status)
icon_state = "[initial(name)]_active"
item_state = "[initial(name)]_active"
else if(!bcell)
icon_state = "[initial(name)]_nocell"
item_state = "[initial(name)]"
else
icon_state = "[initial(name)]"
item_state = "[initial(name)]"
..()

View File

@@ -79,14 +79,14 @@
add_fingerprint(user)
if(blood_overlay && blood_DNA && (blood_DNA.len >= 1)) //updates blood overlay, if any
overlays.Cut()//this might delete other item overlays as well but eeeeeeeh
overlays.Remove(blood_overlay)
var/icon/I = new /icon(src.icon, src.icon_state)
I.Blend(new /icon('icons/effects/blood.dmi', rgb(255,255,255)),ICON_ADD)
I.Blend(new /icon('icons/effects/blood.dmi', "itemblood"),ICON_MULTIPLY)
blood_overlay = I
blood_overlay = image(I)
blood_overlay.color = blood_color
overlays += blood_overlay
update_icon()
return
@@ -101,8 +101,10 @@
else
user.take_organ_damage(2*force)
return
if(..())
//playsound(src.loc, "swing_hit", 50, 1, -1)
if(..() == 1)
playsound(src.loc, "swing_hit", 50, 1, -1)
if(user.zone_sel.selecting == "r_leg" || user.zone_sel.selecting == "l_leg")
target.Weaken(5) //nerfed, because yes.
return
else
return ..()

View File

@@ -303,15 +303,24 @@
var/mob/living/carbon/human/H = M
if(H.species.flags & IS_SYNTHETIC)
if(M == user)
user << "\red You can't repair damage to your own body - it's against OH&S."
user << "<span class='warning'>You can't repair damage to your own body - it's against OH&S.</span>"
return
if(S.brute_dam)
if(S.brute_dam == 0)
// Organ undamaged
user << "Nothing to fix here!"
return
if (!src.welding)
// Welder is switched off!
user << "<span class='warning'>You need to light the welding tool, first!</span>"
return
if (src.remove_fuel(0))
// Use a bit of fuel and repair
S.heal_damage(15,0,0,1)
user.visible_message("\red \The [user] patches some dents on \the [M]'s [S.name] with \the [src].")
return
user.visible_message("<span class='warning'>\The [user] patches some dents on \the [M]'s [S.name] with \the [src].</span>")
else
user << "Nothing to fix!"
// Welding tool is out of fuel
user << "Need more welding fuel!"
return
else
return ..()

View File

@@ -214,3 +214,18 @@
health -= W.force
healthcheck()
..()
/obj/item/weapon/canesword
name = "thin sword"
desc = "A thin, sharp blade with an elegant handle."
icon = 'icons/obj/sword.dmi'
icon_state = "canesword"
item_state = "canesword"
force = 20
throwforce = 5
w_class = 4
sharp = 1
edge = 1
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
contained_sprite = 1

View File

@@ -23,6 +23,7 @@
var/list/icon_supported_species_tags //Used with icon_auto_adapt, a list of species which have differing appearances for this item
var/icon_species_in_hand = 0//If 1, we will use the species tag even for rendering this item in the left/right hand.
var/equip_slot = 0
/obj/Destroy()
processing_objects -= src
return ..()

View File

@@ -102,7 +102,7 @@
desc = "This is a random piece of technology supplies."
icon = 'icons/obj/power.dmi'
icon_state = "cell"
spawn_nothing_percentage = 50
// spawn_nothing_percentage = 50
item_to_spawn()
return pick(prob(3);/obj/random/powercell,\
prob(2);/obj/random/technology_scanner,\
@@ -157,7 +157,7 @@
desc = "Hot Stuff."
icon = 'icons/obj/items.dmi'
icon_state = "purplecomb"
spawn_nothing_percentage = 50
// spawn_nothing_percentage = 50
item_to_spawn()
return pick(prob(3);/obj/item/weapon/storage/pill_bottle/tramadol,\
prob(4);/obj/item/weapon/haircomb,\
@@ -280,3 +280,414 @@
/obj/item/toy/plushie/kitten,\
/obj/item/toy/plushie/lizard)
/obj/random/smalltank/item_to_spawn()
if (prob(40))
return /obj/item/weapon/tank/emergency_oxygen
else if (prob(60))
return /obj/item/weapon/tank/emergency_oxygen/engi
else
return /obj/item/weapon/tank/emergency_oxygen/double
/obj/random/belt/item_to_spawn()
var/list/belts = list("/obj/item/weapon/storage/belt/utility" = 1,
"/obj/item/weapon/storage/belt/medical" = 0.4,
"/obj/item/weapon/storage/belt/medical/emt" = 0.4,
"/obj/item/weapon/storage/belt/security/tactical" = 0.1,
"/obj/item/weapon/storage/belt/military" = 0.1,
"/obj/item/weapon/storage/belt/janitor" = 0.4
)
return pickweight(belts)
//Spawns a random backpack
//Novelty and rare backpacks have lower weights
/obj/random/backpack/item_to_spawn()
var/list/packs = list(
"/obj/item/weapon/storage/backpack" = 3,
"/obj/item/weapon/storage/backpack/holding" = 0.5,
"/obj/item/weapon/storage/backpack/santabag" = 2,
"/obj/item/weapon/storage/backpack/cultpack" = 2,
"/obj/item/weapon/storage/backpack/clown" = 2,
"/obj/item/weapon/storage/backpack/medic" = 3,
"/obj/item/weapon/storage/backpack/security" = 3,
"/obj/item/weapon/storage/backpack/captain" = 2,
"/obj/item/weapon/storage/backpack/industrial" = 3,
"/obj/item/weapon/storage/backpack/toxins" = 3,
"/obj/item/weapon/storage/backpack/hydroponics" = 3,
"/obj/item/weapon/storage/backpack/genetics" = 3,
"/obj/item/weapon/storage/backpack/virology" = 3,
"/obj/item/weapon/storage/backpack/chemistry" = 3,
"/obj/item/weapon/storage/backpack/cloak" = 2,
"/obj/item/weapon/storage/backpack/syndie" = 2,
"/obj/item/weapon/storage/backpack/wizard" = 2,
"/obj/item/weapon/storage/backpack/satchel" = 3,
"/obj/item/weapon/storage/backpack/satchel_norm" = 3,
"/obj/item/weapon/storage/backpack/satchel_eng" = 3,
"/obj/item/weapon/storage/backpack/satchel_med" = 3,
"/obj/item/weapon/storage/backpack/satchel_vir" = 3,
"/obj/item/weapon/storage/backpack/satchel_chem" = 3,
"/obj/item/weapon/storage/backpack/satchel_gen" = 3,
"/obj/item/weapon/storage/backpack/satchel_tox" = 3,
"/obj/item/weapon/storage/backpack/satchel_sec" = 3,
"/obj/item/weapon/storage/backpack/satchel_hyd" = 3,
"/obj/item/weapon/storage/backpack/satchel_cap" = 2,
"/obj/item/weapon/storage/backpack/satchel_syndie" = 2,
"/obj/item/weapon/storage/backpack/satchel_wizard" = 2,
"/obj/item/weapon/storage/backpack/ert" = 2,
"/obj/item/weapon/storage/backpack/ert/security" = 2,
"/obj/item/weapon/storage/backpack/ert/engineer" = 2,
"/obj/item/weapon/storage/backpack/ert/medical" = 2,
"/obj/item/weapon/storage/backpack/duffel" = 3,
"/obj/item/weapon/storage/backpack/duffel/cap" = 2,
"/obj/item/weapon/storage/backpack/duffel/hyd" = 3,
"/obj/item/weapon/storage/backpack/duffel/vir" = 3,
"/obj/item/weapon/storage/backpack/duffel/med" = 3,
"/obj/item/weapon/storage/backpack/duffel/eng" = 3,
"/obj/item/weapon/storage/backpack/duffel/tox" = 3,
"/obj/item/weapon/storage/backpack/duffel/sec" = 3,
"/obj/item/weapon/storage/backpack/duffel/gen" = 3,
"/obj/item/weapon/storage/backpack/duffel/chem" = 3,
"/obj/item/weapon/storage/backpack/duffel/syndie" = 2,
"/obj/item/weapon/storage/backpack/duffel/wizard" = 2
)
return pickweight(packs)
/obj/random/voidsuit
var/damaged = 0
/obj/random/voidsuit/New(var/_damaged = 0)
damaged = _damaged
..()
/obj/random/voidsuit/spawn_item()
var/list/suit_types = list(
"/space/void" = 2,
"/space/void/engineering" = 2,
"/space/void/mining" = 2,
"/space/void/medical" = 2.3,
"/space/void/security" = 1,
"/space/void/atmos" = 1.5,
"/space/void/merc" = 0.5,
"/space/void/captain" = 0.3
)
var/atom/L = src.loc
var/suffix = pickweight(suit_types)
var/stype = "/obj/item/clothing/suit[suffix]"
var/htype = "/obj/item/clothing/head/helmet[suffix]"
var/obj/item/clothing/suit/space/newsuit = new stype(L)
new htype(L)
new /obj/item/clothing/shoes/magboots(L)
if (damaged && prob(60))//put some damage on it
var/damtype = pick(BRUTE,BURN)
var/amount = rand(1,5)
newsuit.create_breaches(damtype, amount)
/obj/random/vendor
var/depleted = 0
/obj/random/vendor/New(var/_depleted = 0)
depleted = _depleted
..()
/obj/random/vendor/spawn_item()
var/list/options = list(
"/obj/machinery/vending/boozeomat" = 1,
"/obj/machinery/vending/coffee" = 1,
"/obj/machinery/vending/snack" = 1,
"/obj/machinery/vending/cola" = 1,
"/obj/machinery/vending/cart" = 1.5,
"/obj/machinery/vending/cigarette" = 1,
"/obj/machinery/vending/medical" = 1.2,
"/obj/machinery/vending/phoronresearch" = 0.7,
"/obj/machinery/vending/security" = 0.3,
"/obj/machinery/vending/hydronutrients" = 1,
"/obj/machinery/vending/hydroseeds" = 1,
"/obj/machinery/vending/magivend" = 0.5,//The things it dispenses are just costumes to non-wizards
"/obj/machinery/vending/dinnerware" = 1,
"/obj/machinery/vending/sovietsoda" = 2,
"/obj/machinery/vending/tool" = 1,
"/obj/machinery/vending/engivend" = 0.6,
"/obj/machinery/vending/engineering" = 1,
"/obj/machinery/vending/robotics" = 1
)
var/turf/L = get_turf(src)
var/type = pickweight(options)
var/obj/machinery/vending/V = new type(L)
if (!depleted)
return
//Greatly reduce the contents. it will have 0-20% of what it usually has
for (var/content in V.products)
if (prob(40))
V.products[content] = 0//40% chance to completely lose an item
else
var/multiplier = rand(0,20)//Else, we reduce it to a very low percentage
if (multiplier)
multiplier /= 100
V.products[content] *= multiplier
if (V.products[content] < 1 && V.products[content] > 0)//But we'll usually have at least 1 left
V.products[content] = 0
/obj/random/pda_cart/item_to_spawn()
var/list/options = typesof(/obj/item/weapon/cartridge)
var/type = pick(options)
//reroll syndicate cartridge once to make it less common
if (type == /obj/item/weapon/cartridge/syndicate)
type = pick(options)
return type
/obj/random/glowstick
name = "random glowstick"
desc = "This is a random glowstick."
icon = 'icons/obj/glowsticks.dmi'
icon_state = "glowstick"
/obj/random/glowstick/item_to_spawn()
return pick(/obj/item/device/flashlight/glowstick,\
/obj/item/device/flashlight/glowstick/red,\
/obj/item/device/flashlight/glowstick/blue,\
/obj/item/device/flashlight/glowstick/orange,\
/obj/item/device/flashlight/glowstick/yellow)
/obj/random/booze
name = "random alcoholic drink"
desc = "This is a random alcoholic drink."
icon = 'icons/obj/drinks.dmi'
icon_state = "broken_bottle"
/obj/random/booze/item_to_spawn()
return pick(/obj/item/weapon/reagent_containers/food/drinks/bottle/gin,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/vodka,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/tequilla,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/rum,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/vermouth,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/kahlua,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/cognac,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/wine,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/melonliquor,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/pwine,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/brandy,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/guinnes,\
/obj/item/weapon/reagent_containers/food/drinks/bottle/drambuie,\
/obj/item/weapon/reagent_containers/food/drinks/cans/beer,\
/obj/item/weapon/reagent_containers/food/drinks/cans/ale)
/obj/random/melee
name = "random melee weapon"
desc = "This is a random melee weapon."
icon = 'icons/obj/weapons.dmi'
icon_state = "baton"
/obj/random/melee/item_to_spawn()
return pick(/obj/item/weapon/melee/telebaton,\
/obj/item/weapon/melee/energy/sword,\
/obj/item/weapon/melee/energy/sword/pirate,\
/obj/item/weapon/melee/energy/glaive,\
/obj/item/weapon/melee/chainsword,\
/obj/item/weapon/melee/baton/stunrod,\
/obj/item/weapon/material/harpoon,\
/obj/item/weapon/material/scythe,\
/obj/item/weapon/material/twohanded/spear/plasteel,\
/obj/item/weapon/material/sword/trench,\
/obj/item/weapon/material/sword/rapier)
/obj/random/coin
name = "random coin"
desc = "This is a random coin."
icon = 'icons/obj/items.dmi'
icon_state = "coin"
/obj/random/coin/item_to_spawn()
var/list/coin = list("/obj/item/weapon/coin/iron" = 5,
"/obj/item/weapon/coin/silver" = 3,
"/obj/item/weapon/coin/gold" = 1,
"/obj/item/weapon/coin/silver" = 0.7,
"/obj/item/weapon/coin/phoron" = 0.5,
"obj/item/weapon/coin/uranium" = 0.5,
"/obj/item/weapon/coin/platinum" = 0.2,
"/obj/item/weapon/coin/diamond" = 0.1,
)
return pickweight(coin)
/obj/random/energy_antag
name = "random energy weapon"
desc = "This is a random energy weapon."
icon = 'icons/obj/gun.dmi'
icon_state = "retro100"
/obj/random/energy_antag/item_to_spawn()
return pick(/obj/item/weapon/gun/energy/retro,\
/obj/item/weapon/gun/energy/xray,\
/obj/item/weapon/gun/energy/gun,\
/obj/item/weapon/gun/energy/pistol,\
/obj/item/weapon/gun/energy/rifle,\
/obj/item/weapon/gun/energy/mindflayer,\
/obj/item/weapon/gun/energy/toxgun,\
/obj/item/weapon/gun/energy/vaurca/gatlinglaser,\
/obj/item/weapon/gun/energy/vaurca/blaster,\
/obj/item/weapon/gun/energy/crossbow/largecrossbow)
/obj/random/colored_jumpsuit
name = "random colored jumpsuit"
desc = "This is a random colowerd jumpsuit."
icon = 'icons/obj/clothing/uniforms.dmi'
icon_state = "black"
/obj/random/colored_jumpsuit/item_to_spawn()
return pick(/obj/item/clothing/under/color/black,\
/obj/item/clothing/under/color/blackf,\
/obj/item/clothing/under/color/blue,\
/obj/item/clothing/under/color/green,\
/obj/item/clothing/under/color/grey,\
/obj/item/clothing/under/color/orange,\
/obj/item/clothing/under/color/pink,\
/obj/item/clothing/under/color/red,\
/obj/item/clothing/under/color/white,\
/obj/item/clothing/under/color/yellow,\
/obj/item/clothing/under/lightblue,\
/obj/item/clothing/under/aqua,\
/obj/item/clothing/under/purple,\
/obj/item/clothing/under/lightpurple,\
/obj/item/clothing/under/lightgreen,\
/obj/item/clothing/under/lightbrown,\
/obj/item/clothing/under/brown,\
/obj/item/clothing/under/yellowgreen,\
/obj/item/clothing/under/darkblue,\
/obj/item/clothing/under/lightred,\
/obj/item/clothing/under/darkred)
/obj/random/loot
name = "random maintenance loot items"
desc = "Stuff for the maint-dwellers."
icon = 'icons/obj/items.dmi'
icon_state = "gift3"
/obj/random/loot/item_to_spawn()
var/list/maint = list("/obj/item/clothing/glasses/meson" = 1,
"/obj/item/clothing/glasses/meson/prescription" = 0.7,
"/obj/item/clothing/glasses/material" = 0.8,
"/obj/item/clothing/glasses/sunglasses" = 1.5,
"/obj/item/clothing/glasses/welding" = 1.2,
"/obj/item/clothing/under/captain_fly" = 0.7,
"/obj/item/clothing/under/rank/mailman" = 0.6,
"/obj/item/clothing/under/rank/vice" = 0.8,
"/obj/item/clothing/under/assistantformal" = 1,
"/obj/item/clothing/under/rainbow" = 0.9,
"/obj/item/clothing/under/overalls" = 1,
"/obj/item/clothing/under/redcoat" = 0.5,
"/obj/item/clothing/under/serviceoveralls" = 1,
"/obj/item/clothing/under/psyche" = 0.5,
"/obj/item/clothing/under/track" = 0.9,
"/obj/item/clothing/under/rank/dispatch" = 1,
"/obj/item/clothing/under/syndicate/tacticool" = 1,
"/obj/item/clothing/under/syndicate/tracksuit" = 0.2,
"/obj/item/clothing/accessory/badge" = 0.2,
"/obj/item/clothing/accessory/badge/old" = 0.2,
"/obj/item/clothing/accessory/storage/webbing" = 0.6,
"/obj/item/clothing/accessory/storage/knifeharness" = 0.3,
"/obj/item/clothing/head/collectable/petehat" = 0.3,
"/obj/item/clothing/head/hardhat" = 1.2,
"/obj/item/clothing/head/redcoat" = 0.4,
"/obj/item/clothing/head/syndicatefake" = 0.5,
"/obj/item/clothing/head/richard" = 0.3,
"/obj/item/clothing/head/soft/rainbow" = 0.7,
"/obj/item/clothing/head/plaguedoctorhat" = 0.5,
"/obj/item/clothing/head/cueball" = 0.5,
"/obj/item/clothing/head/pirate" = 0.4,
"/obj/item/clothing/head/bearpelt" = 0.4,
"/obj/item/clothing/head/witchwig" = 0.5,
"/obj/item/clothing/head/pumpkinhead" = 0.6,
"/obj/item/clothing/head/kitty" = 0.2,
"/obj/item/clothing/head/ushanka" = 0.6,
"/obj/item/clothing/head/helmet/augment" = 0.1,
"/obj/item/clothing/mask/balaclava" = 1,
"/obj/item/clothing/mask/gas" = 1.5,
"/obj/item/clothing/mask/gas/cyborg" = 0.7,
"/obj/item/clothing/mask/gas/owl_mask" = 0.8,
"/obj/item/clothing/mask/gas/syndicate" = 0.4,
"/obj/item/clothing/mask/fakemoustache" = 0.4,
"/obj/item/clothing/mask/horsehead" = 0.9,
"/obj/item/clothing/shoes/rainbow" = 1,
"/obj/item/clothing/shoes/jackboots" = 1,
"/obj/item/clothing/shoes/workboots" = 1,
"/obj/item/clothing/shoes/cyborg" = 0.4,
"/obj/item/clothing/shoes/galoshes" = 0.6,
"/obj/item/clothing/shoes/slippers_worn" = 0.5,
"/obj/item/clothing/shoes/combat" = 0.2,
"/obj/item/clothing/shoes/clown_shoes" = 0.1,
"/obj/item/clothing/suit/storage/hazardvest" = 1,
"/obj/item/clothing/suit/storage/leather_jacket/nanotrasen" = 0.7,
"/obj/item/clothing/suit/storage/toggle/tracksuit" = 0.7,
"/obj/item/clothing/suit/ianshirt" = 0.5,
"/obj/item/clothing/suit/syndicatefake" = 0.6,
"/obj/item/clothing/suit/imperium_monk" = 0.4,
"/obj/item/clothing/suit/storage/vest" = 0.2,
"/obj/item/clothing/gloves/black" = 1,
"/obj/item/clothing/gloves/fyellow" = 1.2,
"/obj/item/clothing/gloves/yellow" = 0.9,
"/obj/item/clothing/gloves/watch" = 0.3,
"/obj/item/clothing/gloves/boxing" = 0.3,
"/obj/item/clothing/gloves/boxing/green" = 0.8,
"/obj/item/clothing/gloves/botanic_leather" = 0.7,
"/obj/item/clothing/gloves/combat" = 0.2,
"/obj/item/toy/bosunwhistle" = 0.5,
"/obj/item/toy/balloon" = 0.4,
"/obj/item/weapon/haircomb" = 0.5,
"/obj/item/weapon/lipstick" = 0.6,
"/obj/item/weapon/material/knife/hook" = 0.3,
"/obj/item/weapon/material/hatchet/tacknife" = 0.4,
"/obj/item/weapon/storage/fancy/cigarettes/dromedaryco" = 1.2,
"/obj/item/weapon/storage/bag/plasticbag" = 1,
"/obj/item/weapon/extinguisher" = 1.3,
"/obj/item/weapon/extinguisher/mini" = 0.9,
"/obj/item/device/flashlight" = 1,
"/obj/item/device/flashlight/heavy" = 0.5,
"/obj/item/device/flashlight/maglight" = 0.4,
"/obj/item/device/flashlight/flare" = 0.5,
"/obj/item/device/flashlight/lantern" = 0.4,
"/obj/item/weapon/reagent_containers/food/drinks/teapot" = 0.4,
"/obj/item/weapon/reagent_containers/food/drinks/flask/shiny" = 0.3,
"/obj/item/weapon/reagent_containers/food/drinks/flask/lithium" = 0.3,
"/obj/item/bodybag" = 0.7,
"/obj/item/weapon/reagent_containers/spray/cleaner" = 0.6,
"/obj/item/weapon/tank/emergency_oxygen" = 0.7,
"/obj/item/weapon/tank/emergency_oxygen/double" = 0.4,
"/obj/item/clothing/mask/smokable/pipe/cobpipe" = 0.5,
"/obj/item/clothing/mask/smokable/cigarette/cigar/cohiba" = 0.7,
"/obj/item/weapon/flame/lighter" = 0.9,
"/obj/item/weapon/flame/lighter/zippo" = 0.7,
"/obj/item/device/gps/engineering" = 0.6,
"/obj/item/device/megaphone" = 0.5,
"/obj/item/device/floor_painter" = 0.6,
"/obj/random/toolbox" = 1,
"/obj/random/coin" = 1.2,
"/obj/random/tech_supply" = 1.2,
"/obj/random/powercell" = 0.8,
"/obj/random/colored_jumpsuit" = 0.7,
"/obj/random/booze" = 1.1,
"/obj/random/belt" = 0.9,
"/obj/random/contraband" = 0.9,
"/obj/random/glowstick" = 0.7,
"/obj/item/weapon/caution/cone" = 0.7,
"/obj/item/weapon/staff/broom" = 0.5,
"/obj/item/weapon/soap" = 0.4,
"/obj/item/weapon/material/wirerod" = 0.4,
"/obj/item/weapon/storage/box/donkpockets" = 0.6,
"/obj/item/weapon/contraband/poster" = 1.3,
"/obj/item/device/magnetic_lock/security" = 0.3,
"/obj/item/device/magnetic_lock/engineering" = 0.3
)
return pickweight(maint)

View File

@@ -46,6 +46,7 @@
/obj/structure/New()
..()
updateVisibility(src)
if(climbable)
verbs += /obj/structure/proc/climb_on

View File

@@ -55,7 +55,12 @@
else
user << "It is full."
/obj/structure/closet/proc/stored_weight()
var/content_size = 0
for(var/obj/item/I in src.contents)
if(!I.anchored)
content_size += Ceiling(I.w_class/2)
return content_size
/obj/structure/closet/alter_health()
return get_turf(src)

View File

@@ -4,6 +4,7 @@
icon_state = "cabinet_closed"
icon_closed = "cabinet_closed"
icon_opened = "cabinet_open"
storage_capacity = 45 //such a big closet deserves a little more capacity
/obj/structure/closet/cabinet/update_icon()
if(!opened)

View File

@@ -7,6 +7,7 @@
icon_opened = "cabinetdetective_open"
icon_broken = "cabinetdetective_broken"
icon_off = "cabinetdetective_broken"
storage_capacity = 45 //such a big closet deserves a little more capacity
New()

View File

@@ -249,20 +249,22 @@
icon_opened = "cabinetdetective_open"
icon_broken = "cabinetdetective_broken"
icon_off = "cabinetdetective_broken"
storage_capacity = 45 //such a big closet deserves a little more capacity
New()
..()
new /obj/item/clothing/under/det(src)
new /obj/item/clothing/under/det/grey(src)
new /obj/item/clothing/under/det/black(src)
new /obj/item/clothing/suit/storage/det_trench(src)
new /obj/item/clothing/suit/storage/det_trench/grey(src)
new /obj/item/clothing/under/det/slob(src)
new /obj/item/clothing/suit/storage/det_suit(src)
new /obj/item/clothing/suit/storage/det_suit/technicolor(src)
new /obj/item/clothing/suit/storage/forensics/blue(src)
new /obj/item/clothing/suit/storage/forensics/red(src)
new /obj/item/clothing/gloves/black(src)
new /obj/item/clothing/head/det(src)
new /obj/item/clothing/head/det/grey(src)
new /obj/item/clothing/shoes/laceup(src)
new /obj/item/clothing/head/det_hat(src)
new /obj/item/clothing/head/det_hat/technicolor(src)
new /obj/item/clothing/shoes/brown(src)
new /obj/item/weapon/storage/box/evidence(src)
new /obj/item/device/radio/headset/headset_sec(src)
new /obj/item/clothing/suit/storage/vest/detective(src)

View File

@@ -36,11 +36,20 @@
playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3)
for(var/obj/O in src)
O.forceMove(get_turf(src))
icon_state = icon_opened
src.opened = 1
if(climbable)
structure_shaken()
for (var/mob/M in src)
M.forceMove(get_turf(src))
if (M.stat == CONSCIOUS)
M.visible_message(span("danger","\The [M.name] bursts out of the [src]!"), span("danger","You burst out of the [src]!"))
else
M.visible_message(span("danger","\The [M.name] tumbles out of the [src]!"))
icon_state = icon_opened
src.opened = 1
return 1
/obj/structure/closet/crate/close()
@@ -67,6 +76,14 @@
src.opened = 0
return 1
/obj/structure/closet/crate/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(istype(mover,/obj/item/projectile) && prob(50))
return 1
if(istype(mover) && mover.checkpass(PASSTABLE))
return 1
return 0
/obj/structure/closet/crate/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(opened)
return ..()
@@ -496,3 +513,60 @@
// new /obj/item/weapon/pestspray(src)
// new /obj/item/weapon/pestspray(src)
// new /obj/item/weapon/pestspray(src)
//A crate that populates itself with randomly selected loot from randomstock.dm
//Can be passed in a rarity value, which is used as a multiplier on the rare/uncommon chance
//Quantity of spawns is number of discrete selections from the loot lists, default 10
/obj/structure/closet/crate/loot
name = "unusual container"
desc = "A mysterious container of unknown origins. What mysteries lie within?"
var/rarity = 1
var/quantity = 10
var/list/spawntypes
//The crate chooses its icon randomly from a number of noticeable options.
//None of these are the standard grey crate sprite, and a few are currently unused ingame
//This ensures that people stumbling across a lootbox will notice it's different and investigate
var/list/iconchoices = list(
"radiation" = "radiationopen",
"o2crate" = "o2crateopen",
"freezer" = "freezeropen",
"weaponcrate" = "weaponcrateopen",
"largebins" = "largebinsopen",
"phoroncrate" = "phoroncrateopen",
"trashcart" = "trashcartopen",
"critter" = "critteropen",
"largemetal" = "largemetalopen",
"medicalcrate" = "medicalcrateopen")
/obj/structure/closet/crate/loot/New(var/location, var/_rarity = 1, var/_quantity = 10)
rarity = _rarity
quantity = _quantity
..(location)
/obj/structure/closet/crate/loot/initialize()
spawntypes = list("1" = STOCK_RARE_PROB*rarity, "2" = STOCK_UNCOMMON_PROB*rarity, "3" = (100 - ((STOCK_RARE_PROB*rarity) + (STOCK_UNCOMMON_PROB*rarity))))
icon_closed = pick(iconchoices)
icon_opened = iconchoices[icon_closed]
update_icon()
while (quantity > 0)
quantity --
var/newtype = get_spawntype()
spawn_stock(newtype,src)
/obj/structure/closet/crate/loot/proc/get_spawntype()
var/stocktype = pickweight(spawntypes)
switch (stocktype)
if ("1")
return pickweight(random_stock_rare)
if ("2")
return pickweight(random_stock_uncommon)
if ("3")
return pickweight(random_stock_common)

View File

@@ -78,6 +78,15 @@
icon = 'icons/obj/plants.dmi'
icon_state = "plant-26"
//Added random icon selection for potted plants.
//It was silly they always used the same sprite when we have 26 sprites of them in the icon file
/obj/structure/flora/pottedplant/random/New()
..()
var/number = rand(1,26)
if (number < 10)
number = "0[number]"
icon_state = "plant-[number]"
//newbushes
/obj/structure/flora/ausbushes

View File

@@ -23,6 +23,10 @@
/obj/structure/sign/attackby(obj/item/tool as obj, mob/user as mob) //deconstruction
if(istype(tool, /obj/item/weapon/screwdriver) && !istype(src, /obj/structure/sign/double))
user << "You unfasten the sign with your [tool]."
unfasten()
else ..()
/obj/structure/sign/proc/unfasten()
var/obj/item/sign/S = new(src.loc)
S.name = name
S.desc = desc
@@ -31,13 +35,12 @@
//S.icon = I.Scale(24, 24)
S.sign_state = icon_state
qdel(src)
else ..()
/obj/item/sign
name = "sign"
desc = ""
icon = 'icons/obj/decals.dmi'
w_class = 3 //big
w_class = 5 //big
var/sign_state = ""
/obj/item/sign/attackby(obj/item/tool as obj, mob/user as mob) //construction

View File

@@ -168,7 +168,7 @@
/obj/structure/window/attack_tk(mob/user as mob)
user.visible_message("<span class='notice'>Something knocks on [src].</span>")
playsound(loc, 'sound/effects/Glasshit.ogg', 50, 1)
playsound(loc, 'sound/effects/Glasshit.ogg', 60, 1)
/obj/structure/window/attack_hand(mob/user as mob)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
@@ -186,13 +186,13 @@
attack_generic(H,25)
return
playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1)
playsound(src.loc, 'sound/effects/glassknock.ogg', 90, 1)
user.do_attack_animation(src)
usr.visible_message("<span class='danger'>\The [usr] bangs against \the [src]!</span>",
"<span class='danger'>You bang against \the [src]!</span>",
"You hear a banging sound.")
else
playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1)
playsound(src.loc, 'sound/effects/glassknock.ogg', 60, 1)
usr.visible_message("[usr.name] knocks on the [src.name].",
"You knock on the [src.name].",
"You hear a knocking sound.")
@@ -207,6 +207,7 @@
take_damage(damage)
else
visible_message("<span class='notice'>\The [user] bonks \the [src] harmlessly.</span>")
playsound(src.loc, 'sound/effects/Glasshit.ogg', 7, 1, -1)
user.do_attack_animation(src)
return 1

View File

@@ -86,11 +86,11 @@ var/list/footstepfx = list("defaultstep","concretestep","grassstep","dirtstep","
var/const/FALLOFF_SOUNDS = 0.5
/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global, var/usepressure = 1, var/environment = -1)
if(!src.client || ear_deaf > 0) return
if(!src.client || ear_deaf > 0) return 0
if(soundin in footstepfx)
if(!(src.client.prefs.asfx_togs & ASFX_FOOTSTEPS))
return
return 0
soundin = get_sfx(soundin)
@@ -120,7 +120,6 @@ var/const/FALLOFF_SOUNDS = 0.5
//This extra falloff should probably be rewritten or removed, but for now ive implemented a quick fix by only setting S.volume to vol after calculations are done
//This fix allows feeding in high volume values (>100) to make longrange sounds audible
// -Nanako
if (usepressure)
//sound volume falloff with pressure. Pass usepressure = 0 to disable these calculations
@@ -141,7 +140,7 @@ var/const/FALLOFF_SOUNDS = 0.5
vol *= pressure_factor
if (vol <= 0)
return //no volume means no sound
return 0//no volume means no sound
S.volume = vol
var/dx = turf_source.x - T.x // Hearing from the right/left
@@ -179,6 +178,7 @@ var/const/FALLOFF_SOUNDS = 0.5
S.environment = A.sound_env
src << S
return S.volume

View File

@@ -137,20 +137,22 @@ var/const/enterloopsanity = 100
if(M.lastarea.has_gravity == 0)
inertial_drift(M)
if (!M.buckled)
var/mob/living/carbon/human/MOB = M
if(istype(MOB) && !MOB.lying && footstep_sound)
if(istype(MOB.shoes, /obj/item/clothing/shoes) && !MOB.shoes:silent)
if(MOB.m_intent == "run")
playsound(MOB, footstep_sound, 70, 1)
else //Run and walk footsteps switched, because walk is the normal movement mode now
if(MOB.footstep >= 2)
MOB.footstep = 0
else
MOB.footstep++
if(MOB.footstep == 0)
playsound(MOB, footstep_sound, 50, 1) // this will get annoying very fast. - Tell them to mute it then -_-
else
playsound(MOB, footstep_sound, 40, 1)
else if(!istype(src, /turf/space))
M.inertia_dir = 0
M.make_floating(0)
@@ -247,7 +249,10 @@ var/const/enterloopsanity = 100
if(istype(O,/obj/effect/decal/cleanable) || istype(O,/obj/effect/overlay))
qdel(O)
if(istype(O,/obj/effect/rune))
user << "<span class='warning'>\red No matter how well you wash, the bloody symbols remain!</span>"
var/obj/effect/rune/R = O
// Only show message for visible runes
if (R.visibility)
user << "<span class='warning'>No matter how well you wash, the bloody symbols remain!</span>"
else
user << "<span class='warning'>\The [source] is too dry to wash that.</span>"
source.reagents.trans_to_turf(src, 1, 10) //10 is the multiplier for the reaction effect. probably needed to wet the floor properly.

View File

@@ -9,6 +9,7 @@ var/global/datum/datacore/data_core = null
var/global/list/all_areas = list()
var/global/list/machines = list()
var/global/list/processing_objects = list()
var/global/list/processing_modifiers = list()
var/global/list/processing_power_items = list()
var/global/list/active_diseases = list()
var/global/list/med_hud_users = list() // List of all entities using a medical HUD.

View File

@@ -29,7 +29,7 @@
//log_admin("HELP: [key_name(src)]: [msg]")
/proc/Centcomm_announce(var/msg, var/mob/Sender, var/iamessage)
discord_bot.send_to_cciaa("@here - Emergency message from the station: `[msg]`, sent by [Sender]!")
discord_bot.send_to_cciaa("Emergency message from the station: `[msg]`, sent by [Sender]!")
var/msg_cciaa = "\blue <b><font color=orange>[uppertext(boss_short)][iamessage ? " IA" : ""]:</font>[key_name(Sender, 1)] (<A HREF='?_src_=holder;CentcommReply=\ref[Sender]'>RPLY</A>):</b> [msg]"

File diff suppressed because it is too large Load Diff

View File

@@ -55,8 +55,6 @@
cmd_admin_discord_pm(href_list["discord_msg"])
return
//Logs all hrefs
if(config && config.log_hrefs && href_logfile)
href_logfile << "<small>[time2text(world.timeofday,"hh:mm")] [src] (usr:[usr])</small> || [hsrc ? "[hsrc] " : ""][href]<br>"
@@ -178,6 +176,10 @@
var/DBQuery/query = dbcon.NewQuery("INSERT INTO ss13_stats_ie (ckey, IsIE, IsEdge, EdgeHtmlVersion, TrueVersion, ActingVersion, CompatibilityMode, DateUpdated) VALUES (_ckey, _IsIE, _IsEdge, _EdgeHtmlVersion, _TrueVersion, _ActingVersion, _CompatibilityMode, NOW()) ON DUPLICATE KEY UPDATE IsIE = VALUES(IsIe), IsEdge = VALUES(IsEdge), EdgeHtmlVersion = VALUES(EdgeHtmlVersion), TrueVersion = VALUES(TrueVersion), ActingVersion = VALUES(ActingVersion), CompatibilityMode = VALUES(CompatibilityMode), DateUpdated = NOW()")
query.Execute(data)
if ("greeting")
if (server_greeting)
server_greeting.handle_call(href_list, src)
return
// Antag contest shit
@@ -291,10 +293,9 @@
send_resources()
nanomanager.send_resources(src)
var/outdated_greeting_info = server_greeting.find_outdated_info(src)
if (outdated_greeting_info)
server_greeting.display_to_client(src, outdated_greeting_info)
// Server greeting shenanigans.
if (server_greeting.find_outdated_info(src, 1))
server_greeting.display_to_client(src)
// Check code/modules/admin/verbs/antag-ooc.dm for definition
add_aooc_if_necessary()
@@ -418,10 +419,7 @@
'html/images/talisman.png',
'html/bootstrap/css/bootstrap.min.css',
'html/bootstrap/js/bootstrap.min.js',
'html/bootstrap/js/html5shiv.min.js',
'html/bootstrap/js/respond.min.js',
'html/jquery/jquery-2.0.0.min.js',
'html/iestats/json2.min.js',
'html/iestats/ie-truth.min.js',
'icons/pda_icons/pda_atmos.png',
'icons/pda_icons/pda_back.png',
@@ -589,4 +587,7 @@
set name = "Open Greeting"
set category = "OOC"
server_greeting.display_to_client(src, server_greeting.find_outdated_info(src))
// Update the information just in case.
server_greeting.find_outdated_info(src, 1)
server_greeting.display_to_client(src)

View File

@@ -61,13 +61,13 @@
* Returns the HTML required to display this alert.
*/
/datum/client_notification/proc/get_html()
var/html = "<div class=\"row\">[note_wrapper[1]]\n"
var/html = "<div class=\"row\">[note_wrapper[1]]"
if (!persistent)
html += "<a href=\"#\" class=\"close\" data-dismiss=\"alert\" aria-label=\"close\">&times;</a>\n"
html += "<a href=\"#\" class=\"close\" data-dismiss=\"alert\" aria-label=\"close\">&times;</a>"
html += note_text
html += "\n[note_wrapper[2]]</div>"
html += "[note_wrapper[2]]</div>"
return html

View File

@@ -164,10 +164,10 @@
flv.robot_standard,
flv.robot_engineering,
flv.robot_construction,
flv.robot_surgeon,
flv.robot_crisis,
flv.robot_medical,
flv.robot_rescue,
flv.robot_miner,
flv.robot_janitor,
flv.robot_custodial,
flv.robot_service,
flv.robot_clerical,
flv.robot_security,
@@ -305,10 +305,10 @@
flavour_texts_robot["Standard"] = character_query.item[33]
flavour_texts_robot["Engineering"] = character_query.item[34]
flavour_texts_robot["Construction"] = character_query.item[35]
flavour_texts_robot["Surgeon"] = character_query.item[36]
flavour_texts_robot["Crisis"] = character_query.item[37]
flavour_texts_robot["Medical"] = character_query.item[36]
flavour_texts_robot["Rescue"] = character_query.item[37]
flavour_texts_robot["Miner"] = character_query.item[38]
flavour_texts_robot["Janitor"] = character_query.item[39]
flavour_texts_robot["Custodial"] = character_query.item[39]
flavour_texts_robot["Service"] = character_query.item[40]
flavour_texts_robot["Clerical"] = character_query.item[41]
flavour_texts_robot["Security"] = character_query.item[42]
@@ -479,10 +479,10 @@
flv.robot_standard = :robot_standard,
flv.robot_engineering = :robot_engineering,
flv.robot_construction = :robot_construction,
flv.robot_surgeon = :robot_surgeon,
flv.robot_crisis = :robot_crisis,
flv.robot_medical = :robot_medical,
flv.robot_rescue = :robot_rescue,
flv.robot_miner = :robot_miner,
flv.robot_janitor = :robot_janitor,
flv.robot_custodial = :robot_custodial,
flv.robot_service = :robot_service,
flv.robot_clerical = :robot_clerical,
flv.robot_security = :robot_security,
@@ -526,8 +526,8 @@
current_character = text2num(get_query.item[1])
params[":char_id"] = current_character
insert_query = dbcon.NewQuery({"INSERT INTO ss13_characters_flavour (char_id, records_employment, records_medical, records_security, records_exploit, flavour_general, flavour_head, flavour_face, flavour_eyes, flavour_torso, flavour_arms, flavour_hands, flavour_legs, flavour_feet, robot_default, robot_standard, robot_engineering, robot_construction, robot_surgeon, robot_crisis, robot_miner, robot_janitor, robot_service, robot_clerical, robot_security, robot_research)
VALUES (:char_id, :gen_rec, :med_rec, :sec_rec, :exploit_record, :flv_general, :flv_head, :flv_face, :flv_eyes, :flv_torso, :flv_arms, :flv_hands, :flv_legs, :flv_feet, :robot_default, :robot_standard, :robot_engineering, :robot_construction, :robot_surgeon, :robot_crisis, :robot_miner, :robot_janitor, :robot_service, :robot_clerical, :robot_security, :robot_research);"})
insert_query = dbcon.NewQuery({"INSERT INTO ss13_characters_flavour (char_id, records_employment, records_medical, records_security, records_exploit, flavour_general, flavour_head, flavour_face, flavour_eyes, flavour_torso, flavour_arms, flavour_hands, flavour_legs, flavour_feet, robot_default, robot_standard, robot_engineering, robot_construction, robot_medical, robot_rescue, robot_miner, robot_custodial, robot_service, robot_clerical, robot_security, robot_research)
VALUES (:char_id, :gen_rec, :med_rec, :sec_rec, :exploit_record, :flv_general, :flv_head, :flv_face, :flv_eyes, :flv_torso, :flv_arms, :flv_hands, :flv_legs, :flv_feet, :robot_default, :robot_standard, :robot_engineering, :robot_construction, :robot_medical, :robot_rescue, :robot_miner, :robot_custodial, :robot_service, :robot_clerical, :robot_security, :robot_research);"})
insert_query.Execute(params, 1)
if (insert_query.ErrorMsg())
@@ -618,10 +618,10 @@
params[":robot_standard"] = flavour_texts_robot["Standard"]
params[":robot_engineering"] = flavour_texts_robot["Engineering"]
params[":robot_construction"] = flavour_texts_robot["Construction"]
params[":robot_surgeon"] = flavour_texts_robot["Surgeon"]
params[":robot_crisis"] = flavour_texts_robot["Crisis"]
params[":robot_medical"] = flavour_texts_robot["Medical"]
params[":robot_rescue"] = flavour_texts_robot["Rescue"]
params[":robot_miner"] = flavour_texts_robot["Miner"]
params[":robot_janitor"] = flavour_texts_robot["Janitor"]
params[":robot_custodial"] = flavour_texts_robot["Custodial"]
params[":robot_service"] = flavour_texts_robot["Service"]
params[":robot_clerical"] = flavour_texts_robot["Clerical"]
params[":robot_security"] = flavour_texts_robot["Security"]

View File

@@ -905,6 +905,53 @@
/mob/living/carbon/human/get_rig()
return back
//Used in random rig spawning for cargo
//Randomly deletes modules
/obj/item/weapon/rig/proc/lose_modules(var/probability)
for(var/obj/item/rig_module/module in installed_modules)
if (probability)
qdel(module)
//Fiddles with some wires to possibly make the suit malfunction a little
//Had to use numeric literals here, the wire defines in rig_wiring.dm weren't working
//Possibly due to being defined in a later file, or undef'd somewhere
/obj/item/weapon/rig/proc/misconfigure(var/probability)
if (prob(probability))
wires.UpdatePulsed(1)//Fiddle with access
if (prob(probability))
wires.UpdatePulsed(2)//frustrate the AI
if (prob(probability))
wires.UpdateCut(4)//break the suit
if (prob(probability))
wires.UpdatePulsed(8)
if (prob(probability))
wires.UpdateCut(16)
if (prob(probability))
subverted = 1
//Drains, rigs or removes the cell
/obj/item/weapon/rig/proc/sabotage_cell()
if (!cell)
return
if (prob(50))
cell.charge = rand(0, cell.charge*0.5)
else if (prob(15))
cell.rigged = 1
else
cell = null
//Depletes or removes the airtank
/obj/item/weapon/rig/proc/sabotage_tank()
if (!air_supply)
return
if (prob(70))
air_supply.remove_air(air_supply.air_contents.total_moles)
else
air_supply = null
#undef ONLY_DEPLOY
#undef ONLY_RETRACT
#undef SEAL_DELAY

View File

@@ -26,6 +26,13 @@
if(RIG_INTERFACE_SHOCK)
rig.electrified = mended ? 0 : -1
rig.shock(usr,100)
if(RIG_SYSTEM_CONTROL)
if(mended)
rig.malfunctioning = 0
rig.malfunction_delay = 0
else
rig.malfunctioning += 10
rig.malfunction_delay = 99999999999999999999
/datum/wires/rig/UpdatePulsed(var/index)

View File

@@ -114,7 +114,6 @@
/obj/item/rig_module/vision/meson
)
//Chief Engineer's rig. This is sort of a halfway point between the old hardsuits (voidsuits) and the rig class.
/obj/item/weapon/rig/ce
name = "advanced voidsuit control module"
@@ -130,12 +129,10 @@
allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/weapon/rcd)
req_access = list()
req_one_access = list()
boot_type = null
glove_type = null
glove_type = /obj/item/clothing/gloves/rig/ce
/obj/item/weapon/rig/ce/equipped
@@ -149,13 +146,8 @@
/obj/item/rig_module/vision/meson
)
chest_type = /obj/item/clothing/suit/space/rig/ce
boot_type = null
glove_type = null
/obj/item/clothing/suit/space/rig/ce
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
/obj/item/clothing/gloves/rig/ce
siemens_coefficient = 0
/obj/item/weapon/rig/hazmat
@@ -169,8 +161,6 @@
helm_type = /obj/item/clothing/head/helmet/space/rig/hazmat
helm_type = /obj/item/clothing/head/helmet/space/rig/ert
allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/stack/flag,/obj/item/weapon/storage/box/excavation,/obj/item/weapon/pickaxe,/obj/item/device/healthanalyzer,/obj/item/device/measuring_tape,/obj/item/device/ano_scanner,/obj/item/device/depth_scanner,/obj/item/device/core_sampler,/obj/item/device/gps,/obj/item/device/beacon_locator,/obj/item/device/radio/beacon,/obj/item/weapon/pickaxe/hand,/obj/item/weapon/storage/bag/fossils)
req_access = list()

View File

@@ -105,10 +105,34 @@
sprite_sheets = list("Vox" = 'icons/mob/species/vox/suit.dmi')
siemens_coefficient = 0.7
/obj/item/clothing/suit/storage/det_trench/grey
name = "grey trenchcoat"
/obj/item/clothing/suit/storage/det_suit/black
icon_state = "detective2"
/obj/item/clothing/suit/storage/det_suit/technicolor
desc = "A 23rd-century multi-purpose trenchcoat. It's fibres are hyper-absorbent."
icon = 'icons/obj/clothing/coloured_detective_coats.dmi'
icon_state = "suit_detective_black"
item_state = "suit_detective_black"
var/suit_color
contained_sprite = 1
/obj/item/clothing/suit/storage/det_suit/technicolor/New()
if(prob(5))
var/list/colors = list("yellow"=2,"red"=1,"white"=1,"orange"=1,"purple"=1,"green"=1,"blue"=1 )
var/color = pickweight(colors)
icon_state = "suit_detective_[color]"
item_state = "suit_detective_[color]"
..()
/obj/item/clothing/suit/storage/det_suit/technicolor/attackby(obj/item/weapon/O as obj, mob/user as mob)
if(istype(O, /obj/item/weapon/reagent_containers/glass/paint))
var/obj/item/weapon/reagent_containers/glass/paint/P = O
suit_color = P.paint_type
user.visible_message("<span class='warning'>[user] soaks \the [src] into [P]!</span>")
icon_state = "suit_detective_[suit_color]"
item_state = "suit_detective_[suit_color]"
..()
//Forensics
/obj/item/clothing/suit/storage/forensics
name = "jacket"

View File

@@ -402,3 +402,13 @@
item_state = "black_hoodie"
icon_open = "black_hoodie_open"
icon_closed = "black_hoodie"
/obj/item/clothing/suit/storage/toggle/tracksuit
name = "track jacket"
desc = "An athletic black and white track jacket."
icon = 'icons/obj/tracksuit.dmi'
icon_state = "trackjacket"
item_state = "trackjacket"
icon_open = "trackjacket_open"
icon_closed = "trackjacket"
contained_sprite = 1

View File

@@ -120,6 +120,31 @@
icon_state = "detective2"
desc = "A grey fedora - either the cornerstone of a detective's style or a poor attempt at looking cool, depending on the person wearing it."
/obj/item/clothing/head/det_hat/technicolor
desc = "A 23rd-century fedora. It's fibres are hyper-absorbent."
icon = 'icons/obj/clothing/coloured_detective_coats.dmi'
icon_state = "hat_detective_black"
item_state = "hat_detective_black"
var/hat_color
contained_sprite = 1
/obj/item/clothing/head/det_hat/technicolor/New()
if(prob(5))
var/list/colors = list("yellow"=2,"red"=1,"white"=1,"orange"=1,"purple"=1,"green"=1,"blue"=1 )
var/color = pickweight(colors)
icon_state = "hat_detective_[color]"
item_state = "hat_detective_[color]"
..()
obj/item/clothing/head/det_hat/technicolor/attackby(obj/item/weapon/O as obj, mob/user as mob)
if(istype(O, /obj/item/weapon/reagent_containers/glass/paint))
var/obj/item/weapon/reagent_containers/glass/paint/P = O
hat_color = P.paint_type
user.visible_message("<span class='warning'>[user] soaks \the [src] into [P]!</span>")
icon_state = "hat_detective_[hat_color]"
item_state = "hat_detective_[hat_color]"
..()
/*
* Head of Security

View File

@@ -525,3 +525,11 @@
icon_state = "blue_blazer"
item_state = "blue_blazer"
worn_state = "blue_blazer"
/obj/item/clothing/under/track
name = "track pants"
desc = "Track pants, perfect for squatting."
icon = 'icons/obj/tracksuit.dmi'
icon_state = "trackpants"
item_state = "trackpants"
contained_sprite = 1

View File

@@ -19,3 +19,11 @@
worn_state = "tactifool"
siemens_coefficient = 1
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
/obj/item/clothing/under/syndicate/tracksuit
name = "tactical tracksuit"
desc = "A tactical ready tracksuit, perfect for stealthy operations and squatting in cold places."
icon = 'icons/obj/tracksuit.dmi'
icon_state = "fulltracksuit"
item_state = "fulltracksuit"
contained_sprite = 1

View File

@@ -138,6 +138,7 @@ All custom items with worn sprites must follow the contained sprite system: http
user << "You close the pocket altar."
desc = "A black tin box with a symbol painted over it. It shimmers in the light."
/obj/item/clothing/head/det_hat/fluff/bell_hat //Brown Hat - Avery Bell - serveris6 - DONE
name = "brown hat"
desc = "A worn mid 20th century brown hat. It seems to have aged very well."
@@ -146,7 +147,6 @@ All custom items with worn sprites must follow the contained sprite system: http
item_state = "bell_hat"
contained_sprite = 1
/obj/item/clothing/suit/storage/det_suit/fluff/bell_coat //Pinned Brown Coat - Avery Bell - serveris6 - DONE
name = "pinned brown coat"
desc = "A worn mid 20th century brown trenchcoat. If you look closely at the breast, you can see an ID flap stitched into the leather - 'Avery Bell, Silhouette Co.'."
@@ -256,11 +256,6 @@ All custom items with worn sprites must follow the contained sprite system: http
/obj/item/weapon/contraband/poster/fluff/conservan_poster/New()
serial_number = 59
/datum/poster/bay_59
name = "ATLAS poster"
desc = "ATLAS: For all of Humanity."
icon_state = "bposter59"
/obj/item/weapon/flame/lighter/zippo/fluff/locke_zippo // Fire Extinguisher Zippo - Jacob Locke - completegarbage - DONE
name = "fire extinguisher lighter"
@@ -554,3 +549,76 @@ All custom items with worn sprites must follow the contained sprite system: http
icon = 'icons/obj/custom_items/akela_photo.dmi'
icon_state = "akela_photo"
w_class = 2
/obj/item/weapon/implant/fluff/ziva_implant //Heart Condition - Ziva Ta'Kim - sierrakomodo - DONE
name = "heart monitor"
desc = "A small machine to watch upon broken hearts."
/obj/item/weapon/implant/fluff/ziva_implant/implanted(mob/living/carbon/human/M as mob)
if (M.ckey == "sierrakomodo") //just to be sure
M.verbs += /mob/living/carbon/human/proc/heart_attack
else
return
/mob/living/carbon/human/proc/heart_attack()
set category = "IC"
set name = "Suffer Heart Condition"
set desc = "HNNNNG."
if(last_special > world.time)
src << "<span class='warning'>Your chest still hurts badly!</span>"
return
last_special = world.time + 500
var/obj/item/organ/F = src.internal_organs_by_name["heart"]
if(isnull(F))
return
F.damage += 5
src << "<span class='warning'>You feel a stabbing pain in your chest!</span>"
playsound(user, 'sound/effects/Heart Beat.ogg', 20, 1)
/obj/item/clothing/accessory/badge/fluff/caleb_badge //Worn Badge - Caleb Greene - notmegatron - DONE
name = "worn badge"
desc = "A simple gold badge denoting the wearer as Head of Security. It is worn and dulled with age, but the name, Caleb Greene, is still clearly legible."
icon_state = "badge"
icon = 'icons/obj/custom_items/caleb_badge.dmi'
item_state = "caleb_badge"
icon_state = "caleb_badge"
stored_name = "Caleb Greene"
badge_string = "NOS Apollo Head of Security"
contained_sprite = 1
/obj/item/fluff/messa_pressing //Pressing of Messa's Tears - Poslan Kur'yer-Isra - jboy2000000 - DONE
name = "pressing of Messa's tears"
desc = "As Messa looked at the pain and death wrought on the world she had given life, she cried, and from her tears sprouted these leaves."
icon = 'icons/obj/custom_items/cat_religion.dmi'
icon_state = "messa"
w_class = 2
/obj/item/fluff/srendarr_pressing //Pressing of S'Rendarr's Hand - Poslan Kur'yer-Isra - jboy2000000 - DONE
name = "pressing of S'Rendarr's hand"
desc = "As S'Rendarr watched her sister cry, she felt rage never known to her before. Her fists clashed with those who upset her sister, and from their blood came these."
icon = 'icons/obj/custom_items/cat_religion.dmi'
icon_state = "srendarr"
w_class = 2
/obj/item/clothing/suit/chaplain_hoodie/fluff/poslan_jacket //Twin Suns Throw-over - Poslan Kur'yer-Isra - jboy2000000 - DONE
name = "twin suns throw-over"
desc = "A light black jacket, on one side of its breast is the design of a yellow sun, and on the other side there is a smaller blue sun."
icon = 'icons/obj/custom_items/cat_religion.dmi'
icon_state = "poslan_jacket"
item_state = "poslan_jacket"
contained_sprite = 1
/obj/item/sign/fluff/alexis_degree //Xenonuerology Doctorate - Alexis Shaw - Tenenza - DONE
name = "xenonuerology degree"
desc = "Certification for a doctorate in Xenonuerology, made out to Alexis Shaw by the St. Grahelm University of Biesel, authenticated by watermarking."
icon_state = "alexis_degree"
sign_state = "alexis_degree"
w_class = 2

View File

@@ -142,8 +142,10 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Trivial News", /datum/event/trivial_news, 400),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Vermin Infestation",/datum/event/infestation, 60, list(ASSIGNMENT_JANITOR = 20, ASSIGNMENT_SECURITY = 10)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Wallrot", /datum/event/wallrot, 75, list(ASSIGNMENT_ENGINEER = 5, ASSIGNMENT_GARDENER = 20)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Clogged Vents", /datum/event/vent_clog, 100),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Clogged Vents", /datum/event/vent_clog, 85),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "False Alarm", /datum/event/false_alarm, 100),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Supply Drop", /datum/event/supply_drop, 80),
)
/datum/event_container/moderate
@@ -171,13 +173,13 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT
/datum/event_container/major
severity = EVENT_LEVEL_MAJOR
available_events = list(
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Nothing", /datum/event/nothing, 80),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Nothing", /datum/event/nothing, 90),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Blob", /datum/event/blob, 50, list(ASSIGNMENT_ENGINEER = 5,ASSIGNMENT_SECURITY = 5), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, 60, list(ASSIGNMENT_SECURITY = 10), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Wave", /datum/event/meteor_wave, 40, list(ASSIGNMENT_ENGINEER = 10),1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Space Vines", /datum/event/spacevine, 50, list(ASSIGNMENT_ENGINEER = 10, ASSIGNMENT_GARDENER = 20), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Space Vines", /datum/event/spacevine, 60, list(ASSIGNMENT_ENGINEER = 10, ASSIGNMENT_GARDENER = 20), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Viral Infection", /datum/event/viral_infection, 20, list(ASSIGNMENT_MEDICAL = 13), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Bluespace Bears", /datum/event/bear_attack, 60, list(ASSIGNMENT_SECURITY = 10), 1)
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Bluespace Bears", /datum/event/bear_attack, 50, list(ASSIGNMENT_SECURITY = 10), 1)
)
//NOTE: Re added nothing option, but with fairly low weight

View File

@@ -104,7 +104,7 @@
spawn_area_type = /area/quartermaster/office
locstrings[numlocs] = "the cargo disposals office"
if(LOC_CARGO)
spawn_area_type = /area/quartermaster/storage
spawn_area_type = /area/quartermaster/loading
locstrings[numlocs] = "the cargo bay"
if(LOC_MEETING)
spawn_area_type = /area/bridge/meeting_room

View File

@@ -1,7 +1,7 @@
/var/global/spacevines_spawned = 0
/datum/event/spacevine
announceWhen = 10
announceWhen = 30
ic_name = "a biohazard"
/datum/event/spacevine/start()

View File

@@ -0,0 +1,34 @@
//This mundane event spawns a random crate of loot
/datum/event/supply_drop
var/location_name
var/turf/spawn_loc
/datum/event/supply_drop/setup()
announceWhen = rand(0,80)
/datum/event/supply_drop/start()
var/rarity = rand()*3
rarity = min(1, rarity)
var/quantity = rand(5,15)
var/area/a = random_station_area()
spawn_loc = a.random_space()
location_name = a.name
new /obj/structure/closet/crate/loot(spawn_loc, rarity, quantity)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(10, 0, spawn_loc)
s.start()
spawn(2)
qdel(s)
/datum/event/supply_drop/announce()
if (prob(65))//Announce the location
command_announcement.Announce("Transport signature of unknown origin detected in [location_name], an object appears to have been beamed aboard [station_name()].", "Unknown Object")
else if (prob(25))//Announce the transport, but not the location
command_announcement.Announce("External transport signature of unknown origin detected aboard [station_name()], precise destination point cannot be determined, please investigate.", "Unknown Object")
//Otherwise, no announcement at all.
//Someone will randomly stumble across it, and probably quietly loot it without telling anyone

View File

@@ -28,10 +28,6 @@
updateVisibility(src)
return ..()
/obj/structure/New()
..()
updateVisibility(src)
// EFFECTS
/obj/effect/Destroy()

View File

@@ -60,6 +60,14 @@
else
return 0
/mob/living/bot/proc/has_ui_access(mob/user)
if (access_scanner.allowed(user))
return 1
if (!locked)
return 1
if (isAI(user))
return 1
return 0
/mob/living/bot/attackby(var/obj/item/O, var/mob/user)
if(O.GetID())

View File

@@ -247,8 +247,12 @@ var/list/cleanbot_types // Going to use this to generate a list of types once th
patrol_path = list()
/mob/living/bot/cleanbot/attack_hand(var/mob/user)
if (!has_ui_access(user) && !emagged)
user << "<span class='warning'>The unit's interface refuses to unlock!</span>"
return
var/dat
dat += "<TT><B>Automatic Station Cleaner v1.0</B></TT><BR><BR>"
dat += "<TT><B>Automatic Station Cleaner v1.1</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];operation=start'>[on ? "On" : "Off"]</A><BR>"
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<BR>"
dat += "Maintenance panel is [open ? "opened" : "closed"]"
@@ -259,7 +263,7 @@ var/list/cleanbot_types // Going to use this to generate a list of types once th
dat += "Odd looking screw twiddled: <A href='?src=\ref[src];operation=screw'>[screwloose ? "Yes" : "No"]</A><BR>"
dat += "Weird button pressed: <A href='?src=\ref[src];operation=oddbutton'>[oddbutton ? "Yes" : "No"]</A>"
user << browse("<HEAD><TITLE>Cleaner v1.0 controls</TITLE></HEAD>[dat]", "window=autocleaner")
user << browse("<HEAD><TITLE>Cleaner v1.1 controls</TITLE></HEAD>[dat]", "window=autocleaner")
onclose(user, "autocleaner")
return
@@ -268,6 +272,11 @@ var/list/cleanbot_types // Going to use this to generate a list of types once th
return
usr.set_machine(src)
add_fingerprint(usr)
if (!has_ui_access(usr) && !emagged)
usr << "<span class='warning'>Insufficient permissions.</span>"
return
switch(href_list["operation"])
if("start")
if(on)

View File

@@ -38,8 +38,13 @@
. = ..()
if(.)
return
if (!has_ui_access(user))
user << "<span class='warning'>The unit's interface refuses to unlock!</span>"
return
var/dat = ""
dat += "<TT><B>Automatic Hyrdoponic Assisting Unit v1.0</B></TT><BR><BR>"
dat += "<TT><B>Automatic Hyrdoponic Assisting Unit v1.1</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];power=1'>[on ? "On" : "Off"]</A><BR>"
dat += "Water Tank: "
if (tank)
@@ -47,7 +52,7 @@
else
dat += "Error: Watertank not found"
dat += "<br>Behaviour controls are [locked ? "locked" : "unlocked"]<hr>"
if(!locked)
if(!locked || issilicon(usr))
dat += "<TT>Watering controls:<br>"
dat += "Water plants : <A href='?src=\ref[src];water=1'>[waters_trays ? "Yes" : "No"]</A><BR>"
dat += "Refill watertank : <A href='?src=\ref[src];refill=1'>[refills_water ? "Yes" : "No"]</A><BR>"
@@ -60,7 +65,7 @@
dat += "Remove dead plants: <A href='?src=\ref[src];removedead=1'>[removes_dead ? "Yes" : "No"]</A><BR>"
dat += "</TT>"
user << browse("<HEAD><TITLE>Farmbot v1.0 controls</TITLE></HEAD>[dat]", "window=autofarm")
user << browse("<HEAD><TITLE>Farmbot v1.1 controls</TITLE></HEAD>[dat]", "window=autofarm")
onclose(user, "autofarm")
return
@@ -79,13 +84,18 @@
return
usr.machine = src
add_fingerprint(usr)
if((href_list["power"]) && (access_scanner.allowed(usr)))
if (!has_ui_access(usr))
usr << "<span class='warning'>Insufficient permissions.</span>"
return
if(href_list["power"])
if(on)
turn_off()
else
turn_on()
if(locked)
if(locked && !issilicon(usr))
return
if(href_list["water"])

View File

@@ -26,9 +26,13 @@
icon_state = "floorbot[on]e"
/mob/living/bot/floorbot/attack_hand(var/mob/user)
if (!has_ui_access(user))
user << "<span class='warning'>The unit's interface refuses to unlock!</span>"
return
user.set_machine(src)
var/dat
dat += "<TT><B>Automatic Station Floor Repairer v1.0</B></TT><BR><BR>"
dat += "<TT><B>Automatic Station Floor Repairer v1.1</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];operation=start'>[src.on ? "On" : "Off"]</A><BR>"
dat += "Maintenance panel is [open ? "opened" : "closed"]<BR>"
//dat += "Tiles left: [amount]<BR>"
@@ -44,7 +48,7 @@
bmode = "Disabled"
dat += "<BR><BR>Bridge Mode : <A href='?src=\ref[src];operation=bridgemode'>[bmode]</A><BR>"
user << browse("<HEAD><TITLE>Repairbot v1.0 controls</TITLE></HEAD>[dat]", "window=autorepair")
user << browse("<HEAD><TITLE>Repairbot v1.1 controls</TITLE></HEAD>[dat]", "window=autorepair")
onclose(user, "autorepair")
return
@@ -61,6 +65,11 @@
return
usr.set_machine(src)
add_fingerprint(usr)
if (!has_ui_access(usr))
usr << "<span class='warning'>Insufficient permissions.</span>"
return
switch(href_list["operation"])
if("start")
if (on)

View File

@@ -120,8 +120,12 @@
icon_state = "medibot[on]"
/mob/living/bot/medbot/attack_hand(var/mob/user)
if (!has_ui_access(user))
user << "<span class='warning'>The unit's interface refuses to unlock!</span>"
return
var/dat
dat += "<TT><B>Automatic Medical Unit v1.0</B></TT><BR><BR>"
dat += "<TT><B>Automatic Medical Unit v1.1</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];power=1'>[on ? "On" : "Off"]</A><BR>"
dat += "Maintenance panel is [open ? "opened" : "closed"]<BR>"
dat += "Beaker: "
@@ -152,7 +156,7 @@
dat += "The speaker switch is [vocal ? "on" : "off"]. <a href='?src=\ref[src];togglevoice=[1]'>Toggle</a><br>"
user << browse("<HEAD><TITLE>Medibot v1.0 controls</TITLE></HEAD>[dat]", "window=automed")
user << browse("<HEAD><TITLE>Medibot v1.1 controls</TITLE></HEAD>[dat]", "window=automed")
onclose(user, "automed")
return
@@ -178,13 +182,18 @@
return
usr.set_machine(src)
add_fingerprint(usr)
if ((href_list["power"]) && access_scanner.allowed(usr))
if (!has_ui_access(usr))
usr << "<span class='warning'>Insufficient permissions.</span>"
return
if (href_list["power"])
if (on)
turn_off()
else
turn_on()
else if((href_list["adj_threshold"]) && (!locked || issilicon(usr)))
else if(href_list["adj_threshold"] && (!locked || issilicon(usr)))
var/adjust_num = text2num(href_list["adj_threshold"])
heal_threshold += adjust_num
if(heal_threshold < 5)
@@ -192,7 +201,7 @@
if(heal_threshold > 75)
heal_threshold = 75
else if((href_list["adj_inject"]) && (!locked || issilicon(usr)))
else if(href_list["adj_inject"] && (!locked || issilicon(usr)))
var/adjust_num = text2num(href_list["adj_inject"])
injection_amount += adjust_num
if(injection_amount < 5)
@@ -200,7 +209,7 @@
if(injection_amount > 15)
injection_amount = 15
else if((href_list["use_beaker"]) && (!locked || issilicon(usr)))
else if(href_list["use_beaker"] && (!locked || issilicon(usr)))
use_beaker = !use_beaker
else if (href_list["eject"] && (!isnull(reagent_glass)))
@@ -210,10 +219,10 @@
else
usr << "<span class='notice'>You cannot eject the beaker because the panel is locked.</span>"
else if ((href_list["togglevoice"]) && (!locked || issilicon(usr)))
else if (href_list["togglevoice"] && (!locked || issilicon(usr)))
vocal = !vocal
else if ((href_list["declaretreatment"]) && (!locked || issilicon(usr)))
else if (href_list["declaretreatment"] && (!locked || issilicon(usr)))
declare_treatment = !declare_treatment
attack_hand(usr)
@@ -255,6 +264,12 @@
qdel(src)
return
/mob/living/bot/medbot/turn_off()
patient = null
frustration = 0
currently_healing = 0
..()
/mob/living/bot/medbot/proc/valid_healing_target(var/mob/living/carbon/human/H)
if(H.stat == DEAD) // He's dead, Jim
return null

View File

@@ -39,7 +39,7 @@
var/next_destination = "__nearest__" // This is the next beacon's ID
var/nearest_beacon // Tag of the beakon that we assume to be the closest one
var/bot_version = 1.3
var/bot_version = 1.4
var/list/threat_found_sounds = new('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg')
var/list/preparing_arrest_sounds = new('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg')
@@ -76,6 +76,9 @@
set_light(0)
/mob/living/bot/secbot/attack_hand(var/mob/user)
if (!has_ui_access(user))
user << "<span class='warning'>The unit's interface refuses to unlock!</span>"
return
user.set_machine(src)
var/dat
dat += "<TT><B>Automatic Security Unit v[bot_version]</B></TT><BR><BR>"
@@ -100,11 +103,18 @@
usr.set_machine(src)
add_fingerprint(usr)
if((href_list["power"]) && (access_scanner.allowed(usr)))
if (!has_ui_access(usr))
usr << "<span class='warning'>Insufficient permissions.</span>"
return
if(href_list["power"])
if(on)
turn_off()
else
turn_on()
attack_hand(usr)
if (locked && !issilicon(usr))
return
switch(href_list["operation"])

View File

@@ -229,14 +229,19 @@
src.visible_message("<span class='danger'>[src] is trying to bite [donor.name]</span>", "\red You start biting [donor.name], you and them must stay still!")
face_atom(get_turf(donor))
if (do_mob(src, donor, 30, needhand = 0))
if (do_mob(src, donor, 40, needhand = 0))
//Attempt to find the blood vessel, but don't create a fake one if its not there.
//If the target doesn't have a vessel its probably due to someone not implementing it properly, like xenos
//We'll still allow it
var/datum/reagents/vessel = donor.get_vessel(1)
var/newDNA
vessel.remove_reagent("blood", 85, 1)//85 units of blood is enough to affect a human and make them woozy
var/datum/reagent/blood/B = vessel.get_master_reagent()
var/total_blood = B.volume
var/remove_amount = (total_blood - 280) * 0.3
if (remove_amount > 0)
vessel.remove_reagent("blood", remove_amount, 1)//85 units of blood is enough to affect a human and make them woozy
nutrition += remove_amount*0.5
var/list/data = vessel.get_data("blood")
newDNA = data["blood_DNA"]
@@ -246,7 +251,7 @@
donor.adjustBruteLoss(4)
src.visible_message("<span class='notice'>[src] sucks some blood from [donor.name]</span>", "<span class='notice'>You extract a delicious mouthful of blood from [donor.name]!</span>")
nutrition += 40
if (newDNA in sampled_DNA)

View File

@@ -1154,6 +1154,12 @@
if (src.is_diona())
setup_gestalt(1)
max_stamina = species.stamina
stamina = max_stamina
sprint_speed_factor = species.sprint_speed_factor
sprint_cost_factor = species.sprint_cost_factor
stamina_recovery = species.stamina_recovery
exhaust_threshold = species.exhaust_threshold
if(species)
return 1
else

View File

@@ -18,7 +18,7 @@
var/clone_l = getCloneLoss()
health = maxHealth - oxy_l - tox_l - clone_l - total_burn - total_brute
update_health_display()
//TODO: fix husking
if( ((maxHealth - total_burn) < config.health_threshold_dead) && stat == DEAD)
ChangeToHusk()

View File

@@ -159,9 +159,13 @@ emp_act
var/hit_zone = get_zone_with_miss_chance(target_zone, src)
if(!hit_zone)
visible_message("<span class='danger'>\The [user] misses [src] with \the [I]!</span>")
return null
if(user == src) // Attacking yourself can't miss
target_zone = user.zone_sel.selecting
if(!target_zone)
visible_message("\red <B>[user] misses [src] with \the [I]!")
return 0
var/obj/item/organ/external/affecting = get_organ(target_zone)
if(check_shields(I.force, I, user, target_zone, "the [I.name]"))
return null

View File

@@ -1,7 +1,6 @@
/mob/living/carbon/human/movement_delay()
var/tally = 0
if(species.slowdown)
tally = species.slowdown
@@ -10,8 +9,7 @@
if(embedded_flag)
handle_embedded_objects() //Moving with objects stuck in you can cause bad times.
if(CE_SPEEDBOOST in chem_effects)
return -1
var/health_deficiency = (100 - health)
if(health_deficiency >= 40) tally += (health_deficiency / 25)
@@ -49,20 +47,30 @@
if(shock_stage >= 10) tally += 3
if(aiming && aiming.aiming_at) tally += 5 // Iron sights make you slower, it's a well-known fact.
if (drowsyness) tally += 6
if(FAT in src.mutations)
tally += 1.5
if (bodytemperature < 283.222)
tally += (283.222 - bodytemperature) / 10 * 1.75
tally += max(2 * stance_damage, 0) //damaged/missing feet or legs is slow
if(mRun in mutations)
tally = 0
tally += move_delay_mod
if(tally > 0 && (CE_SPEEDBOOST in chem_effects))
tally = max(0, tally-3)
return (tally+config.human_delay)
/mob/living/carbon/human/Process_Spacemove(var/check_drift = 0)
//Can we act?
if(restrained()) return 0

View File

@@ -1,7 +1,9 @@
#define AE_DIZZY 5
#define AE_BUZZED_MIN 6
#define AE_SLURRING 15
#define AE_CONFUSION 18
#define AE_CLUMSY 22
#define AE_BUZZED_MAX 24
#define AE_BLURRING 25
#define AE_VOMIT 40
#define AE_DROWSY 55
@@ -70,3 +72,48 @@ var/mob/living/carbon/human/alcohol_clumsy = 0
if(intoxication > AE_BLACKOUT*SR) // Pass out
paralysis = max(paralysis, 20)
sleeping = max(sleeping, 30)
if( intoxication >= AE_BUZZED_MIN && intoxication <= AE_BUZZED_MAX && !(locate(/datum/modifier/buzzed) in modifiers))
add_modifier(/datum/modifier/buzzed, MODIFIER_CUSTOM)
//Pleasant feeling from being slightly drunk
//Makes you faster and reduces sprint cost
//Wears off if you get too drunk or too sober, a balance must be maintained
/datum/modifier/buzzed
/datum/modifier/buzzed/activate()
..()
if (ishuman(target))
var/mob/living/carbon/human/H = target
H.move_delay_mod += -0.75
H.sprint_cost_factor += -0.1
/datum/modifier/buzzed/deactivate()
..()
if (ishuman(target))
var/mob/living/carbon/human/H = target
H.move_delay_mod -= -0.75
H.sprint_cost_factor -= -0.1
/datum/modifier/buzzed/custom_validity()
if (ishuman(target))
var/mob/living/carbon/human/H = target
if (H.intoxication >= AE_BUZZED_MIN && H.intoxication <= AE_BUZZED_MAX)
return 1
return 0
#undef AE_DIZZY
#undef AE_BUZZED_MIN
#undef AE_SLURRING
#undef AE_CONFUSION
#undef AE_CLUMSY
#undef AE_BUZZED_MAX
#undef AE_BLURRING
#undef AE_VOMIT
#undef AE_DROWSY
#undef AE_OVERDOSE
#undef AE_BLACKOUT

View File

@@ -84,6 +84,9 @@
handle_heartbeat()
//Handles regenerating stamina if we have sufficient air and no oxyloss
handle_stamina()
if (is_diona())
diona_handle_light(DS)
@@ -574,6 +577,50 @@
adjustOxyLoss(-5)
// Hot air hurts :(
if((breath.temperature < species.cold_level_1 || breath.temperature > species.heat_level_1) && !(COLD_RESISTANCE in mutations))
if(breath.temperature <= species.cold_level_1)
if(prob(20))
src << "<span class='danger'>You feel your face freezing and icicles forming in your lungs!</span>"
else if(breath.temperature >= species.heat_level_1)
if(prob(20))
src << "<span class='danger'>You feel your face burning and a searing heat in your lungs!</span>"
if(breath.temperature >= species.heat_level_1)
if(breath.temperature < species.heat_level_2)
apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, "head", used_weapon = "Excessive Heat")
fire_alert = max(fire_alert, 2)
else if(breath.temperature < species.heat_level_3)
apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, "head", used_weapon = "Excessive Heat")
fire_alert = max(fire_alert, 2)
else
apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Heat")
fire_alert = max(fire_alert, 2)
else if(breath.temperature <= species.cold_level_1)
if(breath.temperature > species.cold_level_2)
apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, "head", used_weapon = "Excessive Cold")
fire_alert = max(fire_alert, 1)
else if(breath.temperature > species.cold_level_3)
apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, "head", used_weapon = "Excessive Cold")
fire_alert = max(fire_alert, 1)
else
apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Cold")
fire_alert = max(fire_alert, 1)
//breathing in hot/cold air also heats/cools you a bit
var/temp_adj = breath.temperature - bodytemperature
if (temp_adj < 0)
temp_adj /= (BODYTEMP_COLD_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed
else
failed_last_breath = 0
adjustOxyLoss(-3)
// Hot air hurts :(
if((breath.temperature < species.cold_level_1 || breath.temperature > species.heat_level_1) && !(COLD_RESISTANCE in mutations))
@@ -1016,6 +1063,13 @@
else //ALIVE. LIGHTS ARE ON
updatehealth() //TODO
if(health <= config.health_threshold_dead || (species.has_organ["brain"] && !has_brain()))
death()
blinded = 1
silent = 0
else //ALIVE. LIGHTS ARE ON
updatehealth() //TODO
if(health <= config.health_threshold_dead || (species.has_organ["brain"] && !has_brain()))
death()
blinded = 1
@@ -1023,10 +1077,14 @@
return 1
//UNCONSCIOUS. NO-ONE IS HOME
if((getOxyLoss() > 50) || (health <= config.health_threshold_crit))
if((getOxyLoss() > exhaust_threshold) || (health <= config.health_threshold_crit))
Paralyse(3)
if(hallucination)
//Machines do not hallucinate.
if (species.flags & IS_SYNTHETIC)
hallucination = 0
else
if(hallucination >= 20)
if(prob(3))
fake_attack(src)
@@ -1034,10 +1092,17 @@
spawn handle_hallucinations() //The not boring kind!
if(client && prob(5))
client.dir = pick(2,4,8)
var/client/C = client
spawn(rand(20,50))
client.dir = 1
if(C)
C.dir = 1
if(hallucination<=2)
hallucination = 0
halloss = 0
else
hallucination -= 2
hallucination = max(0, hallucination - 2)
else
for(var/atom/a in hallucinations)
qdel(a)
@@ -1230,23 +1295,63 @@
I = overlays_cache[23]
damageoverlay.overlays += I
if( stat == DEAD )
sight = SEE_TURFS|SEE_MOBS|SEE_OBJS|SEE_SELF
see_in_dark = 8
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(healths) healths.icon_state = "health7" //DEAD healthmeter
// #TODO-MERGE: Check the indentation of this file! It's awful!
if(healths)
if (analgesic > 100)
healths.icon_state = "health_numb"
if(client.view != world.view) // If mob dies while zoomed in with device, unzoom them.
for(var/obj/item/item in contents)
if(item.zoom)
item.zoom()
break
/*
if(locate(/obj/item/weapon/gun/energy/sniperrifle, contents))
var/obj/item/weapon/gun/energy/sniperrifle/s = locate() in src
if(s.zoom)
s.zoom()
if(locate(/obj/item/device/binoculars, contents))
var/obj/item/device/binoculars/b = locate() in src
if(b.zoom)
b.zoom()
*/
else
switch(hal_screwyhud)
if(1) healths.icon_state = "health6"
if(2) healths.icon_state = "health7"
if(is_ventcrawling == 0) // Stops sight returning to normal if inside a vent
sight = species.vision_flags
see_in_dark = species.darksight
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING
if(XRAY in mutations)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
see_in_dark = 8
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(seer)
var/obj/effect/rune/R = locate() in loc
if(R && R.word1 == cultwords["see"] && R.word2 == cultwords["hell"] && R.word3 == cultwords["join"])
see_invisible = SEE_INVISIBLE_CULT
else
//switch(health - halloss)
switch(100 - ((species.flags & NO_PAIN) ? 0 : traumatic_shock))
if(100 to INFINITY) healths.icon_state = "health0"
if(80 to 100) healths.icon_state = "health1"
if(60 to 80) healths.icon_state = "health2"
if(40 to 60) healths.icon_state = "health3"
if(20 to 40) healths.icon_state = "health4"
if(0 to 20) healths.icon_state = "health5"
else healths.icon_state = "health6"
seer = 0
if(!seer)
see_invisible = SEE_INVISIBLE_LIVING
var/equipped_glasses = glasses
var/obj/item/weapon/rig/rig = back
if(istype(rig) && rig.visor)
if(!rig.helmet || (head && rig.helmet == head))
if(rig.visor && rig.visor.vision && rig.visor.active && rig.visor.vision.glasses)
equipped_glasses = rig.visor.vision.glasses
if(equipped_glasses)
process_glasses(equipped_glasses)
update_health_display()
if(nutrition_icon)
switch(nutrition)
@@ -1684,5 +1789,62 @@
if(XRAY in mutations)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
/mob/living/carbon/human/proc/handle_stamina()
if (species.stamina == -1)//If species stamina is -1, it has special mechanics which will be handled elsewhere
return//so quit this function
if (failed_last_breath || oxyloss > exhaust_threshold)//Can't catch our breath if we're suffocating
return
if (stamina != max_stamina)
//Any suffocation damage slows stamina regen.
//This includes oxyloss from low blood levels
var/regen = stamina_recovery * (1 - min(((oxyloss*2) / exhaust_threshold), 1))
if (regen > 0)
stamina = min(max_stamina, stamina+regen)
nutrition -= stamina_recovery*0.4
hud_used.move_intent.update_move_icon(src)
/mob/living/carbon/human/proc/update_health_display()
if(!healths)
return
if (analgesic > 100)
healths.icon_state = "health_numb"
else
switch(hal_screwyhud)
if(1) healths.icon_state = "health6"
if(2) healths.icon_state = "health7"
else
//switch(health - halloss)
switch(health - traumatic_shock)
if(100 to INFINITY) healths.icon_state = "health0"
if(80 to 100) healths.icon_state = "health1"
if(60 to 80) healths.icon_state = "health2"
if(40 to 60) healths.icon_state = "health3"
if(20 to 40) healths.icon_state = "health4"
if(0 to 20) healths.icon_state = "health5"
else healths.icon_state = "health6"
/mob/living/carbon/human/proc/update_oxy_overlay()
if(oxyloss)
var/image/I
switch(oxyloss)
if(10 to 20)
I = overlays_cache[11]
if(20 to 25)
I = overlays_cache[12]
if(25 to 30)
I = overlays_cache[13]
if(30 to 35)
I = overlays_cache[14]
if(35 to 40)
I = overlays_cache[15]
if(40 to 45)
I = overlays_cache[16]
if(45 to INFINITY)
I = overlays_cache[17]
damageoverlay.overlays += I
#undef HUMAN_MAX_OXYLOSS
#undef HUMAN_CRIT_MAX_OXYLOSS

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