Merge remote-tracking branch 'origin/master' into perlin-genny
This commit is contained in:
@@ -18,8 +18,8 @@
|
||||
|
||||
/// Integrity defines for clothing (not flags but close enough)
|
||||
#define CLOTHING_PRISTINE 0 // We have no damage on the clothing
|
||||
#define CLOTHING_DAMAGED 1 // There's some damage on the clothing but it still has at least one functioning bodypart and can be equipped
|
||||
#define CLOTHING_SHREDDED 2 // The clothing is useless and cannot be equipped unless repaired first
|
||||
#define CLOTHING_DAMAGED 1 // There's some damage on the clothing but it still has at least one functioning bodypart
|
||||
#define CLOTHING_SHREDDED 2 // The clothing is near useless and has their sensors broken
|
||||
|
||||
// If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support
|
||||
|
||||
|
||||
@@ -1,18 +1,35 @@
|
||||
/// Transparent, let beams pass
|
||||
#define SHIELD_TRANSPARENT (1<<0)
|
||||
|
||||
/// Flammable, takes more damage from fire
|
||||
#define SHIELD_ENERGY_WEAK (1<<1)
|
||||
/// Fragile, takes more damage from brute
|
||||
#define SHIELD_KINETIC_WEAK (1<<2)
|
||||
/// Strong against kinetic, weak against energy
|
||||
#define SHIELD_KINETIC_STRONG (1<<3)
|
||||
/// Strong against energy, weak against kinetic
|
||||
#define SHIELD_ENERGY_STRONG (1<<4)
|
||||
/// Disabler and other stamina based energy weapons boost the damage done to the sheld
|
||||
#define SHIELD_DISABLER_DISRUPTED (1<<5)
|
||||
|
||||
/// Doesn't block ranged attacks whatsoever
|
||||
#define SHIELD_NO_RANGED (1<<6)
|
||||
/// Doesn't block melee attacks whatsoever
|
||||
#define SHIELD_NO_MELEE (1<<7)
|
||||
|
||||
/// Can shield bash
|
||||
#define SHIELD_CAN_BASH (1<<1)
|
||||
#define SHIELD_CAN_BASH (1<<8)
|
||||
/// Shield bash knockdown on wall hit
|
||||
#define SHIELD_BASH_WALL_KNOCKDOWN (1<<2)
|
||||
#define SHIELD_BASH_WALL_KNOCKDOWN (1<<9)
|
||||
/// Shield bash always knockdown
|
||||
#define SHIELD_BASH_ALWAYS_KNOCKDOWN (1<<3)
|
||||
#define SHIELD_BASH_ALWAYS_KNOCKDOWN (1<<10)
|
||||
/// Shield bash disarm on wall hit
|
||||
#define SHIELD_BASH_WALL_DISARM (1<<4)
|
||||
#define SHIELD_BASH_WALL_DISARM (1<<11)
|
||||
/// Shield bash always disarm
|
||||
#define SHIELD_BASH_ALWAYS_DISARM (1<<5)
|
||||
#define SHIELD_BASH_ALWAYS_DISARM (1<<12)
|
||||
/// You can shieldbash target someone on the ground for ground slam
|
||||
#define SHIELD_BASH_GROUND_SLAM (1<<6)
|
||||
#define SHIELD_BASH_GROUND_SLAM (1<<13)
|
||||
/// Shield bashing someone on the ground will disarm
|
||||
#define SHIELD_BASH_GROUND_SLAM_DISARM (1<<7)
|
||||
#define SHIELD_BASH_GROUND_SLAM_DISARM (1<<14)
|
||||
|
||||
#define SHIELD_FLAGS_DEFAULT (SHIELD_CAN_BASH | SHIELD_BASH_WALL_KNOCKDOWN | SHIELD_BASH_WALL_DISARM | SHIELD_BASH_GROUND_SLAM)
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
// signals from globally accessible objects
|
||||
/// from SSsun when the sun changes position : (primary_sun, suns)
|
||||
#define COMSIG_SUN_MOVED "sun_moved"
|
||||
|
||||
/// from SSactivity for things that add threat but aren't "global" (e.g. phylacteries)
|
||||
#define COMSIG_THREAT_CALC "threat_calculation"
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
// /datum signals
|
||||
|
||||
@@ -82,3 +82,12 @@
|
||||
#define LOADOUT_CAN_NAME (1<<0) //renaming items
|
||||
#define LOADOUT_CAN_DESCRIPTION (1<<1) //adding a custom description to items
|
||||
#define LOADOUT_CAN_COLOR_POLYCHROMIC (1<<2)
|
||||
|
||||
//the names of the customization tabs
|
||||
#define SETTINGS_TAB 0
|
||||
#define GAME_PREFERENCES_TAB 1
|
||||
#define APPEARANCE_TAB 2
|
||||
#define SPEECH_TAB 3
|
||||
#define LOADOUT_TAB 4
|
||||
#define CONTENT_PREFERENCES_TAB 5
|
||||
#define KEYBINDINGS_TAB 6
|
||||
|
||||
+12
-2
@@ -173,8 +173,18 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache)
|
||||
|
||||
#define BROKEN_SENSORS -1
|
||||
#define NO_SENSORS 0
|
||||
#define HAS_SENSORS 1
|
||||
#define LOCKED_SENSORS 2
|
||||
#define DAMAGED_SENSORS_LIVING 1
|
||||
#define DAMAGED_SENSORS_VITALS 2
|
||||
#define HAS_SENSORS 3
|
||||
|
||||
//suit sensor flags: sensor_flag defines
|
||||
#define SENSOR_RANDOM (1<<0)
|
||||
#define SENSOR_LOCKED (1<<1)
|
||||
|
||||
//suit sensor integrity percentage threshold defines
|
||||
#define SENSOR_INTEGRITY_COORDS 0.2
|
||||
#define SENSOR_INTEGRITY_VITALS 0.6
|
||||
#define SENSOR_INTEGRITY_BINARY 1
|
||||
|
||||
//Wet floor type flags. Stronger ones should be higher in number.
|
||||
#define TURF_DRY (0)
|
||||
|
||||
@@ -152,6 +152,7 @@
|
||||
// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
|
||||
|
||||
#define FIRE_PRIORITY_VORE 5
|
||||
#define FIRE_PRIORITY_ACTIVITY 10
|
||||
#define FIRE_PRIORITY_IDLE_NPC 10
|
||||
#define FIRE_PRIORITY_SERVER_MAINT 10
|
||||
#define FIRE_PRIORITY_RESEARCH 10
|
||||
|
||||
@@ -386,12 +386,15 @@
|
||||
//ignore this comment, it fixes the broken sytax parsing caused by the " above
|
||||
else
|
||||
parts += "[FOURSPACES]<i>Nobody died this shift!</i>"
|
||||
var/avg_threat = SSactivity.get_average_threat()
|
||||
var/max_threat = SSactivity.get_max_threat()
|
||||
parts += "[FOURSPACES]Threat at round end: [SSactivity.current_threat]"
|
||||
parts += "[FOURSPACES]Average threat: [avg_threat]"
|
||||
parts += "[FOURSPACES]Max threat: [max_threat]"
|
||||
if(istype(SSticker.mode, /datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
mode.update_playercounts() // ?
|
||||
parts += "[FOURSPACES]Threat level: [mode.threat_level]"
|
||||
parts += "[FOURSPACES]Threat left: [mode.threat]"
|
||||
parts += "[FOURSPACES]Average threat: [mode.threat_average]"
|
||||
parts += "[FOURSPACES]Target threat: [mode.threat_level]"
|
||||
parts += "[FOURSPACES]Executed rules:"
|
||||
for(var/datum/dynamic_ruleset/rule in mode.executed_rules)
|
||||
parts += "[FOURSPACES][FOURSPACES][rule.ruletype] - <b>[rule.name]</b>: -[rule.cost + rule.scaled_times * rule.scaling_cost] threat"
|
||||
@@ -400,8 +403,10 @@
|
||||
parts += "[FOURSPACES][FOURSPACES][str]"
|
||||
for(var/entry in mode.threat_tallies)
|
||||
parts += "[FOURSPACES][FOURSPACES][entry] added [mode.threat_tallies[entry]]"
|
||||
SSblackbox.record_feedback("tally","dynamic_threat",mode.threat_level,"Final threat level")
|
||||
SSblackbox.record_feedback("tally","dynamic_threat",mode.threat,"Final Threat")
|
||||
SSblackbox.record_feedback("tally","threat",mode.threat_level,"Target threat")
|
||||
SSblackbox.record_feedback("tally","threat",SSactivity.current_threat,"Final Threat")
|
||||
SSblackbox.record_feedback("tally","threat",avg_threat,"Average Threat")
|
||||
SSblackbox.record_feedback("tally","threat",max_threat,"Max Threat")
|
||||
return parts.Join("<br>")
|
||||
|
||||
/client/proc/roundend_report_file()
|
||||
|
||||
@@ -259,6 +259,13 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
),
|
||||
"shield_flags" = list(
|
||||
"SHIELD_TRANSPARENT" = SHIELD_TRANSPARENT,
|
||||
"SHIELD_ENERGY_WEAK" = SHIELD_ENERGY_WEAK,
|
||||
"SHIELD_KINETIC_WEAK" = SHIELD_KINETIC_WEAK,
|
||||
"SHIELD_KINETIC_STRONG" = SHIELD_KINETIC_STRONG,
|
||||
"SHIELD_ENERGY_STRONG" = SHIELD_ENERGY_STRONG,
|
||||
"SHIELD_DISABLER_DISRUPTED" = SHIELD_DISABLER_DISRUPTED,
|
||||
"SHIELD_NO_RANGED" = SHIELD_NO_RANGED,
|
||||
"SHIELD_NO_MELEE" = SHIELD_NO_MELEE,
|
||||
"SHIELD_CAN_BASH" = SHIELD_CAN_BASH,
|
||||
"SHIELD_BASH_WALL_KNOCKDOWN" = SHIELD_BASH_WALL_KNOCKDOWN,
|
||||
"SHIELD_BASH_ALWAYS_KNOCKDOWN" = SHIELD_BASH_ALWAYS_KNOCKDOWN,
|
||||
|
||||
@@ -169,5 +169,9 @@
|
||||
A.attack_robot(src)
|
||||
|
||||
/atom/proc/attack_robot(mob/user)
|
||||
if((isturf(src) || istype(src, /obj/structure/table) || istype(src, /obj/machinery/conveyor)) && get_dist(user, src) <= 1)
|
||||
user.Move_Pulled(src)
|
||||
return
|
||||
|
||||
attack_ai(user)
|
||||
return
|
||||
|
||||
@@ -361,7 +361,7 @@
|
||||
/obj/screen/mov_intent/update_icon_state()
|
||||
switch(hud?.mymob?.m_intent)
|
||||
if(MOVE_INTENT_WALK)
|
||||
icon_state = "walking"
|
||||
icon_state = CONFIG_GET(flag/sprint_enabled)? "walking" : "walking_nosprint"
|
||||
if(MOVE_INTENT_RUN)
|
||||
icon_state = CONFIG_GET(flag/sprint_enabled)? "running" : "running_nosprint"
|
||||
|
||||
|
||||
@@ -404,9 +404,9 @@ Example config:
|
||||
if(!Get(/datum/config_entry/flag/no_storyteller_threat_removal))
|
||||
var/min_chaos = (probabilities in storyteller_min_chaos) ? storyteller_min_chaos[config_tag] : initial(S.min_chaos)
|
||||
var/max_chaos = (probabilities in storyteller_max_chaos) ? storyteller_max_chaos[config_tag] : initial(S.max_chaos)
|
||||
if(SSpersistence.average_dynamic_threat < min_chaos)
|
||||
if(SSpersistence.average_threat + 50 < min_chaos)
|
||||
continue
|
||||
if(SSpersistence.average_dynamic_threat > max_chaos)
|
||||
if(SSpersistence.average_threat + 50 > max_chaos)
|
||||
continue
|
||||
if(SSpersistence.saved_storytellers.len == repeated_mode_adjust.len)
|
||||
var/name = initial(S.name)
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
SUBSYSTEM_DEF(activity)
|
||||
name = "Activity tracking"
|
||||
flags = SS_BACKGROUND | SS_NO_TICK_CHECK
|
||||
priority = FIRE_PRIORITY_ACTIVITY
|
||||
wait = 1 MINUTES
|
||||
var/list/deferred_threats = list()
|
||||
var/current_threat = 0
|
||||
var/list/threat_history = list()
|
||||
var/list/threats = list()
|
||||
|
||||
/datum/controller/subsystem/activity/Initialize(timeofday)
|
||||
RegisterSignal(SSdcs,COMSIG_GLOB_EXPLOSION,.proc/on_explosion)
|
||||
RegisterSignal(SSdcs,COMSIG_GLOB_MOB_DEATH,.proc/on_death)
|
||||
|
||||
/datum/controller/subsystem/activity/fire(resumed = 0)
|
||||
calculate_threat()
|
||||
|
||||
/datum/controller/subsystem/activity/proc/calculate_threat()
|
||||
threats = deferred_threats.Copy()
|
||||
deferred_threats.Cut()
|
||||
threats["antagonists"] = 0
|
||||
for(var/datum/antagonist/A in GLOB.antagonists)
|
||||
if(A?.owner?.current && A.owner.current.stat != DEAD)
|
||||
threats["antagonists"] += A.threat()
|
||||
threats["events"] = 0
|
||||
for(var/r in SSevents.running)
|
||||
var/datum/round_event/R = r
|
||||
threats["events"] += R.threat()
|
||||
threats["players"] = 0
|
||||
SEND_SIGNAL(src, COMSIG_THREAT_CALC, threats)
|
||||
for(var/m in GLOB.player_list)
|
||||
var/mob/M = m
|
||||
if (M?.mind?.assigned_role && M.stat != DEAD)
|
||||
var/datum/job/J = SSjob.GetJob(M.mind.assigned_role)
|
||||
if(J)
|
||||
if(length(M.mind.antag_datums))
|
||||
threats["players"] += J.GetThreat()
|
||||
else
|
||||
threats["players"] -= J.GetThreat()
|
||||
else if(M?.stat == DEAD && !M.voluntary_ghosted)
|
||||
threats["dead_players"] += 1
|
||||
current_threat = 0
|
||||
for(var/threat_type in threats)
|
||||
current_threat += threats[threat_type]
|
||||
threat_history += "[world.time]"
|
||||
threat_history["[world.time]"] = current_threat
|
||||
|
||||
/datum/controller/subsystem/activity/proc/get_average_threat()
|
||||
if(!length(threat_history))
|
||||
return 0
|
||||
var/total_weight = 0
|
||||
var/total_amt = 0
|
||||
for(var/i in 1 to threat_history.len-1)
|
||||
var/weight = (text2num(threat_history[i+1])-text2num(threat_history[i]))
|
||||
total_weight += weight
|
||||
total_amt += weight * (threat_history[threat_history[i]])
|
||||
return round(total_amt / total_weight,0.1)
|
||||
|
||||
/datum/controller/subsystem/activity/proc/get_max_threat()
|
||||
. = 0
|
||||
for(var/threat in threat_history)
|
||||
. = max(threat_history[threat], .)
|
||||
|
||||
/datum/controller/subsystem/activity/proc/on_explosion(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, took, orig_dev_range, orig_heavy_range, orig_light_range)
|
||||
if(!("explosions" in deferred_threats))
|
||||
deferred_threats["explosions"] = 0
|
||||
var/area/A = get_area(epicenter)
|
||||
if(is_station_level(epicenter.z) && A.blob_allowed && !istype(A, /area/asteroid))
|
||||
deferred_threats["explosions"] += devastation_range**2 + heavy_impact_range**2 / 4 + light_impact_range**2 / 8 // 75 for a maxcap
|
||||
|
||||
/datum/controller/subsystem/activity/proc/on_death(mob/M, gibbed)
|
||||
if(!("crew_deaths" in deferred_threats))
|
||||
deferred_threats["crew_deaths"] = 0
|
||||
if(M?.mind && SSjob.GetJob(M.mind.assigned_role))
|
||||
deferred_threats["crew_deaths"] += 1
|
||||
@@ -6,7 +6,7 @@
|
||||
var/list/saved_chaos = list(5,5,5)
|
||||
var/list/saved_dynamic_rules = list(list(),list(),list())
|
||||
var/list/saved_storytellers = list("foo","bar","baz")
|
||||
var/list/average_dynamic_threat = 50
|
||||
var/average_threat = 50
|
||||
var/list/saved_maps
|
||||
|
||||
/datum/controller/subsystem/persistence/SaveServerPersistence()
|
||||
@@ -38,9 +38,10 @@
|
||||
saved_chaos[3] = saved_chaos[2]
|
||||
saved_chaos[2] = saved_chaos[1]
|
||||
saved_chaos[1] = SSticker.mode.get_chaos()
|
||||
average_threat = (SSactivity.get_average_threat() + average_threat) / 2
|
||||
json_file = file("data/RecentChaos.json")
|
||||
file_data = list()
|
||||
file_data["data"] = saved_chaos
|
||||
file_data["data"] = saved_chaos + average_threat
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
@@ -49,10 +50,9 @@
|
||||
saved_storytellers[3] = saved_storytellers[2]
|
||||
saved_storytellers[2] = saved_storytellers[1]
|
||||
saved_storytellers[1] = mode.storyteller.name
|
||||
average_dynamic_threat = (mode.max_threat + average_dynamic_threat) / 2
|
||||
var/json_file = file("data/RecentStorytellers.json")
|
||||
var/list/file_data = list()
|
||||
file_data["data"] = saved_storytellers + average_dynamic_threat
|
||||
file_data["data"] = saved_storytellers
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
@@ -94,6 +94,9 @@
|
||||
if(!json)
|
||||
return
|
||||
saved_chaos = json["data"]
|
||||
if(saved_chaos.len > 3)
|
||||
average_threat = saved_chaos[4]
|
||||
saved_chaos.len = 3
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadRecentRulesets()
|
||||
var/json_file = file("data/RecentRulesets.json")
|
||||
@@ -112,9 +115,6 @@
|
||||
if(!json)
|
||||
return
|
||||
saved_storytellers = json["data"]
|
||||
if(saved_storytellers.len > 3)
|
||||
average_dynamic_threat = saved_storytellers[4]
|
||||
saved_storytellers.len = 3
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadRecentMaps()
|
||||
var/json_file = file("data/RecentMaps.json")
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
/datum/crafting_recipe/strobeshield
|
||||
name = "Strobe Shield"
|
||||
result = /obj/item/assembly/flash/shield
|
||||
result = /obj/item/shield/riot/flash
|
||||
reqs = list(/obj/item/wallframe/flasher = 1,
|
||||
/obj/item/assembly/flash/handheld = 1,
|
||||
/obj/item/shield/riot = 1)
|
||||
|
||||
@@ -317,6 +317,8 @@ GLOBAL_LIST_EMPTY(explosions)
|
||||
|
||||
var/took = (REALTIMEOFDAY - started_at) / 10
|
||||
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_EXPLOSION,epicenter, devastation_range, heavy_impact_range, light_impact_range, took, orig_dev_range, orig_heavy_range, orig_light_range)
|
||||
|
||||
//You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare
|
||||
if(GLOB.Debug2)
|
||||
log_world("## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds.")
|
||||
|
||||
@@ -52,7 +52,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
name = "diamond"
|
||||
desc = "Highly pressurized carbon"
|
||||
color = list(48/255, 272/255, 301/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
|
||||
strength_modifier = 1.1
|
||||
strength_modifier = 1.2
|
||||
alpha = 132
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/diamond
|
||||
@@ -85,6 +85,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
name = "plasma"
|
||||
desc = "Isn't plasma a state of matter? Oh whatever."
|
||||
color = list(298/255, 46/255, 352/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
|
||||
strength_modifier = 0.7
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/plasma
|
||||
value_per_unit = 0.1
|
||||
|
||||
@@ -58,14 +58,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
var/threat_level = 0
|
||||
/// The current antag threat. Recalculated every time a ruletype starts or ends.
|
||||
var/threat = 0
|
||||
/// Threat average over the course of the round, for endgame logs.
|
||||
var/threat_average = 0
|
||||
/// Number of times threat average has been calculated, for calculating above.
|
||||
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.
|
||||
@@ -745,17 +737,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
continue
|
||||
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)
|
||||
threat_average_weight += cur_sample_weight
|
||||
last_threat_sample_time = world.time
|
||||
else
|
||||
threat_average = threat
|
||||
threat_average_weight++
|
||||
last_threat_sample_time = world.time
|
||||
threat = (SSactivity.current_threat * 0.6 + SSactivity.get_max_threat() * 0.2 + SSactivity.get_average_threat() * 0.2) + added_threat
|
||||
|
||||
/// Removes type from the list
|
||||
/datum/game_mode/dynamic/proc/remove_from_list(list/type_list, type)
|
||||
|
||||
@@ -45,27 +45,6 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_first_midround_delay_min + GLOB.dynamic_first_midround_delay_max)
|
||||
mode.midround_injection_cooldown = round(clamp(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_first_midround_delay_min, GLOB.dynamic_first_midround_delay_max)) + world.time
|
||||
|
||||
/datum/dynamic_storyteller/proc/calculate_threat()
|
||||
var/threat = 0
|
||||
for(var/datum/antagonist/A in GLOB.antagonists)
|
||||
if(A?.owner?.current && A.owner.current.stat != DEAD)
|
||||
threat += A.threat()
|
||||
for(var/r in SSevents.running)
|
||||
var/datum/round_event/R = r
|
||||
threat += R.threat()
|
||||
for(var/obj/item/phylactery/P in GLOB.poi_list)
|
||||
threat += 25 // can't be giving them too much of a break
|
||||
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
|
||||
if (M?.mind?.assigned_role && M.stat != DEAD)
|
||||
var/datum/job/J = SSjob.GetJob(M.mind.assigned_role)
|
||||
if(J)
|
||||
if(length(M.mind.antag_datums))
|
||||
threat += J.GetThreat()
|
||||
else
|
||||
threat -= J.GetThreat()
|
||||
threat += (mode.current_players[CURRENT_DEAD_PLAYERS].len)*dead_player_weight
|
||||
return round(threat,0.1)
|
||||
|
||||
/datum/dynamic_storyteller/proc/do_process()
|
||||
return
|
||||
|
||||
@@ -95,7 +74,7 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
if(voters)
|
||||
GLOB.dynamic_curve_centre += (mean/voters)
|
||||
if(flags & USE_PREV_ROUND_WEIGHTS)
|
||||
GLOB.dynamic_curve_centre += (50 - SSpersistence.average_dynamic_threat) / 10
|
||||
GLOB.dynamic_curve_centre += (SSpersistence.average_threat) / 10
|
||||
GLOB.dynamic_forced_threat_level = forced_threat_level
|
||||
|
||||
/datum/dynamic_storyteller/proc/get_midround_cooldown()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
icon_state = "0"
|
||||
state = 0
|
||||
|
||||
/obj/structure/frame/computer/attackby(obj/item/P, mob/user, params)
|
||||
/obj/structure/frame/computer/attackby(obj/item/P, mob/living/user, params)
|
||||
add_fingerprint(user)
|
||||
switch(state)
|
||||
if(0)
|
||||
@@ -11,7 +11,7 @@
|
||||
to_chat(user, "<span class='notice'>You start wrenching the frame into place...</span>")
|
||||
if(P.use_tool(src, user, 20, volume=50))
|
||||
to_chat(user, "<span class='notice'>You wrench the frame into place.</span>")
|
||||
setAnchored(TRUE)
|
||||
set_anchored(TRUE)
|
||||
state = 1
|
||||
return
|
||||
if(P.tool_behaviour == TOOL_WELDER)
|
||||
@@ -19,7 +19,7 @@
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You start deconstructing the frame...</span>")
|
||||
if(P.use_tool(src, user, 20, volume=50) && state == 0)
|
||||
if(P.use_tool(src, user, 20, volume=50))
|
||||
to_chat(user, "<span class='notice'>You deconstruct the frame.</span>")
|
||||
var/obj/item/stack/sheet/metal/M = new (drop_location(), 5)
|
||||
M.add_fingerprint(user)
|
||||
@@ -28,15 +28,15 @@
|
||||
if(1)
|
||||
if(P.tool_behaviour == TOOL_WRENCH)
|
||||
to_chat(user, "<span class='notice'>You start to unfasten the frame...</span>")
|
||||
if(P.use_tool(src, user, 20, volume=50) && state == 1)
|
||||
if(P.use_tool(src, user, 20, volume=50))
|
||||
to_chat(user, "<span class='notice'>You unfasten the frame.</span>")
|
||||
setAnchored(FALSE)
|
||||
set_anchored(FALSE)
|
||||
state = 0
|
||||
return
|
||||
if(istype(P, /obj/item/circuitboard/computer) && !circuit)
|
||||
if(!user.transferItemToLoc(P, src))
|
||||
return
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
|
||||
to_chat(user, "<span class='notice'>You place [P] inside the frame.</span>")
|
||||
icon_state = "1"
|
||||
circuit = P
|
||||
@@ -71,8 +71,10 @@
|
||||
if(istype(P, /obj/item/stack/cable_coil))
|
||||
if(!P.tool_start_check(user, amount=5))
|
||||
return
|
||||
if(state != 2)
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start adding cables to the frame...</span>")
|
||||
if(P.use_tool(src, user, 20, 5, 50, CALLBACK(src, .proc/check_state, 2)))
|
||||
if(P.use_tool(src, user, 20, volume=50, amount=5))
|
||||
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
|
||||
state = 3
|
||||
icon_state = "3"
|
||||
@@ -90,9 +92,11 @@
|
||||
if(istype(P, /obj/item/stack/sheet/glass))
|
||||
if(!P.tool_start_check(user, amount=2))
|
||||
return
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
if(state != 3)
|
||||
return
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
|
||||
to_chat(user, "<span class='notice'>You start to put in the glass panel...</span>")
|
||||
if(P.use_tool(src, user, 20, 2, 0, CALLBACK(src, .proc/check_state, 3)))
|
||||
if(P.use_tool(src, user, 20, amount=2))
|
||||
to_chat(user, "<span class='notice'>You put in the glass panel.</span>")
|
||||
state = 4
|
||||
src.icon_state = "4"
|
||||
@@ -109,14 +113,51 @@
|
||||
if(P.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You connect the monitor.</span>")
|
||||
var/obj/B = new circuit.build_path (loc, circuit)
|
||||
B.setDir(dir)
|
||||
transfer_fingerprints_to(B)
|
||||
|
||||
var/obj/machinery/new_machine = new circuit.build_path(loc)
|
||||
new_machine.setDir(dir)
|
||||
transfer_fingerprints_to(new_machine)
|
||||
|
||||
if(istype(new_machine, /obj/machinery/computer))
|
||||
var/obj/machinery/computer/new_computer = new_machine
|
||||
|
||||
// Machines will init with a set of default components.
|
||||
// Triggering handle_atom_del will make the machine realise it has lost a component_parts and then deconstruct.
|
||||
// Move to nullspace so we don't trigger handle_atom_del, then qdel.
|
||||
// Finally, replace new machine's parts with this frame's parts.
|
||||
if(new_computer.circuit)
|
||||
// Move to nullspace and delete.
|
||||
new_computer.circuit.moveToNullspace()
|
||||
QDEL_NULL(new_computer.circuit)
|
||||
for(var/old_part in new_computer.component_parts)
|
||||
var/atom/movable/movable_part = old_part
|
||||
// Move to nullspace and delete.
|
||||
movable_part.moveToNullspace()
|
||||
qdel(movable_part)
|
||||
|
||||
// Set anchor state and move the frame's parts over to the new machine.
|
||||
// Then refresh parts and call on_construction().
|
||||
new_computer.set_anchored(anchored)
|
||||
new_computer.component_parts = list()
|
||||
|
||||
circuit.forceMove(new_computer)
|
||||
new_computer.component_parts += circuit
|
||||
new_computer.circuit = circuit
|
||||
|
||||
for(var/new_part in src)
|
||||
var/atom/movable/movable_part = new_part
|
||||
movable_part.forceMove(new_computer)
|
||||
new_computer.component_parts += movable_part
|
||||
|
||||
new_computer.RefreshParts()
|
||||
new_computer.on_construction()
|
||||
|
||||
qdel(src)
|
||||
return
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/structure/frame/computer/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
if(state == 4)
|
||||
@@ -127,13 +168,12 @@
|
||||
..()
|
||||
|
||||
/obj/structure/frame/computer/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
..()
|
||||
if(!user.canUseTopic(src, BE_CLOSE, TRUE, FALSE))
|
||||
return
|
||||
|
||||
if(anchored)
|
||||
to_chat(usr, "<span class='warning'>You must unwrench [src] before rotating it!</span>")
|
||||
return TRUE
|
||||
return
|
||||
|
||||
setDir(turn(dir, -90))
|
||||
return TRUE
|
||||
|
||||
@@ -51,6 +51,11 @@
|
||||
return FALSE
|
||||
return ACCESS_CAPTAIN in authorize_access
|
||||
|
||||
/obj/machinery/computer/communications/proc/authenticated_as_non_silicon_command(mob/user)
|
||||
if (issilicon(user))
|
||||
return FALSE
|
||||
return ACCESS_HEADS in authorize_access //Should always be the case if authorized as it usually needs head access to log in, buut lets be sure.
|
||||
|
||||
/// Are we a silicon, OR we're logged in as the captain?
|
||||
/obj/machinery/computer/communications/proc/authenticated_as_silicon_or_captain(mob/user)
|
||||
if (issilicon(user))
|
||||
@@ -160,7 +165,7 @@
|
||||
return
|
||||
make_announcement(usr)
|
||||
if ("messageAssociates")
|
||||
if (!authenticated_as_non_silicon_captain(usr))
|
||||
if (!authenticated_as_non_silicon_command(usr))
|
||||
return
|
||||
if (!COOLDOWN_FINISHED(src, important_action_cooldown))
|
||||
return
|
||||
@@ -361,9 +366,9 @@
|
||||
data["shuttleCanEvacOrFailReason"] = SSshuttle.canEvac(user, TRUE)
|
||||
|
||||
if (authenticated_as_non_silicon_captain(user))
|
||||
data["canMessageAssociates"] = TRUE
|
||||
data["canRequestNuke"] = TRUE
|
||||
|
||||
if (authenticated_as_non_silicon_command(user))
|
||||
data["canMessageAssociates"] = TRUE
|
||||
if (can_send_messages_to_other_sectors(user))
|
||||
data["canSendToSectors"] = TRUE
|
||||
|
||||
|
||||
@@ -217,6 +217,8 @@
|
||||
new_machine.RefreshParts()
|
||||
|
||||
new_machine.on_construction()
|
||||
// TODO: make sleepers not shit out parts PROPERLY THIS TIME.
|
||||
new_machine.circuit.moveToNullspace()
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
|
||||
@@ -409,7 +409,10 @@
|
||||
visible_message("<span class='notice'>\The [src] hums and hisses as it moves [mob_occupant.real_name] into storage.</span>")
|
||||
|
||||
// Ghost and delete the mob.
|
||||
if(!mob_occupant.get_ghost(1))
|
||||
var/mob/dead/observer/G = mob_occupant.get_ghost(TRUE)
|
||||
if(G)
|
||||
G.voluntary_ghosted = TRUE
|
||||
else
|
||||
mob_occupant.ghostize(FALSE, penalize = TRUE, voluntary = TRUE, cryo = TRUE)
|
||||
|
||||
QDEL_NULL(occupant)
|
||||
|
||||
@@ -178,6 +178,7 @@
|
||||
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)]."
|
||||
limb.forcereplace = TRUE
|
||||
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
|
||||
|
||||
@@ -69,8 +69,7 @@ effective or pretty fucking useless.
|
||||
*/
|
||||
|
||||
/obj/item/healthanalyzer/rad_laser
|
||||
custom_materials = list(/datum/material/iron=400)
|
||||
var/irradiate = 1
|
||||
var/irradiate = TRUE
|
||||
var/intensity = 10 // how much damage the radiation does
|
||||
var/wavelength = 10 // time it takes for the radiation to kick in, in seconds
|
||||
var/used = 0 // is it cooling down?
|
||||
@@ -92,16 +91,16 @@ effective or pretty fucking useless.
|
||||
addtimer(VARSET_CALLBACK(src, used, FALSE), cooldown)
|
||||
addtimer(VARSET_CALLBACK(src, icon_state, "health"), cooldown)
|
||||
to_chat(user, "<span class='warning'>Successfully irradiated [M].</span>")
|
||||
addtimer(CALLBACK(src, .proc/radiation_aftereffect, M), (wavelength+(intensity*4))*5)
|
||||
addtimer(CALLBACK(src, .proc/radiation_aftereffect, M, intensity), (wavelength+(intensity*4))*5)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The radioactive microlaser is still recharging.</span>")
|
||||
|
||||
/obj/item/healthanalyzer/rad_laser/proc/radiation_aftereffect(mob/living/M)
|
||||
if(QDELETED(M))
|
||||
/obj/item/healthanalyzer/rad_laser/proc/radiation_aftereffect(mob/living/M, passed_intensity)
|
||||
if(QDELETED(M) || !ishuman(M) || HAS_TRAIT(M, TRAIT_RADIMMUNE))
|
||||
return
|
||||
if(intensity >= 5)
|
||||
M.apply_effect(round(intensity/0.075), EFFECT_UNCONSCIOUS)
|
||||
M.rad_act(intensity*10)
|
||||
if(passed_intensity >= 5)
|
||||
M.apply_effect(round(passed_intensity/0.075), EFFECT_UNCONSCIOUS) //to save you some math, this is a round(intensity * (4/3)) second long knockout
|
||||
M.rad_act(passed_intensity*10)
|
||||
|
||||
/obj/item/healthanalyzer/rad_laser/proc/get_cooldown()
|
||||
return round(max(10, (stealth*30 + intensity*5 - wavelength/4)))
|
||||
|
||||
@@ -174,6 +174,10 @@
|
||||
var/atom/movable/AM = object
|
||||
if(CHECK_BITFIELD(shield_flags, SHIELD_TRANSPARENT) && (AM.pass_flags & PASSGLASS))
|
||||
return BLOCK_NONE
|
||||
if(CHECK_BITFIELD(shield_flags, SHIELD_NO_RANGED) && (attack_type & ATTACK_TYPE_PROJECTILE))
|
||||
return BLOCK_NONE
|
||||
if(CHECK_BITFIELD(shield_flags, SHIELD_NO_MELEE) && (attack_type & ATTACK_TYPE_MELEE))
|
||||
return BLOCK_NONE
|
||||
if(attack_type & ATTACK_TYPE_THROWN)
|
||||
final_block_chance += 30
|
||||
if(attack_type & ATTACK_TYPE_TACKLE)
|
||||
@@ -238,30 +242,75 @@
|
||||
new /obj/item/shard((get_turf(src)))
|
||||
|
||||
/obj/item/shield/riot/on_shield_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
var/final_damage = damage
|
||||
|
||||
if(attack_type & ATTACK_TYPE_MELEE)
|
||||
var/obj/hittingthing = object
|
||||
if(hittingthing.damtype == BURN)
|
||||
if(CHECK_BITFIELD(shield_flags, SHIELD_ENERGY_WEAK))
|
||||
final_damage *= 2
|
||||
else if(CHECK_BITFIELD(shield_flags, SHIELD_ENERGY_STRONG))
|
||||
final_damage *= 0.5
|
||||
|
||||
if(hittingthing.damtype == BRUTE)
|
||||
if(CHECK_BITFIELD(shield_flags, SHIELD_KINETIC_WEAK))
|
||||
final_damage *= 2
|
||||
else if(CHECK_BITFIELD(shield_flags, SHIELD_KINETIC_STRONG))
|
||||
final_damage *= 0.5
|
||||
|
||||
if(hittingthing.damtype == STAMINA || hittingthing.damtype == TOX || hittingthing.damtype == CLONE || hittingthing.damtype == BRAIN || hittingthing.damtype == OXY)
|
||||
final_damage = 0
|
||||
|
||||
if(attack_type & ATTACK_TYPE_PROJECTILE)
|
||||
var/obj/item/projectile/shootingthing = object
|
||||
if(is_energy_reflectable_projectile(shootingthing))
|
||||
if(CHECK_BITFIELD(shield_flags, SHIELD_ENERGY_WEAK))
|
||||
final_damage *= 2
|
||||
else if(CHECK_BITFIELD(shield_flags, SHIELD_ENERGY_STRONG))
|
||||
final_damage *= 0.5
|
||||
|
||||
if(!is_energy_reflectable_projectile(object))
|
||||
if(CHECK_BITFIELD(shield_flags, SHIELD_KINETIC_WEAK))
|
||||
final_damage *= 2
|
||||
else if(CHECK_BITFIELD(shield_flags, SHIELD_KINETIC_STRONG))
|
||||
final_damage *= 0.5
|
||||
|
||||
if(shootingthing.damage_type == STAMINA)
|
||||
if(CHECK_BITFIELD(shield_flags, SHIELD_DISABLER_DISRUPTED))
|
||||
final_damage *= 3 //disablers melt these kinds of shields. Really meant more for holoshields.
|
||||
else
|
||||
final_damage = 0
|
||||
|
||||
if(shootingthing.damage_type == TOX || shootingthing.damage_type == CLONE || shootingthing.damage_type == BRAIN || shootingthing.damage_type == OXY)
|
||||
final_damage = 0
|
||||
|
||||
if(can_shatter && (obj_integrity <= damage))
|
||||
var/turf/T = get_turf(owner)
|
||||
T.visible_message("<span class='warning'>[attack_text] destroys [src]!</span>")
|
||||
shatter(owner)
|
||||
qdel(src)
|
||||
return FALSE
|
||||
take_damage(damage)
|
||||
take_damage(final_damage)
|
||||
return ..()
|
||||
|
||||
/obj/item/shield/riot/laser_proof
|
||||
name = "laser resistant shield"
|
||||
desc = "A far more frail shield made of dark glass meant to block lasers but suffers from being being weak to ballistic projectiles."
|
||||
/obj/item/shield/riot/energy_proof
|
||||
name = "energy resistant shield"
|
||||
desc = "An ablative shield designed to absorb and disperse energy attacks. This comes at significant cost to its ability to withstand ballistics and kinetics, breaking apart easily."
|
||||
armor = list("melee" = 30, "bullet" = -10, "laser" = 80, "energy" = 80, "bomb" = -40, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 50)
|
||||
icon_state = "riot_laser"
|
||||
item_state = "riot_laser"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
|
||||
shield_flags = SHIELD_FLAGS_DEFAULT
|
||||
shield_flags = SHIELD_FLAGS_DEFAULT | SHIELD_ENERGY_STRONG | SHIELD_KINETIC_WEAK
|
||||
max_integrity = 300
|
||||
|
||||
/obj/item/shield/riot/bullet_proof
|
||||
name = "bullet resistant shield"
|
||||
desc = "A far more frail shield made of resistant plastics and kevlar meant to block ballistics."
|
||||
/obj/item/shield/riot/kinetic_proof
|
||||
name = "kinetic resistant shield"
|
||||
desc = "A polymer and ceramic shield designed to absorb ballistic projectiles and kinetic force. It doesn't do very well into energy attacks, especially from weapons that inflict burns."
|
||||
armor = list("melee" = 30, "bullet" = 80, "laser" = 0, "energy" = 0, "bomb" = -40, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 50)
|
||||
icon_state = "riot_bullet"
|
||||
item_state = "riot_bullet"
|
||||
shield_flags = SHIELD_FLAGS_DEFAULT | SHIELD_KINETIC_STRONG | SHIELD_ENERGY_WEAK
|
||||
max_integrity = 300
|
||||
|
||||
/obj/item/shield/riot/roman
|
||||
@@ -277,8 +326,8 @@
|
||||
|
||||
/obj/item/shield/riot/roman/fake
|
||||
desc = "Bears an inscription on the inside: <i>\"Romanes venio domus\"</i>. It appears to be a bit flimsy."
|
||||
block_chance = 0
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
shield_flags = SHIELD_ENERGY_WEAK | SHIELD_KINETIC_WEAK | SHIELD_NO_RANGED
|
||||
max_integrity = 40
|
||||
|
||||
/obj/item/shield/riot/roman/shatter(mob/living/carbon/human/owner)
|
||||
@@ -295,14 +344,80 @@
|
||||
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 10)
|
||||
resistance_flags = FLAMMABLE
|
||||
repair_material = /obj/item/stack/sheet/mineral/wood
|
||||
block_chance = 30
|
||||
shield_flags = SHIELD_FLAGS_DEFAULT
|
||||
shield_flags = SHIELD_FLAGS_DEFAULT | SHIELD_ENERGY_WEAK
|
||||
max_integrity = 150
|
||||
|
||||
/obj/item/shield/riot/buckler/shatter(mob/living/carbon/human/owner)
|
||||
playsound(owner, 'sound/effects/bang.ogg', 50)
|
||||
new /obj/item/stack/sheet/mineral/wood(get_turf(src))
|
||||
|
||||
/obj/item/shield/riot/flash
|
||||
name = "strobe shield"
|
||||
desc = "A shield with a built in, high intensity light capable of blinding and disorienting suspects. Takes regular handheld flashes as bulbs."
|
||||
icon_state = "flashshield"
|
||||
item_state = "flashshield"
|
||||
var/obj/item/assembly/flash/handheld/embedded_flash
|
||||
|
||||
/obj/item/shield/riot/flash/Initialize()
|
||||
. = ..()
|
||||
embedded_flash = new(src)
|
||||
|
||||
/obj/item/shield/riot/flash/ComponentInitialize()
|
||||
. = .. ()
|
||||
AddElement(/datum/element/update_icon_updates_onmob)
|
||||
|
||||
/obj/item/shield/riot/flash/attack(mob/living/M, mob/user)
|
||||
. = embedded_flash.attack(M, user)
|
||||
update_icon()
|
||||
|
||||
/obj/item/shield/riot/flash/attack_self(mob/living/carbon/user)
|
||||
. = embedded_flash.attack_self(user)
|
||||
update_icon()
|
||||
|
||||
/obj/item/shield/riot/flash/on_shield_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
. = ..()
|
||||
if (. && !embedded_flash.crit_fail)
|
||||
embedded_flash.activate()
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/item/shield/riot/flash/attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/assembly/flash/handheld))
|
||||
var/obj/item/assembly/flash/handheld/flash = W
|
||||
if(flash.crit_fail)
|
||||
to_chat(user, "<span class='warning'>No sense replacing it with a broken bulb!</span>")
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You begin to replace the bulb...</span>")
|
||||
if(do_after(user, 20, target = user))
|
||||
if(flash.crit_fail || !flash || QDELETED(flash))
|
||||
return
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
|
||||
qdel(embedded_flash)
|
||||
embedded_flash = flash
|
||||
flash.forceMove(src)
|
||||
update_icon()
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/shield/riot/flash/emp_act(severity)
|
||||
. = ..()
|
||||
embedded_flash.emp_act(severity)
|
||||
update_icon()
|
||||
|
||||
/obj/item/shield/riot/flash/update_icon_state()
|
||||
if(!embedded_flash || embedded_flash.crit_fail)
|
||||
icon_state = "riot"
|
||||
item_state = "riot"
|
||||
else
|
||||
icon_state = "flashshield"
|
||||
item_state = "flashshield"
|
||||
|
||||
/obj/item/shield/riot/flash/examine(mob/user)
|
||||
. = ..()
|
||||
if (embedded_flash?.crit_fail)
|
||||
. += "<span class='info'>The mounted bulb has burnt out. You can try replacing it with a new one.</span>"
|
||||
|
||||
/obj/item/shield/riot/tele
|
||||
name = "telescopic shield"
|
||||
desc = "An advanced riot shield made of lightweight materials that collapses for easy storage."
|
||||
@@ -348,7 +463,7 @@
|
||||
|
||||
/obj/item/shield/makeshift
|
||||
name = "metal shield"
|
||||
desc = "A large shield made of wired and welded sheets of metal. The handle is made of cloth and leather making it unwieldy."
|
||||
desc = "A large shield made of wired and welded sheets of metal. The handle is made of cloth and leather, making it unwieldy."
|
||||
armor = list("melee" = 25, "bullet" = 25, "laser" = 5, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 80)
|
||||
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
|
||||
@@ -362,33 +477,34 @@
|
||||
|
||||
/obj/item/shield/riot/tower
|
||||
name = "tower shield"
|
||||
desc = "A massive shield that can block a lot of attacks, can take a lot of abuse before braking."
|
||||
desc = "An immense tower shield. Designed to ensure maximum protection to the user, at the expense of mobility."
|
||||
armor = list("melee" = 95, "bullet" = 95, "laser" = 75, "energy" = 60, "bomb" = 90, "bio" = 90, "rad" = 0, "fire" = 90, "acid" = 10) //Armor for the item, dosnt transfer to user
|
||||
item_state = "metal"
|
||||
icon_state = "metal"
|
||||
force = 16
|
||||
slowdown = 2
|
||||
throwforce = 15 //Massive pice of metal
|
||||
throwforce = 15 //Massive piece of metal
|
||||
max_integrity = 600
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
item_flags = SLOWS_WHILE_IN_HAND
|
||||
item_flags = SLOWS_WHILE_IN_HAND | ITEM_CAN_BLOCK
|
||||
shield_flags = SHIELD_FLAGS_DEFAULT
|
||||
|
||||
/obj/item/shield/riot/tower/swat
|
||||
name = "swat shield"
|
||||
desc = "A massive, heavy shield that can block a lot of attacks, can take a lot of abuse before breaking."
|
||||
max_integrity = 250
|
||||
|
||||
/obj/item/shield/riot/implant
|
||||
name = "telescoping shield implant"
|
||||
desc = "A compact, arm-mounted telescopic shield. While nigh-indestructible when powered by a host user, it will eventually overload from damage. Recharges while inside its implant."
|
||||
item_state = "metal"
|
||||
icon_state = "metal"
|
||||
name = "hardlight shield implant"
|
||||
desc = "A hardlight plane of force projected from the implant. While it is capable of withstanding immense amounts of abuse, it will eventually overload from sustained impacts, especially against energy attacks. Recharges while retracted."
|
||||
item_state = "holoshield"
|
||||
icon_state = "holoshield"
|
||||
slowdown = 1
|
||||
shield_flags = SHIELD_FLAGS_DEFAULT
|
||||
max_integrity = 100
|
||||
obj_integrity = 100
|
||||
can_shatter = FALSE
|
||||
item_flags = SLOWS_WHILE_IN_HAND | ITEM_CAN_BLOCK
|
||||
item_flags = ITEM_CAN_BLOCK
|
||||
shield_flags = SHIELD_FLAGS_DEFAULT | SHIELD_KINETIC_STRONG | SHIELD_DISABLER_DISRUPTED
|
||||
var/recharge_timerid
|
||||
var/recharge_delay = 15 SECONDS
|
||||
|
||||
@@ -400,7 +516,7 @@
|
||||
if(obj_integrity == 0)
|
||||
if(ismob(loc))
|
||||
var/mob/living/L = loc
|
||||
playsound(src, 'sound/effects/glassbr3.ogg', 100)
|
||||
playsound(src, "sparks", 100, TRUE)
|
||||
L.visible_message("<span class='boldwarning'>[src] overloads from the damage sustained!</span>")
|
||||
L.dropItemToGround(src) //implant component catch hook will grab it.
|
||||
|
||||
|
||||
@@ -117,8 +117,8 @@ GLOBAL_LIST_INIT(diamond_recipes, list ( \
|
||||
new/datum/stack_recipe("Captain Statue", /obj/structure/statue/diamond/captain, 5, one_per_turf = 1, on_floor = 1), \
|
||||
new/datum/stack_recipe("AI Hologram Statue", /obj/structure/statue/diamond/ai1, 5, one_per_turf = 1, on_floor = 1), \
|
||||
new/datum/stack_recipe("AI Core Statue", /obj/structure/statue/diamond/ai2, 5, one_per_turf = 1, on_floor = 1), \
|
||||
// new/datum/stack_recipe("diamond brick", /obj/item/ingot/diamond, 6, time = 100), \ not yet
|
||||
))
|
||||
new/datum/stack_recipe("diamond ingot", /obj/item/ingot/diamond, 6, time = 100), \
|
||||
))
|
||||
|
||||
/obj/item/stack/sheet/mineral/diamond/get_main_recipes()
|
||||
. = ..()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/item/storage/box/syndicate
|
||||
|
||||
/obj/item/storage/box/syndicate/PopulateContents()
|
||||
switch (pickweight(list("bloodyspai" = 3, "stealth" = 2, "bond" = 2, "screwed" = 2, "sabotage" = 3, "guns" = 2, "murder" = 2, "baseball" = 1, "implant" = 1, "hacker" = 3, "darklord" = 1, "sniper" = 1, "metaops" = 1, "ninja" = 1)))
|
||||
switch (pickweight(list("bloodyspai" = 3, "stealth" = 2, "bond" = 2, "screwed" = 2, "sabotage" = 3, "guns" = 2, "murder" = 2, "baseball" = 1, "implant" = 1, "hacker" = 3, "darklord" = 1, "sniper" = 1, "metaops" = 1, "ninja" = 1, "ancient" = 1)))
|
||||
if("bloodyspai") // 30 tc now this is more right
|
||||
new /obj/item/clothing/under/chameleon(src) // 2 tc since it's not the full set
|
||||
new /obj/item/clothing/mask/chameleon(src) // Goes with above
|
||||
@@ -154,6 +154,20 @@
|
||||
new /obj/item/storage/belt/chameleon(src) // Unique but worth at least 2 tc
|
||||
new /obj/item/card/id/syndicate(src) // 2 tc
|
||||
new /obj/item/chameleon(src) // 7 tc
|
||||
|
||||
if("ancient") //A kit so old, it's probably older than you. //This bundle is filled with the entire unlink contents traitors had access to in 2006, from OpenSS13. Notably the esword was not a choice but existed in code.
|
||||
new /obj/item/storage/toolbox/emergency/old/ancientbundle(src) //Items fit neatly into a classic toolbox just to remind you what the theme is.
|
||||
|
||||
/obj/item/storage/toolbox/emergency/old/ancientbundle //So the subtype works
|
||||
|
||||
/obj/item/storage/toolbox/emergency/old/ancientbundle/PopulateContents()
|
||||
new /obj/item/card/emag(src)
|
||||
new /obj/item/pen/sleepy(src)
|
||||
new /obj/item/reagent_containers/pill/cyanide(src)
|
||||
new /obj/item/chameleon(src) //its not the original cloaking device, but it will do.
|
||||
new /obj/item/gun/ballistic/revolver(src)
|
||||
new /obj/item/implanter/freedom(src)
|
||||
new /obj/item/stack/telecrystal(src) //The failsafe/self destruct isn't an item we can physically include in the kit, but 1 TC is technically enough to buy the equivalent.
|
||||
|
||||
/obj/item/storage/box/syndie_kit
|
||||
name = "box"
|
||||
|
||||
@@ -662,6 +662,72 @@
|
||||
to_chat(M,"<span class='notice'>You're once again longer hearing deadchat.</span>")
|
||||
|
||||
|
||||
/datum/action/disguise
|
||||
name = "Disguise"
|
||||
button_icon_state = "ling_transform"
|
||||
icon_icon = 'icons/mob/actions/actions_changeling.dmi'
|
||||
background_icon_state = "bg_mime"
|
||||
var/currently_disguised = FALSE
|
||||
var/static/list/mob_blacklist = typecacheof(list(
|
||||
/mob/living/simple_animal/pet,
|
||||
/mob/living/simple_animal/hostile/retaliate/goose,
|
||||
/mob/living/simple_animal/hostile/poison,
|
||||
/mob/living/simple_animal/hostile/retaliate/goat,
|
||||
/mob/living/simple_animal/cow,
|
||||
/mob/living/simple_animal/chick,
|
||||
/mob/living/simple_animal/chicken,
|
||||
/mob/living/simple_animal/kiwi,
|
||||
/mob/living/simple_animal/babyKiwi,
|
||||
/mob/living/simple_animal/deer,
|
||||
/mob/living/simple_animal/parrot,
|
||||
/mob/living/simple_animal/hostile/lizard,
|
||||
/mob/living/simple_animal/crab,
|
||||
/mob/living/simple_animal/cockroach,
|
||||
/mob/living/simple_animal/butterfly,
|
||||
/mob/living/simple_animal/mouse,
|
||||
/mob/living/simple_animal/sloth,
|
||||
/mob/living/simple_animal/opossum,
|
||||
/mob/living/simple_animal/hostile/bear,
|
||||
/mob/living/simple_animal/hostile/asteroid/polarbear,
|
||||
/mob/living/simple_animal/hostile/asteroid/wolf,
|
||||
/mob/living/carbon/monkey,
|
||||
/mob/living/simple_animal/hostile/gorilla,
|
||||
/mob/living/carbon/alien/larva,
|
||||
/mob/living/simple_animal/hostile/retaliate/frog
|
||||
))
|
||||
|
||||
|
||||
/datum/action/disguise/Trigger()
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(!currently_disguised)
|
||||
var/user_object_type = input(H, "Disguising as OBJECT or MOB?") as null|anything in list("OBJECT", "MOB")
|
||||
if(user_object_type)
|
||||
var/search_term = stripped_input(H, "Enter the search term")
|
||||
if(search_term)
|
||||
var/list_to_search
|
||||
if(user_object_type == "MOB")
|
||||
list_to_search = subtypesof(/mob) - mob_blacklist
|
||||
else
|
||||
list_to_search = subtypesof(/obj)
|
||||
var/list/filtered_results = list()
|
||||
for(var/some_search_item in list_to_search)
|
||||
if(findtext("[some_search_item]", search_term))
|
||||
filtered_results += some_search_item
|
||||
if(!length(filtered_results))
|
||||
to_chat(H, "Nothing matched your search query!")
|
||||
else
|
||||
var/disguise_selection = input("Select item to disguise as") as null|anything in filtered_results
|
||||
if(disguise_selection)
|
||||
var/atom/disguise_item = disguise_selection
|
||||
var/image/I = image(icon = initial(disguise_item.icon), icon_state = initial(disguise_item.icon_state), loc = H)
|
||||
I.override = TRUE
|
||||
I.layer = ABOVE_MOB_LAYER
|
||||
H.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "ghost_cafe_disguise", I)
|
||||
currently_disguised = TRUE
|
||||
else
|
||||
H.remove_alt_appearance("ghost_cafe_disguise")
|
||||
currently_disguised = FALSE
|
||||
|
||||
/obj/effect/mob_spawn/human/ghostcafe/special(mob/living/carbon/human/new_spawn)
|
||||
if(new_spawn.client)
|
||||
new_spawn.client.prefs.copy_to(new_spawn)
|
||||
@@ -679,6 +745,8 @@
|
||||
to_chat(new_spawn,"<span class='boldwarning'>Ghosting is free!</span>")
|
||||
var/datum/action/toggle_dead_chat_mob/D = new(new_spawn)
|
||||
D.Grant(new_spawn)
|
||||
var/datum/action/disguise/disguise_action = new(new_spawn)
|
||||
disguise_action.Grant(new_spawn)
|
||||
|
||||
/datum/outfit/ghostcafe
|
||||
name = "ID, jumpsuit and shoes"
|
||||
|
||||
@@ -93,6 +93,9 @@
|
||||
user.stop_pulling()
|
||||
return ..()
|
||||
|
||||
/obj/structure/table/attack_robot(mob/user)
|
||||
on_attack_hand(user)
|
||||
|
||||
/obj/structure/table/attack_tk()
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
desc = "A resilient shield made out of brass.. It feels warm to the touch."
|
||||
var/clockwork_desc = "A powerful shield of ratvarian making. It absorbs blocked attacks to charge devastating bashes."
|
||||
armor = list("melee" = 80, "bullet" = 70, "laser" = -10, "energy" = -20, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
shield_flags = SHIELD_FLAGS_DEFAULT
|
||||
shield_flags = SHIELD_FLAGS_DEFAULT | SHIELD_KINETIC_STRONG | SHIELD_ENERGY_WEAK
|
||||
max_integrity = 300 //High integrity, extremely strong against melee / bullets, but still quite easy to destroy with lasers and energy
|
||||
repair_material = /obj/item/stack/tile/brass
|
||||
var/dam_absorbed = 0
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
/datum/action/innate/heretic_shatter/Activate()
|
||||
if(do_after(holder,10, target = holder))
|
||||
var/turf/safe_turf = find_safe_turf(zlevels = sword.z, extended_safety_checks = TRUE)
|
||||
do_teleport(holder,safe_turf,forceMove = TRUE)
|
||||
do_teleport(holder,safe_turf,forceMove = TRUE,channel=TELEPORT_CHANNEL_MAGIC)
|
||||
to_chat(holder,"<span class='warning'>You feel a gust of energy flow through your body... the Rusted Hills heard your call...</span>")
|
||||
qdel(sword)
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
/datum/eldritch_knowledge/summon/stalker
|
||||
name = "Lonely Ritual"
|
||||
gain_text = "I was able to combine my greed and desires to summon an eldritch beast I had never seen before. An ever shapeshifting mass of flesh, it knew well my goals."
|
||||
desc = "You can now summon a Stalker by transmutating a pair of eyes, a candle, a pen and a piece of paper. Stalkers can shapeshift into harmless animals to get close to the victim."
|
||||
desc = "You can now summon a Stalker by transmutating a kitchen knife, a candle, a pen and a piece of paper. Stalkers can shapeshift into harmless animals to get close to the victim."
|
||||
cost = 1
|
||||
required_atoms = list(/obj/item/kitchen/knife,/obj/item/candle,/obj/item/pen,/obj/item/paper)
|
||||
mob_to_summon = /mob/living/simple_animal/hostile/eldritch/stalker
|
||||
|
||||
@@ -7,7 +7,21 @@
|
||||
earliest_start = 1 HOURS
|
||||
min_players = 20
|
||||
|
||||
|
||||
/datum/round_event_control/slaughter/canSpawnEvent()
|
||||
weight = initial(src.weight)
|
||||
var/list/allowed_turf_typecache = typecacheof(/turf/open) - typecacheof(/turf/open/space)
|
||||
var/list/allowed_z_cache = list()
|
||||
for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION))
|
||||
allowed_z_cache[num2text(z)] = TRUE
|
||||
for(var/obj/effect/decal/cleanable/C in world)
|
||||
if(!C.loc || QDELETED(C))
|
||||
continue
|
||||
if(!C.can_bloodcrawl_in())
|
||||
continue
|
||||
if(!SSpersistence.IsValidDebrisLocation(C.loc, allowed_turf_typecache, allowed_z_cache, C.type, FALSE))
|
||||
continue
|
||||
weight += 0.05
|
||||
return ..()
|
||||
|
||||
/datum/round_event/ghost_role/slaughter
|
||||
minimum_required = 1
|
||||
|
||||
@@ -262,70 +262,6 @@
|
||||
/obj/item/assembly/flash/armimplant/proc/cooldown()
|
||||
overheat = FALSE
|
||||
|
||||
/obj/item/assembly/flash/shield
|
||||
name = "strobe shield"
|
||||
desc = "A shield with a built in, high intensity light capable of blinding and disorienting suspects. Takes regular handheld flashes as bulbs."
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "flashshield"
|
||||
item_state = "flashshield"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
|
||||
slot_flags = ITEM_SLOT_BACK
|
||||
force = 10
|
||||
throwforce = 5
|
||||
throw_speed = 2
|
||||
throw_range = 3
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
custom_materials = list(/datum/material/glass=7500, /datum/material/iron=1000)
|
||||
attack_verb = list("shoved", "bashed")
|
||||
block_chance = 50
|
||||
armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 70)
|
||||
|
||||
/obj/item/assembly/flash/shield/flash_recharge(interval=10)
|
||||
if(times_used >= 4)
|
||||
burn_out()
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/flash/shield/attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/assembly/flash/handheld))
|
||||
var/obj/item/assembly/flash/handheld/flash = W
|
||||
if(flash.crit_fail)
|
||||
to_chat(user, "No sense replacing it with a broken bulb.")
|
||||
return
|
||||
else
|
||||
to_chat(user, "You begin to replace the bulb.")
|
||||
if(do_after(user, 20, target = src))
|
||||
if(flash.crit_fail || !flash || QDELETED(flash))
|
||||
return
|
||||
crit_fail = FALSE
|
||||
times_used = 0
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
|
||||
update_icon()
|
||||
flash.crit_fail = TRUE
|
||||
flash.update_icon()
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/assembly/flash/shield/update_icon(flash = FALSE)
|
||||
icon_state = "flashshield"
|
||||
item_state = "flashshield"
|
||||
|
||||
if(crit_fail)
|
||||
icon_state = "riot"
|
||||
item_state = "riot"
|
||||
else if(flash)
|
||||
icon_state = "flashshield_flash"
|
||||
item_state = "flashshield_flash"
|
||||
addtimer(CALLBACK(src, /atom/.proc/update_icon), 5)
|
||||
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
|
||||
/obj/item/assembly/flash/shield/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
activate()
|
||||
return ..()
|
||||
|
||||
//ported from tg - check to make sure it can't appear where it's not supposed to.
|
||||
/obj/item/assembly/flash/hypnotic
|
||||
desc = "A modified flash device, programmed to emit a sequence of subliminal flashes that can send a vulnerable target into a hypnotic trance."
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
/datum/blackmarket_item/New()
|
||||
if(isnull(price))
|
||||
price = rand(price_min, price_max)
|
||||
price = round(rand(price_min, price_max), 5)
|
||||
if(isnull(stock))
|
||||
stock = rand(stock_min, stock_max)
|
||||
|
||||
|
||||
@@ -51,5 +51,30 @@
|
||||
item = /obj/item/clothing/head/chameleon/broken
|
||||
price_min = 100
|
||||
price_max = 200
|
||||
stock_max = 2
|
||||
availability_prob = 70
|
||||
stock_min = 3
|
||||
stock_max = 7
|
||||
availability_prob = 100
|
||||
|
||||
/datum/blackmarket_item/clothing/earmuffs
|
||||
name = "Earmuffs"
|
||||
desc = "Protect your precious ears from security's flashbangs with this handy device."
|
||||
item = /obj/item/clothing/ears/earmuffs
|
||||
price_min = 100
|
||||
price_max = 200
|
||||
stock_min = 3
|
||||
stock_max = 7
|
||||
availability_prob = 100
|
||||
|
||||
/* commented out until someone wants to port the actual boots
|
||||
* i am unsure they are in accordance with server design ideals
|
||||
|
||||
/datum/blackmarket_item/clothing/rocket_boots
|
||||
name = "Rocket Boots"
|
||||
desc = "We found a pair of jump boots and overclocked the hell out of them. No liability for grevious harm to or with a body."
|
||||
item = /obj/item/clothing/shoes/bhop/rocket
|
||||
price_min = 1500
|
||||
price_max = 3000
|
||||
stock_max = 1
|
||||
availability_prob = 30
|
||||
|
||||
*/
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
name = "Box of Donk Pockets"
|
||||
desc = "A well packaged box containing the favourite snack of every spacefarer."
|
||||
item = /obj/item/storage/box/donkpockets
|
||||
stock_min = 2
|
||||
stock_max = 5
|
||||
price_min = 325
|
||||
price_max = 400
|
||||
availability_prob = 80
|
||||
stock_min = 5
|
||||
stock_max = 10
|
||||
price_min = 250
|
||||
price_max = 350
|
||||
availability_prob = 100
|
||||
|
||||
/datum/blackmarket_item/consumable/suspicious_pills
|
||||
name = "Bottle of Suspicious Pills"
|
||||
@@ -46,13 +46,43 @@
|
||||
stock_max = 35
|
||||
price_min = 10
|
||||
price_max = 60
|
||||
availability_prob = 50
|
||||
availability_prob = 70
|
||||
|
||||
/datum/blackmarket_item/consumable/pumpup
|
||||
name = "Shoddy Stimulants"
|
||||
desc = "Feel the energy inside each needle!"
|
||||
item = /obj/item/reagent_containers/hypospray/medipen/stimpack
|
||||
stock_max = 5
|
||||
price_min = 50
|
||||
price_max = 150
|
||||
availability_prob = 90
|
||||
price_min = 80
|
||||
price_max = 170
|
||||
availability_prob = 70
|
||||
|
||||
/datum/blackmarket_item/consumable/stray_drink
|
||||
name = "A random drink"
|
||||
desc = "A surprise drink direcly from the counter. No refunds if the glass breaks." // it will always break if it's launched at the station
|
||||
item = /obj/item/reagent_containers/food/drinks/drinkingglass
|
||||
stock_min = 10
|
||||
stock_max = 15
|
||||
price_min = 100
|
||||
price_max = 200
|
||||
availability_prob = 100
|
||||
// add new drinks here
|
||||
var/list/counter = list(
|
||||
/datum/reagent/consumable/ethanol/gintonic,
|
||||
/datum/reagent/consumable/ethanol/cuba_libre,
|
||||
/datum/reagent/consumable/ethanol/martini,
|
||||
/datum/reagent/consumable/ethanol/b52,
|
||||
/datum/reagent/consumable/ethanol/manhattan,
|
||||
/datum/reagent/consumable/ethanol/bahama_mama,
|
||||
/datum/reagent/consumable/ethanol/syndicatebomb,
|
||||
/datum/reagent/consumable/ethanol/quadruple_sec
|
||||
)
|
||||
|
||||
// i found no other way to fill a glass with a random reagent at runtime. and i definitely was not going to do the same done in bottle.dm
|
||||
/datum/blackmarket_item/consumable/stray_drink/spawn_item(loc)
|
||||
var/obj/item/reagent_containers/food/drinks/drinkingglass/drink = new item(loc)
|
||||
var/picked = pick(counter)
|
||||
drink.list_reagents = list()
|
||||
drink.list_reagents[picked] = 50
|
||||
drink.add_initial_reagents()
|
||||
return drink
|
||||
|
||||
@@ -10,6 +10,15 @@
|
||||
stock_max = 6
|
||||
availability_prob = 80
|
||||
|
||||
/datum/blackmarket_item/misc/clear_pda
|
||||
name = "Clear PDA"
|
||||
desc = "Show off your style with this limited edition clear PDA!."
|
||||
item = /obj/item/pda/clear
|
||||
price_min = 250
|
||||
price_max = 600
|
||||
stock_max = 4
|
||||
availability_prob = 50
|
||||
|
||||
/datum/blackmarket_item/misc/shoulder_holster
|
||||
name = "Shoulder holster"
|
||||
desc = "Yeehaw, hardboiled friends! This holster is the first step in your dream of becoming a detective and being allowed to shoot real guns!"
|
||||
@@ -37,11 +46,11 @@
|
||||
name = "Strange Seeds"
|
||||
desc = "An Exotic Variety of seed that can contain anything from glow to acid."
|
||||
item = /obj/item/seeds/random
|
||||
price_min = 320
|
||||
price_max = 360
|
||||
price_min = 450
|
||||
price_max = 650
|
||||
stock_min = 2
|
||||
stock_max = 5
|
||||
availability_prob = 50
|
||||
availability_prob = 100
|
||||
|
||||
/datum/blackmarket_item/misc/smugglers_satchel
|
||||
name = "Smuggler's Satchel"
|
||||
@@ -51,3 +60,14 @@
|
||||
price_max = 1000
|
||||
stock_max = 2
|
||||
availability_prob = 30
|
||||
|
||||
/datum/blackmarket_item/misc/internals_box
|
||||
name = "Internals Box"
|
||||
desc = "The same one Nanotrasen gives you before starting the shift. Totally not stolen from a dead space-man floating in space."
|
||||
item = /obj/item/storage/box/survival
|
||||
price_min = 250
|
||||
price_max = 350
|
||||
stock_min = 3
|
||||
stock_max = 6
|
||||
availability_prob = 100
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
name = "Thermite Bottle"
|
||||
desc = "30 units of Thermite to assist in creating a quick access point or get away!"
|
||||
item = /obj/item/reagent_containers/glass/bottle/thermite
|
||||
price_min = 500
|
||||
price_min = 750
|
||||
price_max = 1500
|
||||
stock_max = 3
|
||||
availability_prob = 30
|
||||
@@ -68,7 +68,18 @@
|
||||
name = "Science Goggles"
|
||||
desc = "These glasses scan the contents of containers and projects their contents to the user in an easy-to-read format."
|
||||
item = /obj/item/clothing/glasses/science
|
||||
price_min = 150
|
||||
price_max = 200
|
||||
stock_max = 3
|
||||
availability_prob = 50
|
||||
price_min = 200
|
||||
price_max = 300
|
||||
stock_min = 3
|
||||
stock_max = 7
|
||||
availability_prob = 100
|
||||
|
||||
/datum/blackmarket_item/tool/meson_goggles
|
||||
name = "Meson Goggles"
|
||||
desc = "These let you see through walls and inspect other structures."
|
||||
item = /obj/item/clothing/glasses/meson
|
||||
price_min = 200
|
||||
price_max = 300
|
||||
stock_min = 3
|
||||
stock_max = 7
|
||||
availability_prob = 100
|
||||
|
||||
@@ -28,14 +28,23 @@
|
||||
item = /obj/item/spear/bonespear
|
||||
price_min = 200
|
||||
price_max = 300
|
||||
stock_max = 3
|
||||
availability_prob = 60
|
||||
stock_max = 0
|
||||
availability_prob = 0
|
||||
|
||||
/datum/blackmarket_item/weapon/emp_grenade
|
||||
name = "EMP Grenade"
|
||||
desc = "Use this grenade for SHOCKING results!"
|
||||
item = /obj/item/grenade/empgrenade
|
||||
price_min = 100
|
||||
price_max = 400
|
||||
price_min = 300
|
||||
price_max = 600
|
||||
stock_max = 2
|
||||
availability_prob = 50
|
||||
availability_prob = 20
|
||||
|
||||
/datum/blackmarket_item/weapon/smoke_grenade
|
||||
name = "Smoke Grenade"
|
||||
desc = "Used for obcuring a large area with thick smoke."
|
||||
item = /obj/item/grenade/smokebomb
|
||||
price_min = 100
|
||||
price_max = 300
|
||||
stock_max = 3
|
||||
availability_prob = 40
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/obj/item/blackmarket_uplink
|
||||
name = "Black Market Uplink"
|
||||
desc = "A mishmash of a subspace amplifier, a radio, and an analyzer. Somehow able to access the black market, with a variable inventory in limited stock at inflated prices. No refunds, customer responsible for pick-ups."
|
||||
icon = 'icons/obj/blackmarket.dmi'
|
||||
icon_state = "uplink"
|
||||
// UI variables.
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
name = "Strobe Shield"
|
||||
description = "One of our Emergency Response Agents thinks there's vampires in a local station. Send him something to help with his fear of the dark and protect him, too."
|
||||
reward = 3000
|
||||
wanted_types = list(/obj/item/assembly/flash/shield)
|
||||
wanted_types = list(/obj/item/shield/riot/flash)
|
||||
|
||||
/datum/bounty/item/security/sechuds
|
||||
name = "Sec HUDs"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
/datum/export/weapon/riot_shield
|
||||
cost = 70
|
||||
unit_name = "flash shield"
|
||||
export_types = list(/obj/item/assembly/flash/shield)
|
||||
export_types = list(/obj/item/shield/riot/flash)
|
||||
|
||||
/datum/export/weapon/tele_shield
|
||||
cost = 100
|
||||
@@ -138,7 +138,7 @@
|
||||
export_types = list(/obj/item/gun/energy/xray)
|
||||
|
||||
/datum/export/weapon/ioncarbine
|
||||
cost = 200
|
||||
cost = 200
|
||||
unit_name = "ion carbine"
|
||||
export_types = list(/obj/item/gun/energy/ionrifle/carbine)
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@
|
||||
|
||||
/datum/supply_pack/service/replacementdb
|
||||
name = "Replacement Defensive Bar Shotgun"
|
||||
desc = "Someone stole the Bartender's twin-barreled possession? Give them another one at a significant markup. Comes with one unused double-barrel shotgun, shells not included. Requires bartender access to open."
|
||||
desc = "Someone stole the Bartender's twin-barreled possession? Give them another one at a significant markup. Comes with one unused double-barrel shotgun, additional shells not included. Requires bartender access to open."
|
||||
cost = 2200
|
||||
access = ACCESS_BAR
|
||||
contraband = TRUE
|
||||
|
||||
@@ -148,11 +148,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
//Job preferences 2.0 - indexed by job title , no key or value implies never
|
||||
var/list/job_preferences = list()
|
||||
|
||||
// Want randomjob if preferences already filled - Donkie
|
||||
// Want randomjob if preferences already filled - Donkie
|
||||
var/joblessrole = BERANDOMJOB //defaults to 1 for fewer assistants
|
||||
|
||||
// 0 = character settings, 1 = game preferences
|
||||
var/current_tab = 0
|
||||
var/current_tab = SETTINGS_TAB
|
||||
|
||||
var/unlock_content = 0
|
||||
|
||||
@@ -274,13 +274,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
update_preview_icon(current_tab)
|
||||
var/list/dat = list("<center>")
|
||||
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=0' [current_tab == 0 ? "class='linkOn'" : ""]>Character Settings</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=2' [current_tab == 2 ? "class='linkOn'" : ""]>Character Appearance</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=3' [current_tab == 3 ? "class='linkOn'" : ""]>Character Speech</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=4' [current_tab == 4 ? "class='linkOn'" : ""]>Loadout</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=1' [current_tab == 1 ? "class='linkOn'" : ""]>Game Preferences</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=5' [current_tab == 5 ? "class='linkOn'" : ""]>Content Preferences</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=6' [current_tab == 6 ? "class='linkOn'" : ""]>Keybindings</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=[SETTINGS_TAB]' [current_tab == SETTINGS_TAB ? "class='linkOn'" : ""]>Character Settings</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=[APPEARANCE_TAB]' [current_tab == APPEARANCE_TAB ? "class='linkOn'" : ""]>Character Appearance</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=[SPEECH_TAB]' [current_tab == SPEECH_TAB ? "class='linkOn'" : ""]>Character Speech</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=[LOADOUT_TAB]' [current_tab == LOADOUT_TAB ? "class='linkOn'" : ""]>Loadout</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=[GAME_PREFERENCES_TAB]' [current_tab == GAME_PREFERENCES_TAB ? "class='linkOn'" : ""]>Game Preferences</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=[CONTENT_PREFERENCES_TAB]' [current_tab == CONTENT_PREFERENCES_TAB ? "class='linkOn'" : ""]>Content Preferences</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=[KEYBINDINGS_TAB]' [current_tab == KEYBINDINGS_TAB ? "class='linkOn'" : ""]>Keybindings</a>"
|
||||
|
||||
if(!path)
|
||||
dat += "<div class='notice'>Please create an account to save your preferences</div>"
|
||||
@@ -290,7 +290,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<HR>"
|
||||
|
||||
switch(current_tab)
|
||||
if (0) // Character Settings#
|
||||
if(SETTINGS_TAB) // Character Settings#
|
||||
if(path)
|
||||
var/savefile/S = new /savefile(path)
|
||||
if(S)
|
||||
@@ -366,7 +366,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "</tr></table>"
|
||||
|
||||
//Character Appearance
|
||||
if(2)
|
||||
if(APPEARANCE_TAB)
|
||||
if(path)
|
||||
var/savefile/S = new /savefile(path)
|
||||
if(S)
|
||||
@@ -670,7 +670,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "</td>"
|
||||
dat += "</tr></table>"
|
||||
|
||||
if(3)
|
||||
if(SPEECH_TAB)
|
||||
if(path)
|
||||
var/savefile/S = new /savefile(path)
|
||||
if(S)
|
||||
@@ -700,7 +700,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "</td>"
|
||||
dat += "</tr></table>"
|
||||
|
||||
if (1) // Game Preferences
|
||||
if(GAME_PREFERENCES_TAB) // Game Preferences
|
||||
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
|
||||
dat += "<h2>General Settings</h2>"
|
||||
dat += "<b>UI Style:</b> <a href='?_src_=prefs;task=input;preference=ui'>[UI_style]</a><br>"
|
||||
@@ -871,7 +871,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
dat += "<br>"
|
||||
|
||||
if(4)
|
||||
if(LOADOUT_TAB)
|
||||
//calculate your gear points from the chosen item
|
||||
gear_points = CONFIG_GET(number/initial_gear_points)
|
||||
var/list/chosen_gear = loadout_data["SAVE_[loadout_slot]"]
|
||||
@@ -990,7 +990,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "</td><td><font size=2><i>[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description] Progress: [min(progress_made, unlockable.progress_required)]/[unlockable.progress_required]</i></font></td></tr>"
|
||||
|
||||
dat += "</table>"
|
||||
if(5) // Content preferences
|
||||
if(CONTENT_PREFERENCES_TAB) // Content preferences
|
||||
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
|
||||
dat += "<h2>Fetish content prefs</h2>"
|
||||
dat += "<b>Arousal:</b><a href='?_src_=prefs;preference=arousable'>[arousable == TRUE ? "Enabled" : "Disabled"]</a><BR>"
|
||||
@@ -1014,7 +1014,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<b>Automatic Wagging:</b> <a href='?_src_=prefs;preference=auto_wag'>[(cit_toggles & NO_AUTO_WAG) ? "Disabled" : "Enabled"]</a><br>"
|
||||
dat += "</tr></table>"
|
||||
dat += "<br>"
|
||||
if(6) // Custom keybindings
|
||||
if(KEYBINDINGS_TAB) // Custom keybindings
|
||||
dat += "<b>Keybindings:</b> <a href='?_src_=prefs;preference=hotkeys'>[(hotkeys) ? "Hotkeys" : "Input"]</a><br>"
|
||||
dat += "Keybindings mode controls how the game behaves with tab and map/input focus.<br>If it is on <b>Hotkeys</b>, the game will always attempt to force you to map focus, meaning keypresses are sent \
|
||||
directly to the map instead of the input. You will still be able to use the command bar, but you need to tab to do it every time you click on the game map.<br>\
|
||||
@@ -2721,7 +2721,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
save_character()
|
||||
|
||||
if("tab")
|
||||
if (href_list["tab"])
|
||||
if(href_list["tab"])
|
||||
current_tab = text2num(href_list["tab"])
|
||||
if(href_list["preference"] == "gear")
|
||||
if(href_list["clear_loadout"])
|
||||
|
||||
@@ -277,7 +277,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/under/chameleon)
|
||||
item_state = "bl_suit"
|
||||
desc = "It's a plain jumpsuit. It has a small dial on the wrist."
|
||||
sensor_mode = SENSOR_OFF //Hey who's this guy on the Syndicate Shuttle??
|
||||
random_sensor = FALSE
|
||||
sensor_flags = NONE
|
||||
resistance_flags = NONE
|
||||
can_adjust = FALSE
|
||||
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
|
||||
|
||||
@@ -233,7 +233,7 @@
|
||||
/obj/item/clothing/examine(mob/user)
|
||||
. = ..()
|
||||
if(damaged_clothes == CLOTHING_SHREDDED)
|
||||
. += "<span class='warning'><b>It is completely shredded and requires mending before it can be worn again!</b></span>"
|
||||
. += "<span class='warning'><b>It is completely shredded and requires mending!</b></span>"
|
||||
return
|
||||
for(var/zone in damage_by_parts)
|
||||
var/pct_damage_part = damage_by_parts[zone] / limb_integrity * 100
|
||||
@@ -437,12 +437,10 @@ BLIND // can't see anything
|
||||
damaged_clothes = CLOTHING_SHREDDED
|
||||
body_parts_covered = NONE
|
||||
name = "shredded [initial(name)]"
|
||||
slot_flags = NONE
|
||||
update_clothes_damaged_state()
|
||||
update_clothes_damaged_state(CLOTHING_SHREDDED)
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
M.visible_message("<span class='danger'>[M]'s [src.name] falls off, completely shredded!</span>", "<span class='warning'><b>Your [src.name] falls off, completely shredded!</b></span>", vision_distance = COMBAT_MESSAGE_RANGE)
|
||||
M.dropItemToGround(src)
|
||||
M.visible_message("<span class='danger'>[M]'s [src.name] is completely shredded!</span>", "<span class='userdanger'>Your [src.name] is completely shredded!</span>", vision_distance = COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
@@ -78,10 +78,40 @@
|
||||
speech_args[SPEECH_MESSAGE] = trim(message)
|
||||
|
||||
/obj/item/clothing/mask/joy
|
||||
name = "joy mask"
|
||||
desc = "Express your happiness or hide your sorrows with this laughing face with crying tears of joy cutout."
|
||||
name = "Emotional Mask"
|
||||
desc = "Express your happiness or hide your sorrows with this modular cutout."
|
||||
icon_state = "joy"
|
||||
clothing_flags = ALLOWINTERNALS
|
||||
mutantrace_variation = STYLE_MUZZLE
|
||||
actions_types = list(/datum/action/item_action/adjust)
|
||||
var/static/list/joymask_designs = list()
|
||||
|
||||
|
||||
/obj/item/clothing/mask/joy/Initialize(mapload)
|
||||
. = ..()
|
||||
joymask_designs = list(
|
||||
"Joy" = image(icon = src.icon, icon_state = "joy"),
|
||||
"Flushed" = image(icon = src.icon, icon_state = "flushed"),
|
||||
"Pensive" = image(icon = src.icon, icon_state = "pensive"),
|
||||
"Angry" = image(icon = src.icon, icon_state = "angry"),
|
||||
)
|
||||
|
||||
/obj/item/clothing/mask/joy/ui_action_click(mob/user)
|
||||
if(!istype(user) || user.incapacitated())
|
||||
return
|
||||
|
||||
var/static/list/options = list("Joy" = "joy", "Flushed" = "flushed", "Pensive" = "pensive","Angry" ="angry")
|
||||
|
||||
var/choice = show_radial_menu(user, src, joymask_designs, custom_check = FALSE, radius = 36, require_near = TRUE)
|
||||
|
||||
if(src && choice && !user.incapacitated() && in_range(user,src))
|
||||
icon_state = options[choice]
|
||||
user.update_inv_wear_mask()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
to_chat(user, "<span class='notice'>Your Joy mask now has a [choice] Emotion!</span>")
|
||||
return 1
|
||||
|
||||
/obj/item/clothing/mask/pig
|
||||
name = "pig mask"
|
||||
|
||||
@@ -7,11 +7,14 @@
|
||||
slot_flags = ITEM_SLOT_ICLOTHING
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|USE_TAUR_CLIP_MASK
|
||||
limb_integrity = 30
|
||||
limb_integrity = 120
|
||||
var/fitted = FEMALE_UNIFORM_FULL // For use in alternate clothing styles for women
|
||||
var/has_sensor = HAS_SENSORS // For the crew computer
|
||||
var/random_sensor = TRUE
|
||||
var/sensor_flags = SENSOR_RANDOM
|
||||
var/sensor_mode = NO_SENSORS
|
||||
var/sensor_mode_intended = NO_SENSORS //if sensors become damaged and are repaired later, it will revert to the user's intended preferences
|
||||
var/sensormaxintegrity = 200 //if this is zero, then our sensors can only be destroyed by shredded clothing
|
||||
var/sensordamage = 0 //how much damage did our sensors take?
|
||||
var/can_adjust = TRUE
|
||||
var/adjusted = NORMAL_STYLE
|
||||
var/alt_covers_chest = FALSE // for adjusted/rolled-down jumpsuits, FALSE = exposes chest and arms, TRUE = exposes arms only
|
||||
@@ -31,30 +34,76 @@
|
||||
. += accessory_overlay
|
||||
|
||||
/obj/item/clothing/under/attackby(obj/item/I, mob/user, params)
|
||||
if((has_sensor == BROKEN_SENSORS) && istype(I, /obj/item/stack/cable_coil))
|
||||
if(damaged_clothes)
|
||||
to_chat(user,"<span class='warning'>You should repair the damage done to [src] first.</span>")
|
||||
if((sensordamage || (has_sensor < HAS_SENSORS && has_sensor != NO_SENSORS)) && istype(I, /obj/item/stack/cable_coil))
|
||||
if(damaged_clothes == CLOTHING_SHREDDED)
|
||||
to_chat(user,"<span class='warning'>[src] is too damaged to have its suit sensors repaired! Repair it first.</span>")
|
||||
return 0
|
||||
var/obj/item/stack/cable_coil/C = I
|
||||
I.use_tool(src, user, 0, 1)
|
||||
has_sensor = HAS_SENSORS
|
||||
sensordamage = 0
|
||||
sensor_mode = sensor_mode_intended
|
||||
to_chat(user,"<span class='notice'>You repair the suit sensors on [src] with [C].</span>")
|
||||
return 1
|
||||
|
||||
if(!attach_accessory(I, user))
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/under/take_damage_zone(def_zone, damage_amount, damage_type, armour_penetration)
|
||||
..()
|
||||
if(sensormaxintegrity == 0 || has_sensor == NO_SENSORS || sensordamage >= sensormaxintegrity) return //sensors are invincible if max integrity is 0
|
||||
var/damage_dealt = take_damage(damage_amount * 0.1, damage_type, armour_penetration, FALSE) * 10 // only deal 10% of the damage to the general integrity damage, then multiply it by 10 so we know how much to deal to limb
|
||||
sensordamage += damage_dealt
|
||||
var/integ = has_sensor
|
||||
var/newinteg = sensorintegrity()
|
||||
if(newinteg != integ)
|
||||
if(newinteg < integ && iscarbon(src.loc)) //the first check is to see if for some inexplicable reason the attack healed our suit sensors
|
||||
var/mob/living/carbon/C = src.loc
|
||||
switch(newinteg)
|
||||
if(DAMAGED_SENSORS_VITALS)
|
||||
to_chat(C,"<span class='warning'>Your tracking beacon on your suit sensors have shorted out!</span>")
|
||||
if(DAMAGED_SENSORS_LIVING)
|
||||
to_chat(C,"<span class='warning'>Your vital tracker on your suit sensors have shorted out!</span>")
|
||||
if(BROKEN_SENSORS)
|
||||
to_chat(C,"<span class='userdanger'>Your suit sensors have shorted out completely!</span>")
|
||||
updatesensorintegrity(newinteg)
|
||||
|
||||
|
||||
/obj/item/clothing/under/proc/sensorintegrity()
|
||||
var/percentage = sensordamage/sensormaxintegrity //calculate the percentage of how much damage taken
|
||||
if(percentage < SENSOR_INTEGRITY_COORDS) return HAS_SENSORS
|
||||
else if(percentage < SENSOR_INTEGRITY_VITALS) return DAMAGED_SENSORS_VITALS
|
||||
else if(percentage < SENSOR_INTEGRITY_BINARY) return DAMAGED_SENSORS_LIVING
|
||||
else return BROKEN_SENSORS
|
||||
|
||||
/obj/item/clothing/under/proc/updatesensorintegrity(integ = HAS_SENSORS)
|
||||
if(sensormaxintegrity == 0 || has_sensor == NO_SENSORS) return //sanity check
|
||||
has_sensor = integ
|
||||
switch(has_sensor)
|
||||
if(HAS_SENSORS)
|
||||
sensor_mode = sensor_mode_intended
|
||||
if(DAMAGED_SENSORS_VITALS)
|
||||
if(sensor_mode > SENSOR_VITALS) sensor_mode = SENSOR_VITALS
|
||||
if(DAMAGED_SENSORS_LIVING)
|
||||
if(sensor_mode > SENSOR_LIVING) sensor_mode = SENSOR_LIVING
|
||||
if(BROKEN_SENSORS)
|
||||
sensor_mode = NO_SENSORS
|
||||
|
||||
|
||||
/obj/item/clothing/under/update_clothes_damaged_state()
|
||||
..()
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
M.update_inv_w_uniform()
|
||||
if(has_sensor > NO_SENSORS)
|
||||
if(has_sensor > NO_SENSORS && damaged_clothes == CLOTHING_SHREDDED)
|
||||
has_sensor = BROKEN_SENSORS
|
||||
sensordamage = sensormaxintegrity
|
||||
|
||||
/obj/item/clothing/under/New()
|
||||
if(random_sensor)
|
||||
if(sensor_flags & SENSOR_RANDOM)
|
||||
//make the sensor mode favor higher levels, except coords.
|
||||
sensor_mode = pick(SENSOR_OFF, SENSOR_LIVING, SENSOR_LIVING, SENSOR_VITALS, SENSOR_VITALS, SENSOR_VITALS, SENSOR_COORDS, SENSOR_COORDS)
|
||||
sensor_mode_intended = sensor_mode
|
||||
..()
|
||||
|
||||
/obj/item/clothing/under/equipped(mob/user, slot)
|
||||
@@ -143,9 +192,14 @@
|
||||
. += "Alt-click on [src] to wear it normally."
|
||||
else
|
||||
. += "Alt-click on [src] to wear it casually."
|
||||
if (has_sensor == BROKEN_SENSORS)
|
||||
. += "Its sensors appear to be shorted out."
|
||||
else if(has_sensor > NO_SENSORS)
|
||||
switch(has_sensor)
|
||||
if(BROKEN_SENSORS)
|
||||
. += "<span class='warning'>Its sensors appear to be shorted out completely. It can be repaired using cable.</span>"
|
||||
if(DAMAGED_SENSORS_LIVING)
|
||||
. += "<span class='warning'>Its sensors appear to have its tracking beacon and vital tracker broken. It can be repaired using cable.</span>"
|
||||
if(DAMAGED_SENSORS_VITALS)
|
||||
. += "<span class='warning'>Its sensors appear to have its tracking beacon broken. It can be repaired using cable.</span>"
|
||||
if(has_sensor > NO_SENSORS)
|
||||
switch(sensor_mode)
|
||||
if(SENSOR_OFF)
|
||||
. += "Its sensors appear to be disabled."
|
||||
@@ -167,12 +221,12 @@
|
||||
return
|
||||
if (!can_use(M))
|
||||
return
|
||||
if(src.has_sensor == LOCKED_SENSORS)
|
||||
to_chat(usr, "The controls are locked.")
|
||||
return 0
|
||||
if(src.has_sensor == BROKEN_SENSORS)
|
||||
to_chat(usr, "The sensors have shorted out!")
|
||||
return 0
|
||||
if(src.sensor_flags & SENSOR_LOCKED)
|
||||
to_chat(usr, "The controls are locked.")
|
||||
return 0
|
||||
if(src.has_sensor <= NO_SENSORS)
|
||||
to_chat(usr, "This suit does not have any sensors.")
|
||||
return 0
|
||||
@@ -182,18 +236,34 @@
|
||||
if(get_dist(usr, src) > 1)
|
||||
to_chat(usr, "<span class='warning'>You have moved too far away!</span>")
|
||||
return
|
||||
sensor_mode = modes.Find(switchMode) - 1
|
||||
sensor_mode_intended = modes.Find(switchMode) - 1
|
||||
|
||||
if (src.loc == usr)
|
||||
switch(sensor_mode)
|
||||
switch(sensor_mode_intended)
|
||||
if(0)
|
||||
to_chat(usr, "<span class='notice'>You disable your suit's remote sensing equipment.</span>")
|
||||
sensor_mode = sensor_mode_intended
|
||||
if(1)
|
||||
to_chat(usr, "<span class='notice'>Your suit will now only report whether you are alive or dead.</span>")
|
||||
sensor_mode = sensor_mode_intended
|
||||
if(2)
|
||||
to_chat(usr, "<span class='notice'>Your suit will now only report your exact vital lifesigns.</span>")
|
||||
if(src.has_sensor == DAMAGED_SENSORS_LIVING)
|
||||
to_chat(usr, "<span class='warning'>Your suit's vital tracker is broken, so it will only report whether you are alive or dead.</span>")
|
||||
sensor_mode = SENSOR_LIVING
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>Your suit will now only report your exact vital lifesigns.</span>")
|
||||
sensor_mode = sensor_mode_intended
|
||||
if(3)
|
||||
to_chat(usr, "<span class='notice'>Your suit will now report your exact vital lifesigns as well as your coordinate position.</span>")
|
||||
switch(src.has_sensor)
|
||||
if(DAMAGED_SENSORS_LIVING)
|
||||
to_chat(usr, "<span class='warning'>Your suit's tracking beacon and vital tracker is broken, so it will only report whether you are alive or dead.</span>")
|
||||
sensor_mode = SENSOR_LIVING
|
||||
if(DAMAGED_SENSORS_VITALS)
|
||||
to_chat(usr, "<span class='warning'>Your suit's tracking beacon is broken, so it will only report your vital lifesigns.</span>")
|
||||
sensor_mode = SENSOR_VITALS
|
||||
if(HAS_SENSORS)
|
||||
to_chat(usr, "<span class='notice'>Your suit will now report your exact vital lifesigns as well as your coordinate position.</span>")
|
||||
sensor_mode = sensor_mode_intended
|
||||
|
||||
if(ishuman(loc))
|
||||
var/mob/living/carbon/human/H = loc
|
||||
@@ -210,19 +280,28 @@
|
||||
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
|
||||
if(has_sensor == LOCKED_SENSORS)
|
||||
to_chat(user, "The controls are locked.")
|
||||
return
|
||||
if(has_sensor == BROKEN_SENSORS)
|
||||
to_chat(user, "The sensors have shorted out!")
|
||||
return
|
||||
if(src.has_sensor == BROKEN_SENSORS)
|
||||
to_chat(usr, "The sensors have shorted out!")
|
||||
return 0
|
||||
if(src.sensor_flags & SENSOR_LOCKED)
|
||||
to_chat(usr, "The controls are locked.")
|
||||
return 0
|
||||
if(has_sensor <= NO_SENSORS)
|
||||
to_chat(user, "This suit does not have any sensors.")
|
||||
return
|
||||
|
||||
sensor_mode = SENSOR_COORDS
|
||||
sensor_mode_intended = SENSOR_COORDS
|
||||
|
||||
to_chat(user, "<span class='notice'>Your suit will now report your exact vital lifesigns as well as your coordinate position.</span>")
|
||||
switch(src.has_sensor)
|
||||
if(DAMAGED_SENSORS_LIVING)
|
||||
to_chat(usr, "<span class='warning'>Your suit's tracking beacon and vital tracker is broken, so it will only report whether you are alive or dead.</span>")
|
||||
sensor_mode = SENSOR_LIVING
|
||||
if(DAMAGED_SENSORS_VITALS)
|
||||
to_chat(usr, "<span class='warning'>Your suit's tracking beacon is broken, so it will only report your vital lifesigns.</span>")
|
||||
sensor_mode = SENSOR_VITALS
|
||||
if(HAS_SENSORS)
|
||||
to_chat(usr, "<span class='notice'>Your suit will now report your exact vital lifesigns as well as your coordinate position.</span>")
|
||||
sensor_mode = sensor_mode_intended
|
||||
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
item_state = "captain_envirosuit"
|
||||
armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95, "wound" = 15)
|
||||
sensor_mode = SENSOR_COORDS
|
||||
random_sensor = FALSE
|
||||
sensor_flags = NONE
|
||||
|
||||
/obj/item/clothing/under/plasmaman/mime
|
||||
name = "mime envirosuit"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
item_state = "security_envirosuit"
|
||||
armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95, "wound" = 10)
|
||||
sensor_mode = SENSOR_COORDS
|
||||
random_sensor = FALSE
|
||||
sensor_flags = NONE
|
||||
|
||||
/obj/item/clothing/under/plasmaman/security/warden
|
||||
name = "warden plasma envirosuit"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
item_state = "b_suit"
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 15)
|
||||
sensor_mode = SENSOR_COORDS
|
||||
random_sensor = FALSE
|
||||
sensor_flags = NONE
|
||||
|
||||
/obj/item/clothing/under/rank/captain/util
|
||||
name = "command utility uniform"
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
strip_delay = 50
|
||||
alt_covers_chest = TRUE
|
||||
sensor_mode = SENSOR_COORDS
|
||||
random_sensor = FALSE
|
||||
sensor_flags = NONE
|
||||
|
||||
/obj/item/clothing/under/rank/security/officer
|
||||
name = "security jumpsuit"
|
||||
|
||||
@@ -23,16 +23,15 @@
|
||||
name = "prison jumpsuit"
|
||||
desc = "It's standardised Nanotrasen prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position."
|
||||
icon_state = "prisoner"
|
||||
item_state = "o_suit"
|
||||
has_sensor = LOCKED_SENSORS
|
||||
item_state = "prisoner"
|
||||
sensor_mode = SENSOR_COORDS
|
||||
random_sensor = FALSE
|
||||
sensor_flags = SENSOR_LOCKED
|
||||
|
||||
/obj/item/clothing/under/rank/prisoner/skirt
|
||||
name = "prison jumpskirt"
|
||||
desc = "It's standardised Nanotrasen prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position."
|
||||
icon_state = "prisoner_skirt"
|
||||
item_state = "o_suit"
|
||||
item_state = "prisoner_skirt"
|
||||
body_parts_covered = CHEST|GROIN|ARMS
|
||||
can_adjust = FALSE
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
@@ -166,6 +165,7 @@
|
||||
/obj/item/clothing/under/misc/gear_harness
|
||||
name = "gear harness"
|
||||
desc = "A simple, inconspicuous harness replacement for a jumpsuit."
|
||||
limb_integrity = 180
|
||||
icon_state = "gear_harness"
|
||||
item_state = "gear_harness"
|
||||
can_adjust = TRUE
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
supernova.power_mod = 0
|
||||
|
||||
/datum/round_event/supernova/announce()
|
||||
var/message = "Our tachyon-doppler array has detected a supernova in your vicinity. Peak flux from the supernova estimated to be [round(power,0.1)] times current solar flux. [power > 4 ? "Short burts of radiation may be possible, so please prepare accordingly." : ""]"
|
||||
var/message = "Our tachyon-doppler array has detected a supernova in your vicinity. Peak flux from the supernova estimated to be [round(power,0.1)] times current solar flux. [power > 1 ? "Short burts of radiation may be possible, so please prepare accordingly." : ""]"
|
||||
if(prob(power * 25))
|
||||
priority_announce(message)
|
||||
else
|
||||
@@ -47,12 +47,11 @@
|
||||
|
||||
/datum/round_event/supernova/tick()
|
||||
var/midpoint = round((endWhen-startWhen)/2)
|
||||
switch(activeFor)
|
||||
if(startWhen to midpoint)
|
||||
supernova.power_mod = min(supernova.power_mod*1.2, power)
|
||||
if(endWhen-10 to endWhen)
|
||||
supernova.power_mod /= 4
|
||||
if(prob(round(supernova.power_mod / 2)) && storm_count < 4 && !SSweather.get_weather_by_type(/datum/weather/rad_storm))
|
||||
if(activeFor < midpoint)
|
||||
supernova.power_mod = min(supernova.power_mod*1.2, power)
|
||||
if(activeFor > endWhen-10)
|
||||
supernova.power_mod /= 4
|
||||
if(prob(round(supernova.power_mod)) && prob(5) && storm_count < 5 && !SSweather.get_weather_by_type(/datum/weather/rad_storm))
|
||||
SSweather.run_weather(/datum/weather/rad_storm/supernova)
|
||||
storm_count++
|
||||
|
||||
@@ -63,5 +62,7 @@
|
||||
/datum/weather/rad_storm/supernova
|
||||
weather_duration_lower = 50
|
||||
weather_duration_upper = 100
|
||||
telegraph_duration = 100
|
||||
radiation_intensity = 50
|
||||
telegraph_duration = 200
|
||||
radiation_intensity = 1000
|
||||
weather_sound = null
|
||||
telegraph_message = "<span class='userdanger'>The air begins to grow very warm!</span>"
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
desc = "It's watching you suspiciously."
|
||||
|
||||
/obj/structure/closet/crate/necropolis/tendril/magic/PopulateContents()
|
||||
var/loot = rand(1,10)
|
||||
var/loot = rand(1,9)
|
||||
switch(loot)
|
||||
if(1)
|
||||
new /obj/item/soulstone/anybody(src)
|
||||
@@ -57,10 +57,6 @@
|
||||
new /obj/item/immortality_talisman(src)
|
||||
if(9)
|
||||
new /obj/item/gun/magic/wand/book/healing(src)
|
||||
if(10)
|
||||
new /obj/item/reagent_containers/glass/bottle/ichor/red(src)
|
||||
new /obj/item/reagent_containers/glass/bottle/ichor/blue(src)
|
||||
new /obj/item/reagent_containers/glass/bottle/ichor/green(src)
|
||||
|
||||
/obj/structure/closet/crate/necropolis/tendril/weapon_armor/PopulateContents()
|
||||
var/loot = rand(1,11)
|
||||
@@ -132,7 +128,7 @@
|
||||
new /obj/item/disk/design_disk/modkit_disc/rapid_repeater(src)
|
||||
|
||||
/obj/structure/closet/crate/necropolis/tendril/all/PopulateContents()
|
||||
var/loot = rand(1,29)
|
||||
var/loot = rand(1,28)
|
||||
switch(loot)
|
||||
if(1)
|
||||
new /obj/item/shared_storage/red(src)
|
||||
@@ -196,10 +192,6 @@
|
||||
new /obj/item/immortality_talisman(src)
|
||||
if(28)
|
||||
new /obj/item/gun/magic/wand/book/healing(src)
|
||||
if(29)
|
||||
new /obj/item/reagent_containers/glass/bottle/ichor/red(src)
|
||||
new /obj/item/reagent_containers/glass/bottle/ichor/blue(src)
|
||||
new /obj/item/reagent_containers/glass/bottle/ichor/green(src)
|
||||
|
||||
//KA modkit design discs
|
||||
/obj/item/disk/design_disk/modkit_disc
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
age = rand(AGE_MIN,AGE_MAX)
|
||||
|
||||
/datum/preferences/proc/update_preview_icon(current_tab)
|
||||
var/equip_job = (current_tab != 2)
|
||||
var/equip_job = (current_tab != APPEARANCE_TAB)
|
||||
// Determine what job is marked as 'High' priority, and dress them up as such.
|
||||
var/datum/job/previewJob = get_highest_job()
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
mannequin.add_overlay(mutable_appearance('modular_citadel/icons/ui/backgrounds.dmi', bgstate, layer = SPACE_LAYER))
|
||||
copy_to(mannequin, initial_spawn = TRUE)
|
||||
|
||||
if(current_tab == 3)
|
||||
if(current_tab == LOADOUT_TAB)
|
||||
//give it its loadout if not on the appearance tab
|
||||
SSjob.equip_loadout(parent.mob, mannequin, FALSE, bypass_prereqs = TRUE, can_drop = FALSE)
|
||||
else
|
||||
|
||||
@@ -514,6 +514,20 @@
|
||||
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
|
||||
matrixed_sections = MATRIX_RED_GREEN
|
||||
|
||||
/datum/sprite_accessory/tails/human/triple_kitsune
|
||||
name = "Triple Kitsune Tails"
|
||||
icon_state = "3sune"
|
||||
color_src = MATRIXED
|
||||
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
|
||||
matrixed_sections = MATRIX_RED_GREEN
|
||||
|
||||
/datum/sprite_accessory/tails_animated/human/triple_kitsune
|
||||
name = "Triple Kitsune Tails"
|
||||
icon_state = "3sune"
|
||||
color_src = MATRIXED
|
||||
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
|
||||
matrixed_sections = MATRIX_RED_GREEN
|
||||
|
||||
/datum/sprite_accessory/tails/human/tentacle
|
||||
name = "Tentacle"
|
||||
icon_state = "tentacle"
|
||||
@@ -965,6 +979,16 @@
|
||||
icon_state = "9sune"
|
||||
matrixed_sections = MATRIX_RED_GREEN
|
||||
|
||||
/datum/sprite_accessory/tails/mam_tails/triple_kitsune
|
||||
name = "Triple Kitsune Tails"
|
||||
icon_state = "3sune"
|
||||
matrixed_sections = MATRIX_RED_GREEN
|
||||
|
||||
/datum/sprite_accessory/tails_animated/mam_tails_animated/triple_kitsune
|
||||
name = "Triple Kitsune Tails"
|
||||
icon_state = "3sune"
|
||||
matrixed_sections = MATRIX_RED_GREEN
|
||||
|
||||
/datum/sprite_accessory/tails/mam_tails/tentacle
|
||||
name = "Tentacle"
|
||||
icon_state = "tentacle"
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
addtimer(CALLBACK(src, .proc/med_hud_set_status), (DEFIB_TIME_LIMIT * 10) + 1)
|
||||
stop_pulling()
|
||||
|
||||
var/signal = SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed)
|
||||
var/signal = SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed) | SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MOB_DEATH, src, gibbed)
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(mind && mind.name && mind.active && !istype(T.loc, /area/ctf) && !(signal & COMPONENT_BLOCK_DEATH_BROADCAST))
|
||||
|
||||
@@ -55,3 +55,9 @@
|
||||
name = "triple-barrel shotgun internal magazine"
|
||||
ammo_type = /obj/item/ammo_casing/shotgun/incapacitate
|
||||
max_ammo = 3
|
||||
|
||||
/obj/item/ammo_box/magazine/internal/shot/levergun
|
||||
name = "levergun internal magazine"
|
||||
ammo_type = /obj/item/ammo_casing/c38 // they're rubber by default, i guess
|
||||
caliber = "38"
|
||||
max_ammo = 7
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
var/obj/item/ammo_box/magazine/magazine
|
||||
var/casing_ejector = TRUE //whether the gun ejects the chambered casing
|
||||
var/magazine_wording = "magazine"
|
||||
var/sawn_item_state = "gun"
|
||||
|
||||
/obj/item/gun/ballistic/Initialize()
|
||||
. = ..()
|
||||
@@ -198,13 +199,17 @@
|
||||
name = "sawn-off [src.name]"
|
||||
desc = sawn_desc
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
item_state = "gun"
|
||||
item_state = sawn_item_state
|
||||
slot_flags &= ~ITEM_SLOT_BACK //you can't sling it on your back
|
||||
slot_flags |= ITEM_SLOT_BELT //but you can wear it on your belt (poorly concealed under a trenchcoat, ideally)
|
||||
sawn_off = TRUE
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
/// is something supposed to happen here?
|
||||
/obj/item/gun/ballistic/proc/on_sawoff(mob/user)
|
||||
return
|
||||
|
||||
// Sawing guns related proc
|
||||
/obj/item/gun/ballistic/proc/blow_up(mob/user)
|
||||
. = 0
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
casing_ejector = FALSE
|
||||
var/recentpump = 0 // to prevent spammage
|
||||
weapon_weight = WEAPON_HEAVY
|
||||
sawn_item_state = "sawnshotgun"
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/attackby(obj/item/A, mob/user, params)
|
||||
. = ..()
|
||||
@@ -335,3 +336,34 @@
|
||||
//our hook gun!
|
||||
var/obj/item/gun/magic/hook/bounty/hook
|
||||
var/toggled = FALSE
|
||||
|
||||
// hey you kids like
|
||||
// LEVER GUNS?
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/leveraction
|
||||
name = "lever-action rifle"
|
||||
desc = "While lever-actions have been horribly out of date for hundreds of years now, \
|
||||
the reported potential versatility of .38 Special is worth paying attention to."
|
||||
fire_sound = "sound/weapons/revolvershot.ogg"
|
||||
mag_type = /obj/item/ammo_box/magazine/internal/shot/levergun
|
||||
icon_state = "levercarabine"
|
||||
item_state = "leveraction"
|
||||
sawn_item_state = "maresleg"
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/leveraction/attackby(obj/item/A, mob/user, params)
|
||||
..()
|
||||
if(A.tool_behaviour == TOOL_SAW || istype(A, /obj/item/gun/energy/plasmacutter))
|
||||
sawoff(user)
|
||||
if(istype(A, /obj/item/melee/transforming/energy))
|
||||
var/obj/item/melee/transforming/energy/W = A
|
||||
if(W.active)
|
||||
sawoff(user)
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/leveraction/on_sawoff(mob/user)
|
||||
magazine.max_ammo-- // sawing off drops from 7+1 to 6+1
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/leveraction/update_icon_state()
|
||||
if(current_skin)
|
||||
icon_state = "[unique_reskin[current_skin]][sawn_off ? "-sawn" : ""][chambered ? "" : "-e"]"
|
||||
else
|
||||
icon_state = "[initial(icon_state)][sawn_off ? "-sawn" : ""][chambered ? "" : "-e"]"
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
name = "Machine Design (Automatic Hydroponics Tray Board)"
|
||||
desc = "The circuit board for an automatic hydroponics tray. GIVE ME THE PLANT, CAPTAIN."
|
||||
id = "autohydrotray"
|
||||
build_path = /obj/machinery/hydroponics/constructable/automagic
|
||||
build_path = /obj/item/circuitboard/machine/hydroponics/automagic
|
||||
category = list ("Hydroponics Machinery")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SERVICE | DEPARTMENTAL_FLAG_MEDICAL
|
||||
|
||||
|
||||
@@ -457,23 +457,23 @@
|
||||
category = list("Weapons")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
|
||||
|
||||
/datum/design/laser_shield
|
||||
name = "Laser Resistant Riot Shield"
|
||||
desc = "An advanced riot shield made of darker glasses to prevent laser fire from passing through."
|
||||
/datum/design/energy_shield
|
||||
name = "Energy Resistant Shield"
|
||||
desc = "An ablative shield designed to stop energy-based attacks dead in their tracks, but shatter easily against kinetic blows."
|
||||
id = "laser_shield"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(/datum/material/iron = 4000, /datum/material/glass = 1000, /datum/material/plastic = 4000, /datum/material/silver = 800, /datum/material/titanium = 600, /datum/material/plasma = 5000)
|
||||
build_path = /obj/item/shield/riot/laser_proof
|
||||
build_path = /obj/item/shield/riot/energy_proof
|
||||
category = list("Weapons")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
|
||||
|
||||
/datum/design/bullet_shield
|
||||
name = "Bullet Resistant Riot Shield"
|
||||
desc = "An advanced riot shield made bullet resistant plastics and heavy metals to protect against projectile harm."
|
||||
/datum/design/kinetic_shield
|
||||
name = "Kinetic Resistant Shield"
|
||||
desc = "An advanced polymer shield designed to stop kinetic-based attacks with ease, but splinter apart against energy-based attacks."
|
||||
id = "bullet_shield"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(/datum/material/iron = 4000, /datum/material/glass = 1000, /datum/material/silver = 2000, /datum/material/titanium = 1200, /datum/material/plastic = 2500)
|
||||
build_path = /obj/item/shield/riot/bullet_proof
|
||||
build_path = /obj/item/shield/riot/kinetic_proof
|
||||
category = list("Weapons")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
custom_materials = list(/datum/material/iron=12000)
|
||||
|
||||
/obj/item/ingot/diamond
|
||||
custom_materials = list(/datum/material/diamond=12000) //yeah ok
|
||||
custom_materials = list(/datum/material/diamond=12000)
|
||||
|
||||
/obj/item/ingot/uranium
|
||||
custom_materials = list(/datum/material/uranium=12000)
|
||||
|
||||
@@ -93,12 +93,14 @@
|
||||
active_phylacteries++
|
||||
GLOB.poi_list |= src
|
||||
START_PROCESSING(SSobj, src)
|
||||
RegisterSignal(SSactivity, COMSIG_THREAT_CALC, .proc/get_threat)
|
||||
set_light(lon_range)
|
||||
if(initial(SSticker.mode.round_ends_with_antag_death))
|
||||
SSticker.mode.round_ends_with_antag_death = FALSE
|
||||
|
||||
/obj/item/phylactery/Destroy(force=FALSE)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
UnregisterSignal(SSactivity, COMSIG_THREAT_CALC)
|
||||
active_phylacteries--
|
||||
GLOB.poi_list -= src
|
||||
if(!active_phylacteries)
|
||||
@@ -113,6 +115,12 @@
|
||||
if(!mind.current || (mind.current && mind.current.stat == DEAD))
|
||||
addtimer(CALLBACK(src, .proc/rise), respawn_time, TIMER_UNIQUE)
|
||||
|
||||
/obj/item/phylactery/proc/get_threat(list/threat_list)
|
||||
if(mind?.current?.stat == DEAD)
|
||||
if(!("phylactery" in threat_list))
|
||||
threat_list["phylactery"] = 0
|
||||
threat_list["phylactery"] += 25
|
||||
|
||||
/obj/item/phylactery/proc/rise()
|
||||
if(mind.current && mind.current.stat != DEAD)
|
||||
return "[mind] already has a living body: [mind.current]"
|
||||
|
||||
@@ -99,6 +99,9 @@
|
||||
var/generic_bleedstacks
|
||||
/// If we have a gauze wrapping currently applied (not including splints)
|
||||
var/obj/item/stack/current_gauze
|
||||
/// does this limb have replacement capability, despite probably not being robotic?
|
||||
// see code\modules\surgery\limb_augmentation.dm, or code\game\machinery\limbgrower.dm
|
||||
var/forcereplace = FALSE
|
||||
|
||||
/obj/item/bodypart/examine(mob/user)
|
||||
. = ..()
|
||||
@@ -240,7 +243,13 @@
|
||||
wounding_dmg *= (easy_dismember ? 1 : 0.75)
|
||||
if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
|
||||
return
|
||||
// note that there's no handling for BIO_JUST_FLESH since we don't have any that are that right now (slimepeople maybe someday)
|
||||
// if we're flesh only, all blunt attacks become weakened slashes in terms of wound damage
|
||||
if(BIO_JUST_FLESH)
|
||||
if(wounding_type == WOUND_BLUNT)
|
||||
wounding_type = WOUND_SLASH
|
||||
wounding_dmg *= (easy_dismember ? 1 : 0.3)
|
||||
if((mangled_state & BODYPART_MANGLED_FLESH) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
|
||||
return
|
||||
// standard humanoids
|
||||
if(BIO_FLESH_BONE)
|
||||
// if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
if(istype(tool, /obj/item/organ_storage) && istype(tool.contents[1], /obj/item/bodypart))
|
||||
tool = tool.contents[1]
|
||||
var/obj/item/bodypart/aug = tool
|
||||
if(!aug.is_robotic_limb())
|
||||
if(!aug.is_robotic_limb() && !aug.forcereplace) // forcereplace used here to allow for replacing limbs with synthflesh variants
|
||||
to_chat(user, "<span class='warning'>That's not an augment, silly!</span>")
|
||||
return -1
|
||||
if(aug.body_zone != target_zone)
|
||||
@@ -18,9 +18,14 @@
|
||||
return -1
|
||||
L = surgery.operated_bodypart
|
||||
if(L)
|
||||
display_results(user, target, "<span class ='notice'>You begin to augment [target]'s [parse_zone(user.zone_selected)]...</span>",
|
||||
"[user] begins to augment [target]'s [parse_zone(user.zone_selected)] with [aug].",
|
||||
"[user] begins to augment [target]'s [parse_zone(user.zone_selected)].")
|
||||
if(aug.is_robotic_limb())
|
||||
display_results(user, target, "<span class ='notice'>You begin to augment [target]'s [parse_zone(user.zone_selected)]...</span>",
|
||||
"[user] begins to augment [target]'s [parse_zone(user.zone_selected)] with [aug].",
|
||||
"[user] begins to augment [target]'s [parse_zone(user.zone_selected)].")
|
||||
else
|
||||
display_results(user, target, "<span class ='notice'>You begin to replace [target]'s [parse_zone(user.zone_selected)]...</span>",
|
||||
"[user] begins to replace [target]'s [parse_zone(user.zone_selected)] with [aug].",
|
||||
"[user] begins to replace [target]'s [parse_zone(user.zone_selected)].")
|
||||
else
|
||||
user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_selected)].", "<span class ='notice'>You look for [target]'s [parse_zone(user.zone_selected)]...</span>")
|
||||
|
||||
@@ -47,10 +52,15 @@
|
||||
tool = tool.contents[1]
|
||||
if(istype(tool) && user.temporarilyRemoveItemFromInventory(tool))
|
||||
tool.replace_limb(target, TRUE)
|
||||
display_results(user, target, "<span class='notice'>You successfully augment [target]'s [parse_zone(target_zone)].</span>",
|
||||
"[user] successfully augments [target]'s [parse_zone(target_zone)] with [tool]!",
|
||||
"[user] successfully augments [target]'s [parse_zone(target_zone)]!")
|
||||
log_combat(user, target, "augmented", addition="by giving him new [parse_zone(target_zone)] INTENT: [uppertext(user.a_intent)]")
|
||||
if(tool.is_robotic_limb())
|
||||
display_results(user, target, "<span class='notice'>You successfully augment [target]'s [parse_zone(target_zone)].</span>",
|
||||
"[user] successfully augments [target]'s [parse_zone(target_zone)] with [tool]!",
|
||||
"[user] successfully augments [target]'s [parse_zone(target_zone)]!")
|
||||
else
|
||||
display_results(user, target, "<span class='notice'>You successfully replace [target]'s [parse_zone(target_zone)].</span>",
|
||||
"[user] successfully replaces [target]'s [parse_zone(target_zone)] with [tool]!",
|
||||
"[user] successfully replaces [target]'s [parse_zone(target_zone)]!")
|
||||
log_combat(user, target, "augmented", addition="by giving them a new [parse_zone(target_zone)] INTENT: [uppertext(user.a_intent)]")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[target] has no organic [parse_zone(target_zone)] there!</span>")
|
||||
return TRUE
|
||||
|
||||
Reference in New Issue
Block a user