Merge conflict fix

This commit is contained in:
Artur
2020-05-13 12:37:18 +03:00
985 changed files with 295527 additions and 16121 deletions
+30 -10
View File
@@ -11,13 +11,27 @@
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
invisibility = INVISIBILITY_LIGHTING
var/map_name // Set in New(); preserves the name set by the map maker, even if renamed by the Blueprints.
/// Set in New(); preserves the name set by the map maker, even if renamed by the Blueprints.
var/map_name
var/valid_territory = TRUE // If it's a valid territory for gangs to claim
var/blob_allowed = TRUE // Does it count for blobs score? By default, all areas count.
var/clockwork_warp_allowed = TRUE // Can servants warp into this area from Reebe?
/// If it's valid territory for gangs/cults to summon
var/valid_territory = TRUE
/// if blobs can spawn there and if it counts towards their score.
var/blob_allowed = TRUE
/// whether servants can warp into this area from Reebe
var/clockwork_warp_allowed = TRUE
/// Message to display when the clockwork warp fails
var/clockwork_warp_fail = "The structure there is too dense for warping to pierce. (This is normal in high-security areas.)"
/// If mining tunnel generation is allowed in this area
var/tunnel_allowed = FALSE
/// If flora are allowed to spawn in this area randomly through tunnel generation
var/flora_allowed = FALSE
/// if mobs can be spawned by natural random generation
var/mob_spawn_allowed = FALSE
/// If megafauna can be spawned by natural random generation
var/megafauna_spawn_allowed = FALSE
var/fire = null
var/atmos = TRUE
var/atmosalm = FALSE
@@ -25,11 +39,14 @@
var/lightswitch = TRUE
var/requires_power = TRUE
var/always_unpowered = FALSE // This gets overridden to 1 for space in area/Initialize().
/// This gets overridden to 1 for space in area/Initialize().
var/always_unpowered = FALSE
var/outdoors = FALSE //For space, the asteroid, lavaland, etc. Used with blueprints to determine if we are adding a new area (vs editing a station room)
/// For space, the asteroid, lavaland, etc. Used with blueprints to determine if we are adding a new area (vs editing a station room)
var/outdoors = FALSE
var/areasize = 0 //Size of the area in open turfs, only calculated for indoors areas.
/// Size of the area in open turfs, only calculated for indoors areas.
var/areasize = 0
var/power_equip = TRUE
var/power_light = TRUE
@@ -43,9 +60,12 @@
var/static_environ
var/has_gravity = 0
var/noteleport = FALSE //Are you forbidden from teleporting to the area? (centcom, mobs, wizard, hand teleporter)
var/hidden = FALSE //Hides area from player Teleport function.
var/safe = FALSE //Is the area teleport-safe: no space / radiation / aggresive mobs / other dangers
/// Are you forbidden from teleporting to the area? (centcom, mobs, wizard, hand teleporter)
var/noteleport = FALSE
/// Hides area from player Teleport function.
var/hidden = FALSE
/// Is the area teleport-safe: no space / radiation / aggresive mobs / other dangers
var/safe = FALSE
/// If false, loading multiple maps with this area type will create multiple instances.
var/unique = TRUE
+74
View File
@@ -3,6 +3,7 @@
/area/mine
icon_state = "mining"
has_gravity = STANDARD_GRAVITY
flora_allowed = TRUE
/area/mine/explored
name = "Mine"
@@ -17,6 +18,7 @@
outdoors = TRUE
flags_1 = NONE
ambientsounds = MINING
flora_allowed = FALSE
/area/mine/unexplored
name = "Mine"
@@ -31,6 +33,7 @@
outdoors = TRUE
flags_1 = NONE
ambientsounds = MINING
tunnel_allowed = TRUE
/area/mine/lobby
name = "Mining Station"
@@ -82,6 +85,7 @@
icon_state = "mining"
has_gravity = STANDARD_GRAVITY
flags_1 = NONE
flora_allowed = TRUE
/area/lavaland/surface
name = "Lavaland"
@@ -114,9 +118,79 @@
/area/lavaland/surface/outdoors/unexplored //monsters and ruins spawn here
icon_state = "unexplored"
tunnel_allowed = TRUE
mob_spawn_allowed = TRUE
/area/lavaland/surface/outdoors/unexplored/danger //megafauna will also spawn here
icon_state = "danger"
megafauna_spawn_allowed = TRUE
/area/lavaland/surface/outdoors/explored
name = "Lavaland Labor Camp"
flora_allowed = FALSE
/**********************Ice Moon Areas**************************/
/area/icemoon
icon_state = "mining"
has_gravity = STANDARD_GRAVITY
flags_1 = NONE
flora_allowed = TRUE
blob_allowed = FALSE
/area/icemoon/surface
name = "Icemoon"
icon_state = "explored"
always_unpowered = TRUE
poweralm = FALSE
power_environ = FALSE
power_equip = FALSE
power_light = FALSE
requires_power = TRUE
ambientsounds = MINING
/area/icemoon/underground
name = "Icemoon Caves"
outdoors = TRUE
always_unpowered = TRUE
requires_power = TRUE
poweralm = FALSE
power_environ = FALSE
power_equip = FALSE
power_light = FALSE
ambientsounds = MINING
/area/icemoon/underground/unexplored // mobs and megafauna and ruins spawn here
name = "Icemoon Caves"
icon_state = "unexplored"
tunnel_allowed = TRUE
mob_spawn_allowed = TRUE
megafauna_spawn_allowed = TRUE
/area/icemoon/underground/unexplored/rivers // rivers spawn here
icon_state = "danger"
/area/icemoon/underground/explored
name = "Icemoon Underground"
flora_allowed = FALSE
/area/icemoon/surface/outdoors
name = "Icemoon Wastes"
outdoors = TRUE
/area/icemoon/surface/outdoors/labor_camp
name = "Icemoon Labor Camp"
flora_allowed = FALSE
/area/icemoon/surface/outdoors/unexplored //monsters and ruins spawn here
icon_state = "unexplored"
tunnel_allowed = TRUE
mob_spawn_allowed = TRUE
/area/icemoon/surface/outdoors/unexplored/rivers // rivers spawn here
icon_state = "danger"
/area/icemoon/surface/outdoors/unexplored/rivers/no_monsters
mob_spawn_allowed = FALSE
+9
View File
@@ -0,0 +1,9 @@
// Icemoon Ruins
/area/ruin/unpowered/buried_library
name = "Buried Library"
icon_state = "dk_yellow"
/area/ruin/powered/bathhouse
name = "Bath House"
icon_state = "dk_yellow"
+10 -3
View File
@@ -50,6 +50,13 @@
var/list/blood_DNA
var/list/suit_fibers
/// Last name used to calculate a color for the chatmessage overlays
var/chat_color_name
/// Last color calculated for the the chatmessage overlays
var/chat_color
/// A luminescence-shifted value of the last color calculated for chatmessage overlays
var/chat_color_darkened
/atom/New(loc, ...)
//atom creation method that preloads variables at creation
if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New()
@@ -192,7 +199,7 @@
reagents = new()
reagents.reagent_list.Add(A)
reagents.conditional_update()
else if(ismovableatom(A))
else if(ismovable(A))
var/atom/movable/M = A
if(isliving(M.loc))
var/mob/living/L = M.loc
@@ -692,7 +699,7 @@
/atom/vv_get_dropdown()
. = ..()
VV_DROPDOWN_OPTION("", "---------")
if(!ismovableatom(src))
if(!ismovable(src))
var/turf/curturf = get_turf(src)
if(curturf)
. += "<option value='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[curturf.x];Y=[curturf.y];Z=[curturf.z]'>Jump To</option>"
@@ -970,7 +977,7 @@ Proc for attack log creation, because really why not
for(var/x in materials)
var/datum/material/custom_material = SSmaterials.GetMaterialRef(x)
if(!(material_flags & MATERIAL_NO_EFFECTS))
if(material_flags & MATERIAL_EFFECTS)
custom_material.on_applied(src, materials[custom_material] * multiplier * material_modifier, material_flags)
custom_materials[custom_material] += materials[x] * multiplier
+91 -76
View File
@@ -11,7 +11,7 @@
var/throw_range = 7
var/mob/pulledby = null
var/initial_language_holder = /datum/language_holder
var/datum/language_holder/language_holder
var/datum/language_holder/language_holder // Mindless mobs and objects need language too, some times. Mind holder takes prescedence.
var/verb_say = "says"
var/verb_ask = "asks"
var/verb_exclaim = "exclaims"
@@ -25,6 +25,7 @@
var/inertia_move_delay = 5
var/pass_flags = 0
var/moving_diagonally = 0 //0: not doing a diagonal move. 1 and 2: doing the first/second step of the diagonal move
var/atom/movable/moving_from_pull //attempt to resume grab after moving instead of before.
var/list/client_mobs_in_contents // This contains all the client mobs within this container
var/list/acted_explosions //for explosion dodging
glide_size = 8
@@ -68,7 +69,7 @@
if(vs.plane == EMISSIVE_BLOCKER_PLANE)
SSvis_overlays.remove_vis_overlay(src, list(vs))
break
SSvis_overlays.add_vis_overlay(src, icon, icon_state, EMISSIVE_BLOCKER_LAYER, EMISSIVE_BLOCKER_PLANE)
SSvis_overlays.add_vis_overlay(src, icon, icon_state, EMISSIVE_BLOCKER_LAYER, EMISSIVE_BLOCKER_PLANE, dir)
/atom/movable/proc/can_zFall(turf/source, levels = 1, turf/target, direction)
if(!direction)
@@ -207,6 +208,7 @@
if(!Process_Spacemove(get_dir(pulling.loc, A)))
return
step(pulling, get_dir(pulling.loc, A))
return TRUE
/atom/movable/proc/check_pulling()
if(pulling)
@@ -224,6 +226,8 @@
if(pulling.anchored || pulling.move_resist > move_force)
stop_pulling()
return
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1) //separated from our puller and not in the middle of a diagonal move.
pulledby.stop_pulling()
/atom/movable/Destroy(force)
QDEL_NULL(proximity_monitor)
@@ -251,8 +255,13 @@
/atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
set waitfor = 0
SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
return hit_atom.hitby(src, throwingdatum=throwingdatum)
var/hitpush = TRUE
var/impact_signal = SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
if(impact_signal & COMPONENT_MOVABLE_IMPACT_FLIP_HITPUSH)
hitpush = FALSE // hacky, tie this to something else or a proper workaround later
if(impact_signal & ~COMPONENT_MOVABLE_IMPACT_NEVERMIND) // in case a signal interceptor broke or deleted the thing before we could process our hit
return hit_atom.hitby(src, throwingdatum = throwingdatum, hitpush = hitpush)
/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked, datum/thrownthing/throwingdatum)
if(!anchored && hitpush && (!throwingdatum || (throwingdatum.force >= (move_resist * MOVE_FORCE_PUSH_RATIO))))
@@ -493,88 +502,94 @@
animate(src, pixel_y = initial(pixel_y), time = 10)
setMovetype(movement_type & ~FLOATING)
/* Language procs */
/atom/movable/proc/get_language_holder(shadow=TRUE)
if(language_holder)
return language_holder
else
/* Language procs
* Unless you are doing something very specific, these are the ones you want to use.
*/
/// Gets or creates the relevant language holder. For mindless atoms, gets the local one. For atom with mind, gets the mind one.
/atom/movable/proc/get_language_holder(get_minds = TRUE)
if(!language_holder)
language_holder = new initial_language_holder(src)
return language_holder
return language_holder
/atom/movable/proc/grant_language(datum/language/dt, body = FALSE)
var/datum/language_holder/H = get_language_holder(!body)
H.grant_language(dt, body)
/// Grants the supplied language and sets omnitongue true.
/atom/movable/proc/grant_language(language, understood = TRUE, spoken = TRUE, source = LANGUAGE_ATOM)
var/datum/language_holder/LH = get_language_holder()
return LH.grant_language(language, understood, spoken, source)
/atom/movable/proc/grant_all_languages(omnitongue=FALSE)
var/datum/language_holder/H = get_language_holder()
H.grant_all_languages(omnitongue)
/// Grants every language.
/atom/movable/proc/grant_all_languages(understood = TRUE, spoken = TRUE, grant_omnitongue = TRUE, source = LANGUAGE_MIND)
var/datum/language_holder/LH = get_language_holder()
return LH.grant_all_languages(understood, spoken, grant_omnitongue, source)
/// Removes a single language.
/atom/movable/proc/remove_language(language, understood = TRUE, spoken = TRUE, source = LANGUAGE_ALL)
var/datum/language_holder/LH = get_language_holder()
return LH.remove_language(language, understood, spoken, source)
/// Removes every language and sets omnitongue false.
/atom/movable/proc/remove_all_languages(source = LANGUAGE_ALL, remove_omnitongue = FALSE)
var/datum/language_holder/LH = get_language_holder()
return LH.remove_all_languages(source, remove_omnitongue)
/// Adds a language to the blocked language list. Use this over remove_language in cases where you will give languages back later.
/atom/movable/proc/add_blocked_language(language, source = LANGUAGE_ATOM)
var/datum/language_holder/LH = get_language_holder()
return LH.add_blocked_language(language, source)
/// Removes a language from the blocked language list.
/atom/movable/proc/remove_blocked_language(language, source = LANGUAGE_ATOM)
var/datum/language_holder/LH = get_language_holder()
return LH.remove_blocked_language(language, source)
/// Checks if atom has the language. If spoken is true, only checks if atom can speak the language.
/atom/movable/proc/has_language(language, spoken = FALSE)
var/datum/language_holder/LH = get_language_holder()
return LH.has_language(language, spoken)
/// Checks if atom can speak the language.
/atom/movable/proc/can_speak_language(language)
var/datum/language_holder/LH = get_language_holder()
return LH.can_speak_language(language)
/// Returns the result of tongue specific limitations on spoken languages.
/atom/movable/proc/could_speak_language(language)
return TRUE
/// Returns selected language, if it can be spoken, or finds, sets and returns a new selected language if possible.
/atom/movable/proc/get_selected_language()
var/datum/language_holder/LH = get_language_holder()
return LH.get_selected_language()
/// Gets a random understood language, useful for hallucinations and such.
/atom/movable/proc/get_random_understood_language()
var/datum/language_holder/H = get_language_holder()
. = H.get_random_understood_language()
var/datum/language_holder/LH = get_language_holder()
return LH.get_random_understood_language()
/atom/movable/proc/remove_language(datum/language/dt, body = FALSE)
var/datum/language_holder/H = get_language_holder(!body)
H.remove_language(dt, body)
/// Gets a random spoken language, useful for forced speech and such.
/atom/movable/proc/get_random_spoken_language()
var/datum/language_holder/LH = get_language_holder()
return LH.get_random_spoken_language()
/atom/movable/proc/remove_all_languages()
var/datum/language_holder/H = get_language_holder()
H.remove_all_languages()
/// Copies all languages into the supplied atom/language holder. Source should be overridden when you
/// do not want the language overwritten by later atom updates or want to avoid blocked languages.
/atom/movable/proc/copy_languages(from_holder, source_override)
if(isatom(from_holder))
var/atom/movable/thing = from_holder
from_holder = thing.get_language_holder()
var/datum/language_holder/LH = get_language_holder()
return LH.copy_languages(from_holder, source_override)
/atom/movable/proc/has_language(datum/language/dt)
var/datum/language_holder/H = get_language_holder()
. = H.has_language(dt)
/atom/movable/proc/copy_known_languages_from(thing, replace=FALSE)
var/datum/language_holder/H = get_language_holder()
. = H.copy_known_languages_from(thing, replace)
// Whether an AM can speak in a language or not, independent of whether
// it KNOWS the language
/atom/movable/proc/could_speak_in_language(datum/language/dt)
. = TRUE
/atom/movable/proc/can_speak_in_language(datum/language/dt)
var/datum/language_holder/H = get_language_holder()
if(!H.has_language(dt))
return FALSE
else if(H.omnitongue)
return TRUE
else if(could_speak_in_language(dt) && (!H.only_speaks_language || H.only_speaks_language == dt))
return TRUE
else
return FALSE
/atom/movable/proc/get_default_language()
// if no language is specified, and we want to say() something, which
// language do we use?
var/datum/language_holder/H = get_language_holder()
if(H.selected_default_language)
if(can_speak_in_language(H.selected_default_language))
return H.selected_default_language
else
H.selected_default_language = null
var/datum/language/chosen_langtype
var/highest_priority
for(var/lt in H.languages)
var/datum/language/langtype = lt
if(!can_speak_in_language(langtype))
continue
var/pri = initial(langtype.default_priority)
if(!highest_priority || (pri > highest_priority))
chosen_langtype = langtype
highest_priority = pri
H.selected_default_language = .
. = chosen_langtype
/// Empties out the atom specific languages and updates them according to the current atoms language holder.
/// As a side effect, it also creates missing language holders in the process.
/atom/movable/proc/update_atom_languages()
var/datum/language_holder/LH = get_language_holder()
return LH.update_atom_languages(src)
/* End language procs */
/atom/movable/proc/ConveyorMove(movedir)
set waitfor = FALSE
if(!anchored && has_gravity())
+8 -13
View File
@@ -20,6 +20,9 @@
if(!newloc.Enter(src, src.loc))
return
if (SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_MOVE, newloc) & COMPONENT_MOVABLE_BLOCK_PRE_MOVE)
return
// Past this is the point of no return
var/atom/oldloc = loc
var/area/oldarea = get_area(oldloc)
@@ -51,13 +54,8 @@
/atom/movable/Move(atom/newloc, direct)
var/atom/movable/pullee = pulling
var/turf/T = loc
if(pulling)
if(pullee && get_dist(src, pullee) > 1)
stop_pulling()
if(pullee && pullee.loc != loc && !isturf(pullee.loc) ) //to be removed once all code that changes an object's loc uses forceMove().
log_game("DEBUG:[src]'s pull on [pullee] wasn't broken despite [pullee] being in [pullee.loc]. Pull stopped manually.")
stop_pulling()
if(!moving_from_pull)
check_pulling()
if(!loc || !newloc)
return FALSE
var/atom/oldloc = loc
@@ -130,19 +128,16 @@
if(has_buckled_mobs() && !handle_buckled_mob_movement(loc,direct)) //movement failed due to buckled mob(s)
return FALSE
if(pulling && pulling == pullee) //we were pulling a thing and didn't lose it during our move.
if(pulling && pulling == pullee && pulling != moving_from_pull) //we were pulling a thing and didn't lose it during our move.
if(pulling.anchored)
stop_pulling()
else
var/pull_dir = get_dir(src, pulling)
//puller and pullee more than one tile away or in diagonal position
if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir)))
pulling.moving_from_pull = src
pulling.Move(T, get_dir(pulling, T)) //the pullee tries to reach our previous position
if(pulling && get_dist(src, pulling) > 1) //the pullee couldn't keep up
stop_pulling()
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1)//separated from our puller and not in the middle of a diagonal move.
pulledby.stop_pulling()
pulling.moving_from_pull = null
Moved(oldloc, direct)
/atom/movable/proc/handle_buckled_mob_movement(newloc,direct)
@@ -53,7 +53,7 @@
restricted_jobs += "Assistant"
// Set number of Vamps
recommended_enemies = CLAMP(round(num_players()/10), 1, 6);
recommended_enemies = clamp(round(num_players()/10), 1, 6);
// Select Antags
for(var/i = 0, i < recommended_enemies, i++)
@@ -195,7 +195,7 @@
return FALSE
if(target.stat > UNCONSCIOUS)
return FALSE
// Check Overdose: Am I even addicted to blood? Do I even have any in me?
//if (!target.reagents.addiction_list || !target.reagents.reagent_list)
//message_admins("DEBUG2: can_make_vassal() Abort: No reagents")
+29 -5
View File
@@ -40,8 +40,10 @@ GLOBAL_VAR_INIT(dynamic_stacking_limit, 90)
GLOBAL_LIST_EMPTY(dynamic_forced_roundstart_ruleset)
// Forced threat level, setting this to zero or higher forces the roundstart threat to the value.
GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
// Storyteller picked by the voting.
GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
// Storyteller forced by admins during voting--will be used instead of above.
GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
/datum/game_mode/dynamic
name = "dynamic mode"
@@ -164,7 +166,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
dat += "Current threat: <b>[threat]</b> <a href='?src=\ref[src];[HrefToken()];adjustthreat=1'>\[Adjust\]</A> <a href='?src=\ref[src];[HrefToken()];threatlog=1'>\[View Log\]</a><br/>"
dat += "<br/>"
dat += "Storyteller: <b>[storyteller.name]</b><br/>"
dat += "Storyteller: <a href='?src=\ref[src];[HrefToken()];change_storyteller=1'><b>[storyteller.name]</b></a> <br/>"
dat += "Parameters: centre = [GLOB.dynamic_curve_centre] ; width = [GLOB.dynamic_curve_width].<br/>"
dat += "<i>On average, <b>[peaceful_percentage]</b>% of the rounds are more peaceful.</i><br/>"
dat += "Forced extended: <a href='?src=\ref[src];[HrefToken()];forced_extended=1'><b>[GLOB.dynamic_forced_extended ? "On" : "Off"]</b></a><br/>"
@@ -222,6 +224,15 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
show_threatlog(usr)
else if (href_list["stacking_limit"])
GLOB.dynamic_stacking_limit = input(usr,"Change the threat limit at which round-endings rulesets will start to stack.", "Change stacking limit", null) as num
else if (href_list["change_storyteller"])
var/list/choices = list()
for(var/T in config.storyteller_cache)
var/datum/dynamic_storyteller/S = T
choices[initial(S.name)] = T
var/selected_storyteller = choices[input("Select storyteller:", "Storyteller", storyteller.name) as null|anything in choices]
storyteller = new selected_storyteller
storyteller.on_start()
message_admins("[key_name(usr)] changed the storyteller to [storyteller].", 1)
admin_panel() // Refreshes the window
@@ -243,7 +254,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
/datum/game_mode/dynamic/send_intercept()
. = "<b><i>Central Command Status Summary</i></b><hr>"
switch(round(threat_level))
if(0 to 20)
if(-INFINITY to 20)
. += "<b>Peaceful Waypoint</b></center><BR>"
. += "Your station orbits deep within controlled, core-sector systems and serves as a waypoint for routine traffic through Nanotrasen's trade empire. Due to the combination of high security, interstellar traffic, and low strategic value, it makes any direct threat of violence unlikely. Your primary enemies will be incompetence and bored crewmen: try to organize team-building events to keep staffers interested and productive. However, even deep in our territory there may be subversive elements, especially for such a high-value target as your station. Keep an eye out, but don't expect much trouble."
set_security_level(SEC_LEVEL_GREEN)
@@ -275,7 +286,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
. += "<b>Black Orbit</b></center><BR>"
. += "As part of a mandatory security protocol, we are required to inform you that as a result of your orbital pattern directly behind an astrological body (oriented from our nearest observatory), your station will be under decreased monitoring and support. It is anticipated that your extreme location and decreased surveillance could pose security risks. Avoid unnecessary risks and attempt to keep your station in one piece."
set_security_level(SEC_LEVEL_AMBER)
if(96 to 100)
if(96 to INFINITY)
. += "<b>Impending Doom</b></center><BR>"
. += "Your station is somehow in the middle of hostile territory, in clear view of any enemy of the corporation. Your likelihood to survive is low, and station destruction is expected and almost inevitable. Secure any sensitive material and neutralize any enemy you will come across. It is important that you at least try to maintain the station.<BR>"
. += "Good luck."
@@ -346,6 +357,8 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
SSblackbox.record_feedback("tally","dynamic_threat",peaceful_percentage,"Percent of same-vote rounds that are more peaceful")
/datum/game_mode/dynamic/can_start()
if(GLOB.dynamic_forced_storyteller)
GLOB.dynamic_storyteller_type = GLOB.dynamic_forced_storyteller
storyteller = new GLOB.dynamic_storyteller_type // this is where all the initialization happens
storyteller.on_start()
SSblackbox.record_feedback("text","dynamic_storyteller",1,storyteller.name)
@@ -441,6 +454,8 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
if(!drafted_rules.len)
message_admins("Not enough threat level for roundstart antags!")
log_game("DYNAMIC: Not enough threat level for roundstart antags!")
midround_injection_cooldown = round((midround_injection_cooldown + world.time) / 2, 1)
latejoin_injection_cooldown = round((latejoin_injection_cooldown + world.time) / 2, 1)
var/indice_pop = min(10,round(roundstart_pop_ready/pop_per_requirement)+1)
extra_rulesets_amount = 0
if (GLOB.dynamic_classic_secret)
@@ -721,7 +736,8 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
if (O.started_as_observer) // Observers
current_players[CURRENT_OBSERVERS].Add(M)
continue
current_players[CURRENT_DEAD_PLAYERS].Add(M) // Players who actually died (and admins who ghosted, would be nice to avoid counting them somehow)
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
if(threat_average_weight)
var/cur_sample_weight = world.time - last_threat_sample_time
@@ -823,3 +839,11 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
return RULE_OF_THREE(40, 20, x) + 50
if (20 to INFINITY)
return rand(90, 100)
/datum/game_mode/dynamic/ghost_info()
. = list()
. += "Current threat: [threat]"
. += "Target threat: [threat_level]"
. += "Storyteller: <b>[storyteller.name]</b><br/>"
. += "Parameters: centre = [GLOB.dynamic_curve_centre] ; width = [GLOB.dynamic_curve_width].<br/>"
. += "<i>On average, <b>[peaceful_percentage]</b>% of the rounds are more peaceful.</i><br/>"
@@ -105,7 +105,7 @@
if (M.mind && M.mind.assigned_role && (M.mind.assigned_role in enemy_roles) && (!(M in candidates) || (M.mind.assigned_role in restricted_roles)))
job_check++ // Checking for "enemies" (such as sec officers). To be counters, they must either not be candidates to that rule, or have a job that restricts them from it
var/threat = CLAMP(round(mode.threat_level/10),1,10)
var/threat = clamp(round(mode.threat_level/10),1,10)
if (job_check < required_enemies[threat])
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough enemy roles")
return FALSE
@@ -642,6 +642,9 @@
for(var/obj/effect/landmark/carpspawn/L in GLOB.landmarks_list)
if(isturf(L.loc))
spawn_locs += L.loc
for(var/obj/effect/landmark/loneopspawn/L in GLOB.landmarks_list)
if(isturf(L.loc))
spawn_locs += L.loc
if(!spawn_locs.len)
return FALSE
spawn_loc = pick(spawn_locs)
@@ -671,7 +674,7 @@
message_admins("[ADMIN_LOOKUPFLW(Ninja)] has been made into a ninja by dynamic.")
log_game("[key_name(Ninja)] was spawned as a ninja by dynamic.")
return Ninja
/datum/dynamic_ruleset/midround/from_ghosts/ninja/finish_setup(mob/new_character, index)
return
@@ -789,7 +789,7 @@
if (prob(meteorminutes/2))
wavetype = GLOB.meteors_catastrophic
var/ramp_up_final = CLAMP(round(meteorminutes/rampupdelta), 1, 10)
var/ramp_up_final = clamp(round(meteorminutes/rampupdelta), 1, 10)
spawn_meteors(ramp_up_final, wavetype)
@@ -11,7 +11,7 @@
WAROPS_ALWAYS_ALLOWED: Can always do warops, regardless of threat level.
USE_PREF_WEIGHTS: Will use peoples' preferences to change the threat centre.
FORCE_IF_WON: If this mode won the vote, forces it
USE_PREV_ROUND_WEIGHTS: Changes its threat centre based on the average chaos of previous rounds.
USE_PREV_ROUND_WEIGHTS: Changes its threat centre based on the average chaos of previous rounds.
*/
var/flags = 0
var/dead_player_weight = 1 // How much dead players matter for threat calculation
@@ -22,11 +22,11 @@
var/datum/game_mode/dynamic/mode = null // Cached as soon as it's made, by dynamic.
/**
Property weights are:
Property weights are:
"story_potential" -- essentially how many different ways the antag can be played.
"trust" -- How much it makes the crew trust each other. Negative values means they're suspicious. Team antags are like this.
"chaos" -- How chaotic it makes the round. Has some overlap with "valid" and somewhat contradicts "extended".
"valid" -- How likely the non-antag-enemy crew are to get involved, e.g. nukies encouraging the warden to
"valid" -- How likely the non-antag-enemy crew are to get involved, e.g. nukies encouraging the warden to
let everyone into the armory, wizard moving around and being a nuisance, nightmare busting lights.
"extended" -- How much the antag is conducive to a long round. Nukies and cults are bad for this; Wizard is less bad; and so on.
"conversion" -- Basically a bool. Conversion antags, well, convert. It's its own class for a good reason.
@@ -34,13 +34,13 @@ Property weights are:
/datum/dynamic_storyteller/proc/start_injection_cooldowns()
var/latejoin_injection_cooldown_middle = 0.5*(GLOB.dynamic_first_latejoin_delay_max + GLOB.dynamic_first_latejoin_delay_min)
mode.latejoin_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_first_latejoin_delay_min, GLOB.dynamic_first_latejoin_delay_max)) + world.time
mode.latejoin_injection_cooldown = round(clamp(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_first_latejoin_delay_min, GLOB.dynamic_first_latejoin_delay_max)) + world.time
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
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
var/event_injection_cooldown_middle = 0.5*(GLOB.dynamic_event_delay_max + GLOB.dynamic_event_delay_min)
mode.event_injection_cooldown = (round(CLAMP(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max)) + world.time)
mode.event_injection_cooldown = (round(clamp(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max)) + world.time)
/datum/dynamic_storyteller/proc/calculate_threat()
var/threat = 0
@@ -99,15 +99,15 @@ Property weights are:
/datum/dynamic_storyteller/proc/get_midround_cooldown()
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_midround_delay_max + GLOB.dynamic_midround_delay_min)
return round(CLAMP(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_midround_delay_min, GLOB.dynamic_midround_delay_max))
return round(clamp(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_midround_delay_min, GLOB.dynamic_midround_delay_max))
/datum/dynamic_storyteller/proc/get_event_cooldown()
var/event_injection_cooldown_middle = 0.5*(GLOB.dynamic_event_delay_max + GLOB.dynamic_event_delay_min)
return round(CLAMP(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max))
return round(clamp(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max))
/datum/dynamic_storyteller/proc/get_latejoin_cooldown()
var/latejoin_injection_cooldown_middle = 0.5*(GLOB.dynamic_latejoin_delay_max + GLOB.dynamic_latejoin_delay_min)
return round(CLAMP(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_latejoin_delay_min, GLOB.dynamic_latejoin_delay_max))
return round(clamp(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_latejoin_delay_min, GLOB.dynamic_latejoin_delay_max))
/datum/dynamic_storyteller/proc/get_injection_chance(dry_run = FALSE)
if(mode.forced_injection)
@@ -115,7 +115,7 @@ Property weights are:
return 100
var/threat_perc = mode.threat/mode.threat_level
return round(max(0,100*(1-(threat_perc*threat_perc*threat_perc))))
return clamp(round(100*(1-(threat_perc*threat_perc))**2,1),0,100)
/datum/dynamic_storyteller/proc/roundstart_draft()
var/list/drafted_rules = list()
@@ -144,7 +144,7 @@ Property weights are:
if(!(rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
/* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to
pick this particular ruleset.
pick this particular ruleset.
Let's use a toy example: there's 60 threat level and 10 threat spent.
We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets.
Ruleset 1 has 30 cost, ruleset 2 has 5 cost.
@@ -152,7 +152,7 @@ Property weights are:
is 2.26 times as likely to be picked, all other things considered.
Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight.
*/
threat_weight = 1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0))
threat_weight = abs(1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
if (rule.ready())
var/property_weight = 0
for(var/property in property_weights)
@@ -209,10 +209,10 @@ Property weights are:
weight = 1
event_frequency_lower = 2 MINUTES
event_frequency_upper = 10 MINUTES
flags = WAROPS_ALWAYS_ALLOWED
min_players = 40
flags = WAROPS_ALWAYS_ALLOWED | FORCE_IF_WON
min_players = 30
var/refund_cooldown = 0
/datum/dynamic_storyteller/chaotic/do_process()
if(refund_cooldown < world.time)
mode.create_threat(20)
@@ -221,7 +221,7 @@ Property weights are:
/datum/dynamic_storyteller/chaotic/get_midround_cooldown()
return ..() / 4
/datum/dynamic_storyteller/chaotic/get_latejoin_cooldown()
return ..() / 4
@@ -232,7 +232,7 @@ Property weights are:
curve_centre = 2
curve_width = 1.5
weight = 2
min_players = 30
min_players = 20
flags = WAROPS_ALWAYS_ALLOWED | USE_PREV_ROUND_WEIGHTS
property_weights = list("valid" = 3, "trust" = 5)
@@ -331,7 +331,7 @@ Property weights are:
/datum/dynamic_storyteller/story/calculate_threat()
var/current_time = (world.time / SSautotransfer.targettime)*180
mode.threat_level = round(mode.initial_threat_level*(sin(current_time)+0.25),0.1)
..()
return ..()
/datum/dynamic_storyteller/classic
name = "Classic"
@@ -358,7 +358,7 @@ Property weights are:
flags = NO_ASSASSIN | FORCE_IF_WON
weight = 1
dead_player_weight = 5
property_weights = list("extended" = 2, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10)
property_weights = list("extended" = 2, "chaos" = -1, "valid" = -1, "conversion" = -10)
/datum/dynamic_storyteller/no_antag
name = "Extended"
+6 -2
View File
@@ -272,7 +272,7 @@
reports += config.mode_reports[config_tag]
Count++
for(var/i in Count to rand(3,5)) //Between three and five wrong entries on the list.
var/false_report_type = pickweightAllowZero(report_weights)
var/false_report_type = pickweight(report_weights, 0)
report_weights[false_report_type] = 0 //Make it so the same false report won't be selected twice
reports += config.mode_reports[false_report_type]
@@ -417,7 +417,7 @@
if(player.assigned_role == job)
candidates -= player
if(candidates.len < recommended_enemies)
if(candidates.len < recommended_enemies && CONFIG_GET(keyed_list/force_antag_count)[config_tag])
for(var/mob/dead/new_player/player in players)
if(player.client && player.ready == PLAYER_READY_TO_PLAY)
if(!(role in player.client.prefs.be_special)) // We don't have enough people who want to be antagonist, make a separate list of people who don't want to be one
@@ -604,3 +604,7 @@
/// Mode specific admin panel.
/datum/game_mode/proc/admin_panel()
return
/// Mode specific info for ghost game_info
/datum/game_mode/proc/ghost_info()
return
+1 -1
View File
@@ -229,7 +229,7 @@
if(!was_stranded)
priority_announce("All hostile activity within station systems has ceased.","Network Alert")
if(get_security_level() == "delta")
if(NUM2SECLEVEL(GLOB.security_level) == "delta")
set_security_level("red")
SSshuttle.clearHostileEnvironment(src)
+1 -1
View File
@@ -25,7 +25,7 @@
if (prob(meteorminutes/2))
wavetype = GLOB.meteors_catastrophic
var/ramp_up_final = CLAMP(round(meteorminutes/rampupdelta), 1, 10)
var/ramp_up_final = clamp(round(meteorminutes/rampupdelta), 1, 10)
spawn_meteors(ramp_up_final, wavetype)
+4 -1
View File
@@ -90,7 +90,10 @@
sabotage_type = "cloner"
/datum/sabotage_objective/cloner/check_conditions()
return !(locate(/obj/machinery/clonepod) in GLOB.machines)
for(var/obj/machinery/clonepod/cloner in GLOB.machines)
if(is_station_level(cloner.z))
return FALSE
return TRUE
/datum/sabotage_objective/ai_law
name = "Upload a hacked law to the AI."
+1 -1
View File
@@ -70,7 +70,7 @@
/datum/game_mode/revolution/post_setup()
var/list/heads = SSjob.get_living_heads()
var/list/sec = SSjob.get_living_sec()
var/weighted_score = CLAMP(round(heads.len - ((3 - sec.len) / 3)), 1, max_headrevs)
var/weighted_score = clamp(round(heads.len - ((3 - sec.len) / 3)), 1, max_headrevs)
for(var/datum/mind/rev_mind in headrev_candidates) //People with return to lobby may still be in the lobby. Let's pick someone else in that case.
if(isnewplayer(rev_mind.current))
+50 -22
View File
@@ -17,7 +17,6 @@
var/list/L = list()
var/list/LL = list()
var/hacked = FALSE
var/hackable = TRUE
var/disabled = 0
var/shocked = FALSE
var/hack_wire
@@ -28,11 +27,11 @@
var/prod_coeff = 1
var/datum/design/being_built
var/datum/techweb/stored_research
var/list/datum/design/matching_designs
var/selected_category
var/screen = 1
var/datum/techweb/specialized/autounlocking/stored_research = /datum/techweb/specialized/autounlocking/autolathe
var/list/categories = list(
"Tools",
"Electronics",
@@ -45,9 +44,7 @@
"Dinnerware",
"Imported"
)
/obj/machinery/autolathe/Initialize()
var/static/list/allowed_types = list(
var/list/allowed_materials = list(
/datum/material/iron,
/datum/material/glass,
/datum/material/gold,
@@ -63,10 +60,15 @@
/datum/material/adamantine,
/datum/material/mythril
)
AddComponent(/datum/component/material_container, allowed_types, _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert))
/// Base print speed
var/base_print_speed = 10
/obj/machinery/autolathe/Initialize()
AddComponent(/datum/component/material_container, allowed_materials, _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert))
. = ..()
wires = new /datum/wires/autolathe(src)
stored_research = new /datum/techweb/specialized/autounlocking/autolathe
stored_research = new stored_research
matching_designs = list()
/obj/machinery/autolathe/Destroy()
@@ -91,7 +93,7 @@
if(AUTOLATHE_SEARCH_MENU)
dat = search_win(user)
var/datum/browser/popup = new(user, "autolathe", name, 400, 500)
var/datum/browser/popup = new(user, name, name, 400, 500)
popup.set_content(dat)
popup.open()
@@ -169,7 +171,7 @@
var/multiplier = text2num(href_list["multiplier"])
var/is_stack = ispath(being_built.build_path, /obj/item/stack)
multiplier = CLAMP(multiplier,1,50)
multiplier = clamp(multiplier,1,50)
/////////////////
@@ -206,7 +208,7 @@
busy = TRUE
use_power(power)
icon_state = "autolathe_n"
var/time = is_stack ? 32 : 32*coeff*multiplier
var/time = is_stack ? 10 : base_print_speed * coeff * multiplier
addtimer(CALLBACK(src, .proc/make_item, power, materials_used, custom_materials, multiplier, coeff, is_stack), time)
else
to_chat(usr, "<span class=\"alert\">Not enough materials for this operation.</span>")
@@ -254,10 +256,12 @@
T += MB.rating*75000
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = T
T=1.2
var/manips = 0
var/total_manip_rating = 0
for(var/obj/item/stock_parts/manipulator/M in component_parts)
T -= M.rating*0.2
prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
total_manip_rating += M.rating
manips++
prod_coeff = STANDARD_PART_LEVEL_LATHE_COEFFICIENT(total_manip_rating / (manips? manips : 1))
/obj/machinery/autolathe/examine(mob/user)
. += ..()
@@ -420,11 +424,11 @@
/obj/machinery/autolathe/proc/adjust_hacked(state)
hacked = state
if(!hackable && hacked)
return
for(var/id in SSresearch.techweb_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(id)
if((D.build_type & AUTOLATHE) && ("hacked" in D.category))
if(D.build_type & stored_research.design_autounlock_skip_types)
continue
if((D.build_type & stored_research.design_autounlock_buildtypes) && ("hacked" in D.category))
if(hacked)
stored_research.add_design(D)
else
@@ -436,11 +440,35 @@
/obj/machinery/autolathe/secure
name = "secured autolathe"
desc = "An autolathe reprogrammed with security protocols to prevent hacking."
hackable = FALSE
desc = "It produces items using metal and glass. This model was reprogrammed without some of the more hazardous designs."
circuit = /obj/item/circuitboard/machine/autolathe/secure
stored_research = /datum/techweb/specialized/autounlocking/autolathe/public
base_print_speed = 20
//Called when the object is constructed by an autolathe
//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes
/obj/item/proc/autolathe_crafted(obj/machinery/autolathe/A)
return
/obj/machinery/autolathe/toy
name = "autoylathe"
desc = "It produces toys using plastic, metal and glass."
circuit = /obj/item/circuitboard/machine/autolathe/toy
stored_research = /datum/techweb/specialized/autounlocking/autolathe/toy
categories = list(
"Toys",
"Figurines",
"Pistols",
"Rifles",
"Heavy",
"Melee",
"Armor",
"Adult",
"Misc",
"Imported"
)
allowed_materials = list(
/datum/material/iron,
/datum/material/glass,
/datum/material/plastic
)
/obj/machinery/autolathe/toy/hacked/Initialize()
. = ..()
adjust_hacked(TRUE)
+8
View File
@@ -16,6 +16,9 @@
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
/obj/machinery/button/Initialize(mapload, ndir = 0, built = 0)
if(istext(id) && mapload)
if(copytext(id, 1, 2) == "!")
id = SSmapping.get_obfuscated_id(id)
. = ..()
if(built)
setDir(ndir)
@@ -269,6 +272,11 @@
req_access = list()
id = 1
/obj/machinery/button/electrochromatic
name = "window dim control"
desc = "Controls linked electrochromatic windows"
device_type = /obj/item/assembly/control/electrochromatic
/obj/item/wallframe/button
name = "button frame"
desc = "Used for building buttons."
@@ -48,8 +48,7 @@
if(2)
// State 2
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = W
if(C.use(2))
if(W.use_tool(src, user, 0, 2))
to_chat(user, "<span class='notice'>You add wires to the assembly.</span>")
state = 3
else
+2 -2
View File
@@ -69,8 +69,8 @@
for(var/obj/item/stock_parts/manipulator/P in component_parts)
speed_coeff += (P.rating / 2)
speed_coeff = max(1, speed_coeff)
heal_level = CLAMP((efficiency * 10) + 10, MINIMUM_HEAL_LEVEL, 100)
heal_level = clamp((efficiency * 10) + 10, MINIMUM_HEAL_LEVEL, 100)
//Clonepod
/obj/machinery/clonepod/examine(mob/user)
+2 -2
View File
@@ -150,7 +150,7 @@
return
log_activity("changed greater than charge filter to \"[new_filter]\"")
if(new_filter)
new_filter = CLAMP(new_filter, 0, 100)
new_filter = clamp(new_filter, 0, 100)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
result_filters["Charge Above"] = new_filter
if(href_list["below_filter"])
@@ -160,7 +160,7 @@
return
log_activity("changed lesser than charge filter to \"[new_filter]\"")
if(new_filter)
new_filter = CLAMP(new_filter, 0, 100)
new_filter = clamp(new_filter, 0, 100)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
result_filters["Charge Below"] = new_filter
if(href_list["access_filter"])
@@ -308,12 +308,12 @@
var/new_rows = input(user, "How many rows do you want? (Minimum: 4, Maximum: 30)", "Minesweeper Rows") as null|num
if(!new_rows || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return FALSE
new_rows = CLAMP(new_rows + 1, 4, 30)
new_rows = clamp(new_rows + 1, 4, 30)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
var/new_columns = input(user, "How many columns do you want? (Minimum: 4, Maximum: 50)", "Minesweeper Squares") as null|num
if(!new_columns || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return FALSE
new_columns = CLAMP(new_columns + 1, 4, 50)
new_columns = clamp(new_columns + 1, 4, 50)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
var/grid_area = (new_rows - 1) * (new_columns - 1)
var/lower_limit = round(grid_area*0.156)
@@ -324,7 +324,7 @@
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
rows = new_rows
columns = new_columns
mine_limit = CLAMP(new_mine_limit, lower_limit, upper_limit)
mine_limit = clamp(new_mine_limit, lower_limit, upper_limit)
return TRUE
/obj/machinery/computer/arcade/minesweeper/proc/make_mines(var/reset_everything)
@@ -296,7 +296,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
if("rate")
var/target = text2num(params["rate"])
if(!isnull(target))
target = CLAMP(target, 0, MAX_TRANSFER_RATE)
target = clamp(target, 0, MAX_TRANSFER_RATE)
signal.data += list("tag" = input_tag, "set_volume_rate" = target)
. = TRUE
if("output")
@@ -305,7 +305,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
if("pressure")
var/target = text2num(params["pressure"])
if(!isnull(target))
target = CLAMP(target, 0, MAX_OUTPUT_PRESSURE)
target = clamp(target, 0, MAX_OUTPUT_PRESSURE)
signal.data += list("tag" = output_tag, "set_internal_pressure" = target)
. = TRUE
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
@@ -111,7 +111,7 @@
to_chat(usr, "<span class='notice'>Authorization confirmed. Modifying security level.</span>")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
//Only notify people if an actual change happened
var/security_level = get_security_level()
var/security_level = NUM2SECLEVEL(GLOB.security_level)
log_game("[key_name(usr)] has changed the security level to [security_level] with [src] at [AREACOORD(usr)].")
message_admins("[ADMIN_LOOKUPFLW(usr)] has changed the security level to [security_level] with [src] at [AREACOORD(usr)].")
deadchat_broadcast("<span class='deadsay'><span class='name'>[usr.real_name]</span> has changed the security level to [security_level] with [src] at <span class='name'>[get_area_name(usr, TRUE)]</span>.</span>", usr)
@@ -400,7 +400,7 @@
security_level_cd = world.time + 15 SECONDS
if(GLOB.security_level != old_level)
//Only notify people if an actual change happened
var/security_level = get_security_level()
var/security_level = NUM2SECLEVEL(GLOB.security_level)
log_game("[key_name(usr)] has changed the security level to [security_level] from [src] at [AREACOORD(usr)].")
message_admins("[ADMIN_LOOKUPFLW(usr)] has changed the security level to [security_level] from [src] at [AREACOORD(usr)].")
deadchat_broadcast("<span class='deadsay'><span class='name'>[usr.real_name]</span> has changed the security level to [security_level] from [src] at [get_area_name(usr, TRUE)].</span>", usr)
@@ -551,7 +551,7 @@
dat += " <A HREF='?src=[REF(src)];operation=setstat;statdisp=alert;alert=biohazard'>Biohazard</A> \]<BR><HR>"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
if(STATE_ALERT_LEVEL)
dat += "Current alert level: [get_security_level()]<BR>"
dat += "Current alert level: [NUM2SECLEVEL(GLOB.security_level)]<BR>"
if(GLOB.security_level == SEC_LEVEL_DELTA)
dat += "<font color='red'><b>The self-destruct mechanism is active. Find a way to deactivate the mechanism to lower the alert level or evacuate.</b></font>"
else
@@ -559,8 +559,8 @@
dat += "<A HREF='?src=[REF(src)];operation=securitylevel;newalertlevel=[SEC_LEVEL_BLUE]'>Blue</A><BR>"
dat += "<A HREF='?src=[REF(src)];operation=securitylevel;newalertlevel=[SEC_LEVEL_GREEN]'>Green</A>"
if(STATE_CONFIRM_LEVEL)
dat += "Current alert level: [get_security_level()]<BR>"
dat += "Confirm the change to: [num2seclevel(tmp_alertlevel)]<BR>"
dat += "Current alert level: [NUM2SECLEVEL(GLOB.security_level)]<BR>"
dat += "Confirm the change to: [NUM2SECLEVEL(tmp_alertlevel)]<BR>"
dat += "<A HREF='?src=[REF(src)];operation=swipeidseclevel'>Swipe ID</A> to confirm change.<BR>"
if(STATE_TOGGLE_EMERGENCY)
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
@@ -692,7 +692,7 @@
dat += " <A HREF='?src=[REF(src)];operation=setstat;statdisp=alert;alert=biohazard'>Biohazard</A> \]<BR><HR>"
if(STATE_ALERT_LEVEL)
dat += "Current alert level: [get_security_level()]<BR>"
dat += "Current alert level: [NUM2SECLEVEL(GLOB.security_level)]<BR>"
if(GLOB.security_level == SEC_LEVEL_DELTA)
dat += "<font color='red'><b>The self-destruct mechanism is active. Find a way to deactivate the mechanism to lower the alert level or evacuate.</b></font>"
else
@@ -97,7 +97,7 @@
return
if(!new_goal)
new_goal = default_goal
contained_id.goal = CLAMP(new_goal, 0, 1000) //maximum 1000 points
contained_id.goal = clamp(new_goal, 0, 1000) //maximum 1000 points
return TRUE
if("toggle_open")
if(teleporter.locked)
@@ -83,7 +83,6 @@
if(istype(P, /obj/item/stack/cable_coil))
if(!P.tool_start_check(user, amount=5))
return
to_chat(user, "<span class='notice'>You start to add cables to the frame...</span>")
if(P.use_tool(src, user, 20, volume=50, amount=5))
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
+1 -1
View File
@@ -405,7 +405,7 @@
// Ghost and delete the mob.
if(!mob_occupant.get_ghost(1))
mob_occupant.ghostize(FALSE, penalize = TRUE)
mob_occupant.ghostize(FALSE, penalize = TRUE, voluntary = TRUE)
QDEL_NULL(occupant)
for(var/I in cryo_items) //only "CRYO_DESTROY_LATER" atoms are left)
+1 -1
View File
@@ -33,7 +33,7 @@
to_chat(user, "<span class='notice'>You begin repairing [src]...</span>")
if(I.use_tool(src, user, 40, volume=40))
obj_integrity = CLAMP(obj_integrity + 20, 0, max_integrity)
obj_integrity = clamp(obj_integrity + 20, 0, max_integrity)
else
return ..()
+1 -1
View File
@@ -135,7 +135,7 @@
. /= 10
/obj/machinery/door_timer/proc/set_timer(value)
var/new_time = CLAMP(value,0,MAX_TIMER)
var/new_time = clamp(value,0,MAX_TIMER)
. = new_time == timer_duration //return 1 on no change
timer_duration = new_time
+1 -2
View File
@@ -400,12 +400,11 @@
"<span class='notice'>You begin adding wires to [src]...</span>")
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
if(do_after(user, 60, target = src))
if(constructionStep != CONSTRUCTION_GUTTED || B.get_amount() < 5 || !B)
if(constructionStep != CONSTRUCTION_GUTTED || !B.use_tool(src, user, 0, 5))
return
user.visible_message("<span class='notice'>[user] adds wires to [src].</span>", \
"<span class='notice'>You wire [src].</span>")
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
B.use(5)
constructionStep = CONSTRUCTION_WIRES_EXPOSED
update_icon()
return
+1 -3
View File
@@ -205,11 +205,9 @@
return
if(1)
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/coil = W
if(coil.get_amount() < 5)
if(!W.use_tool(src, user, 0, 5))
to_chat(user, "<span class='warning'>You need more cable for this!</span>")
else
coil.use(5)
buildstage = 2
to_chat(user, "<span class='notice'>You wire \the [src].</span>")
update_icon()
+3 -4
View File
@@ -396,7 +396,6 @@ GLOBAL_LIST_EMPTY(network_holopads)
Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY)
Hologram.Impersonation = user
Hologram.copy_known_languages_from(user,replace = TRUE)
Hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it.
Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
Hologram.setAnchored(TRUE)//So space wind cannot drag it.
@@ -555,9 +554,8 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
Hologram.alpha = 170
Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY)
Hologram.dir = SOUTH //for now
Hologram.grant_all_languages(omnitongue=TRUE)
var/datum/language_holder/holder = Hologram.get_language_holder()
holder.selected_default_language = record.language
holder.selected_language = record.language
Hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it.
Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
Hologram.setAnchored(TRUE)//So space wind cannot drag it.
@@ -649,7 +647,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
return
if(HOLORECORD_LANGUAGE)
var/datum/language_holder/holder = replay_holo.get_language_holder()
holder.selected_default_language = entry[2]
holder.selected_language = entry[2]
if(HOLORECORD_PRESET)
var/preset_type = entry[2]
var/datum/preset_holoimage/H = new preset_type
@@ -672,6 +670,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
updateDialog()
/obj/effect/overlay/holo_pad_hologram
initial_language_holder = /datum/language_holder/universal
var/mob/living/Impersonation
var/datum/holocall/HC
+2 -2
View File
@@ -68,9 +68,9 @@
if(teleporting)
return
if(!isnull(x))
x_offset = CLAMP(x, -range, range)
x_offset = clamp(x, -range, range)
if(!isnull(y))
y_offset = CLAMP(y, -range, range)
y_offset = clamp(y, -range, range)
/obj/machinery/launchpad/proc/doteleport(mob/user, sending)
if(teleporting)
+2 -2
View File
@@ -55,9 +55,9 @@
new /obj/item/pipe_meter(loc)
wait = world.time + 15
if(href_list["layer_up"])
piping_layer = CLAMP(++piping_layer, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
piping_layer = clamp(++piping_layer, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
if(href_list["layer_down"])
piping_layer = CLAMP(--piping_layer, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
piping_layer = clamp(--piping_layer, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
return
/obj/machinery/pipedispenser/attackby(obj/item/W, mob/user, params)
+5 -3
View File
@@ -53,6 +53,11 @@
using_power = FALSE
update_icon()
/obj/machinery/recharger/Exited(atom/movable/M, atom/newloc)
. = ..()
if(charging == M)
setCharging()
/obj/machinery/recharger/attackby(obj/item/G, mob/user, params)
if(istype(G, /obj/item/wrench))
if(charging)
@@ -109,15 +114,12 @@
add_fingerprint(user)
if(charging)
charging.update_icon()
charging.forceMove(drop_location())
user.put_in_hands(charging)
setCharging(null)
/obj/machinery/recharger/attack_tk(mob/user)
if(charging)
charging.update_icon()
charging.forceMove(drop_location())
setCharging(null)
/obj/machinery/recharger/process()
if(stat & (NOPOWER|BROKEN) || !anchored)
+2 -5
View File
@@ -160,10 +160,7 @@
to_chat(user, "<span class='warning'>You need one length of cable to repair [src]!</span>")
return
to_chat(user, "<span class='notice'>You begin to replace the wires...</span>")
if(do_after(user, 30, target = src))
if(coil.get_amount() < 1)
return
coil.use(1)
if(W.use_tool(src, user, 30, 1))
obj_integrity = max_integrity
stat &= ~BROKEN
to_chat(user, "<span class='notice'>You repair \the [src].</span>")
@@ -270,7 +267,7 @@
use_stored_power(50)
/obj/machinery/shieldwallgen/proc/use_stored_power(amount)
power = CLAMP(power - amount, 0, maximum_stored_power)
power = clamp(power - amount, 0, maximum_stored_power)
update_activity()
/obj/machinery/shieldwallgen/proc/update_activity()
+2 -2
View File
@@ -127,7 +127,7 @@
settableTemperatureRange = cap * 30
efficiency = (cap + 1) * 10000
targetTemperature = CLAMP(targetTemperature,
targetTemperature = clamp(targetTemperature,
max(settableTemperatureMedian - settableTemperatureRange, TCMB),
settableTemperatureMedian + settableTemperatureRange)
@@ -230,7 +230,7 @@
target= text2num(target) + T0C
. = TRUE
if(.)
targetTemperature = CLAMP(round(target),
targetTemperature = clamp(round(target),
max(settableTemperatureMedian - settableTemperatureRange, TCMB),
settableTemperatureMedian + settableTemperatureRange)
if("eject")
+1 -1
View File
@@ -195,7 +195,7 @@
/obj/machinery/syndicatebomb/proc/settings(mob/user)
var/new_timer = input(user, "Please set the timer.", "Timer", "[timer_set]") as num
if(in_range(src, user) && isliving(user)) //No running off and setting bombs from across the station
timer_set = CLAMP(new_timer, minimum_timer, maximum_timer)
timer_set = clamp(new_timer, minimum_timer, maximum_timer)
loc.visible_message("<span class='notice'>[icon2html(src, viewers(src))] timer set for [timer_set] seconds.</span>")
if(alert(user,"Would you like to start the countdown now?",,"Yes","No") == "Yes" && in_range(src, user) && isliving(user))
if(defused || active)
@@ -100,7 +100,7 @@
obj/source, // the originating radio
frequency, // the frequency the signal is taking place on
atom/movable/virtualspeaker/speaker, // representation of the method's speaker
datum/language/language, // the langauge of the message
datum/language/language, // the language of the message
message, // the text content of the message
spans // the list of spans applied to the message
)
+1 -1
View File
@@ -70,7 +70,7 @@
com.target = null
visible_message("<span class='alert'>Cannot authenticate locked on coordinates. Please reinstate coordinate matrix.</span>")
return
if (ismovableatom(M))
if (ismovable(M))
if(do_teleport(M, com.target, channel = TELEPORT_CHANNEL_BLUESPACE))
use_power(5000)
-415
View File
@@ -1,415 +0,0 @@
#define AUTOYLATHE_MAIN_MENU 1
#define AUTOYLATHE_CATEGORY_MENU 2
#define AUTOYLATHE_SEARCH_MENU 3
/obj/machinery/autoylathe
name = "autoylathe"
desc = "It produces toys using plastic, metal and glass."
icon_state = "autolathe"
density = TRUE
use_power = IDLE_POWER_USE
idle_power_usage = 10
active_power_usage = 100
circuit = /obj/item/circuitboard/machine/autoylathe
layer = BELOW_OBJ_LAYER
var/operating = FALSE
var/list/L = list()
var/list/LL = list()
var/hacked = FALSE
var/disabled = 0
var/shocked = FALSE
var/hack_wire
var/disable_wire
var/shock_wire
var/busy = FALSE
var/prod_coeff = 1
var/datum/design/being_built
var/datum/techweb/stored_research
var/list/datum/design/matching_designs
var/selected_category
var/screen = 1
var/list/categories = list(
"Toys",
"Figurines",
"Pistols",
"Rifles",
"Heavy",
"Melee",
"Armor",
"Adult",
"Misc",
"Imported"
)
/obj/machinery/autoylathe/Initialize()
var/static/list/allowed_materials = list(
/datum/material/iron,
/datum/material/glass,
/datum/material/plastic
)
AddComponent(/datum/component/material_container, allowed_materials, 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
. = ..()
wires = new /datum/wires/autoylathe(src)
stored_research = new /datum/techweb/specialized/autounlocking/autoylathe
matching_designs = list()
/obj/machinery/autoylathe/Destroy()
QDEL_NULL(wires)
return ..()
/obj/machinery/autoylathe/ui_interact(mob/user)
. = ..()
if(!is_operational())
return
if(shocked && !(stat & NOPOWER))
shock(user,50)
var/dat
switch(screen)
if(AUTOYLATHE_MAIN_MENU)
dat = main_win(user)
if(AUTOYLATHE_CATEGORY_MENU)
dat = category_win(user,selected_category)
if(AUTOYLATHE_SEARCH_MENU)
dat = search_win(user)
var/datum/browser/popup = new(user, "Autoylathe", name, 400, 500)
popup.set_content(dat)
popup.open()
/obj/machinery/autoylathe/on_deconstruction()
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
/obj/machinery/autoylathe/attackby(obj/item/O, mob/user, params)
if (busy)
to_chat(user, "<span class=\"alert\">The autoylathe is busy. Please wait for completion of previous operation.</span>")
return TRUE
if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", O))
updateUsrDialog()
return TRUE
if(default_deconstruction_crowbar(O))
return TRUE
if(panel_open && is_wire_tool(O))
wires.interact(user)
return TRUE
if(user.a_intent == INTENT_HARM) //so we can hit the machine
return ..()
if(stat)
return TRUE
if(istype(O, /obj/item/disk/design_disk))
user.visible_message("[user] begins to load \the [O] in \the [src]...",
"You begin to load a design from \the [O]...",
"You hear the chatter of a floppy drive.")
busy = TRUE
var/obj/item/disk/design_disk/D = O
if(do_after(user, 14.4, target = src))
for(var/B in D.blueprints)
if(B)
stored_research.add_design(B)
busy = FALSE
return TRUE
return ..()
/obj/machinery/autoylathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
if(item_inserted.custom_materials?.len && item_inserted.custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
flick("autolathe_r",src)//plays glass insertion animation by default otherwise
else
flick("autolathe_o",src)//plays metal insertion animation
use_power(min(1000, amount_inserted / 100))
updateUsrDialog()
/obj/machinery/autoylathe/Topic(href, href_list)
if(..())
return
if (!busy)
if(href_list["menu"])
screen = text2num(href_list["menu"])
updateUsrDialog()
if(href_list["category"])
selected_category = href_list["category"]
updateUsrDialog()
if(href_list["make"])
/////////////////
//href protection
being_built = stored_research.isDesignResearchedID(href_list["make"])
if(!being_built)
return
var/multiplier = text2num(href_list["multiplier"])
var/is_stack = ispath(being_built.build_path, /obj/item/stack)
multiplier = CLAMP(multiplier,1,50)
/////////////////
var/coeff = (is_stack ? 1 : prod_coeff) //stacks are unaffected by production coefficient
var/total_amount = 0
for(var/MAT in being_built.materials)
total_amount += being_built.materials[MAT]
var/power = max(2000, (total_amount)*multiplier/5) //Change this to use all materials
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/list/materials_used = list()
var/list/custom_materials = list() //These will apply their material effect, This should usually only be one.
for(var/MAT in being_built.materials)
var/datum/material/used_material = MAT
var/amount_needed = being_built.materials[MAT] * coeff * multiplier
if(istext(used_material)) //This means its a category
var/list/list_to_show = list()
for(var/i in SSmaterials.materials_by_category[used_material])
if(materials.materials[i] > 0)
list_to_show += i
used_material = input("Choose [used_material]", "Custom Material") as null|anything in list_to_show
if(!used_material)
return //Didn't pick any material, so you can't build shit either.
custom_materials[used_material] += amount_needed
materials_used[used_material] = amount_needed
if(materials.has_materials(materials_used))
busy = TRUE
use_power(power)
icon_state = "autolathe_n"
var/time = is_stack ? 32 : 32*coeff*multiplier
addtimer(CALLBACK(src, .proc/make_item, power, materials_used, custom_materials, multiplier, coeff, is_stack), time)
else
to_chat(usr, "<span class=\"alert\">Not enough materials for this operation.</span>")
if(href_list["search"])
matching_designs.Cut()
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(findtext(D.name,href_list["to_search"]))
matching_designs.Add(D)
updateUsrDialog()
else
to_chat(usr, "<span class=\"alert\">The autoylathe is busy. Please wait for completion of previous operation.</span>")
updateUsrDialog()
return
/obj/machinery/autoylathe/proc/make_item(power, list/materials_used, list/picked_materials, multiplier, coeff, is_stack)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/atom/A = drop_location()
use_power(power)
materials.use_materials(materials_used)
if(is_stack)
var/obj/item/stack/N = new being_built.build_path(A, multiplier)
N.update_icon()
N.autoylathe_crafted(src)
else
for(var/i=1, i<=multiplier, i++)
var/obj/item/new_item = new being_built.build_path(A)
new_item.autoylathe_crafted(src)
if(length(picked_materials))
new_item.set_custom_materials(picked_materials, 1 / multiplier) //Ensure we get the non multiplied amount
icon_state = "autolathe"
busy = FALSE
updateDialog()
/obj/machinery/autoylathe/RefreshParts()
var/T = 0
for(var/obj/item/stock_parts/matter_bin/MB in component_parts)
T += MB.rating*75000
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = T
T=1.2
for(var/obj/item/stock_parts/manipulator/M in component_parts)
T -= M.rating*0.2
prod_coeff = CLAMP(T,1,0) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
/obj/machinery/autoylathe/proc/main_win(mob/user)
var/dat = "<div class='statusDisplay'><h3>Autoylathe Menu:</h3><br>"
dat += materials_printout()
dat += "<form name='search' action='?src=[REF(src)]'>\
<input type='hidden' name='src' value='[REF(src)]'>\
<input type='hidden' name='search' value='to_search'>\
<input type='hidden' name='menu' value='[AUTOYLATHE_SEARCH_MENU]'>\
<input type='text' name='to_search'>\
<input type='submit' value='Search'>\
</form><hr>"
var/line_length = 1
dat += "<table style='width:100%' align='center'><tr>"
for(var/C in categories)
if(line_length > 2)
dat += "</tr><tr>"
line_length = 1
dat += "<td><A href='?src=[REF(src)];category=[C];menu=[AUTOYLATHE_CATEGORY_MENU]'>[C]</A></td>"
line_length++
dat += "</tr></table></div>"
return dat
/obj/machinery/autoylathe/proc/category_win(mob/user,selected_category)
var/dat = "<A href='?src=[REF(src)];menu=[AUTOYLATHE_MAIN_MENU]'>Return to main menu</A>"
dat += "<div class='statusDisplay'><h3>Browsing [selected_category]:</h3><br>"
dat += materials_printout()
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(!(selected_category in D.category))
continue
if(disabled || !can_build(D))
dat += "<span class='linkOff'>[D.name]</span>"
else
dat += "<a href='?src=[REF(src)];make=[D.id];multiplier=1'>[D.name]</a>"
if(ispath(D.build_path, /obj/item/stack))
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/max_multiplier
for(var/datum/material/mat in D.materials)
max_multiplier = min(D.maxstack, round(materials.get_material_amount(mat)/D.materials[mat]))
if (max_multiplier>10 && !disabled)
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
if (max_multiplier>25 && !disabled)
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=25'>x25</a>"
if(max_multiplier > 0 && !disabled)
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=[max_multiplier]'>x[max_multiplier]</a>"
else
if(!disabled && can_build(D, 5))
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=5'>x5</a>"
if(!disabled && can_build(D, 10))
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
dat += "[get_design_cost(D)]<br>"
dat += "</div>"
return dat
/obj/machinery/autoylathe/proc/search_win(mob/user)
var/dat = "<A href='?src=[REF(src)];menu=[AUTOYLATHE_MAIN_MENU]'>Return to main menu</A>"
dat += "<div class='statusDisplay'><h3>Search results:</h3><br>"
dat += materials_printout()
for(var/v in matching_designs)
var/datum/design/D = v
if(disabled || !can_build(D))
dat += "<span class='linkOff'>[D.name]</span>"
else
dat += "<a href='?src=[REF(src)];make=[D.id];multiplier=1'>[D.name]</a>"
if(ispath(D.build_path, /obj/item/stack))
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/max_multiplier
for(var/datum/material/mat in D.materials)
max_multiplier = min(D.maxstack, round(materials.get_material_amount(mat)/D.materials[mat]))
if (max_multiplier>10 && !disabled)
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
if (max_multiplier>25 && !disabled)
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=25'>x25</a>"
if(max_multiplier > 0 && !disabled)
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=[max_multiplier]'>x[max_multiplier]</a>"
dat += "[get_design_cost(D)]<br>"
dat += "</div>"
return dat
/obj/machinery/autoylathe/proc/materials_printout()
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/dat = "<b>Total amount:</b> [materials.total_amount] / [materials.max_amount] cm<sup>3</sup><br>"
for(var/mat_id in materials.materials)
var/datum/material/M = mat_id
var/mineral_amount = materials.materials[mat_id]
if(mineral_amount > 0)
dat += "<b>[M.name] amount:</b> [mineral_amount] cm<sup>3</sup><br>"
return dat
/obj/machinery/autoylathe/proc/can_build(datum/design/D, amount = 1)
if(D.make_reagents.len)
return FALSE
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
var/list/required_materials = list()
for(var/i in D.materials)
required_materials[i] = D.materials[i] * coeff * amount
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
return materials.has_materials(required_materials)
/obj/machinery/autoylathe/proc/get_design_cost(datum/design/D)
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
var/dat
for(var/i in D.materials)
if(istext(i)) //Category handling
dat += "[D.materials[i] * coeff] [i]"
else
var/datum/material/M = i
dat += "[D.materials[i] * coeff] [M.name] "
return dat
/obj/machinery/autoylathe/proc/reset(wire)
switch(wire)
if(WIRE_HACK)
if(!wires.is_cut(wire))
adjust_hacked(FALSE)
if(WIRE_SHOCK)
if(!wires.is_cut(wire))
shocked = FALSE
if(WIRE_DISABLE)
if(!wires.is_cut(wire))
disabled = FALSE
/obj/machinery/autoylathe/proc/shock(mob/user, prb)
if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
return FALSE
if(!prob(prb))
return FALSE
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src)
s.start()
if (electrocute_mob(user, get_area(src), src, 0.7, TRUE))
return TRUE
else
return FALSE
/obj/machinery/autoylathe/proc/adjust_hacked(state)
hacked = state
for(var/id in SSresearch.techweb_designs)
var/datum/design/D = SSresearch.techweb_designs[id]
if((D.build_type & AUTOYLATHE) && ("hacked" in D.category))
if(hacked)
stored_research.add_design(D)
else
stored_research.remove_design(D)
/obj/machinery/autoylathe/hacked/Initialize()
. = ..()
adjust_hacked(TRUE)
//Called when the object is constructed by an autoylathe
//Has a reference to the autoylathe so you can do !!FUN!! things with hacked lathes
/obj/item/proc/autoylathe_crafted(obj/machinery/autoylathe/A)
return
@@ -530,7 +530,6 @@
equip_cooldown = 0
var/obj/item/gun/medbeam/mech/medigun
custom_materials = list(/datum/material/iron = 15000, /datum/material/glass = 8000, /datum/material/plasma = 3000, /datum/material/gold = 8000, /datum/material/diamond = 2000)
material_flags = MATERIAL_NO_EFFECTS
/obj/item/mecha_parts/mecha_equipment/medical/mechmedbeam/Initialize()
. = ..()
+1 -1
View File
@@ -484,7 +484,7 @@
/obj/item/punching_glove/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(!..())
if(ismovableatom(hit_atom))
if(ismovable(hit_atom))
var/atom/movable/AM = hit_atom
AM.safe_throw_at(get_edge_target_turf(AM,get_dir(src, AM)), 7, 2)
qdel(src)
+29 -4
View File
@@ -19,6 +19,7 @@
var/processing_queue = 0
var/screen = "main"
var/temp
var/offstation_security_levels = TRUE
var/list/part_sets = list(
"Cyborg",
"Ripley",
@@ -72,6 +73,8 @@
for(var/obj/item/stock_parts/manipulator/Ml in component_parts)
T += Ml.rating
time_coeff = round(initial(time_coeff) - (initial(time_coeff)*(T))/5,0.01)
var/obj/item/circuitboard/machine/mechfab/C = circuit
offstation_security_levels = C.offstation_security_levels
/obj/machinery/mecha_part_fabricator/examine(mob/user)
. = ..()
@@ -106,13 +109,27 @@
if(!(set_name in D.category))
continue
output += "<div class='part'>[output_part_info(D)]<br>\["
if(check_resources(D))
if(check_clearance(D) && check_resources(D))
output += "<a href='?src=[REF(src)];part=[D.id]'>Build</a> | "
output += "<a href='?src=[REF(src)];add_to_queue=[D.id]'>Add to queue</a>\]\[<a href='?src=[REF(src)];part_desc=[D.id]'>?</a>\]</div>"
return output
/obj/machinery/mecha_part_fabricator/proc/check_clearance(datum/design/D)
if(!(obj_flags & EMAGGED) && (offstation_security_levels || is_station_level(z)) && !ISINRANGE(GLOB.security_level, D.min_security_level, D.max_security_level))
return FALSE
return TRUE
/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D)
var/output = "[initial(D.name)] (Cost: [output_part_cost(D)]) [get_construction_time_w_coeff(D)/10]sec"
var/clearance = !(obj_flags & EMAGGED) && (offstation_security_levels || is_station_level(z))
var/sec_text = ""
if(clearance && (D.min_security_level > SEC_LEVEL_GREEN || D.max_security_level < SEC_LEVEL_DELTA))
sec_text = " (Allowed security levels: "
for(var/n in D.min_security_level to D.max_security_level)
sec_text += NUM2SECLEVEL(n)
if(n + 1 <= D.max_security_level)
sec_text += ", "
sec_text += ") "
var/output = "[initial(D.name)] (Cost: [output_part_cost(D)]) [sec_text][get_construction_time_w_coeff(D)/10]sec"
return output
/obj/machinery/mecha_part_fabricator/proc/output_part_cost(datum/design/D)
@@ -171,7 +188,6 @@
var/location = get_step(src,(dir))
var/obj/item/I = new D.build_path(location)
I.material_flags |= MATERIAL_NO_EFFECTS //Find a better way to do this.
I.set_custom_materials(res_coef)
say("\The [I] is complete.")
being_built = null
@@ -216,6 +232,11 @@
while(D)
if(stat&(NOPOWER|BROKEN))
return FALSE
if(!check_clearance(D))
say("Security level not met. Queue processing stopped.")
temp = {"<span class='alert'>Security level not met to build next part.</span><br>
<a href='?src=[REF(src)];process_queue=1'>Try again</a> | <a href='?src=[REF(src)];clear_temp=1'>Return</a><a>"}
return FALSE
if(!check_resources(D))
say("Not enough resources. Queue processing stopped.")
temp = {"<span class='alert'>Not enough resources to build next part.</span><br>
@@ -236,7 +257,7 @@
for(var/datum/design/D in queue)
i++
var/obj/part = D.build_path
output += "<li[!check_resources(D)?" style='color: #f00;'":null]>"
output += "<li[(!check_clearance(D) ||!check_resources(D))?" style='color: #f00;'":null]>"
output += initial(part.name) + " - "
output += "[i>1?"<a href='?src=[REF(src)];queue_move=-1;index=[i]' class='arrow'>&uarr;</a>":null] "
output += "[i<queue.len?"<a href='?src=[REF(src)];queue_move=+1;index=[i]' class='arrow'>&darr;</a>":null] "
@@ -440,3 +461,7 @@
return FALSE
return TRUE
/obj/machinery/mecha_part_fabricator/offstation
offstation_security_levels = FALSE
circuit = /obj/item/circuitboard/machine/mechfab/offstation
@@ -3,6 +3,46 @@
////////////////////////////////
/datum/component/construction/mecha
var/base_icon
var/looky_helpy = TRUE
/datum/component/construction/mecha/examine(mob/user)
. = ..()
if(looky_helpy)
switch(steps[index]["key"])
if(TOOL_WRENCH)
. += "<span class='notice'>The mech could be <b>wrenched</b> into place.</span>"
if(TOOL_SCREWDRIVER)
. += "<span class='notice'>The mech could be <b>screwed</b> into place.</span>"
if(TOOL_WIRECUTTER)
. += "<span class='notice'>The mech wires could be <b>trimmed</b> into place.</span>"
if(/obj/item/stack/cable_coil)
. += "<span class='notice'>The mech could use some <b>wiring</b>.</span>"
if(/obj/item/circuitboard)
. += "<span class='notice'>The mech could use a type of<b>circuitboard</b>.</span>"
if(/obj/item/stock_parts/scanning_module)
. += "<span class='notice'>The mech could use a <b>scanning stock part</b>.</span>"
if(/obj/item/stock_parts/capacitor)
. += "<span class='notice'>The mech could use a <b>power based stock part</b>.</span>"
if(/obj/item/stock_parts/cell)
. += "<span class='notice'>The mech could use a <b>power source</b>.</span>"
if(/obj/item/stack/sheet/metal)
. += "<span class='notice'>The mech could use some <b>sheets of metal</b>.</span>"
if(/obj/item/stack/sheet/plasteel)
. += "<span class='notice'>The mech could use some <b>sheets of strong steel</b>.</span>"
if(/obj/item/bikehorn)
. += "<span class='notice'>HONK IT!.</span>"
if(/obj/item/clothing/mask/gas/clown_hat)
. += "<span class='notice'>GIVE IT CLOWN MAKEUP HONK!.</span>"
if(/obj/item/clothing/shoes/clown_shoes)
. += "<span class='notice'>GIVE IT GOOFY SHOES HONK HONK!.</span>"
if(/obj/item/mecha_parts/part)
. += "<span class='notice'>The mech could use a mech <b>part</b>.</span>"
if(/obj/item/stack/ore/bluespace_crystal)
. += "<span class='notice'>The mech could use a <b>crystal</b> of sorts.</span>"
if(/obj/item/assembly/signaler/anomaly)
. += "<span class='notice'>The mech could use a <b>anomaly</b> of sorts.</span>"
else
return
/datum/component/construction/mecha/spawn_result()
if(!result)
+1 -2
View File
@@ -220,8 +220,7 @@
return
else if(istype(W, /obj/item/stack/cable_coil))
if(state == 3 && (internal_damage & MECHA_INT_SHORT_CIRCUIT))
var/obj/item/stack/cable_coil/CC = W
if(CC.use(2))
if(W.use_tool(src, user, 0, 2))
clearInternalDamage(MECHA_INT_SHORT_CIRCUIT)
to_chat(user, "<span class='notice'>You replace the fused wires.</span>")
else
+9 -2
View File
@@ -55,8 +55,12 @@
M.buckling = null
return FALSE
if(M.pulledby && buckle_prevents_pull)
M.pulledby.stop_pulling()
if(M.pulledby)
if(buckle_prevents_pull)
M.pulledby.stop_pulling()
else if(isliving(M.pulledby))
var/mob/living/L = M.pulledby
L.reset_pull_offsets(M, TRUE)
if(!check_loc && M.loc != loc)
M.forceMove(loc)
@@ -137,4 +141,7 @@
"<span class='notice'>You unbuckle yourself from [src].</span>",\
"<span class='italics'>You hear metal clanking.</span>")
add_fingerprint(user)
if(isliving(M.pulledby))
var/mob/living/L = M.pulledby
L.set_pull_offsets(M, L.grab_state)
return M
+1 -1
View File
@@ -17,7 +17,7 @@
target = get_turf(src)
if(acid_amt)
acid_level = min( (CLAMP(round(acid_amt, 1), 0, INFINITY)) *acid_pwr, 12000) //capped so the acid effect doesn't last a half hour on the floor.
acid_level = min( (clamp(round(acid_amt, 1), 0, INFINITY)) *acid_pwr, 12000) //capped so the acid effect doesn't last a half hour on the floor.
//handle APCs and newscasters and stuff nicely
pixel_x = target.pixel_x + rand(-4,4)
+1 -1
View File
@@ -7,7 +7,7 @@
move_resist = INFINITY
obj_flags = 0
vis_flags = NONE
vis_flags = VIS_INHERIT_PLANE
/obj/effect/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
return
+13 -3
View File
@@ -313,6 +313,11 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
name = "carpspawn"
icon_state = "carp_spawn"
// lone op (optional)
/obj/effect/landmark/loneopspawn
name = "loneop+ninjaspawn"
icon_state = "snukeop_spawn"
// observer-start.
/obj/effect/landmark/observer_start
name = "Observer-Start"
@@ -483,7 +488,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
if(!SSmapping.station_room_templates[t])
log_world("Station room spawner placed at ([T.x], [T.y], [T.z]) has invalid ruin name of \"[t]\" in its list")
templates -= t
template_name = pickweightAllowZero(templates)
template_name = pickweight(templates, 0)
if(!template_name)
GLOB.stationroom_landmarks -= src
qdel(src)
@@ -492,7 +497,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
if(!template)
return FALSE
testing("Room \"[template_name]\" placed at ([T.x], [T.y], [T.z])")
template.load(T, centered = FALSE)
template.load(T, centered = FALSE, orientation = dir, rotate_placement_to_orientation = TRUE)
template.loaded++
GLOB.stationroom_landmarks -= src
qdel(src)
@@ -504,7 +509,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
templates = list("Engine SM" = 3, "Engine Singulo" = 3, "Engine Tesla" = 3)
icon = 'icons/rooms/box/engine.dmi'
/obj/effect/landmark/stationroom/box/engine/New()
. = ..()
templates = CONFIG_GET(keyed_list/box_random_engine)
@@ -513,3 +517,9 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
/obj/effect/landmark/stationroom/lavaland/station
templates = list("Public Mining Base" = 3)
icon = 'icons/rooms/Lavaland/Mining.dmi'
// handled in portals.dm, id connected to one-way portal
/obj/effect/landmark/portal_exit
name = "portal exit"
icon_state = "portal_exit"
var/id
+2 -2
View File
@@ -170,7 +170,7 @@
if(!victim.client || !istype(victim))
return
to_chat(victim, "<span class='notice'>You feel fast!</span>")
victim.add_movespeed_modifier(MOVESPEED_ID_YELLOW_ORB, update=TRUE, priority=100, multiplicative_slowdown=-2, blacklisted_movetypes=(FLYING|FLOATING))
victim.add_movespeed_modifier(/datum/movespeed_modifier/yellow_orb)
sleep(duration)
victim.remove_movespeed_modifier(MOVESPEED_ID_YELLOW_ORB)
victim.remove_movespeed_modifier(/datum/movespeed_modifier/yellow_orb)
to_chat(victim, "<span class='notice'>You slow down.</span>")
+1
View File
@@ -49,5 +49,6 @@
/obj/effect/overlay/vis
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
anchored = TRUE
vis_flags = NONE
var/unused = 0 //When detected to be unused it gets set to world.time, after a while it gets removed
var/cache_expiration = 2 MINUTES // overlays which go unused for 2 minutes get cleaned up
+46 -1
View File
@@ -29,6 +29,7 @@
var/allow_anchored = FALSE
var/innate_accuracy_penalty = 0
var/last_effect = 0
var/force_teleport = FALSE
/obj/effect/portal/anom
name = "wormhole"
@@ -162,7 +163,7 @@
no_effect = TRUE
else
last_effect = world.time
if(do_teleport(M, real_target, innate_accuracy_penalty, no_effects = no_effect, channel = teleport_channel))
if(do_teleport(M, real_target, innate_accuracy_penalty, no_effects = no_effect, channel = teleport_channel, forced = force_teleport))
if(istype(M, /obj/item/projectile))
var/obj/item/projectile/P = M
P.ignore_source_check = TRUE
@@ -183,3 +184,47 @@
else
real_target = get_turf(linked)
return real_target
/obj/effect/portal/permanent
name = "permanent portal"
desc = "An unwavering portal that will never fade."
hardlinked = FALSE // dont qdel my portal nerd
force_teleport = TRUE // force teleports because they're a mapmaker tool
var/id // var edit or set id in map editor
/obj/effect/portal/permanent/proc/set_linked()
if(!id)
return
for(var/obj/effect/portal/permanent/P in GLOB.portals - src)
if(P.id == id)
P.linked = src
linked = P
break
/obj/effect/portal/permanent/teleport(atom/movable/M, force = FALSE)
set_linked() // update portal links
. = ..()
/obj/effect/portal/permanent/one_way // doesn't have a return portal, can have multiple exits, /obj/effect/landmark/portal_exit to mark them
name = "one-way portal"
desc = "You get the feeling that this might not be the safest thing you've ever done."
/obj/effect/portal/permanent/one_way/set_linked()
if(!id)
return
var/list/possible_turfs = list()
for(var/obj/effect/landmark/portal_exit/PE in GLOB.landmarks_list)
if(PE.id == id)
var/turf/T = get_turf(PE)
if(T)
possible_turfs |= T
if(possible_turfs.len)
hard_target = pick(possible_turfs)
/obj/effect/portal/permanent/one_way/one_use
name = "one-use portal"
desc = "This is probably the worst decision you'll ever make in your life."
/obj/effect/portal/permanent/one_way/one_use/teleport(atom/movable/M, force = FALSE)
. = ..()
qdel(src)
@@ -521,7 +521,7 @@
/obj/item/gun/ballistic/automatic/toy/pistol = 5,
/obj/item/firing_pin = 5,
/obj/item/grenade/empgrenade = 15,
/obj/item/clothing/gloves/combat = 10,
/obj/item/clothing/gloves/tackler/combat/insulated = 10,
/obj/item/clothing/shoes/sneakers/noslip = 10
)
+1 -1
View File
@@ -52,7 +52,7 @@
var/list/affecting = list()
/obj/effect/step_trigger/thrower/Trigger(atom/A)
if(!A || !ismovableatom(A))
if(!A || !ismovable(A))
return
var/atom/movable/AM = A
var/curtiles = 0
+2 -2
View File
@@ -7,7 +7,7 @@
if(log)
message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ")
log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ")
log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ")
if(heavy_range >= 1)
new /obj/effect/temp_visual/emp/pulse(epicenter)
@@ -29,4 +29,4 @@
T.emp_act(EMP_LIGHT)
else if(distance <= light_range)
T.emp_act(EMP_LIGHT)
return 1
return 1
+24 -7
View File
@@ -132,6 +132,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/list/grind_results //A reagent list containing the reagents this item produces when ground up in a grinder - this can be an empty list to allow for reagent transferring only
var/list/juice_results //A reagent list containing blah blah... but when JUICED in a grinder!
///Skills vars
//list of skill PATHS exercised when using this item. An associated bitfield can be set to indicate additional ways the skill is used by this specific item.
var/list/datum/skill/used_skills
var/skill_difficulty = THRESHOLD_COMPETENT //how difficult it's to use this item in general.
var/skill_gain = DEF_SKILL_GAIN //base skill value gain from using this item.
/obj/item/Initialize()
if (attack_verb)
@@ -392,7 +398,8 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
if(item_flags & DROPDEL)
qdel(src)
item_flags &= ~IN_INVENTORY
SEND_SIGNAL(src, COMSIG_ITEM_DROPPED,user)
if(SEND_SIGNAL(src, COMSIG_ITEM_DROPPED,user) & COMPONENT_DROPPED_RELOCATION)
. = ITEM_RELOCATED_BY_DROPPED
user.update_equipment_speed_mods()
// called just as an item is picked up (loc is not yet changed)
@@ -433,11 +440,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
// for items that can be placed in multiple slots
// note this isn't called during the initial dressing of a player
/obj/item/proc/equipped(mob/user, slot)
SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot)
for(var/X in actions)
var/datum/action/A = X
if(item_action_slot_check(slot, user, A)) //some items only give their actions buttons when in a specific slot.
A.Grant(user)
. = SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot)
if(!(. & COMPONENT_NO_GRANT_ACTIONS))
for(var/X in actions)
var/datum/action/A = X
if(item_action_slot_check(slot, user, A)) //some items only give their actions buttons when in a specific slot.
A.Grant(user)
item_flags |= IN_INVENTORY
user.update_equipment_speed_mods()
@@ -781,7 +789,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
// Called when a mob tries to use the item as a tool.
// Handles most checks.
/obj/item/proc/use_tool(atom/target, mob/living/user, delay, amount=0, volume=0, datum/callback/extra_checks)
/obj/item/proc/use_tool(atom/target, mob/living/user, delay, amount=0, volume=0, datum/callback/extra_checks, skill_gain_mult = 1, max_level = INFINITY)
// No delay means there is no start message, and no reason to call tool_start_check before use_tool.
// Run the start check here so we wouldn't have to call it manually.
if(!delay && !tool_start_check(user, amount))
@@ -793,6 +801,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
play_tool_sound(target, volume)
if(delay)
if(user.mind && used_skills)
delay = user.mind.skill_holder.item_action_skills_mod(src, delay, skill_difficulty, SKILL_USE_TOOL, NONE, FALSE)
// Create a callback with checks that would be called every tick by do_after.
var/datum/callback/tool_check = CALLBACK(src, .proc/tool_check_callback, user, amount, extra_checks)
@@ -817,6 +828,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
if(delay >= MIN_TOOL_SOUND_DELAY)
play_tool_sound(target, volume)
if(user.mind && used_skills && skill_gain_mult)
for(var/skill in used_skills)
if(!(used_skills[skill] & SKILL_TRAINING_TOOL))
continue
user.mind.skill_holder.auto_gain_experience(skill, skill_gain*skill_gain_mult, GET_STANDARD_LVL(max_level))
return TRUE
// Called before use_tool if there is a delay, or by use_tool if there isn't.
+74 -24
View File
@@ -6,17 +6,42 @@
icon_state = "cutout_basic"
w_class = WEIGHT_CLASS_BULKY
resistance_flags = FLAMMABLE
// Possible restyles for the cutout;
// add an entry in change_appearance() if you add to here
var/list/possible_appearances = list("Assistant", "Clown", "Mime",
"Traitor", "Nuke Op", "Cultist", "Brass Cultist", "Clockwork Cultist",
"Revolutionary", "Wizard", "Shadowling", "Xenomorph", "Xenomorph Maid", "Swarmer",
"Ash Walker", "Deathsquad Officer", "Ian", "Slaughter Demon",
"Laughter Demon", "Private Security Officer", "Securitron", "Gondola", "Monkey")
var/pushed_over = FALSE //If the cutout is pushed over and has to be righted
var/deceptive = FALSE //If the cutout actually appears as what it portray and not a discolored version
/// Possible restyles for the cutout, add an entry in change_appearance() if you add to here
var/static/list/possible_appearances
/// If the cutout is pushed over and has to be righted
var/pushed_over = FALSE
/// If the cutout actually appears as what it portray and not a discolored version
var/deceptive = FALSE
var/lastattacker = null
/obj/item/cardboard_cutout/Initialize()
. = ..()
if(possible_appearances)
return
possible_appearances = sortList(list(
"Assistant" = image(icon = src.icon, icon_state = "cutout_greytide"),
"Clown" = image(icon = src.icon, icon_state = "cutout_clown"),
"Mime" = image(icon = src.icon, icon_state = "cutout_mime"),
"Traitor" = image(icon = src.icon, icon_state = "cutout_traitor"),
"Nuke Op" = image(icon = src.icon, icon_state = "cutout_fluke"),
"Cultist" = image(icon = src.icon, icon_state = "cutout_cultist"),
"Brass Cultist" = image(icon = src.icon, icon_state = "cutout_servant"),
"Clockwork Cultist" = image(icon = src.icon, icon_state = "cutout_new_servant"),
"Revolutionary" = image(icon = src.icon, icon_state = "cutout_viva"),
"Wizard" = image(icon = src.icon, icon_state = "cutout_wizard"),
"Shadowling" = image(icon = src.icon, icon_state = "cutout_shadowling"),
"Xenomorph" = image(icon = src.icon, icon_state = "cutout_fukken_xeno"),
"Xenomorph Maid" = image(icon = src.icon, icon_state = "cutout_lusty"),
"Swarmer" = image(icon = src.icon, icon_state = "cutout_swarmer"),
"Ash Walker" = image(icon = src.icon, icon_state = "cutout_free_antag"),
"Deathsquad Officer" = image(icon = src.icon, icon_state = "cutout_deathsquad"),
"Ian" = image(icon = src.icon, icon_state = "cutout_ian"),
"Slaughter Demon" = image(icon = 'icons/mob/mob.dmi', icon_state = "daemon"),
"Laughter Demon" = image(icon = 'icons/mob/mob.dmi', icon_state = "bowmon"),
"Private Security Officer" = image(icon = src.icon, icon_state = "cutout_ntsec"),
"Securitron" = image(icon = src.icon, icon_state = "cutout_law"),
"Gondola" = image(icon = src.icon, icon_state = "cutout_gondola"),
"Monkey" = image(icon = src.icon, icon_state = "cutout_monky"),
))
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/cardboard_cutout/attack_hand(mob/living/user)
@@ -76,22 +101,21 @@
push_over()
return BULLET_ACT_HIT
/**
* change_appearance: Changes a skin of the cardboard cutout based on a user's choice
*
* Arguments:
* * crayon The crayon used to change and recolor the cardboard cutout
* * user The mob choosing a skin of the cardboard cutout
*/
/obj/item/cardboard_cutout/proc/change_appearance(obj/item/toy/crayon/crayon, mob/living/user)
if(!crayon || !user)
return
if(pushed_over)
to_chat(user, "<span class='warning'>Right [src] first!</span>")
return
if(crayon.check_empty(user))
return
if(crayon.is_capped)
to_chat(user, "<span class='warning'>Take the cap off first!</span>")
return
var/new_appearance = input(user, "Choose a new appearance for [src].", "26th Century Deception") as null|anything in possible_appearances
if(!new_appearance || !crayon || !user.canUseTopic(src))
var/new_appearance = show_radial_menu(user, src, possible_appearances, custom_check = CALLBACK(src, .proc/check_menu, user, crayon), radius = 36, require_near = TRUE)
if(!new_appearance)
return
if(!do_after(user, 10, FALSE, src, TRUE))
return
return FALSE
if(!check_menu(user, crayon))
return FALSE
user.visible_message("<span class='notice'>[user] gives [src] a new look.</span>", "<span class='notice'>Voila! You give [src] a new look.</span>")
crayon.use_charges(1)
crayon.check_empty(user)
@@ -196,7 +220,33 @@
name = "monkey ([rand(1, 999)])"
desc = "A cardboard cutout of a monkey."
icon_state = "cutout_monky"
return 1
else
return FALSE
return TRUE
/**
* check_menu: Checks if we are allowed to interact with a radial menu
*
* Arguments:
* * user The mob interacting with a menu
* * crayon The crayon used to interact with a menu
*/
/obj/item/cardboard_cutout/proc/check_menu(mob/living/user, obj/item/toy/crayon/crayon)
if(!istype(user))
return FALSE
if(user.incapacitated())
return FALSE
if(pushed_over)
to_chat(user, "<span class='warning'>Right [src] first!</span>")
return FALSE
if(!crayon || !user.is_holding(crayon))
return FALSE
if(crayon.check_empty(user))
return FALSE
if(crayon.is_capped)
to_chat(user, "<span class='warning'>Take the cap off first!</span>")
return FALSE
return TRUE
/obj/item/cardboard_cutout/setDir(newdir)
dir = SOUTH
+2
View File
@@ -258,6 +258,8 @@ update_label("John Doe", "Clowny")
chameleon_action.chameleon_type = /obj/item/card/id
chameleon_action.chameleon_name = "ID Card"
chameleon_action.initialize_disguises()
if(!anyone)
AddComponent(/datum/component/identification/syndicate, ID_COMPONENT_DEL_ON_IDENTIFY, ID_COMPONENT_EFFECT_NO_ACTIONS, NONE) //no deconstructive analyzer usage.
/obj/item/card/id/syndicate/afterattack(obj/item/O, mob/user, proximity)
if(!proximity)
+1 -1
View File
@@ -193,7 +193,7 @@
/obj/effect/chrono_field/update_icon()
var/ttk_frame = 1 - (tickstokill / initial(tickstokill))
ttk_frame = CLAMP(CEILING(ttk_frame * CHRONO_FRAME_COUNT, 1), 1, CHRONO_FRAME_COUNT)
ttk_frame = clamp(CEILING(ttk_frame * CHRONO_FRAME_COUNT, 1), 1, CHRONO_FRAME_COUNT)
if(ttk_frame != RPpos)
RPpos = ttk_frame
mob_underlay.icon_state = "frame[RPpos]"
@@ -308,6 +308,13 @@
/obj/item/stock_parts/manipulator = 1,
/obj/item/stock_parts/micro_laser = 1,
/obj/item/stack/sheet/glass = 1)
var/offstation_security_levels = TRUE
/obj/item/circuitboard/machine/mechfab/offstation
offstation_security_levels = FALSE
/obj/item/circuitboard/machine/mechfab/rnd_crafted(obj/machinery/rnd/production/P)
offstation_security_levels = P.offstation_security_levels
/obj/item/circuitboard/machine/cryo_tube
name = "Cryotube (Machine Board)"
@@ -759,6 +766,13 @@
/obj/item/stock_parts/matter_bin = 1,
/obj/item/stock_parts/manipulator = 1,
/obj/item/reagent_containers/glass/beaker = 2)
var/offstation_security_levels = TRUE
/obj/item/circuitboard/machine/circuit_imprinter/offstation
offstation_security_levels = FALSE
/obj/item/circuitboard/machine/mechfab/rnd_crafted(obj/machinery/rnd/production/P)
offstation_security_levels = P.offstation_security_levels
/obj/item/circuitboard/machine/circuit_imprinter/department
name = "Departmental Circuit Imprinter (Machine Board)"
@@ -804,7 +818,7 @@
var/new_cloud = input("Set the public nanite chamber's Cloud ID (1-100).", "Cloud ID", cloud_id) as num|null
if(new_cloud == null)
return
cloud_id = CLAMP(round(new_cloud, 1), 1, 100)
cloud_id = clamp(round(new_cloud, 1), 1, 100)
/obj/item/circuitboard/machine/public_nanite_chamber/examine(mob/user)
. = ..()
@@ -832,6 +846,13 @@
/obj/item/stock_parts/matter_bin = 2,
/obj/item/stock_parts/manipulator = 2,
/obj/item/reagent_containers/glass/beaker = 2)
var/offstation_security_levels = TRUE
/obj/item/circuitboard/machine/protolathe/offstation
offstation_security_levels = FALSE
/obj/item/circuitboard/machine/protolathe/rnd_crafted(obj/machinery/rnd/production/P)
offstation_security_levels = P.offstation_security_levels
/obj/item/circuitboard/machine/protolathe/department
name = "Departmental Protolathe (Machine Board)"
@@ -1033,9 +1054,9 @@
build_path = /obj/machinery/vending/kink
req_components = list(/obj/item/vending_refill/kink = 1)
/obj/item/circuitboard/machine/autoylathe
/obj/item/circuitboard/machine/autolathe/toy
name = "Autoylathe (Machine Board)"
build_path = /obj/machinery/autoylathe
build_path = /obj/machinery/autolathe/toy
req_components = list(
/obj/item/stock_parts/matter_bin = 3,
/obj/item/stock_parts/manipulator = 1,
+17 -19
View File
@@ -59,7 +59,7 @@
var/edible = TRUE // That doesn't mean eating it is a good idea
var/list/reagent_contents = list(/datum/reagent/consumable/nutriment = 1)
var/list/reagent_contents = list(/datum/reagent/consumable/nutriment = 0.1)
// If the user can toggle the colour, a la vanilla spraycan
var/can_change_colour = FALSE
@@ -346,8 +346,8 @@
var/clicky
if(click_params && click_params["icon-x"] && click_params["icon-y"])
clickx = CLAMP(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2)
clicky = CLAMP(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2)
clickx = clamp(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2)
clicky = clamp(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2)
if(!instant)
to_chat(user, "<span class='notice'>You start drawing a [temp] on the [target.name]...</span>")
@@ -487,56 +487,56 @@
icon_state = "crayonred"
paint_color = "#DA0000"
crayon_color = "red"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/red = 1)
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.1, /datum/reagent/colorful_reagent/crayonpowder/red = 0.9)
dye_color = DYE_RED
/obj/item/toy/crayon/orange
icon_state = "crayonorange"
paint_color = "#FF9300"
crayon_color = "orange"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/orange = 1)
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.1, /datum/reagent/colorful_reagent/crayonpowder/orange = 0.9)
dye_color = DYE_ORANGE
/obj/item/toy/crayon/yellow
icon_state = "crayonyellow"
paint_color = "#FFF200"
crayon_color = "yellow"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/yellow = 1)
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.1, /datum/reagent/colorful_reagent/crayonpowder/yellow = 0.9)
dye_color = DYE_YELLOW
/obj/item/toy/crayon/green
icon_state = "crayongreen"
paint_color = "#A8E61D"
crayon_color = "green"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/green = 1)
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.1, /datum/reagent/colorful_reagent/crayonpowder/green = 0.9)
dye_color = DYE_GREEN
/obj/item/toy/crayon/blue
icon_state = "crayonblue"
paint_color = "#00B7EF"
crayon_color = "blue"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/blue = 1)
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.1, /datum/reagent/colorful_reagent/crayonpowder/blue = 0.9)
dye_color = DYE_BLUE
/obj/item/toy/crayon/purple
icon_state = "crayonpurple"
paint_color = "#DA00FF"
crayon_color = "purple"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/purple = 1)
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.1, /datum/reagent/colorful_reagent/crayonpowder/purple = 0.9)
dye_color = DYE_PURPLE
/obj/item/toy/crayon/black
icon_state = "crayonblack"
paint_color = "#1C1C1C" //Not completely black because total black looks bad. So Mostly Black.
crayon_color = "black"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/black = 1)
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.1, /datum/reagent/colorful_reagent/crayonpowder/black = 0.9)
dye_color = DYE_BLACK
/obj/item/toy/crayon/white
icon_state = "crayonwhite"
paint_color = "#FFFFFF"
crayon_color = "white"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/white = 1)
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.1, /datum/reagent/colorful_reagent/crayonpowder/white = 0.9)
dye_color = DYE_WHITE
/obj/item/toy/crayon/mime
@@ -544,7 +544,7 @@
desc = "A very sad-looking crayon."
paint_color = "#FFFFFF"
crayon_color = "mime"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/invisible = 1)
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.1, /datum/reagent/colorful_reagent/crayonpowder/invisible = 0.9)
charges = -1
dye_color = DYE_MIME
@@ -552,10 +552,9 @@
icon_state = "crayonrainbow"
paint_color = "#FFF000"
crayon_color = "rainbow"
reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent = 1)
reagent_contents = list(/datum/reagent/consumable/nutriment = 0.1, /datum/reagent/colorful_reagent = 0.9)
drawtype = RANDOM_ANY // just the default starter.
dye_color = DYE_RAINBOW
charges = -1
/obj/item/toy/crayon/rainbow/afterattack(atom/target, mob/user, proximity, params)
@@ -727,13 +726,12 @@
to_chat(usr, "<span class='warning'>A color that dark on an object like this? Surely not...</span>")
return FALSE
target.add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY)
if(istype(target, /obj/structure/window))
if(color_hex2num(paint_color) < 255)
target.set_opacity(255)
else
target.set_opacity(initial(target.opacity))
var/obj/structure/window/W = target
W.spraycan_paint(paint_color)
else
target.add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY)
. = use_charges(user, 2)
var/fraction = min(1, . / reagents.maximum_volume)
@@ -39,7 +39,7 @@
var/new_duration = input(user, "Set the duration (5-300):", "Desynchronizer", duration / 10) as null|num
if(new_duration)
new_duration = new_duration SECONDS
new_duration = CLAMP(new_duration, 50, max_duration)
new_duration = clamp(new_duration, 50, max_duration)
duration = new_duration
to_chat(user, "<span class='notice'>You set the duration to [DisplayTimeText(duration)].</span>")
return TRUE
@@ -0,0 +1,14 @@
/obj/item/electronics/electrochromatic_kit
name = "electrochromatic kit"
desc = "A kit for upgrading a window into an electrochromatic one."
/// Electrochromatic ID
var/id
/obj/item/electronics/electrochromatic_kit/attack_self(mob/user)
. = ..()
if(.)
return
var/new_id = input(user, "Set this kit's electrochromatic ID", "Set ID", id) as text|null
if(isnull(new_id))
return
id = new_id
@@ -351,6 +351,12 @@
light_color = "#FFAA44"
flashlight_power = 0.8
/obj/item/flashlight/lantern/jade
name = "jade lantern"
desc = "An ornate, green lantern."
color = LIGHT_COLOR_GREEN
light_color = LIGHT_COLOR_GREEN
/obj/item/flashlight/slime
gender = PLURAL
name = "glowing slime extract"
+1 -1
View File
@@ -75,7 +75,7 @@ GLOBAL_LIST_EMPTY(GPS_list)
if(!ui)
// Variable window height, depending on how many GPS units there are
// to show, clamped to relatively safe range.
var/gps_window_height = CLAMP(325 + GLOB.GPS_list.len * 14, 325, 700)
var/gps_window_height = clamp(325 + GLOB.GPS_list.len * 14, 325, 700)
ui = new(user, src, ui_key, "gps", "Global Positioning System", 470, gps_window_height, master_ui, state) //width, height
ui.open()
@@ -171,7 +171,7 @@
// Negative numbers will subtract
/obj/item/lightreplacer/proc/AddUses(amount = 1)
uses = CLAMP(uses + amount, 0, max_uses)
uses = clamp(uses + amount, 0, max_uses)
/obj/item/lightreplacer/proc/AddShards(amount = 1, user)
bulb_shards += amount
+2 -3
View File
@@ -68,10 +68,9 @@
update_icon()
/obj/item/multitool/update_icon_state()
icon_state = initial(icon_state)
if(selected_io)
icon_state = "multitool_red"
else
icon_state = "multitool"
icon_state += "_red"
/obj/item/multitool/proc/wire(var/datum/integrated_io/io, mob/user)
if(!io.holder.assembly)
@@ -8,6 +8,7 @@
level = 1
var/trigger_mob = TRUE
var/trigger_item = FALSE
var/specific_item = null
var/trigger_silent = FALSE
var/sound/trigger_sound = 'sound/effects/pressureplate.ogg'
var/obj/item/assembly/signaler/sigdev = null
@@ -35,6 +36,8 @@
. = ..()
if(!can_trigger || !active)
return
if(trigger_item && !istype(AM, specific_item))
return
if(trigger_mob && isliving(AM))
var/mob/living/L = AM
to_chat(L, "<span class='warning'>You feel something click beneath you!</span>")
@@ -84,7 +84,7 @@
if(!usr.canUseTopic(src, BE_CLOSE))
return
new_code = round(new_code)
new_code = CLAMP(new_code, 1, 100)
new_code = clamp(new_code, 1, 100)
code = new_code
if(href_list["set"] == "power")
@@ -199,7 +199,7 @@
if(!spans)
spans = list(M.speech_span)
if(!language)
language = M.get_default_language()
language = M.get_selected_language()
INVOKE_ASYNC(src, .proc/talk_into_impl, M, message, channel, spans.Copy(), language)
return ITALICS | REDUCE_RANGE
@@ -240,7 +240,7 @@ effective or pretty fucking useless.
charge = max(0,charge - 25)//Quick decrease in light
else
charge = min(max_charge,charge + 50) //Charge in the dark
animate(user,alpha = CLAMP(255 - charge,0,255),time = 10)
animate(user,alpha = clamp(255 - charge,0,255),time = 10)
/obj/item/jammer
+1 -1
View File
@@ -170,7 +170,7 @@
/obj/item/dice/proc/diceroll(mob/user)
result = roll(sides)
if(rigged && result != rigged)
if(prob(CLAMP(1/(sides - 1) * 100, 25, 80)))
if(prob(clamp(1/(sides - 1) * 100, 25, 80)))
result = rigged
var/fake_result = roll(sides)//Daredevil isn't as good as he used to be
var/comment = ""
+29
View File
@@ -57,6 +57,35 @@
on_reading_finished(user)
reading = FALSE
return TRUE
///TRAITS///
/obj/item/book/granter/trait
var/granted_trait
var/traitname = "being cool"
/obj/item/book/granter/trait/already_known(mob/user)
if(!granted_trait)
return TRUE
if(HAS_TRAIT(user, granted_trait))
to_chat(user, "<span class ='notice'>You already have all the insight you need about [traitname].")
return TRUE
return FALSE
/obj/item/book/granter/trait/on_reading_start(mob/user)
to_chat(user, "<span class='notice'>You start reading about [traitname]...</span>")
/obj/item/book/granter/trait/on_reading_finished(mob/user)
to_chat(user, "<span class='notice'>You feel like you've got a good handle on [traitname]!</span>")
ADD_TRAIT(user, granted_trait, BOOK_TRAIT)
/obj/item/book/granter/trait/rifleman
name = "\proper the Neo-Russian Rifleman\'s Primer"
desc = "A book with stains of vodka and...blood? The back is hard to read, but says something about bolt-actions. Or pump-actions. Both, maybe."
oneuse = FALSE
granted_trait = TRAIT_FAST_PUMP
traitname = "riflery"
icon_state = "book1"
remarks = list("One smooth motion...", "Palm the bolt...", "Push up, rotate back, push forward, down...", "Don't slap yourself with the bolt...", "Wait, what's this about pumping?", "Who just scribbled \"Z\" and \"LMB\" on this page?")
///ACTION BUTTONS///
@@ -97,8 +97,7 @@
to_chat(user, "<span class='notice'>You add [A] to the [initial(name)] assembly.</span>")
else if(stage == EMPTY && istype(I, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = I
if (C.use(1))
if (I.use_tool(src, user, 0, 1, max_level = JOB_SKILL_BASIC))
det_time = 50 // In case the cable_coil was removed and readded.
stage_change(WIRED)
to_chat(user, "<span class='notice'>You rig the [initial(name)] assembly.</span>")
+1 -1
View File
@@ -94,7 +94,7 @@
return
var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num
if(user.get_active_held_item() == src)
newtime = CLAMP(newtime, 10, 60000)
newtime = clamp(newtime, 10, 60000)
det_time = newtime
to_chat(user, "Timer set for [det_time] seconds.")
+11 -12
View File
@@ -118,7 +118,7 @@
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
custom_materials = list(/datum/material/iron=150, /datum/material/glass=75)
breakouttime = 300 //Deciseconds = 30s
cuffsound = 'sound/weapons/cablecuff.ogg'
cuffsound = 'sound/weapons/cablecuff.ogg'
/obj/item/restraints/handcuffs/cable/attack_self(mob/user)
to_chat(user, "<span class='notice'>You start unwinding the cable restraints back into coil</span>")
@@ -130,7 +130,7 @@
user.put_in_hands(coil)
coil.color = color
to_chat(user, "<span class='notice'>You unwind the cable restraints back into coil</span>")
/obj/item/restraints/handcuffs/cable/red
color = "#ff0000"
@@ -225,7 +225,6 @@
/obj/item/restraints/handcuffs/fake/kinky
name = "kinky handcuffs"
desc = "Fake handcuffs meant for erotic roleplay."
icon = 'modular_citadel/icons/obj/items_and_weapons.dmi'
icon_state = "handcuffgag"
item_state = "kinkycuff"
@@ -252,7 +251,7 @@
throw_range = 1
icon_state = "beartrap"
desc = "A trap used to catch bears and other legged creatures."
var/armed = 0
var/armed = FALSE
var/trap_damage = 20
/obj/item/restraints/legcuffs/beartrap/Initialize()
@@ -275,14 +274,14 @@
if(armed && isturf(src.loc))
if(isliving(AM))
var/mob/living/L = AM
var/snap = 0
var/snap = FALSE
var/def_zone = BODY_ZONE_CHEST
if(iscarbon(L))
var/mob/living/carbon/C = L
snap = 1
if(!C.lying)
def_zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
if(!C.legcuffed && C.get_num_legs(FALSE) >= 2) //beartrap can't cuff your leg if there's already a beartrap or legcuffs, or you don't have two legs.
snap = TRUE
C.legcuffed = src
forceMove(C)
C.update_equipment_speed_mods()
@@ -291,21 +290,21 @@
else if(isanimal(L))
var/mob/living/simple_animal/SA = L
if(SA.mob_size > MOB_SIZE_TINY)
snap = 1
if(L.movement_type & FLYING)
snap = 0
snap = TRUE
if(L.movement_type & (FLYING | FLOATING))
snap = FALSE
if(snap)
armed = 0
armed = FALSE
icon_state = "[initial(icon_state)][armed]"
playsound(src.loc, 'sound/effects/snap.ogg', 50, 1)
L.visible_message("<span class='danger'>[L] triggers \the [src].</span>", \
"<span class='userdanger'>You trigger \the [src]!</span>")
L.apply_damage(trap_damage,BRUTE, def_zone)
L.apply_damage(trap_damage, BRUTE, def_zone)
..()
/obj/item/restraints/legcuffs/beartrap/energy
name = "energy snare"
armed = 1
armed = TRUE
icon_state = "e_snare"
trap_damage = 0
item_flags = DROPDEL
+2 -2
View File
@@ -197,9 +197,9 @@
/obj/item/his_grace/proc/adjust_bloodthirst(amt)
prev_bloodthirst = bloodthirst
if(prev_bloodthirst < HIS_GRACE_CONSUME_OWNER && !ascended)
bloodthirst = CLAMP(bloodthirst + amt, HIS_GRACE_SATIATED, HIS_GRACE_CONSUME_OWNER)
bloodthirst = clamp(bloodthirst + amt, HIS_GRACE_SATIATED, HIS_GRACE_CONSUME_OWNER)
else if(!ascended)
bloodthirst = CLAMP(bloodthirst + amt, HIS_GRACE_CONSUME_OWNER, HIS_GRACE_FALL_ASLEEP)
bloodthirst = clamp(bloodthirst + amt, HIS_GRACE_CONSUME_OWNER, HIS_GRACE_FALL_ASLEEP)
update_stats()
/obj/item/his_grace/proc/update_stats()
+3 -1
View File
@@ -519,7 +519,9 @@
S.name = name
S.ckey = C.ckey
S.status_flags |= GODMODE
S.language_holder = user.language_holder.copy(S)
S.copy_languages(user, LANGUAGE_MASTER) //Make sure the sword can understand and communicate with the user.
S.update_atom_languages()
grant_all_languages(FALSE, FALSE, TRUE) //Grants omnitongue
S.AddElement(/datum/element/ghost_role_eligibility,penalize_on_ghost = TRUE)
START_PROCESSING(SSprocessing,src)
var/input = stripped_input(S,"What are you named?", ,"", MAX_NAME_LEN)
+1 -1
View File
@@ -74,7 +74,7 @@
L.SetAllImmobility(0)
L.SetSleeping(0)
L.SetUnconscious(0)
L.reagents.add_reagent(/datum/reagent/medicine/muscle_stimulant, CLAMP(5 - L.reagents.get_reagent_amount(/datum/reagent/medicine/muscle_stimulant), 0, 5)) //If you don't have legs or get bola'd, tough luck!
L.reagents.add_reagent(/datum/reagent/medicine/muscle_stimulant, clamp(5 - L.reagents.get_reagent_amount(/datum/reagent/medicine/muscle_stimulant), 0, 5)) //If you don't have legs or get bola'd, tough luck!
colorize(L)
/obj/item/hot_potato/examine(mob/user)
+23
View File
@@ -3,6 +3,7 @@
* Fork
* Kitchen knives
* Ritual Knife
* Bloodletter
* Butcher's cleaver
* Combat Knife
* Rolling Pins
@@ -97,6 +98,28 @@
righthand_file = 'icons/mob/inhands/equipment/kitchen_righthand.dmi'
w_class = WEIGHT_CLASS_NORMAL
/obj/item/kitchen/knife/bloodletter
name = "bloodletter"
desc = "An occult looking dagger that is cold to the touch. Somehow, the flawless orb on the pommel is made entirely of liquid blood."
icon = 'icons/obj/ice_moon/artifacts.dmi'
icon_state = "bloodletter"
w_class = WEIGHT_CLASS_NORMAL
/// Bleed stacks applied when an organic mob target is hit
var/bleed_stacks_per_hit = 3
/obj/item/kitchen/knife/bloodletter/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(!isliving(target) || !proximity_flag)
return
var/mob/living/M = target
if(!(M.mob_biotypes & MOB_ORGANIC))
return
var/datum/status_effect/stacking/saw_bleed/bloodletting/B = M.has_status_effect(/datum/status_effect/stacking/saw_bleed/bloodletting)
if(!B)
M.apply_status_effect(/datum/status_effect/stacking/saw_bleed/bloodletting, bleed_stacks_per_hit)
else
B.add_stacks(bleed_stacks_per_hit)
/obj/item/kitchen/knife/butcher
name = "butcher's cleaver"
icon_state = "butch"
+3 -3
View File
@@ -304,7 +304,7 @@
return
else
if(cooldown_check < world.time)
if(target.run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user) & BLOCK_SUCCESS)
if(target.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, null) & BLOCK_SUCCESS)
playsound(target, 'sound/weapons/genhit.ogg', 50, 1)
return
if(ishuman(target))
@@ -325,7 +325,7 @@
else
target.LAssailant = WEAKREF(user)
cooldown_check = world.time + cooldown
user.adjustStaminaLossBuffered(getweight())//CIT CHANGE - makes swinging batons cost stamina
user.adjustStaminaLossBuffered(getweight(user, STAM_COST_BATON_MOB_MULT))
else
var/wait_desc = get_wait_description()
if(wait_desc)
@@ -648,7 +648,7 @@
item_state = "mace_greyscale"
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS //Material type changes the prefix as well as the color.
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS | MATERIAL_EFFECTS //Material type changes the prefix as well as the color.
custom_materials = list(/datum/material/iron = 12000) //Defaults to an Iron Mace.
slot_flags = ITEM_SLOT_BELT
force = 14
-8
View File
@@ -123,11 +123,3 @@
w_class = WEIGHT_CLASS_BULKY
attack_verb = list("skubbed")
/obj/item/supermatterspray
name = "supermatter spray"
desc = "A spray bottle containing some kind of magical spray to fix the SM. \"Do not inhale.\" is written on the side. Unless aimed at the supermatter, it does nothing."
icon = 'icons/obj/supermatter.dmi'
icon_state = "supermatterspray"
w_class = WEIGHT_CLASS_SMALL
var/usesleft = 2
+1 -1
View File
@@ -112,7 +112,7 @@
. = ..()
if(!proximity)
return
if(!isturf(target) || !isobj(target))
if(!isturf(target) && !isobj(target))
return
if(target.color != initial(target.color))
target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
+2 -2
View File
@@ -201,8 +201,8 @@
return target
var/x_o = (target.x - starting.x)
var/y_o = (target.y - starting.y)
var/new_x = CLAMP((starting.x + (x_o * range_multiplier)), 0, world.maxx)
var/new_y = CLAMP((starting.y + (y_o * range_multiplier)), 0, world.maxy)
var/new_x = clamp((starting.x + (x_o * range_multiplier)), 0, world.maxx)
var/new_y = clamp((starting.y + (y_o * range_multiplier)), 0, world.maxy)
var/turf/newtarget = locate(new_x, new_y, starting.z)
return newtarget
+146
View File
@@ -0,0 +1,146 @@
//**************
//*****Keys*******************
//************** ** **
/obj/item/keycard
name = "security keycard"
desc = "This feels like it belongs to a door."
icon = 'icons/obj/puzzle_small.dmi'
icon_state = "keycard"
force = 0
throwforce = 0
w_class = WEIGHT_CLASS_TINY
throw_speed = 1
throw_range = 7
resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF
var/puzzle_id = null
//Two test keys for use alongside the two test doors.
/obj/item/keycard/cheese
name = "cheese keycard"
desc = "Look, I still don't understand the reference. What the heck is a keyzza?"
color = "#f0da12"
puzzle_id = "cheese"
/obj/item/keycard/swordfish
name = "titanic keycard"
desc = "Smells like it was at the bottom of a harbor."
color = "#3bbbdb"
puzzle_id = "swordfish"
//***************
//*****Doors*****
//***************
/obj/machinery/door/keycard
name = "locked door"
desc = "This door only opens when a keycard is swiped. It looks virtually indestructable."
icon = 'icons/obj/doors/puzzledoor/default.dmi'
icon_state = "door_closed"
explosion_block = 3
heat_proof = TRUE
max_integrity = 600
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF
damage_deflection = 70
/// Make sure that the key has the same puzzle_id as the keycard door!
var/puzzle_id = null
/// Message that occurs when the door is opened
var/open_message = "The door beeps, and slides opens."
//Standard Expressions to make keycard doors basically un-cheeseable
/obj/machinery/door/keycard/Bumped(atom/movable/AM)
return !density && ..()
/obj/machinery/door/keycard/emp_act(severity)
return
/obj/machinery/door/keycard/ex_act(severity, target)
return
/obj/machinery/door/keycard/try_to_activate_door(mob/user)
add_fingerprint(user)
if(operating)
return
/obj/machinery/door/keycard/attackby(obj/item/I, mob/user, params)
. = ..()
if(istype(I,/obj/item/keycard))
var/obj/item/keycard/key = I
if((!puzzle_id || puzzle_id == key.puzzle_id) && density)
if(open_message)
to_chat(user, "<span class='notice'>[open_message]</span>")
open()
return
else if(puzzle_id != key.puzzle_id)
to_chat(user, "<span class='notice'>[src] buzzes. This must not be the right key.</span>")
return
else
to_chat(user, "<span class='notice'>This door doesn't appear to close.</span>")
return
//Test doors. Gives admins a few doors to use quickly should they so choose.
/obj/machinery/door/keycard/cheese
name = "blue airlock"
desc = "Smells like... pizza?"
puzzle_id = "cheese"
/obj/machinery/door/keycard/swordfish
name = "blue airlock"
desc = "If nautical nonsense be something you wish."
puzzle_id = "swordfish"
//*************************
//***Box Pushing Puzzles***
//*************************
//We're working off a subtype of pressureplates, which should work just a BIT better now.
/obj/structure/holobox
name = "holobox"
desc = "A hard-light box, containing a secure decryption key."
icon = 'icons/obj/puzzle_small.dmi'
icon_state = "laserbox"
density = TRUE
resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF
//Uses the pressure_plate settings for a pretty basic custom pattern that waits for a specific item to trigger. Easy enough to retool for mapping purposes or subtypes.
/obj/item/pressure_plate/hologrid
name = "hologrid"
desc = "A high power, electronic input port for a holobox, which can unlock the hologrid's storage compartment. Safe to stand on."
icon = 'icons/obj/puzzle_small.dmi'
icon_state = "lasergrid"
anchored = TRUE
trigger_mob = FALSE
trigger_item = TRUE
specific_item = /obj/structure/holobox
removable_signaller = FALSE //Being a pressure plate subtype, this can also use signals.
roundstart_signaller_freq = FREQ_HOLOGRID_SOLUTION //Frequency is kept on it's own default channel however.
active = TRUE
trigger_delay = 10
resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF
var/reward = /obj/item/reagent_containers/food/snacks/cookie
var/claimed = FALSE
/obj/item/pressure_plate/hologrid/examine(mob/user)
. = ..()
if(claimed)
. += "<span class='notice'>This one appears to be spent already.</span>"
/obj/item/pressure_plate/hologrid/trigger()
if(!claimed)
new reward(loc)
flick("lasergrid_a",src)
icon_state = "lasergrid_full"
claimed = TRUE
/obj/item/pressure_plate/hologrid/Crossed(atom/movable/AM)
. = ..()
if(trigger_item && istype(AM, specific_item) && !claimed)
AM.anchored = TRUE
flick("laserbox_burn", AM)
trigger()
sleep(15)
qdel(AM)
// snowflake code until undertile elements
/obj/item/pressure_plate/hologrid/hide()
. = ..()
anchored = TRUE
+3 -3
View File
@@ -11,7 +11,7 @@
var/charge_cost = 30
/obj/item/borg/stun/attack(mob/living/M, mob/living/user)
if(M.run_block(src, 0, "[M]'s [name]", ATTACK_TYPE_MELEE, 0, user, ran_zone(user.zone_selected)) & BLOCK_SUCCESS)
if(M.mob_run_block(src, 0, "[M]'s [name]", ATTACK_TYPE_MELEE, 0, user, ran_zone(user.zone_selected), null) & BLOCK_SUCCESS)
playsound(M, 'sound/weapons/genhit.ogg', 50, 1)
return FALSE
if(iscyborg(user))
@@ -649,7 +649,7 @@
continue
usage += projectile_tick_speed_ecost
usage += (tracked[I] * projectile_damage_tick_ecost_coefficient)
energy = CLAMP(energy - usage, 0, maxenergy)
energy = clamp(energy - usage, 0, maxenergy)
if(energy <= 0)
deactivate_field()
visible_message("<span class='warning'>[src] blinks \"ENERGY DEPLETED\".</span>")
@@ -659,7 +659,7 @@
if(iscyborg(host.loc))
host = host.loc
else
energy = CLAMP(energy + energy_recharge, 0, maxenergy)
energy = clamp(energy + energy_recharge, 0, maxenergy)
return
if(host.cell && (host.cell.charge >= (host.cell.maxcharge * cyborg_cell_critical_percentage)) && (energy < maxenergy))
host.cell.use(energy_recharge*energy_recharge_cyborg_drain_coefficient)
+3 -3
View File
@@ -35,14 +35,14 @@
if(TH.force_wielded > initial(TH.force_wielded))
to_chat(user, "<span class='warning'>[TH] has already been refined before. It cannot be sharpened further!</span>")
return
TH.force_wielded = CLAMP(TH.force_wielded + increment, 0, max)//wieldforce is increased since normal force wont stay
TH.force_wielded = clamp(TH.force_wielded + increment, 0, max)//wieldforce is increased since normal force wont stay
if(I.force > initial(I.force))
to_chat(user, "<span class='warning'>[I] has already been refined before. It cannot be sharpened further!</span>")
return
user.visible_message("<span class='notice'>[user] sharpens [I] with [src]!</span>", "<span class='notice'>You sharpen [I], making it much more deadly than before.</span>")
I.sharpness = IS_SHARP_ACCURATE
I.force = CLAMP(I.force + increment, 0, max)
I.throwforce = CLAMP(I.throwforce + increment, 0, max)
I.force = clamp(I.force + increment, 0, max)
I.throwforce = clamp(I.throwforce + increment, 0, max)
I.name = "[prefix] [I.name]"
name = "worn out [name]"
desc = "[desc] At least, it used to."
+54 -22
View File
@@ -33,11 +33,11 @@
return TRUE
/obj/item/shield/alt_pre_attack(atom/A, mob/living/user, params)
user_shieldbash(user, A, user.a_intent != INTENT_HARM)
user_shieldbash(user, A, user.a_intent == INTENT_HARM)
return TRUE
/obj/item/shield/altafterattack(atom/target, mob/user, proximity_flag, click_parameters)
user_shieldbash(user, target, user.a_intent != INTENT_HARM)
user_shieldbash(user, target, user.a_intent == INTENT_HARM)
return TRUE
/obj/item/shield/proc/do_shieldbash_effect(mob/living/user, dir, harmful)
@@ -52,13 +52,13 @@
px = 12
if(WEST)
px = -12
var/oldpx = user.pixel_x
var/oldpy = user.pixel_y
animate(user, pixel_x = px, pixel_y = py, time = 3, easing = SINE_EASING | EASE_OUT, flags = ANIMATION_END_NOW)
animate(user, pixel_x = oldpx, pixel_y = oldpy, time = 3)
user.visible_message("<span class='warning'>[user] [harmful? "charges forwards with" : "sweeps"] [src]!</span>")
var/obj/effect/temp_visual/dir_setting/shield_bash/effect = new(user.loc, dir)
animate(effect, alpha = 0, pixel_x = px + 4, pixel_y = py + 4, time = 3)
effect.pixel_x = user.pixel_x - 32 //96x96 effect, -32.
effect.pixel_y = user.pixel_y - 32
user.visible_message("<span class='warning'>[user] [harmful? "charges forwards with" : "sweeps"] [src]!</span>")
animate(user, pixel_x = px, pixel_y = py, time = 3, easing = SINE_EASING | EASE_OUT, flags = ANIMATION_PARALLEL | ANIMATION_RELATIVE)
animate(user, pixel_x = -px, pixel_y = -py, time = 3, flags = ANIMATION_RELATIVE)
animate(effect, alpha = 0, pixel_x = px * 1.5, pixel_y = py * 1.5, time = 3, flags = ANIMATION_PARALLEL | ANIMATION_RELATIVE)
/obj/item/shield/proc/bash_target(mob/living/user, mob/living/target, bashdir, harmful)
if(!(target.status_flags & CANKNOCKDOWN) || HAS_TRAIT(src, TRAIT_STUNIMMUNE)) // should probably add stun absorption check at some point I guess..
@@ -76,7 +76,7 @@
"<span class='warning'>[user] shoves you with [src]!</span>")
for(var/i in 1 to harmful? shieldbash_knockback : shieldbash_push_distance)
var/turf/new_turf = get_step(target, bashdir)
var/mob/living/carbon/human/H = locate() in new_turf
var/mob/living/carbon/human/H = locate() in (new_turf.contents - target)
if(H && harmful)
H.visible_message("<span class='warning'>[target] is sent crashing into [H]!</span>",
"<span class='userdanger'>[target] is sent crashing into you!</span>")
@@ -107,13 +107,19 @@
return TRUE
/obj/item/shield/proc/user_shieldbash(mob/living/user, atom/target, harmful)
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) //Combat mode has to be enabled for shield bashing
return FALSE
if(!(shield_flags & SHIELD_CAN_BASH))
to_chat(user, "<span class='warning'>[src] can't be used to shield bash!</span>")
return FALSE
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
to_chat(user, "<span class='warning'>You can't bash with [src] while on the ground!</span>")
return FALSE
if(world.time < last_shieldbash + shieldbash_cooldown)
to_chat(user, "<span class='warning'>You can't bash with [src] again so soon!</span>")
return FALSE
if(isliving(target)) //GROUND SLAAAM
var/mob/living/livingtarget = target //only access after an isliving check!
if(isliving(target) && !CHECK_MOBILITY(livingtarget, MOBILITY_STAND)) //GROUND SLAAAM
if(!(shield_flags & SHIELD_BASH_GROUND_SLAM))
to_chat(user, "<span class='warning'>You can't ground slam with [src]!</span>")
return FALSE
@@ -122,7 +128,7 @@
playsound(src, harmful? "swing_hit" : 'sound/weapons/thudswoosh.ogg', 75, 1)
last_shieldbash = world.time
user.adjustStaminaLossBuffered(shieldbash_stamcost)
return 1
return TRUE
// Directional sweep!
last_shieldbash = world.time
user.adjustStaminaLossBuffered(shieldbash_stamcost)
@@ -164,11 +170,12 @@
attack_verb = list("shoved", "bashed")
var/cooldown = 0 //shield bash cooldown. based on world.time
var/repair_material = /obj/item/stack/sheet/mineral/titanium
var/can_shatter = TRUE
shield_flags = SHIELD_FLAGS_DEFAULT | SHIELD_TRANSPARENT
max_integrity = 75
/obj/item/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)
if(ismovableatom(object))
if(ismovable(object))
var/atom/movable/AM = object
if(CHECK_BITFIELD(shield_flags, SHIELD_TRANSPARENT) && (AM.pass_flags & PASSGLASS))
return BLOCK_NONE
@@ -213,7 +220,7 @@
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)
if(obj_integrity <= damage)
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)
@@ -324,7 +331,6 @@ obj/item/shield/riot/bullet_proof
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'
icon = 'icons/obj/items_and_weapons.dmi'
item_state = "metal"
icon_state = "makeshift_shield"
custom_materials = list(/datum/material/iron = 18000)
@@ -340,7 +346,6 @@ obj/item/shield/riot/bullet_proof
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"
icon = 'icons/obj/items_and_weapons.dmi'
block_chance = 75 //1/4 shots will hit*
force = 16
slowdown = 2
@@ -356,20 +361,47 @@ obj/item/shield/riot/bullet_proof
block_chance = 50
/obj/item/shield/riot/implant
name = "riot tower shield"
desc = "A massive shield that can block a lot of attacks and can take a lot of abuse before breaking." //It cant break unless it is removed from the 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"
block_chance = 30 //May be big but hard to move around to block.
block_chance = 50
slowdown = 1
shield_flags = SHIELD_FLAGS_DEFAULT
max_integrity = 60
obj_integrity = 60
can_shatter = FALSE
item_flags = SLOWS_WHILE_IN_HAND
var/recharge_timerid
var/recharge_delay = 15 SECONDS
/obj/item/shield/riot/implant/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
if(attack_type & ATTACK_TYPE_PROJECTILE)
final_block_chance = 60 //Massive shield
return ..()
/// Entirely overriden take_damage. This shouldn't exist outside of an implant (other than maybe christmas).
/obj/item/shield/riot/implant/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir, armour_penetration = 0)
obj_integrity -= damage_amount
if(obj_integrity < 0)
obj_integrity = 0
if(obj_integrity == 0)
if(ismob(loc))
var/mob/living/L = loc
playsound(src, 'sound/effects/glassbr3.ogg', 100)
L.visible_message("<span class='boldwarning'>[src] overloads from the damage sustained!</span>")
L.dropItemToGround(src) //implant component catch hook will grab it.
/obj/item/shield/riot/implant/Moved()
. = ..()
if(istype(loc, /obj/item/organ/cyberimp/arm/shield))
recharge_timerid = addtimer(CALLBACK(src, .proc/recharge), recharge_delay, flags = TIMER_STOPPABLE)
else //extending
if(recharge_timerid)
deltimer(recharge_timerid)
recharge_timerid = null
/obj/item/shield/riot/implant/proc/recharge()
if(obj_integrity == max_integrity)
return
obj_integrity = max_integrity
if(ismob(loc.loc)) //cyberimplant.user
to_chat(loc, "<span class='notice'>[src] has recharged its reinforcement matrix and is ready for use!</span>")
/obj/item/shield/energy
name = "energy combat shield"
+1 -1
View File
@@ -37,7 +37,7 @@
/obj/item/twohanded/singularityhammer/proc/vortex(turf/pull, mob/wielder)
for(var/atom/X in orange(5,pull))
if(ismovableatom(X))
if(ismovable(X))
var/atom/movable/A = X
if(A == wielder)
continue
+16
View File
@@ -59,6 +59,9 @@
self_delay = 20
grind_results = list(/datum/reagent/medicine/styptic_powder = 10)
/obj/item/stack/medical/bruise_pack/one
amount = 1
/obj/item/stack/medical/bruise_pack/heal(mob/living/M, mob/user)
if(M.stat == DEAD)
to_chat(user, "<span class='notice'> [M] is dead. You can not help [M.p_them()]!</span>")
@@ -100,6 +103,7 @@
if(!H.bleedsuppress && H.bleed_rate) //so you can't stack bleed suppression
H.suppress_bloodloss(stop_bleeding)
to_chat(user, "<span class='notice'>You stop the bleeding of [M]!</span>")
H.adjustBruteLoss(-(heal_brute))
return TRUE
to_chat(user, "<span class='notice'>You can not use \the [src] on [M]!</span>")
@@ -127,6 +131,15 @@
stop_bleeding = 900
heal_brute = 0
/obj/item/stack/medical/gauze/adv
name = "sterilized medical gauze"
desc = "A roll of elastic sterilized cloth that is extremely effective at stopping bleeding, heals minor wounds and cleans them."
singular_name = "sterilized medical gauze"
self_delay = 5
/obj/item/stack/medical/gauze/adv/one
amount = 1
/obj/item/stack/medical/gauze/cyborg
custom_materials = null
is_cyborg = 1
@@ -144,6 +157,9 @@
self_delay = 20
grind_results = list(/datum/reagent/medicine/silver_sulfadiazine = 10)
/obj/item/stack/medical/ointment/one
amount = 1
/obj/item/stack/medical/ointment/heal(mob/living/M, mob/user)
if(M.stat == DEAD)
to_chat(user, "<span class='notice'> [M] is dead. You can not help [M.p_them()]!</span>")
@@ -69,7 +69,7 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
if (get_amount() < 1 || CC.get_amount() < 5)
to_chat(user, "<span class='warning>You need five lengths of coil and one sheet of glass to make wired glass!</span>")
return
CC.use(5)
CC.use_tool(src, user, 0, 5, max_level = JOB_SKILL_BASIC)
use(1)
to_chat(user, "<span class='notice'>You attach wire to the [name].</span>")
var/obj/item/stack/light_w/new_tile = new(user.loc)
@@ -109,7 +109,6 @@ GLOBAL_LIST_INIT(pglass_recipes, list ( \
merge_type = /obj/item/stack/sheet/plasmaglass
grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/toxin/plasma = 10)
tableVariant = /obj/structure/table/plasmaglass
material_flags = MATERIAL_NO_EFFECTS
shard_type = /obj/item/shard/plasma
/obj/item/stack/sheet/plasmaglass/fifty
@@ -209,7 +208,6 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \
custom_materials = list(/datum/material/plasma=MINERAL_MATERIAL_AMOUNT * 0.5, /datum/material/glass=MINERAL_MATERIAL_AMOUNT, /datum/material/iron=MINERAL_MATERIAL_AMOUNT * 0.5,)
armor = list("melee" = 20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 100)
resistance_flags = ACID_PROOF
material_flags = MATERIAL_NO_EFFECTS
merge_type = /obj/item/stack/sheet/plasmarglass
grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/toxin/plasma = 10, /datum/reagent/iron = 10)
point_value = 23
@@ -259,7 +257,6 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
item_state = "sheet-plastitaniumglass"
custom_materials = list(/datum/material/titanium=MINERAL_MATERIAL_AMOUNT * 0.5, /datum/material/plasma=MINERAL_MATERIAL_AMOUNT * 0.5, /datum/material/glass=MINERAL_MATERIAL_AMOUNT)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 100)
material_flags = MATERIAL_NO_EFFECTS
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/plastitaniumglass
shard_type = /obj/item/shard
@@ -178,6 +178,11 @@ GLOBAL_LIST_INIT(leather_recipes, list ( \
icon_state = "sinew"
novariants = TRUE
/obj/item/stack/sheet/sinew/wolf
name = "wolf sinew"
desc = "Long stringy filaments which came from the insides of a wolf."
singular_name = "wolf sinew"
GLOBAL_LIST_INIT(sinew_recipes, list ( \
new/datum/stack_recipe("sinew restraints", /obj/item/restraints/handcuffs/sinew, 1), \
@@ -202,6 +207,11 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
w_class = WEIGHT_CLASS_NORMAL
layer = MOB_LAYER
/obj/item/stack/sheet/animalhide/goliath_hide/polar_bear_hide
name = "polar bear hides"
desc = "Pieces of a polar bear's fur, these might be able to make your suit a bit more durable to attack from the local fauna."
icon_state = "polar_bear_hide"
singular_name = "polar bear hide"
/obj/item/stack/sheet/animalhide/ashdrake
name = "ash drake hide"
@@ -324,7 +324,6 @@ GLOBAL_LIST_INIT(titanium_recipes, list ( \
custom_materials = list(/datum/material/titanium=MINERAL_MATERIAL_AMOUNT, /datum/material/plasma=MINERAL_MATERIAL_AMOUNT)
point_value = 45
merge_type = /obj/item/stack/sheet/mineral/plastitanium
material_flags = MATERIAL_NO_EFFECTS
/obj/item/stack/sheet/mineral/plastitanium/fifty
amount = 50
@@ -215,7 +215,6 @@ GLOBAL_LIST_INIT(plasteel_recipes, list ( \
grind_results = list(/datum/reagent/iron = 20, /datum/reagent/toxin/plasma = 20)
point_value = 23
tableVariant = /obj/structure/table/reinforced
material_flags = MATERIAL_NO_EFFECTS
/obj/item/stack/sheet/plasteel/get_main_recipes()
. = ..()
+2 -2
View File
@@ -71,9 +71,9 @@
/obj/item/stack/proc/update_weight()
if(amount <= (max_amount * (1/3)))
w_class = CLAMP(full_w_class-2, WEIGHT_CLASS_TINY, full_w_class)
w_class = clamp(full_w_class-2, WEIGHT_CLASS_TINY, full_w_class)
else if (amount <= (max_amount * (2/3)))
w_class = CLAMP(full_w_class-1, WEIGHT_CLASS_TINY, full_w_class)
w_class = clamp(full_w_class-1, WEIGHT_CLASS_TINY, full_w_class)
else
w_class = full_w_class
@@ -78,4 +78,3 @@
turf_type = /turf/open/floor/mineral/plastitanium
mineralType = "plastitanium"
custom_materials = list(/datum/material/titanium=250, /datum/material/plasma=250)
material_flags = MATERIAL_NO_EFFECTS
+1 -1
View File
@@ -412,7 +412,7 @@
STR.max_combined_w_class = 200
STR.max_items = 25
STR.insert_preposition = "in"
STR.can_hold = typecacheof(list(/obj/item/slime_extract, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/blood, /obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/food/snacks/deadmouse, /obj/item/reagent_containers/food/snacks/monkeycube, /obj/item/organ, /obj/item/reagent_containers/food/snacks/meat/slab, /obj/item/bodypart))
STR.can_hold = typecacheof(list(/obj/item/slime_extract, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/blood, /obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/food/snacks/deadmouse, /obj/item/reagent_containers/food/snacks/cube, /obj/item/organ, /obj/item/reagent_containers/food/snacks/meat/slab, /obj/item/bodypart))
STR.cant_hold = typecacheof(list(/obj/item/organ/brain, /obj/item/organ/liver/cybernetic, /obj/item/organ/heart/cybernetic, /obj/item/organ/lungs/cybernetic, /obj/item/organ/tongue/cybernetic, /obj/item/organ/ears/cybernetic, /obj/item/organ/eyes/robotic, /obj/item/organ/cyberimp))
/obj/item/storage/bag/bio/holding
+4 -1
View File
@@ -695,7 +695,10 @@
/obj/item/gun/ballistic/revolver,
/obj/item/ammo_box,
/obj/item/toy/gun,
/obj/item/gun/energy/e_gun/mini
/obj/item/gun/energy/e_gun/mini,
/obj/item/gun/ballistic/automatic/magrifle/pistol,
/obj/item/gun/energy/disabler,
/obj/item/gun/energy/taser
))
/obj/item/storage/belt/holster/full/PopulateContents()
+55 -41
View File
@@ -454,11 +454,11 @@
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 7
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/monkeycube))
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/cube/monkey))
/obj/item/storage/box/monkeycubes/PopulateContents()
for(var/i in 1 to 5)
new /obj/item/reagent_containers/food/snacks/monkeycube(src)
new /obj/item/reagent_containers/food/snacks/cube/monkey(src)
/obj/item/storage/box/ids
name = "box of spare IDs"
@@ -850,12 +850,6 @@
#define NODESIGN "None"
#define NANOTRASEN "NanotrasenStandard"
#define SYNDI "SyndiSnacks"
#define HEART "Heart"
#define SMILEY "SmileyFace"
/obj/item/storage/box/papersack
name = "paper sack"
desc = "A sack neatly crafted out of paper."
@@ -863,7 +857,18 @@
item_state = "paperbag_None"
resistance_flags = FLAMMABLE
foldable = null
var/design = NODESIGN
/// A list of all available papersack reskins
var/list/papersack_designs = list()
/obj/item/storage/box/papersack/Initialize(mapload)
. = ..()
papersack_designs = sortList(list(
"None" = image(icon = src.icon, icon_state = "paperbag_None"),
"NanotrasenStandard" = image(icon = src.icon, icon_state = "paperbag_NanotrasenStandard"),
"SyndiSnacks" = image(icon = src.icon, icon_state = "paperbag_SyndiSnacks"),
"Heart" = image(icon = src.icon, icon_state = "paperbag_Heart"),
"SmileyFace" = image(icon = src.icon, icon_state = "paperbag_SmileyFace")
))
/obj/item/storage/box/papersack/update_icon_state()
if(contents.len == 0)
@@ -871,55 +876,64 @@
else
icon_state = "[item_state]_closed"
/obj/item/storage/box/papersack/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/pen))
//if a pen is used on the sack, dialogue to change its design appears
if(contents.len)
to_chat(user, "<span class='warning'>You can't modify [src] with items still inside!</span>")
return
var/list/designs = list(NODESIGN, NANOTRASEN, SYNDI, HEART, SMILEY, "Cancel")
var/switchDesign = input("Select a Design:", "Paper Sack Design", designs[1]) in designs
if(get_dist(usr, src) > 1)
to_chat(usr, "<span class='warning'>You have moved too far away!</span>")
return
var/choice = designs.Find(switchDesign)
if(design == designs[choice] || designs[choice] == "Cancel")
return 0
to_chat(usr, "<span class='notice'>You make some modifications to [src] using your pen.</span>")
design = designs[choice]
icon_state = "paperbag_[design]"
item_state = "paperbag_[design]"
switch(designs[choice])
if(NODESIGN)
var/choice = show_radial_menu(user, src , papersack_designs, custom_check = CALLBACK(src, .proc/check_menu, user, W), radius = 36, require_near = TRUE)
if(!choice)
return FALSE
if(icon_state == "paperbag_[choice]")
return FALSE
switch(choice)
if("None")
desc = "A sack neatly crafted out of paper."
if(NANOTRASEN)
if("NanotrasenStandard")
desc = "A standard Nanotrasen paper lunch sack for loyal employees on the go."
if(SYNDI)
if("SyndiSnacks")
desc = "The design on this paper sack is a remnant of the notorious 'SyndieSnacks' program."
if(HEART)
if("Heart")
desc = "A paper sack with a heart etched onto the side."
if(SMILEY)
if("SmileyFace")
desc = "A paper sack with a crude smile etched onto the side."
return 0
else
return FALSE
to_chat(user, "<span class='notice'>You make some modifications to [src] using your pen.</span>")
icon_state = "paperbag_[choice]"
item_state = "paperbag_[choice]"
return FALSE
else if(W.get_sharpness())
if(!contents.len)
if(item_state == "paperbag_None")
user.show_message("<span class='notice'>You cut eyeholes into [src].</span>", MSG_VISUAL)
new /obj/item/clothing/head/papersack(user.loc)
qdel(src)
return 0
return FALSE
else if(item_state == "paperbag_SmileyFace")
user.show_message("<span class='notice'>You cut eyeholes into [src] and modify the design.</span>", MSG_VISUAL)
new /obj/item/clothing/head/papersack/smiley(user.loc)
qdel(src)
return 0
return FALSE
return ..()
#undef NODESIGN
#undef NANOTRASEN
#undef SYNDI
#undef HEART
#undef SMILEY
/**
* check_menu: Checks if we are allowed to interact with a radial menu
*
* Arguments:
* * user The mob interacting with a menu
* * P The pen used to interact with a menu
*/
/obj/item/storage/box/papersack/proc/check_menu(mob/user, obj/item/pen/P)
if(!istype(user))
return FALSE
if(user.incapacitated())
return FALSE
if(contents.len)
to_chat(user, "<span class='warning'>You can't modify [src] with items still inside!</span>")
return FALSE
if(!P || !user.is_holding(P))
to_chat(user, "<span class='warning'>You need a pen to modify [src]!</span>")
return FALSE
return TRUE
/obj/item/storage/box/ingredients //This box is for the randomly chosen version the chef spawns with, it shouldn't actually exist.
name = "ingredients box"
@@ -1117,9 +1131,9 @@
desc = "A box containing a gift for worthy golems."
/obj/item/storage/box/rndboards/PopulateContents()
new /obj/item/circuitboard/machine/protolathe(src)
new /obj/item/circuitboard/machine/protolathe/offstation(src)
new /obj/item/circuitboard/machine/destructive_analyzer(src)
new /obj/item/circuitboard/machine/circuit_imprinter(src)
new /obj/item/circuitboard/machine/circuit_imprinter/offstation(src)
new /obj/item/circuitboard/computer/rdconsole(src)
/obj/item/storage/box/silver_sulf

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