mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-24 00:51:26 +00:00
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:
BIN
ByondPOST.dll
BIN
ByondPOST.dll
Binary file not shown.
@@ -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,
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
22
code/controllers/Processes/modifier.dm
Normal file
22
code/controllers/Processes/modifier.dm
Normal 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")
|
||||
89
code/controllers/Processes/night_lighting.dm
Normal file
89
code/controllers/Processes/night_lighting.dm
Normal 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
|
||||
@@ -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")
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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]!",\
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
452
code/game/modifiers/modifiers.dm
Normal file
452
code/game/modifiers/modifiers.dm
Normal 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
|
||||
73
code/game/modifiers/modifiers_chem.dm
Normal file
73
code/game/modifiers/modifiers_chem.dm
Normal 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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
..()
|
||||
|
||||
@@ -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()
|
||||
..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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"))
|
||||
|
||||
|
||||
@@ -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)]"
|
||||
|
||||
..()
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
|
||||
/obj/structure/New()
|
||||
..()
|
||||
updateVisibility(src)
|
||||
if(climbable)
|
||||
verbs += /obj/structure/proc/climb_on
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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]"
|
||||
|
||||
|
||||
1889
code/modules/cargo/randomstock.dm
Normal file
1889
code/modules/cargo/randomstock.dm
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
@@ -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\">×</a>\n"
|
||||
html += "<a href=\"#\" class=\"close\" data-dismiss=\"alert\" aria-label=\"close\">×</a>"
|
||||
|
||||
html += note_text
|
||||
html += "\n[note_wrapper[2]]</div>"
|
||||
html += "[note_wrapper[2]]</div>"
|
||||
|
||||
return html
|
||||
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/var/global/spacevines_spawned = 0
|
||||
|
||||
/datum/event/spacevine
|
||||
announceWhen = 10
|
||||
announceWhen = 30
|
||||
ic_name = "a biohazard"
|
||||
|
||||
/datum/event/spacevine/start()
|
||||
|
||||
34
code/modules/events/supply_drop.dm
Normal file
34
code/modules/events/supply_drop.dm
Normal 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
|
||||
@@ -28,10 +28,6 @@
|
||||
updateVisibility(src)
|
||||
return ..()
|
||||
|
||||
/obj/structure/New()
|
||||
..()
|
||||
updateVisibility(src)
|
||||
|
||||
// EFFECTS
|
||||
|
||||
/obj/effect/Destroy()
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"])
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"])
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user