Merge branch 'master' into clockcultrework_v2
This commit is contained in:
@@ -41,6 +41,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
power_environ = FALSE
|
||||
valid_territory = FALSE
|
||||
outdoors = TRUE
|
||||
persistent_debris_allowed = FALSE
|
||||
ambientsounds = SPACE
|
||||
blob_allowed = FALSE //Eating up space doesn't count for victory as a blob.
|
||||
considered_hull_exterior = TRUE
|
||||
@@ -325,10 +326,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
name = "Service Hallway"
|
||||
icon_state = "hall_service"
|
||||
|
||||
/area/hallway/secondary/civilian
|
||||
name = "Civilian Wing"
|
||||
icon_state = "hallFS"
|
||||
|
||||
|
||||
//Command
|
||||
|
||||
@@ -469,6 +466,11 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "yellow"
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
|
||||
|
||||
/area/crew_quarters/arcade
|
||||
name = "Arcade"
|
||||
icon_state = "abandoned_g_den"
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
|
||||
|
||||
/area/crew_quarters/fitness
|
||||
name = "Fitness Room"
|
||||
icon_state = "fitness"
|
||||
@@ -479,6 +481,10 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "fitness"
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
|
||||
|
||||
/area/crew_quarters/fitness/pool
|
||||
name = "Pool Area"
|
||||
icon_state = "pool"
|
||||
|
||||
/area/crew_quarters/cafeteria
|
||||
name = "Cafeteria"
|
||||
icon_state = "cafeteria"
|
||||
@@ -765,6 +771,11 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "medbay3"
|
||||
ambientsounds = MEDICAL
|
||||
|
||||
/area/medical/clinic
|
||||
name = "Clinic"
|
||||
icon_state = "medbay3"
|
||||
ambientsounds = MEDICAL
|
||||
|
||||
/area/medical/abandoned
|
||||
name = "Abandoned Medbay"
|
||||
icon_state = "medbay3"
|
||||
@@ -1036,10 +1047,19 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "janitor"
|
||||
flags_1 = NONE
|
||||
|
||||
/area/janitor/aux
|
||||
name = "Auxiliary Custodial Closet"
|
||||
icon_state = "janitor"
|
||||
flags_1 = NONE
|
||||
|
||||
/area/hydroponics
|
||||
name = "Hydroponics"
|
||||
icon_state = "hydro"
|
||||
|
||||
/area/hydroponics/lobby
|
||||
name = "Hydroponics Lobby"
|
||||
icon_state = "hydro"
|
||||
|
||||
/area/hydroponics/garden
|
||||
name = "Garden"
|
||||
icon_state = "garden"
|
||||
@@ -1058,6 +1078,10 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
name = "Science Division"
|
||||
icon_state = "toxlab"
|
||||
|
||||
/area/science/observatory
|
||||
name = "Research Observatory"
|
||||
icon_state = "toxmisc"
|
||||
|
||||
/area/science/lab
|
||||
name = "Research and Development"
|
||||
icon_state = "toxlab"
|
||||
@@ -1100,6 +1124,10 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
name = "Research Division Server Room"
|
||||
icon_state = "server"
|
||||
|
||||
/area/science/server/compcore
|
||||
name = "Computer Core"
|
||||
icon_state = "server"
|
||||
|
||||
/area/science/explab
|
||||
name = "Experimentation Lab"
|
||||
icon_state = "toxmisc"
|
||||
@@ -1186,6 +1214,10 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "storage"
|
||||
clockwork_warp_allowed = FALSE
|
||||
|
||||
/area/storage/emergency
|
||||
name = "Emergency Storage"
|
||||
icon_state = "emergencystorage"
|
||||
|
||||
/area/storage/emergency/starboard
|
||||
name = "Starboard Emergency Storage"
|
||||
icon_state = "emergencystorage"
|
||||
@@ -1395,100 +1427,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
name = "Telecommunications Satellite Lounge"
|
||||
icon_state = "tcomsatlounge"
|
||||
|
||||
/area/crew_quarters/fitness/pool
|
||||
name = "Pool Area"
|
||||
icon_state = "pool"
|
||||
|
||||
/area/crew_quarters/dorms/blue
|
||||
name = "Blue Dorms"
|
||||
icon_state = "Sleep"
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_NONE
|
||||
|
||||
/area/crew_quarters/dorms/purple
|
||||
name = "Purple Dorms"
|
||||
icon_state = "Sleep"
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_NONE
|
||||
|
||||
/area/crew_quarters/lounge/jazz
|
||||
name = "Jazz Lounge"
|
||||
icon_state = "yellow"
|
||||
ambientsounds = list('sound/ambience/ambidet1.ogg','sound/ambience/ambidet2.ogg')
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
|
||||
|
||||
|
||||
/area/crew_quarters/fitness/recreation
|
||||
name = "Recreation Area"
|
||||
icon_state = "fitness"
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
|
||||
|
||||
/area/crew_quarters/fitness/cogpool
|
||||
name = "Pool"
|
||||
icon_state = "fitness"
|
||||
clockwork_warp_fail = "Pool's closed."
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
|
||||
|
||||
/area/crew_quarters/barbershop
|
||||
name = "Barbershop"
|
||||
icon_state = "blue"
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
|
||||
|
||||
/area/crew_quarters/observatory
|
||||
name = "Observatory"
|
||||
icon_state = "Sleep"
|
||||
|
||||
//Engineering
|
||||
|
||||
/area/engine/teg_hot
|
||||
name = "Hot Loop"
|
||||
icon_state = "red"
|
||||
|
||||
/area/engine/teg_cold
|
||||
name = "Cold Loop"
|
||||
icon_state = "blue"
|
||||
|
||||
/area/engine/workshop
|
||||
name = "Engineering Workshop"
|
||||
icon_state = "engine"
|
||||
|
||||
/area/security/courtroom/jury
|
||||
name = "Jury Room"
|
||||
icon_state = "courtroom"
|
||||
|
||||
/area/quartermaster/miningdock/airless
|
||||
name = "Mining Dock"
|
||||
icon_state = "mining"
|
||||
has_gravity = STANDARD_GRAVITY
|
||||
valid_territory = FALSE
|
||||
outdoors = TRUE
|
||||
ambientsounds = SPACE
|
||||
blob_allowed = FALSE //While part of the station, what good will it do you?
|
||||
|
||||
/area/quartermaster/miningdock/airless/no_grav
|
||||
name = "Mining Dock"
|
||||
icon_state = "mining"
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT
|
||||
power_light = FALSE
|
||||
power_equip = FALSE
|
||||
power_environ = FALSE
|
||||
valid_territory = FALSE
|
||||
outdoors = TRUE
|
||||
ambientsounds = SPACE
|
||||
blob_allowed = FALSE //While part of the station, what good will it do you?
|
||||
|
||||
/area/janitor/aux
|
||||
name = "Auxiliary Custodial Closet"
|
||||
icon_state = "janitor"
|
||||
flags_1 = NONE
|
||||
|
||||
/area/hydroponics/lobby
|
||||
name = "Hydroponics Lobby"
|
||||
icon_state = "hydro"
|
||||
|
||||
//Storage
|
||||
|
||||
/area/storage/emergency/generic
|
||||
name = "Emergency Storage"
|
||||
icon_state = "emergencystorage"
|
||||
|
||||
//Construction
|
||||
|
||||
@@ -1545,10 +1483,99 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
name = "Storage Wing"
|
||||
icon_state = "storage_wing"
|
||||
|
||||
//Routers
|
||||
//Areas that predominantly only apply to CogStation
|
||||
|
||||
/area/crew_quarters/dorms/blue
|
||||
name = "Blue Dorms"
|
||||
icon_state = "Sleep"
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_NONE
|
||||
|
||||
/area/crew_quarters/dorms/purple
|
||||
name = "Purple Dorms"
|
||||
icon_state = "Sleep"
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_NONE
|
||||
|
||||
/area/crew_quarters/lounge/jazz
|
||||
name = "Jazz Lounge"
|
||||
icon_state = "yellow"
|
||||
ambientsounds = list('sound/ambience/ambidet1.ogg','sound/ambience/ambidet2.ogg')
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
|
||||
|
||||
/area/crew_quarters/fitness/cogpool
|
||||
name = "Pool"
|
||||
icon_state = "fitness"
|
||||
clockwork_warp_fail = "Pool's closed."
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
|
||||
|
||||
/area/crew_quarters/barbershop
|
||||
name = "Barbershop"
|
||||
icon_state = "blue"
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
|
||||
|
||||
/area/crew_quarters/observatory
|
||||
name = "Observatory"
|
||||
icon_state = "Sleep"
|
||||
|
||||
/area/hallway/secondary/civilian
|
||||
name = "Civilian Wing"
|
||||
icon_state = "hallFS"
|
||||
|
||||
/area/engine/atmos/aftair
|
||||
name = "Aft Air Hookup"
|
||||
icon_state = "atmos"
|
||||
flags_1 = NONE
|
||||
|
||||
/area/engine/teg
|
||||
name = "Thermo-Electric Generator"
|
||||
icon_state = "engine"
|
||||
|
||||
/area/engine/teg/hotloop
|
||||
name = "Hot Loop"
|
||||
icon_state = "red"
|
||||
|
||||
/area/engine/teg/coldloop
|
||||
name = "Cold Loop"
|
||||
icon_state = "blue"
|
||||
|
||||
/area/engine/workshop
|
||||
name = "Engineering Workshop"
|
||||
icon_state = "engine"
|
||||
|
||||
/area/engine/substation
|
||||
name = "Electrical Substation"
|
||||
icon_state = "engine"
|
||||
|
||||
/area/security/courtroom/jury
|
||||
name = "Jury Room"
|
||||
icon_state = "courtroom"
|
||||
|
||||
/area/quartermaster/miningdock/airless
|
||||
name = "Mining Dock"
|
||||
icon_state = "mining"
|
||||
has_gravity = STANDARD_GRAVITY
|
||||
valid_territory = FALSE
|
||||
outdoors = TRUE
|
||||
ambientsounds = SPACE
|
||||
blob_allowed = FALSE //While part of the station, what good will it do you?
|
||||
|
||||
/area/quartermaster/miningdock/airless/no_grav
|
||||
name = "Mining Dock"
|
||||
icon_state = "mining"
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT
|
||||
power_light = FALSE
|
||||
power_equip = FALSE
|
||||
power_environ = FALSE
|
||||
valid_territory = FALSE
|
||||
outdoors = TRUE
|
||||
ambientsounds = SPACE
|
||||
blob_allowed = FALSE //While part of the station, what good will it do you?
|
||||
|
||||
|
||||
|
||||
//Routers (currently exclusive to CogStation)
|
||||
|
||||
/area/router
|
||||
name = "Router"
|
||||
name = "Routing Depot"
|
||||
icon_state = "yellow"
|
||||
ambientsounds = ENGINEERING
|
||||
|
||||
|
||||
@@ -28,4 +28,4 @@
|
||||
for(var/X in motioncameras)
|
||||
var/obj/machinery/camera/cam = X
|
||||
cam.lostTargetRef(WEAKREF(O))
|
||||
return
|
||||
return
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
var/clockwork_warp_allowed = TRUE
|
||||
/// Message to display when the clockwork warp fails
|
||||
var/clockwork_warp_fail = "The structure there is too dense for warping to pierce. (This is normal in high-security areas.)"
|
||||
/// Persistent debris alowed
|
||||
var/persistent_debris_allowed = TRUE
|
||||
/// Dirty flooring allowed
|
||||
var/dirt_buildup_allowed = TRUE
|
||||
|
||||
/// If mining tunnel generation is allowed in this area
|
||||
var/tunnel_allowed = FALSE
|
||||
|
||||
@@ -25,4 +25,4 @@ Unused icons for new areas are "awaycontent1" ~ "awaycontent30"
|
||||
|
||||
/area/awaymission/vr
|
||||
name = "Virtual Reality"
|
||||
icon_state = "awaycontent1"
|
||||
icon_state = "awaycontent1"
|
||||
|
||||
@@ -94,4 +94,4 @@
|
||||
|
||||
//ash walker nest
|
||||
/area/ruin/unpowered/ash_walkers
|
||||
icon_state = "red"
|
||||
icon_state = "red"
|
||||
|
||||
@@ -150,7 +150,6 @@
|
||||
|
||||
/area/shuttle/escape/luxury
|
||||
name = "Luxurious Emergency Shuttle"
|
||||
noteleport = TRUE
|
||||
|
||||
/area/shuttle/escape/arena
|
||||
name = "The Arena"
|
||||
|
||||
@@ -1143,21 +1143,3 @@
|
||||
*/
|
||||
/atom/proc/setClosed()
|
||||
return
|
||||
|
||||
///Passes Stat Browser Panel clicks to the game and calls client click on an atom
|
||||
/atom/Topic(href, list/href_list)
|
||||
. = ..()
|
||||
if(!usr?.client)
|
||||
return
|
||||
var/client/usr_client = usr.client
|
||||
var/list/paramslist = list()
|
||||
if(href_list["statpanel_item_shiftclick"])
|
||||
paramslist["shift"] = "1"
|
||||
if(href_list["statpanel_item_ctrlclick"])
|
||||
paramslist["ctrl"] = "1"
|
||||
if(href_list["statpanel_item_altclick"])
|
||||
paramslist["alt"] = "1"
|
||||
if(href_list["statpanel_item_click"])
|
||||
// first of all make sure we valid
|
||||
var/mouseparams = list2params(paramslist)
|
||||
usr_client.Click(src, loc, null, mouseparams)
|
||||
|
||||
@@ -150,14 +150,14 @@ Credit where due:
|
||||
var/datum/team/clockcult/main_clockcult
|
||||
|
||||
/datum/game_mode/clockwork_cult/pre_setup() //Gamemode and job code is pain. Have fun codediving all of that stuff, whoever works on this next - Delta
|
||||
var/list/errorList = list()
|
||||
/*var/list/errorList = list()
|
||||
var/list/reebes = SSmapping.LoadGroup(errorList, "Reebe", "map_files/generic", "City_of_Cogs.dmm", default_traits = ZTRAITS_REEBE, silent = TRUE)
|
||||
if(errorList.len) // reebe failed to load
|
||||
message_admins("Reebe failed to load!")
|
||||
log_game("Reebe failed to load!")
|
||||
return FALSE
|
||||
for(var/datum/parsed_map/PM in reebes)
|
||||
PM.initTemplateBounds()
|
||||
for(var/datum/parsed_map/PM in reebes) //Temporarily commented because of z-level loading reliably segfaulting the server.
|
||||
PM.initTemplateBounds()*/
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
|
||||
@@ -64,6 +64,8 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
var/threat_average_weight = 0
|
||||
/// Last time a threat average sample was taken. Used for weighting the rolling average.
|
||||
var/last_threat_sample_time = 0
|
||||
/// Maximum threat recorded so far, for cross-round chaos adjustment.
|
||||
var/max_threat = 0
|
||||
/// Things that cause a rolling threat adjustment to be displayed at roundend.
|
||||
var/list/threat_tallies = list()
|
||||
/// Running information about the threat. Can store text or datum entries.
|
||||
@@ -145,6 +147,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
third_rule_req = list(101, 101, 101, 101, 101, 100, 90, 80, 70, 60)
|
||||
high_pop_second_rule_req = CONFIG_GET(number/dynamic_second_rule_high_pop_requirement)
|
||||
high_pop_third_rule_req = CONFIG_GET(number/dynamic_third_rule_high_pop_requirement)
|
||||
added_threat = CONFIG_GET(number/dynamic_threat_baseline)
|
||||
GLOB.dynamic_high_pop_limit = CONFIG_GET(number/dynamic_high_pop_limit)
|
||||
GLOB.dynamic_latejoin_delay_min = CONFIG_GET(number/dynamic_latejoin_delay_min)*600
|
||||
GLOB.dynamic_latejoin_delay_max = CONFIG_GET(number/dynamic_latejoin_delay_max)*600
|
||||
@@ -415,7 +418,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
/datum/game_mode/dynamic/post_setup(report)
|
||||
update_playercounts()
|
||||
if(minor_ruleset_start)
|
||||
addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/minor_roundstart),rand(1 MINUTES,5 MINUTES))
|
||||
addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/minor_roundstart),rand(1 MINUTES,3 MINUTES))
|
||||
else
|
||||
for(var/datum/dynamic_ruleset/roundstart/rule in executed_rules)
|
||||
addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/execute_roundstart_rule, rule), rule.delay)
|
||||
@@ -439,7 +442,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
potential_minor_rulesets -= rule
|
||||
update_playercounts()
|
||||
iterations++
|
||||
message_admins("Minor antag roundstart rolls completed, with [num_rulesets_executed] antags or antag teams made.")
|
||||
message_admins("Minor antag roundstart rolls completed, with [iterations] rolls done and [num_rulesets_executed] antags or antag teams made.")
|
||||
log_game("DYNAMIC: Minor antag roundstart made [num_rulesets_executed] antags or antag teams.")
|
||||
|
||||
|
||||
@@ -612,6 +615,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
latejoin_rules = remove_from_list(latejoin_rules, rule.type)
|
||||
else if(rule.ruletype == "Midround")
|
||||
midround_rules = remove_from_list(midround_rules, rule.type)
|
||||
message_admins("DYNAMIC: Picked [rule]; executing soon...")
|
||||
addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/execute_midround_latejoin_rule, rule), rule.delay)
|
||||
return TRUE
|
||||
|
||||
@@ -663,6 +667,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
/datum/game_mode/dynamic/proc/execute_midround_latejoin_rule(sent_rule)
|
||||
var/datum/dynamic_ruleset/rule = sent_rule
|
||||
if (rule.execute())
|
||||
message_admins("DYNAMIC: Injected a [rule.ruletype == "latejoin" ? "latejoin" : "midround"] ruleset [rule.name].")
|
||||
log_game("DYNAMIC: Injected a [rule.ruletype == "latejoin" ? "latejoin" : "midround"] ruleset [rule.name].")
|
||||
log_threat("[rule.ruletype] [rule.name] added [rule.cost]", verbose = TRUE)
|
||||
if(rule.flags & HIGHLANDER_RULESET)
|
||||
@@ -741,6 +746,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
if(!M.voluntary_ghosted)
|
||||
current_players[CURRENT_DEAD_PLAYERS].Add(M) // Players who actually died (and admins who ghosted, would be nice to avoid counting them somehow)
|
||||
threat = storyteller.calculate_threat() + added_threat
|
||||
max_threat = max(max_threat,threat)
|
||||
if(threat_average_weight)
|
||||
var/cur_sample_weight = world.time - last_threat_sample_time
|
||||
threat_average = ((threat_average * threat_average_weight) + (threat * cur_sample_weight)) / (threat_average_weight + cur_sample_weight)
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
if (!M.client) // Are they connected?
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if(M.client.prefs && M.client.prefs.toggles & MIDROUND_ANTAG)
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if(!mode.check_age(M.client, minimum_required_age))
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
|
||||
@@ -1,3 +1,46 @@
|
||||
/datum/dynamic_ruleset/minor/proc/trim_list(list/L = list())
|
||||
var/list/trimmed_list = L.Copy()
|
||||
for(var/mob/M in trimmed_list)
|
||||
if (!ishuman(M))
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if (HAS_TRAIT(M, TRAIT_NO_MIDROUND_ANTAG))
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if (!M.client) // Are they connected?
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if(!mode.check_age(M.client, minimum_required_age))
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if(antag_flag_override)
|
||||
if(!(antag_flag_override in M.client.prefs.be_special) || jobban_isbanned(M.ckey, antag_flag_override))
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
else
|
||||
if(!(antag_flag in M.client.prefs.be_special) || jobban_isbanned(M.ckey, antag_flag))
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if (M.mind)
|
||||
if ((M.mind.assigned_role in GLOB.exp_specialmap[EXP_TYPE_SPECIAL])) // Are they playing a ghost role?
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if (M.mind.assigned_role in restricted_roles) // Does their job allow it?
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if ((exclusive_roles.len > 0) && !(M.mind.assigned_role in exclusive_roles)) // Is the rule exclusive to their job?
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
return trimmed_list
|
||||
|
||||
/datum/dynamic_ruleset/minor/trim_candidates()
|
||||
//
|
||||
// All you need to know is that here, the candidates list contains 4 lists itself, indexed with the following defines:
|
||||
// Candidates = list(CURRENT_LIVING_PLAYERS, CURRENT_LIVING_ANTAGS, CURRENT_DEAD_PLAYERS, CURRENT_OBSERVERS)
|
||||
// So for example you can get the list of all current dead players with var/list/dead_players = candidates[CURRENT_DEAD_PLAYERS]
|
||||
// Make sure to properly typecheck the mobs in those lists, as the dead_players list could contain ghosts, or dead players still in their bodies.
|
||||
// We're still gonna trim the obvious (mobs without clients, jobbanned players, etc)
|
||||
candidates = trim_list(mode.current_players[CURRENT_LIVING_PLAYERS])
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
/datum/dynamic_ruleset/roundstart/traitor
|
||||
name = "Traitors"
|
||||
config_tag = "traitor"
|
||||
persistent = TRUE
|
||||
antag_flag = ROLE_TRAITOR
|
||||
antag_datum = /datum/antagonist/traitor/
|
||||
minimum_required_age = 0
|
||||
@@ -34,15 +33,6 @@
|
||||
M.mind.restricted_roles = restricted_roles
|
||||
return TRUE
|
||||
|
||||
/datum/dynamic_ruleset/roundstart/traitor/rule_process()
|
||||
if (autotraitor_cooldown > 0)
|
||||
autotraitor_cooldown--
|
||||
else
|
||||
autotraitor_cooldown = 450 // 15 minutes
|
||||
message_admins("Checking if we can turn someone into a traitor.")
|
||||
log_game("DYNAMIC: Checking if we can turn someone into a traitor.")
|
||||
mode.picking_specific_rule(/datum/dynamic_ruleset/midround/autotraitor)
|
||||
|
||||
//////////////////////////////////////////
|
||||
// //
|
||||
// BLOOD BROTHERS //
|
||||
|
||||
@@ -15,10 +15,13 @@
|
||||
*/
|
||||
var/flags = 0
|
||||
var/dead_player_weight = 1 // How much dead players matter for threat calculation
|
||||
var/weight = 3 // Weights for randomly picking storyteller. Multiplied by score after voting.
|
||||
var/weight = 0 // Weights for randomly picking storyteller. Multiplied by score after voting.
|
||||
var/min_chaos = -1000 // Won't show up if recent rounds have been below this chaotic on average
|
||||
var/max_chaos = 1000 // Won't show up if recent rounds have been above this chaotic on average
|
||||
var/event_frequency_lower = 6 MINUTES // How rare events will be, at least.
|
||||
var/event_frequency_upper = 20 MINUTES // How rare events will be, at most.
|
||||
var/min_players = -1 // How many players are required for this one to start.
|
||||
var/soft_antag_ratio_cap = 4 // how many players-per-antag there should be
|
||||
var/datum/game_mode/dynamic/mode = null // Cached as soon as it's made, by dynamic.
|
||||
|
||||
/**
|
||||
@@ -101,8 +104,10 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
|
||||
/datum/dynamic_storyteller/proc/should_inject_antag(dry_run = FALSE)
|
||||
if(mode.forced_injection)
|
||||
mode.forced_injection = !dry_run
|
||||
mode.forced_injection = dry_run
|
||||
return TRUE
|
||||
if(mode.current_players[CURRENT_LIVING_PLAYERS].len < (mode.current_players[CURRENT_LIVING_ANTAGS].len * soft_antag_ratio_cap))
|
||||
return FALSE
|
||||
return mode.threat < mode.threat_level
|
||||
|
||||
/datum/dynamic_storyteller/proc/roundstart_draft()
|
||||
@@ -126,11 +131,10 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
|
||||
/datum/dynamic_storyteller/proc/minor_rule_draft()
|
||||
var/list/drafted_rules = list()
|
||||
for (var/datum/dynamic_ruleset/minor/rule in mode.minor_rules)
|
||||
for (var/datum/dynamic_ruleset/rule in mode.minor_rules)
|
||||
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
|
||||
rule.candidates = mode.candidates.Copy()
|
||||
rule.trim_candidates()
|
||||
if (rule.ready() && rule.candidates.len > 0)
|
||||
if (rule.ready())
|
||||
var/property_weight = 0
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights) // just treat it as 0 if it's not in there
|
||||
@@ -213,6 +217,8 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
weight = 1
|
||||
event_frequency_lower = 2 MINUTES
|
||||
event_frequency_upper = 10 MINUTES
|
||||
max_chaos = 50
|
||||
soft_antag_ratio_cap = 1
|
||||
flags = WAROPS_ALWAYS_ALLOWED | FORCE_IF_WON
|
||||
min_players = 30
|
||||
var/refund_cooldown = 0
|
||||
@@ -235,12 +241,13 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
desc = "Modes where the crew must band together. Nukies, xenos, blob. Only one antag threat at once."
|
||||
curve_centre = 2
|
||||
curve_width = 1.5
|
||||
weight = 2
|
||||
weight = 4
|
||||
max_chaos = 75
|
||||
min_players = 20
|
||||
flags = WAROPS_ALWAYS_ALLOWED | USE_PREV_ROUND_WEIGHTS
|
||||
property_weights = list("valid" = 3, "trust" = 5)
|
||||
|
||||
/datum/dynamic_storyteller/chaotic/minor_start_chance()
|
||||
/datum/dynamic_storyteller/team/minor_start_chance()
|
||||
return 0
|
||||
|
||||
/datum/dynamic_storyteller/team/should_inject_antag(dry_run = FALSE)
|
||||
@@ -256,13 +263,15 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
flags = WAROPS_ALWAYS_ALLOWED
|
||||
property_weights = list("valid" = 1, "conversion" = 20)
|
||||
|
||||
/datum/dynamic_storyteller/chaotic/minor_start_chance()
|
||||
/datum/dynamic_storyteller/conversion/minor_start_chance()
|
||||
return 0
|
||||
|
||||
/datum/dynamic_storyteller/random
|
||||
name = "Random"
|
||||
config_tag = "random"
|
||||
weight = 1
|
||||
max_chaos = 60
|
||||
soft_antag_ratio_cap = 1
|
||||
desc = "No weighting at all; every ruleset has the same chance of happening. Cooldowns vary wildly. As random as it gets."
|
||||
|
||||
/datum/dynamic_storyteller/random/on_start()
|
||||
@@ -275,7 +284,7 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
/datum/dynamic_storyteller/random/should_inject_antag()
|
||||
return prob(50)
|
||||
|
||||
/datum/dynamic_storyteller/chaotic/minor_start_chance()
|
||||
/datum/dynamic_storyteller/random/minor_start_chance()
|
||||
return 20
|
||||
|
||||
/datum/dynamic_storyteller/random/roundstart_draft()
|
||||
@@ -331,7 +340,7 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
name = "Story"
|
||||
config_tag = "story"
|
||||
desc = "Antags with options for loadouts and gimmicks. Traitor, wizard, nukies."
|
||||
weight = 2
|
||||
weight = 4
|
||||
curve_width = 2
|
||||
flags = USE_PREV_ROUND_WEIGHTS
|
||||
property_weights = list("story_potential" = 2)
|
||||
@@ -339,6 +348,7 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
/datum/dynamic_storyteller/classic
|
||||
name = "Classic"
|
||||
config_tag = "classic"
|
||||
weight = 8
|
||||
desc = "No special antagonist weights. Good variety, but not like random. Uses your chaos preference to weight."
|
||||
flags = USE_PREF_WEIGHTS | USE_PREV_ROUND_WEIGHTS
|
||||
|
||||
@@ -346,7 +356,7 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
name = "Intrigue"
|
||||
config_tag = "intrigue"
|
||||
desc = "Antags that instill distrust in the crew. Traitors, bloodsuckers."
|
||||
weight = 2
|
||||
weight = 4
|
||||
curve_width = 2
|
||||
dead_player_weight = 2
|
||||
flags = USE_PREV_ROUND_WEIGHTS
|
||||
@@ -358,8 +368,8 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
/datum/dynamic_storyteller/grabbag
|
||||
name = "Grab Bag"
|
||||
config_tag = "grabbag"
|
||||
desc = "Crew antags (e.g. traitor, changeling, bloodsucker, heretic) only, all mixed together."
|
||||
weight = 2
|
||||
desc = "Crew antags (e.g. traitor, changeling, bloodsucker, heretic) only at round start, all mixed together."
|
||||
weight = 4
|
||||
flags = USE_PREF_WEIGHTS | USE_PREV_ROUND_WEIGHTS
|
||||
|
||||
/datum/dynamic_storyteller/grabbag/minor_start_chance()
|
||||
@@ -372,12 +382,14 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
curve_centre = -3
|
||||
curve_width = 0.5
|
||||
flags = NO_ASSASSIN
|
||||
weight = 1
|
||||
min_chaos = 30
|
||||
weight = 3
|
||||
dead_player_weight = 5
|
||||
soft_antag_ratio_cap = 8
|
||||
property_weights = list("extended" = 2, "chaos" = -1, "valid" = -1, "conversion" = -10)
|
||||
|
||||
/datum/dynamic_storyteller/liteextended/minor_start_chance()
|
||||
return 100
|
||||
return 90
|
||||
|
||||
/datum/dynamic_storyteller/no_antag
|
||||
name = "Extended"
|
||||
@@ -385,6 +397,7 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
desc = "No standard antags."
|
||||
curve_centre = -5
|
||||
curve_width = 0.5
|
||||
min_chaos = 40
|
||||
flags = NO_ASSASSIN | FORCE_IF_WON
|
||||
weight = 1
|
||||
property_weights = list("extended" = 2)
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
break
|
||||
var/datum/mind/cultie = antag_pick(antag_candidates)
|
||||
antag_candidates -= cultie
|
||||
cultie.special_role = ROLE_HERETIC
|
||||
cultie.restricted_roles = restricted_jobs
|
||||
culties += cultie
|
||||
|
||||
|
||||
@@ -10,4 +10,4 @@
|
||||
else if(D.gang && D.gang.domination_time != NOT_DOMINATING)
|
||||
return D.gang.domination_time_remaining()
|
||||
else
|
||||
return "OFFLINE"
|
||||
return "OFFLINE"
|
||||
|
||||
@@ -35,4 +35,4 @@
|
||||
return ..()
|
||||
|
||||
/obj/effect/decal/cleanable/crayon/NeverShouldHaveComeHere(turf/T)
|
||||
return isspaceturf(T) || islava(T) || istype(T, /turf/open/water) || ischasm(T)
|
||||
return isspaceturf(T) || islava(T) || istype(T, /turf/open/water) || ischasm(T)
|
||||
|
||||
@@ -31,4 +31,4 @@
|
||||
var/image/holder = M.hud_list[ANTAG_HUD]
|
||||
if(holder)
|
||||
holder.color = null
|
||||
..()
|
||||
..()
|
||||
|
||||
@@ -56,4 +56,4 @@
|
||||
H.silent = max(H.silent, 5)
|
||||
H.DefaultCombatKnockdown(100)
|
||||
gangster_mind.add_antag_datum(/datum/antagonist/gang, gang)
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
@@ -256,4 +256,4 @@
|
||||
outfits = TRUE
|
||||
|
||||
/obj/item/device/gangtool/spare/lt
|
||||
promotable = TRUE
|
||||
promotable = TRUE
|
||||
|
||||
@@ -58,4 +58,4 @@
|
||||
qdel(src)
|
||||
return
|
||||
imp = new /obj/item/implant/gang(src,gang)
|
||||
.=..()
|
||||
.=..()
|
||||
|
||||
@@ -46,17 +46,17 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
var/startx
|
||||
switch(startSide)
|
||||
if(NORTH)
|
||||
starty = world.maxy-(TRANSITIONEDGE+1)
|
||||
startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
|
||||
starty = world.maxy-(TRANSITIONEDGE+2)
|
||||
startx = rand((TRANSITIONEDGE+2), world.maxx-(TRANSITIONEDGE+2))
|
||||
if(EAST)
|
||||
starty = rand((TRANSITIONEDGE+1),world.maxy-(TRANSITIONEDGE+1))
|
||||
startx = world.maxx-(TRANSITIONEDGE+1)
|
||||
starty = rand((TRANSITIONEDGE+2),world.maxy-(TRANSITIONEDGE+2))
|
||||
startx = world.maxx-(TRANSITIONEDGE+2)
|
||||
if(SOUTH)
|
||||
starty = (TRANSITIONEDGE+1)
|
||||
startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
|
||||
starty = (TRANSITIONEDGE+2)
|
||||
startx = rand((TRANSITIONEDGE+2), world.maxx-(TRANSITIONEDGE+2))
|
||||
if(WEST)
|
||||
starty = rand((TRANSITIONEDGE+1), world.maxy-(TRANSITIONEDGE+1))
|
||||
startx = (TRANSITIONEDGE+1)
|
||||
starty = rand((TRANSITIONEDGE+2), world.maxy-(TRANSITIONEDGE+2))
|
||||
startx = (TRANSITIONEDGE+2)
|
||||
. = locate(startx, starty, Z)
|
||||
|
||||
/proc/spaceDebrisFinishLoc(startSide, Z)
|
||||
|
||||
@@ -145,8 +145,8 @@
|
||||
|
||||
/obj/machinery/sleeper/ui_state(mob/user)
|
||||
if(controls_inside)
|
||||
return GLOB.contained_state
|
||||
return GLOB.default_state
|
||||
return GLOB.default_state
|
||||
return GLOB.notcontained_state
|
||||
|
||||
/obj/machinery/sleeper/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
@@ -209,6 +209,7 @@
|
||||
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
|
||||
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
|
||||
data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN)
|
||||
data["occupant"]["is_robotic_organism"] = HAS_TRAIT(mob_occupant, TRAIT_ROBOTIC_ORGANISM)
|
||||
data["occupant"]["reagents"] = list()
|
||||
if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len)
|
||||
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
|
||||
|
||||
@@ -75,3 +75,38 @@
|
||||
if (!area_motion)
|
||||
if(isliving(AM))
|
||||
newTarget(AM)
|
||||
|
||||
/obj/machinery/camera/motion/thunderdome
|
||||
name = "entertainment camera"
|
||||
network = list("thunder")
|
||||
c_tag = "Arena"
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF | FREEZE_PROOF
|
||||
|
||||
/obj/machinery/camera/motion/thunderdome/Initialize()
|
||||
. = ..()
|
||||
proximity_monitor.SetRange(7)
|
||||
|
||||
/obj/machinery/camera/motion/thunderdome/HasProximity(atom/movable/AM as mob|obj)
|
||||
if (!isliving(AM) || get_area(AM) != get_area(src))
|
||||
return
|
||||
localMotionTargets |= WEAKREF(AM)
|
||||
if (!detectTime)
|
||||
for(var/obj/machinery/computer/security/telescreen/entertainment/TV in GLOB.machines)
|
||||
TV.notify(TRUE)
|
||||
detectTime = world.time + 30 SECONDS
|
||||
|
||||
/obj/machinery/camera/motion/thunderdome/process()
|
||||
if (!detectTime)
|
||||
return
|
||||
|
||||
for (var/datum/weakref/targetref in localMotionTargets)
|
||||
var/mob/target = targetref.resolve()
|
||||
if(QDELETED(target) || target.stat == DEAD || get_dist(src, target) > 7 || get_area(src) != get_area(target))
|
||||
localMotionTargets -= targetref
|
||||
|
||||
if (localMotionTargets.len)
|
||||
detectTime = world.time + 30 SECONDS
|
||||
else if (world.time > detectTime)
|
||||
detectTime = 0
|
||||
for(var/obj/machinery/computer/security/telescreen/entertainment/TV in GLOB.machines)
|
||||
TV.notify(FALSE)
|
||||
@@ -0,0 +1,223 @@
|
||||
/obj/machinery/gear_painter
|
||||
name = "\improper Color Mate"
|
||||
desc = "A machine to give your apparel a fresh new color! Recommended to use with white items for best results."
|
||||
icon = 'icons/obj/vending.dmi'
|
||||
icon_state = "colormate"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/colormate
|
||||
var/obj/item/inserted
|
||||
var/activecolor = "#FFFFFF"
|
||||
var/list/color_matrix_last
|
||||
var/matrix_mode = FALSE
|
||||
/// Minimum lightness for normal mode
|
||||
var/minimum_normal_lightness = 50
|
||||
/// Minimum lightness for matrix mode, tested using 4 test colors of full red, green, blue, white.
|
||||
var/minimum_matrix_lightness = 75
|
||||
/// Minimum matrix tests that must pass for something to be considered a valid color (see above)
|
||||
var/minimum_matrix_tests = 2
|
||||
var/list/allowed_types = list(
|
||||
/obj/item/clothing,
|
||||
/obj/item/storage/backpack,
|
||||
/obj/item/storage/belt
|
||||
)
|
||||
|
||||
/obj/machinery/gear_painter/Initialize(mapload)
|
||||
. = ..()
|
||||
color_matrix_last = list(
|
||||
1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1,
|
||||
0, 0, 0
|
||||
)
|
||||
|
||||
/obj/machinery/gear_painter/update_icon_state()
|
||||
if(panel_open)
|
||||
icon_state = "colormate_open"
|
||||
else if(!is_operational())
|
||||
icon_state = "colormate_off"
|
||||
else if(inserted)
|
||||
icon_state = "colormate_active"
|
||||
else
|
||||
icon_state = "colormate"
|
||||
|
||||
/obj/machinery/gear_painter/Destroy()
|
||||
inserted.forceMove(drop_location())
|
||||
return ..()
|
||||
|
||||
/obj/machinery/gear_painter/attackby(obj/item/I, mob/living/user)
|
||||
if(inserted)
|
||||
to_chat(user, "<span class='warning'>The machine is already loaded.</span>")
|
||||
return
|
||||
if(default_deconstruction_screwdriver(user, "colormate_open", "colormate", I))
|
||||
return
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
if(default_unfasten_wrench(user, I, 40))
|
||||
return
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return ..()
|
||||
|
||||
if(is_type_in_list(I, allowed_types) && is_operational())
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
to_chat(user, "<span class='warning'>[I] is stuck to your hand!</span>")
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] inserts [I] into [src]'s receptable.</span>")
|
||||
|
||||
inserted = I
|
||||
update_icon()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/gear_painter/AllowDrop()
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/gear_painter/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.CanReach(src))
|
||||
return
|
||||
if(!inserted)
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You remove [inserted] from [src]")
|
||||
inserted.forceMove(drop_location())
|
||||
inserted = null
|
||||
update_icon()
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/gear_painter/ui_interact(mob/user)
|
||||
if(!is_operational())
|
||||
return
|
||||
user.set_machine(src)
|
||||
var/list/dat = list("<TITLE>Color Mate Control Panel</TITLE><BR>")
|
||||
if(!inserted)
|
||||
dat += "No item inserted."
|
||||
else
|
||||
dat += "Item inserted: [inserted]<HR>"
|
||||
dat += "<a href='?src=[REF(src)];toggle_matrix_mode=1'>Matrix mode: [matrix_mode? "On" : "Off"]</a>"
|
||||
if(!matrix_mode)
|
||||
dat += "<A href='?src=\ref[src];select=1'>Select new color.</A><BR>"
|
||||
dat += "Color: <font color='[activecolor]'>⚫</font>"
|
||||
dat += "<A href='?src=\ref[src];paint=1'>Apply new color.</A><BR><BR>"
|
||||
else
|
||||
// POGGERS
|
||||
#define MATRIX_FIELD(field, default) "<b><label for='[##field]'>[##field]</label></b> <input type='number' step='0.001' name='[field]' value='[default]'>"
|
||||
dat += "<br><form name='matrix paint' action='?src=[REF(src)]'>"
|
||||
dat += "<input type='hidden' name='src' value='[REF(src)]'>"
|
||||
dat += "<input type='hidden' name='matrix_paint' value='1'"
|
||||
dat += "<br><br>"
|
||||
dat += MATRIX_FIELD("rr", color_matrix_last[1])
|
||||
dat += MATRIX_FIELD("gr", color_matrix_last[4])
|
||||
dat += MATRIX_FIELD("br", color_matrix_last[7])
|
||||
dat += "<br><br>"
|
||||
dat += MATRIX_FIELD("rg", color_matrix_last[2])
|
||||
dat += MATRIX_FIELD("gg", color_matrix_last[5])
|
||||
dat += MATRIX_FIELD("bg", color_matrix_last[8])
|
||||
dat += "<br><br>"
|
||||
dat += MATRIX_FIELD("rb", color_matrix_last[3])
|
||||
dat += MATRIX_FIELD("gb", color_matrix_last[6])
|
||||
dat += MATRIX_FIELD("bb", color_matrix_last[9])
|
||||
dat += "<br><br>"
|
||||
dat += MATRIX_FIELD("cr", color_matrix_last[10])
|
||||
dat += MATRIX_FIELD("cg", color_matrix_last[11])
|
||||
dat += MATRIX_FIELD("cb", color_matrix_last[12])
|
||||
dat += "<br><br>"
|
||||
dat += "<input type='submit' value='Matrix Paint'>"
|
||||
dat += "</form><br>"
|
||||
#undef MATRIX_FIELD
|
||||
dat += "<A href='?src=\ref[src];clear=1'>Remove paintjob.</A><BR><BR>"
|
||||
dat += "<A href='?src=\ref[src];eject=1'>Eject item.</A><BR><BR>"
|
||||
|
||||
var/datum/browser/menu = new(user, "colormate","Color Mate Control Panel", 800, 600, src)
|
||||
menu.set_content(dat.Join(""))
|
||||
menu.open()
|
||||
|
||||
/obj/machinery/gear_painter/Topic(href, href_list)
|
||||
if((. = ..()))
|
||||
return
|
||||
|
||||
add_fingerprint(usr)
|
||||
|
||||
if(href_list["close"])
|
||||
usr << browse(null, "window=colormate")
|
||||
return
|
||||
|
||||
if(href_list["select"])
|
||||
var/newcolor = input(usr, "Choose a color.", "", activecolor) as color|null
|
||||
if(newcolor)
|
||||
activecolor = newcolor
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["paint"])
|
||||
if(!inserted)
|
||||
return
|
||||
if(!check_valid_color(activecolor, usr))
|
||||
return
|
||||
inserted.add_atom_colour(activecolor, FIXED_COLOUR_PRIORITY)
|
||||
playsound(src, 'sound/effects/spray3.ogg', 50, 1)
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["toggle_matrix_mode"])
|
||||
matrix_mode = !matrix_mode
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["matrix_paint"])
|
||||
if(!inserted)
|
||||
return
|
||||
// assemble matrix
|
||||
var/list/cm = rgb_construct_color_matrix(
|
||||
text2num(href_list["rr"]),
|
||||
text2num(href_list["rg"]),
|
||||
text2num(href_list["rb"]),
|
||||
text2num(href_list["gr"]),
|
||||
text2num(href_list["gg"]),
|
||||
text2num(href_list["gb"]),
|
||||
text2num(href_list["br"]),
|
||||
text2num(href_list["bg"]),
|
||||
text2num(href_list["bb"]),
|
||||
text2num(href_list["cr"]),
|
||||
text2num(href_list["cg"]),
|
||||
text2num(href_list["cb"])
|
||||
)
|
||||
color_matrix_last = cm.Copy()
|
||||
if(!check_valid_color(cm, usr))
|
||||
return
|
||||
inserted.add_atom_colour(cm, FIXED_COLOUR_PRIORITY)
|
||||
playsound(src, 'sound/effects/spray3.ogg', 50, 1)
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["clear"])
|
||||
if(!inserted)
|
||||
return
|
||||
inserted.remove_atom_colour(FIXED_COLOUR_PRIORITY)
|
||||
playsound(src, 'sound/effects/spray3.ogg', 50, 1)
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["eject"])
|
||||
if(!inserted)
|
||||
return
|
||||
inserted.forceMove(drop_location())
|
||||
inserted = null
|
||||
update_icon()
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/gear_painter/proc/check_valid_color(list/cm, mob/user)
|
||||
if(!islist(cm)) // normal
|
||||
var/list/HSV = ReadHSV(RGBtoHSV(cm))
|
||||
if(HSV[3] < minimum_normal_lightness)
|
||||
to_chat(user, "<span class='warning'>[cm] is far too dark (min lightness [minimum_normal_lightness]!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
else // matrix
|
||||
// We test using full red, green, blue, and white
|
||||
// A predefined number of them must pass to be considered valid
|
||||
var/passed = 0
|
||||
#define COLORTEST(thestring, thematrix) passed += (ReadHSV(RGBtoHSV(RGBMatrixTransform(thestring, thematrix)))[3] >= minimum_matrix_lightness)
|
||||
COLORTEST("FF0000", cm)
|
||||
COLORTEST("00FF00", cm)
|
||||
COLORTEST("0000FF", cm)
|
||||
COLORTEST("FFFFFF", cm)
|
||||
#undef COLORTEST
|
||||
if(passed < minimum_matrix_tests)
|
||||
to_chat(user, "<span class='warning'>[english_list(color)] is not allowed (pased [passed] out of 4, minimum [minimum_matrix_tests], minimum lightness [minimum_matrix_lightness]).</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
@@ -88,6 +88,7 @@
|
||||
data["patient"]["fireLoss"] = patient.getFireLoss()
|
||||
data["patient"]["toxLoss"] = patient.getToxLoss()
|
||||
data["patient"]["oxyLoss"] = patient.getOxyLoss()
|
||||
data["patient"]["is_robotic_organism"] = HAS_TRAIT(patient, TRAIT_ROBOTIC_ORGANISM)
|
||||
if(patient.surgeries.len)
|
||||
data["procedures"] = list()
|
||||
for(var/datum/surgery/procedure in patient.surgeries)
|
||||
|
||||
@@ -212,4 +212,4 @@
|
||||
name = "Outbomb Cuban Pete"
|
||||
|
||||
updateUsrDialog()
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
name = "gas sensor"
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "gsensor1"
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 0)
|
||||
|
||||
var/on = TRUE
|
||||
|
||||
|
||||
@@ -246,10 +246,12 @@
|
||||
network = list("thunder")
|
||||
density = FALSE
|
||||
circuit = null
|
||||
interaction_flags_atom = NONE // interact() is called by BigClick()
|
||||
//interaction_flags_atom = NONE // interact() is called by BigClick()
|
||||
var/icon_state_off = "entertainment_blank"
|
||||
var/icon_state_on = "entertainment"
|
||||
|
||||
/* If someone would like to try to get this long-distance viewing thing working, be my guest. I tried everything I could possibly think of and it just refused to operate correctly.
|
||||
|
||||
/obj/machinery/computer/security/telescreen/entertainment/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_CLICK, .proc/BigClick)
|
||||
@@ -258,6 +260,8 @@
|
||||
/obj/machinery/computer/security/telescreen/entertainment/proc/BigClick()
|
||||
interact(usr)
|
||||
|
||||
*/
|
||||
|
||||
/obj/machinery/computer/security/telescreen/entertainment/proc/notify(on)
|
||||
if(on && icon_state == icon_state_off)
|
||||
say(pick(
|
||||
@@ -278,7 +282,7 @@
|
||||
name = "circuitry telescreen"
|
||||
desc = "Used for watching the other eggheads from the safety of the circuitry lab."
|
||||
network = list("rd")
|
||||
|
||||
|
||||
/obj/machinery/computer/security/telescreen/ce
|
||||
name = "\improper Chief Engineer's telescreen"
|
||||
desc = "Used for watching the engine, telecommunications and the minisat."
|
||||
|
||||
@@ -69,4 +69,4 @@
|
||||
return 0
|
||||
if(B.scrambledcodes || B.emagged)
|
||||
return 0
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
+110
-125
@@ -22,17 +22,16 @@
|
||||
|
||||
//Used for logging people entering cryosleep and important items they are carrying.
|
||||
var/list/frozen_crew = list()
|
||||
var/list/frozen_items = list()
|
||||
|
||||
// Used for containing rare items traitors need to steal, so it's not
|
||||
// game-over if they get iced
|
||||
var/list/objective_items = list()
|
||||
// A cache of theft datums so you don't have to re-create them for
|
||||
// each item check
|
||||
var/list/theft_cache = list()
|
||||
var/list/obj/stored_packages = list()
|
||||
|
||||
var/allow_items = TRUE
|
||||
|
||||
/obj/machinery/computer/cryopod/deconstruct()
|
||||
. = ..()
|
||||
for(var/i in stored_packages)
|
||||
var/obj/O = i
|
||||
O.forceMove(drop_location())
|
||||
|
||||
/obj/machinery/computer/cryopod/attack_ai()
|
||||
attack_hand()
|
||||
|
||||
@@ -67,11 +66,11 @@
|
||||
if(3)
|
||||
dat += "<a href='byond://?src=[REF(src)];menu=1'><< Back</a><br><br>"
|
||||
dat += "<h3>Recently stored objects</h3><br/><hr/><br/>"
|
||||
if(!frozen_items.len)
|
||||
if(!stored_packages.len)
|
||||
dat += "There has been no storage usage at this terminal.<br/>"
|
||||
else
|
||||
for(var/obj/item/I in frozen_items)
|
||||
dat += "[I.name]<br/>"
|
||||
for(var/obj/O in stored_packages)
|
||||
dat += "[O.name]<br/>"
|
||||
dat += "<hr/>"
|
||||
|
||||
var/datum/browser/popup = new(user, "cryopod_console", "Cryogenic System Control")
|
||||
@@ -87,25 +86,27 @@
|
||||
add_fingerprint(user)
|
||||
|
||||
if(href_list["item"])
|
||||
if(!allowed(user))
|
||||
if(!allowed(user) && !(obj_flags & EMAGGED))
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(!allow_items) return
|
||||
|
||||
if(frozen_items.len == 0)
|
||||
if(!allow_items)
|
||||
return
|
||||
|
||||
if(stored_packages.len == 0)
|
||||
to_chat(user, "<span class='notice'>There is nothing to recover from storage.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
var/obj/item/I = input(user, "Please choose which object to retrieve.","Object recovery",null) as null|anything in frozen_items
|
||||
var/obj/I = input(user, "Please choose which object to retrieve.","Object recovery",null) as null|anything in stored_packages
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
if(!I)
|
||||
return
|
||||
|
||||
if(!(I in frozen_items))
|
||||
if(!(I in stored_packages))
|
||||
to_chat(user, "<span class='notice'>\The [I] is no longer in storage.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
@@ -117,20 +118,21 @@
|
||||
I.forceMove(drop_location())
|
||||
if(user && Adjacent(user) && user.can_hold_items())
|
||||
user.put_in_hands(I)
|
||||
frozen_items -= I
|
||||
stored_packages -= I
|
||||
updateUsrDialog()
|
||||
|
||||
else if(href_list["allitems"])
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
if(!allowed(user))
|
||||
if(!allowed(user) && !(obj_flags & EMAGGED))
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
if(!allow_items)
|
||||
return
|
||||
|
||||
if(frozen_items.len == 0)
|
||||
if(stored_packages.len == 0)
|
||||
to_chat(user, "<span class='notice'>There is nothing to recover from storage.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
@@ -138,10 +140,10 @@
|
||||
visible_message("<span class='notice'>The console beeps happily as it disgorges the desired objects.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
for(var/obj/item/I in frozen_items)
|
||||
I.forceMove(drop_location())
|
||||
frozen_items -= I
|
||||
updateUsrDialog()
|
||||
for(var/obj/O in stored_packages)
|
||||
O.forceMove(get_turf(src))
|
||||
stored_packages.Cut()
|
||||
updateUsrDialog()
|
||||
|
||||
else if (href_list["menu"])
|
||||
src.menu = text2num(href_list["menu"])
|
||||
@@ -159,6 +161,13 @@
|
||||
/obj/machinery/computer/cryopod/contents_explosion()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/cryopod/contents_explosion()
|
||||
return //don't blow everyone's shit up.
|
||||
|
||||
/// The box
|
||||
/obj/item/storage/box/blue/cryostorage_items
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
|
||||
//Cryopods themselves.
|
||||
/obj/machinery/cryopod
|
||||
name = "cryogenic freezer"
|
||||
@@ -177,44 +186,9 @@
|
||||
var/despawn_world_time = null // Used to keep track of the safe period.
|
||||
|
||||
var/obj/machinery/computer/cryopod/control_computer
|
||||
var/item_storage_type = /obj/item/storage/box/blue/cryostorage_items //with how storage components work this can be anything the player can open or anything with a storage component.
|
||||
var/last_no_computer_message = 0
|
||||
|
||||
// These items are preserved when the process() despawn proc occurs.
|
||||
var/static/list/preserve_items = typecacheof(list(
|
||||
/obj/item/hand_tele,
|
||||
/obj/item/card/id/captains_spare,
|
||||
/obj/item/aicard,
|
||||
/obj/item/mmi,
|
||||
/obj/item/paicard,
|
||||
/obj/item/gun,
|
||||
/obj/item/pinpointer,
|
||||
/obj/item/clothing/shoes/magboots,
|
||||
/obj/item/areaeditor/blueprints,
|
||||
/obj/item/clothing/head/helmet/space,
|
||||
/obj/item/clothing/suit/space,
|
||||
/obj/item/clothing/suit/armor,
|
||||
/obj/item/defibrillator/compact,
|
||||
/obj/item/reagent_containers/hypospray/CMO,
|
||||
/obj/item/clothing/accessory/medal/gold/captain,
|
||||
/obj/item/clothing/gloves/krav_maga,
|
||||
/obj/item/nullrod,
|
||||
/obj/item/tank/jetpack,
|
||||
/obj/item/documents,
|
||||
/obj/item/nuke_core_container
|
||||
))
|
||||
// These items will NOT be preserved
|
||||
var/static/list/do_not_preserve_items = typecacheof(list(
|
||||
/obj/item/mmi/posibrain,
|
||||
/obj/item/gun/energy/laser/mounted,
|
||||
/obj/item/gun/energy/e_gun/advtaser/mounted,
|
||||
/obj/item/gun/ballistic/revolver/grenadelauncher/cyborg,
|
||||
/obj/item/gun/energy/disabler/cyborg,
|
||||
/obj/item/gun/energy/e_gun/advtaser/cyborg,
|
||||
/obj/item/gun/energy/printer,
|
||||
/obj/item/gun/energy/kinetic_accelerator/cyborg,
|
||||
/obj/item/gun/energy/laser/cyborg
|
||||
))
|
||||
|
||||
/obj/machinery/cryopod/Initialize(mapload)
|
||||
. = ..()
|
||||
update_icon()
|
||||
@@ -286,73 +260,89 @@
|
||||
|
||||
despawn_occupant()
|
||||
|
||||
#define CRYO_DESTROY 0
|
||||
#define CRYO_PRESERVE 1
|
||||
#define CRYO_OBJECTIVE 2
|
||||
#define CRYO_IGNORE 3
|
||||
#define CRYO_DESTROY_LATER 4
|
||||
|
||||
/obj/machinery/cryopod/proc/should_preserve_item(obj/item/I)
|
||||
for(var/datum/objective_item/steal/T in control_computer.theft_cache)
|
||||
if(istype(I, T.targetitem) && T.check_special_completion(I))
|
||||
return CRYO_OBJECTIVE
|
||||
if(preserve_items[I] && !do_not_preserve_items[I])
|
||||
return CRYO_PRESERVE
|
||||
return CRYO_DESTROY
|
||||
|
||||
// This function can not be undone; do not call this unless you are sure
|
||||
/obj/machinery/cryopod/proc/despawn_occupant()
|
||||
if(!control_computer)
|
||||
find_control_computer()
|
||||
|
||||
var/mob/living/mob_occupant = occupant
|
||||
var/list/obj/item/cryo_items = list()
|
||||
|
||||
var/list/obj/item/storing = list()
|
||||
var/list/obj/item/destroying = list()
|
||||
var/list/obj/item/destroy_later = list()
|
||||
|
||||
investigate_log("Despawning [key_name(mob_occupant)].", INVESTIGATE_CRYOGENICS)
|
||||
|
||||
//Handle Borg stuff first
|
||||
var/atom/target_store = (control_computer?.allow_items && control_computer) || src //the double control computer check makes it return the control computer.
|
||||
var/drop_to_ground = !istype(target_store, /obj/machinery/computer/cryopod)
|
||||
|
||||
var/mind_identity = mob_occupant.mind?.name
|
||||
var/occupant_identity = mob_occupant.real_name
|
||||
|
||||
if(iscyborg(mob_occupant))
|
||||
var/mob/living/silicon/robot/R = mob_occupant
|
||||
if(R.mmi?.brain)
|
||||
cryo_items[R.mmi] = CRYO_DESTROY_LATER
|
||||
cryo_items[R.mmi.brain] = CRYO_DESTROY_LATER
|
||||
for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc
|
||||
for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags
|
||||
cryo_items[O] = should_preserve_item(O)
|
||||
O.forceMove(src)
|
||||
R.module.remove_module(I, TRUE) //delete the module itself so it doesn't transfer over.
|
||||
|
||||
//Drop all items into the pod.
|
||||
for(var/obj/item/I in mob_occupant)
|
||||
if(cryo_items[I] == CRYO_IGNORE || cryo_items[I] ==CRYO_DESTROY_LATER)
|
||||
continue
|
||||
cryo_items[I] = should_preserve_item(I)
|
||||
mob_occupant.transferItemToLoc(I, src, TRUE)
|
||||
if(I.contents.len) //Make sure we catch anything not handled by qdel() on the items.
|
||||
if(cryo_items[I] != CRYO_DESTROY) // Don't remove the contents of things that need preservation
|
||||
destroy_later += R.mmi
|
||||
destroy_later += R.mmi.brain
|
||||
for(var/i in R.module)
|
||||
if(!isitem(i))
|
||||
destroying += i
|
||||
continue
|
||||
for(var/obj/item/O in I.contents)
|
||||
cryo_items[O] = should_preserve_item(O)
|
||||
O.forceMove(src)
|
||||
|
||||
for(var/A in cryo_items)
|
||||
var/obj/item/I = A
|
||||
if(QDELETED(I)) //edge cases and DROPDEL.
|
||||
continue
|
||||
var/preserve = cryo_items[I]
|
||||
if(preserve == CRYO_DESTROY_LATER)
|
||||
continue
|
||||
if(preserve != CRYO_IGNORE)
|
||||
if(preserve == CRYO_DESTROY)
|
||||
qdel(I)
|
||||
else if(control_computer?.allow_items)
|
||||
control_computer.frozen_items += I
|
||||
if(preserve == CRYO_OBJECTIVE)
|
||||
control_computer.objective_items += I
|
||||
I.moveToNullspace()
|
||||
var/obj/item/I = i
|
||||
// let's be honest we only care about the trash bag don't beat around the bush
|
||||
if(SEND_SIGNAL(I, COMSIG_CONTAINS_STORAGE))
|
||||
storing += I.contents
|
||||
for(var/atom/movable/AM in I.contents)
|
||||
AM.forceMove(src)
|
||||
R.module.remove_module(I, TRUE)
|
||||
else
|
||||
var/list/gear = list()
|
||||
if(iscarbon(mob_occupant)) // sorry simp-le-mobs deserve no mercy
|
||||
var/mob/living/carbon/C = mob_occupant
|
||||
gear = C.get_all_gear()
|
||||
for(var/i in gear)
|
||||
var/obj/item/I = i
|
||||
I.forceMove(src)
|
||||
if(!istype(I))
|
||||
destroying += I
|
||||
continue
|
||||
if(I.item_flags & (DROPDEL | ABSTRACT))
|
||||
destroying += I
|
||||
continue
|
||||
if(HAS_TRAIT(I, TRAIT_NODROP))
|
||||
destroying += I
|
||||
continue
|
||||
// WEE WOO SNOWFLAKE TIME
|
||||
if(istype(I, /obj/item/pda))
|
||||
var/obj/item/pda/P = I
|
||||
if((P.owner == mind_identity) || (P.owner == occupant_identity))
|
||||
destroying += P
|
||||
else
|
||||
storing += P
|
||||
else if(istype(I, /obj/item/card/id))
|
||||
var/obj/item/card/id/idcard = I
|
||||
if((idcard.registered_name == mind_identity) || (idcard.registered_name == occupant_identity))
|
||||
destroying += idcard
|
||||
else
|
||||
storing += idcard
|
||||
else
|
||||
I.forceMove(loc)
|
||||
cryo_items -= I
|
||||
storing += I
|
||||
|
||||
// get rid of mobs
|
||||
for(var/mob/living/L in mob_occupant.GetAllContents() - mob_occupant)
|
||||
L.forceMove(drop_location())
|
||||
|
||||
if(storing.len)
|
||||
var/obj/O = new item_storage_type
|
||||
O.name = "cryogenic retrieval package: [mob_occupant.real_name]"
|
||||
for(var/i in storing)
|
||||
var/obj/item/I = i
|
||||
I.forceMove(O)
|
||||
O.forceMove(drop_to_ground? target_store.drop_location() : target_store)
|
||||
if((target_store == control_computer) && !drop_to_ground)
|
||||
control_computer.stored_packages += O
|
||||
|
||||
QDEL_LIST(destroying)
|
||||
|
||||
//Update any existing objectives involving this mob.
|
||||
for(var/i in GLOB.objectives)
|
||||
@@ -361,8 +351,12 @@
|
||||
// them win or lose based on cryo is silly so we remove the objective.
|
||||
if(istype(O,/datum/objective/mutiny) && O.target == mob_occupant.mind)
|
||||
qdel(O)
|
||||
else if(O.target && istype(O.target, /datum/mind) && !O.check_midround_completion())
|
||||
if(O.target == mob_occupant.mind && O.owner?.current)
|
||||
else if(O.target && istype(O.target, /datum/mind))
|
||||
if(O.target != mob_occupant.mind)
|
||||
continue
|
||||
if(O.check_midround_completion())
|
||||
continue
|
||||
if(O.owner && O.owner.current)
|
||||
to_chat(O.owner.current, "<BR><span class='userdanger'>You get the feeling your target is no longer within reach. Time for Plan [pick("A","B","C","D","X","Y","Z")]. Objectives updated!</span>")
|
||||
O.target = null
|
||||
spawn(10) //This should ideally fire after the occupant is deleted.
|
||||
@@ -410,22 +404,13 @@
|
||||
|
||||
// Ghost and delete the mob.
|
||||
if(!mob_occupant.get_ghost(1))
|
||||
mob_occupant.ghostize(FALSE, penalize = TRUE, voluntary = TRUE)
|
||||
mob_occupant.ghostize(FALSE, penalize = TRUE, voluntary = TRUE, cryo = TRUE)
|
||||
|
||||
QDEL_NULL(occupant)
|
||||
for(var/I in cryo_items) //only "CRYO_DESTROY_LATER" atoms are left)
|
||||
var/atom/A = I
|
||||
if(!QDELETED(A))
|
||||
qdel(A)
|
||||
QDEL_LIST(destroy_later)
|
||||
open_machine()
|
||||
name = initial(name)
|
||||
|
||||
#undef CRYO_DESTROY
|
||||
#undef CRYO_PRESERVE
|
||||
#undef CRYO_OBJECTIVE
|
||||
#undef CRYO_IGNORE
|
||||
#undef CRYO_DESTROY_LATER
|
||||
|
||||
/obj/machinery/cryopod/MouseDrop_T(mob/living/target, mob/user)
|
||||
if(!istype(target) || user.incapacitated() || !target.Adjacent(user) || !Adjacent(user) || !ismob(target) || (!ishuman(user) && !iscyborg(user)) || !istype(user.loc, /turf) || target.buckled)
|
||||
return
|
||||
|
||||
@@ -40,4 +40,4 @@
|
||||
close()
|
||||
if("minor", "clear")
|
||||
autoclose = FALSE
|
||||
open()
|
||||
open()
|
||||
|
||||
@@ -13,4 +13,4 @@
|
||||
if(!istype(D, /obj/machinery/door/window) && D.density)
|
||||
return 0
|
||||
//There are no false wall checks because that would be fucking
|
||||
return 1
|
||||
return 1
|
||||
|
||||
@@ -70,4 +70,4 @@
|
||||
return
|
||||
|
||||
/obj/machinery/door/password/ex_act(severity, target)
|
||||
return
|
||||
return
|
||||
|
||||
@@ -19,4 +19,4 @@
|
||||
icon_state = "door1"
|
||||
opacity = 1
|
||||
density = TRUE
|
||||
explosion_block = 1
|
||||
explosion_block = 1
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
icon_state = "[src.base_state]open"
|
||||
|
||||
/obj/machinery/door/window/update_atom_colour()
|
||||
. = ..()
|
||||
if((color && (color_hex2num(color) < 255)))
|
||||
visible = TRUE
|
||||
if(density)
|
||||
@@ -66,9 +67,9 @@
|
||||
/obj/machinery/door/window/proc/open_and_close()
|
||||
open()
|
||||
if(src.check_access(null))
|
||||
sleep(50)
|
||||
sleep(60)
|
||||
else //secure doors close faster
|
||||
sleep(20)
|
||||
sleep(40)
|
||||
close()
|
||||
|
||||
/obj/machinery/door/window/Bumped(atom/movable/AM)
|
||||
|
||||
@@ -187,4 +187,4 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
|
||||
|
||||
/obj/machinery/doppler_array/research/science/Initialize()
|
||||
. = ..()
|
||||
linked_techweb = SSresearch.science_tech
|
||||
linked_techweb = SSresearch.science_tech
|
||||
|
||||
@@ -312,4 +312,4 @@
|
||||
</div>
|
||||
[state_options]"}
|
||||
|
||||
return output
|
||||
return output
|
||||
|
||||
@@ -24,19 +24,24 @@
|
||||
var/selected_category
|
||||
var/screen = 1
|
||||
var/list/categories = list(
|
||||
"human",
|
||||
"lizard",
|
||||
"fly",
|
||||
"insect",
|
||||
"plasmaman",
|
||||
"mammal",
|
||||
"xeno",
|
||||
"other"
|
||||
"human" = /datum/species/human,
|
||||
"lizard" = /datum/species/lizard,
|
||||
"mammal" = /datum/species/mammal,
|
||||
"insect" = /datum/species/insect,
|
||||
"fly" = /datum/species/fly,
|
||||
"plasmaman" = /datum/species/plasmaman,
|
||||
"xeno" = /datum/species/xeno,
|
||||
"other" = /datum/species,
|
||||
)
|
||||
var/list/stored_species = list()
|
||||
var/obj/item/disk/data/dna_disk
|
||||
|
||||
/obj/machinery/limbgrower/Initialize()
|
||||
create_reagents(100, OPENCONTAINER)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/limbgrower
|
||||
for(var/i in categories)
|
||||
var/species = categories[i]
|
||||
stored_species[i] = new species()
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/limbgrower/ui_interact(mob/user)
|
||||
@@ -64,8 +69,8 @@
|
||||
..()
|
||||
|
||||
/obj/machinery/limbgrower/attackby(obj/item/O, mob/user, params)
|
||||
if (busy)
|
||||
to_chat(user, "<span class=\"alert\">The Limb Grower is busy. Please wait for completion of previous operation.</span>")
|
||||
if(busy)
|
||||
to_chat(user, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
|
||||
return
|
||||
|
||||
if(default_deconstruction_screwdriver(user, "limbgrower_panelopen", "limbgrower_idleoff", O))
|
||||
@@ -78,6 +83,16 @@
|
||||
if(user.a_intent == INTENT_HARM) //so we can hit the machine
|
||||
return ..()
|
||||
|
||||
if(istype(O, /obj/item/disk))
|
||||
if(dna_disk)
|
||||
to_chat(user, "<span class='warning'>\The [src] already has a dna disk, take it out first!</span>")
|
||||
return
|
||||
else
|
||||
O.forceMove(src)
|
||||
dna_disk = O
|
||||
to_chat(user, "<span class='notice'>You insert \the [O] into \the [src].</span>")
|
||||
return
|
||||
|
||||
/obj/machinery/limbgrower/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
@@ -110,8 +125,24 @@
|
||||
icon_state = "limbgrower_idleon"
|
||||
addtimer(CALLBACK(src, .proc/build_item),32*prod_coeff)
|
||||
|
||||
if(href_list["dna_disk"])
|
||||
var/mob/living/carbon/user = usr
|
||||
if(istype(user))
|
||||
if(!dna_disk)
|
||||
var/obj/item/disk/diskette = user.get_active_held_item()
|
||||
if(istype(diskette))
|
||||
diskette.forceMove(src)
|
||||
dna_disk = diskette
|
||||
to_chat(user, "<span class='notice'>You insert \the [diskette] into \the [src].</span>")
|
||||
else
|
||||
dna_disk.forceMove(src.loc)
|
||||
user.put_in_active_hand(dna_disk)
|
||||
to_chat(user, "<span class='notice'>You remove \the [dna_disk] from \the [src].</span>")
|
||||
dna_disk = null
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You are unable to grasp \the [dna_disk] disk from \the [src].</span>")
|
||||
else
|
||||
to_chat(usr, "<span class=\"alert\">The limb grower is busy. Please wait for completion of previous operation.</span>")
|
||||
to_chat(usr, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
|
||||
|
||||
updateUsrDialog()
|
||||
return
|
||||
@@ -120,8 +151,10 @@
|
||||
if(reagents.has_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)) //sanity check, if this happens we are in big trouble
|
||||
reagents.remove_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)
|
||||
var/buildpath = being_built.build_path
|
||||
if(ispath(buildpath, /obj/item/bodypart)) //This feels like spatgheti code, but i need to initilise a limb somehow
|
||||
if(ispath(buildpath, /obj/item/bodypart)) //This feels like spaghetti code, but i need to initiliaze a limb somehow
|
||||
build_limb(buildpath)
|
||||
else if(ispath(buildpath, /obj/item/organ/genital)) //genitals are uhh... customizable
|
||||
build_genital(buildpath)
|
||||
else
|
||||
//Just build whatever it is
|
||||
new buildpath(loc)
|
||||
@@ -135,19 +168,65 @@
|
||||
/obj/machinery/limbgrower/proc/build_limb(buildpath)
|
||||
//i need to create a body part manually using a set icon (otherwise it doesnt appear)
|
||||
var/obj/item/bodypart/limb
|
||||
var/datum/species/selected = stored_species[selected_category]
|
||||
limb = new buildpath(loc)
|
||||
if(selected_category=="human" || selected_category=="lizard") //Species with greyscale parts should be included here
|
||||
limb.icon = 'icons/mob/human_parts_greyscale.dmi'
|
||||
limb.base_bp_icon = DEFAULT_BODYPART_ICON_ORGANIC
|
||||
limb.color_src = MUTCOLORS
|
||||
else
|
||||
limb.icon = 'icons/mob/human_parts.dmi'
|
||||
// Set this limb up using the specias name and body zone
|
||||
limb.icon_state = "[selected_category]_[limb.body_zone]"
|
||||
limb.name = "\improper synthetic [selected_category] [parse_zone(limb.body_zone)]"
|
||||
limb.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]."
|
||||
limb.species_id = selected_category
|
||||
limb.base_bp_icon = selected.icon_limbs || DEFAULT_BODYPART_ICON_ORGANIC
|
||||
limb.species_id = selected.limbs_id
|
||||
limb.color_src = (MUTCOLORS in selected.species_traits ? MUTCOLORS : (selected.use_skintones ? SKINTONE : FALSE))
|
||||
limb.should_draw_gender = (selected.sexes && (limb.body_zone in list(BODY_ZONE_HEAD, BODY_ZONE_CHEST)))
|
||||
limb.update_limb(TRUE)
|
||||
limb.update_icon_dropped()
|
||||
limb.name = "\improper synthetic [lowertext(selected.name)] [limb.name]"
|
||||
limb.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]."
|
||||
for(var/obj/item/bodypart/BP in limb)
|
||||
BP.base_bp_icon = selected.icon_limbs || DEFAULT_BODYPART_ICON_ORGANIC
|
||||
BP.species_id = selected.limbs_id
|
||||
BP.color_src = (MUTCOLORS in selected.species_traits ? MUTCOLORS : (selected.use_skintones ? SKINTONE : FALSE))
|
||||
BP.should_draw_gender = (selected.sexes && (limb.body_zone in list(BODY_ZONE_HEAD, BODY_ZONE_CHEST)))
|
||||
BP.update_limb(TRUE)
|
||||
BP.update_icon_dropped()
|
||||
BP.name = "\improper synthetic [lowertext(selected.name)] [limb.name]"
|
||||
BP.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]."
|
||||
|
||||
/obj/machinery/limbgrower/proc/build_genital(buildpath)
|
||||
//i needed to create a way to customize gene tools using dna
|
||||
var/list/features = dna_disk?.fields["features"]
|
||||
if(length(features))
|
||||
switch(buildpath)
|
||||
if(/obj/item/organ/genital/penis)
|
||||
var/obj/item/organ/genital/penis/penis = new(loc)
|
||||
if(features["has_cock"])
|
||||
penis.shape = features["cock_shape"]
|
||||
penis.length = features["cock_shape"]
|
||||
penis.diameter_ratio = features["cock_diameter_ratio"]
|
||||
penis.color = sanitize_hexcolor(features["cock_color"], 6)
|
||||
penis.update_icon()
|
||||
if(/obj/item/organ/genital/testicles)
|
||||
var/obj/item/organ/genital/testicles/balls = new(loc)
|
||||
if(features["has_balls"])
|
||||
balls.color = sanitize_hexcolor(features["balls_color"], 6)
|
||||
balls.shape = features["balls_shape"]
|
||||
balls.size = features["balls_size"]
|
||||
balls.fluid_rate = features["balls_cum_rate"]
|
||||
balls.fluid_mult = features["balls_cum_mult"]
|
||||
balls.fluid_efficiency = features["balls_efficiency"]
|
||||
if(/obj/item/organ/genital/vagina)
|
||||
var/obj/item/organ/genital/vagina/vegana = new(loc)
|
||||
if(features["has_vagina"])
|
||||
vegana.color = sanitize_hexcolor(features["vag_color"], 6)
|
||||
vegana.shape = features["vag_shape"]
|
||||
if(/obj/item/organ/genital/breasts)
|
||||
var/obj/item/organ/genital/breasts/boobs = new(loc)
|
||||
if(features["has_breasts"])
|
||||
boobs.color = sanitize_hexcolor(features["breasts_color"], 6)
|
||||
boobs.size = features["breasts_size"]
|
||||
boobs.shape = features["breasts_shape"]
|
||||
if(!features["breasts_producing"])
|
||||
boobs.genital_flags &= ~(GENITAL_FUID_PRODUCTION|CAN_CLIMAX_WITH|CAN_MASTURBATE_WITH)
|
||||
else
|
||||
new buildpath(loc)
|
||||
else
|
||||
new buildpath(loc)
|
||||
|
||||
/obj/machinery/limbgrower/RefreshParts()
|
||||
reagents.maximum_volume = 0
|
||||
@@ -165,7 +244,9 @@
|
||||
. += "<span class='notice'>The status display reads: Storing up to <b>[reagents.maximum_volume]u</b> of synthflesh.<br>Synthflesh consumption at <b>[prod_coeff*100]%</b>.<span>"
|
||||
|
||||
/obj/machinery/limbgrower/proc/main_win(mob/user)
|
||||
var/dat = "<div class='statusDisplay'><h3>Limb Grower Menu:</h3><br>"
|
||||
var/dat = "<div class='statusDisplay'><h3>[src] Menu:</h3><br>"
|
||||
dat += "<A href='?src=[REF(src)];dna_disk=1'>[dna_disk ? "Remove" : "Insert"] cloning data disk</A>"
|
||||
dat += "<hr>"
|
||||
dat += "<A href='?src=[REF(src)];menu=[LIMBGROWER_CHEMICAL_MENU]'>Chemical Storage</A>"
|
||||
dat += materials_printout()
|
||||
dat += "<table style='width:100%' align='center'><tr>"
|
||||
@@ -218,7 +299,7 @@
|
||||
|
||||
/obj/machinery/limbgrower/proc/get_design_cost(datum/design/D)
|
||||
var/dat
|
||||
if(D.reagents_list["synthflesh"])
|
||||
if(D.reagents_list[/datum/reagent/medicine/synthflesh])
|
||||
dat += "[D.reagents_list[/datum/reagent/medicine/synthflesh] * prod_coeff] Synthetic flesh "
|
||||
return dat
|
||||
|
||||
@@ -233,3 +314,47 @@
|
||||
to_chat(user, "<span class='warning'>A warning flashes onto the screen, stating that safety overrides have been deactivated!</span>")
|
||||
obj_flags |= EMAGGED
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/limbgrower/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(istype(user) && user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
if(busy)
|
||||
to_chat(user, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
|
||||
else
|
||||
if(dna_disk)
|
||||
dna_disk.forceMove(src.loc)
|
||||
user.put_in_active_hand(dna_disk)
|
||||
to_chat(user, "<span class='notice'>You remove \the [dna_disk] from \the [src].</span>")
|
||||
dna_disk = null
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [src] has doesn't have a disk on it!")
|
||||
|
||||
//Defines some vars that makes limbs appears, TO-DO: define every single species.
|
||||
|
||||
/datum/species/human
|
||||
limbs_id = SPECIES_HUMAN
|
||||
icon_limbs = 'icons/mob/human_parts_greyscale.dmi'
|
||||
|
||||
/datum/species/lizard
|
||||
limbs_id = SPECIES_LIZARD
|
||||
icon_limbs = 'icons/mob/human_parts_greyscale.dmi'
|
||||
|
||||
/datum/species/mammal
|
||||
limbs_id = SPECIES_MAMMAL
|
||||
icon_limbs = 'icons/mob/human_parts_greyscale.dmi'
|
||||
|
||||
/datum/species/insect
|
||||
limbs_id = SPECIES_INSECT
|
||||
icon_limbs = 'icons/mob/human_parts_greyscale.dmi'
|
||||
|
||||
/datum/species/fly
|
||||
limbs_id = SPECIES_FLY
|
||||
icon_limbs = 'icons/mob/human_parts.dmi'
|
||||
|
||||
/datum/species/plasmaman
|
||||
limbs_id = SPECIES_PLASMAMAN
|
||||
icon_limbs = 'icons/mob/human_parts.dmi'
|
||||
|
||||
/datum/species/xeno
|
||||
limbs_id = SPECIES_XENOHYBRID
|
||||
icon_limbs = 'icons/mob/human_parts_greyscale.dmi'
|
||||
|
||||
@@ -48,4 +48,4 @@
|
||||
if(isliving(O))
|
||||
var/mob/living/L = O
|
||||
to_chat(L, "<span class='warning'>You feel something click beneath you!</span>")
|
||||
addtimer(CALLBACK(src, .proc/drive), drive_delay)
|
||||
addtimer(CALLBACK(src, .proc/drive), drive_delay)
|
||||
|
||||
@@ -774,6 +774,9 @@
|
||||
stun_projectile_sound = 'sound/weapons/gunshot_smg.ogg'
|
||||
armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 80, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/pod/toolbox
|
||||
max_integrity = 100
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/shuttle/target(atom/movable/target)
|
||||
if(target)
|
||||
setDir(get_dir(base, target))//even if you can't shoot, follow the target
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
var/mode = HEATER_MODE_STANDBY
|
||||
var/setMode = "auto" // Anything other than "heat" or "cool" is considered auto.
|
||||
var/targetTemperature = T20C
|
||||
var/heatingPower = 40000
|
||||
var/heatingPower = 10000
|
||||
var/efficiency = 20000
|
||||
var/temperatureTolerance = 1
|
||||
var/settableTemperatureMedian = 30 + T0C
|
||||
@@ -74,46 +74,55 @@
|
||||
|
||||
if(cell && cell.charge > 0)
|
||||
var/turf/L = loc
|
||||
if(!istype(L))
|
||||
if(mode != HEATER_MODE_STANDBY)
|
||||
mode = HEATER_MODE_STANDBY
|
||||
update_icon()
|
||||
return
|
||||
PerformHeating(L)
|
||||
|
||||
var/datum/gas_mixture/env = L.return_air()
|
||||
for(var/direction in GLOB.alldirs)
|
||||
L=get_step(src,direction)
|
||||
if(!locate(/turf/closed) in L) // we don't want to heat walls and cause jank
|
||||
PerformHeating(L)
|
||||
|
||||
var/newMode = HEATER_MODE_STANDBY
|
||||
if(setMode != HEATER_MODE_COOL && env.return_temperature() < targetTemperature - temperatureTolerance)
|
||||
newMode = HEATER_MODE_HEAT
|
||||
else if(setMode != HEATER_MODE_HEAT && env.return_temperature() > targetTemperature + temperatureTolerance)
|
||||
newMode = HEATER_MODE_COOL
|
||||
|
||||
if(mode != newMode)
|
||||
mode = newMode
|
||||
update_icon()
|
||||
|
||||
if(mode == HEATER_MODE_STANDBY)
|
||||
return
|
||||
|
||||
var/heat_capacity = env.heat_capacity()
|
||||
var/requiredPower = abs(env.return_temperature() - targetTemperature) * heat_capacity
|
||||
requiredPower = min(requiredPower, heatingPower)
|
||||
|
||||
if(requiredPower < 1)
|
||||
return
|
||||
|
||||
var/deltaTemperature = requiredPower / heat_capacity
|
||||
if(mode == HEATER_MODE_COOL)
|
||||
deltaTemperature *= -1
|
||||
if(deltaTemperature)
|
||||
env.set_temperature(env.return_temperature() + deltaTemperature)
|
||||
air_update_turf()
|
||||
cell.use(requiredPower / efficiency)
|
||||
else
|
||||
on = FALSE
|
||||
update_icon()
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/machinery/space_heater/proc/PerformHeating(turf/L)
|
||||
if(!istype(L))
|
||||
if(mode != HEATER_MODE_STANDBY)
|
||||
mode = HEATER_MODE_STANDBY
|
||||
update_icon()
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/env = L.return_air()
|
||||
|
||||
var/newMode = HEATER_MODE_STANDBY
|
||||
if(setMode != HEATER_MODE_COOL && env.return_temperature() < targetTemperature - temperatureTolerance)
|
||||
newMode = HEATER_MODE_HEAT
|
||||
else if(setMode != HEATER_MODE_HEAT && env.return_temperature() > targetTemperature + temperatureTolerance)
|
||||
newMode = HEATER_MODE_COOL
|
||||
|
||||
if(mode != newMode)
|
||||
mode = newMode
|
||||
update_icon()
|
||||
|
||||
if(mode == HEATER_MODE_STANDBY)
|
||||
return
|
||||
|
||||
var/heat_capacity = env.heat_capacity()
|
||||
var/requiredPower = abs(env.return_temperature() - targetTemperature) * heat_capacity
|
||||
requiredPower = min(requiredPower, heatingPower)
|
||||
|
||||
if(requiredPower < 1)
|
||||
return
|
||||
|
||||
var/deltaTemperature = requiredPower / heat_capacity
|
||||
if(mode == HEATER_MODE_COOL)
|
||||
deltaTemperature *= -1
|
||||
if(deltaTemperature)
|
||||
env.set_temperature(env.return_temperature() + deltaTemperature)
|
||||
air_update_turf()
|
||||
cell.use(requiredPower / efficiency)
|
||||
|
||||
/obj/machinery/space_heater/RefreshParts()
|
||||
var/laser = 2
|
||||
var/cap = 1
|
||||
@@ -122,7 +131,7 @@
|
||||
for(var/obj/item/stock_parts/capacitor/M in component_parts)
|
||||
cap += M.rating
|
||||
|
||||
heatingPower = laser * 40000
|
||||
heatingPower = laser * 10000
|
||||
|
||||
settableTemperatureRange = cap * 30
|
||||
efficiency = (cap + 1) * 10000
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
for(var/obj/item/I in equipment)
|
||||
if(istype(I, /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/))
|
||||
var/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/gun = I
|
||||
gun.projectiles_cache = gun.projectiles_cache_max
|
||||
gun.projectiles_cache = gun.projectiles_cache_max
|
||||
|
||||
@@ -172,4 +172,4 @@
|
||||
mineral_scan_pulse(get_turf(src))
|
||||
|
||||
#undef DRILL_BASIC
|
||||
#undef DRILL_HARDENED
|
||||
#undef DRILL_HARDENED
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
if(.)
|
||||
return
|
||||
if(can_buckle && has_buckled_mobs())
|
||||
if(ishuman(src)) //prevent people from unbuckling fireman-carried/piggybacked people unless on disarm or harm intents
|
||||
if(act_intent == INTENT_HELP || act_intent == INTENT_GRAB)
|
||||
return
|
||||
if(buckled_mobs.len > 1)
|
||||
var/unbuckled = input(user, "Who do you wish to unbuckle?","Unbuckle Who?") as null|mob in buckled_mobs
|
||||
if(user_unbuckle_mob(unbuckled,user))
|
||||
|
||||
@@ -24,4 +24,4 @@
|
||||
|
||||
/obj/effect/blessing/proc/block_cult_teleport(datum/source, channel, turf/origin, turf/destination)
|
||||
if(channel == TELEPORT_CHANNEL_CULT)
|
||||
return COMPONENT_BLOCK_TELEPORT
|
||||
return COMPONENT_BLOCK_TELEPORT
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
/obj/effect/decal/cleanable
|
||||
gender = PLURAL
|
||||
layer = ABOVE_NORMAL_TURF_LAYER
|
||||
/// Is this kind of cleanable decal persistent
|
||||
var/persistent = FALSE
|
||||
/// Can we stack multiple in one tile?
|
||||
var/persistence_allow_stacking = FALSE
|
||||
/// Are we deleted by turf changes?
|
||||
var/wiped_by_floor_change = FALSE
|
||||
|
||||
var/list/random_icon_states = null
|
||||
var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA
|
||||
var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints
|
||||
@@ -29,9 +36,21 @@
|
||||
|
||||
addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, beauty)), 0)
|
||||
|
||||
/**
|
||||
* A data list is passed into this.
|
||||
* This should return null to skip saving, or the type of data to save. Type must be /cleanable.
|
||||
*/
|
||||
/obj/effect/decal/cleanable/proc/PersistenceSave(list/data)
|
||||
return type
|
||||
|
||||
/**
|
||||
* Loads from a data list.
|
||||
*/
|
||||
/obj/effect/decal/cleanable/proc/PersistenceLoad(list/data)
|
||||
return
|
||||
|
||||
/obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) // Returns true if we should give up in favor of the pre-existing decal
|
||||
if(mergeable_decal)
|
||||
qdel(C)
|
||||
return mergeable_decal
|
||||
|
||||
/obj/effect/decal/cleanable/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/reagent_containers/glass) || istype(W, /obj/item/reagent_containers/food/drinks))
|
||||
|
||||
@@ -74,4 +74,4 @@
|
||||
|
||||
/obj/effect/decal/cleanable/blood/xtracks/Initialize()
|
||||
add_blood_DNA(list("UNKNOWN DNA" = "X*"))
|
||||
. = ..()
|
||||
. = ..()
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
|
||||
mergeable_decal = FALSE
|
||||
bloodiness = 0 //This isn't supposed to be bloody.
|
||||
persistent = TRUE
|
||||
var/body_colors = "#e3ba84" //a default color just in case.
|
||||
var/gibs_reagent_id = /datum/reagent/liquidgibs
|
||||
var/gibs_bloodtype = "A+"
|
||||
@@ -31,6 +32,10 @@
|
||||
flesh.color = body_colors
|
||||
add_overlay(flesh)
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/PersistenceSave(list/data)
|
||||
. = ..()
|
||||
return /obj/effect/decal/cleanable/blood/gibs/old
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/ex_act(severity, target)
|
||||
return
|
||||
|
||||
@@ -159,6 +164,10 @@
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/slime/PersistenceSave(list/data)
|
||||
. = ..()
|
||||
return type
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/slime/update_icon()
|
||||
add_atom_colour(body_colors, FIXED_COLOUR_PRIORITY)
|
||||
cut_overlays()
|
||||
@@ -198,6 +207,10 @@
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/synth/PersistenceSave(list/data)
|
||||
. = ..()
|
||||
return type
|
||||
|
||||
//IPCs
|
||||
/obj/effect/decal/cleanable/blood/gibs/ipc
|
||||
desc = "They look sharp yet oozing."
|
||||
@@ -209,6 +222,10 @@
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/ipc/PersistenceSave(list/data)
|
||||
. = ..()
|
||||
return type
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/ipc/update_icon()
|
||||
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
|
||||
cut_overlays()
|
||||
|
||||
@@ -8,12 +8,18 @@
|
||||
bloodiness = BLOOD_AMOUNT_PER_DECAL
|
||||
color = BLOOD_COLOR_HUMAN //default so we don't have white splotches everywhere.
|
||||
beauty = -100
|
||||
persistent = TRUE
|
||||
var/fixed_color = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C)
|
||||
if(C.fixed_color)
|
||||
qdel(C)
|
||||
return FALSE
|
||||
if (C.blood_DNA)
|
||||
blood_DNA |= C.blood_DNA
|
||||
qdel(C)
|
||||
update_icon()
|
||||
..()
|
||||
return FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/blood/transfer_blood_dna()
|
||||
..()
|
||||
@@ -24,7 +30,22 @@
|
||||
update_icon()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/update_icon()
|
||||
color = blood_DNA_to_color()
|
||||
. = ..()
|
||||
if(!fixed_color)
|
||||
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
|
||||
|
||||
/obj/effect/decal/cleanable/blood/PersistenceSave(list/data)
|
||||
. = ..()
|
||||
data["color"] = color
|
||||
|
||||
/obj/effect/decal/cleanable/blood/PersistenceLoad(list/data)
|
||||
. = ..()
|
||||
if(data["color"])
|
||||
fixed_color = TRUE
|
||||
add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY)
|
||||
name = "dried blood"
|
||||
desc = "Looks like it's been here a while. Eew"
|
||||
bloodiness = 0
|
||||
|
||||
/obj/effect/decal/cleanable/blood/old
|
||||
name = "dried blood"
|
||||
@@ -38,6 +59,7 @@
|
||||
|
||||
/obj/effect/decal/cleanable/blood/splats
|
||||
random_icon_states = list("gibbl1", "gibbl2", "gibbl3", "gibbl4", "gibbl5")
|
||||
persistence_allow_stacking = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/blood/splatter
|
||||
random_icon_states = list("splatter1", "splatter2", "splatter3", "splatter4", "splatter5")
|
||||
@@ -48,16 +70,43 @@
|
||||
random_icon_states = null
|
||||
beauty = -50
|
||||
|
||||
/obj/effect/decal/cleanable/blood/tracks/PersistenceSave(list/data)
|
||||
. = ..()
|
||||
data["dir"] = dir
|
||||
|
||||
/obj/effect/decal/cleanable/blood/tracks/PersistenceLoad(list/data)
|
||||
. = ..()
|
||||
if(data["dir"])
|
||||
setDir(text2num(data["dir"]))
|
||||
|
||||
/obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose
|
||||
name = "blood"
|
||||
icon_state = "ltrails_1"
|
||||
desc = "Your instincts say you shouldn't be following these."
|
||||
random_icon_states = null
|
||||
beauty = -50
|
||||
persistent = TRUE
|
||||
persistence_allow_stacking = TRUE
|
||||
var/list/existing_dirs = list()
|
||||
var/fixed_color = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/trail_holder/PersistenceSave(list/data)
|
||||
. = ..()
|
||||
data["dir"] = dir
|
||||
data["color"] = color
|
||||
|
||||
/obj/effect/decal/cleanable/trail_holder/PersistenceLoad(list/data)
|
||||
. = ..()
|
||||
if(data["dir"])
|
||||
setDir(text2num(data["dir"]))
|
||||
if(data["color"])
|
||||
fixed_color = TRUE
|
||||
add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY)
|
||||
|
||||
/obj/effect/decal/cleanable/trail_holder/update_icon()
|
||||
color = blood_DNA_to_color()
|
||||
. = ..()
|
||||
if(!fixed_color)
|
||||
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
|
||||
|
||||
/obj/effect/cleanable/trail_holder/Initialize()
|
||||
. = ..()
|
||||
@@ -84,8 +133,19 @@
|
||||
var/entered_dirs = 0
|
||||
var/exited_dirs = 0
|
||||
blood_state = BLOOD_STATE_BLOOD //the icon state to load images from
|
||||
persistent = TRUE
|
||||
persistence_allow_stacking = TRUE
|
||||
var/list/shoe_types = list()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/footprints/PersistenceSave(list/data)
|
||||
. = ..()
|
||||
data["dir"] = dir
|
||||
|
||||
/obj/effect/decal/cleanable/blood/footprints/PersistenceLoad(list/data)
|
||||
. = ..()
|
||||
if(data["dir"])
|
||||
setDir(text2num(data["dir"]))
|
||||
|
||||
/obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O)
|
||||
if(ishuman(O))
|
||||
var/mob/living/carbon/human/H = O
|
||||
@@ -143,7 +203,7 @@
|
||||
return
|
||||
if(color != C.color)
|
||||
return
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/footprints/can_bloodcrawl_in()
|
||||
if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY))
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
icon_state = "ash"
|
||||
mergeable_decal = FALSE
|
||||
beauty = -50
|
||||
persistent = TRUE
|
||||
persistence_allow_stacking = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/ash/Initialize()
|
||||
. = ..()
|
||||
@@ -38,6 +40,8 @@
|
||||
icon = 'icons/obj/shards.dmi'
|
||||
icon_state = "tiny"
|
||||
beauty = -100
|
||||
mergeable_decal = TRUE
|
||||
persistent = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/glass/Initialize()
|
||||
. = ..()
|
||||
@@ -53,10 +57,33 @@
|
||||
name = "dirt"
|
||||
desc = "Someone should clean that up."
|
||||
icon_state = "dirt"
|
||||
alpha = 127
|
||||
canSmoothWith = list(/obj/effect/decal/cleanable/dirt, /turf/closed/wall, /obj/structure/falsewall)
|
||||
smooth = SMOOTH_FALSE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
beauty = -75
|
||||
mergeable_decal = TRUE
|
||||
persistent = TRUE
|
||||
wiped_by_floor_change = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/dirt/Initialize(mapload)
|
||||
. = ..()
|
||||
alpha = CONFIG_GET(number/dirt_alpha_starting)
|
||||
|
||||
/obj/effect/decal/cleanable/dirt/proc/dirty(strength = 1)
|
||||
if(alpha < 255)
|
||||
alpha += strength
|
||||
if(alpha > 255)
|
||||
alpha = 255
|
||||
|
||||
/obj/effect/decal/cleanable/dirt/PersistenceSave(list/data)
|
||||
. = ..()
|
||||
data["alpha"] = alpha
|
||||
|
||||
/obj/effect/decal/cleanable/dirt/PersistenceLoad(list/data)
|
||||
. = ..()
|
||||
if(data["alpha"])
|
||||
alpha = text2num(data["alpha"])
|
||||
|
||||
/obj/effect/decal/cleanable/dirt/Initialize()
|
||||
. = ..()
|
||||
@@ -94,6 +121,8 @@
|
||||
light_color = LIGHT_COLOR_GREEN
|
||||
icon_state = "greenglow"
|
||||
beauty = -300
|
||||
mergeable_decal = TRUE
|
||||
persistent = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/greenglow/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -122,6 +151,8 @@
|
||||
icon_state = "molten"
|
||||
mergeable_decal = FALSE
|
||||
beauty = -150
|
||||
persistent = TRUE
|
||||
persistence_allow_stacking = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/molten_object/large
|
||||
name = "big gooey grey mass"
|
||||
@@ -136,6 +167,7 @@
|
||||
icon_state = "vomit_1"
|
||||
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
|
||||
beauty = -150
|
||||
persistent = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/vomit/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(ishuman(user))
|
||||
@@ -151,6 +183,10 @@
|
||||
reagents.trans_to(H, reagents.total_volume)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/decal/cleanable/vomit/PersistenceSave(list/data)
|
||||
. = ..()
|
||||
return /obj/effect/decal/cleanable/vomit/old
|
||||
|
||||
/obj/effect/decal/cleanable/vomit/old
|
||||
name = "crusty dried vomit"
|
||||
desc = "You try not to look at the chunks, and fail."
|
||||
@@ -166,12 +202,16 @@
|
||||
icon = 'icons/effects/tomatodecal.dmi'
|
||||
random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3")
|
||||
beauty = -100
|
||||
mergeable_decal = TRUE
|
||||
persistent = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/plant_smudge
|
||||
name = "plant smudge"
|
||||
gender = NEUTER
|
||||
icon = 'icons/effects/tomatodecal.dmi'
|
||||
random_icon_states = list("smashed_plant")
|
||||
mergeable_decal = TRUE
|
||||
persistent = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/egg_smudge
|
||||
name = "smashed egg"
|
||||
@@ -179,6 +219,8 @@
|
||||
gender = NEUTER
|
||||
icon = 'icons/effects/tomatodecal.dmi'
|
||||
random_icon_states = list("smashed_egg1", "smashed_egg2", "smashed_egg3")
|
||||
mergeable_decal = TRUE
|
||||
persistent = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/pie_smudge //honk
|
||||
name = "smashed pie"
|
||||
@@ -186,6 +228,8 @@
|
||||
gender = NEUTER
|
||||
icon = 'icons/effects/tomatodecal.dmi'
|
||||
random_icon_states = list("smashed_pie")
|
||||
mergeable_decal = TRUE
|
||||
persistent = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/chem_pile
|
||||
name = "chemical pile"
|
||||
@@ -193,6 +237,8 @@
|
||||
gender = NEUTER
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "ash"
|
||||
mergeable_decal = TRUE
|
||||
persistent = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/shreds
|
||||
name = "shreds"
|
||||
@@ -200,6 +246,8 @@
|
||||
icon_state = "shreds"
|
||||
gender = PLURAL
|
||||
mergeable_decal = FALSE
|
||||
mergeable_decal = TRUE
|
||||
persistent = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/shreds/ex_act(severity, target)
|
||||
if(severity == 1) //so shreds created during an explosion aren't deleted by the explosion.
|
||||
@@ -222,6 +270,8 @@
|
||||
desc = "The herpes of arts and crafts."
|
||||
icon = 'icons/effects/atmospherics.dmi'
|
||||
gender = NEUTER
|
||||
mergeable_decal = TRUE
|
||||
persistent = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/glitter/pink
|
||||
name = "pink glitter"
|
||||
@@ -247,3 +297,5 @@
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "xfloor1"
|
||||
random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7")
|
||||
mergeable_decal = TRUE
|
||||
persistent = TRUE
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
bloodiness = BLOOD_AMOUNT_PER_DECAL
|
||||
mergeable_decal = FALSE
|
||||
beauty = -50
|
||||
persistent = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/robot_debris/Initialize(mapload, list/datum/disease/diseases)
|
||||
. = ..()
|
||||
@@ -52,6 +53,7 @@
|
||||
blood_state = BLOOD_STATE_OIL
|
||||
bloodiness = BLOOD_AMOUNT_PER_DECAL
|
||||
beauty = -100
|
||||
persistent = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/oil/Initialize()
|
||||
. = ..()
|
||||
@@ -61,8 +63,10 @@
|
||||
/obj/effect/decal/cleanable/oil/streak
|
||||
random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5")
|
||||
beauty = -50
|
||||
persistent = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/oil/slippery
|
||||
persistent = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/oil/slippery/Initialize()
|
||||
AddComponent(/datum/component/slippery, 80, (NO_SLIP_WHEN_WALKING | SLIDE))
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
icon_state = "rune1"
|
||||
plane = ABOVE_WALL_PLANE //makes the graffiti visible over a wall.
|
||||
gender = NEUTER
|
||||
persistent = TRUE
|
||||
persistence_allow_stacking = TRUE
|
||||
mergeable_decal = FALSE
|
||||
var/do_icon_rotate = TRUE
|
||||
var/rotation = 0
|
||||
@@ -29,3 +31,35 @@
|
||||
if(main)
|
||||
paint_colour = main
|
||||
add_atom_colour(paint_colour, FIXED_COLOUR_PRIORITY)
|
||||
|
||||
/obj/effect/decal/cleanable/crayon/PersistenceSave(list/data)
|
||||
. = ..()
|
||||
if(icon != initial(icon)) // no support for alticons yet, awful system anyways
|
||||
return null
|
||||
data["icon_state"] = icon_state
|
||||
data["paint_color"] = paint_colour
|
||||
if(do_icon_rotate)
|
||||
data["rotation"] = rotation
|
||||
data["name"] = name
|
||||
if(pixel_x != initial(pixel_x))
|
||||
data["pixel_x"] = pixel_x
|
||||
if(pixel_y != initial(pixel_y))
|
||||
data["pixel_y"] = pixel_y
|
||||
|
||||
/obj/effect/decal/cleanable/crayon/PersistenceLoad(list/data)
|
||||
. = ..()
|
||||
if(data["name"])
|
||||
name = data["name"]
|
||||
if(do_icon_rotate && data["rotation"])
|
||||
var/matrix/M = matrix()
|
||||
M.Turn(text2num(data["rotation"]))
|
||||
transform = M
|
||||
if(data["paint_color"])
|
||||
paint_colour = data["paint_color"]
|
||||
add_atom_colour(paint_colour, FIXED_COLOUR_PRIORITY)
|
||||
if(data["icon_state"])
|
||||
icon_state = data["icon_state"]
|
||||
if(data["pixel_x"])
|
||||
pixel_x = data["pixel_x"]
|
||||
if(data["pixel_y"])
|
||||
pixel_y = data["pixel_y"]
|
||||
|
||||
@@ -235,4 +235,4 @@
|
||||
icon_state = "trimline_corner_fill"
|
||||
|
||||
/obj/effect/turf_decal/trimline/neutral/filled/end
|
||||
icon_state = "trimline_end_fill"
|
||||
icon_state = "trimline_end_fill"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
return
|
||||
. = ..()
|
||||
|
||||
if(AM.movement_type & FLYING)
|
||||
if(AM.movement_type & FLYING || iseffect(AM))
|
||||
return
|
||||
|
||||
triggermine(AM)
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
..()
|
||||
var/new_type = pick(subtypesof(/obj/structure/trap) - typesof(/obj/structure/trap/ctf))
|
||||
new new_type(get_turf(src))
|
||||
return INITIALIZE_HINT_QDEL
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
@@ -89,4 +89,4 @@
|
||||
|
||||
/obj/item/chromosome/reinforcer/apply(datum/mutation/human/HM)
|
||||
HM.mutadone_proof = TRUE
|
||||
..()
|
||||
..()
|
||||
|
||||
@@ -297,6 +297,10 @@
|
||||
name = "Mining Shuttle (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/mining
|
||||
|
||||
/obj/item/circuitboard/computer/mining_shuttle/common
|
||||
name = "Lavaland Shuttle (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/mining/common
|
||||
|
||||
/obj/item/circuitboard/computer/snow_taxi
|
||||
name = "Snow Taxi (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/snow_taxi
|
||||
|
||||
@@ -253,6 +253,12 @@
|
||||
/obj/item/stack/sheet/glass = 1)
|
||||
def_components = list(/obj/item/stack/ore/bluespace_crystal = /obj/item/stack/ore/bluespace_crystal/artificial)
|
||||
|
||||
/obj/item/circuitboard/machine/colormate
|
||||
name = "Colormate (Machine Board)"
|
||||
build_path = /obj/machinery/gear_painter
|
||||
req_components = list()
|
||||
def_components = list()
|
||||
|
||||
/obj/item/circuitboard/machine/vendor
|
||||
name = "Custom Vendor (Machine Board)"
|
||||
desc = "You can turn the \"brand selection\" dial using a screwdriver."
|
||||
|
||||
@@ -100,4 +100,4 @@
|
||||
|
||||
#undef WAND_OPEN
|
||||
#undef WAND_BOLT
|
||||
#undef WAND_EMERGENCY
|
||||
#undef WAND_EMERGENCY
|
||||
|
||||
@@ -80,6 +80,17 @@
|
||||
to_chat(user, "<span class='notice'>You insert the credits into [src].</span>")
|
||||
update_icon()
|
||||
qdel(H)
|
||||
if(istype(I, /obj/item/card/id))
|
||||
var/obj/item/card/id/ID = I
|
||||
if(!ID.registered_account)
|
||||
to_chat(user, "<span class='warning'>[ID] doesn't have a linked account to deposit into!</span>")
|
||||
return
|
||||
for(var/obj/item/holochip/money in src.loc.contents)
|
||||
ID.attackby(money, user)
|
||||
for(var/obj/item/stack/spacecash/money in src.loc.contents)
|
||||
ID.attackby(money, user)
|
||||
for(var/obj/item/coin/money in src.loc.contents)
|
||||
ID.attackby(money, user)
|
||||
|
||||
/obj/item/holochip/AltClick(mob/user)
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
|
||||
@@ -91,4 +91,4 @@
|
||||
return ..()
|
||||
|
||||
/obj/effect/abstract/sync_holder/AllowDrop()
|
||||
return TRUE //no dropping spaghetti out of your spacetime pocket
|
||||
return TRUE //no dropping spaghetti out of your spacetime pocket
|
||||
|
||||
@@ -29,4 +29,4 @@
|
||||
if(uses == 0)
|
||||
icon_state = "glue_used"
|
||||
name = "empty bottle of super glue"
|
||||
return
|
||||
return
|
||||
|
||||
@@ -62,4 +62,4 @@
|
||||
name = "clown's megaphone"
|
||||
desc = "Something that should not exist."
|
||||
icon_state = "megaphone-clown"
|
||||
voicespan = list(SPAN_CLOWN)
|
||||
voicespan = list(SPAN_CLOWN)
|
||||
|
||||
@@ -21,13 +21,13 @@
|
||||
force = 5
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
tool_behaviour = TOOL_MULTITOOL
|
||||
item_flags = SURGICAL_TOOL
|
||||
throwforce = 0
|
||||
throw_range = 7
|
||||
throw_speed = 3
|
||||
custom_materials = list(/datum/material/iron=50, /datum/material/glass=20)
|
||||
var/obj/machinery/buffer // simple machine buffer for device linkage
|
||||
toolspeed = 1
|
||||
tool_behaviour = TOOL_MULTITOOL
|
||||
usesound = 'sound/weapons/empty.ogg'
|
||||
var/datum/integrated_io/selected_io = null //functional for integrated circuits.
|
||||
var/mode = 0
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
/obj/item/paicard/Initialize()
|
||||
SSpai.pai_card_list += src
|
||||
add_overlay("pai-off")
|
||||
AddElement(/datum/element/bed_tuckable, 6, -5, 90)
|
||||
return ..()
|
||||
|
||||
/obj/item/paicard/Destroy()
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
else
|
||||
if(zero_amount())
|
||||
return
|
||||
chosen_circuit = input("What type of circuit would you like to remove?", "Choose a Circuit Type", chosen_circuit) in list("airlock","firelock","fire alarm","air alarm","APC")
|
||||
if(zero_amount())
|
||||
chosen_circuit = input("What type of circuit would you like to remove?", "Choose a Circuit Type", chosen_circuit) as null|anything in list("airlock","firelock","fire alarm","air alarm","APC")
|
||||
if(zero_amount() || !chosen_circuit || !in_range(src,user))
|
||||
return
|
||||
switch(chosen_circuit)
|
||||
if("airlock")
|
||||
|
||||
@@ -16,9 +16,9 @@ GLOBAL_LIST_EMPTY(power_sinks)
|
||||
throw_speed = 1
|
||||
throw_range = 2
|
||||
custom_materials = list(/datum/material/iron=750)
|
||||
var/drain_rate = 1600000 // amount of power to drain per tick
|
||||
var/drain_rate = 2000000 // amount of power to drain per tick. Currently 2MJ.
|
||||
var/power_drained = 0 // has drained this much power
|
||||
var/max_power = 1e10 // maximum power that can be drained before exploding
|
||||
var/max_power = 2000000000 // maximum power that can be drained before exploding. Currently 2GJ. About 17 minutes to explode at the max rate.
|
||||
var/mode = 0 // 0 = off, 1=clamped (off), 2=operating
|
||||
var/admins_warned = FALSE // stop spam, only warn the admins once that we are about to boom
|
||||
|
||||
@@ -155,5 +155,5 @@ GLOBAL_LIST_EMPTY(power_sinks)
|
||||
|
||||
if(power_drained >= max_power)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
explosion(src.loc, 4,8,16,32)
|
||||
explosion(src.loc, 3,7,14,28)
|
||||
qdel(src)
|
||||
|
||||
@@ -155,7 +155,7 @@ GENETICS SCANNER
|
||||
if(oxy_loss > 10)
|
||||
msg += "\n\t<span class='info'><span class='alert'>[oxy_loss > 50 ? "Severe" : "Minor"] oxygen deprivation detected.</span>"
|
||||
if(tox_loss > 10)
|
||||
msg += "\n\t<span class='alert'>[tox_loss > 50 ? "Severe" : "Minor"] amount of toxin damage detected.</span>"
|
||||
msg += "\n\t<span class='alert'>[tox_loss > 50 ? "Severe" : "Minor"] amount of [HAS_TRAIT(M, TRAIT_ROBOTIC_ORGANISM) ? "system corruption" : "toxin damage"] detected.</span>"
|
||||
if(M.getStaminaLoss())
|
||||
msg += "\n\t<span class='alert'>Subject appears to be suffering from fatigue.</span>"
|
||||
if(advanced)
|
||||
@@ -182,7 +182,7 @@ GENETICS SCANNER
|
||||
<td style='width: 90px;'><font color='#0000CC'>Damage:</font></td>\
|
||||
<td style='width: 55px;'><font color='red'><b>Brute</b></font></td>\
|
||||
<td style='width: 45px;'><font color='orange'><b>Burn</b></font></td>\
|
||||
<td style='width: 45px;'><font color='green'><b>Toxin</b></font></td>\
|
||||
<td style='width: 45px;'><font color='green'><b>[HAS_TRAIT(C, TRAIT_ROBOTIC_ORGANISM) ? "Corruption" :"Toxin"]</b></font></td>\
|
||||
<td style='width: 90px;'><font color='purple'><b>Suffocation</b></font></td></tr>\
|
||||
<tr><td><font color='#0000CC'>Overall:</font></td>\
|
||||
<td><font color='red'>[brute_loss]</font></td>\
|
||||
@@ -628,9 +628,9 @@ GENETICS SCANNER
|
||||
var/turf/location = get_turf(user)
|
||||
if(!istype(location))
|
||||
return
|
||||
|
||||
|
||||
scan_turf(user, location)
|
||||
|
||||
|
||||
/obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -264,6 +264,30 @@ effective or pretty fucking useless.
|
||||
GLOB.active_jammers -= src
|
||||
update_icon()
|
||||
|
||||
/*portable turret*/
|
||||
/obj/item/storage/toolbox/emergency/turret
|
||||
desc = "You feel a strange urge to hit this with a wrench."
|
||||
|
||||
/obj/item/storage/toolbox/emergency/turret/PopulateContents()
|
||||
new /obj/item/screwdriver(src)
|
||||
new /obj/item/wrench(src)
|
||||
new /obj/item/weldingtool(src)
|
||||
new /obj/item/crowbar(src)
|
||||
new /obj/item/analyzer(src)
|
||||
new /obj/item/wirecutters(src)
|
||||
|
||||
/obj/item/storage/toolbox/emergency/turret/attackby(obj/item/I, mob/living/user, params)
|
||||
if(I.tool_behaviour == TOOL_WRENCH && user.a_intent == INTENT_HARM)
|
||||
user.visible_message("<span class='danger'>[user] bashes [src] with [I]!</span>", \
|
||||
"<span class='danger'>You bash [src] with [I]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
playsound(src, "sound/items/drill_use.ogg", 80, TRUE, -1)
|
||||
var/obj/machinery/porta_turret/syndicate/pod/toolbox/turret = new(get_turf(loc))
|
||||
turret.faction = list("[REF(user)]")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/headsetupgrader
|
||||
name = "headset upgrader"
|
||||
desc = "A tool that can be used to upgrade a normal headset to be able to protect from flashbangs."
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
* Gifts
|
||||
*/
|
||||
|
||||
/var/static/blacklisted_items = typecacheof(list(
|
||||
GLOBAL_LIST_INIT(gift_item_blacklist, typecacheof(list(
|
||||
/obj/effect,
|
||||
/obj/belly,
|
||||
/obj/mafia_game_board,
|
||||
/obj/docking_port,
|
||||
/obj/shapeshift_holder,
|
||||
/obj/screen))
|
||||
/obj/screen
|
||||
)))
|
||||
|
||||
GLOBAL_LIST_EMPTY(possible_gifts)
|
||||
|
||||
@@ -103,7 +104,7 @@ GLOBAL_LIST_EMPTY(possible_gifts)
|
||||
var/list/gift_types_list = subtypesof(/obj/item)
|
||||
for(var/V in gift_types_list)
|
||||
var/obj/item/I = V
|
||||
if((!initial(I.icon_state)) || (!initial(I.item_state)) || (initial(I.item_flags) & ABSTRACT) || (is_type_in_typecache(I, blacklisted_items)))
|
||||
if((!initial(I.icon_state)) || (!initial(I.item_state)) || (initial(I.item_flags) & ABSTRACT) || (is_type_in_typecache(I, GLOB.gift_item_blacklist)))
|
||||
gift_types_list -= V
|
||||
GLOB.possible_gifts = gift_types_list
|
||||
var/gift_type = pick(GLOB.possible_gifts)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
var/boom_sizes = list(0, 0, 3)
|
||||
var/can_attach_mob = FALSE
|
||||
var/full_damage_on_mobs = FALSE
|
||||
var/can_gib_mobs = FALSE
|
||||
|
||||
/obj/item/grenade/plastic/Initialize()
|
||||
. = ..()
|
||||
@@ -72,7 +73,7 @@
|
||||
explosion(get_step(T, aim_dir), boom_sizes[1], boom_sizes[2], boom_sizes[3])
|
||||
else
|
||||
explosion(location, boom_sizes[1], boom_sizes[2], boom_sizes[3])
|
||||
if(ismob(target))
|
||||
if(ismob(target) && can_gib_mobs)
|
||||
var/mob/M = target
|
||||
M.gib()
|
||||
qdel(src)
|
||||
|
||||
@@ -377,10 +377,3 @@
|
||||
hitsound = 'sound/weapons/taserhit.ogg'
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
breakouttime = 60
|
||||
|
||||
/obj/item/restraints/legcuffs/bola/energy/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
if(iscarbon(hit_atom))
|
||||
var/obj/item/restraints/legcuffs/beartrap/B = new /obj/item/restraints/legcuffs/beartrap/energy/cyborg(get_turf(hit_atom))
|
||||
B.Crossed(hit_atom)
|
||||
qdel(src)
|
||||
..()
|
||||
|
||||
@@ -96,4 +96,4 @@
|
||||
if(implant?.imp_in)
|
||||
qdel(implant)
|
||||
else
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
@@ -66,4 +66,4 @@
|
||||
|
||||
/obj/item/implanter/radio/syndicate
|
||||
name = "implanter (internal syndicate radio)"
|
||||
imp_type = /obj/item/implant/radio/syndicate
|
||||
imp_type = /obj/item/implant/radio/syndicate
|
||||
|
||||
@@ -73,4 +73,4 @@
|
||||
/obj/item/implantcase/track
|
||||
name = "implant case - 'Tracking'"
|
||||
desc = "A glass case containing a tracking implant."
|
||||
imp_type = /obj/item/implant/tracking
|
||||
imp_type = /obj/item/implant/tracking
|
||||
|
||||
@@ -77,4 +77,4 @@
|
||||
|
||||
/obj/item/implanter/hijack
|
||||
name = "implanter (hijack)"
|
||||
imp_type = /obj/item/implant/hijack
|
||||
imp_type = /obj/item/implant/hijack
|
||||
|
||||
@@ -175,7 +175,7 @@
|
||||
|
||||
/obj/item/kitchen/knife/combat/survival/knuckledagger/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/butchering, 50, 120, 5) // it's good for butchering stuff
|
||||
AddComponent(/datum/component/butchering, 30, 130, 20) // it's good for butchering stuff
|
||||
|
||||
/obj/item/kitchen/knife/combat/survival/knuckledagger/ui_action_click(mob/user, actiontype)
|
||||
light_on = !light_on
|
||||
@@ -189,6 +189,11 @@
|
||||
else
|
||||
set_light(0)
|
||||
|
||||
/obj/item/kitchen/knife/combat/survival/knuckledagger/update_overlays()
|
||||
. = ..()
|
||||
if(light_on)
|
||||
. += "[icon_state]_lit"
|
||||
|
||||
/obj/item/kitchen/knife/combat/bone
|
||||
name = "bone dagger"
|
||||
item_state = "bone_dagger"
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
/obj/item/caution
|
||||
desc = "Caution! Wet Floor!"
|
||||
name = "wet floor sign"
|
||||
icon = 'icons/obj/janitor.dmi'
|
||||
icon_state = "caution"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
|
||||
force = 1
|
||||
throwforce = 3
|
||||
throw_speed = 2
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
attack_verb = list("warned", "cautioned", "smashed")
|
||||
|
||||
/obj/item/choice_beacon
|
||||
name = "choice beacon"
|
||||
desc = "Hey, why are you viewing this?!! Please let Centcom know about this odd occurance."
|
||||
@@ -52,7 +38,8 @@
|
||||
|
||||
/obj/item/choice_beacon/proc/spawn_option(atom/choice,mob/living/M)
|
||||
var/obj/new_item = create_choice_atom(choice, M)
|
||||
var/obj/structure/closet/supplypod/bluespacepod/pod = new()
|
||||
var/area/pod_storage_area = locate(/area/centcom/supplypod/podStorage) in GLOB.sortedAreas
|
||||
var/obj/structure/closet/supplypod/bluespacepod/pod = new(pick(get_area_turfs(pod_storage_area))) //Lets just have it in the pod storage zone for a really short time because we don't want it in nullspace
|
||||
pod.explosionSize = list(0,0,0,0)
|
||||
new_item.forceMove(pod)
|
||||
var/msg = "<span class='danger'>After making your selection, you notice a strange target on the ground. It might be best to step back!</span>"
|
||||
|
||||
@@ -24,13 +24,17 @@
|
||||
create_reagents(mopcap, NONE, NO_REAGENTS_VALUE)
|
||||
|
||||
|
||||
/obj/item/mop/proc/clean(turf/A)
|
||||
/obj/item/mop/proc/clean(turf/A, mob/user)
|
||||
if(reagents.has_reagent(/datum/reagent/water, 1) || reagents.has_reagent(/datum/reagent/water/holywater, 1) || reagents.has_reagent(/datum/reagent/consumable/ethanol/vodka, 1) || reagents.has_reagent(/datum/reagent/space_cleaner, 1))
|
||||
SEND_SIGNAL(A, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
|
||||
A.clean_blood()
|
||||
var/cleaned_something = FALSE
|
||||
for(var/obj/effect/O in A)
|
||||
if(is_cleanable(O))
|
||||
cleaned_something = TRUE
|
||||
qdel(O)
|
||||
if(cleaned_something && user && user.client)
|
||||
user.client.increment_progress("janitor", 1)
|
||||
reagents.reaction(A, TOUCH, 10) //Needed for proper floor wetting.
|
||||
reagents.remove_any(1) //reaction() doesn't use up the reagents
|
||||
|
||||
@@ -59,7 +63,7 @@
|
||||
if(!L.UseStaminaBuffer(stamusage, warn = TRUE))
|
||||
return
|
||||
user.visible_message("[user] cleans \the [T] with [src].", "<span class='notice'>You clean \the [T] with [src].</span>")
|
||||
clean(T)
|
||||
clean(T, user)
|
||||
user.DelayNextAction(CLICK_CD_MELEE)
|
||||
user.do_attack_animation(T, used_item = src)
|
||||
playsound(T, "slosh", 50, 1)
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
//--end of love :'(--
|
||||
|
||||
var/snowflake_id //if we set from a config snowflake plushie.
|
||||
/// wrapper, do not use, read only
|
||||
var/__ADMIN_SET_TO_ID
|
||||
var/can_random_spawn = TRUE //if this is FALSE, don't spawn this for random plushies.
|
||||
|
||||
/obj/item/toy/plush/random_snowflake/Initialize(mapload, set_snowflake_id)
|
||||
@@ -46,6 +48,7 @@
|
||||
/obj/item/toy/plush/Initialize(mapload, set_snowflake_id)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/squeak, squeak_override)
|
||||
AddElement(/datum/element/bed_tuckable, 6, -5, 90)
|
||||
|
||||
//have we decided if Pinocchio goes in the blue or pink aisle yet?
|
||||
if(gender == NEUTER)
|
||||
@@ -112,10 +115,21 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/toy/plush/vv_get_var(var_name)
|
||||
if(var_name == NAMEOF(src, __ADMIN_SET_TO_ID))
|
||||
return debug_variable("__ADMIN: SET SNOWFLAKE ID", snowflake_id, 0, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/toy/plush/vv_edit_var(var_name, var_value)
|
||||
if(var_name == NAMEOF(src, __ADMIN_SET_TO_ID))
|
||||
return set_snowflake_from_config(var_value)
|
||||
return ..()
|
||||
|
||||
/obj/item/toy/plush/proc/set_snowflake_from_config(id)
|
||||
var/list/configlist = CONFIG_GET(keyed_list/snowflake_plushies)
|
||||
var/list/jsonlist = configlist[id]
|
||||
ASSERT(jsonlist)
|
||||
if(!jsonlist)
|
||||
return FALSE
|
||||
jsonlist = json_decode(jsonlist)
|
||||
if(jsonlist["inherit_from"])
|
||||
var/path = text2path(jsonlist["inherit_from"])
|
||||
@@ -151,6 +165,7 @@
|
||||
var/datum/component/squeak/S = GetComponent(/datum/component/squeak)
|
||||
S?.override_squeak_sounds = squeak_override
|
||||
snowflake_id = id
|
||||
return TRUE
|
||||
|
||||
/obj/item/toy/plush/handle_atom_del(atom/A)
|
||||
if(A == grenade)
|
||||
|
||||
@@ -137,8 +137,7 @@
|
||||
AM.anchored = TRUE
|
||||
flick("laserbox_burn", AM)
|
||||
trigger()
|
||||
sleep(15)
|
||||
qdel(AM)
|
||||
QDEL_IN(src, 15)
|
||||
|
||||
// snowflake code until undertile elements
|
||||
/obj/item/pressure_plate/hologrid/hide()
|
||||
|
||||
@@ -321,4 +321,4 @@
|
||||
desc = "A rusted claymore, once at the heart of a powerful scottish clan struck down and oppressed by tyrants, it has been passed down the ages as a symbol of defiance."
|
||||
force = 15
|
||||
block_chance = 30
|
||||
armour_penetration = 5
|
||||
armour_penetration = 5
|
||||
|
||||
@@ -326,6 +326,9 @@
|
||||
else if(istype(W, /obj/item/borg/upgrade/ai))
|
||||
var/obj/item/borg/upgrade/ai/M = W
|
||||
if(check_completion())
|
||||
if(!chest.cell)
|
||||
to_chat(user, "<span class='warning'>The endoskeleton still needs a power cell!</span>")
|
||||
return
|
||||
if(!isturf(loc))
|
||||
to_chat(user, "<span class='warning'>You cannot install[M], the frame has to be standing on the ground to be perfectly precise!</span>")
|
||||
return
|
||||
@@ -346,7 +349,6 @@
|
||||
O.lawupdate = FALSE
|
||||
O.make_laws()
|
||||
|
||||
|
||||
O.cell = chest.cell
|
||||
chest.cell.forceMove(O)
|
||||
chest.cell = null
|
||||
@@ -392,6 +394,7 @@
|
||||
created_name = new_name
|
||||
else
|
||||
created_name = ""
|
||||
log_game("[key_name(usr)] renamed [src] ([REF(src)]) to [created_name].")
|
||||
|
||||
else if(href_list["Master"])
|
||||
forced_ai = select_active_ai(usr)
|
||||
|
||||
@@ -80,6 +80,7 @@ as performing this in action() will cause the upgrade to end up in the borg inst
|
||||
desc = "Used to kick in a cyborg's VTEC systems, increasing their speed."
|
||||
icon_state = "cyborg_upgrade2"
|
||||
require_module = 1
|
||||
var/obj/effect/proc_holder/silicon/cyborg/vtecControl/VC
|
||||
|
||||
/obj/item/borg/upgrade/vtec/action(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
@@ -91,12 +92,14 @@ as performing this in action() will cause the upgrade to end up in the borg inst
|
||||
|
||||
//R.speed = -2 // Gotta go fast.
|
||||
//Citadel change - makes vtecs give an ability rather than reducing the borg's speed instantly
|
||||
R.AddAbility(new/obj/effect/proc_holder/silicon/cyborg/vtecControl)
|
||||
VC = new /obj/effect/proc_holder/silicon/cyborg/vtecControl
|
||||
R.AddAbility(VC)
|
||||
R.cansprint = 0
|
||||
|
||||
/obj/item/borg/upgrade/vtec/deactivate(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
if (.)
|
||||
R.RemoveAbility(VC)
|
||||
R.speed = initial(R.speed)
|
||||
R.cansprint = 1
|
||||
|
||||
|
||||
@@ -33,6 +33,20 @@
|
||||
. = ..()
|
||||
update_desc()
|
||||
|
||||
/obj/item/stack/spacecash/attackby(obj/item/W, mob/user, params)
|
||||
. = ..()
|
||||
if(istype(W, /obj/item/card/id))
|
||||
var/obj/item/card/id/ID = W
|
||||
if(!ID.registered_account)
|
||||
to_chat(user, "<span class='warning'>[ID] doesn't have a linked account to deposit into!</span>")
|
||||
return
|
||||
for(var/obj/item/holochip/money in src.loc.contents)
|
||||
ID.attackby(money, user)
|
||||
for(var/obj/item/stack/spacecash/money in src.loc.contents)
|
||||
ID.attackby(money, user)
|
||||
for(var/obj/item/coin/money in src.loc.contents)
|
||||
ID.attackby(money, user)
|
||||
|
||||
/obj/item/stack/spacecash/c1
|
||||
icon_state = "spacecash"
|
||||
singular_name = "one credit bill"
|
||||
|
||||
@@ -173,11 +173,11 @@
|
||||
"<span class='italics'>You hear cutting.</span>")
|
||||
use(2)
|
||||
else if(I.is_drainable() && I.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine))
|
||||
if(!I.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine, 10))
|
||||
if(!I.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine, 5))
|
||||
to_chat(user, "<span class='warning'>There's not enough sterilizine in [I] to sterilize [src]!</span>")
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] pours the contents of [I] onto [src], sterilizing it.</span>", "<span class='notice'>You pour the contents of [I] onto [src], sterilizing it.</span>")
|
||||
I.reagents.remove_reagent(/datum/reagent/space_cleaner/sterilizine, 10)
|
||||
user.visible_message("<span class='notice'>[user] sterilizes [src] with the contents of [I].</span>", "<span class='notice'>You pour the contents of [I] onto [src], sterilizing it.</span>")
|
||||
I.reagents.remove_reagent(/datum/reagent/space_cleaner/sterilizine, 5)
|
||||
new /obj/item/stack/medical/gauze/adv/one(user.drop_location())
|
||||
use(1)
|
||||
else
|
||||
@@ -187,6 +187,9 @@
|
||||
user.visible_message("<span class='suicide'>[user] begins tightening \the [src] around [user.p_their()] neck! It looks like [user.p_they()] forgot how to use medical supplies!</span>")
|
||||
return OXYLOSS
|
||||
|
||||
/obj/item/stack/medical/gauze/one
|
||||
amount = 1
|
||||
|
||||
/obj/item/stack/medical/gauze/improvised
|
||||
name = "improvised gauze"
|
||||
singular_name = "improvised gauze"
|
||||
@@ -204,8 +207,9 @@
|
||||
heal_brute = 6
|
||||
self_delay = 45
|
||||
other_delay = 15
|
||||
absorption_rate = 0.4
|
||||
absorption_capacity = 6
|
||||
absorption_rate = 0.5
|
||||
absorption_capacity = 12
|
||||
splint_factor = 0.15
|
||||
|
||||
/obj/item/stack/medical/gauze/adv/one
|
||||
amount = 1
|
||||
|
||||
@@ -388,4 +388,4 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
|
||||
|
||||
/obj/item/shard/plasma/alien
|
||||
name = "alien shard"
|
||||
desc = "A nasty looking shard of advanced alloy glass."
|
||||
desc = "A nasty looking shard of advanced alloy glass."
|
||||
|
||||
@@ -253,7 +253,6 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
|
||||
new/datum/stack_recipe("painting frame", /obj/item/wallframe/painting, 1, time = 10),\
|
||||
new/datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40), \
|
||||
new/datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 15),\
|
||||
new/datum/stack_recipe("training bokken", /obj/item/melee/bokken, 10, time = 15),\
|
||||
null, \
|
||||
new/datum/stack_recipe("wooden chair", /obj/structure/chair/wood/, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
|
||||
new/datum/stack_recipe("winged wooden chair", /obj/structure/chair/wood/wings, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
|
||||
@@ -388,6 +387,8 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
|
||||
new/datum/stack_recipe("mining satchel", /obj/item/storage/bag/ore, 4), \
|
||||
new/datum/stack_recipe("chemistry bag", /obj/item/storage/bag/chemistry, 4), \
|
||||
new/datum/stack_recipe("bio bag", /obj/item/storage/bag/bio, 4), \
|
||||
new/datum/stack_recipe("material bag", /obj/item/storage/bag/material, 4), \
|
||||
new/datum/stack_recipe("construction bag", /obj/item/storage/bag/construction, 4), \
|
||||
null, \
|
||||
new/datum/stack_recipe("string", /obj/item/weaponcrafting/string, 1, time = 10), \
|
||||
new/datum/stack_recipe("improvised gauze", /obj/item/stack/medical/gauze/improvised, 1, 2, 6), \
|
||||
@@ -793,7 +794,7 @@ GLOBAL_LIST_INIT(plastic_recipes, list(
|
||||
new /datum/stack_recipe("shower curtain", /obj/structure/curtain, 10, time = 10, one_per_turf = 1, on_floor = 1), \
|
||||
new /datum/stack_recipe("duct", /obj/item/stack/ducts,1), \
|
||||
new /datum/stack_recipe("laser pointer case", /obj/item/glasswork/glass_base/laserpointer_shell, 30), \
|
||||
new /datum/stack_recipe("wet floor sign", /obj/item/caution, 2)))
|
||||
new /datum/stack_recipe("wet floor sign", /obj/item/clothing/suit/caution, 2)))
|
||||
|
||||
/obj/item/stack/sheet/plastic
|
||||
name = "plastic"
|
||||
|
||||
@@ -457,6 +457,9 @@
|
||||
STR.display_numerical_stacking = FALSE
|
||||
STR.can_hold = typecacheof(list(/obj/item/ammo_box/magazine, /obj/item/ammo_casing))
|
||||
|
||||
/*
|
||||
Bag for holding materials
|
||||
*/
|
||||
/obj/item/storage/bag/material
|
||||
name = "material pouch"
|
||||
desc = "A pouch for sheets and RCD ammunition that manages to hang where you would normally put things in your pocket."
|
||||
@@ -474,3 +477,24 @@
|
||||
STR.max_items = 2
|
||||
STR.display_numerical_stacking = TRUE
|
||||
STR.can_hold = typecacheof(list(/obj/item/rcd_ammo, /obj/item/stack/sheet))
|
||||
|
||||
/*
|
||||
* Construction bag (for engineering, holds stock parts and electronics)
|
||||
*/
|
||||
|
||||
/obj/item/storage/bag/construction
|
||||
name = "construction bag"
|
||||
icon = 'icons/obj/tools.dmi'
|
||||
icon_state = "construction_bag"
|
||||
desc = "A bag for storing small construction components."
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
/obj/item/storage/bag/construction/ComponentInitialize()
|
||||
. = ..()
|
||||
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
|
||||
STR.max_combined_w_class = 100
|
||||
STR.max_items = 50
|
||||
STR.max_w_class = WEIGHT_CLASS_SMALL
|
||||
STR.insert_preposition = "in"
|
||||
STR.can_hold = typecacheof(list(/obj/item/stack/ore/bluespace_crystal, /obj/item/assembly, /obj/item/stock_parts, /obj/item/reagent_containers/glass/beaker, /obj/item/stack/cable_coil, /obj/item/circuitboard, /obj/item/electronics,/obj/item/wallframe/camera))
|
||||
|
||||
@@ -802,7 +802,8 @@
|
||||
. += "<span class='notice'>Alt-click it to quickly draw the blade.</span>"
|
||||
|
||||
/obj/item/storage/belt/sabre/PopulateContents()
|
||||
new starting_sword(src)
|
||||
if(starting_sword)
|
||||
new starting_sword(src)
|
||||
|
||||
/obj/item/storage/belt/sabre/rapier
|
||||
name = "rapier sheath"
|
||||
@@ -853,8 +854,8 @@
|
||||
/obj/item/storage/belt/sabre/twin
|
||||
name = "twin sheath"
|
||||
desc = "Two sheaths. One is capable of holding a katana (or bokken) and the other a wakizashi. You could put two wakizashis in if you really wanted to. Now you can really roleplay as a samurai."
|
||||
icon_state = "twinsheath"
|
||||
item_state = "quiver" //this'll do.
|
||||
icon_state = "2sheath"
|
||||
item_state = "katana" //this'll do.
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
fitting_swords = list(/obj/item/melee/smith/wakizashi, /obj/item/melee/smith/twohand/katana, /obj/item/melee/bokken)
|
||||
starting_sword = null
|
||||
@@ -864,6 +865,43 @@
|
||||
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
|
||||
STR.max_items = 2
|
||||
STR.max_w_class = WEIGHT_CLASS_BULKY + WEIGHT_CLASS_NORMAL //katana and waki.
|
||||
STR.max_combined_w_class = 7
|
||||
|
||||
/obj/item/melee/smith/twohand/katana/on_exit_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/twin/B = S.parent
|
||||
if(istype(B))
|
||||
playsound(B, 'sound/items/unsheath.ogg', 25, 1)
|
||||
. = ..()
|
||||
|
||||
/obj/item/melee/smith/twohand/katana/on_enter_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/twin/B = S.parent
|
||||
if(istype(B))
|
||||
playsound(B, 'sound/items/sheath.ogg', 25, 1)
|
||||
. = ..()
|
||||
|
||||
/obj/item/melee/smith/wakizashi/on_exit_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/twin/B = S.parent
|
||||
if(istype(B))
|
||||
playsound(B, 'sound/items/unsheath.ogg', 25, 1)
|
||||
. = ..()
|
||||
|
||||
/obj/item/melee/smith/wakizashi/on_enter_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/twin/B = S.parent
|
||||
if(istype(B))
|
||||
playsound(B, 'sound/items/sheath.ogg', 25, 1)
|
||||
. = ..()
|
||||
|
||||
/obj/item/melee/bokken/on_exit_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/twin/B = S.parent
|
||||
if(istype(B))
|
||||
playsound(B, 'sound/items/unsheath.ogg', 25, 1)
|
||||
. = ..()
|
||||
|
||||
/obj/item/melee/bokken/on_enter_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/twin/B = S.parent
|
||||
if(istype(B))
|
||||
playsound(B, 'sound/items/sheath.ogg', 25, 1)
|
||||
. = ..()
|
||||
|
||||
/obj/item/storage/belt/plant
|
||||
name = "botanical belt"
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
|
||||
/obj/item/storage/fancy
|
||||
icon = 'icons/obj/food/containers.dmi'
|
||||
icon_state = "donutbox6"
|
||||
name = "donut box"
|
||||
desc = "Mmm. Donuts."
|
||||
resistance_flags = FLAMMABLE
|
||||
var/icon_type = "donut"
|
||||
var/spawn_type = null
|
||||
@@ -59,18 +56,22 @@
|
||||
fancy_open = TRUE
|
||||
update_icon()
|
||||
|
||||
#define DONUT_INBOX_SPRITE_WIDTH 3
|
||||
|
||||
/*
|
||||
* Donut Box
|
||||
*/
|
||||
|
||||
/obj/item/storage/fancy/donut_box
|
||||
icon = 'icons/obj/food/containers.dmi'
|
||||
icon_state = "donutbox6"
|
||||
icon_type = "donut"
|
||||
name = "donut box"
|
||||
desc = "Mmm. Donuts."
|
||||
icon = 'icons/obj/food/donut.dmi'
|
||||
icon_state = "donutbox_inner"
|
||||
icon_type = "donut"
|
||||
spawn_type = /obj/item/reagent_containers/food/snacks/donut
|
||||
fancy_open = TRUE
|
||||
custom_price = PRICE_NORMAL
|
||||
appearance_flags = KEEP_TOGETHER
|
||||
|
||||
/obj/item/storage/fancy/donut_box/ComponentInitialize()
|
||||
. = ..()
|
||||
@@ -78,6 +79,36 @@
|
||||
STR.max_items = 6
|
||||
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/donut))
|
||||
|
||||
/obj/item/storage/fancy/donut_box/PopulateContents()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/storage/fancy/donut_box/update_icon_state()
|
||||
if(fancy_open)
|
||||
icon_state = "donutbox_inner"
|
||||
else
|
||||
icon_state = "donutbox"
|
||||
|
||||
/obj/item/storage/fancy/donut_box/update_overlays()
|
||||
. = ..()
|
||||
|
||||
if (!fancy_open)
|
||||
return
|
||||
|
||||
var/donuts = 0
|
||||
|
||||
for (var/_donut in contents)
|
||||
var/obj/item/reagent_containers/food/snacks/donut/donut = _donut
|
||||
if (!istype(donut))
|
||||
continue
|
||||
|
||||
. += image(icon = initial(icon), icon_state = donut.in_box_sprite(), pixel_x = donuts * DONUT_INBOX_SPRITE_WIDTH)
|
||||
donuts += 1
|
||||
|
||||
. += image(icon = initial(icon), icon_state = "donutbox_top")
|
||||
|
||||
#undef DONUT_INBOX_SPRITE_WIDTH
|
||||
|
||||
/*
|
||||
* Egg Box
|
||||
*/
|
||||
|
||||
@@ -103,6 +103,39 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
|
||||
/obj/item/storage/toolbox/mechanical/old/heirloom/PopulateContents()
|
||||
return
|
||||
|
||||
/obj/item/storage/toolbox/mechanical/old/clean // the assistant traitor toolbox, damage scales with TC inside
|
||||
name = "toolbox"
|
||||
desc = "An old, blue toolbox. It menaces with a sickening miasma of robust energies. You sure about this, Brain?"
|
||||
icon_state = "toolbox_blue_clean"
|
||||
force = 19
|
||||
throwforce = 22
|
||||
wound_bonus = 0
|
||||
bare_wound_bonus = 10
|
||||
|
||||
/obj/item/storage/toolbox/mechanical/old/clean/proc/calc_damage()
|
||||
var/power = 0
|
||||
for (var/obj/item/stack/telecrystal/TC in GetAllContents())
|
||||
power += TC.amount
|
||||
force = 19 + power
|
||||
throwforce = 22 + power
|
||||
|
||||
/obj/item/storage/toolbox/mechanical/old/clean/attack(mob/target, mob/living/user)
|
||||
calc_damage() // one damage for one telecrystal equals about thirty seven(?) damage if you pour ALL your tc
|
||||
..()
|
||||
|
||||
/obj/item/storage/toolbox/mechanical/old/clean/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
calc_damage()
|
||||
..()
|
||||
|
||||
/obj/item/storage/toolbox/mechanical/old/clean/PopulateContents()
|
||||
new /obj/item/screwdriver(src)
|
||||
new /obj/item/wrench(src)
|
||||
new /obj/item/weldingtool(src)
|
||||
new /obj/item/crowbar(src)
|
||||
new /obj/item/wirecutters(src)
|
||||
new /obj/item/multitool(src)
|
||||
new /obj/item/clothing/gloves/color/yellow(src)
|
||||
|
||||
/obj/item/storage/toolbox/electrical
|
||||
name = "electrical toolbox"
|
||||
icon_state = "yellow"
|
||||
|
||||
@@ -520,3 +520,9 @@
|
||||
new /obj/item/storage/fancy/cigarettes/cigpack_syndicate(src)
|
||||
new /obj/item/lighter(src)
|
||||
|
||||
/obj/item/storage/box/syndie_kit/scarp
|
||||
|
||||
/obj/item/storage/box/syndie_kit/scarp/PopulateContents()
|
||||
new /obj/item/book/granter/martial/carp(src)
|
||||
new /obj/item/clothing/suit/hooded/carp_costume(src)
|
||||
new /obj/item/staff/bostaff(src)
|
||||
|
||||
@@ -198,4 +198,4 @@
|
||||
|
||||
/obj/item/tank/internals/methyl_bromide/populate_gas()
|
||||
air_contents.set_moles(/datum/gas/methyl_bromide, (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
|
||||
return
|
||||
return
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
usesound = 'sound/items/crowbar.ogg'
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
item_flags = SURGICAL_TOOL
|
||||
force = 5
|
||||
throwforce = 7
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
@@ -107,4 +108,4 @@
|
||||
icon = 'icons/obj/advancedtools.dmi'
|
||||
usesound = 'sound/weapons/sonic_jackhammer.ogg'
|
||||
icon_state = "crowbar"
|
||||
toolspeed = 0.2
|
||||
toolspeed = 0.2
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
item_flags = SURGICAL_TOOL
|
||||
force = 5
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
throwforce = 5
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
item_flags = SURGICAL_TOOL
|
||||
force = 3
|
||||
throwforce = 5
|
||||
hitsound = "swing_hit"
|
||||
@@ -22,14 +23,15 @@
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
var/self_fueling = FALSE //Do we refill ourselves or not
|
||||
var/nextrefueltick = 0 // How long it takes before we get a new fuel unit
|
||||
var/nextrefueltick = 0 //When is the next tick we refuel?
|
||||
var/refueling_interval = 10 //Every how many processing ticks does this refuel? (1 = every processing tick)
|
||||
|
||||
custom_materials = list(/datum/material/iron=70, /datum/material/glass=30)
|
||||
var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2)
|
||||
var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower)
|
||||
var/max_fuel = 20 //The max amount of fuel the welder can hold
|
||||
var/change_icons = 1
|
||||
var/can_off_process = 0
|
||||
var/can_off_process = FALSE
|
||||
var/light_intensity = 2 //how powerful the emitted light is when used.
|
||||
var/progress_flash_divisor = 10
|
||||
var/burned_fuel_for = 0 //when fuel was last removed
|
||||
@@ -65,6 +67,14 @@
|
||||
. += "[initial(icon_state)]-on"
|
||||
|
||||
/obj/item/weldingtool/process()
|
||||
//This handles refueling. Its looking at how much fuel the tool has and comparing that to how much it holds
|
||||
//This then looks if the refuel tick has come based on world time.
|
||||
//Then looks if we refuel ourselves or not.
|
||||
|
||||
if(self_fueling && get_fuel() < max_fuel && nextrefueltick <= world.time)
|
||||
nextrefueltick = world.time + refueling_interval
|
||||
reagents.add_reagent(/datum/reagent/fuel, 1)
|
||||
|
||||
switch(welding)
|
||||
if(0)
|
||||
force = 3
|
||||
@@ -85,14 +95,6 @@
|
||||
//This is to start fires. process() is only called if the welder is on.
|
||||
open_flame()
|
||||
|
||||
//This handles refueling. Its looking at how much fuel the tool has and comparing that to how much it holds
|
||||
//This then looks if the refuel tick has come based on world time.
|
||||
//Then looks if we refuel ourselves or not.
|
||||
|
||||
if(get_fuel() < max_fuel && nextrefueltick < world.time && self_fueling)
|
||||
nextrefueltick = world.time + 10
|
||||
reagents.add_reagent(/datum/reagent/fuel, 1)
|
||||
|
||||
/obj/item/weldingtool/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return (FIRELOSS)
|
||||
@@ -366,7 +368,7 @@
|
||||
custom_materials = list(/datum/material/iron=70, /datum/material/glass=120)
|
||||
change_icons = 0
|
||||
self_fueling = TRUE
|
||||
can_off_process = 1
|
||||
can_off_process = TRUE
|
||||
light_intensity = 1
|
||||
toolspeed = 0.5
|
||||
|
||||
@@ -374,6 +376,7 @@
|
||||
name = "brass welding tool"
|
||||
desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch."
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
refueling_interval = 5
|
||||
icon_state = "clockwelder"
|
||||
item_state = "brasswelder"
|
||||
|
||||
@@ -383,16 +386,20 @@
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
icon_state = "welder"
|
||||
self_fueling = TRUE
|
||||
can_off_process = TRUE
|
||||
refueling_interval = 1
|
||||
toolspeed = 0.1
|
||||
light_intensity = 0
|
||||
change_icons = 0
|
||||
|
||||
/obj/item/weldingtool/advanced
|
||||
name = "advanced welding tool"
|
||||
desc = "A modern welding tool combined with an alien welding tool, it never runs out of fuel and works almost as fast."
|
||||
desc = "A modern welding tool combined with an alien welding tool, it almost never runs out of fuel and works nearly as fast."
|
||||
icon = 'icons/obj/advancedtools.dmi'
|
||||
icon_state = "welder"
|
||||
self_fueling = TRUE
|
||||
can_off_process = TRUE
|
||||
refueling_interval = 2
|
||||
toolspeed = 0.2
|
||||
light_intensity = 0
|
||||
change_icons = 0
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
item_flags = SURGICAL_TOOL
|
||||
force = 6
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
@@ -148,4 +149,4 @@
|
||||
icon = 'icons/obj/advancedtools.dmi'
|
||||
icon_state = "cutters"
|
||||
toolspeed = 0.2
|
||||
random_color = FALSE
|
||||
random_color = FALSE
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
item_flags = SURGICAL_TOOL
|
||||
force = 5
|
||||
throwforce = 7
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
@@ -128,4 +129,4 @@
|
||||
icon = 'icons/obj/advancedtools.dmi'
|
||||
icon_state = "wrench"
|
||||
usesound = 'sound/effects/empulse.ogg'
|
||||
toolspeed = 0.2
|
||||
toolspeed = 0.2
|
||||
|
||||
@@ -296,8 +296,8 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
||||
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
force = 7 //how much harm mode damage we do
|
||||
var/stamina_damage_increment = 4 //how much extra damage do we do when in non-harm mode
|
||||
force = 10 //how much harm mode damage we do
|
||||
var/stamina_damage_increment = 5 //how much extra damage do we do when in non-harm mode
|
||||
throwforce = 10
|
||||
damtype = STAMINA
|
||||
attack_verb = list("whacked", "smacked", "struck")
|
||||
@@ -310,11 +310,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
var/quick_parry = FALSE // false = default parry, true = really small parry window
|
||||
item_flags = ITEM_CAN_PARRY
|
||||
block_parry_data = /datum/block_parry_data/bokken
|
||||
var/default_parry_data = /datum/block_parry_data/bokken
|
||||
var/quick_parry_data = /datum/block_parry_data/bokken/quick_parry
|
||||
bare_wound_bonus = 0
|
||||
wound_bonus = 0
|
||||
|
||||
/datum/block_parry_data/bokken // fucked up parry data, emphasizing quicker, shorter parries
|
||||
parry_stamina_cost = 8 // be wise about when you parry, though, else you won't be able to fight enough to make it count
|
||||
parry_stamina_cost = 10 // be wise about when you parry, though, else you won't be able to fight enough to make it count
|
||||
parry_time_windup = 0
|
||||
parry_time_active = 10 // small parry window
|
||||
parry_time_spindown = 0
|
||||
@@ -330,11 +332,11 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
)
|
||||
parry_failed_stagger_duration = 3 SECONDS
|
||||
parry_data = list(
|
||||
PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5, // 7*2.5 = 17.5, 8*2.5 = 20, 9*2.5 = 22.5, 10*2.5 = 25
|
||||
PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5, // 10*2.5 = 25, 11*2.5 = 27.5, 12*2.5 = 30, 13*2.5 = 32.5
|
||||
)
|
||||
|
||||
/datum/block_parry_data/bokken/quick_parry // emphasizing REALLY SHORT PARRIES
|
||||
parry_stamina_cost = 6 // still more costly than most parries, but less than a full bokken parry
|
||||
parry_stamina_cost = 8 // still more costly than most parries, but less than a full bokken parry
|
||||
parry_time_active = 5 // REALLY small parry window
|
||||
parry_time_perfect = 2.5 // however...
|
||||
parry_time_perfect_leeway = 2 // the entire time, the parry is perfect
|
||||
@@ -371,9 +373,9 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
. = ..()
|
||||
quick_parry = !quick_parry
|
||||
if(quick_parry)
|
||||
block_parry_data = /datum/block_parry_data/bokken/quick_parry
|
||||
block_parry_data = quick_parry_data
|
||||
else
|
||||
block_parry_data = /datum/block_parry_data/bokken
|
||||
block_parry_data = default_parry_data
|
||||
to_chat(user, "<span class='notice'>[src] is now [quick_parry ? "emphasizing shorter parries, forcing you to riposte or be staggered" : "emphasizing longer parries, with a shorter window to riposte but more forgiving parries"].</span>")
|
||||
|
||||
/obj/item/melee/bokken/attackby(obj/item/I, mob/living/user, params)
|
||||
@@ -410,23 +412,76 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
if(burnt)
|
||||
. += " Burned into the \"blade\" is [burned_in]."
|
||||
|
||||
/obj/item/melee/bokken/steelwood
|
||||
name = "steelwood bokken"
|
||||
desc = "A misnomer of sorts, this is effectively a blunt katana made from steelwood, a dense organic wood derived from steelcaps. Why steelwood? Druids can use it. Duh."
|
||||
icon_state = "bokken_steel"
|
||||
item_state = "bokken_steel"
|
||||
force = 12
|
||||
stamina_damage_increment = 3
|
||||
|
||||
/obj/item/melee/bokken/waki
|
||||
name = "wakizashi bokken"
|
||||
desc = "A space-Japanese training sword made of wood and shaped like a wakizashi."
|
||||
icon_state = "wakibokken"
|
||||
item_state = "wakibokken"
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
force = 6
|
||||
stamina_damage_increment = 4
|
||||
block_parry_data = /datum/block_parry_data/bokken/waki
|
||||
default_parry_data = /datum/block_parry_data/bokken/waki
|
||||
quick_parry_data = /datum/block_parry_data/bokken/waki/quick_parry
|
||||
|
||||
/datum/block_parry_data/bokken/waki // weaker parries than the bigger variant, but cheaper and faster recovery, like quick parry
|
||||
parry_stamina_cost = 4
|
||||
parry_time_windup = 0
|
||||
parry_time_active = 6
|
||||
parry_time_spindown = 0
|
||||
parry_time_perfect = 1.5
|
||||
parry_time_perfect_leeway = 1
|
||||
parry_imperfect_falloff_percent = 7.5
|
||||
parry_efficiency_to_counterattack = 120
|
||||
parry_efficiency_considered_successful = 65
|
||||
parry_efficiency_perfect = 120
|
||||
parry_efficiency_perfect_override = list(
|
||||
TEXT_ATTACK_TYPE_PROJECTILE = 30,
|
||||
)
|
||||
parry_failed_stagger_duration = 2 SECONDS
|
||||
parry_data = list(
|
||||
PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 1.5, // 6*1.5 = 9, 7*1.5 = 10.5, 8*1.5 = 12, 9*1.5 = 13.5
|
||||
)
|
||||
|
||||
/datum/block_parry_data/bokken/waki/quick_parry //For the parry spammer in you
|
||||
parry_stamina_cost = 2 // Slam that parry button
|
||||
parry_time_active = 2.5
|
||||
parry_time_perfect = 1
|
||||
parry_time_perfect_leeway = 1
|
||||
parry_failed_stagger_duration = 1 SECONDS
|
||||
parry_failed_clickcd_duration = 1 SECONDS
|
||||
|
||||
/datum/block_parry_data/bokken/waki/quick_parry/proj
|
||||
parry_efficiency_perfect_override = list()
|
||||
|
||||
/obj/item/melee/bokken/waki/steelwood
|
||||
name = "wakizashi steelwood bokken"
|
||||
desc = "A misnomer of sorts, this is effectively a blunt wakizashi made from steelwood, a dense organic wood derived from steelcaps. Why steelwood? Druids can use it. Duh."
|
||||
icon_state = "wakibokken_steel"
|
||||
item_state = "wakibokken_steel"
|
||||
force = 8
|
||||
stamina_damage_increment = 2
|
||||
|
||||
/obj/item/melee/bokken/debug
|
||||
name = "funny debug parrying stick"
|
||||
desc = "if you see this you've fucked up somewhere my good man"
|
||||
block_parry_data = /datum/block_parry_data/bokken/debug
|
||||
|
||||
/obj/item/melee/bokken/debug/AltClick(mob/user)
|
||||
quick_parry = !quick_parry
|
||||
if(quick_parry)
|
||||
block_parry_data = /datum/block_parry_data/bokken/quick_parry/debug
|
||||
else
|
||||
block_parry_data = /datum/block_parry_data/bokken/debug
|
||||
to_chat(user, "<span class='notice'>[src] is now [quick_parry ? "emphasizing shorter parries, forcing you to riposte or be staggered" : "emphasizing longer parries, with a shorter window to riposte but more forgiving parries"].</span>")
|
||||
default_parry_data = /datum/block_parry_data/bokken/debug
|
||||
quick_parry_data = /datum/block_parry_data/bokken/quick_parry/debug
|
||||
|
||||
/datum/block_parry_data/bokken/debug
|
||||
parry_efficiency_perfect_override = list()
|
||||
parry_data = list(
|
||||
PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5, // 7*2.5 = 17.5, 8*2.5 = 20, 9*2.5 = 22.5, 10*2.5 = 25
|
||||
PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5, // 10*2.5 = 25, 11*2.5 = 27.5, 12*2.5 = 30, 13*2.5 = 32.5
|
||||
PARRY_DISARM_ATTACKER = TRUE,
|
||||
PARRY_KNOCKDOWN_ATTACKER = 10,
|
||||
PARRY_STAGGER_ATTACKER = 10,
|
||||
@@ -436,13 +491,63 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
/datum/block_parry_data/bokken/quick_parry/debug
|
||||
parry_efficiency_perfect_override = list()
|
||||
parry_data = list(
|
||||
PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5, // 7*2.5 = 17.5, 8*2.5 = 20, 9*2.5 = 22.5, 10*2.5 = 25
|
||||
PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5, // 10*2.5 = 25, 11*2.5 = 27.5, 12*2.5 = 30, 13*2.5 = 32.5
|
||||
PARRY_DISARM_ATTACKER = TRUE,
|
||||
PARRY_KNOCKDOWN_ATTACKER = 10,
|
||||
PARRY_STAGGER_ATTACKER = 10,
|
||||
PARRY_DAZE_ATTACKER = 10,
|
||||
)
|
||||
|
||||
/// BOKKEN CRAFTNG PIECES
|
||||
|
||||
/obj/item/bokken_blade
|
||||
name = "training bokken wooden blade"
|
||||
desc = "The blade piece of a bokken katana."
|
||||
icon = 'icons/obj/smith.dmi'
|
||||
icon_state = "bokken"
|
||||
item_state = "bone_dagger"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
|
||||
/obj/item/bokken_steelblade
|
||||
name = "training bokken steelwood blade"
|
||||
desc = "The blade piece of a steelwood bokken katana."
|
||||
icon = 'icons/obj/smith.dmi'
|
||||
icon_state = "bokken_steel"
|
||||
item_state = "switchblade_ext"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
|
||||
/obj/item/wakibokken_blade
|
||||
name = "training bokken wooden wakizashi blade"
|
||||
desc = "The blade piece of a bokken wakizashi."
|
||||
icon = 'icons/obj/smith.dmi'
|
||||
icon_state = "wakibokken"
|
||||
item_state = "bone_dagger"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
|
||||
/obj/item/wakibokken_steelblade
|
||||
name = "training bokken steelwood wakizashi blade"
|
||||
desc = "The blade piece of a steelwood bokken katana."
|
||||
icon = 'icons/obj/smith.dmi'
|
||||
icon_state = "wakibokken_steel"
|
||||
item_state = "switchblade_ext"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
|
||||
/obj/item/bokken_hilt
|
||||
name = "training bokken hilt"
|
||||
desc = "The hilt piece of a bokken. This hilt is appropriate for any potential blade length or material."
|
||||
icon = 'icons/obj/smith.dmi'
|
||||
icon_state = "bokken_hilt"
|
||||
item_state = "bone_dagger"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
||||
|
||||
/obj/item/wirerod
|
||||
name = "wired rod"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user