Conflict fix

This commit is contained in:
Artur
2020-02-12 16:21:29 +02:00
401 changed files with 9640 additions and 8170 deletions
+6 -4
View File
@@ -106,6 +106,9 @@
#define COMSIG_CLICK "atom_click" //from base of atom/Click(): (location, control, params, mob/user)
#define COMSIG_CLICK_SHIFT "shift_click" //from base of atom/ShiftClick(): (/mob)
#define COMPONENT_ALLOW_EXAMINATE 1
#define COMPONENT_DENY_EXAMINATE 2 //Higher priority compared to the above one
#define COMSIG_CLICK_CTRL "ctrl_click" //from base of atom/CtrlClickOn(): (/mob)
#define COMSIG_CLICK_ALT "alt_click" //from base of atom/AltClick(): (/mob)
#define COMSIG_CLICK_CTRL_SHIFT "ctrl_shift_click" //from base of atom/CtrlShiftClick(/mob)
@@ -159,7 +162,6 @@
// /mob signals
#define COMSIG_MOB_EXAMINATE "mob_examinate" //from base of /mob/verb/examinate(): (atom/A)
#define COMPONENT_ALLOW_EXAMINE 1
#define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed)
#define COMPONENT_BLOCK_DEATH_BROADCAST 1 //stops the death from being broadcasted in deadchat.
#define COMSIG_MOB_GHOSTIZE "mob_ghostize" //from base of mob/Ghostize(): (can_reenter_corpse, special, penalize)
@@ -185,10 +187,10 @@
#define SPEECH_MESSAGE 1
// #define SPEECH_BUBBLE_TYPE 2
#define SPEECH_SPANS 3
/* #define SPEECH_SANITIZE 4
// #define SPEECH_SANITIZE 4
#define SPEECH_LANGUAGE 5
#define SPEECH_IGNORE_SPAM 6
#define SPEECH_FORCED 7 */
// #define SPEECH_IGNORE_SPAM 6
// #define SPEECH_FORCED 7
// /mob/living signals
#define COMSIG_LIVING_FULLY_HEAL "living_fully_healed" //from base of /mob/living/fully_heal(): (admin_revive)
+1
View File
@@ -5,6 +5,7 @@
#define NO_ASSASSIN (1<<0)
#define WAROPS_ALWAYS_ALLOWED (1<<1)
#define USE_PREF_WEIGHTS (1<<2)
#define ONLY_RULESET (1<<0)
#define HIGHLANDER_RULESET (1<<1)
+6 -5
View File
@@ -56,11 +56,12 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
//Movement Types
#define GROUND (1<<0)
#define FLYING (1<<1)
#define VENTCRAWLING (1<<2)
#define FLOATING (1<<3)
#define UNSTOPPABLE (1<<4) //When moving, will Bump()/Cross()/Uncross() everything, but won't be stopped.
#define GROUND (1<<0)
#define FLYING (1<<1)
#define VENTCRAWLING (1<<2)
#define FLOATING (1<<3)
#define UNSTOPPABLE (1<<4) //When moving, will Bump()/Cross()/Uncross() everything, but won't be stopped.
#define CRAWLING (1<<5) //Applied if you're crawling around on the ground/resting.
//Fire and Acid stuff, for resistance_flags
#define LAVA_PROOF (1<<0)
+2
View File
@@ -20,3 +20,5 @@
#define INTERACT_MACHINE_SET_MACHINE (1<<6) //MACHINES HAVE THIS BY DEFAULT, SOMEONE SHOULD RUN THROUGH MACHINES AND REMOVE IT FROM THINGS LIKE LIGHT SWITCHES WHEN POSSIBLE!!--------------------------
//This flag determines if a machine set_machine's the user when the user uses it, making updateUsrDialog make the user re-call interact() on it.
//THIS FLAG IS ON ALL MACHINES BY DEFAULT, NEEDS TO BE RE-EVALUATED LATER!!
#define INTERACT_GHOST_READ (1<<0)
+3 -1
View File
@@ -199,4 +199,6 @@
#define LORENTZ_CUMULATIVE_DISTRIBUTION(x, y, s) ( (1/PI)*TORADIANS(arctan((x-y)/s)) + 1/2 )
#define RULE_OF_THREE(a, b, x) ((a*x)/b)
// )
// )
#define MANHATTAN_DISTANCE(a, b) (abs(a.x - b.x) + abs(a.y - b.y))
+2
View File
@@ -40,6 +40,8 @@
#define ADD_REAGENT 2 // reagent added
#define REM_REAGENT 3 // reagent removed (may still exist)
#define THRESHOLD_UNHUSK 50 // health threshold for synthflesh/rezadone to unhusk someone
//reagent bitflags, used for altering how they works
#define REAGENT_DEAD_PROCESS (1<<0) //calls on_mob_dead() if present in a dead body
#define REAGENT_DONOTSPLIT (1<<1) //Do not split the chem at all during processing
+1
View File
@@ -38,6 +38,7 @@
#define ROLE_BLOODSUCKER "bloodsucker"
//#define ROLE_MONSTERHUNTER "monster hunter" Disabled for now
#define ROLE_GHOSTCAFE "ghostcafe"
#define ROLE_MINOR_ANTAG "minorantag"
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
//(in game days played) to play that role
+5
View File
@@ -11,3 +11,8 @@
#define SHOULD_CALL_PARENT(X)
#define UNLINT(X) X
#endif
/world/proc/enable_debugger()
var/dll = world.GetConfig("env", "EXTOOLS_DLL")
if (dll)
call(dll, "debug_initialize")()
+3 -1
View File
@@ -46,7 +46,9 @@
#define STATUS_EFFECT_SLEEPING /datum/status_effect/incapacitating/sleeping //the affected is asleep
#define STATUS_EFFECT_TASED /datum/status_effect/no_combat_mode/electrode/ //the affected has been tased, preventing fine muscle control
#define STATUS_EFFECT_TASED_WEAK /datum/status_effect/electrode //not as crippling, just slows down
#define STATUS_EFFECT_TASED /datum/status_effect/electrode/no_combat_mode //the affected has been tased, preventing fine muscle control
#define STATUS_EFFECT_PACIFY /datum/status_effect/pacify //the affected is pacified, preventing direct hostile actions
+2 -1
View File
@@ -110,6 +110,7 @@
#define TRAIT_NOHARDCRIT "nohardcrit"
#define TRAIT_NOSOFTCRIT "nosoftcrit"
#define TRAIT_MINDSHIELD "mindshield"
#define TRAIT_HIJACKER "hijacker"
#define TRAIT_SIXTHSENSE "sixthsense"
#define TRAIT_DISSECTED "dissected"
#define TRAIT_FEARLESS "fearless"
@@ -233,9 +234,9 @@
#define SLEEPING_CARP_TRAIT "sleeping_carp"
#define RISING_BASS_TRAIT "rising_bass"
#define ABDUCTOR_ANTAGONIST "abductor-antagonist"
#define NUKEOP_ANTAGONIST "nukeop-antagonist"
#define MADE_UNCLONEABLE "made-uncloneable"
#define TIMESTOP_TRAIT "timestop"
#define NUKEOP_TRAIT "nuke-op"
#define CLOWNOP_TRAIT "clown-op"
#define MEGAFAUNA_TRAIT "megafauna"
#define DEATHSQUAD_TRAIT "deathsquad"
+12 -1
View File
@@ -1,6 +1,17 @@
#define PLURALITY_VOTING 0
#define APPROVAL_VOTING 1
#define RANKED_CHOICE_VOTING 2
#define SCHULZE_VOTING 2
#define SCORE_VOTING 3
#define MAJORITY_JUDGEMENT_VOTING 4
#define INSTANT_RUNOFF_VOTING 5
GLOBAL_LIST_INIT(vote_score_options,list("Bad","Poor","Acceptable","Good","Great"))
GLOBAL_LIST_INIT(vote_type_names,list(\
"Plurality (default)" = PLURALITY_VOTING,\
"Approval" = APPROVAL_VOTING,\
"IRV (single winner ranked choice)" = INSTANT_RUNOFF_VOTING,\
"Schulze (ranked choice, higher result=better)" = SCHULZE_VOTING,\
"Raw Score (returns results from 0 to 1, winner is 1)" = SCORE_VOTING,\
"Majority Judgement (single-winner score voting)" = MAJORITY_JUDGEMENT_VOTING,\
))
-3
View File
@@ -179,7 +179,6 @@
"balls_cum_rate" = CUM_RATE,
"balls_cum_mult" = CUM_RATE_MULT,
"balls_efficiency" = CUM_EFFICIENCY,
"balls_fluid" = "semen",
"has_ovi" = FALSE,
"ovi_shape" = "knotted",
"ovi_length" = 6,
@@ -194,7 +193,6 @@
"breasts_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),
"breasts_size" = pick(GLOB.breasts_size_list),
"breasts_shape" = "Pair",
"breasts_fluid" = "milk",
"breasts_producing" = FALSE,
"has_vag" = FALSE,
"vag_shape" = pick(GLOB.vagina_shapes_list),
@@ -206,7 +204,6 @@
"womb_cum_rate" = CUM_RATE,
"womb_cum_mult" = CUM_RATE_MULT,
"womb_efficiency" = CUM_EFFICIENCY,
"womb_fluid" = "femcum",
"ipc_screen" = "Sunburst",
"ipc_antenna" = "None",
"flavor_text" = "",
+20 -7
View File
@@ -3,6 +3,9 @@
#define POPCOUNT_SHUTTLE_ESCAPEES "shuttle_escapees" //Emergency shuttle only.
/datum/controller/subsystem/ticker/proc/gather_roundend_feedback()
var/datum/station_state/end_state = new /datum/station_state()
end_state.count()
station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
gather_antag_data()
record_nuke_disk_location()
var/json_file = file("[GLOB.log_directory]/round_end_data.json")
@@ -71,9 +74,6 @@
mob_data += list("name" = m.name, "typepath" = m.type)
var/pos = length(file_data["[escaped]"]["[category]"]) + 1
file_data["[escaped]"]["[category]"]["[pos]"] = mob_data
var/datum/station_state/end_state = new /datum/station_state()
end_state.count()
var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
file_data["additional data"]["station integrity"] = station_integrity
WRITE_FILE(json_file, json_encode(file_data))
SSblackbox.record_feedback("nested tally", "round_end_stats", num_survivors, list("survivors", "total"))
@@ -111,7 +111,14 @@
if(A.objectives.len)
for(var/datum/objective/O in A.objectives)
var/result = O.check_completion() ? "SUCCESS" : "FAIL"
var/result = "UNKNOWN"
var/actual_result = O.check_completion()
if(actual_result >= 1)
result = "SUCCESS"
else if(actual_result <= 0)
result = "FAIL"
else
result = "[actual_result*100]%"
antag_info["objectives"] += list(list("objective_type"=O.type,"text"=O.explanation_text,"result"=result))
SSblackbox.record_feedback("associative", "antagonists", 1, antag_info)
@@ -550,10 +557,16 @@
var/list/objective_parts = list()
var/count = 1
for(var/datum/objective/objective in objectives)
if(objective.check_completion())
objective_parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='greentext'>Success!</span>"
if(objective.completable)
var/completion = objective.check_completion()
if(completion >= 1)
objective_parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
else if(completion <= 0)
objective_parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
else
objective_parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
else
objective_parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
objective_parts += "<B>Objective #[count]</B>: [objective.explanation_text]"
count++
return objective_parts.Join("<br>")
+7 -1
View File
@@ -44,6 +44,12 @@
index = findtext(t, char, index + length(char))
return t
/proc/sanitize_name(t,list/repl_chars = null)
if(t == "space" || t == "floor" || t == "wall" || t == "r-wall" || t == "monkey" || t == "unknown" || t == "inactive ai") //prevents these common metagamey names
alert("Invalid name.")
return ""
return sanitize(t)
/proc/sanitize_filename(t)
return sanitize_simple(t, list("\n"="", "\t"="", "/"="", "\\"="", "?"="", "%"="", "*"="", ":"="", "|"="", "\""="", "<"="", ">"=""))
@@ -775,4 +781,4 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
#define is_alpha(X) ((text2ascii(X) <= 122) && (text2ascii(X) >= 97))
#define is_digit(X) ((length(X) == 1) && (length(text2num(X)) == 1))
#define is_digit(X) ((length(X) == 1) && (length(text2num(X)) == 1))
+6 -1
View File
@@ -1537,4 +1537,9 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
if(190)
return "."
if(189)
return "-"
return "-"
/proc/generate_items_inside(list/items_list, where_to)
for(var/each_item in items_list)
for(var/i in 1 to items_list[each_item])
new each_item(where_to)
+57
View File
@@ -0,0 +1,57 @@
// Basic geometry things.
/datum/vector/
var/x = 0
var/y = 0
/datum/vector/New(var/x, var/y)
src.x = x
src.y = y
/datum/vector/proc/duplicate()
return new /datum/vector(x, y)
/datum/vector/proc/euclidian_norm()
return sqrt(x*x + y*y)
/datum/vector/proc/squared_norm()
return x*x + y*y
/datum/vector/proc/normalize()
var/norm = euclidian_norm()
x = x/norm
y = y/norm
return src
/datum/vector/proc/chebyshev_norm()
return max(abs(x), abs(y))
/datum/vector/proc/chebyshev_normalize()
var/norm = chebyshev_norm()
x = x/norm
y = y/norm
return src
/datum/vector/proc/is_integer()
return ISINTEGER(x) && ISINTEGER(y)
/atom/movable/proc/vector_translate(var/datum/vector/V, var/delay)
var/turf/T = get_turf(src)
var/turf/destination = locate(T.x + V.x, T.y + V.y, z)
var/datum/vector/V_norm = V.duplicate()
V_norm.chebyshev_normalize()
if (!V_norm.is_integer())
return
var/turf/destination_temp
while (destination_temp != destination)
destination_temp = locate(T.x + V_norm.x, T.y + V_norm.y, z)
forceMove(destination_temp)
T = get_turf(src)
sleep(delay + world.tick_lag) // Shortest possible time to sleep
/atom/proc/get_translated_turf(var/datum/vector/V)
var/turf/T = get_turf(src)
return locate(T.x + V.x, T.y + V.y, z)
/proc/atoms2vector(var/atom/A, var/atom/B)
return new /datum/vector((B.x - A.x), (B.y - A.y)) // Vector from A -> B
+4 -2
View File
@@ -319,9 +319,11 @@
/mob/proc/ShiftClickOn(atom/A)
A.ShiftClick(src)
return
/atom/proc/ShiftClick(mob/user)
SEND_SIGNAL(src, COMSIG_CLICK_SHIFT, user)
user.examinate(src)
var/flags = SEND_SIGNAL(src, COMSIG_CLICK_SHIFT, user)
if(!(flags & COMPONENT_DENY_EXAMINATE) && user.client && (user.client.eye == user || user.client.eye == user.loc || flags & COMPONENT_ALLOW_EXAMINATE))
user.examinate(src)
return
/*
@@ -364,6 +364,29 @@
runnable_modes[M] = final_weight
return runnable_modes
/datum/controller/configuration/proc/get_runnable_storytellers()
var/list/datum/dynamic_storyteller/runnable_storytellers = new
var/list/probabilities = Get(/datum/config_entry/keyed_list/storyteller_weight)
var/list/repeated_mode_adjust = Get(/datum/config_entry/number_list/repeated_mode_adjust)
for(var/T in storyteller_cache)
var/datum/dynamic_storyteller/S = T
var/config_tag = initial(S.config_tag)
var/final_weight = initial(S.weight)
if(probabilities[config_tag]<=0)
continue
final_weight = probabilities[config_tag]
if(SSpersistence.saved_storytellers.len == 3 && repeated_mode_adjust.len == 3)
var/name = initial(S.name)
var/recent_round = min(SSpersistence.saved_storytellers.Find(name),3)
var/adjustment = 0
while(recent_round)
adjustment += repeated_mode_adjust[recent_round]
recent_round = SSpersistence.saved_modes.Find(name,recent_round+1,0)
final_weight *= ((100-adjustment)/100)
runnable_storytellers[S] = final_weight
return runnable_storytellers
/datum/controller/configuration/proc/get_runnable_midround_modes(crew)
var/list/datum/game_mode/runnable_modes = new
var/list/probabilities = Get(/datum/config_entry/keyed_list/probability)
@@ -88,3 +88,7 @@
/datum/config_entry/number/dynamic_warops_cost
config_entry_value = 10
min_val = 0
/datum/config_entry/keyed_list/storyteller_weight
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
@@ -267,6 +267,9 @@
/datum/config_entry/flag/tgstyle_maprotation
/datum/config_entry/string/map_vote_type
config_entry_value = "SCORE"
/datum/config_entry/number/maprotatechancedelta
config_entry_value = 0.75
min_val = 0
@@ -0,0 +1,6 @@
/datum/config_entry/number/snowflake_plushie_prob
config_entry_value = 50
/datum/config_entry/keyed_list/snowflake_plushies
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_TEXT
+12 -9
View File
@@ -31,15 +31,18 @@ SUBSYSTEM_DEF(fail2topic)
return ..()
/datum/controller/subsystem/fail2topic/fire()
for(var/i in 1 to length(rate_limiting))
var/ip = rate_limiting[i]
var/last_attempt = rate_limiting[ip]
if (world.time - last_attempt > rate_limit)
rate_limiting -= ip
fail_counts -= ip
if (MC_TICK_CHECK)
return
if(length(rate_limiting))
var/i = 1
while(i <= length(rate_limiting))
var/ip = rate_limiting[i]
var/last_attempt = rate_limiting[ip]
if(world.time - last_attempt > rate_limit)
rate_limiting -= ip
fail_counts -= ip
else //if we remove that, and the next element is in its place. check that instead of incrementing.
++i
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/fail2topic/Shutdown()
DropFirewallRule()
+5 -5
View File
@@ -13,7 +13,7 @@ SUBSYSTEM_DEF(persistence)
var/list/saved_messages = list()
var/list/saved_modes = list(1,2,3)
var/list/saved_dynamic_rules = list(list(),list(),list())
var/list/saved_storytellers = list("foo","bar","baz","foo again","bar again")
var/list/saved_storytellers = list("foo","bar","baz")
var/list/saved_maps
var/list/saved_trophies = list()
var/list/spawned_objects = list()
@@ -191,6 +191,7 @@ SUBSYSTEM_DEF(persistence)
if(!json)
return
saved_storytellers = json["data"]
saved_storytellers.len = 3
/datum/controller/subsystem/persistence/proc/LoadRecentMaps()
var/json_file = file("data/RecentMaps.json")
@@ -265,7 +266,8 @@ SUBSYSTEM_DEF(persistence)
/datum/controller/subsystem/persistence/proc/LoadPanicBunker()
var/bunker_path = file("data/bunker_passthrough.json")
if(fexists(bunker_path))
GLOB.bunker_passthrough = json_decode(file2text(bunker_path))
var/list/json = json_decode(file2text(bunker_path))
GLOB.bunker_passthrough = json["data"]
for(var/ckey in GLOB.bunker_passthrough)
if(daysSince(GLOB.bunker_passthrough[ckey]) >= CONFIG_GET(number/max_bunker_days))
GLOB.bunker_passthrough -= ckey
@@ -428,9 +430,7 @@ SUBSYSTEM_DEF(persistence)
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/CollectStoryteller(var/datum/game_mode/dynamic/mode)
saved_storytellers.len = 5
saved_storytellers[5] = saved_storytellers[4]
saved_storytellers[4] = saved_storytellers[3]
saved_storytellers.len = 3
saved_storytellers[3] = saved_storytellers[2]
saved_storytellers[2] = saved_storytellers[1]
saved_storytellers[1] = mode.storyteller.name
@@ -35,7 +35,7 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
var/list/my_quirks = cli.prefs.all_quirks.Copy()
var/list/cut
if(job?.blacklisted_quirks)
cut = filter_quirks(my_quirks, job)
cut = filter_quirks(my_quirks, job.blacklisted_quirks)
for(var/V in my_quirks)
var/datum/quirk/Q = quirks[V]
if(Q)
@@ -63,11 +63,11 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
for(var/i in quirk_names)
. += quirk_points_by_name(i)
/datum/controller/subsystem/processing/quirks/proc/filter_quirks(list/our_quirks, datum/job/job)
/datum/controller/subsystem/processing/quirks/proc/filter_quirks(list/our_quirks, list/blacklisted_quirks)
var/list/cut = list()
var/list/banned_names = list()
var/pointscut = 0
for(var/i in job.blacklisted_quirks)
for(var/i in blacklisted_quirks)
var/name = quirk_name_by_path(i)
if(name)
banned_names += name
+15 -2
View File
@@ -68,6 +68,8 @@ SUBSYSTEM_DEF(ticker)
var/modevoted = FALSE //Have we sent a vote for the gamemode?
var/station_integrity = 100 // stored at roundend for use in some antag goals
/datum/controller/subsystem/ticker/Initialize(timeofday)
load_mode()
@@ -363,7 +365,7 @@ SUBSYSTEM_DEF(ticker)
var/turf/epi = bomb.loc
qdel(bomb)
if(epi)
explosion(epi, 0, 256, 512, 0, TRUE, TRUE, 0, TRUE)
explosion(epi, 512, 0, 0, 0, TRUE, TRUE, 0, TRUE)
/datum/controller/subsystem/ticker/proc/create_characters()
for(var/mob/dead/new_player/player in GLOB.player_list)
@@ -475,7 +477,18 @@ SUBSYSTEM_DEF(ticker)
if(CONFIG_GET(flag/tgstyle_maprotation))
INVOKE_ASYNC(SSmapping, /datum/controller/subsystem/mapping/.proc/maprotate)
else
SSvote.initiate_vote("map","server",TRUE)
var/vote_type = CONFIG_GET(string/map_vote_type)
switch(vote_type)
if("PLURALITY")
SSvote.initiate_vote("map","server",hideresults=TRUE)
if("APPROVAL")
SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = APPROVAL_VOTING)
if("IRV")
SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = INSTANT_RUNOFF_VOTING)
if("SCORE")
SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = MAJORITY_JUDGEMENT_VOTING)
// fallback
SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = MAJORITY_JUDGEMENT_VOTING)
/datum/controller/subsystem/ticker/proc/HasRoundStarted()
return current_state >= GAME_STATE_PLAYING
+93 -62
View File
@@ -188,22 +188,47 @@ SUBSYSTEM_DEF(vote)
choices[score_name]++
/datum/controller/subsystem/vote/proc/calculate_scores(var/blackbox_text)
var/list/scores_by_choice = list()
for(var/choice in choices)
scores_by_choice += "[choice]"
scores_by_choice["[choice]"] = list()
scores += "[choice]"
scores["[choice]"] = 0
for(var/ckey in voted)
var/list/this_vote = voted[ckey]
for(var/choice in choices)
if("[choice]" in this_vote && "[choice]" in scores_by_choice)
sorted_insert(scores_by_choice["[choice]"],this_vote["[choice]"],/proc/cmp_numeric_asc)
var/middle_score = round(GLOB.vote_score_options.len/2,1)
for(var/score_name in scores_by_choice)
var/list/score = scores_by_choice[score_name]
for(var/S in score)
scores[score_name] += S-middle_score
for(var/choice in this_vote)
scores["[choice]"] += this_vote["[choice]"]
var/min_score = 100
var/max_score = -100
for(var/score_name in scores) // normalize the scores from 0-1
max_score=max(max_score,scores[score_name])
min_score=min(min_score,scores[score_name])
for(var/score_name in scores)
if(max_score == min_score)
scores[score_name] = 1
else
scores[score_name] = (scores[score_name]-min_score)/(max_score-min_score)
SSblackbox.record_feedback("nested tally","voting",scores[score_name],list(blackbox_text,"Total scores",score_name))
/datum/controller/subsystem/vote/proc/get_runoff_results(var/blackbox_text)
var/already_lost_runoff = list()
var/list/cur_choices = choices.Copy()
for(var/ckey in voted)
choices[choices[voted[ckey][1]]]++ // jesus christ how horrifying
for(var/_this_var_unused_ignore_it in 1 to choices.len) // if it takes more than this something REALLY wrong happened
for(var/ckey in voted)
cur_choices[cur_choices[voted[ckey][1]]]++ // jesus christ how horrifying
var/least_vote = 100000
var/least_voted
for(var/i in 1 to cur_choices.len)
var/option = cur_choices[i]
if(cur_choices[option] > voted.len/2)
return list(option)
else if(cur_choices[option] < least_vote && !(option in already_lost_runoff))
least_vote = cur_choices[option]
least_voted = i
already_lost_runoff += cur_choices[least_voted]
for(var/ckey in voted)
voted[ckey] -= least_voted
for(var/option in cur_choices)
cur_choices[option] = 0
/datum/controller/subsystem/vote/proc/announce_result()
var/vote_title_text
@@ -214,32 +239,29 @@ SUBSYSTEM_DEF(vote)
else
text += "<b>[capitalize(mode)] Vote</b>"
vote_title_text = "[capitalize(mode)] Vote"
if(vote_system == RANKED_CHOICE_VOTING)
if(vote_system == SCHULZE_VOTING)
calculate_condorcet_votes(vote_title_text)
if(vote_system == SCORE_VOTING)
calculate_majority_judgement_vote(vote_title_text)
calculate_scores(vote_title_text)
var/list/winners = get_result()
if(vote_system == MAJORITY_JUDGEMENT_VOTING)
calculate_majority_judgement_vote(vote_title_text) // nothing uses this at the moment
var/list/winners = vote_system == INSTANT_RUNOFF_VOTING ? get_runoff_results() : get_result()
var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic"
if(winners.len > 0)
if(was_roundtype_vote)
stored_gamemode_votes = list()
if(!obfuscated && vote_system == RANKED_CHOICE_VOTING)
text += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!"
if(mode == "mode tiers")
for(var/score_name in scores)
var/score = scores[score_name]
if(!score)
score = 0
text = "\n<b>[score_name]:</b> [obfuscated ? "???" : score]"
else
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
if(!votes)
votes = 0
if(was_roundtype_vote)
stored_gamemode_votes[choices[i]] = votes
text += "\n<b>[choices[i]]:</b> [obfuscated ? "???" : votes]" //CIT CHANGE - adds obfuscated votes
if(!obfuscated)
if(vote_system == SCHULZE_VOTING)
text += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!"
if(vote_system == MAJORITY_JUDGEMENT_VOTING)
text += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!"
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
if(!votes)
votes = 0
if(was_roundtype_vote)
stored_gamemode_votes[choices[i]] = votes
text += "\n<b>[choices[i]]:</b> [obfuscated ? "???" : votes]" //CIT CHANGE - adds obfuscated votes
if(mode != "custom")
if(winners.len > 1 && !obfuscated) //CIT CHANGE - adds obfuscated votes
text = "\n<b>Vote Tied Between:</b>"
@@ -249,6 +271,15 @@ SUBSYSTEM_DEF(vote)
text += "\n<b>Vote Result: [obfuscated ? "???" : .]</b>" //CIT CHANGE - adds obfuscated votes
else
text += "\n<b>Did not vote:</b> [GLOB.clients.len-voted.len]"
else if(vote_system == SCORE_VOTING)
for(var/score_name in scores)
var/score = scores[score_name]
if(!score)
score = 0
if(was_roundtype_vote)
stored_gamemode_votes[score_name] = score
text = "\n<b>[score_name]:</b> [obfuscated ? "???" : score]"
. = 1
else
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
log_vote(text)
@@ -258,7 +289,7 @@ SUBSYSTEM_DEF(vote)
if(APPROVAL_VOTING,PLURALITY_VOTING)
for(var/i=1,i<=choices.len,i++)
SSblackbox.record_feedback("nested tally","voting",choices[choices[i]],list(vote_title_text,choices[i]))
if(RANKED_CHOICE_VOTING)
if(SCHULZE_VOTING,INSTANT_RUNOFF_VOTING)
for(var/i=1,i<=voted.len,i++)
var/list/myvote = voted[voted[i]]
if(islist(myvote))
@@ -266,13 +297,18 @@ SUBSYSTEM_DEF(vote)
SSblackbox.record_feedback("nested tally","voting",1,list(vote_title_text,"[j]\th",choices[myvote[j]]))
if(obfuscated) //CIT CHANGE - adds obfuscated votes. this messages admins with the vote's true results
var/admintext = "Obfuscated results"
if(vote_system == RANKED_CHOICE_VOTING)
admintext += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!"
else if(vote_system == SCORE_VOTING)
admintext += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!"
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
admintext += "\n<b>[choices[i]]:</b> [votes]"
if(vote_system != SCORE_VOTING)
if(vote_system == SCHULZE_VOTING)
admintext += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!"
else if(vote_system == MAJORITY_JUDGEMENT_VOTING)
admintext += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!"
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
admintext += "\n<b>[choices[i]]:</b> [votes]"
else
for(var/i=1,i<=scores.len,i++)
var/score = scores[scores[i]]
admintext += "\n<b>[scores[i]]:</b> [score]"
message_admins(admintext)
return .
@@ -316,15 +352,13 @@ SUBSYSTEM_DEF(vote)
if("dynamic")
if(SSticker.current_state > GAME_STATE_PREGAME)//Don't change the mode if the round already started.
return message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.")
if(. == "Secret")
GLOB.master_mode = "secret"
SSticker.save_mode(.)
message_admins("The gamemode has been voted for, and has been changed to: [GLOB.master_mode]")
log_admin("Gamemode has been voted for and switched to: [GLOB.master_mode].")
else
GLOB.master_mode = "dynamic"
var/datum/dynamic_storyteller/S = config.pick_storyteller(.)
GLOB.dynamic_storyteller_type = S
GLOB.master_mode = "dynamic"
var/list/runnable_storytellers = config.get_runnable_storytellers()
for(var/T in runnable_storytellers)
var/datum/dynamic_storyteller/S = T
runnable_storytellers[S] *= scores[initial(S.name)]
var/datum/dynamic_storyteller/S = pickweightAllowZero(runnable_storytellers)
GLOB.dynamic_storyteller_type = S
if("map")
var/datum/map_config/VM = config.maplist[.]
message_admins("The map has been voted for and will change to: [VM.map_name]")
@@ -375,7 +409,7 @@ SUBSYSTEM_DEF(vote)
voted[usr.ckey] = list(vote)
choices[choices[vote]]++
return vote
if(RANKED_CHOICE_VOTING)
if(SCHULZE_VOTING,INSTANT_RUNOFF_VOTING)
if(usr.ckey in voted)
if(vote in voted[usr.ckey])
voted[usr.ckey] -= vote
@@ -384,7 +418,7 @@ SUBSYSTEM_DEF(vote)
voted[usr.ckey] = list()
voted[usr.ckey] += vote
saved -= usr.ckey
if(SCORE_VOTING)
if(SCORE_VOTING,MAJORITY_JUDGEMENT_VOTING)
if(!(usr.ckey in voted))
voted += usr.ckey
voted[usr.ckey] = list()
@@ -444,19 +478,16 @@ SUBSYSTEM_DEF(vote)
if("dynamic")
for(var/T in config.storyteller_cache)
var/datum/dynamic_storyteller/S = T
var/recent_rounds = 0
for(var/i in 1 to SSpersistence.saved_storytellers.len)
if(SSpersistence.saved_storytellers[i] == initial(S.name))
recent_rounds++
if(recent_rounds < initial(S.weight))
var/list/probabilities = CONFIG_GET(keyed_list/storyteller_weight)
if(probabilities[initial(S.config_tag)] > 0)
choices.Add(initial(S.name))
choice_descs.Add(initial(S.desc))
choices.Add("Secret")
choice_descs.Add("Standard secret. Switches mode if it wins.")
if("custom")
question = stripped_input(usr,"What is the vote for?")
if(!question)
return 0
var/system_string = input(usr,"Which voting type?",GLOB.vote_type_names[1]) in GLOB.vote_type_names
vote_system = GLOB.vote_type_names[system_string]
for(var/i=1,i<=10,i++)
var/option = capitalize(stripped_input(usr,"Please enter an option or hit cancel to finish"))
if(!option || mode || !usr.client)
@@ -514,9 +545,9 @@ SUBSYSTEM_DEF(vote)
. += "<h3>Vote one.</h3>"
if(APPROVAL_VOTING)
. += "<h3>Vote any number of choices.</h3>"
if(RANKED_CHOICE_VOTING)
if(SCHULZE_VOTING,INSTANT_RUNOFF_VOTING)
. += "<h3>Vote by order of preference. Revoting will demote to the bottom. 1 is your favorite, and higher numbers are worse.</h3>"
if(SCORE_VOTING)
if(SCORE_VOTING,MAJORITY_JUDGEMENT_VOTING)
. += "<h3>Grade the candidates by how much you like them.</h3>"
. += "<h3>No-votes have no power--your opinion is only heard if you vote!</h3>"
. += "Time Left: [DisplayTimeText(end_time-world.time)]<hr><ul>"
@@ -536,7 +567,7 @@ SUBSYSTEM_DEF(vote)
if(choice_descs.len >= i)
. += "<li>[choice_descs[i]]</li>"
. += "</ul><hr>"
if(RANKED_CHOICE_VOTING)
if(SCHULZE_VOTING,INSTANT_RUNOFF_VOTING)
var/list/myvote = voted[C.ckey]
for(var/i=1,i<=choices.len,i++)
var/vote = (islist(myvote) ? (myvote.Find(i)) : 0)
@@ -553,7 +584,7 @@ SUBSYSTEM_DEF(vote)
. += "(Saved!)"
. += "(<a href='?src=[REF(src)];vote=load'>Load vote from save</a>)"
. += "(<a href='?src=[REF(src)];vote=reset'>Reset votes</a>)"
if(SCORE_VOTING)
if(SCORE_VOTING,MAJORITY_JUDGEMENT_VOTING)
var/list/myvote = voted[C.ckey]
for(var/i=1,i<=choices.len,i++)
. += "<li><b>[choices[i]]</b>"
@@ -656,7 +687,7 @@ SUBSYSTEM_DEF(vote)
voted[usr.ckey] = SSpersistence.saved_votes[usr.ckey][mode]
if(islist(voted[usr.ckey]))
var/malformed = FALSE
if(vote_system == SCORE_VOTING)
if(vote_system == SCORE_VOTING || vote_system == MAJORITY_JUDGEMENT_VOTING)
for(var/thing in voted[usr.ckey])
if(!(thing in choices))
malformed = TRUE
@@ -670,7 +701,7 @@ SUBSYSTEM_DEF(vote)
to_chat(usr,"Your saved vote was malformed! Start over!")
voted -= usr.ckey
else
if(vote_system == SCORE_VOTING)
if(vote_system == SCORE_VOTING || vote_system == MAJORITY_JUDGEMENT_VOTING)
submit_vote(round(text2num(href_list["vote"])),round(text2num(href_list["score"])))
else
submit_vote(round(text2num(href_list["vote"])))
+72
View File
@@ -544,6 +544,70 @@
cooldown = world.time
owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE)
/datum/action/item_action/removeAPCs
name = "Relinquish APC"
desc = "Let go of an APC, relinquish control back to the station."
icon_icon = 'icons/obj/implants.dmi'
button_icon_state = "hijackx"
/datum/action/item_action/removeAPCs/Trigger()
var/list/areas = list()
for (var/area/a in owner.siliconaccessareas)
areas[a.name] = a
var/removeAPC = input("Select an APC to remove:","Remove APC Control",1) as null|anything in areas
if (!removeAPC)
return
var/area/area = areas[removeAPC]
var/obj/machinery/power/apc/apc = area.get_apc()
if (!apc || !(area in owner.siliconaccessareas))
return
apc.hijacker = null
apc.update_icon()
apc.set_hijacked_lighting()
owner.toggleSiliconAccessArea(area)
/datum/action/item_action/accessAPCs
name = "Access APC Interface"
desc = "Open the APC's interface."
icon_icon = 'icons/obj/implants.dmi'
button_icon_state = "hijacky"
/datum/action/item_action/accessAPCs/Trigger()
var/list/areas = list()
for (var/area/a in owner.siliconaccessareas)
areas[a.name] = a
var/accessAPC = input("Select an APC to access:","Access APC Interface",1) as null|anything in areas
if (!accessAPC)
return
var/area/area = areas[accessAPC]
var/obj/machinery/power/apc/apc = area.get_apc()
if (!apc || !(area in owner.siliconaccessareas))
return
apc.ui_interact(owner)
/datum/action/item_action/stealthmodetoggle
name = "Toggle Stealth Mode"
desc = "Toggles the stealth mode on the hijack implant."
icon_icon = 'icons/obj/implants.dmi'
button_icon_state = "hijackz"
/datum/action/item_action/stealthmodetoggle/Trigger()
var/obj/item/implant/hijack/H = target
if (!istype(H))
return
if (H.stealthcooldown > world.time)
to_chat(owner,"<span class='warning'>The hijack implant's stealth mode toggle is still rebooting!</span>")
return
H.stealthmode = !H.stealthmode
for (var/area/area in H.imp_in.siliconaccessareas)
var/obj/machinery/power/apc/apc = area.get_apc()
if (apc)
apc.set_hijacked_lighting()
apc.update_icon()
H.stealthcooldown = world.time + 15 SECONDS
H.toggle_eyes()
to_chat(owner,"<span class='notice'>You toggle the hijack implant's stealthmode [H.stealthmode ? "on" : "off"].</span>")
/datum/action/item_action/flash
name = "Flash"
@@ -756,3 +820,11 @@
target.layer = old_layer
target.plane = old_plane
current_button.appearance_cache = target.appearance
/proc/get_action_of_type(mob/M, var/action_type)
if(!M.actions || !ispath(action_type, /datum/action))
return
for(var/datum/action/A in M.actions)
if(istype(A, action_type))
return A
return
@@ -1,10 +1,3 @@
/datum/crafting_recipe/bonearmor
name = "Bone Armor"
result = /obj/item/clothing/suit/armor/bone
time = 30
reqs = list(/obj/item/stack/sheet/bone = 6)
category = CAT_PRIMAL
/datum/crafting_recipe/bonetalisman
name = "Bone Talisman"
result = /obj/item/clothing/accessory/talisman
@@ -29,13 +22,6 @@
/obj/item/stack/sheet/sinew = 1)
category = CAT_PRIMAL
/datum/crafting_recipe/skullhelm
name = "Skull Helmet"
result = /obj/item/clothing/head/helmet/skull
time = 30
reqs = list(/obj/item/stack/sheet/bone = 4)
category = CAT_PRIMAL
/datum/crafting_recipe/goliathcloak
name = "Goliath Cloak"
result = /obj/item/clothing/suit/hooded/cloak/goliath
@@ -62,13 +48,6 @@
/obj/item/stack/sheet/sinew = 2)
category = CAT_PRIMAL
/datum/crafting_recipe/bonedagger
name = "Bone Dagger"
result = /obj/item/kitchen/knife/combat/bone
time = 20
reqs = list(/obj/item/stack/sheet/bone = 2)
category = CAT_PRIMAL
/datum/crafting_recipe/bonespear
name = "Bone Spear"
result = /obj/item/twohanded/bonespear
@@ -56,7 +56,7 @@
/obj/item/scalpel, /obj/item/reagent_containers/syringe, /obj/item/dnainjector,
/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/dropper,
/obj/item/implanter, /obj/item/screwdriver, /obj/item/weldingtool/mini,
/obj/item/firing_pin, /obj/item/gun/ballistic/automatic/pistol
/obj/item/firing_pin, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/automatic/magrifle/pistol
))
/datum/component/storage/concrete/pockets/shoes/clown/Initialize()
+13
View File
@@ -26,6 +26,7 @@ GLOBAL_LIST_EMPTY(uplinks)
var/failsafe_code
var/datum/ui_state/checkstate
var/compact_mode = FALSE
var/debug = FALSE
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/ui_state/_checkstate)
if(!isitem(parent))
@@ -166,6 +167,18 @@ GLOBAL_LIST_EMPTY(uplinks)
"cost" = I.cost,
"desc" = I.desc,
))
if(I.restricted_roles.len)
var/is_inaccessible = 1
for(var/R in I.restricted_roles)
if(R == user.mind.assigned_role || debug)
is_inaccessible = 0
if(is_inaccessible)
continue
cat["items"] += list(list(
"name" = I.name,
"cost" = I.cost,
"desc" = I.desc,
))
data["categories"] += list(cat)
return data
@@ -448,9 +448,11 @@
symptom_delay_max = 1
passive_message = "<span class='notice'>Your skin glows faintly for a moment.</span>"
var/cellular_damage = FALSE
threshold_desc = "<b>Transmission 6:</b> Additionally heals cellular damage and toxin lovers.<br>\
<b>Resistance 7:</b> Increases healing speed."
threshold_desc = list(
"Transmission 6" = "Additionally heals cellular damage and toxin lovers.",
"Resistance 7" = "Increases healing speed.",
)
/datum/symptom/heal/radiation/Start(datum/disease/advance/A)
if(!..())
return
+184
View File
@@ -0,0 +1,184 @@
/datum/element/mob_holder
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
id_arg_index = 2
var/worn_state
var/alt_worn
var/right_hand
var/left_hand
var/inv_slots
var/proctype //if present, will be invoked on headwear generation.
/datum/element/mob_holder/Attach(datum/target, _worn_state, _alt_worn, _right_hand, _left_hand, _inv_slots = NONE, _proctype)
. = ..()
if(!isliving(target))
return ELEMENT_INCOMPATIBLE
worn_state = _worn_state
alt_worn = _alt_worn
right_hand = _right_hand
left_hand = _left_hand
inv_slots = _inv_slots
proctype = _proctype
RegisterSignal(target, COMSIG_CLICK_ALT, .proc/mob_try_pickup)
RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/on_examine)
/datum/element/mob_holder/Detach(datum/source, force)
. = ..()
UnregisterSignal(source, COMSIG_CLICK_ALT)
UnregisterSignal(source, COMSIG_PARENT_EXAMINE)
/datum/element/mob_holder/proc/on_examine(mob/living/source, mob/user, list/examine_list)
if(ishuman(user) && !istype(source.loc, /obj/item/clothing/head/mob_holder))
examine_list += "<span class='notice'>Looks like [source.p_they(TRUE)] can be picked up with <b>Alt+Click</b>!</span>"
/datum/element/mob_holder/proc/mob_try_pickup(mob/living/source, mob/user)
if(!ishuman(user) || !user.Adjacent(source) || user.incapacitated())
return FALSE
if(user.get_active_held_item())
to_chat(user, "<span class='warning'>Your hands are full!</span>")
return FALSE
if(source.buckled)
to_chat(user, "<span class='warning'>[src] is buckled to something!</span>")
return FALSE
if(source == user)
to_chat(user, "<span class='warning'>You can't pick yourself up.</span>")
return FALSE
source.visible_message("<span class='warning'>[user] starts picking up [source].</span>", \
"<span class='userdanger'>[user] starts picking you up!</span>")
if(!do_after(user, 20, target = source) || source.buckled)
return FALSE
source.visible_message("<span class='warning'>[user] picks up [source]!</span>", \
"<span class='userdanger'>[user] picks you up!</span>")
to_chat(user, "<span class='notice'>You pick [src] up.</span>")
source.drop_all_held_items()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(source), source, worn_state, alt_worn, right_hand, left_hand, inv_slots)
if(proctype)
INVOKE_ASYNC(src, proctype, source, holder, user)
user.put_in_hands(holder)
return TRUE
/datum/element/mob_holder/proc/drone_worn_icon(mob/living/simple_animal/drone/D, obj/item/clothing/head/mob_holder/holder, mob/user)
var/new_state = "[D.visualAppearence]_hat"
holder.item_state = new_state
holder.icon_state = new_state
//The item itself,
/obj/item/clothing/head/mob_holder
name = "bugged mob"
desc = "Yell at coderbrush."
icon = null
alternate_worn_icon = 'icons/mob/animals_held.dmi'
righthand_file = 'icons/mob/animals_held_rh.dmi'
lefthand_file = 'icons/mob/animals_held_lh.dmi'
icon_state = ""
w_class = WEIGHT_CLASS_BULKY
var/mob/living/held_mob
/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/target, worn_state, alt_worn, right_hand, left_hand, slots = NONE)
. = ..()
if(target)
assimilate(target)
if(alt_worn)
alternate_worn_icon = alt_worn
if(worn_state)
item_state = worn_state
icon_state = worn_state
if(left_hand)
lefthand_file = left_hand
if(right_hand)
righthand_file = right_hand
slot_flags = slots
/obj/item/clothing/head/mob_holder/proc/assimilate(mob/living/target)
target.setDir(SOUTH)
held_mob = target
target.forceMove(src)
var/image/I = new //work around to retain the same appearance to the mob idependently from inhands/worn states.
I.appearance = target.appearance
I.override = TRUE
add_overlay(I)
name = target.name
desc = target.desc
switch(target.mob_size)
if(MOB_SIZE_TINY)
w_class = WEIGHT_CLASS_TINY
if(MOB_SIZE_SMALL)
w_class = WEIGHT_CLASS_NORMAL
if(MOB_SIZE_LARGE)
w_class = WEIGHT_CLASS_HUGE
RegisterSignal(src, COMSIG_CLICK_SHIFT, .proc/examine_held_mob)
/obj/item/clothing/head/mob_holder/Destroy()
if(held_mob)
release()
return ..()
/obj/item/clothing/head/mob_holder/proc/examine_held_mob(datum/source, mob/user)
held_mob.ShiftClick(user)
return COMPONENT_DENY_EXAMINATE
/obj/item/clothing/head/mob_holder/Exited(atom/movable/AM, atom/newloc)
. = ..()
if(AM == held_mob)
held_mob.reset_perspective()
held_mob = null
qdel(src)
/obj/item/clothing/head/mob_holder/Entered(atom/movable/AM, atom/newloc)
. = ..()
if(AM != held_mob)
var/destination = loc
if(isliving(loc)) //the mob is held or worn, drop things on the floor
destination = get_turf(loc)
AM.forceMove(destination)
/obj/item/clothing/head/mob_holder/dropped()
. = ..()
if(held_mob && isturf(loc))//don't release on soft-drops
release()
/obj/item/clothing/head/mob_holder/proc/release()
if(held_mob)
var/mob/living/L = held_mob
held_mob = null
L.forceMove(get_turf(L))
L.reset_perspective()
L.setDir(SOUTH)
qdel(src)
/obj/item/clothing/head/mob_holder/relaymove(mob/user)
return
/obj/item/clothing/head/mob_holder/container_resist()
if(isliving(loc))
var/mob/living/L = loc
L.visible_message("<span class='warning'>[src] escapes from [L]!</span>", "<span class='warning'>[src] escapes your grip!</span>")
release()
/obj/item/clothing/head/mob_holder/assume_air(datum/gas_mixture/env)
var/atom/location = loc
if(!loc)
return //null
var/turf/T = get_turf(loc)
while(location != T)
location = location.loc
if(ismob(location))
return location.loc.assume_air(env)
return loc.assume_air(env)
/obj/item/clothing/head/mob_holder/remove_air(amount)
var/atom/location = loc
if(!loc)
return //null
var/turf/T = get_turf(loc)
while(location != T)
location = location.loc
if(ismob(location))
return location.loc.remove_air(amount)
return loc.remove_air(amount)
+5 -1
View File
@@ -1,6 +1,6 @@
/datum/element/wuv //D'awwwww
element_flags = ELEMENT_BESPOKE
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
id_arg_index = 2
//the for the me emote proc call when petted.
var/pet_emote
@@ -30,6 +30,10 @@
RegisterSignal(target, COMSIG_MOB_ATTACK_HAND, .proc/on_attack_hand)
/datum/element/wuv/Detach(datum/source, force)
. = ..()
UnregisterSignal(source, COMSIG_MOB_ATTACK_HAND)
/datum/element/wuv/proc/on_attack_hand(datum/source, mob/user)
var/mob/living/L = source
+1
View File
@@ -458,6 +458,7 @@
var/list/allowed_types = list(
/datum/objective/assassinate,
/datum/objective/assassinate/once,
/datum/objective/maroon,
/datum/objective/debrain,
/datum/objective/protect,
+41 -19
View File
@@ -33,7 +33,6 @@
if(owner.getStaminaLoss())
owner.adjustStaminaLoss(-0.3) //reduce stamina loss by 0.3 per tick, 6 per 2 seconds
//UNCONSCIOUS
/datum/status_effect/incapacitating/unconscious
id = "unconscious"
@@ -80,11 +79,11 @@
desc = "You've fallen asleep. Wait a bit and you should wake up. Unless you don't, considering how helpless you are."
icon_state = "asleep"
/datum/status_effect/no_combat_mode/
/datum/status_effect/no_combat_mode
id = "no_combat_mode"
blocks_combatmode = TRUE
alert_type = null
status_type = STATUS_EFFECT_REPLACE
blocks_combatmode = TRUE
/datum/status_effect/no_combat_mode/on_creation(mob/living/new_owner, set_duration)
if(isnum(set_duration))
@@ -113,31 +112,54 @@
icon = 'icons/mob/actions/bloodsucker.dmi'
icon_state = "power_mez"
/datum/status_effect/no_combat_mode/electrode
/datum/status_effect/electrode
id = "tased"
var/slowdown = 1.5
var/slowdown_priority = 50 //to make sure the stronger effect overrides
var/affect_crawl = FALSE
var/nextmove_modifier = 1
var/stamdmg_per_ds = 1 //a 20 duration would do 20 stamdmg, disablers do 24 or something
var/last_tick = 0 //fastprocess processing speed is a goddamn sham, don't trust it.
/datum/status_effect/no_combat_mode/electrode/on_creation(mob/living/new_owner, set_duration)
/datum/status_effect/electrode/on_creation(mob/living/new_owner, set_duration)
if(isnum(set_duration)) //TODO, figure out how to grab from subtype
duration = set_duration
. = ..()
last_tick = world.time
if(iscarbon(owner))
var/mob/living/carbon/C = owner
if(C.combatmode)
C.toggle_combat_mode(TRUE)
C.add_movespeed_modifier("[MOVESPEED_ID_TASED_STATUS]_[id]", TRUE, priority = slowdown_priority, override = TRUE, multiplicative_slowdown = slowdown, blacklisted_movetypes = affect_crawl? NONE : CRAWLING)
/datum/status_effect/electrode/on_remove()
if(iscarbon(owner))
var/mob/living/carbon/C = owner
C.remove_movespeed_modifier("[MOVESPEED_ID_TASED_STATUS]_[id]")
. = ..()
/datum/status_effect/electrode/tick()
var/diff = world.time - last_tick
if(owner)
owner.adjustStaminaLoss(max(0, stamdmg_per_ds * diff)) //if you really want to try to stamcrit someone with a taser alone, you can, but it'll take time and good timing.
last_tick = world.time
/datum/status_effect/electrode/nextmove_modifier() //why is this a proc. its no big deal since this doesnt get called often at all but literally w h y
return nextmove_modifier
/datum/status_effect/electrode/no_combat_mode
id = "tased_strong"
slowdown = 8
slowdown_priority = 100
nextmove_modifier = 2
blocks_combatmode = TRUE
/datum/status_effect/electrode/no_combat_mode/on_creation(mob/living/new_owner, set_duration)
. = ..()
if(iscarbon(owner))
var/mob/living/carbon/C = owner
if(C.combatmode)
C.toggle_combat_mode(TRUE)
C.add_movespeed_modifier(MOVESPEED_ID_TASED_STATUS, TRUE, override = TRUE, multiplicative_slowdown = 8)
/datum/status_effect/no_combat_mode/electrode/on_remove()
if(iscarbon(owner))
var/mob/living/carbon/C = owner
C.remove_movespeed_modifier(MOVESPEED_ID_TASED_STATUS)
. = ..()
/datum/status_effect/no_combat_mode/electrode/tick()
if(owner)
owner.adjustStaminaLoss(5) //if you really want to try to stamcrit someone with a taser alone, you can, but it'll take time and good timing.
/datum/status_effect/no_combat_mode/electrode/nextmove_modifier() //why is this a proc. its no big deal since this doesnt get called often at all but literally w h y
return 2
//OTHER DEBUFFS
/datum/status_effect/his_wrath //does minor damage over time unless holding His Grace
+1
View File
@@ -8,6 +8,7 @@
var/gain_text
var/lose_text
var/medical_record_text //This text will appear on medical records for the trait. Not yet implemented
var/antag_removal_text // Text will be given to the quirk holder if they get an antag that has it blacklisted.
var/mood_quirk = FALSE //if true, this quirk affects mood and is unavailable if moodlets are disabled
var/mob_trait //if applicable, apply and remove this mob trait
var/mob/living/quirk_holder
+8 -13
View File
@@ -6,6 +6,7 @@
value = -2
gain_text = "<span class='danger'>You feel your vigor slowly fading away.</span>"
lose_text = "<span class='notice'>You feel vigorous again.</span>"
antag_removal_text = "Your antagonistic nature has removed your blood deficiency."
medical_record_text = "Patient requires regular treatment for blood loss due to low production of blood."
/datum/quirk/blooddeficiency/on_process()
@@ -38,6 +39,8 @@
var/obj/item/heirloom
var/where
GLOBAL_LIST_EMPTY(family_heirlooms)
/datum/quirk/family_heirloom/on_spawn()
var/mob/living/carbon/human/H = quirk_holder
var/obj/item/heirloom_type
@@ -76,6 +79,7 @@
/obj/item/lighter,
/obj/item/dice/d20)
heirloom = new heirloom_type(get_turf(quirk_holder))
GLOB.family_heirlooms += heirloom
var/list/slots = list(
"in your left pocket" = SLOT_L_STORE,
"in your right pocket" = SLOT_R_STORE,
@@ -140,9 +144,8 @@
/datum/quirk/nearsighted/on_spawn()
var/mob/living/carbon/human/H = quirk_holder
var/obj/item/clothing/glasses/regular/glasses = new(get_turf(H))
H.put_in_hands(glasses)
H.equip_to_slot(glasses, SLOT_GLASSES)
H.regenerate_icons() //this is to remove the inhand icon, which persists even if it's not in their hands
if(!H.equip_to_slot_if_possible(glasses, SLOT_GLASSES))
H.put_in_hands(glasses)
/datum/quirk/nyctophobia
name = "Nyctophobia"
@@ -188,11 +191,7 @@
gain_text = "<span class='danger'>You feel repulsed by the thought of violence!</span>"
lose_text = "<span class='notice'>You think you can defend yourself again.</span>"
medical_record_text = "Patient is unusually pacifistic and cannot bring themselves to cause physical harm."
/datum/quirk/nonviolent/on_process()
if(quirk_holder.mind && LAZYLEN(quirk_holder.mind.antag_datums))
to_chat(quirk_holder, "<span class='boldannounce'>Your antagonistic nature has caused you to renounce your pacifism.</span>")
qdel(src)
antag_removal_text = "Your antagonistic nature has caused you to renounce your pacifism."
/datum/quirk/paraplegic
name = "Paraplegic"
@@ -355,6 +354,7 @@
gain_text = "<span class='danger'>You find yourself unable to speak!</span>"
lose_text = "<span class='notice'>You feel a growing strength in your vocal chords.</span>"
medical_record_text = "Functionally mute, patient is unable to use their voice in any capacity."
antag_removal_text = "Your antagonistic nature has caused your voice to be heard."
var/datum/brain_trauma/severe/mute/mute
/datum/quirk/mute/add()
@@ -366,11 +366,6 @@
var/mob/living/carbon/human/H = quirk_holder
H?.cure_trauma_type(mute, TRAUMA_RESILIENCE_ABSOLUTE)
/datum/quirk/mute/on_process()
if(quirk_holder.mind && LAZYLEN(quirk_holder.mind.antag_datums))
to_chat(quirk_holder, "<span class='boldannounce'>Your antagonistic nature has caused your voice to be heard.</span>")
qdel(src)
/datum/quirk/unstable
name = "Unstable"
desc = "Due to past troubles, you are unable to recover your sanity if you lose it. Be very careful managing your mood!"
+1 -1
View File
@@ -52,7 +52,7 @@
/datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder
if(!issilicon(user) && A.isElectrified() && A.shock(user, 100))
if(!A.hasSiliconAccessInArea(user) && A.isElectrified() && A.shock(user, 100))
return FALSE
if(A.panel_open)
return TRUE
+1 -1
View File
@@ -12,7 +12,7 @@
/datum/wires/vending/interactable(mob/user)
var/obj/machinery/vending/V = holder
if(!issilicon(user) && V.seconds_electrified && V.shock(user, 100))
if(!V.hasSiliconAccessInArea(user) && V.seconds_electrified && V.shock(user, 100))
return FALSE
if(V.panel_open)
return TRUE
+1
View File
@@ -6,6 +6,7 @@
var/flags_1 = NONE
var/interaction_flags_atom = NONE
var/ghost_flags = NONE
var/datum/reagents/reagents = null
//This atom's HUD (med/sec, etc) images. Associative list.
+13 -4
View File
@@ -41,7 +41,7 @@ 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)
GLOBAL_VAR_INIT(dynamic_storyteller_type, null)
GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
/datum/game_mode/dynamic
name = "dynamic mode"
@@ -239,12 +239,20 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, null)
. += "<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)
for(var/T in subtypesof(/datum/station_goal))
var/datum/station_goal/G = new T
if(!(G in station_goals))
station_goals += G
if(21 to 79)
var/perc_green = 100-round(100*((threat_level-21)/(79-21)))
if(prob(perc_green))
. += "<b>Core Territory</b></center><BR>"
. += "Your station orbits within reliably mundane, secure space. Although Nanotrasen has a firm grip on security in your region, the valuable resources and strategic position aboard your station make it a potential target for infiltrations. Monitor crew for non-loyal behavior, but expect a relatively tame shift free of large-scale destruction. We expect great things from your station."
set_security_level(SEC_LEVEL_GREEN)
for(var/T in subtypesof(/datum/station_goal))
var/datum/station_goal/G = new T
if(!(G in station_goals))
station_goals += G
else if(prob(perc_green))
. += "<b>Contested System</b></center><BR>"
. += "Your station's orbit passes along the edge of Nanotrasen's sphere of influence. While subversive elements remain the most likely threat against your station, hostile organizations are bolder here, where our grip is weaker. Exercise increased caution against elite Syndicate strike forces, or Executives forbid, some kind of ill-conceived unionizing attempt."
@@ -273,7 +281,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, null)
if(GLOB.security_level >= SEC_LEVEL_BLUE)
priority_announce("A summary has been copied and printed to all communications consoles.", "Security level elevated.", "intercept")
else
priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no likely threats to [station_name()]. Have a secure shift!", "Security Report", "commandreport")
priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no likely threats to [station_name()]. All station construction projects have been authorized. Have a secure shift!", "Security Report", "commandreport")
// Yes, this is copy pasted from game_mode
/datum/game_mode/dynamic/check_finished(force_ending)
@@ -346,7 +354,8 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, null)
generate_threat()
storyteller.start_injection_cooldowns()
SSevents.frequency_lower = storyteller.event_frequency_lower // 6 minutes by default
SSevents.frequency_upper = storyteller.event_frequency_upper // 20 minutes by default
log_game("DYNAMIC: Dynamic Mode initialized with a Threat Level of... [threat_level]!")
initial_threat_level = threat_level
return TRUE
@@ -395,7 +404,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, null)
/datum/game_mode/dynamic/post_setup(report)
update_playercounts()
for(var/datum/dynamic_ruleset/roundstart/rule in executed_rules)
addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/execute_roundstart_rule, rule), rule.delay)
..()
@@ -47,6 +47,8 @@
assigned += M.mind
M.mind.special_role = antag_flag
M.mind.add_antag_datum(antag_datum)
log_admin("[M.name] was made into a [name] by dynamic.")
message_admins("[M.name] was made into a [name] by dynamic.")
return TRUE
//////////////////////////////////////////////
@@ -72,12 +74,6 @@
property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1)
always_max_weight = TRUE
/datum/dynamic_ruleset/latejoin/infiltrator/execute()
. = ..()
for(var/datum/mind/M in assigned)
log_admin("[M.name] was made into a traitor by dynamic.")
message_admins("[M.name] was made into a traitor by dynamic.")
//////////////////////////////////////////////
// //
// REVOLUTIONARY PROVOCATEUR //
@@ -225,3 +221,25 @@
log_admin("[M.name] was made into a bloodsucker by dynamic.")
message_admins("[M.name] was made into a bloodsucker by dynamic.")
return TRUE
//////////////////////////////////////////////
// //
// COLLECTOR //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/latejoin/collector
name = "Contraband Collector"
config_tag = "latejoin_collector"
antag_datum = /datum/antagonist/collector
antag_flag = ROLE_MINOR_ANTAG
restricted_roles = list("AI", "Cyborg")
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_candidates = 1
weight = 5
cost = 1
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
flags = TRAITOR_RULESET
property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 2)
@@ -494,7 +494,7 @@
high_population_requirement = 50
repeatable_weight_decrease = 2
repeatable = TRUE
property_weights = list("story_potential" = 1, "trust" = 1, "extended" = 1, "valid" = 2, "integrity" = 2)
property_weights = list("story_potential" = 1, "trust" = 1, "extended" = 1, "valid" = 2, "integrity" = 1)
var/list/spawn_locs = list()
/datum/dynamic_ruleset/midround/from_ghosts/nightmare/execute()
@@ -1,5 +1,6 @@
/datum/dynamic_storyteller
var/name = "none"
var/config_tag = null
var/desc = "A coder's idiocy."
var/list/property_weights = list()
var/curve_centre = 0
@@ -7,6 +8,8 @@
var/forced_threat_level = -1
var/flags = 0
var/weight = 3 // how many rounds need to have been recently played for this storyteller to be left out of the vote
var/event_frequency_lower = 6 MINUTES
var/event_frequency_upper = 20 MINUTES
var/datum/game_mode/dynamic/mode = null
/**
@@ -20,14 +23,6 @@ Property weights are:
"conversion" -- Basically a bool. Conversion antags, well, convert. It's its own class for a good reason.
*/
/datum/dynamic_storyteller/New()
..()
if (istype(SSticker.mode, /datum/game_mode/dynamic))
mode = SSticker.mode
GLOB.dynamic_curve_centre = curve_centre
GLOB.dynamic_curve_width = curve_width
GLOB.dynamic_forced_threat_level = forced_threat_level
/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
@@ -42,7 +37,28 @@ Property weights are:
return
/datum/dynamic_storyteller/proc/on_start()
return
if (istype(SSticker.mode, /datum/game_mode/dynamic))
mode = SSticker.mode
GLOB.dynamic_curve_centre = curve_centre
GLOB.dynamic_curve_width = curve_width
if(flags & USE_PREF_WEIGHTS)
var/voters = 0
var/mean = 0
for(var/client/c in GLOB.clients)
var/vote = c.prefs.preferred_chaos
if(vote)
voters += 1
switch(vote)
if(CHAOS_NONE)
mean -= 5
if(CHAOS_LOW)
mean -= 2.5
if(CHAOS_HIGH)
mean += 2.5
if(CHAOS_MAX)
mean += 5
GLOB.dynamic_curve_centre += (mean/voters)
GLOB.dynamic_forced_threat_level = forced_threat_level
/datum/dynamic_storyteller/proc/get_midround_cooldown()
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_midround_delay_max + GLOB.dynamic_midround_delay_min)
@@ -154,12 +170,15 @@ Property weights are:
/datum/dynamic_storyteller/cowabunga
name = "Chaotic"
config_tag = "chaotic"
curve_centre = 10
desc = "Chaos: high. Variation: high. Likely antags: clock cult, revs, wizard."
property_weights = list("extended" = -1, "chaos" = 10)
weight = 2
weight = 1
event_frequency_lower = 2 MINUTES
event_frequency_upper = 10 MINUTES
flags = WAROPS_ALWAYS_ALLOWED
var/refund_cooldown
var/refund_cooldown = 0
/datum/dynamic_storyteller/cowabunga/get_midround_cooldown()
return ..() / 4
@@ -169,12 +188,13 @@ Property weights are:
/datum/dynamic_storyteller/cowabunga/do_process()
if(refund_cooldown < world.time)
mode.refund_threat(10)
mode.log_threat("Cowabunga it is. Refunded 10 threat. Threat is now [mode.threat].")
refund_cooldown = world.time + 300 SECONDS
mode.refund_threat(20)
mode.log_threat("Cowabunga it is. Refunded 20 threat. Threat is now [mode.threat].")
refund_cooldown = world.time + 600 SECONDS
/datum/dynamic_storyteller/team
name = "Teamwork"
config_tag = "teamwork"
desc = "Chaos: high. Variation: low. Likely antags: nukies, clockwork cult, wizard, blob, xenomorph."
curve_centre = 2
curve_width = 1.5
@@ -187,6 +207,7 @@ Property weights are:
/datum/dynamic_storyteller/conversion
name = "Conversion"
config_tag = "conversion"
desc = "Chaos: high. Variation: medium. Likely antags: cults, bloodsuckers, revs."
curve_centre = 3
curve_width = 1
@@ -196,24 +217,33 @@ Property weights are:
/datum/dynamic_storyteller/classic
name = "Random"
config_tag = "random"
desc = "Chaos: varies. Variation: highest. No special weights attached."
weight = 6
flags = USE_PREF_WEIGHTS
curve_width = 4
/datum/dynamic_storyteller/memes
name = "Story"
config_tag = "story"
desc = "Chaos: varies. Variation: high. Likely antags: abductors, nukies, wizard, traitor."
weight = 4
flags = USE_PREF_WEIGHTS
curve_width = 4
property_weights = list("story_potential" = 10)
/datum/dynamic_storyteller/suspicion
name = "Intrigue"
config_tag = "intrigue"
desc = "Chaos: low. Variation: high. Likely antags: traitor, bloodsucker. Rare: revs, blood cult."
weight = 4
flags = USE_PREF_WEIGHTS
curve_width = 4
property_weights = list("trust" = -5)
/datum/dynamic_storyteller/liteextended
name = "Calm"
config_tag = "calm"
desc = "Chaos: low. Variation: medium. Likely antags: bloodsuckers, traitors, sentient disease, revenant."
curve_centre = -5
curve_width = 0.5
@@ -226,10 +256,12 @@ Property weights are:
/datum/dynamic_storyteller/extended
name = "Extended"
config_tag = "extended"
desc = "Chaos: none. Variation: none. Likely antags: none."
curve_centre = -20
weight = 2
weight = 0
curve_width = 0.5
/datum/dynamic_storyteller/extended/on_start()
..()
GLOB.dynamic_forced_extended = TRUE
+2 -1
View File
@@ -6,7 +6,8 @@ GLOBAL_LIST_EMPTY(gangs)
name = "gang war"
config_tag = "gang"
antag_flag = ROLE_GANG
restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security")
restricted_jobs = list("AI", "Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_players = 15
required_enemies = 0
recommended_enemies = 2
+190 -35
View File
@@ -9,9 +9,10 @@ GLOBAL_LIST_EMPTY(objectives)
var/explanation_text = "Nothing" //What that person is supposed to do.
var/team_explanation_text //For when there are multiple owners.
var/datum/mind/target = null //If they are focused on a particular person.
var/target_amount = 0 //If they are focused on a particular number. Steal objectives have their own counter.
var/completed = 0 //currently only used for custom objectives.
var/martyr_compatible = 0 //If the objective is compatible with martyr objective, i.e. if you can still do it while dead.
var/target_amount = FALSE //If they are focused on a particular number. Steal objectives have their own counter.
var/completed = FALSE //currently only used for custom objectives.
var/completable = TRUE //Whether this objective shows greentext when completed
var/martyr_compatible = FALSE //If the objective is compatible with martyr objective, i.e. if you can still do it while dead.
/datum/objective/New(var/text)
GLOB.objectives += src // CITADEL EDIT FOR CRYOPODS
@@ -172,6 +173,26 @@ GLOBAL_LIST_EMPTY(objectives)
/datum/objective/assassinate/admin_edit(mob/admin)
admin_simple_target_pick(admin)
/datum/objective/assassinate/once
name = "kill once"
var/won = FALSE
/datum/objective/assassinate/once/update_explanation_text()
..()
if(target && target.current)
explanation_text = "Kill [target.name], the [!target_role_type ? target.assigned_role : target.special_role]. You only need to kill them once; if they come back, you've still succeeded."
START_PROCESSING(SSprocessing,src)
else
explanation_text = "Free Objective"
/datum/objective/assassinate/once/check_completion()
return won || ..()
/datum/objective/assassinate/once/process()
won = check_completion()
if(won)
STOP_PROCESSING(SSprocessing,src)
/datum/objective/assassinate/internal
var/stolen = 0 //Have we already eliminated this target?
@@ -365,6 +386,28 @@ GLOBAL_LIST_EMPTY(objectives)
return FALSE
return TRUE
/datum/objective/breakout
name = "breakout"
martyr_compatible = 1
var/target_role_type = 0
var/human_check = TRUE
/datum/objective/breakout/check_completion()
return !target || considered_escaped(target)
/datum/objective/breakout/find_target_by_role(role, role_type=0, invert=0)
if(!invert)
target_role_type = role_type
..()
return target
/datum/objective/breakout/update_explanation_text()
..()
if(target && target.current)
explanation_text = "Make sure [target.name], the [!target_role_type ? target.assigned_role : target.special_role] escapes on the shuttle or an escape pod alive and without being in custody."
else
explanation_text = "Free Objective"
/datum/objective/escape/escape_with_identity
name = "escape with identity"
var/target_real_name // Has to be stored because the target's real_name can change over the course of the round
@@ -582,7 +625,6 @@ GLOBAL_LIST_EMPTY(possible_items_special)
explanation_text = "Do not give up or lose [targetinfo.name]."
steal_target = targetinfo.targetitem
/datum/objective/download
name = "download"
@@ -786,40 +828,10 @@ GLOBAL_LIST_EMPTY(possible_items_special)
/datum/objective/destroy/internal
var/stolen = FALSE //Have we already eliminated this target?
/datum/objective/steal_five_of_type
name = "steal five of"
explanation_text = "Steal at least five items!"
var/list/wanted_items = list(/obj/item)
/datum/objective/steal_five_of_type/New()
..()
wanted_items = typecacheof(wanted_items)
/datum/objective/steal_five_of_type/summon_guns
name = "steal guns"
explanation_text = "Steal at least five guns!"
wanted_items = list(/obj/item/gun)
/datum/objective/steal_five_of_type/summon_magic
name = "steal magic"
explanation_text = "Steal at least five magical artefacts!"
wanted_items = list(/obj/item/spellbook, /obj/item/gun/magic, /obj/item/clothing/suit/space/hardsuit/wizard, /obj/item/scrying, /obj/item/antag_spawner/contract, /obj/item/necromantic_stone)
/datum/objective/steal_five_of_type/check_completion()
var/list/datum/mind/owners = get_owners()
var/stolen_count = 0
for(var/datum/mind/M in owners)
if(!isliving(M.current))
continue
var/list/all_items = M.current.GetAllContents() //this should get things in cheesewheels, books, etc.
for(var/obj/I in all_items) //Check for wanted items
if(is_type_in_typecache(I, wanted_items))
stolen_count++
return stolen_count >= 5
//Created by admin tools
/datum/objective/custom
name = "custom"
completable = FALSE
/datum/objective/custom/admin_edit(mob/admin)
var/expl = stripped_input(admin, "Custom objective:", "Objective", explanation_text)
@@ -997,4 +1009,147 @@ GLOBAL_LIST_EMPTY(possible_items_special)
command_staff_only = TRUE
/datum/objective/hoard
name = "hoard"
var/obj/item/hoarded_item = null
/datum/objective/hoard/get_target()
return hoarded_item
/datum/objective/hoard/proc/set_target(obj/item/I)
if(I)
hoarded_item = I
explanation_text = "Keep [I] on your person at all times."
return hoarded_item
else
explanation_text = "Free objective"
return
/datum/objective/hoard/check_completion()
var/list/datum/mind/owners = get_owners()
if(!hoarded_item)
return TRUE
for(var/datum/mind/M in owners)
if(!isliving(M.current))
continue
var/list/all_items = M.current.GetAllContents() //this should get things in cheesewheels, books, etc.
for(var/obj/I in all_items) //Check for items
if(I == hoarded_item)
return TRUE
return FALSE
/datum/objective/hoard/heirloom
name = "steal heirloom"
/datum/objective/hoard/heirloom/find_target()
set_target(pick(GLOB.family_heirlooms))
GLOBAL_LIST_EMPTY(traitor_contraband)
GLOBAL_LIST_EMPTY(cult_contraband)
/datum/objective/hoard/collector
name = "Hoard contraband"
/datum/objective/collector/New()
..()
if(!GLOB.traitor_contraband.len)//Only need to fill the list when it's needed.
GLOB.traitor_contraband = list(/obj/item/card/emag/empty,/obj/item/clothing/glasses/phantomthief,/obj/item/clothing/gloves/chameleon/broken)
if(!GLOB.cult_contraband.len)
GLOB.cult_contraband = list(/obj/item/clockwork/slab,/obj/item/clockwork/component/belligerent_eye,/obj/item/clockwork/component/belligerent_eye/lens_gem,/obj/item/shuttle_curse,/obj/item/cult_shift)
/datum/objective/hoard/collector/find_target()
var/obj/item/I
var/I_type
if(prob(50))
I_type = pick_n_take(GLOB.traitor_contraband) // always unique unless it's run out, in which case we refill it anyway
else
I_type = pick_n_take(GLOB.cult_contraband)
I = new I_type
I.forceMove(get_turf(owner))
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
H.equip_in_one_of_slots(I, list("backpack" = SLOT_IN_BACKPACK))
hoarded_item = I
GLOBAL_LIST_EMPTY(possible_sabotages)
// For saboteurs. Go in and cause some trouble somewhere. Not necessarily breaking things, just sufficiently troublemaking.
/datum/objective/sabotage
name = "sabotage"
var/datum/sabotage_objective/targetinfo = null //composition > inheritance.
/datum/objective/sabotage/get_target()
return targetinfo.sabotage_type
/datum/objective/sabotage/New()
..()
if(!GLOB.possible_sabotages.len)//Only need to fill the list when it's needed.
for(var/I in subtypesof(/datum/sabotage_objective))
new I
/datum/objective/sabotage/find_target()
var/list/datum/mind/owners = get_owners()
var/approved_targets = list()
check_sabotages:
for(var/datum/sabotage_objective/possible_sabotage in GLOB.possible_sabotages)
if(!is_unique_objective(possible_sabotage.sabotage_type) || possible_sabotage.check_conditions())
continue
for(var/datum/mind/M in owners)
if(M.current.mind.assigned_role in possible_sabotage.excludefromjob)
continue check_sabotages
approved_targets += possible_sabotage
return set_target(safepick(approved_targets))
/datum/objective/sabotage/proc/set_target(datum/sabotage_objective/sabo)
if(sabo)
targetinfo = sabo
explanation_text = "[targetinfo.name]"
give_special_equipment(targetinfo.special_equipment)
return sabo
else
explanation_text = "Free objective"
return
/datum/objective/sabotage/check_completion()
return targetinfo.check_conditions()
/datum/objective/flavor
name = "flavor"
completable = FALSE
var/flavor_file
/datum/objective/flavor/proc/get_flavor_list()
return world.file2list(flavor_file)
/datum/objective/flavor/proc/forge_objective()
var/flavor_list = get_flavor_list()
explanation_text = pick(flavor_list)
/datum/objective/flavor/traitor
name = "traitor flavor"
flavor_file = "strings/flavor_objectives/traitor.txt"
/datum/objective/flavor/traitor/get_flavor_list()
. = ..()
switch(owner.assigned_role)
if("Station Engineer", "Atmospheric Technician")
. += world.file2list("strings/flavor_objectives/traitor/engineering.txt")
if("Medical Doctor","Chemist","Virologist","Geneticist")
. += world.file2list("strings/flavor_objectives/traitor/medical.txt")
if("Scientist","Roboticist","Geneticist")
. += world.file2list("strings/flavor_objectives/traitor/science.txt")
if("Assistant")
. += world.file2list("strings/flavor_objectives/traitor/assistant.txt")
/datum/objective/flavor/ninja_helping
flavor_file = "strings/flavor_objectives/ninja_helping.txt"
/datum/objective/flavor/ninja_syndie
flavor_file = "strings/flavor_objectives/ninja_syndie.txt"
/datum/objective/flavor/wizard
flavor_file = "strings/flavor_objectives/wizard.txt"
+107
View File
@@ -0,0 +1,107 @@
/datum/sabotage_objective
var/name = "Free Objective"
var/sabotage_type = "nothing"
var/special_equipment = list()
var/list/excludefromjob = list()
/datum/sabotage_objective/New()
..()
if(sabotage_type!="nothing")
GLOB.possible_sabotages += src
/datum/sabotage_objective/proc/check_conditions()
return TRUE
/datum/sabotage_objective/processing
var/won = FALSE
/datum/sabotage_objective/processing/New()
..()
START_PROCESSING(SSprocessing, src)
/datum/sabotage_objective/processing/proc/check_condition_processing()
return 100
/datum/sabotage_objective/processing/process()
check_condition_processing()
if(won >= 100)
STOP_PROCESSING(SSprocessing,src)
/datum/sabotage_objective/processing/check_conditions()
return won
/datum/sabotage_objective/processing/power_sink
name = "Drain at least 1 gigajoule of power using a power sink."
sabotage_type = "powersink"
special_equipment = list(/obj/item/powersink)
var/sink_found = FALSE
var/count = 0
/datum/sabotage_objective/processing/power_sink/check_condition_processing()
count += 1
if(count==10 || sink_found) // doesn't need to fire that often unless a sink exists
var/sink_found_this_time = FALSE
for(var/datum/powernet/PN in GLOB.powernets)
for(var/obj/item/powersink/sink in PN.nodes)
sink_found_this_time = TRUE
won = max(won,sink.power_drained/1e9)
sink_found = sink_found_this_time
count = 0
return FALSE
/obj/item/paper/guides/antag/supermatter_sabotage
info = "Ways to sabotage a supermatter:<br>\
<ul>\
<li>Set the air alarm's operating mode to anything that isn't 'draught' (yes, anything, though 'off' works best). Or just smash the air alarm, that works too.</li>\
<li>Wrench a pipe (the junction to the cold loop is most effective, but some setups will robust through this no issue; best to try for multiple)</li>\
<li>Pump in as much carbon dioxide, oxygen, plasma or tritium as you can find (this will likely also cause a singularity or tesla delamination, so watch out!)</li>\
<li>Unset the filters on the cooling loop, or, perhaps more insidious, set them to oxygen/plasma.</li>\
<li>Deactivate the digital valve that sends the exhaust gases to space (note: only works on box station; others you must unwrench).</li>\
<li>There are many other ways; be creative!</li>\
</ul>"
/datum/sabotage_objective/processing/supermatter
name = "Sabotage the supermatter so that it goes under 50% integrity. If it is delaminated, you will fail."
sabotage_type = "supermatter"
special_equipment = list(/obj/item/paper/guides/antag/supermatter_sabotage)
var/list/supermatters = list()
excludefromjob = list("Chief Engineer", "Station Engineer", "Atmospheric Technician")
/datum/sabotage_objective/processing/supermatter/check_condition_processing()
if(!supermatters.len)
supermatters = list()
for(var/obj/machinery/power/supermatter_crystal/S in GLOB.machines)
// Delaminating, not within coverage, not on a tile.
if (!isturf(S.loc) || !(is_station_level(S.z) || is_mining_level(S.z)))
continue
supermatters.Add(S)
for(var/obj/machinery/power/supermatter_crystal/S in supermatters) // you can win this with a wishgranter... lol.
won = max(1-((S.get_integrity()-50)/50),won)
return FALSE
/datum/sabotage_objective/station_integrity
name = "Make sure the station is at less than 80% integrity by the end. Smash walls, windows etc. to reach this goal."
sabotage_type = "integrity"
/datum/sabotage_objective/station_integrity/check_conditions()
return 5-(max(SSticker.station_integrity*4,320)/80)
/datum/sabotage_objective/cloner
name = "Destroy all Nanotrasen cloning machines."
sabotage_type = "cloner"
/datum/sabotage_objective/cloner/check_conditions()
return !(locate(/obj/machinery/clonepod) in GLOB.machines)
/datum/sabotage_objective/ai_law
name = "Upload a hacked law to the AI."
sabotage_type = "ailaw"
special_equipment = list(/obj/item/aiModule/syndicate)
excludefromjob = list("Chief Engineer","Research Director","Head of Personnel","Captain","Chief Medical Officer","Head Of Security")
/datum/sabotage_objective/ai_law/check_conditions()
for (var/i in GLOB.ai_list)
var/mob/living/silicon/ai/aiPlayer = i
if(aiPlayer.mind && length(aiPlayer.laws.hacked))
return TRUE
return FALSE
+1 -1
View File
@@ -182,7 +182,7 @@
/obj/machinery/sleeper/AltClick(mob/user)
. = ..()
if(!user.canUseTopic(src, !issilicon(user)))
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return
if(state_open)
close_machine()
+2 -2
View File
@@ -229,7 +229,7 @@ Class Procs:
return !(stat & (NOPOWER|BROKEN|MAINT))
/obj/machinery/can_interact(mob/user)
var/silicon = issiliconoradminghost(user)
var/silicon = hasSiliconAccessInArea(user) || IsAdminGhost(user)
if((stat & (NOPOWER|BROKEN)) && !(interaction_flags_machine & INTERACT_MACHINE_OFFLINE))
return FALSE
if(panel_open && !(interaction_flags_machine & INTERACT_MACHINE_OPEN))
@@ -242,7 +242,7 @@ Class Procs:
else
if(interaction_flags_machine & INTERACT_MACHINE_REQUIRES_SILICON)
return FALSE
if(!Adjacent(user))
if(!Adjacent(user) && !isobserver(user))
var/mob/living/carbon/H = user
if(!(istype(H) && H.has_dna() && H.dna.check_mutation(TK)))
return FALSE
+5 -5
View File
@@ -105,7 +105,7 @@ GLOBAL_LIST_EMPTY(announcement_systems)
/obj/machinery/announcement_system/ui_interact(mob/user)
. = ..()
if(!user.canUseTopic(src, !issilicon(user)))
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return
if(stat & BROKEN)
visible_message("<span class='warning'>[src] buzzes.</span>", "<span class='italics'>You hear a faint buzz.</span>")
@@ -123,7 +123,7 @@ GLOBAL_LIST_EMPTY(announcement_systems)
/obj/machinery/announcement_system/Topic(href, href_list)
if(..())
return
if(!usr.canUseTopic(src, !issilicon(usr)))
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
return
if(stat & BROKEN)
visible_message("<span class='warning'>[src] buzzes.</span>", "<span class='italics'>You hear a faint buzz.</span>")
@@ -132,13 +132,13 @@ GLOBAL_LIST_EMPTY(announcement_systems)
if(href_list["ArrivalTopic"])
var/NewMessage = stripped_input(usr, "Enter in the arrivals announcement configuration.", "Arrivals Announcement Config", arrival)
if(!usr.canUseTopic(src, !issilicon(usr)))
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
return
if(NewMessage)
arrival = NewMessage
else if(href_list["NewheadTopic"])
var/NewMessage = stripped_input(usr, "Enter in the departmental head announcement configuration.", "Head Departmental Announcement Config", newhead)
if(!usr.canUseTopic(src, !issilicon(usr)))
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
return
if(NewMessage)
newhead = NewMessage
@@ -157,7 +157,7 @@ GLOBAL_LIST_EMPTY(announcement_systems)
. = attack_ai(user)
/obj/machinery/announcement_system/attack_ai(mob/user)
if(!user.canUseTopic(src, !issilicon(user)))
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return
if(stat & BROKEN)
to_chat(user, "<span class='warning'>[src]'s firmware appears to be malfunctioning!</span>")
@@ -304,12 +304,12 @@
/obj/machinery/computer/arcade/minesweeper/proc/custom_generation(mob/user)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) //Entered into the menu so ping sound
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, !issilicon(user)))
if(!new_rows || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return FALSE
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, !issilicon(user)))
if(!new_columns || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return FALSE
new_columns = CLAMP(new_columns + 1, 4, 50)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
@@ -317,7 +317,7 @@
var/lower_limit = round(grid_area*0.156)
var/upper_limit = round(grid_area*0.85)
var/new_mine_limit = input(user, "How many mines do you want? (Minimum: [lower_limit], Maximum: [upper_limit])", "Minesweeper Mines") as null|num
if(!new_mine_limit || !user.canUseTopic(src, !issilicon(user)))
if(!new_mine_limit || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return FALSE
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
rows = new_rows
+1 -1
View File
@@ -36,7 +36,7 @@
return ..()
/obj/machinery/computer/security/can_interact(mob/user)
if((!issilicon(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src))
if((!hasSiliconAccessInArea(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src))
return FALSE
return ..()
+5 -5
View File
@@ -171,7 +171,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
/obj/machinery/computer/card/AltClick(mob/user)
. = ..()
if(!user.canUseTopic(src, !issilicon(user)) || !is_operational())
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)) || !is_operational())
return
if(inserted_modify_id)
if(id_eject(user, inserted_modify_id))
@@ -360,7 +360,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
if(..())
return
if(!usr.canUseTopic(src, !issilicon(usr)) || !is_operational())
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)) || !is_operational())
usr.unset_machine()
usr << browse(null, "window=id_com")
return
@@ -392,7 +392,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
inserted_scan_id = id_to_insert
updateUsrDialog()
if ("auth")
if ((!( authenticated ) && (inserted_scan_id || issilicon(usr)) || mode))
if ((!( authenticated ) && (inserted_scan_id || hasSiliconAccessInArea(usr)) || mode))
if (check_access(inserted_scan_id))
region_access = list()
head_subordinates = list()
@@ -426,7 +426,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
get_subordinates("Quartermaster")
if(region_access)
authenticated = 1
else if ((!( authenticated ) && issilicon(usr)) && (!inserted_modify_id))
else if ((!( authenticated ) && hasSiliconAccessInArea(usr)) && (!inserted_modify_id))
to_chat(usr, "<span class='warning'>You can't modify an ID without an ID inserted to modify! Once one is in the modify slot on the computer, you can log in.</span>")
if ("logout")
region_access = null
@@ -481,7 +481,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
if ("reg")
if (authenticated)
var/t2 = inserted_modify_id
if ((authenticated && inserted_modify_id == t2 && (in_range(src, usr) || issilicon(usr)) && isturf(loc)))
if ((authenticated && inserted_modify_id == t2 && (in_range(src, usr) || hasSiliconAccessInArea(usr)) && isturf(loc)))
var/newName = reject_bad_name(href_list["reg"])
if(newName)
inserted_modify_id.registered_name = newName
@@ -449,7 +449,7 @@
var/datum/browser/popup = new(user, "communications", "Communications Console", 400, 500)
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
if(issilicon(user))
if(issilicon(user) || (hasSiliconAccessInArea(user) && !in_range(user,src)))
var/dat2 = interact_ai(user) // give the AI a different interact proc to limit its access
if(dat2)
dat += dat2
+2 -2
View File
@@ -64,7 +64,7 @@
if(!user)
return
var/datum/browser/popup = new(user, "scannernew", "DNA Modifier Console", 800, 630) // Set up the popup browser window
if(!(in_range(src, user) || issilicon(user)))
if(!(in_range(src, user) || hasSiliconAccessInArea(user)))
popup.close()
return
popup.add_stylesheet("scannernew", 'html/browser/scannernew.css')
@@ -318,7 +318,7 @@
return
if(!isturf(usr.loc))
return
if(!((isturf(loc) && in_range(src, usr)) || issilicon(usr)))
if(!((isturf(loc) && in_range(src, usr)) || hasSiliconAccessInArea(usr)))
return
if(current_screen == "working")
return
+3 -3
View File
@@ -190,7 +190,7 @@
if(!(active2 in GLOB.data_core.medical))
active2 = null
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr) || IsAdminGhost(usr))
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr) || IsAdminGhost(usr))
usr.set_machine(src)
if(href_list["temp"])
temp = null
@@ -216,7 +216,7 @@
else if(href_list["login"])
var/mob/M = usr
var/obj/item/card/id/I = M.get_idcard(TRUE)
if(issilicon(M))
if(hasSiliconAccessInArea(M))
active1 = null
active2 = null
authenticated = 1
@@ -569,7 +569,7 @@
if(user)
if(message)
if(authenticated)
if(user.canUseTopic(src, !issilicon(user)))
if(user.canUseTopic(src, !hasSiliconAccessInArea(user)))
if(!record1 || record1 == active1)
if(!record2 || record2 == active2)
return 1
+1 -1
View File
@@ -86,7 +86,7 @@
/obj/machinery/computer/pod/Topic(href, href_list)
if(..())
return
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr))
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr))
usr.set_machine(src)
if(href_list["power"])
var/t = text2num(href_list["power"])
@@ -87,7 +87,7 @@
/obj/machinery/computer/prisoner/management/Topic(href, href_list)
if(..())
return
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr))
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr))
usr.set_machine(src)
if(href_list["id"])
+3 -3
View File
@@ -265,7 +265,7 @@ What a mess.*/
active1 = null
if(!( GLOB.data_core.security.Find(active2) ))
active2 = null
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr) || IsAdminGhost(usr))
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr) || IsAdminGhost(usr))
usr.set_machine(src)
switch(href_list["choice"])
// SORTING!
@@ -299,7 +299,7 @@ What a mess.*/
if("Log In")
var/mob/M = usr
var/obj/item/card/id/I = M.get_idcard(TRUE)
if(issilicon(M))
if(hasSiliconAccessInArea(M))
var/mob/living/silicon/borg = M
active1 = null
active2 = null
@@ -802,7 +802,7 @@ What a mess.*/
/obj/machinery/computer/secure_data/proc/canUseSecurityRecordsConsole(mob/user, message1 = 0, record1, record2)
if(user)
if(authenticated)
if(user.canUseTopic(src, !issilicon(user)))
if(user.canUseTopic(src, !hasSiliconAccessInArea(user)))
if(!trim(message1))
return 0
if(!record1 || record1 == active1)
+2 -2
View File
@@ -140,7 +140,7 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t
L[avoid_assoc_duplicate_keys(M.real_name, areaindex)] = M
var/desc = input("Please select a location to lock in.", "Locking Computer") as null|anything in L
if(!user.canUseTopic(src, !issilicon(user), NO_DEXTERY)) //check if we are still around
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user), NO_DEXTERY)) //check if we are still around
return
target = L[desc]
if(imp_t)
@@ -168,7 +168,7 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t
to_chat(user, "<span class='alert'>No active connected stations located.</span>")
return
var/desc = input("Please select a station to lock in.", "Locking Computer") as null|anything in L
if(!user.canUseTopic(src, !issilicon(user), NO_DEXTERY)) //again, check if we are still around
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user), NO_DEXTERY)) //again, check if we are still around
return
var/obj/machinery/teleport/station/target_station = L[desc]
if(!target_station || !target_station.teleporter_hub)
+2 -2
View File
@@ -53,7 +53,7 @@
/obj/machinery/jukebox/ui_interact(mob/user)
. = ..()
if(!user.canUseTopic(src, !issilicon(user)))
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return
if (!anchored)
to_chat(user,"<span class='warning'>This device must be anchored by a wrench!</span>")
@@ -430,6 +430,6 @@
/obj/machinery/jukebox/disco/process()
. = ..()
if(active)
for(var/mob/M in rangers)
for(var/mob/living/M in rangers)
if(prob(5+(allowed(M)*4)) && M.canmove)
dance(M)
+4 -3
View File
@@ -120,7 +120,7 @@
/obj/machinery/defibrillator_mount/AltClick(mob/living/carbon/user)
. = ..()
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
. = TRUE
if(!defib)
@@ -129,9 +129,10 @@
if(clamps_locked)
to_chat(user, "<span class='warning'>You try to tug out [defib], but the mount's clamps are locked tight!</span>")
return
if(!user.put_in_hands(defib))
if(!user.get_empty_held_indexes())
to_chat(user, "<span class='warning'>You need a free hand!</span>")
return
user.put_in_hands(defib)
user.visible_message("<span class='notice'>[user] unhooks [defib] from [src].</span>", \
"<span class='notice'>You slide out [defib] from [src] and unhook the charging cables.</span>")
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
@@ -147,4 +148,4 @@
materials = list(MAT_METAL = 300, MAT_GLASS = 100)
w_class = WEIGHT_CLASS_BULKY
result_path = /obj/machinery/defibrillator_mount
pixel_shift = -28
pixel_shift = -28
+1 -1
View File
@@ -98,7 +98,7 @@
/obj/machinery/dish_drive/AltClick(mob/living/user)
. = ..()
if(user.canUseTopic(src, !issilicon(user)))
if(user.canUseTopic(src, !hasSiliconAccessInArea(user)))
do_the_dishes(TRUE)
return TRUE
+1 -1
View File
@@ -172,7 +172,7 @@
/obj/machinery/dna_scannernew/AltClick(mob/user)
. = ..()
if(!user.canUseTopic(src, !issilicon(user)))
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return
interact(user)
return TRUE
+6 -6
View File
@@ -676,7 +676,7 @@
else
. += "It looks very robust."
if(issilicon(user) && (!stat & BROKEN))
if(hasSiliconAccessInArea(user) && (!stat & BROKEN))
. += "<span class='notice'>Shift-click [src] to [ density ? "open" : "close"] it.</span>"
. += "<span class='notice'>Ctrl-click [src] to [ locked ? "raise" : "drop"] its bolts.</span>"
. += "<span class='notice'>Alt-click [src] to [ secondsElectrified ? "un-electrify" : "permanently electrify"] it.</span>"
@@ -1322,9 +1322,9 @@
if(density && !open(2)) //The airlock is still closed, but something prevented it opening. (Another player noticed and bolted/welded the airlock in time!)
to_chat(user, "<span class='warning'>Despite your efforts, [src] managed to resist your attempts to open it!</span>")
/obj/machinery/door/airlock/hostile_lockdown(mob/origin)
/obj/machinery/door/airlock/hostile_lockdown(mob/origin, aicontrolneeded = TRUE)
// Must be powered and have working AI wire.
if(canAIControl(src) && !stat)
if((aicontrolneeded && canAIControl(src) && !stat) || !aicontrolneeded)
locked = FALSE //For airlocks that were bolted open.
safe = FALSE //DOOR CRUSH
close()
@@ -1334,9 +1334,9 @@
LAZYADD(shockedby, "\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(origin)]")
/obj/machinery/door/airlock/disable_lockdown()
/obj/machinery/door/airlock/disable_lockdown(aicontrolneeded = TRUE)
// Must be powered and have working AI wire.
if(canAIControl(src) && !stat)
if((aicontrolneeded && canAIControl(src) && !stat) || !aicontrolneeded)
unbolt()
set_electrified(NOT_ELECTRIFIED)
open()
@@ -1528,7 +1528,7 @@
. = TRUE
/obj/machinery/door/airlock/proc/user_allowed(mob/user)
return (issilicon(user) && canAIControl(user)) || IsAdminGhost(user)
return (hasSiliconAccessInArea(user) && canAIControl(user)) || IsAdminGhost(user)
/obj/machinery/door/airlock/proc/shock_restore(mob/user)
if(!user_allowed(user))
+89 -8
View File
@@ -189,6 +189,7 @@ GLOBAL_LIST_EMPTY(allCasters)
armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
max_integrity = 200
integrity_failure = 50
ghost_flags = INTERACT_GHOST_READ
var/screen = 0
var/paper_remaining = 15
var/securityCaster = 0
@@ -196,6 +197,7 @@ GLOBAL_LIST_EMPTY(allCasters)
var/alert_delay = 500
var/alert = FALSE
var/scanned_user = "Unknown"
var/mob/active_user = null
var/msg = ""
var/datum/picture/picture
var/channel_name = ""
@@ -264,10 +266,10 @@ GLOBAL_LIST_EMPTY(allCasters)
/obj/machinery/newscaster/ui_interact(mob/user)
. = ..()
if(ishuman(user) || issilicon(user))
var/mob/living/human_or_robot_user = user
if(ishuman(user) || issilicon(user) || isobserver(user))
var/mob/M = user
var/dat
scan_user(human_or_robot_user)
scan_user(M)
switch(screen)
if(0)
dat += "Welcome to Newscasting Unit #[unit_no].<BR> Interface & News networks Operational."
@@ -279,7 +281,7 @@ GLOBAL_LIST_EMPTY(allCasters)
dat+= "<BR><A href='?src=[REF(src)];create_feed_story=1'>Submit new Feed story</A>"
dat+= "<BR><A href='?src=[REF(src)];menu_paper=1'>Print newspaper</A>"
dat+= "<BR><A href='?src=[REF(src)];refresh=1'>Re-scan User</A>"
dat+= "<BR><BR><A href='?src=[REF(human_or_robot_user)];mach_close=newscaster_main'>Exit</A>"
dat+= "<BR><BR><A href='?src=[REF(M)];mach_close=newscaster_main'>Exit</A>"
if(securityCaster)
var/wanted_already = 0
if(GLOB.news_network.wanted_issue.active)
@@ -501,24 +503,36 @@ GLOBAL_LIST_EMPTY(allCasters)
if(21)
dat+="<FONT COLOR='maroon'>Unable to print newspaper. Insufficient paper. Please notify maintenance personnel to refill machine storage.</FONT><BR><BR>"
dat+="<A href='?src=[REF(src)];setScreen=[0]'>Return</A>"
var/datum/browser/popup = new(human_or_robot_user, "newscaster_main", "Newscaster Unit #[unit_no]", 400, 600)
var/datum/browser/popup = new(M, "newscaster_main", "Newscaster Unit #[unit_no]", 400, 600)
popup.set_content(dat)
popup.set_title_image(human_or_robot_user.browse_rsc_icon(icon, icon_state))
popup.set_title_image(M.browse_rsc_icon(icon, icon_state))
popup.open()
/obj/machinery/newscaster/Topic(href, href_list)
if(..())
return
if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && isturf(loc))) || issilicon(usr))
if(active_user && !isobserver(active_user) && get_dist(active_user,src)<=1 && usr!=active_user)
to_chat(usr, "<span class='warning'>You must wait for [active_user] to finish and move away.</span>")
return
if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && isturf(loc))) || hasSiliconAccessInArea(usr) || isobserver(usr))
usr.set_machine(src)
scan_user(usr)
if(href_list["set_channel_name"])
if(isobserver(usr) && !canGhostWrite(usr,src,"set a channel's name"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
channel_name = stripped_input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "", MAX_NAME_LEN)
updateUsrDialog()
else if(href_list["set_channel_lock"])
if(isobserver(usr) && !canGhostWrite(usr,src,"locked a channel"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
c_locked = !c_locked
updateUsrDialog()
else if(href_list["submit_new_channel"])
if(isobserver(usr) && !canGhostWrite(usr,src,"created a new channel"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
var/list/existing_authors = list()
for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels)
if(FC.authorCensor)
@@ -541,6 +555,9 @@ GLOBAL_LIST_EMPTY(allCasters)
screen=5
updateUsrDialog()
else if(href_list["set_channel_receiving"])
if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set the receiving channel"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
var/list/available_channels = list()
for(var/datum/newscaster/feed_channel/F in GLOB.news_network.network_channels)
if( (!F.locked || F.author == scanned_user) && !F.censored)
@@ -548,14 +565,23 @@ GLOBAL_LIST_EMPTY(allCasters)
channel_name = input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels
updateUsrDialog()
else if(href_list["set_new_message"])
if(isobserver(usr) && !canGhostWrite(usr,src,"set the message of a new feed story"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
var/temp_message = trim(stripped_multiline_input(usr, "Write your Feed story", "Network Channel Handler", msg))
if(temp_message)
msg = temp_message
updateUsrDialog()
else if(href_list["set_attachment"])
if(isobserver(usr))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
AttachPhoto(usr)
updateUsrDialog()
else if(href_list["submit_new_message"])
if(isobserver(usr) && !canGhostWrite(usr,src,"added a new story"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
if(msg =="" || msg=="\[REDACTED\]" || scanned_user == "Unknown" || channel_name == "" )
screen=6
else
@@ -565,15 +591,27 @@ GLOBAL_LIST_EMPTY(allCasters)
msg = ""
updateUsrDialog()
else if(href_list["create_channel"])
if(isobserver(usr) && !canGhostWrite(usr,src,"created a channel"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
screen=2
updateUsrDialog()
else if(href_list["create_feed_story"])
if(isobserver(usr) && !canGhostWrite(usr,src,"created a feed story"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
screen=3
updateUsrDialog()
else if(href_list["menu_paper"])
if(isobserver(usr) && !canGhostWrite(usr,src,""))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
screen=8
updateUsrDialog()
else if(href_list["print_paper"])
if(isobserver(usr) && !canGhostWrite(usr,src,"printed a paper"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
if(!paper_remaining)
screen=21
else
@@ -581,12 +619,21 @@ GLOBAL_LIST_EMPTY(allCasters)
screen = 20
updateUsrDialog()
else if(href_list["menu_censor_story"])
if(isobserver(usr) && !canGhostWrite(usr,src,"censored a story"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
screen=10
updateUsrDialog()
else if(href_list["menu_censor_channel"])
if(isobserver(usr) && !canGhostWrite(usr,src,"censored a channel"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
screen=11
updateUsrDialog()
else if(href_list["menu_wanted"])
if(isobserver(usr) && !canGhostWrite(usr,src,""))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
var/already_wanted = 0
if(GLOB.news_network.wanted_issue.active)
already_wanted = 1
@@ -596,12 +643,21 @@ GLOBAL_LIST_EMPTY(allCasters)
screen = 14
updateUsrDialog()
else if(href_list["set_wanted_name"])
if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set the name of a wanted person"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
channel_name = stripped_input(usr, "Provide the name of the Wanted person", "Network Security Handler")
updateUsrDialog()
else if(href_list["set_wanted_desc"])
if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set the description of a wanted person"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
msg = stripped_input(usr, "Provide a description of the Wanted person and any other details you deem important", "Network Security Handler")
updateUsrDialog()
else if(href_list["submit_wanted"])
if(isobserver(usr) && !canGhostWrite(usr,src,"submitted a wanted poster"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
var/input_param = text2num(href_list["submit_wanted"])
if(msg == "" || channel_name == "" || scanned_user == "Unknown")
screen = 16
@@ -632,6 +688,9 @@ GLOBAL_LIST_EMPTY(allCasters)
screen=18
updateUsrDialog()
else if(href_list["censor_channel_author"])
if(isobserver(usr) && !canGhostWrite(usr,src,"tried to censor an author"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
var/datum/newscaster/feed_channel/FC = locate(href_list["censor_channel_author"])
if(FC.is_admin_channel)
alert("This channel was created by a Nanotrasen Officer. You cannot censor it.","Ok")
@@ -639,6 +698,9 @@ GLOBAL_LIST_EMPTY(allCasters)
FC.toggleCensorAuthor()
updateUsrDialog()
else if(href_list["censor_channel_story_author"])
if(isobserver(usr) && !canGhostWrite(usr,src,"tried to censor a story's author"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
var/datum/newscaster/feed_message/MSG = locate(href_list["censor_channel_story_author"])
if(MSG.is_admin_message)
alert("This message was created by a Nanotrasen Officer. You cannot censor its author.","Ok")
@@ -646,6 +708,9 @@ GLOBAL_LIST_EMPTY(allCasters)
MSG.toggleCensorAuthor()
updateUsrDialog()
else if(href_list["censor_channel_story_body"])
if(isobserver(usr) && !canGhostWrite(usr,src,"tried to censor a story"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
var/datum/newscaster/feed_message/MSG = locate(href_list["censor_channel_story_body"])
if(MSG.is_admin_message)
alert("This channel was created by a Nanotrasen Officer. You cannot censor it.","Ok")
@@ -653,11 +718,17 @@ GLOBAL_LIST_EMPTY(allCasters)
MSG.toggleCensorBody()
updateUsrDialog()
else if(href_list["pick_d_notice"])
if(isobserver(usr) && !canGhostWrite(usr,src,""))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
var/datum/newscaster/feed_channel/FC = locate(href_list["pick_d_notice"])
viewing_channel = FC
screen=13
updateUsrDialog()
else if(href_list["toggle_d_notice"])
if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set a D-notice"))
to_chat(usr, "<span class='warning'>You can't do that.</span>")
return
var/datum/newscaster/feed_channel/FC = locate(href_list["toggle_d_notice"])
if(FC.is_admin_channel)
alert("This channel was created by a Nanotrasen Officer. You cannot place a D-Notice upon it.","Ok")
@@ -805,6 +876,12 @@ GLOBAL_LIST_EMPTY(allCasters)
picture = selection
/obj/machinery/newscaster/proc/scan_user(mob/living/user)
if(active_user)
if(active_user != user)
if(get_dist(active_user,src)<=1)
if(!isobserver(active_user))
to_chat(user, "<span class='warning'>Wait for [active_user] to finish and move away.</span>")
return
if(ishuman(user))
var/mob/living/carbon/human/human_user = user
if(human_user.wear_id)
@@ -824,9 +901,14 @@ GLOBAL_LIST_EMPTY(allCasters)
else if(issilicon(user))
var/mob/living/silicon/ai_user = user
scanned_user = "[ai_user.name] ([ai_user.job])"
else if (IsAdminGhost(user))
scanned_user = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]"
else if (isobserver(user))
scanned_user = "Space-Time Anomaly #[rand(0,9)][rand(0,9)][rand(0,9)]"
else
throw EXCEPTION("Invalid user for this proc")
return
active_user = user
/obj/machinery/newscaster/proc/print_paper()
SSblackbox.record_feedback("amount", "newspapers_printed", 1)
@@ -859,7 +941,6 @@ GLOBAL_LIST_EMPTY(allCasters)
say("Attention! Wanted issue distributed!")
playsound(loc, 'sound/machines/warning-buzzer.ogg', 75, 1)
/obj/item/newspaper
name = "newspaper"
desc = "An issue of The Griffon, the newspaper circulating aboard Nanotrasen Space Stations."
@@ -348,6 +348,26 @@
spark_system.start() //creates some sparks because they look cool
qdel(cover) //deletes the cover - no need on keeping it there!
//turret healing
/obj/machinery/porta_turret/examine(mob/user)
. = ..()
if(obj_integrity < max_integrity)
. += "<span class='notice'>Use a welder to fix it.</span>"
/obj/machinery/porta_turret/welder_act(mob/living/user, obj/item/I)
. = TRUE
if(obj_integrity < max_integrity)
if(!I.tool_start_check(user, amount=0))
return
user.visible_message("[user] is welding the turret.", \
"<span class='notice'>You begin repairing the turret...</span>", \
"<span class='italics'>You hear welding.</span>")
if(I.use_tool(src, user, 40, volume=50))
obj_integrity = max_integrity
user.visible_message("[user.name] has repaired [src].", \
"<span class='notice'>You finish repairing the turret.</span>")
else
to_chat(user, "<span class='notice'>The turret doesn't need repairing.</span>")
/obj/machinery/porta_turret/process()
@@ -672,6 +692,7 @@
lethal_projectile_sound = 'sound/weapons/laser.ogg'
desc = "An energy blaster auto-turret."
/obj/machinery/porta_turret/syndicate/energy/heavy
icon_state = "standard_stun"
base_icon_state = "standard"
@@ -683,6 +704,11 @@
lethal_projectile_sound = 'sound/weapons/lasercannonfire.ogg'
desc = "An energy blaster auto-turret."
/obj/machinery/porta_turret/syndicate/energy/pirate
max_integrity = 260
integrity_failure = 20
armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
/obj/machinery/porta_turret/syndicate/setup()
return
@@ -839,7 +865,7 @@
/obj/machinery/turretid/examine(mob/user)
. = ..()
if(issilicon(user) && (!stat & BROKEN))
if(hasSiliconAccessInArea(user) && (!stat & BROKEN))
. += "<span class='notice'>Ctrl-click [src] to [ enabled ? "disable" : "enable"] turrets.</span>"
. += "<span class='notice'>Alt-click [src] to set turrets to [ lethal ? "stun" : "kill"].</span>"
@@ -854,7 +880,7 @@
to_chat(user, "You link \the [M.buffer] with \the [src]")
return
if (issilicon(user))
if (hasSiliconAccessInArea(user))
return attack_hand(user)
if ( get_dist(src, user) == 0 ) // trying to unlock the interface
@@ -895,7 +921,7 @@
/obj/machinery/turretid/ui_interact(mob/user)
. = ..()
if ( get_dist(src, user) > 0 )
if ( !(issilicon(user) || IsAdminGhost(user)) )
if ( !(hasSiliconAccessInArea(user) || IsAdminGhost(user)) )
to_chat(user, "<span class='notice'>You are too far away.</span>")
user.unset_machine()
user << browse(null, "window=turretid")
@@ -903,10 +929,10 @@
var/t = ""
if(locked && !(issilicon(user) || IsAdminGhost(user)))
if(locked && !(hasSiliconAccessInArea(user) || IsAdminGhost(user)))
t += "<div class='notice icon'>Swipe ID card to unlock interface</div>"
else
if(!issilicon(user) && !IsAdminGhost(user))
if(!hasSiliconAccessInArea(user) && !IsAdminGhost(user))
t += "<div class='notice icon'>Swipe ID card to lock interface</div>"
t += "Turrets [enabled?"activated":"deactivated"] - <A href='?src=[REF(src)];toggleOn=1'>[enabled?"Disable":"Enable"]?</a><br>"
t += "Currently set for [lethal?"lethal":"stun repeatedly"] - <A href='?src=[REF(src)];toggleLethal=1'>Change to [lethal?"Stun repeatedly":"Lethal"]?</a><br>"
@@ -920,7 +946,7 @@
if(..())
return
if (locked)
if(!(issilicon(usr) || IsAdminGhost(usr)))
if(!(hasSiliconAccessInArea(usr) || IsAdminGhost(usr)))
to_chat(usr, "Control panel is locked!")
return
if (href_list["toggleOn"])
+2 -2
View File
@@ -124,7 +124,7 @@
. = ..()
if(.)
return
if(locked && !issilicon(user))
if(locked && !hasSiliconAccessInArea(user))
to_chat(user, "<span class='warning'>The machine is locked, you are unable to use it!</span>")
return
if(panel_open)
@@ -370,7 +370,7 @@
if(!anchored)
to_chat(user, "<span class='warning'>\The [src] needs to be firmly secured to the floor first!</span>")
return
if(locked && !issilicon(user))
if(locked && !hasSiliconAccessInArea(user))
to_chat(user, "<span class='warning'>The controls are locked!</span>")
return
if(!power)
@@ -196,7 +196,7 @@
var/newnet = stripped_input(usr, "Which network do you want to view?", "Comm Monitor", network)
if(newnet && ((usr in range(1, src)) || issilicon(usr)))
if(newnet && ((usr in range(1, src)) || hasSiliconAccessInArea(usr)))
if(length(newnet) > 15)
temp = "<font color = #D70B00>- FAILED: NETWORK TAG STRING TOO LENGHTLY -</font color>"
@@ -260,7 +260,7 @@
if(..())
return
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr))
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr))
//Authenticate
if (href_list["auth"])
if(LINKED_SERVER_NONRESPONSIVE)
@@ -108,7 +108,7 @@
if(href_list["network"])
var/newnet = stripped_input(usr, "Which network do you want to view?", "Comm Monitor", network)
if(newnet && ((usr in range(1, src)) || issilicon(usr)))
if(newnet && ((usr in range(1, src)) || hasSiliconAccessInArea(usr)))
if(length(newnet) > 15)
temp = "<font color = #D70B00>- FAILED: NETWORK TAG STRING TOO LENGHTLY -</font color>"
@@ -30,7 +30,7 @@
/obj/machinery/telecomms/ui_interact(mob/user)
. = ..()
// You need a multitool to use this, or be silicon
if(!issilicon(user))
if(!hasSiliconAccessInArea(user))
// istype returns false if the value is null
if(!istype(user.get_active_held_item(), /obj/item/multitool))
return
@@ -97,7 +97,7 @@
var/obj/item/multitool/P = null
// Let's double check
if(!issilicon(user) && istype(user.get_active_held_item(), /obj/item/multitool))
if(!hasSiliconAccessInArea(user) && istype(user.get_active_held_item(), /obj/item/multitool))
P = user.get_active_held_item()
else if(isAI(user))
var/mob/living/silicon/ai/U = user
@@ -162,7 +162,7 @@
if(..())
return
if(!issilicon(usr))
if(!hasSiliconAccessInArea(usr))
if(!istype(usr.get_active_held_item(), /obj/item/multitool))
return
@@ -270,6 +270,6 @@
updateUsrDialog()
/obj/machinery/telecomms/proc/canAccess(mob/user)
if(issilicon(user) || in_range(user, src))
if(hasSiliconAccessInArea(user) || in_range(user, src))
return TRUE
return FALSE
+1 -1
View File
@@ -27,7 +27,7 @@
/obj/machinery/transformer/examine(mob/user)
. = ..()
if(cooldown && (issilicon(user) || isobserver(user)))
if(cooldown && (hasSiliconAccessInArea(user) || isobserver(user)))
. += "It will be ready in [DisplayTimeText(cooldown_timer - world.time)]."
/obj/machinery/transformer/Destroy()
+2 -1
View File
@@ -57,6 +57,7 @@
var/poster_item_name = "hypothetical poster"
var/poster_item_desc = "This hypothetical poster item should not exist, let's be honest here."
var/poster_item_icon_state = "rolled_poster"
var/poster_item_type = /obj/item/poster
/obj/structure/sign/poster/Initialize()
. = ..()
@@ -114,7 +115,7 @@
/obj/structure/sign/poster/proc/roll_and_drop(loc)
pixel_x = 0
pixel_y = 0
var/obj/item/poster/P = new(loc, src)
var/obj/item/poster/P = new poster_item_type(loc, src)
forceMove(P)
return P
@@ -10,7 +10,7 @@
var/list/gibamounts = list() //amount to spawn for each gib decal type we'll spawn.
var/list/gibdirections = list() //of lists of possible directions to spread each gib decal type towards.
/obj/effect/gibspawner/Initialize(mapload, mob/living/source_mob, list/datum/disease/diseases)
/obj/effect/gibspawner/Initialize(mapload, mob/living/source_mob, list/datum/disease/diseases, list/blood_dna)
. = ..()
if(gibtypes.len != gibamounts.len)
stack_trace("Gib list amount length mismatch!")
@@ -33,7 +33,7 @@
var/body_coloring = ""
if(source_mob)
if(!issilicon(source_mob))
dna_to_add = source_mob.get_blood_dna_list() //ez pz
dna_to_add = blood_dna || source_mob.get_blood_dna_list() //ez pz
if(ishuman(source_mob))
var/mob/living/carbon/human/H = source_mob
if(H.dna.species.use_skintones)
@@ -163,6 +163,10 @@ again.
icon_state = "plastitaniumwindow_spawner"
spawn_list = list(/obj/structure/grille, /obj/structure/window/plastitanium)
//plastitanium pirate window
/obj/effect/spawner/structure/window/plastitanium/pirate
spawn_list = list(/obj/structure/grille, /obj/structure/window/plastitanium/pirate)
//ice window
@@ -8,6 +8,7 @@
/obj/structure/sign/poster/wanted
var/wanted_name
poster_item_type = /obj/item/poster/wanted
/obj/structure/sign/poster/wanted/Initialize(mapload, icon/person_icon, person_name, description)
. = ..()
+15 -1
View File
@@ -128,6 +128,9 @@
return
. = ..()
/obj/item/card/emag/empty
uses = 0
/obj/item/emagrecharge
name = "electromagnet charging device"
desc = "A small cell with two prongs lazily jabbed into it. It looks like it's made for charging the small batteries found in electromagnetic devices, sadly this can't be recharged like a normal cell."
@@ -538,4 +541,15 @@ update_label("John Doe", "Clowny")
id_color = "#0000FF"
/obj/item/card/id/knight/captain
id_color = "#FFD700"
id_color = "#FFD700"
/obj/item/card/id/debug
name = "\improper Debug ID"
desc = "A debug ID card. Has ALL the all access, you really shouldn't have this."
icon_state = "ert_janitor"
assignment = "Jannie"
/obj/item/card/id/debug/Initialize()
access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access()
. = ..()
@@ -238,6 +238,14 @@
/obj/machinery/vending/cigarette = "ShadyCigs Deluxe",
/obj/machinery/vending/games = "\improper Good Clean Fun",
/obj/machinery/vending/autodrobe = "AutoDrobe",
/obj/machinery/vending/assist = "\improper Vendomat",
/obj/machinery/vending/engivend = "\improper Engi-Vend",
/obj/machinery/vending/engivend = "\improper YouTool",
/obj/machinery/vending/sustenance = "\improper Sustenance Vendor",
/obj/machinery/vending/dinnerware = "\improper Plasteel Chef's Dinnerware Vendor",
/obj/machinery/vending/cart = "\improper PTech",
/obj/machinery/vending/hydronutrients = "\improper NutriMax",
/obj/machinery/vending/hydroseeds = "\improper MegaSeed Servitor",
/obj/machinery/vending/wardrobe/sec_wardrobe = "SecDrobe",
/obj/machinery/vending/wardrobe/medi_wardrobe = "MediDrobe",
/obj/machinery/vending/wardrobe/engi_wardrobe = "EngiDrobe",
+102
View File
@@ -0,0 +1,102 @@
/* This file contains standalone items for debug purposes. */
/obj/item/debug/human_spawner
name = "human spawner"
desc = "Spawn a human by aiming at a turf and clicking. Use in hand to change type."
icon = 'icons/obj/guns/magic.dmi'
icon_state = "nothingwand"
item_state = "wand"
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
w_class = WEIGHT_CLASS_SMALL
var/datum/species/selected_species
var/valid_species = list()
/obj/item/debug/human_spawner/afterattack(atom/target, mob/user, proximity)
..()
if(isturf(target))
var/mob/living/carbon/human/H = new /mob/living/carbon/human(target)
if(selected_species)
H.set_species(selected_species)
/obj/item/debug/human_spawner/attack_self(mob/user)
..()
var/choice = input("Select a species", "Human Spawner", null) in GLOB.species_list
selected_species = GLOB.species_list[choice]
/* Revive this once we purge all the istype checks for tools for tool_behaviour
/obj/item/debug/omnitool
name = "omnitool"
desc = "The original hypertool, born before them all. Use it in hand to unleash it's true power."
icon = 'icons/obj/device.dmi'
icon_state = "hypertool"
item_state = "hypertool"
toolspeed = 0.1
tool_behaviour = null
/obj/item/debug/omnitool/examine()
. = ..()
. += " The mode is: [tool_behaviour]"
/obj/item/debug/omnitool/proc/check_menu(mob/user)
if(!istype(user))
return FALSE
if(user.incapacitated() || !user.Adjacent(src))
return FALSE
return TRUE
/obj/item/debug/omnitool/attack_self(mob/user)
if(!user)
return
var/list/tool_list = list(
"Crowbar" = image(icon = 'icons/obj/tools.dmi', icon_state = "crowbar"),
"Multitool" = image(icon = 'icons/obj/device.dmi', icon_state = "multitool"),
"Screwdriver" = image(icon = 'icons/obj/tools.dmi', icon_state = "screwdriver_map"),
"Wirecutters" = image(icon = 'icons/obj/tools.dmi', icon_state = "cutters_map"),
"Wrench" = image(icon = 'icons/obj/tools.dmi', icon_state = "wrench"),
"Welding Tool" = image(icon = 'icons/obj/tools.dmi', icon_state = "miniwelder"),
"Analyzer" = image(icon = 'icons/obj/device.dmi', icon_state = "analyzer"),
"Mining Tool" = image(icon = 'icons/obj/mining.dmi', icon_state = "minipick"),
"Shovel" = image(icon = 'icons/obj/mining.dmi', icon_state = "spade"),
"Retractor" = image(icon = 'icons/obj/surgery.dmi', icon_state = "retractor"),
"Hemostat" = image(icon = 'icons/obj/surgery.dmi', icon_state = "hemostat"),
"Cautery" = image(icon = 'icons/obj/surgery.dmi', icon_state = "cautery"),
"Drill" = image(icon = 'icons/obj/surgery.dmi', icon_state = "drill"),
"Scalpel" = image(icon = 'icons/obj/surgery.dmi', icon_state = "scalpel"),
"Saw" = image(icon = 'icons/obj/surgery.dmi', icon_state = "saw")
)
var/tool_result = show_radial_menu(user, src, tool_list, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE)
if(!check_menu(user))
return
switch(tool_result)
if("Crowbar")
tool_behaviour = TOOL_CROWBAR
if("Multitool")
tool_behaviour = TOOL_MULTITOOL
if("Screwdriver")
tool_behaviour = TOOL_SCREWDRIVER
if("Wirecutters")
tool_behaviour = TOOL_WIRECUTTER
if("Wrench")
tool_behaviour = TOOL_WRENCH
if("Welding Tool")
tool_behaviour = TOOL_WELDER
if("Analyzer")
tool_behaviour = TOOL_ANALYZER
if("Mining Tool")
tool_behaviour = TOOL_MINING
if("Shovel")
tool_behaviour = TOOL_SHOVEL
if("Retractor")
tool_behaviour = TOOL_RETRACTOR
if("Hemostat")
tool_behaviour = TOOL_HEMOSTAT
if("Cautery")
tool_behaviour = TOOL_CAUTERY
if("Drill")
tool_behaviour = TOOL_DRILL
if("Scalpel")
tool_behaviour = TOOL_SCALPEL
if("Saw")
tool_behaviour = TOOL_SAW
*/
+1
View File
@@ -8,6 +8,7 @@
var/mob/owner = null //Carp doesn't attack owner, set when using in hand
var/owned = 0 //Boolean, no owner to begin with
var/mobtype = /mob/living/simple_animal/hostile/carp //So admins can change what mob spawns via var fuckery
can_random_spawn = FALSE
//Attack self
/obj/item/toy/plush/carpplushie/dehy_carp/attack_self(mob/user)
+3 -3
View File
@@ -721,7 +721,7 @@ GLOBAL_LIST_EMPTY(PDAs)
return
/obj/item/pda/proc/remove_id(mob/user)
if(issilicon(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
if(hasSiliconAccessInArea(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
do_remove_id(user)
@@ -916,7 +916,7 @@ GLOBAL_LIST_EMPTY(PDAs)
remove_pen()
/obj/item/pda/proc/toggle_light()
if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE))
if(hasSiliconAccessInArea(usr) || !usr.canUseTopic(src, BE_CLOSE))
return
if(fon)
fon = FALSE
@@ -928,7 +928,7 @@ GLOBAL_LIST_EMPTY(PDAs)
/obj/item/pda/proc/remove_pen()
if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
if(hasSiliconAccessInArea(usr) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if(inserted_item)
+3 -2
View File
@@ -100,7 +100,8 @@
bot_access_flags = CLEAN_BOT
/obj/item/cartridge/lawyer
name = "\improper P.R.O.V.E. cartridge"
name = "\improper S.P.A.M. cartridge"
desc = "Introducing the Station Public Announcement Messenger cartridge, featuring the unique ability to broadcast-mark messages, designed for lawyers across Nanotrasen to advertise their useful and important services."
icon_state = "cart-law"
access = CART_SECURITY
spam_enabled = 1
@@ -608,7 +609,7 @@ Code:
/obj/item/cartridge/Topic(href, href_list)
..()
if(!usr.canUseTopic(src, !issilicon(usr)))
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
usr.unset_machine()
usr << browse(null, "window=pda")
return
@@ -82,8 +82,9 @@
/obj/item/implant/explosive/proc/boom_goes_the_weasel()
explosion(get_turf(imp_in ? imp_in : src), heavy, medium, weak, weak, flame_range = weak)
imp_in?.gib(TRUE)
qdel(src)
if(!QDELETED(imp_in))
imp_in.gib(TRUE)
qdel(src)
/obj/item/implant/explosive/macro
name = "macrobomb implant"
@@ -0,0 +1,121 @@
#define HIJACK_APC_MAX_AMOUNT 5
/obj/item/implant/hijack
name = "hijack implant"
desc = "Allows you to control the machinery in a room by hacking into the APC."
actions_types = list(/datum/action/item_action/hands_free/activate, /datum/action/item_action/removeAPCs, /datum/action/item_action/accessAPCs, /datum/action/item_action/stealthmodetoggle)
activated = 1
var/toggled = FALSE
icon_state = "hijack"
var/eye_color
var/stealthmode = FALSE
var/stealthcooldown = 0
var/hijacking = FALSE
/obj/item/implant/hijack/activate()
. = ..()
toggled = !toggled
imp_in.click_intercept = toggled ? src : null
imp_in.siliconaccesstoggle = toggled ? TRUE : FALSE
to_chat(imp_in,"<span class='notice'>You turn [toggled ? "on" : "off"] [src]'s silicon interactions.</span>")
toggle_eyes()
/obj/item/implant/hijack/proc/toggle_eyes()
if (!ishuman(imp_in))
return
var/on = toggled && !stealthmode
var/mob/living/carbon/human/H = imp_in
H.eye_color = on ? "ff0" : eye_color
H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
H.update_body()
/obj/item/implant/hijack/implant(mob/living/target, mob/user, silent = FALSE)
if(..())
ADD_TRAIT(target, TRAIT_HIJACKER, "implant")
if (ishuman(target))
var/mob/living/carbon/human/H = target
eye_color = H.eye_color
return TRUE
/obj/item/implant/hijack/removed(mob/target, silent = FALSE, special = 0)
if(..())
REMOVE_TRAIT(target, TRAIT_HIJACKER, "implant")
for (var/area/area in imp_in.siliconaccessareas)
imp_in.toggleSiliconAccessArea(area)
var/obj/machinery/power/apc/apc = area.get_apc()
if (apc)
apc.hijacker = null
apc.set_hijacked_lighting()
apc.update_icon()
if (ishuman(target))
var/mob/living/carbon/human/H = target
H.eye_color = eye_color
return TRUE
/obj/item/implant/hijack/proc/InterceptClickOn(mob/living/user,params,atom/object)
if (isitem(object) || !toggled || user.incapacitated())
return
if (stealthmode == FALSE && istype(object,/obj/machinery/power/apc) && !user.CanReach(object))
if (hijack_remotely(object))
return
if (stealthmode && !user.CanReach(object))
return
if (!object.hasSiliconAccessInArea(imp_in))
return
var/list/modifiers = params2list(params)
imp_in.face_atom(object)
if (modifiers["shift"] && modifiers["ctrl"])
object.AICtrlShiftClick(imp_in)
return TRUE
if (modifiers["shift"])
object.AIShiftClick(imp_in)
return TRUE
if (modifiers["ctrl"])
object.AICtrlClick(imp_in)
return TRUE
if (modifiers["alt"])
object.AIAltClick(imp_in)
return TRUE
if (user.get_active_held_item())
return
if (user.CanReach(object))
object.attack_robot(imp_in)
else
object.attack_ai(imp_in)
return TRUE
/obj/item/implant/hijack/proc/hijack_remotely(obj/machinery/power/apc/apc)
if (apc.hijacker || hijacking)
return FALSE //can't remotely hijack an already hijacked APC
hijacking = TRUE
to_chat(imp_in, "<span class='notice'>Establishing remote connection with APC.</span>")
if (!do_after(imp_in, 4 SECONDS,target=apc))
to_chat(imp_in, "<span class='warning'>Aborting.</span>")
hijacking = FALSE
return TRUE
if (LAZYLEN(imp_in.siliconaccessareas) >= HIJACK_APC_MAX_AMOUNT)
to_chat(src,"<span class='warning'>You are connected to too many APCs! Too many more will fry your brain.</span>")
hijacking = FALSE
return TRUE
imp_in.light_power = 2
imp_in.light_range = 2
imp_in.light_color = COLOR_YELLOW
imp_in.update_light()
imp_in.visible_message("<span class='warning'>[imp_in] starts glowing a with a hollow yellow light!</span>")
to_chat(imp_in, "<span class='notice'>Beginning hijack of APC.</span>")
if (do_after(imp_in, 21 SECONDS,target=apc))
apc.hijacker = imp_in
stealthmode = FALSE
apc.set_hijacked_lighting()
imp_in.toggleSiliconAccessArea(apc.area)
apc.update_icon()
stealthcooldown = world.time + 1 MINUTES + 30 SECONDS
toggle_eyes()
else
to_chat(imp_in, "<span class='warning'>Aborting.</span>")
hijacking = FALSE
imp_in.light_power = 0
imp_in.light_range = 0
imp_in.light_color = COLOR_YELLOW
imp_in.update_light()
return TRUE
@@ -74,4 +74,8 @@
/obj/item/implanter/stealth
name = "implanter (stealth)"
imp_type = /obj/item/implant/stealth
imp_type = /obj/item/implant/stealth
/obj/item/implanter/hijack
name = "implanter (hijack)"
imp_type = /obj/item/implant/hijack
+108 -400
View File
@@ -31,7 +31,16 @@
var/normal_desc
//--end of love :'(--
/obj/item/toy/plush/Initialize()
var/snowflake_id //if we set from a config snowflake plushie.
var/can_random_spawn = TRUE //if this is FALSE, don't spawn this for random plushies.
/obj/item/toy/plush/random_snowflake/Initialize(mapload, set_snowflake_id)
. = ..()
var/list/configlist = CONFIG_GET(keyed_list/snowflake_plushies)
var/id = pick(configlist)
set_snowflake_from_config(id)
/obj/item/toy/plush/Initialize(mapload, set_snowflake_id)
. = ..()
AddComponent(/datum/component/squeak, squeak_override)
@@ -50,6 +59,9 @@
normal_desc = desc
if(set_snowflake_id)
set_snowflake_from_config(set_snowflake_id)
/obj/item/toy/plush/Destroy()
QDEL_NULL(grenade)
@@ -97,6 +109,44 @@
return ..()
/obj/item/toy/plush/proc/set_snowflake_from_config(id)
var/list/configlist = CONFIG_GET(keyed_list/snowflake_plushies)
var/list/jsonlist = configlist[id]
ASSERT(jsonlist)
jsonlist = json_decode(jsonlist)
if(jsonlist["inherit_from"])
var/path = text2path(jsonlist["inherit_from"])
if(!ispath(path, /obj/item/toy/plush))
stack_trace("Invalid path for inheritance")
else
var/obj/item/toy/plush/P = new path //can't initial() lists
name = P.name
desc = P.desc
icon_state = P.icon_state
item_state = P.item_state
icon = P.icon
squeak_override = P.squeak_override
attack_verb = P.attack_verb
gender = P.gender
qdel(P)
if(jsonlist["name"])
name = jsonlist["name"]
if(jsonlist["desc"])
desc = jsonlist["desc"]
if(jsonlist["gender"])
gender = jsonlist["gender"]
if(jsonlist["icon_state"])
icon_state = jsonlist["icon_state"]
item_state = jsonlist["item_state"]
icon = 'config/plushies/sprites.dmi'
if(jsonlist["attack_verb"])
attack_verb = jsonlist["attack_verb"]
if(jsonlist["squeak_override"])
squeak_override = jsonlist["squeak_override"]
if(squeak_override)
var/datum/component/squeak/S = GetComponent(/datum/component/squeak)
S?.override_squeak_sounds = squeak_override
/obj/item/toy/plush/handle_atom_del(atom/A)
if(A == grenade)
grenade = null
@@ -367,13 +417,22 @@
if(mood_message)
desc += mood_message
GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths())
/proc/valid_plushie_paths()
. = list()
for(var/i in subtypesof(/obj/item/toy/plush))
var/obj/item/toy/plush/abstract = i
if(!initial(abstract.can_random_spawn))
continue
. += i
/obj/item/toy/plush/random
name = "Illegal plushie"
desc = "Something fucked up"
var/blacklisted_plushes = list(/obj/item/toy/plush/carpplushie/dehy_carp, /obj/item/toy/plush/awakenedplushie, /obj/item/toy/plush/random)
can_random_spawn = FALSE
/obj/item/toy/plush/random/Initialize()
var/newtype = pick(subtypesof(/obj/item/toy/plush) - typecacheof(blacklisted_plushes))
var/newtype = prob(CONFIG_GET(number/snowflake_plushie_prob))? /obj/item/toy/plush/random_snowflake : pick(GLOB.valid_plushie_paths)
new newtype(loc)
return INITIALIZE_HINT_QDEL
@@ -504,115 +563,12 @@
attack_verb = list("clawed", "hissed", "tail slapped")
squeak_override = list('sound/weapons/slash.ogg' = 1)
/obj/item/toy/plush/lizardplushie/durgit
icon_state = "durgit"
item_state = "durgit"
squeak_override = list('modular_citadel/sound/voice/weh.ogg' = 1) //Durgit's the origin of the sound
/obj/item/toy/plush/lizardplushie/rio
icon_state = "rio"
item_state = "rio"
/obj/item/toy/plush/lizardplushie/dan
icon_state = "dan"
item_state = "dan"
/obj/item/toy/plush/lizardplushie/urinsu
icon_state = "urinsu"
item_state = "urinsu"
/obj/item/toy/plush/lizardplushie/arfrehn
icon_state = "arfrehn"
item_state = "arfrehn"
/obj/item/toy/plush/lizardplushie/soars
icon_state = "soars"
item_state = "soars"
/obj/item/toy/plush/lizardplushie/ghostie
icon_state = "ghostie"
item_state = "ghostie"
/obj/item/toy/plush/lizardplushie/amber
icon_state = "amber"
item_state = "amber"
/obj/item/toy/plush/lizardplushie/cyan
icon_state = "cyan"
item_state = "cyan"
/obj/item/toy/plush/lizardplushie/meena
icon_state = "meena"
item_state = "meena"
/obj/item/toy/plush/lizardplushie/stalks
icon_state = "stalks"
item_state = "stalks"
/obj/item/toy/plush/lizardplushie/kobold
name = "kobold plushie"
desc = "An adorable stuffed toy that resembles a kobold."
icon_state = "kobold"
item_state = "kobold"
/obj/item/toy/plush/lizardplushie/gorgi
icon_state = "gorgi"
item_state = "gorgi"
/obj/item/toy/plush/lizardplushie/almaz
icon_state = "almaz"
item_state = "almaz"
squeak_override = list('modular_citadel/sound/voice/raptor_purr.ogg' = 1)
/obj/item/toy/plush/lizardplushie/garou
icon_state = "garou"
item_state = "garou"
/obj/item/toy/plush/lizardplushie/augments
icon_state = "augments"
item_state = "augments"
squeak_override = list('modular_citadel/sound/voice/weh.ogg' = 1) //I have no mouth and I must weh
attack_verb = list("hugged", "patted", "snugged", "booped")
/obj/item/toy/plush/lizardplushie/xekov
icon_state = "xekov"
item_state = "xekov"
/obj/item/toy/plush/lizardplushie/greg
icon_state = "greg"
item_state = "greg"
/obj/item/toy/plush/lizardplushie/sin
icon_state = "sin"
item_state = "sin"
desc = "An adorable stuffed toy that resembles a lizardperson.. It faintly smells of sulfur."
/obj/item/toy/plush/lizardplushie/ends
icon_state = "ends"
item_state = "ends"
/obj/item/toy/plush/lizardplushie/lyssa
icon_state = "lyssa"
item_state = "lyssa"
/obj/item/toy/plush/snakeplushie
name = "snake plushie"
desc = "An adorable stuffed toy that resembles a snake. Not to be mistaken for the real thing."
icon_state = "plushie_snake"
item_state = "plushie_snake"
attack_verb = list("bitten", "hissed", "tail slapped")
squeak_override = list('modular_citadel/sound/voice/hiss.ogg' = 1)
/obj/item/toy/plush/snakeplushie/sasha
icon_state = "sasha"
item_state = "sasha"
/obj/item/toy/plush/snakeplushie/shay
icon_state = "shay"
item_state = "shay"
/obj/item/toy/plush/snakeplushie/vulken
icon_state = "vulken"
item_state = "vulken"
/obj/item/toy/plush/nukeplushie
name = "operative plushie"
desc = "A stuffed toy that resembles a syndicate nuclear operative. The tag claims operatives to be purely fictitious."
@@ -630,29 +586,17 @@
squeak_override = list('sound/effects/blobattack.ogg' = 1)
gender = FEMALE //given all the jokes and drawings, I'm not sure the xenobiologists would make a slimeboy
/obj/item/toy/plush/slimeplushie/annie
desc = "An adorable stuffed toy that resembles a slimey crewmember."
icon_state = "annie"
item_state = "annie"
/obj/item/toy/plush/slimeplushie/paxton
desc = "An adorable stuffed toy that resembles a slimey crewmember."
icon_state = "paxton"
item_state = "paxton"
attack_verb = list("CQC'd", "jabroni'd", "powergamed", "robusted", "cakehatted")
gender = MALE
/obj/item/toy/plush/awakenedplushie
name = "awakened plushie"
desc = "An ancient plushie that has grown enlightened to the true nature of reality."
icon_state = "plushie_awake"
item_state = "plushie_awake"
can_random_spawn = FALSE
/obj/item/toy/plush/awakenedplushie/ComponentInitialize()
. = ..()
AddComponent(/datum/component/edit_complainer)
/obj/item/toy/plush/beeplushie
name = "bee plushie"
desc = "A cute toy that resembles an even cuter bee."
@@ -668,21 +612,7 @@
icon_state = "bumble"
item_state = "bumble"
squeak_override = list('modular_citadel/sound/voice/mothsqueak.ogg' = 1)
/obj/item/toy/plush/mothplushie/nameko
icon_state = "nameko"
item_state = "nameko"
/obj/item/toy/plush/mothplushie/suru
icon_state = "suru"
item_state = "suru"
/obj/item/toy/plush/xeno
name = "xenohybrid plushie"
desc = "An adorable stuffed toy that resmembles a xenomorphic crewmember."
icon_state = "seras"
item_state = "seras"
squeak_override = list('sound/voice/hiss2.ogg' = 1)
can_random_spawn = FALSE
/obj/item/toy/plush/lampplushie
name = "lamp plushie"
@@ -736,20 +666,6 @@
icon_state = "scrubpuppy"
item_state = "scrubpuppy"
/obj/item/toy/plush/borgplushie/seeking
icon_state = "seeking"
item_state = "seeking"
/obj/item/toy/plush/borgplushie/neeb
icon_state = "neeb"
item_state = "neeb"
/obj/item/toy/plush/borgplushie/bhijn
desc = "An adorable stuffed toy of a IPC."
icon_state = "bhijn"
item_state = "bhijn"
attack_verb = list("closed", "reworked", "merged")
/obj/item/toy/plush/aiplush
name = "AI plushie"
desc = "A little stuffed toy AI core... it appears to be malfunctioning."
@@ -758,246 +674,22 @@
attack_verb = list("hacked", "detonated", "overloaded")
squeak_override = list('sound/machines/beep.ogg' = 9, 'sound/machines/buzz-two.ogg' = 1)
/obj/item/toy/plush/bird
name = "bird plushie"
desc = "An adorable stuffed plushie that resembles an avian."
icon_state = "sylas"
item_state = "sylas"
attack_verb = list("peeped", "beeped", "poofed")
squeak_override = list('modular_citadel/sound/voice/peep.ogg' = 1)
/obj/item/toy/plush/bird/esela
icon_state = "esela"
item_state = "esela"
/obj/item/toy/plush/bird/jahonna
icon_state = "jahonna"
item_state = "jahonna"
/obj/item/toy/plush/bird/krick
icon_state = "krick"
item_state = "krick"
/obj/item/toy/plush/bird/birddi
icon_state = "birddi"
item_state = "birddi"
/obj/item/toy/plush/bird/jewel
icon_state = "jewel"
item_state = "jewel"
/obj/item/toy/plush/sergal
name = "sergal plushie"
desc = "An adorable stuffed plushie that resembles a sagaru."
icon_state = "faux"
item_state = "faux"
squeak_override = list('modular_citadel/sound/voice/merp.ogg' = 1)
/obj/item/toy/plush/sergal/gladwyn
icon_state = "gladwyn"
item_state = "gladwyn"
/obj/item/toy/plush/sergal/jermaine
icon_state = "jermaine"
item_state = "jermaine"
/obj/item/toy/plush/mammal
name = "mammal plushie"
desc = "An adorable stuffed toy resembling some sort of crew member."
icon_state = "dubious"
item_state = "dubious"
/obj/item/toy/plush/mammal/gavin
icon_state = "gavin"
item_state = "gavin"
/obj/item/toy/plush/mammal/blep
icon_state = "blep"
item_state = "blep"
/obj/item/toy/plush/mammal/circe
desc = "A luxuriously soft toy that resembles a nine-tailed kitsune."
icon_state = "circe"
item_state = "circe"
attack_verb = list("medicated", "tailhugged", "kissed")
/obj/item/toy/plush/mammal/robin
icon_state = "robin"
item_state = "robin"
/obj/item/toy/plush/mammal/pavel
icon_state = "pavel"
item_state = "pavel"
/obj/item/toy/plush/mammal/mason
icon_state = "mason"
item_state = "mason"
/obj/item/toy/plush/mammal/oten
icon_state = "oten"
item_state = "oten"
/obj/item/toy/plush/mammal/ray
icon_state = "ray"
item_state = "ray"
/obj/item/toy/plush/mammal/redtail
icon_state = "redtail"
item_state = "redtail"
/obj/item/toy/plush/mammal/dawud
icon_state = "dawud"
item_state = "dawud"
/obj/item/toy/plush/mammal/edgar
icon_state = "edgar"
item_state = "edgar"
attack_verb = list("collared", "tricked", "headpatted")
/obj/item/toy/plush/mammal/frank
icon_state = "frank"
item_state = "frank"
/obj/item/toy/plush/mammal/poojawa
icon_state = "poojawa"
item_state = "poojawa"
/obj/item/toy/plush/mammal/hazel
icon_state = "hazel"
item_state = "hazel"
/obj/item/toy/plush/mammal/joker
icon_state = "joker"
item_state = "joker"
/obj/item/toy/plush/mammal/gunther
icon_state = "gunther"
item_state = "gunther"
/obj/item/toy/plush/mammal/fox
icon_state = "fox"
item_state = "fox"
/obj/item/toy/plush/mammal/rae
desc = "An adorable stuffed toy of an artic fox."
icon_state = "rae"
item_state = "rae"
/obj/item/toy/plush/snakeplushie
name = "snake plushie"
desc = "An adorable stuffed toy that resembles a snake. Not to be mistaken for the real thing."
icon_state = "plushie_snake"
item_state = "plushie_snake"
attack_verb = list("bitten", "hissed", "tail slapped")
squeak_override = list('modular_citadel/sound/voice/hiss.ogg' = 1)
/obj/item/toy/plush/mammal/zed
desc = "A masked stuffed toy that resembles a fierce miner. He even comes with his own little crusher!"
icon_state = "zed"
item_state = "zed"
attack_verb = list("ENDED", "CRUSHED", "GNOMED")
/obj/item/toy/plush/mammal/justin
icon_state = "justin"
item_state = "justin"
attack_verb = list("buttslapped", "fixed")
/obj/item/toy/plush/mammal/reece
icon_state = "reece"
item_state = "reece"
attack_verb = list("healed", "cured", "demoted")
/obj/item/toy/plush/mammal/redwood
desc = "An adorable stuffed toy resembling a Nanotrasen Captain. That just happens to be a bunny."
icon_state = "redwood"
item_state = "redwood"
attack_verb = list("ordered", "bapped", "reprimanded")
/obj/item/toy/plush/mammal/marisol
desc = "An adorable stuffed toy resembling a demi-wolf security officer."
icon_state = "marisol"
item_state = "marisol"
attack_verb = list("arrested", "harmbattoned", "lasered")
/obj/item/toy/plush/mammal/minty
desc = "An adorable stuffed toy resembling some sort of crew member. It smells like mint.."
icon_state = "minty"
item_state = "minty"
attack_verb = list("freshened", "brushed")
/obj/item/toy/plush/mammal/dog
desc = "An adorable stuffed toy that resembles a canine."
icon_state = "katlin"
item_state = "katlin"
attack_verb = list("barked", "boofed", "borked")
squeak_override = list(
'modular_citadel/sound/voice/bark1.ogg' = 1,
'modular_citadel/sound/voice/bark2.ogg' = 1
)
/obj/item/toy/plush/mammal/dog/frost
icon_state = "frost"
item_state = "frost"
/obj/item/toy/plush/mammal/dog/atticus
icon_state = "atticus"
item_state = "atticus"
/obj/item/toy/plush/mammal/dog/fletch
icon_state = "fletch"
item_state = "fletch"
/obj/item/toy/plush/mammal/dog/vincent
icon_state = "vincent"
item_state = "vincent"
/obj/item/toy/plush/mammal/dog/zigfried
desc = "An adorable stuffed toy of a very good boy."
icon_state = "zigfried"
item_state = "zigfried"
/obj/item/toy/plush/mammal/dog/nikolai
icon_state = "nikolai"
item_state = "nikolai"
/obj/item/toy/plush/mammal/dog/flynn
icon_state = "flynn"
item_state = "flynn"
/obj/item/toy/plush/mammal/dog/fritz
icon_state = "fritz"
item_state = "fritz"
attack_verb = list("barked", "boofed", "shotgun'd")
obj_flags = UNIQUE_RENAME
unique_reskin = list("Goodboye" = "fritz", "Badboye" = "fritz_bad")
/obj/item/toy/plush/mammal/dog/jesse
desc = "An adorable wolf toy that resembles a cream-colored wolf. He has a little pride flag!"
icon_state = "jesse"
item_state = "jesse"
attack_verb = list("greeted", "merc'd", "howdy'd")
/obj/item/toy/plush/catgirl
name = "feline plushie"
desc = "An adorable stuffed toy that resembles a feline."
icon_state = "bailey"
item_state = "bailey"
attack_verb = list("headbutt", "scritched", "bit")
squeak_override = list('modular_citadel/sound/voice/nya.ogg' = 1)
/obj/item/toy/plush/catgirl/mikeel
desc = "An adorable stuffed toy of some tauric cat person."
icon_state = "mikeel"
item_state = "mikeel"
/obj/item/toy/plush/catgirl/skylar
desc = "An adorable stuffed toy that resembles a degenerate."
icon_state = "skylar2"
item_state = "skylar2"
attack_verb = list("powergamed", "merged", "tabled")
squeak_override = list('sound/effects/meow1.ogg' = 1)
/obj/item/toy/plush/catgirl/drew
icon_state = "drew"
item_state = "drew"
/obj/item/toy/plush/catgirl/trilby
desc = "A masked stuffed toy that resembles a feline scientist."
icon_state = "trilby"
item_state = "trilby"
attack_verb = list("PR'd", "coded", "remembered")
/obj/item/toy/plush/mammal
name = "mammal plushie"
desc = "An adorable stuffed toy resembling some sort of crew member."
can_random_spawn = FALSE
/obj/item/toy/plush/catgirl/fermis
name = "medcat plushie"
@@ -1007,20 +699,36 @@
attack_verb = list("cuddled", "petpatted", "wigglepurred")
squeak_override = list('modular_citadel/sound/voice/merowr.ogg' = 1)
/obj/item/toy/plush/catgirl/mariaf
desc = "An adorable stuffed toy that resembles a very tall cat girl."
icon_state = "mariaf"
item_state = "mariaf"
attack_verb = list("hugged", "stabbed", "licked")
/obj/item/toy/plush/xeno
name = "xenohybrid plushie"
desc = "An adorable stuffed toy that resmembles a xenomorphic crewmember."
squeak_override = list('sound/voice/hiss2.ogg' = 1)
can_random_spawn = FALSE
/obj/item/toy/plush/catgirl/maya
desc = "An adorable stuffed toy that resembles an angry cat girl. She has her own tiny nuke disk!"
icon_state = "maya"
item_state = "maya"
attack_verb = list("nuked", "arrested", "harmbatonned")
/obj/item/toy/plush/bird
name = "bird plushie"
desc = "An adorable stuffed plushie that resembles an avian."
attack_verb = list("peeped", "beeped", "poofed")
squeak_override = list('modular_citadel/sound/voice/peep.ogg' = 1)
can_random_spawn = FALSE
/obj/item/toy/plush/catgirl/marisa
desc = "An adorable stuffed toy that resembles a crew member, or maybe a witch. Having it makes you feel you can win."
icon_state = "marisa"
item_state = "marisa"
attack_verb = list("blasted", "sparked", "dazzled")
/obj/item/toy/plush/sergal
name = "sergal plushie"
desc = "An adorable stuffed plushie that resembles a sagaru."
squeak_override = list('modular_citadel/sound/voice/merp.ogg' = 1)
can_random_spawn = FALSE
/obj/item/toy/plush/mammal/dog
desc = "An adorable stuffed toy that resembles a canine."
attack_verb = list("barked", "boofed", "borked")
squeak_override = list(
'modular_citadel/sound/voice/bark1.ogg' = 1,
'modular_citadel/sound/voice/bark2.ogg' = 1
)
/obj/item/toy/plush/catgirl
name = "feline plushie"
desc = "An adorable stuffed toy that resembles a feline."
attack_verb = list("headbutt", "scritched", "bit")
squeak_override = list('modular_citadel/sound/voice/nya.ogg' = 1)
can_random_spawn = FALSE
@@ -1,7 +1,11 @@
/* Glass stack types
* Contains:
* Glass sheets
* Plasma glass
* Reinforced glass sheets
* Reinforced plasma glass
* Titanium glass
* Plastitanium glass
* Glass shards - TODO: Move this into code/game/object/item/weapons
*/
@@ -373,4 +377,8 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
throwforce = 11
icon_state = "plasmalarge"
materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
icon_prefix = "plasma"
icon_prefix = "plasma"
/obj/item/shard/plasma/alien
name = "alien shard"
desc = "A nasty looking shard of advanced alloy glass."
@@ -401,6 +401,8 @@ GLOBAL_LIST_INIT(abductor_recipes, list ( \
new/datum/stack_recipe("alien bed", /obj/structure/bed/abductor, 2, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("alien locker", /obj/structure/closet/abductor, 2, time = 15, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("alien table frame", /obj/structure/table_frame/abductor, 1, time = 15, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("alien bar stool", /obj/item/chair/stool/bar/alien, 1, time = 20, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("alien stool", /obj/item/chair/stool/alien, 1, time = 20, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("alien airlock assembly", /obj/structure/door_assembly/door_assembly_abductor, 4, time = 20, one_per_turf = 1, on_floor = 1), \
null, \
new/datum/stack_recipe("alien floor tile", /obj/item/stack/tile/mineral/abductor, 1, 4, 20), \
@@ -698,6 +698,16 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \
/*
* Bones
*/
GLOBAL_LIST_INIT(bone_recipes, list(
new /datum/stack_recipe("Bone Dagger", /obj/item/kitchen/knife/combat/bone, 2, time = 20), \
new /datum/stack_recipe("Skull Helmet", /obj/item/clothing/head/helmet/skull, 4, time = 30), \
new /datum/stack_recipe("Bone Armor", /obj/item/clothing/suit/armor/bone, 6, time = 30)))
/obj/item/stack/sheet/bone/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.bone_recipes
. = ..()
/obj/item/stack/sheet/bone
name = "bones"
icon = 'icons/obj/mining.dmi'
@@ -714,6 +724,10 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \
grind_results = list(/datum/reagent/carbon = 10)
merge_type = /obj/item/stack/sheet/bone
/*
* Plastic
*/
GLOBAL_LIST_INIT(plastic_recipes, list(
new /datum/stack_recipe("see-through plastic flaps", /obj/structure/plasticflaps, 5, one_per_turf = TRUE, on_floor = TRUE, time = 40), \
new /datum/stack_recipe("opaque plastic flaps", /obj/structure/plasticflaps/opaque, 5, one_per_turf = TRUE, on_floor = TRUE, time = 40), \
+3
View File
@@ -244,3 +244,6 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
/obj/item/storage/book/bible/syndicate/add_blood_DNA(list/blood_dna)
return FALSE
/obj/item/storage/book/bible/syndicate/empty
uses = 0
+59
View File
@@ -1288,3 +1288,62 @@
/obj/item/storage/box/marshmallow/PopulateContents()
for (var/i in 1 to 5)
new /obj/item/reagent_containers/food/snacks/marshmallow(src)
/obj/item/storage/box/material/PopulateContents() //less uranium because radioactive
var/static/items_inside = list(
/obj/item/stack/sheet/metal/fifty=1,\
/obj/item/stack/sheet/glass/fifty=1,\
/obj/item/stack/sheet/rglass=50,\
/obj/item/stack/sheet/plasmaglass=50,\
/obj/item/stack/sheet/titaniumglass=50,\
/obj/item/stack/sheet/plastitaniumglass=50,\
/obj/item/stack/sheet/plasteel=50,\
/obj/item/stack/sheet/mineral/plastitanium=50,\
/obj/item/stack/sheet/mineral/titanium=50,\
/obj/item/stack/sheet/mineral/gold=50,\
/obj/item/stack/sheet/mineral/silver=50,\
/obj/item/stack/sheet/mineral/plasma=50,\
/obj/item/stack/sheet/mineral/uranium=50,\
/obj/item/stack/sheet/mineral/diamond=50,\
/obj/item/stack/sheet/bluespace_crystal=50,\
/obj/item/stack/sheet/mineral/bananium=50,\
/obj/item/stack/sheet/mineral/wood=50,\
/obj/item/stack/sheet/plastic/fifty=1,\
/obj/item/stack/sheet/runed_metal/fifty=1
)
generate_items_inside(items_inside, src)
/obj/item/storage/box/debugtools
name = "box of debug tools"
icon_state = "syndiebox"
/obj/item/storage/box/debugtools/PopulateContents()
var/static/items_inside = list(
/obj/item/flashlight/emp/debug=1,\
/obj/item/pda=1,\
/obj/item/modular_computer/tablet/preset/advanced=1,\
/obj/item/geiger_counter=1,\
/obj/item/construction/rcd/combat/admin=1,\
/obj/item/pipe_dispenser=1,\
/obj/item/card/emag=1,\
/obj/item/healthanalyzer/advanced=1,\
/obj/item/disk/tech_disk/debug=1,\
/obj/item/uplink/debug=1,\
/obj/item/uplink/nuclear/debug=1,\
/obj/item/storage/box/beakers/bluespace=1,\
/obj/item/storage/box/beakers/variety=1,\
/obj/item/storage/box/material=1,\
/obj/item/storage/belt/medical/surgery_belt_adv
)
generate_items_inside(items_inside, src)
/obj/item/storage/box/beakers/variety
name = "beaker variety box"
/obj/item/storage/box/beakers/variety/PopulateContents()
new /obj/item/reagent_containers/glass/beaker(src)
new /obj/item/reagent_containers/glass/beaker/large(src)
new /obj/item/reagent_containers/glass/beaker/plastic(src)
new /obj/item/reagent_containers/glass/beaker/meta(src)
new /obj/item/reagent_containers/glass/beaker/noreact(src)
new /obj/item/reagent_containers/glass/beaker/bluespace(src)
+1 -1
View File
@@ -189,7 +189,7 @@
L.Knockdown(stunpwr, override_stamdmg = 0)
L.apply_damage(stunpwr*0.55, STAMINA, user.zone_selected)
L.apply_damage(stunpwr*0.5, STAMINA, user.zone_selected)
L.apply_effect(EFFECT_STUTTER, stunforce)
SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK)
if(user)
+2
View File
@@ -453,6 +453,7 @@
force_wielded = 0
attack_verb = list("attacked", "struck", "hit")
total_mass_on = TOTAL_MASS_TOY_SWORD
sharpness = IS_BLUNT
/obj/item/twohanded/dualsaber/toy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
return FALSE
@@ -472,6 +473,7 @@
attack_verb = list("attacked", "struck", "hit")
total_mass_on = TOTAL_MASS_TOY_SWORD
slowdown_wielded = 0
sharpness = IS_BLUNT
/obj/item/twohanded/dualsaber/hypereutactic/toy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
return FALSE
+1 -1
View File
@@ -125,7 +125,7 @@
if ((M.client && M.machine == src))
is_in_use = TRUE
ui_interact(M)
if(isAI(usr) || iscyborg(usr) || IsAdminGhost(usr))
if(isAI(usr) || iscyborg(usr) || IsAdminGhost(usr) || hasSiliconAccessInArea(usr))
if (!(usr in nearby))
if (usr.client && usr.machine==src) // && M.machine == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh.
is_in_use = TRUE
+1 -1
View File
@@ -37,7 +37,7 @@
structureclimber.visible_message("<span class='warning'>[structureclimber] has been knocked off [src].", "You're knocked off [src]!", "You see [structureclimber] get knocked off [src].</span>")
/obj/structure/ui_act(action, params)
..()
. = ..()
add_fingerprint(usr)
/obj/structure/MouseDrop_T(atom/movable/O, mob/user)
@@ -370,6 +370,43 @@
item_state = "stool_bar"
origin_type = /obj/structure/chair/stool/bar
//////////////////////////
//Alien(Disco) Stools!////
//////////////////////////
/obj/structure/chair/stool/alien
name = "alien stool"
desc = "A hard stool made of advanced alien alloy."
icon_state = "stoolalien"
icon = 'icons/obj/abductor.dmi'
item_chair = /obj/item/chair/stool/alien
buildstacktype = /obj/item/stack/sheet/mineral/abductor
buildstackamount = 1
/obj/structure/chair/stool/bar/alien
name = "bronze bar stool"
desc = "A hard bar stool made of advanced alien alloy."
icon_state = "baralien"
icon = 'icons/obj/abductor.dmi'
item_chair = /obj/item/chair/stool/bar/alien
buildstacktype = /obj/item/stack/sheet/mineral/abductor
buildstackamount = 1
/obj/item/chair/stool/alien
name = "stool"
icon_state = "stoolalien_toppled"
item_state = "stoolalien"
icon = 'icons/obj/abductor.dmi'
origin_type = /obj/structure/chair/stool/alien
break_chance = 0 //It's too sturdy.
/obj/item/chair/stool/bar/alien
name = "bar stool"
icon_state = "baralien_toppled"
item_state = "baralien"
icon = 'icons/obj/abductor.dmi'
origin_type = /obj/structure/chair/stool/bar/alien
//////////////////////////
//Brass & Bronze stools!//
//////////////////////////
+8 -2
View File
@@ -8,14 +8,16 @@
max_integrity = 1
armor = list("melee" = 0, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 20)
var/obj/item/holosign_creator/projector
var/init_vis_overlay = TRUE
/obj/structure/holosign/Initialize(mapload, source_projector)
. = ..()
if(source_projector)
projector = source_projector
projector.signs += src
SSvis_overlays.add_vis_overlay(src, icon, icon_state, ABOVE_MOB_LAYER, plane, dir, alpha, RESET_ALPHA) //you see mobs under it, but you hit them like they are above it
alpha = 0
if(init_vis_overlay)
SSvis_overlays.add_vis_overlay(src, icon, icon_state, ABOVE_MOB_LAYER, plane, dir, alpha, RESET_ALPHA) //you see mobs under it, but you hit them like they are above it
alpha = 0
/obj/structure/holosign/Destroy()
if(projector)
@@ -74,8 +76,10 @@
icon_state = "holo_fan"
density = FALSE
anchored = TRUE
layer = ABOVE_NORMAL_TURF_LAYER
CanAtmosPass = ATMOS_PASS_NO
alpha = 150
init_vis_overlay = FALSE
/obj/structure/holosign/barrier/atmos/Initialize()
. = ..()
@@ -100,7 +104,9 @@
max_integrity = 30
density = FALSE
anchored = TRUE
layer = ABOVE_NORMAL_TURF_LAYER
alpha = 150
init_vis_overlay = FALSE
CanAtmosPass = ATMOS_PASS_NO
resistance_flags = FIRE_PROOF
+1 -1
View File
@@ -168,7 +168,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an
/obj/structure/bodycontainer/morgue/AltClick(mob/user)
. = ..()
if(!user.canUseTopic(src, !issilicon(user)))
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return
beeper = !beeper
to_chat(user, "<span class='notice'>You turn the speaker function [beeper ? "on" : "off"].</span>")
+8
View File
@@ -595,6 +595,14 @@
/obj/structure/window/plastitanium/unanchored
anchored = FALSE
//pirate ship windows
/obj/structure/window/plastitanium/pirate
desc = "Yarr this window be explosion proof!"
explosion_block = 30
/obj/structure/window/plastitanium/pirate/unanchored
anchored = FALSE
/obj/structure/window/reinforced/clockwork
name = "brass window"
desc = "A paper-thin pane of translucent yet reinforced brass."

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