Merge remote-tracking branch 'upstream/master' into Lambdastation

This commit is contained in:
Dap
2020-03-21 19:09:50 -06:00
118 changed files with 6740 additions and 4750 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+3
View File
@@ -1,3 +1,6 @@
#define TRAITOR_HUMAN /datum/traitor_class/human/freeform
#define TRAITOR_AI /datum/traitor_class/ai
#define NUKE_RESULT_FLUKE 0
#define NUKE_RESULT_NUKE_WIN 1
#define NUKE_RESULT_CREW_WIN 2
+1 -1
View File
@@ -425,7 +425,7 @@
candidates -= M
/proc/pollGhostCandidates(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, ignore_category = null, flashwindow = TRUE)
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(/datum/element/ghost_role_eligibility)
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
var/list/candidates = eligibility.get_all_ghost_role_eligible()
return pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category, flashwindow, candidates)
+4 -2
View File
@@ -1426,7 +1426,9 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
/proc/get_random_drink()
var/list/blocked = list(/obj/item/reagent_containers/food/drinks/soda_cans,
/obj/item/reagent_containers/food/drinks/bottle
/obj/item/reagent_containers/food/drinks/bottle,
/obj/item/reagent_containers/food/drinks/flask/russian,
/obj/item/reagent_containers/food/drinks/flask/steel
)
return pick(subtypesof(/obj/item/reagent_containers/food/drinks) - blocked)
@@ -1562,4 +1564,4 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
channels_to_use += channel
if(channels_to_use.len)
world.TgsChatBroadcast()
world.TgsChatBroadcast()
+1 -1
View File
@@ -103,7 +103,7 @@ SUBSYSTEM_DEF(jukeboxes)
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS))
if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS) || !M.can_hear())
M.stop_sound_channel(jukeinfo[2])
continue
@@ -85,7 +85,7 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
our_quirks -= i
cut += i
pointscut += quirk_points_by_name(i)
if (pointscut >= 0) //with how it works, it needs to be above zero, not below, as points for positive is positive, and negative is negative, we only want it to break if it's above zero, ie. we cut more positive than negative
if (pointscut >= 0)
break
/* //Code to automatically reduce positive quirks until balance is even.
var/points_used = total_points(our_quirks)
@@ -102,7 +102,7 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
*/
//Nah, let's null all non-neutrals out.
if (pointscut != 0)// only if the pointscutting didn't work.
if (pointscut < 0)// only if the pointscutting didn't work.
if(cut.len)
for(var/i in our_quirks)
if(quirk_points_by_name(i) != 0)
+1 -1
View File
@@ -443,7 +443,7 @@ SUBSYSTEM_DEF(vote)
var/admin = FALSE
var/ckey = ckey(initiator_key)
if(GLOB.admin_datums[ckey])
if(GLOB.admin_datums[ckey] || initiator_key == "server")
admin = TRUE
if(next_allowed_time > world.time && !admin)
+2 -1
View File
@@ -83,6 +83,7 @@
elements.Cut()
/datum/beam/Destroy()
finished = TRUE
Reset()
target = null
origin = null
@@ -100,7 +101,7 @@
var/length = round(sqrt((DX)**2+(DY)**2)) //hypotenuse of the triangle formed by target and origin's displacement
for(N in 0 to length-1 step 32)//-1 as we want < not <=, but we want the speed of X in Y to Z and step X
if(QDELETED(src) || finished)
if(finished)
break
var/obj/effect/ebeam/X = new beam_type(origin_oldloc)
X.owner = src
@@ -107,7 +107,7 @@
/obj/item/stack/cable_coil = 5)
category = CAT_CLOTHING
/datum/crafting_recipe/diagnostic_singlasses_removal
/datum/crafting_recipe/diagnostic_sunglasses_removal
name = "Diagnostic HUDsunglasses removal"
result = /obj/item/clothing/glasses/sunglasses
time = 20
@@ -126,6 +126,85 @@
/obj/item/stack/cable_coil = 5)
category = CAT_CLOTHING
*/
// Eyepatch Glasses
/datum/crafting_recipe/secpatch
name = "Security Eyepatch HUD"
result = /obj/item/clothing/glasses/hud/security/sunglasses/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
parts = list(/obj/item/clothing/glasses/hud/security/sunglasses = 1,
/obj/item/clothing/glasses/eyepatch = 1)
reqs = list(/obj/item/clothing/glasses/hud/security/sunglasses = 1,
/obj/item/clothing/glasses/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/secpatch_removal
name = "Security HUDpatch Removal"
result = /obj/item/clothing/glasses/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
reqs = list(/obj/item/clothing/glasses/hud/security/sunglasses/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/medpatch
name = "Medical Eyepatch HUD"
result = /obj/item/clothing/glasses/hud/health/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
parts = list(/obj/item/clothing/glasses/hud/health = 1,
/obj/item/clothing/glasses/eyepatch = 1)
reqs = list(/obj/item/clothing/glasses/hud/health = 1,
/obj/item/clothing/glasses/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/medpatch_removal
name = "Medical HUDpatch Removal"
result = /obj/item/clothing/glasses/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
reqs = list(/obj/item/clothing/glasses/hud/health/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/diagpatch
name = "Diagnostic Eyepatch HUD"
result = /obj/item/clothing/glasses/hud/diagnostic/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
parts = list(/obj/item/clothing/glasses/hud/diagnostic = 1,
/obj/item/clothing/glasses/eyepatch = 1)
reqs = list(/obj/item/clothing/glasses/hud/diagnostic = 1,
/obj/item/clothing/glasses/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/diagpatch_removal
name = "Diagnostic HUDpatch Removal"
result = /obj/item/clothing/glasses/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
reqs = list(/obj/item/clothing/glasses/hud/diagnostic/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/mesonpatch
name = "Meson Scanner Eyepatch"
result = /obj/item/clothing/glasses/meson/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
parts = list(/obj/item/clothing/glasses/meson = 1,
/obj/item/clothing/glasses/eyepatch = 1)
reqs = list(/obj/item/clothing/glasses/meson = 1,
/obj/item/clothing/glasses/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/mesonpatch_removal
name = "Meson Scanner patch Removal"
result = /obj/item/clothing/glasses/eyepatch
time = 20
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
reqs = list(/obj/item/clothing/glasses/meson/eyepatch = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/ghostsheet
name = "Ghost Sheet"
result = /obj/item/clothing/suit/ghost_sheet
+6 -2
View File
@@ -28,7 +28,7 @@ GLOBAL_LIST_EMPTY(uplinks)
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)
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/ui_state/_checkstate, datum/traitor_class/traitor_class)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
@@ -47,7 +47,11 @@ GLOBAL_LIST_EMPTY(uplinks)
RegisterSignal(parent, COMSIG_PEN_ROTATED, .proc/pen_rotation)
GLOB.uplinks += src
uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted)
var/list/filters = list()
if(istype(traitor_class))
filters = traitor_class.uplink_filters
starting_tc = traitor_class.TC
uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted, filters)
if(_owner)
owner = _owner
+6 -6
View File
@@ -32,16 +32,16 @@
..()
switch(stage)
if(1)
if (prob(stage_prob) && stage1)
if (prob(stage_prob) && length(stage1))
to_chat(affected_mob, pick(stage1))
if(2)
if (prob(stage_prob) && stage2)
if (prob(stage_prob) && length(stage2))
to_chat(affected_mob, pick(stage2))
if(3)
if (prob(stage_prob*2) && stage3)
if (prob(stage_prob*2) && length(stage3))
to_chat(affected_mob, pick(stage3))
if(4)
if (prob(stage_prob*2) && stage4)
if (prob(stage_prob*2) && length(stage4))
to_chat(affected_mob, pick(stage4))
if(5)
do_disease_transformation(affected_mob)
@@ -162,7 +162,7 @@
desc = "This disease, actually acute nanomachine infection, converts the victim into a cyborg."
severity = DISEASE_SEVERITY_BIOHAZARD
visibility_flags = 0
stage1 = list()
stage1 = null
stage2 = list("Your joints feel stiff.", "<span class='danger'>Beep...boop..</span>")
stage3 = list("<span class='danger'>Your joints feel very stiff.</span>", "Your skin feels loose.", "<span class='danger'>You can feel something move...inside.</span>")
stage4 = list("<span class='danger'>Your skin feels very loose.</span>", "<span class='danger'>You can feel... something...inside you.</span>")
@@ -195,7 +195,7 @@
desc = "This disease changes the victim into a xenomorph."
severity = DISEASE_SEVERITY_BIOHAZARD
visibility_flags = 0
stage1 = list()
stage1 = null
stage2 = list("Your throat feels scratchy.", "<span class='danger'>Kill...</span>")
stage3 = list("<span class='danger'>Your throat feels very scratchy.</span>", "Your skin feels tight.", "<span class='danger'>You can feel something move...inside.</span>")
stage4 = list("<span class='danger'>Your skin feels very tight.</span>", "<span class='danger'>Your blood boils!</span>", "<span class='danger'>You can feel... something...inside you.</span>")
@@ -42,7 +42,7 @@
return candidates
/mob/proc/can_reenter_round(silent = FALSE)
var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(/datum/element/ghost_role_eligibility)
var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
return eli.can_reenter_round(src,silent)
/datum/element/ghost_role_eligibility/proc/can_reenter_round(var/mob/M,silent = FALSE)
+8 -6
View File
@@ -256,9 +256,11 @@
remove_rev()
SSticker.mode.update_cult_icons_removed(src)
/datum/mind/proc/equip_traitor(employer = "The Syndicate", silent = FALSE, datum/antagonist/uplink_owner)
/datum/mind/proc/equip_traitor(datum/traitor_class/traitor_class, silent = FALSE, datum/antagonist/uplink_owner)
if(!current)
return
if(!traitor_class)
traitor_class = GLOB.traitor_classes[TRAITOR_HUMAN]
var/mob/living/carbon/human/traitor_mob = current
if (!istype(traitor_mob))
return
@@ -306,21 +308,21 @@
if (!uplink_loc)
if(!silent)
to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.")
to_chat(traitor_mob, "Unfortunately, [traitor_class.employer] wasn't able to get you an Uplink.")
. = 0
else
. = uplink_loc
var/datum/component/uplink/U = uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key)
var/datum/component/uplink/U = uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key,traitor_class)
if(!U)
CRASH("Uplink creation failed.")
U.setup_unlock_code()
if(!silent)
if(uplink_loc == R)
to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(U.unlock_code)] to unlock its hidden features.")
to_chat(traitor_mob, "[traitor_class.employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(U.unlock_code)] to unlock its hidden features.")
else if(uplink_loc == PDA)
to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[U.unlock_code]\" into the ringtone select to unlock its hidden features.")
to_chat(traitor_mob, "[traitor_class.employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[U.unlock_code]\" into the ringtone select to unlock its hidden features.")
else if(uplink_loc == P)
to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [U.unlock_code] from its starting position to unlock its hidden features.")
to_chat(traitor_mob, "[traitor_class.employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [U.unlock_code] from its starting position to unlock its hidden features.")
if(uplink_owner)
uplink_owner.antag_memory += U.unlock_note + "<br>"
+1 -1
View File
@@ -40,7 +40,7 @@
name = "Fire Breath"
desc = "You can breathe fire at a target."
school = "evocation"
charge_max = 1200
charge_max = 600
clothes_req = FALSE
range = 20
base_icon_state = "fireball"
+2 -2
View File
@@ -108,10 +108,10 @@
var/mob/living/carbon/human/H = quirk_holder
var/obj/item/choice_beacon/music/B = new(get_turf(H))
H.put_in_hands(B)
H.equip_to_slot(B, SLOT_IN_BACKPACK)
H.equip_to_slot_if_possible(B, SLOT_IN_BACKPACK)
var/obj/item/musicaltuner/musicaltuner = new(get_turf(H))
H.put_in_hands(musicaltuner)
H.equip_to_slot(musicaltuner, SLOT_IN_BACKPACK)
H.equip_to_slot_if_possible(musicaltuner, SLOT_IN_BACKPACK)
H.regenerate_icons()
/datum/quirk/photographer
@@ -34,7 +34,7 @@
living_players = trim_list(mode.current_players[CURRENT_LIVING_PLAYERS])
living_antags = trim_list(mode.current_players[CURRENT_LIVING_ANTAGS])
list_observers = trim_list(mode.current_players[CURRENT_OBSERVERS])
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(/datum/element/ghost_role_eligibility)
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
ghost_eligible = trim_list(eligibility.get_all_ghost_role_eligible())
/datum/dynamic_ruleset/midround/proc/trim_list(list/L = list())
@@ -677,6 +677,9 @@
message_admins("[ADMIN_LOOKUPFLW(Ninja)] has been made into a ninja by dynamic.")
log_game("[key_name(Ninja)] was spawned as a ninja by dynamic.")
return Ninja
/datum/dynamic_ruleset/midround/from_ghosts/ninja/finish_setup(mob/new_character, index)
return
#undef ABDUCTOR_MAX_TEAMS
#undef REVENANT_SPAWN_THRESHOLD
+6 -1
View File
@@ -1163,12 +1163,17 @@ GLOBAL_LIST_EMPTY(possible_sabotages)
var/payout = 0
var/payout_bonus = 0
var/area/dropoff = null
var/static/list/blacklisted_areas = typecacheof(list(/area/ai_monitored/turret_protected,
/area/solar/,
/area/ruin/, //thank you station space ruins
/area/science/test_area/,
/area/shuttle/))
/datum/objective/contract/proc/generate_dropoff() // Generate a random valid area on the station that the dropoff will happen.
var/found = FALSE
while(!found)
var/area/dropoff_area = pick(GLOB.sortedAreas)
if(dropoff_area && is_station_level(dropoff_area.z) && !dropoff_area.outdoors && !istype(dropoff_area, /area/shuttle/))
if(dropoff_area && is_station_level(dropoff_area.z) && !dropoff_area.outdoors && !is_type_in_typecache(dropoff_area, blacklisted_areas))
dropoff = dropoff_area
found = TRUE
+3 -3
View File
@@ -115,10 +115,10 @@
if(src.allowed(usr))
var/mob/living/silicon/robot/R = locate(href_list["stopbot"]) in GLOB.silicon_mobs
if(can_control(usr, R))
var/choice = input("Are you certain you wish to [R.locked_down? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
var/choice = input("Are you certain you wish to [!R.locked_down ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
if(choice == "Confirm" && can_control(usr, R) && !..())
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [R.locked_down? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
log_game("[key_name(usr)] [R.locked_down? "locked down" : "released"] [key_name(R)]!")
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [!R.locked_down ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
log_game("[key_name(usr)] [!R.locked_down ? "locked down" : "released"] [key_name(R)]!")
R.SetLockdown(!R.locked_down)
to_chat(R, "[!R.locked_down ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
if(R.connected_ai)
+2 -2
View File
@@ -316,7 +316,7 @@
if("togglemoving")
moving = !moving
if(moving)
spawn() MagnetMove()
INVOKE_ASYNC(src, .proc/MagnetMove)
updateUsrDialog()
@@ -325,7 +325,7 @@
if(looping)
return
while(moving && rpath.len >= 1)
while(moving && length(rpath) >= 1)
if(stat & (BROKEN|NOPOWER))
break
@@ -247,6 +247,7 @@
if(prob(70))
if(stored_gun)
stored_gun.forceMove(loc)
stored_gun = null
to_chat(user, "<span class='notice'>You remove the turret and salvage some components.</span>")
if(prob(50))
new /obj/item/stack/sheet/metal(loc, rand(1,4))
+9 -9
View File
@@ -8,7 +8,7 @@
layer = ABOVE_ALL_MOB_LAYER // Overhead
density = TRUE
circuit = /obj/item/circuitboard/machine/recycler
var/safety_mode = FALSE // Temporarily stops machine if it detects a mob
var/safety_mode = FALSE // Temporarily stops machine if it detects a mob, or upon deconstruction.
var/icon_name = "grinder-o"
var/blood = 0
var/eat_dir = WEST
@@ -24,6 +24,10 @@
update_icon()
req_one_access = get_all_accesses() + get_all_centcom_access()
/obj/machinery/recycler/deconstruct(disassembled = TRUE)
safety_mode = TRUE //to stop stock parts and circuit from being deleted.
return ..()
/obj/machinery/recycler/RefreshParts()
var/amt_made = 0
var/mat_mod = 0
@@ -97,18 +101,14 @@
. = ..()
/obj/machinery/recycler/proc/eat(atom/AM0, sound=TRUE)
if(stat & (BROKEN|NOPOWER))
return
if(safety_mode)
if(stat & (BROKEN|NOPOWER) || safety_mode)
return
var/list/to_eat
if(isitem(AM0))
to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
else
to_eat = list(AM0)
to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
var/items_recycled = 0
for(var/i in to_eat)
var/atom/movable/AM = i
var/obj/item/bodypart/head/as_head = AM
+10
View File
@@ -152,6 +152,16 @@
else
..()
/obj/structure/spider/spiderling/attack_hand(mob/user)
. = ..()
if(user.a_intent != INTENT_HELP)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
user.visible_message("<span class='warning'>[user] splats [src].</span>", "<span class='warning'>You splat [src].</span>", "<span class='italics'>You hear a splat...</span>")
playsound(loc, 'sound/effects/snap.ogg', 25)
qdel(src)
return TRUE
/obj/structure/spider/spiderling/process()
if(travelling_in_vent)
if(isturf(loc))
@@ -173,37 +173,6 @@
R.module.basic_modules += S
R.module.add_module(S, FALSE, TRUE)
/obj/item/borg/upgrade/premiumka
name = "mining cyborg premium KA"
desc = "A premium kinetic accelerator replacement for the mining module's standard kinetic accelerator."
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = list(/obj/item/robot_module/miner)
/obj/item/borg/upgrade/premiumka/action(mob/living/silicon/robot/R, user = usr)
. = ..()
if(.)
for(var/obj/item/gun/energy/kinetic_accelerator/cyborg/KA in R.module)
for(var/obj/item/borg/upgrade/modkit/M in KA.modkits)
M.uninstall(src)
R.module.remove_module(KA, TRUE)
var/obj/item/gun/energy/kinetic_accelerator/premiumka/cyborg/PKA = new /obj/item/gun/energy/kinetic_accelerator/premiumka/cyborg(R.module)
R.module.basic_modules += PKA
R.module.add_module(PKA, FALSE, TRUE)
/obj/item/borg/upgrade/premiumka/deactivate(mob/living/silicon/robot/R, user = usr)
. = ..()
if (.)
for(var/obj/item/gun/energy/kinetic_accelerator/premiumka/cyborg/PKA in R.module)
for(var/obj/item/borg/upgrade/modkit/M in PKA.modkits)
M.uninstall(src)
R.module.remove_module(PKA, TRUE)
var/obj/item/gun/energy/kinetic_accelerator/cyborg/KA = new (R.module)
R.module.basic_modules += KA
R.module.add_module(KA, FALSE, TRUE)
/obj/item/borg/upgrade/advcutter
name = "mining cyborg advanced plasma cutter"
@@ -462,7 +431,7 @@
desc = "An upgrade to the Medical module's hypospray, containing \
stronger versions of existing chemicals."
additional_reagents = list(/datum/reagent/medicine/oxandrolone, /datum/reagent/medicine/sal_acid,
/datum/reagent/medicine/rezadone, /datum/reagent/medicine/pen_acid)
/datum/reagent/medicine/rezadone, /datum/reagent/medicine/pen_acid, /datum/reagent/medicine/prussian_blue)
/obj/item/borg/upgrade/piercing_hypospray
name = "cyborg piercing hypospray"
@@ -136,6 +136,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
merge_type = /obj/item/stack/sheet/metal
grind_results = list(/datum/reagent/iron = 20)
point_value = 2
tableVariant = /obj/structure/table
material_type = /datum/material/iron
/obj/item/stack/sheet/metal/ratvar_act()
+2 -1
View File
@@ -219,8 +219,9 @@
O = new R.result_type(usr.drop_location())
if(O)
O.setDir(usr.dir)
log_craft("[O] crafted by [usr] at [loc_name(O.loc)]")
use(R.req_amount * multiplier)
log_craft("[O] crafted by [usr] at [loc_name(O.loc)]")
if(R.applies_mats && custom_materials && custom_materials.len)
var/list/used_materials = list()
+1 -1
View File
@@ -66,7 +66,7 @@
return
if(!istype(target))
return
if(target.anchored)
if(target.anchored || (user in target))
return
if(isitem(target))
+6 -1
View File
@@ -54,7 +54,12 @@
icon_state = "holdingsat"
item_state = "holdingsat"
species_exception = list(/datum/species/angel)
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
/obj/item/storage/backpack/holding/duffel
name = "duffel bag of holding"
desc = "A duffel bag that opens into a localized pocket of Blue Space."
icon_state = "holdingduffel"
item_state = "holdingduffel"
/obj/item/storage/backpack/holding/ComponentInitialize()
. = ..()
+1 -3
View File
@@ -25,7 +25,7 @@
/obj/item/melee/baton/examine(mob/user)
. = ..()
. += "<span class='notice'>Right click attack while in combat mode or attack while in disarm intent to disarm instead of stun.</span>"
. += "<span class='notice'>Right click attack while in combat mode to disarm instead of stun.</span>"
/obj/item/melee/baton/get_cell()
. = cell
@@ -149,8 +149,6 @@
//return TRUE to interrupt attack chain.
/obj/item/melee/baton/proc/common_baton_melee(mob/M, mob/living/user, disarming = FALSE)
if(user.a_intent == INTENT_DISARM)
disarming = TRUE //override if they're in disarm intent.
if(iscyborg(M) || !isliving(M)) //can't baton cyborgs
return FALSE
if(status && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
+3 -3
View File
@@ -1012,7 +1012,7 @@
/obj/item/twohanded/electrostaff
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "electrostaff_3"
icon_state = "electrostaff"
item_state = "electrostaff"
lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
@@ -1116,10 +1116,10 @@
/obj/item/twohanded/electrostaff/update_icon_state()
. = ..()
if(!wielded)
icon_state = "electrostaff_3"
icon_state = "electrostaff"
item_state = "electrostaff"
else
icon_state = item_state = (on? "electrostaff_1" : "electrostaff_3")
icon_state = item_state = (on? "electrostaff_1" : "electrostaff_0")
set_light(7, on? 1 : 0, LIGHT_COLOR_CYAN)
/obj/item/twohanded/electrostaff/examine(mob/living/user)
@@ -59,6 +59,7 @@
new_spawn.real_name = random_unique_lizard_name(gender)
if(is_mining_level(z))
to_chat(new_spawn, "<b>Drag the corpses of men and beasts to your nest. It will absorb them to create more of your kind. Glory to the Necropolis!</b>")
to_chat(new_spawn, "<b>You can expand the weather proof area provided by your shelters by using the 'New Area' key near the bottom right of your HUD.</b>")
else
to_chat(new_spawn, "<span class='userdanger'>You have been born outside of your natural home! Whether you decide to return home, or make due with your new home is your own decision.</span>")
+2 -1
View File
@@ -70,7 +70,8 @@
/turf/closed/wall/proc/break_wall()
new sheet_type(src, sheet_amount)
return new girder_type(src)
if(girder_type)
return new girder_type(src)
/turf/closed/wall/proc/devastate_wall()
new sheet_type(src, sheet_amount)
+1 -3
View File
@@ -639,15 +639,13 @@
var/almcam = CONFIG_GET(flag/allow_ai_multicam)
CONFIG_SET(flag/allow_ai_multicam, !almcam)
if (almcam)
to_chat(world, "<B>The AI no longer has multicam.</B>")
for(var/i in GLOB.ai_list)
var/mob/living/silicon/ai/aiPlayer = i
if(aiPlayer.multicam_on)
aiPlayer.end_multicam()
else
to_chat(world, "<B>The AI now has multicam.</B>")
log_admin("[key_name(usr)] toggled AI multicam.")
world.update_status()
to_chat(GLOB.ai_list | GLOB.admins, "<B>The AI [almcam ? "no longer" : "now"] has multicam.</B>")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Multicam", "[!almcam ? "Disabled" : "Enabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/toggleaban()
+1 -1
View File
@@ -1732,7 +1732,7 @@
var/mob/M = locate(href_list["makeeligible"])
if(!ismob(M))
to_chat(usr, "this can only be used on instances of type /mob.")
var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(/datum/element/ghost_role_eligibility)
var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
if(M.ckey in eli.timeouts)
eli.timeouts -= M.ckey
+3 -3
View File
@@ -1315,15 +1315,15 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/creamy = new(get_turf(target))
creamy.splat(target)
if (ADMIN_PUNISHMENT_CUSTOM_PIE)
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/A = new(get_turf(target))
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/A = new()
if(!A.reagents)
var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num
var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num|null
if(amount)
A.create_reagents(amount)
if(A.reagents)
var/chosen_id = choose_reagent_id(usr)
if(chosen_id)
var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num
var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num|null
if(amount)
A.reagents.add_reagent(chosen_id, amount)
A.splat(target)
@@ -43,7 +43,7 @@
// EXPLANATION
/datum/objective/bloodsucker/lair/update_explanation_text()
explanation_text = "Create a lair by claiming a coffin, and protect it until the end of the shift"// Make sure to keep it safe!"
explanation_text = "Create a lair by claiming a coffin, and protect it until the end of the shift."// Make sure to keep it safe!"
// WIN CONDITIONS?
/datum/objective/bloodsucker/lair/check_completion()
@@ -228,7 +228,7 @@
if (SC && SC.lastgen > 0 && SC.connected_panels.len > 0 && SC.connected_tracker)
return FALSE
return TRUE
*/
*/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -250,15 +250,15 @@
// WIN CONDITIONS?
/datum/objective/bloodsucker/heartthief/check_completion()
// -Must have a body.
if (!owner.current)
if(!owner.current)
return FALSE
// Taken from /steal in objective.dm
var/list/all_items = owner.current.GetAllContents() // Includes items inside other items.
var/itemcount = FALSE
for(var/obj/I in all_items) //Check for items
if(I == /obj/item/organ/heart)
itemcount ++
if (itemcount >= target_amount) // Got the right amount?
if(istype(I, /obj/item/organ/heart/))
itemcount++
if(itemcount >= target_amount) // Got the right amount?
return TRUE
return FALSE
@@ -120,7 +120,7 @@
/datum/antagonist/traitor/internal_affairs/reinstate_escape_objective()
..()
var/objtype = traitor_kind == TRAITOR_HUMAN ? /datum/objective/escape : /datum/objective/survive
var/objtype = !istype(traitor_kind,TRAITOR_AI) ? /datum/objective/escape : /datum/objective/survive
var/datum/objective/escape_objective = new objtype
escape_objective.owner = owner
add_objective(escape_objective)
@@ -215,20 +215,12 @@
kill_objective.target = target_mind
kill_objective.update_explanation_text()
add_objective(kill_objective)
//Optional traitor objective
if(prob(PROB_ACTUAL_TRAITOR))
employer = "The Syndicate"
owner.special_role = TRAITOR_AGENT_ROLE
special_role = TRAITOR_AGENT_ROLE
syndicate = TRUE
forge_single_objective()
return
/datum/antagonist/traitor/internal_affairs/forge_traitor_objectives()
forge_iaa_objectives()
var/objtype = traitor_kind == TRAITOR_HUMAN ? /datum/objective/escape : /datum/objective/survive
var/objtype = !istype(traitor_kind,TRAITOR_AI) ? /datum/objective/escape : /datum/objective/survive
var/datum/objective/escape_objective = new objtype
escape_objective.owner = owner
add_objective(escape_objective)
@@ -0,0 +1,68 @@
/datum/traitor_class/ai // this one is special, so has no weight
name = "Malfunctioning AI"
/datum/traitor_class/ai/forge_objectives(datum/antagonist/traitor/T)
var/objective_count = 0
if(prob(30))
objective_count += forge_single_objective()
for(var/i = objective_count, i < CONFIG_GET(number/traitor_objectives_amount), i++)
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
var/datum/objective/survive/exist/exist_objective = new
exist_objective.owner = T.owner
T.add_objective(exist_objective)
/datum/traitor_class/ai/forge_single_objective(datum/antagonist/traitor/T)
.=1
var/special_pick = rand(1,4)
switch(special_pick)
if(1)
var/datum/objective/block/block_objective = new
block_objective.owner = T.owner
T.add_objective(block_objective)
if(2)
var/datum/objective/purge/purge_objective = new
purge_objective.owner = T.owner
T.add_objective(purge_objective)
if(3)
var/datum/objective/robot_army/robot_objective = new
robot_objective.owner = T.owner
T.add_objective(robot_objective)
if(4) //Protect and strand a target
var/datum/objective/protect/yandere_one = new
yandere_one.owner = T.owner
T.add_objective(yandere_one)
yandere_one.find_target()
var/datum/objective/maroon/yandere_two = new
yandere_two.owner = T.owner
yandere_two.target = yandere_one.target
yandere_two.update_explanation_text() // normally called in find_target()
T.add_objective(yandere_two)
.=2
/datum/traitor_class/ai/on_removal(datum/antagonist/traitor/T)
var/mob/living/silicon/ai/A = T.owner.current
A.set_zeroth_law("")
A.verbs -= /mob/living/silicon/ai/proc/choose_modules
A.malf_picker.remove_malf_verbs(A)
qdel(A.malf_picker)
/datum/traitor_class/ai/apply_innate_effects(mob/living/M)
var/mob/living/silicon/ai/A = M
A.hack_software = TRUE
/datum/traitor_class/ai/remove_innate_effects(mob/living/M)
var/mob/living/silicon/ai/A = M
A.hack_software = FALSE
/datum/traitor_class/ai/finalize_traitor(datum/antagonist/traitor/T)
T.add_law_zero()
T.owner.current.playsound_local(get_turf(T.owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE)
T.owner.current.grant_language(/datum/language/codespeak)
return FALSE
@@ -0,0 +1,37 @@
/datum/traitor_class/human/assassin
name = "Donk Co Operative"
employer = "Donk Corporation"
weight = 0
chaos = 1
cost = 2
/datum/traitor_class/human/assassin/forge_single_objective(datum/antagonist/traitor/T)
.=1
var/permakill_prob = 20
var/is_dynamic = FALSE
var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
is_dynamic = TRUE
permakill_prob = max(0,mode.threat_level-50)
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = T.owner
destroy_objective.find_target()
T.add_objective(destroy_objective)
else if(prob(30) || (is_dynamic && (mode.storyteller.flags & NO_ASSASSIN)))
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = T.owner
maroon_objective.find_target()
T.add_objective(maroon_objective)
else if(prob(permakill_prob))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
else
var/datum/objective/assassinate/once/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
@@ -0,0 +1,12 @@
/datum/traitor_class/human/freeform
name = "Waffle Co Agent"
employer = "Waffle Company"
weight = 16
chaos = 0
/datum/traitor_class/human/freeform/forge_objectives(datum/antagonist/traitor/T)
var/datum/objective/escape/O = new
O.explanation_text = "You have no goals! Whatever you can do do antagonize Nanotrasen, do it! The gimmickier, the better! Make sure to escape alive, though!"
O.owner = T.owner
T.add_objective(O)
return
@@ -0,0 +1,18 @@
/datum/traitor_class/human/hijack
name = "Gorlex Marauder"
employer = "The Gorlex Marauders"
weight = 3
chaos = 5
cost = 5
uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit)
/datum/traitor_class/human/hijack/forge_objectives(datum/antagonist/traitor/T)
var/datum/objective/hijack/O = new
O.explanation_text = "The Gorlex Marauders are letting you do what you want, with one condition: the shuttle must be hijacked by hacking its navigational protocols through the control console (alt click emergency shuttle console)."
O.owner = T.owner
T.add_objective(O)
return
/datum/traitor_class/human/hijack/finalize_traitor(datum/antagonist/traitor/T)
T.hijack_speed=1
return TRUE
@@ -0,0 +1,82 @@
/datum/traitor_class/human
name = "Syndicate Agent"
chaos = 0
/datum/traitor_class/human/forge_objectives(datum/antagonist/traitor/T)
var/objective_count = 0 //Hijacking counts towards number of objectives
if(!SSticker.mode.exchange_blue && SSticker.mode.traitors.len >= 8) //Set up an exchange if there are enough traitors
if(!SSticker.mode.exchange_red)
SSticker.mode.exchange_red = T.owner
else
SSticker.mode.exchange_blue = T.owner
T.assign_exchange_role(SSticker.mode.exchange_red)
T.assign_exchange_role(SSticker.mode.exchange_blue)
objective_count += 1 //Exchange counts towards number of objectives
var/toa = CONFIG_GET(number/traitor_objectives_amount)
for(var/i = objective_count, i < toa, i++)
forge_single_objective(T)
if(!(locate(/datum/objective/escape) in T.objectives))
var/datum/objective/escape/escape_objective = new
escape_objective.owner = T.owner
T.add_objective(escape_objective)
return
/datum/traitor_class/human/forge_single_objective(datum/antagonist/traitor/T)
.=1
var/assassin_prob = 50
var/is_dynamic = FALSE
var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
is_dynamic = TRUE
assassin_prob = max(0,mode.threat_level-20)
if(prob(assassin_prob))
if(is_dynamic)
var/threat_spent = CONFIG_GET(number/dynamic_assassinate_cost)
mode.spend_threat(threat_spent)
mode.log_threat("[T.owner.name] spent [threat_spent] on an assassination target.")
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = T.owner
destroy_objective.find_target()
T.add_objective(destroy_objective)
else if(prob(30) || (is_dynamic && (mode.storyteller.flags & NO_ASSASSIN)))
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = T.owner
maroon_objective.find_target()
T.add_objective(maroon_objective)
else if(prob(max(0,assassin_prob-20)))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
else
var/datum/objective/assassinate/once/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
else
if(prob(15) && !(locate(/datum/objective/download) in T.objectives) && !(T.owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
var/datum/objective/download/download_objective = new
download_objective.owner = T.owner
download_objective.gen_amount_goal()
T.add_objective(download_objective)
else if(prob(40)) // cum. not counting download: 40%.
var/datum/objective/steal/steal_objective = new
steal_objective.owner = T.owner
steal_objective.find_target()
T.add_objective(steal_objective)
else if(prob(100/3)) // cum. not counting download: 20%.
var/datum/objective/sabotage/sabotage_objective = new
sabotage_objective.owner = T.owner
sabotage_objective.find_target()
T.add_objective(sabotage_objective)
else // cum. not counting download: 40%
var/datum/objective/flavor/traitor/flavor_objective = new
flavor_objective.owner = T.owner
flavor_objective.forge_objective()
T.add_objective(flavor_objective)
/datum/traitor_class/human/greet(datum/antagonist/traitor/T)
to_chat(T.owner.current, "<B><font size=2 color=red>You are under contract with [employer]. They have given you your objectives.</font></B>")
@@ -0,0 +1,14 @@
/datum/traitor_class/human/martyr
name = "Tiger Cooperator"
employer = "The Tiger Cooperative"
weight = 2
chaos = 5
cost = 5
uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit,/datum/uplink_item/bundles_TC/contract_kit)
/datum/traitor_class/human/martyr/forge_objectives(datum/antagonist/traitor/T)
var/datum/objective/martyr/O = new
O.explanation_text = "The tiger cooperative have given you free reign. You may do as you wish, as long as you die a glorious death!"
O.owner = T.owner
T.add_objective(O)
return
@@ -0,0 +1,40 @@
/datum/traitor_class/human/subterfuge
name = "MI13 Operative"
employer = "MI13"
weight = 20
chaos = -5
/datum/traitor_class/human/subterfuge/forge_single_objective(datum/antagonist/traitor/T)
.=1
var/assassin_prob = 30
var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
assassin_prob = max(0,mode.threat_level-40)
if(prob(assassin_prob))
if(prob(assassin_prob))
var/datum/objective/assassinate/once/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
else
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = T.owner
maroon_objective.find_target()
T.add_objective(maroon_objective)
else
if(prob(15) && !(locate(/datum/objective/download) in T.objectives) && !(T.owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
var/datum/objective/download/download_objective = new
download_objective.owner = T.owner
download_objective.gen_amount_goal()
T.add_objective(download_objective)
else if(prob(70)) // cum. not counting download: 40%.
var/datum/objective/steal/steal_objective = new
steal_objective.owner = T.owner
steal_objective.find_target()
T.add_objective(steal_objective)
else
var/datum/objective/sabotage/sabotage_objective = new
sabotage_objective.owner = T.owner
sabotage_objective.find_target()
T.add_objective(sabotage_objective)
@@ -0,0 +1,40 @@
GLOBAL_LIST_EMPTY(traitor_classes)
/datum/traitor_class
var/name = "Bad Coders Ltd."
var/employer = "The Syndicate"
var/weight = 0
var/chaos = 0
var/cost = 0
var/TC = 20
var/list/uplink_filters
/datum/traitor_class/New()
..()
if(src.type in GLOB.traitor_classes)
qdel(src)
else
GLOB.traitor_classes += src.type
GLOB.traitor_classes[src.type] = src
/datum/traitor_class/proc/forge_objectives(datum/antagonist/traitor/T)
// Like the old forge_human_objectives. Makes all the objectives for this traitor class.
/datum/traitor_class/proc/forge_single_objective(datum/antagonist/traitor/T)
// As forge_single_objective.
/datum/traitor_class/proc/on_removal(datum/antagonist/traitor/T)
// What this does to the antag datum on removal. Called before proper removal, obviously.
/datum/traitor_class/proc/apply_innate_effects(mob/living/M)
// What innate effects it should have. See: AI.
/datum/traitor_class/proc/remove_innate_effects(mob/living/M)
// Cleaning up the innate effects.
/datum/traitor_class/proc/greet(datum/antagonist/traitor/T)
// Message upon creation. Not necessary, but can be useful.
/datum/traitor_class/proc/finalize_traitor(datum/antagonist/traitor/T)
// Finalization. Return TRUE if should play standard traitor sound/equip, return FALSE if both are special case
return TRUE
+52 -227
View File
@@ -1,6 +1,3 @@
#define TRAITOR_HUMAN "human"
#define TRAITOR_AI "AI"
/datum/antagonist/traitor
name = "Traitor"
roundend_category = "traitors"
@@ -12,43 +9,52 @@
var/give_objectives = TRUE
var/should_give_codewords = TRUE
var/should_equip = TRUE
var/traitor_kind = TRAITOR_HUMAN //Set on initial assignment
var/datum/traitor_class/traitor_kind
var/datum/contractor_hub/contractor_hub
hijack_speed = 0.5 //10 seconds per hijack stage by default
/datum/antagonist/traitor/New()
..()
if(!GLOB.traitor_classes.len)//Only need to fill the list when it's needed.
for(var/I in subtypesof(/datum/traitor_class))
new I
/datum/antagonist/traitor/proc/set_traitor_kind(var/kind)
traitor_kind = GLOB.traitor_classes[kind]
if(istype(SSticker.mode, /datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
if(traitor_kind.cost)
mode.spend_threat(traitor_kind.cost)
mode.log_threat("[traitor_kind.cost] was spent due to [owner.name] being a [traitor_kind.name].")
/datum/antagonist/traitor/on_gain()
if(owner.current && isAI(owner.current))
traitor_kind = TRAITOR_AI
set_traitor_kind(TRAITOR_AI)
else
var/chaos_weight = 0
if(istype(SSticker.mode,/datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
chaos_weight = (mode.threat - 50)/50
var/list/weights = list()
for(var/C in GLOB.traitor_classes)
var/datum/traitor_class/class = GLOB.traitor_classes[C]
var/weight = (1.5*class.weight)/(0.5+NUM_E**(-chaos_weight*class.chaos)) // just a logistic function
weights[C] = weight
var/choice = pickweightAllowZero(weights)
if(!choice)
choice = GLOB.traitor_classes[TRAITOR_HUMAN]
set_traitor_kind(pickweightAllowZero(weights))
traitor_kind.weight *= 0.8 // less likely this round
SSticker.mode.traitors += owner
owner.special_role = special_role
if(give_objectives)
forge_traitor_objectives()
traitor_kind.forge_objectives(src)
finalize_traitor()
..()
/datum/antagonist/traitor/apply_innate_effects()
if(owner.assigned_role == "Clown")
var/mob/living/carbon/human/traitor_mob = owner.current
if(traitor_mob && istype(traitor_mob))
if(!silent)
to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.")
traitor_mob.dna.remove_mutation(CLOWNMUT)
/datum/antagonist/traitor/remove_innate_effects()
if(owner.assigned_role == "Clown")
var/mob/living/carbon/human/traitor_mob = owner.current
if(traitor_mob && istype(traitor_mob))
traitor_mob.dna.add_mutation(CLOWNMUT)
/datum/antagonist/traitor/on_removal()
//Remove malf powers.
if(traitor_kind == TRAITOR_AI && owner.current && isAI(owner.current))
var/mob/living/silicon/ai/A = owner.current
A.set_zeroth_law("")
A.verbs -= /mob/living/silicon/ai/proc/choose_modules
A.malf_picker.remove_malf_verbs(A)
qdel(A.malf_picker)
traitor_kind.on_removal(src)
SSticker.mode.traitors -= owner
if(!silent && owner.current)
to_chat(owner.current,"<span class='userdanger'> You are no longer the [special_role]! </span>")
@@ -69,192 +75,11 @@
objectives -= O
/datum/antagonist/traitor/proc/forge_traitor_objectives()
switch(traitor_kind)
if(TRAITOR_AI)
forge_ai_objectives()
else
forge_human_objectives()
/datum/antagonist/traitor/proc/forge_human_objectives()
var/is_hijacker = FALSE
var/datum/game_mode/dynamic/mode
var/is_dynamic = FALSE
var/hijack_prob = 0
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
is_dynamic = TRUE
if(mode.threat >= CONFIG_GET(number/dynamic_hijack_cost))
hijack_prob = CLAMP(mode.threat_level-50,0,20)
if(GLOB.joined_player_list.len>=GLOB.dynamic_high_pop_limit)
is_hijacker = (prob(hijack_prob) && mode.threat_level > CONFIG_GET(number/dynamic_hijack_high_population_requirement))
else
var/indice_pop = min(10,round(GLOB.joined_player_list.len/mode.pop_per_requirement)+1)
is_hijacker = (prob(hijack_prob) && (mode.threat_level >= CONFIG_GET(number_list/dynamic_hijack_requirements)[indice_pop]))
if(mode.storyteller.flags & NO_ASSASSIN)
is_hijacker = FALSE
else if (GLOB.joined_player_list.len >= 30) // Less murderboning on lowpop thanks
hijack_prob = 10
is_hijacker = prob(10)
var/martyr_chance = prob(hijack_prob*2)
var/objective_count = is_hijacker //Hijacking counts towards number of objectives
if(!SSticker.mode.exchange_blue && SSticker.mode.traitors.len >= 8) //Set up an exchange if there are enough traitors
if(!SSticker.mode.exchange_red)
SSticker.mode.exchange_red = owner
else
SSticker.mode.exchange_blue = owner
assign_exchange_role(SSticker.mode.exchange_red)
assign_exchange_role(SSticker.mode.exchange_blue)
objective_count += 1 //Exchange counts towards number of objectives
var/toa = CONFIG_GET(number/traitor_objectives_amount)
for(var/i = objective_count, i < toa, i++)
forge_single_objective()
if(is_hijacker && objective_count <= toa) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount
if (!(locate(/datum/objective/hijack) in objectives))
var/datum/objective/hijack/hijack_objective = new
hijack_objective.owner = owner
add_objective(hijack_objective)
if(is_dynamic)
var/threat_spent = CONFIG_GET(number/dynamic_hijack_cost)
mode.spend_threat(threat_spent)
mode.log_threat("[owner.name] spent [threat_spent] on hijack.")
return
var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead.
for(var/datum/objective/O in objectives)
if(!O.martyr_compatible)
martyr_compatibility = 0
break
if(martyr_compatibility && martyr_chance)
var/datum/objective/martyr/martyr_objective = new
martyr_objective.owner = owner
add_objective(martyr_objective)
if(is_dynamic)
var/threat_spent = CONFIG_GET(number/dynamic_hijack_cost)
mode.spend_threat(threat_spent)
mode.log_threat("[owner.name] spent [threat_spent] on glorious death.")
return
else
if(!(locate(/datum/objective/escape) in objectives))
var/datum/objective/escape/escape_objective = new
escape_objective.owner = owner
add_objective(escape_objective)
return
/datum/antagonist/traitor/proc/forge_ai_objectives()
var/objective_count = 0
if(prob(30))
objective_count += forge_single_objective()
for(var/i = objective_count, i < CONFIG_GET(number/traitor_objectives_amount), i++)
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = owner
kill_objective.find_target()
add_objective(kill_objective)
var/datum/objective/survive/exist/exist_objective = new
exist_objective.owner = owner
add_objective(exist_objective)
/datum/antagonist/traitor/proc/forge_single_objective()
switch(traitor_kind)
if(TRAITOR_AI)
return forge_single_AI_objective()
else
return forge_single_human_objective()
/datum/antagonist/traitor/proc/forge_single_human_objective() //Returns how many objectives are added
.=1
var/assassin_prob = 50
var/is_dynamic = FALSE
var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
is_dynamic = TRUE
assassin_prob = max(0,mode.threat_level-20)
if(prob(assassin_prob))
if(is_dynamic)
var/threat_spent = CONFIG_GET(number/dynamic_assassinate_cost)
mode.spend_threat(threat_spent)
mode.log_threat("[owner.name] spent [threat_spent] on an assassination target.")
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = owner
destroy_objective.find_target()
add_objective(destroy_objective)
else if(prob(30) || (is_dynamic && (mode.storyteller.flags & NO_ASSASSIN)))
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = owner
maroon_objective.find_target()
add_objective(maroon_objective)
else if(prob(max(0,assassin_prob-20)))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = owner
kill_objective.find_target()
add_objective(kill_objective)
else
var/datum/objective/assassinate/once/kill_objective = new
kill_objective.owner = owner
kill_objective.find_target()
add_objective(kill_objective)
else
if(prob(15) && !(locate(/datum/objective/download) in objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
var/datum/objective/download/download_objective = new
download_objective.owner = owner
download_objective.gen_amount_goal()
add_objective(download_objective)
else if(prob(40)) // cum. not counting download: 40%.
var/datum/objective/steal/steal_objective = new
steal_objective.owner = owner
steal_objective.find_target()
add_objective(steal_objective)
else if(prob(100/3)) // cum. not counting download: 20%.
var/datum/objective/sabotage/sabotage_objective = new
sabotage_objective.owner = owner
sabotage_objective.find_target()
add_objective(sabotage_objective)
else // cum. not counting download: 40%
var/datum/objective/flavor/traitor/flavor_objective = new
flavor_objective.owner = owner
flavor_objective.forge_objective()
add_objective(flavor_objective)
/datum/antagonist/traitor/proc/forge_single_AI_objective()
.=1
var/special_pick = rand(1,4)
switch(special_pick)
if(1)
var/datum/objective/block/block_objective = new
block_objective.owner = owner
add_objective(block_objective)
if(2)
var/datum/objective/purge/purge_objective = new
purge_objective.owner = owner
add_objective(purge_objective)
if(3)
var/datum/objective/robot_army/robot_objective = new
robot_objective.owner = owner
add_objective(robot_objective)
if(4) //Protect and strand a target
var/datum/objective/protect/yandere_one = new
yandere_one.owner = owner
add_objective(yandere_one)
yandere_one.find_target()
var/datum/objective/maroon/yandere_two = new
yandere_two.owner = owner
yandere_two.target = yandere_one.target
yandere_two.update_explanation_text() // normally called in find_target()
add_objective(yandere_two)
.=2
traitor_kind.forge_objectives(src)
/datum/antagonist/traitor/greet()
to_chat(owner.current, "<B><font size=3 color=red>You are the [owner.special_role].</font></B>")
traitor_kind.greet(src)
owner.announce_objectives()
if(should_give_codewords)
give_codewords()
@@ -270,32 +95,33 @@
set_antag_hud(owner.current, null)
/datum/antagonist/traitor/proc/finalize_traitor()
switch(traitor_kind)
if(TRAITOR_AI)
add_law_zero()
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE)
owner.current.grant_language(/datum/language/codespeak)
if(TRAITOR_HUMAN)
if(should_equip)
equip(silent)
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/tatoralert.ogg', 100, FALSE, pressure_affected = FALSE)
if(traitor_kind.finalize_traitor(src))
if(should_equip)
equip(silent)
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/tatoralert.ogg', 100, FALSE, pressure_affected = FALSE)
/datum/antagonist/traitor/apply_innate_effects(mob/living/mob_override)
. = ..()
update_traitor_icons_added()
var/mob/M = mob_override || owner.current
if(isAI(M) && traitor_kind == TRAITOR_AI)
var/mob/living/silicon/ai/A = M
A.hack_software = TRUE
traitor_kind.apply_innate_effects(M)
if(owner.assigned_role == "Clown")
var/mob/living/carbon/human/H = M
if(istype(H))
if(!silent)
to_chat(H, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.")
H.dna.remove_mutation(CLOWNMUT)
RegisterSignal(M, COMSIG_MOVABLE_HEAR, .proc/handle_hearing)
/datum/antagonist/traitor/remove_innate_effects(mob/living/mob_override)
. = ..()
update_traitor_icons_removed()
var/mob/M = mob_override || owner.current
if(isAI(M) && traitor_kind == TRAITOR_AI)
var/mob/living/silicon/ai/A = M
A.hack_software = FALSE
traitor_kind.remove_innate_effects(M)
if(owner.assigned_role == "Clown")
var/mob/living/carbon/human/H = M
if(istype(H))
H.dna.add_mutation(CLOWNMUT)
UnregisterSignal(M, COMSIG_MOVABLE_HEAR)
/datum/antagonist/traitor/proc/give_codewords()
@@ -326,8 +152,7 @@
killer.add_malf_picker()
/datum/antagonist/traitor/proc/equip(var/silent = FALSE)
if(traitor_kind == TRAITOR_HUMAN)
owner.equip_traitor(employer, silent, src)
owner.equip_traitor(traitor_kind, silent, src)
/datum/antagonist/traitor/proc/assign_exchange_role()
//set faction
+18 -39
View File
@@ -89,32 +89,17 @@
/datum/supply_pack/misc/paper_work
name = "Freelance Paper work"
desc = "The Nanotrasen Primary Bureaucratic Database Intelligence (PDBI) reports that the station has not completed its funding and grant paperwork this solar cycle. In order to gain further funding, your station is required to fill out (20) ten of these forms or no additional capital will be disbursed. We have sent you ten copies of the following form and we expect every one to be up to Nanotrasen Standards." // Disbursement. It's not a typo, look it up.
cost = 700 // Net of 0 credits but makes (120 x 20 = 2400)
desc = "The Nanotrasen Primary Bureaucratic Database Intelligence (PDBI) reports that the station has not completed its funding and grant paperwork this solar cycle. In order to gain further funding, your station is required to fill out (10) ten of these forms or no additional capital will be disbursed. We have sent you ten copies of the following form and we expect every one to be up to Nanotrasen Standards." // Disbursement. It's not a typo, look it up.
cost = 700 // Net of 0 credits but makes (120 x 10 = 1200)
contains = list(/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/pen/fountain
)
crate_name = "Paperwork"
/datum/supply_pack/misc/paper_work/generate()
. = ..()
for(var/i in 1 to 9)
new /obj/item/folder/paperwork(.)
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////// Entertainment ///////////////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -123,16 +108,14 @@
name = "Bedsheet Crate (R)"
desc = "Snuggle up in some sweet sheets with this assorted bedsheet crate. Each set comes with eight random bedsheets for your slumbering pleasure!"
cost = 2000
contains = list(/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random) //I'm lazy, and I copy paste stuff.
contains = list(/obj/item/bedsheet/random)
crate_name = "random bedsheet crate"
/datum/supply_pack/misc/randombedsheets/generate()
. = ..()
for(var/i in 1 to 7)
new /obj/item/bedsheet/random(.)
/datum/supply_pack/misc/coloredsheets
name = "Bedsheet Crate (C)"
desc = "Give your night life a splash of color with this crate filled with bedsheets! Contains a total of nine different-colored sheets."
@@ -208,13 +191,14 @@
name = "Dueling Pistols"
desc = "Resolve all your quarrels with some nonlethal fun."
cost = 2000
contains = list(/obj/item/storage/lockbox/dueling/hugbox/stamina,
/obj/item/storage/lockbox/dueling/hugbox/stamina,
/obj/item/storage/lockbox/dueling/hugbox/stamina,
/obj/item/storage/lockbox/dueling/hugbox/stamina,
/obj/item/storage/lockbox/dueling/hugbox/stamina)
contains = list(/obj/item/storage/lockbox/dueling/hugbox/stamina)
crate_name = "dueling pistols"
/datum/supply_pack/misc/dueling_stam/generate()
. = ..()
for(var/i in 1 to 3)
new /obj/item/storage/lockbox/dueling/hugbox/stamina(.)
/datum/supply_pack/misc/dueling_lethal
name = "Lethal Dueling Pistols"
desc = "Settle your differences the true spaceman way."
@@ -240,12 +224,7 @@
cost = 12000
var/num_contained = 3
contains = list(/obj/item/ammo_box/a357,
/obj/item/ammo_box/a357,
/obj/item/ammo_box/a357,
/obj/item/ammo_box/magazine/pistolm9mm,
/obj/item/ammo_box/magazine/pistolm9mm,
/obj/item/ammo_box/magazine/pistolm9mm,
/obj/item/ammo_box/magazine/m45/kitchengun,
/obj/item/ammo_box/magazine/m45/kitchengun)
crate_name = "crate"
@@ -97,6 +97,11 @@
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP
/obj/item/clothing/glasses/meson/eyepatch
name = "eyepatch mesons"
desc = "A meson system that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "mesonpatch"
/obj/item/clothing/glasses/science
name = "science goggles"
desc = "A pair of snazzy goggles used to protect against chemical spills. Fitted with an analyzer for scanning items and reagents."
+17 -6
View File
@@ -83,6 +83,11 @@
name = "prescription medical HUDSunglasses"
vision_correction = 1
/obj/item/clothing/glasses/hud/health/eyepatch
name = "eyepatch medHUD"
desc = "A heads-up display that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "medpatch"
///////////////////
//Diagnostic Huds//
///////////////////
@@ -97,7 +102,8 @@
/obj/item/clothing/glasses/hud/diagnostic/sunglasses
name = "diagnostic HUDSunglasses"
desc = "Sunglasses with a diagnostic HUD."
icon_state = "sunhuddiagnostic"
icon_state = "sunhuddiag"
item_state = "glasses"
darkness_view = 1
flash_protect = 1
tint = 1
@@ -123,6 +129,11 @@
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/hud/diagnostic/eyepatch
name = "eyepatch diagnostic HUD"
desc = "A heads-up display that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "diagpatch"
////////////
//Sec Huds//
////////////
@@ -165,11 +176,6 @@
return
chameleon_action.emp_randomise()
/obj/item/clothing/glasses/hud/security/sunglasses/eyepatch
name = "eyepatch HUD"
desc = "A heads-up display that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "hudpatch"
/obj/item/clothing/glasses/hud/security/sunglasses
name = "security HUDSunglasses"
desc = "Sunglasses with a security HUD."
@@ -179,6 +185,11 @@
tint = 1
glass_colour_type = /datum/client_colour/glass_colour/darkred
/obj/item/clothing/glasses/hud/security/sunglasses/eyepatch // why was this defined *before* the sunglasses it is a subtype of.
name = "eyepatch HUD"
desc = "A heads-up display that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "hudpatch"
/obj/item/clothing/glasses/hud/security/sunglasses/prescription
name = "prescription security HUDSunglasses"
vision_correction = 1
@@ -44,8 +44,8 @@
if(ishuman(hit_atom))
var/mob/living/carbon/human/H = hit_atom
var/mutable_appearance/creamoverlay = mutable_appearance('icons/effects/creampie.dmi')
if(H.dna.species.limbs_id == "lizard")
creamoverlay.icon_state = "creampie_lizard"
if((("mam_snouts" in H.dna.species.default_features) && H.dna.features["mam_snouts"] != "None") || (("snout" in H.dna.species.default_features) && H.dna.features["snout"] != "None"))
creamoverlay.icon_state = "creampie_snout"
else
creamoverlay.icon_state = "creampie_human"
if(stunning)
@@ -53,7 +53,7 @@
H.adjust_blurriness(1)
H.visible_message("<span class='warning'>[H] is creamed by [src]!</span>", "<span class='userdanger'>You've been creamed by [src]!</span>")
playsound(H, "desceration", 50, TRUE)
if(!H.is_mouth_covered())
if(!H.is_mouth_covered())
reagents.trans_to(H,15) //Cream pie combat
if(!H.creamed) // one layer at a time
H.add_overlay(creamoverlay)
@@ -139,6 +139,9 @@
icon = 'icons/obj/lavaland/survival_pod.dmi'
icon_state = "sleeper"
/obj/machinery/sleeper/survival_pod/update_icon_state()
return
/obj/machinery/sleeper/survival_pod/update_overlays()
. = ..()
if(!state_open)
@@ -189,7 +192,7 @@
flags_1 = NODECONSTRUCT_1
var/empty = FALSE
/obj/machinery/stasis/survival_pod/ComponentInitialize()
/obj/machinery/smartfridge/survival_pod/ComponentInitialize()
. = ..()
AddElement(/datum/element/update_icon_blocker)
+3
View File
@@ -24,6 +24,9 @@
/obj/item/mmi/update_overlays()
. = ..()
. += add_mmi_overlay()
/obj/item/mmi/proc/add_mmi_overlay()
if(brainmob && brainmob.stat != DEAD)
. += "mmi_alive"
else
@@ -193,3 +193,6 @@ GLOBAL_VAR(posibrain_notify_cooldown)
icon_state = "[initial(icon_state)]-occupied"
else
icon_state = initial(icon_state)
/obj/item/mmi/posibrain/add_mmi_overlay()
return
@@ -264,11 +264,11 @@
jitteriness += 1000 //High numbers for violent convulsions
do_jitter_animation(jitteriness)
stuttering += 2
if((!(flags & SHOCK_TESLA) || siemens_coeff > 0.5) && (flags & SHOCK_NOSTUN))
if((!(flags & SHOCK_TESLA) || siemens_coeff > 0.5) && !(flags & SHOCK_NOSTUN))
Stun(40)
spawn(20)
jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less
if((!(flags & SHOCK_TESLA) || siemens_coeff > 0.5) && (flags & SHOCK_NOSTUN))
if((!(flags & SHOCK_TESLA) || siemens_coeff > 0.5) && !(flags & SHOCK_NOSTUN))
DefaultCombatKnockdown(60)
return shock_damage
@@ -242,6 +242,12 @@
return
if(href_list["pockets"])
var/strip_mod = 1
var/strip_silence = FALSE
var/obj/item/clothing/gloves/g = gloves
if (istype(g))
strip_mod = g.strip_mod
strip_silence = g.strip_silence
var/pocket_side = href_list["pockets"]
var/pocket_id = (pocket_side == "right" ? SLOT_R_STORE : SLOT_L_STORE)
var/obj/item/pocket_item = (pocket_id == SLOT_R_STORE ? r_store : l_store)
@@ -258,7 +264,7 @@
else
return
if(do_mob(usr, src, POCKET_STRIP_DELAY/delay_denominator, ignorehelditem = TRUE)) //placing an item into the pocket is 4 times faster
if(do_mob(usr, src, max(round(POCKET_STRIP_DELAY/(delay_denominator*strip_mod)),1), ignorehelditem = TRUE)) //placing an item into the pocket is 4 times faster (and the strip_mod too)
if(pocket_item)
if(pocket_item == (pocket_id == SLOT_R_STORE ? r_store : l_store)) //item still in the pocket we search
dropItemToGround(pocket_item)
@@ -276,7 +282,8 @@
show_inv(usr)
else
// Display a warning if the user mocks up
to_chat(src, "<span class='warning'>You feel your [pocket_side] pocket being fumbled with!</span>")
if (!strip_silence)
to_chat(src, "<span class='warning'>You feel your [pocket_side] pocket being fumbled with!</span>")
..() //CITADEL CHANGE - removes a tab from behind this ..() so that flavortext can actually be examined
@@ -397,7 +397,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(I.flags_inv & HIDEFACIALHAIR)
facialhair_hidden = TRUE
if(H.wear_mask)
if(H.wear_mask && istype(H.wear_mask))
var/obj/item/clothing/mask/M = H.wear_mask
dynamic_fhair_suffix = M.dynamic_fhair_suffix //mask > head in terms of facial hair
if(M.flags_inv & HIDEFACIALHAIR)
@@ -451,7 +451,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(I.flags_inv & HIDEHAIR)
hair_hidden = TRUE
if(H.wear_mask)
if(H.wear_mask && istype(H.wear_mask))
var/obj/item/clothing/mask/M = H.wear_mask
if(!dynamic_hair_suffix) //head > mask in terms of head hair
dynamic_hair_suffix = M.dynamic_hair_suffix
@@ -1116,6 +1116,7 @@
desc = "Stop controlling your shell and resume normal core operations."
icon_icon = 'icons/mob/actions/actions_AI.dmi'
button_icon_state = "ai_core"
required_mobility_flags = NONE
/datum/action/innate/undeployment/Trigger()
if(!..())
@@ -821,7 +821,6 @@
/obj/item/gps/cyborg,
/obj/item/weapon/gripper/mining,
/obj/item/cyborg_clamp,
/obj/item/card/id/miningborg,
/obj/item/stack/marker_beacon,
/obj/item/destTagger,
/obj/item/stack/packageWrap)
@@ -1023,4 +1022,4 @@
/datum/robot_energy_storage/wrapping_paper
max_energy = 30
recharge_rate = 1
name = "Wrapping Paper Storage"
name = "Wrapping Paper Storage"
@@ -363,10 +363,8 @@
icon_dead = "old_corgi_dead"
desc = "At a ripe old age of [record_age] Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP
turns_per_move = 20
var/datum/element/mob_holder/ele = SSdcs.GetElement(/datum/element/mob_holder, held_icon)
if(ele)
ele.Detach(src)
AddElement(/datum/element/mob_holder, "old_corgi")
RemoveElement(/datum/element/mob_holder, held_icon)
AddElement(/datum/element/mob_holder, "old_corgi")
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
@@ -447,7 +445,7 @@
sleep(3)
step_to(src,movement_target,1)
if(movement_target) //Not redundant due to sleeps, Item can be gone in 6 decisecomds
if(movement_target?.loc) //Not redundant due to sleeps, Item can be gone in 6 decisecomds
if (movement_target.loc.x < src.x)
setDir(WEST)
else if (movement_target.loc.x > src.x)
@@ -64,7 +64,7 @@
..()
/mob/living/simple_animal/mouse/handle_automated_action()
if(isbelly(loc))
if(!isturf(loc))
return
if(prob(chew_probability))
@@ -76,7 +76,7 @@
visible_message("<span class='warning'>[src] chews through the [C]. It's toast!</span>")
playsound(src, 'sound/effects/sparks2.ogg', 100, 1)
C.deconstruct()
death(toast=1)
death(toast=TRUE)
else
C.deconstruct()
visible_message("<span class='warning'>[src] chews through the [C].</span>")
@@ -204,7 +204,7 @@
rapid = 2
icon_state = "syndicate_smg"
icon_living = "syndicate_smg"
casingtype = /obj/item/ammo_casing/c45/nostamina
casingtype = /obj/item/ammo_casing/c45
projectilesound = 'sound/weapons/gunshot_smg.ogg'
/mob/living/simple_animal/hostile/syndicate/ranged/smg/pilot //caravan ambush ruin
+8 -2
View File
@@ -19,9 +19,15 @@
/mob/proc/set_dizziness(amount)
dizziness = max(amount, 0)
///Blind a mobs eyes by amount
/**
* Sets a mob's blindness to an amount if it was not above it already, similar to how status effects work
*/
/mob/proc/blind_eyes(amount)
adjust_blindness(amount)
var/old_blind = eye_blind || HAS_TRAIT(src, TRAIT_BLIND)
eye_blind = max(eye_blind, amount)
var/new_blind = eye_blind || HAS_TRAIT(src, TRAIT_BLIND)
if(old_blind != new_blind)
update_blindness()
/**
* Adjust a mobs blindness by an amount
@@ -12,6 +12,10 @@
battery = new battery_type(src)
..()
/obj/item/computer_hardware/battery/Destroy()
. = ..()
QDEL_NULL(battery)
/obj/item/computer_hardware/battery/try_insert(obj/item/I, mob/living/user = null)
if(!holder)
return FALSE
+3
View File
@@ -70,6 +70,9 @@
else
. = FALSE //as to not cancel attack_hand()
/obj/item/clothing/gloves/space_ninja/dropped(mob/user)
. = ..()
REMOVE_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT)
/obj/item/clothing/gloves/space_ninja/proc/toggledrain()
var/mob/living/carbon/human/U = loc
+5 -1
View File
@@ -9,4 +9,8 @@
strip_delay = 12
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
blockTracking = 1//Roughly the only unique thing about this helmet.
flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
/obj/item/clothing/head/helmet/space/space_ninja/dropped(mob/user)
. = ..()
REMOVE_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT)
+4
View File
@@ -19,6 +19,10 @@ Contents:
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
modifies_speech = TRUE
/obj/item/clothing/mask/gas/space_ninja/dropped(mob/user)
. = ..()
REMOVE_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT)
/obj/item/clothing/mask/gas/space_ninja/handle_speech(datum/source, list/speech_args)
var/message = speech_args[SPEECH_MESSAGE]
if(message[1] != "*")
@@ -24,9 +24,6 @@
caliber = ".45"
projectile_type = /obj/item/projectile/bullet/c45
/obj/item/ammo_casing/c45/nostamina
projectile_type = /obj/item/projectile/bullet/c45_nostamina
/obj/item/ammo_casing/c45/kitchengun
desc = "A .45 bullet casing. It has a small sponge attached to it."
projectile_type = /obj/item/projectile/bullet/c45_cleaning
+1 -1
View File
@@ -60,7 +60,7 @@
/obj/item/ammo_box/magazine/smgm45
name = "SMG magazine (.45)"
icon_state = "c20r45-24"
ammo_type = /obj/item/ammo_casing/c45/nostamina
ammo_type = /obj/item/ammo_casing/c45
caliber = ".45"
max_ammo = 24
@@ -47,7 +47,7 @@
var/mob/current_user = null
var/list/obj/effect/projectile/tracer/current_tracers
var/structure_piercing = 1
var/structure_piercing = 0
var/structure_bleed_coeff = 0.7
var/wall_pierce_amount = 0
var/wall_devastate = 0
@@ -60,7 +60,7 @@
var/impact_structure_damage = 75
var/projectile_damage = 40
var/projectile_stun = 0
var/projectile_setting_pierce = TRUE
var/projectile_setting_pierce = FALSE
var/delay = 30
var/lastfire = 0
@@ -160,6 +160,9 @@
add_overlay(drained_overlay)
/obj/item/gun/energy/beam_rifle/attack_self(mob/user)
if(!structure_piercing)
projectile_setting_pierce = FALSE
return
projectile_setting_pierce = !projectile_setting_pierce
to_chat(user, "<span class='boldnotice'>You set \the [src] to [projectile_setting_pierce? "pierce":"impact"] mode.</span>")
aiming_beam()
@@ -402,7 +405,7 @@
/obj/item/ammo_casing/energy/beam_rifle/hitscan
projectile_type = /obj/item/projectile/beam/beam_rifle/hitscan
select_name = "beam"
e_cost = 5000
e_cost = 10000
fire_sound = 'sound/weapons/beam_sniper.ogg'
/obj/item/projectile/beam/beam_rifle
@@ -557,9 +560,4 @@
hitscan_light_color_override = "#99ff99"
/obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/prehit(atom/target)
qdel(src)
return FALSE
/obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/on_hit()
qdel(src)
return BULLET_ACT_HIT
@@ -1,18 +1,12 @@
// .45 (M1911 & C20r)
/obj/item/projectile/bullet/c45
name = ".45 bullet"
damage = 20
stamina = 65
/obj/item/projectile/bullet/c45_nostamina
name = ".45 bullet"
damage = 30
/obj/item/projectile/bullet/c45_cleaning
name = ".45 bullet"
damage = 24
stamina = 10
damage = 40 //BANG BANG BANG
/obj/item/projectile/bullet/c45_cleaning/on_hit(atom/target, blocked = FALSE)
. = ..()
+3 -4
View File
@@ -43,14 +43,14 @@
set_APTFT()
return TRUE
/obj/item/reagent_containers/proc/set_APTFT(mob/user) //set amount_per_transfer_from_this
/obj/item/reagent_containers/proc/set_APTFT() //set amount_per_transfer_from_this
set name = "Set Transfer Amount"
set category = "Object"
set waitfor = FALSE
var/N = input("Amount per transfer from this:","[src]") as null|anything in possible_transfer_amounts
if(N)
amount_per_transfer_from_this = N
to_chat(user, "<span class='notice'>[src]'s transfer amount is now [amount_per_transfer_from_this] units.</span>")
to_chat(usr, "<span class='notice'>[src]'s transfer amount is now [amount_per_transfer_from_this] units.</span>")
/obj/item/reagent_containers/proc/add_initial_reagents()
if(list_reagents)
@@ -134,6 +134,7 @@
throwerstring = " THROWN BY [key_name(thrownby)] at [AT] (AREACOORD(AT)]"
log_reagent("SPLASH: [src] mob SplashReagents() onto [key_name(target)] at [TT] ([AREACOORD(TT)])[throwerstring] - [R]")
reagents.reaction(target, TOUCH)
reagents.clear_reagents()
else if(bartender_check(target) && thrown)
visible_message("<span class='notice'>[src] lands without spilling a single drop.</span>")
@@ -154,8 +155,6 @@
visible_message("<span class='notice'>[src] spills its contents all over [target].</span>")
reagents.reaction(target, TOUCH)
reagents.clear_reagents()
if(QDELETED(src))
return
//melts plastic beakers
/obj/item/reagent_containers/microwave_act(obj/machinery/microwave/M)
@@ -28,7 +28,7 @@ Borg Hypospray
var/list/datum/reagents/reagent_list = list()
var/list/reagent_ids = list(/datum/reagent/medicine/dexalin, /datum/reagent/medicine/kelotane, /datum/reagent/medicine/bicaridine, /datum/reagent/medicine/antitoxin,
/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/spaceacillin, /datum/reagent/medicine/salglu_solution, /datum/reagent/medicine/insulin)
/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/spaceacillin, /datum/reagent/medicine/salglu_solution, /datum/reagent/medicine/insulin, /datum/reagent/medicine/potass_iodide)
var/accepts_reagent_upgrades = TRUE //If upgrades can increase number of reagents dispensed.
var/list/modes = list() //Basically the inverse of reagent_ids. Instead of having numbers as "keys" and strings as values it has strings as keys and numbers as values.
//Used as list for input() in shakers.
@@ -164,7 +164,7 @@ Borg Hypospray
icon_state = "borghypo_s"
charge_cost = 20
recharge_time = 2
reagent_ids = list(/datum/reagent/medicine/syndicate_nanites, /datum/reagent/medicine/potass_iodide, /datum/reagent/medicine/morphine, /datum/reagent/medicine/insulin)
reagent_ids = list(/datum/reagent/medicine/syndicate_nanites, /datum/reagent/medicine/prussian_blue, /datum/reagent/medicine/morphine, /datum/reagent/medicine/insulin)
bypass_protection = 1
accepts_reagent_upgrades = FALSE
@@ -261,5 +261,5 @@ Borg Shaker
/obj/item/reagent_containers/borghypo/epi
name = "Stabilizer injector"
desc = "An advanced chemical synthesizer and injection system, designed to stabilize patients."
reagent_ids = list(/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/insulin)
reagent_ids = list(/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/insulin, /datum/reagent/medicine/potass_iodide)
accepts_reagent_upgrades = FALSE
@@ -35,6 +35,17 @@
dangerous_construction = TRUE
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
/datum/design/duffelbag_holding
name = "Duffel Bag of Holding"
desc = "A duffel bag that opens into a localized pocket of bluespace."
id = "duffelbag_holding"
build_type = PROTOLATHE
materials = list(/datum/material/gold = 3000, /datum/material/diamond = 1500, /datum/material/uranium = 250, /datum/material/bluespace = 2000)
build_path = /obj/item/storage/backpack/holding/duffel
category = list("Bluespace Designs")
dangerous_construction = TRUE
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
/datum/design/biobag_holding
name = "Bio Bag of Holding"
desc = "A chemical holding thingy. Mostly used for xenobiology."
@@ -633,15 +633,6 @@
construction_time = 120
category = list("Cyborg Upgrade Modules")
/datum/design/borg_upgrade_premiumka
name = "Cyborg Upgrade (Premium Kinetic Accelerator)"
id = "borg_upgrade_premiumka"
build_type = MECHFAB
build_path = /obj/item/borg/upgrade/premiumka
materials = list(/datum/material/iron=8000, /datum/material/glass=4000, /datum/material/titanium=2000)
construction_time = 120
category = list("Cyborg Upgrade Modules")
/datum/design/borg_upgrade_lavaproof
name = "Cyborg Upgrade (Lavaproof Tracks)"
id = "borg_upgrade_lavaproof"
+2 -2
View File
@@ -278,7 +278,7 @@
display_name = "Bluespace Pockets"
description = "Studies into the mysterious alternate dimension known as bluespace and how to place items in the threads of reality."
prereq_ids = list("adv_power", "adv_bluespace", "adv_biotech", "adv_plasma")
design_ids = list( "bluespacebodybag","bag_holding", "bluespace_pod", "borg_upgrade_trashofholding", "blutrash", "satchel_holding", "bsblood_bag")
design_ids = list( "bluespacebodybag","bag_holding", "bluespace_pod", "borg_upgrade_trashofholding", "blutrash", "satchel_holding", "bsblood_bag", "duffelbag_holding")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5500)
/datum/techweb_node/bluespace_portal
@@ -336,7 +336,7 @@
display_name = "Advanced Robotics Research"
description = "It can even do the dishes!"
prereq_ids = list("robotics")
design_ids = list("borg_upgrade_diamonddrill", "borg_upgrade_advancedmop", "borg_upgrade_advcutter", "borg_upgrade_premiumka")
design_ids = list("borg_upgrade_diamonddrill", "borg_upgrade_advancedmop", "borg_upgrade_advcutter")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000)
/datum/techweb_node/neural_programming
+2
View File
@@ -319,6 +319,8 @@
on_mob.forceMove(scanning)
for(var/i in 1 to light_beam_distance)
scanning = get_step(scanning, scandir)
if(!scanning)
break
if(scanning.opacity || scanning.has_opaque_atom)
stop = TRUE
var/obj/effect/abstract/eye_lighting/L = LAZYACCESS(eye_lighting, i)
+3 -2
View File
@@ -1,4 +1,4 @@
/proc/get_uplink_items(datum/game_mode/gamemode, allow_sales = TRUE, allow_restricted = TRUE)
/proc/get_uplink_items(datum/game_mode/gamemode, allow_sales = TRUE, allow_restricted = TRUE, other_filter = list())
var/list/filtered_uplink_items = GLOB.uplink_categories.Copy() // list of uplink categories without associated values.
var/list/sale_items = list()
@@ -18,7 +18,8 @@
continue
if (I.restricted && !allow_restricted)
continue
if (I.type in other_filter)
continue
LAZYSET(filtered_uplink_items[I.category], I.name, I)
if(I.limited_stock < 0 && !I.cant_discount && I.item && I.cost > 1)
@@ -159,7 +159,7 @@
/datum/uplink_item/role_restricted/kitchen_gun
name = "Kitchen Gun (TM)"
desc = "A revolutionary .45 caliber cleaning solution! Say goodbye to daily stains and dirty surfaces with Kitchen Gun (TM)! \
Just five shots from Kitchen Gun (TM), and it'll sparkle like new! Includes two extra ammunition clips!"
Just three shots from Kitchen Gun (TM), and it'll sparkle like new! Includes two extra ammunition clips!"
cost = 10
surplus = 40
restricted_roles = list("Cook", "Janitor")
@@ -0,0 +1,4 @@
author: "Putnam3145"
delete-after: True
changes:
- rscadd: "Traitor classes for traitors: a new way for traitors to have objectives assigned."
@@ -0,0 +1,5 @@
author: "Trilbyspaceclone"
delete-after: True
changes:
- tweak: "Number of paper work in the crate \"freelance paperwork\" is half"
- code_imp: "A few cases were something their is unneeded copy past replaced with many 1 in spawns"
@@ -0,0 +1,4 @@
author: "bunny232"
delete-after: True
changes:
- rscadd: "Box station captain office now has a standard issue renault"
@@ -0,0 +1,5 @@
author: "Trilbyspaceclone"
delete-after: True
changes:
- rscadd: "Potass Iodide has been fitted into standered borgs as well as medical ones. Upgraded hypos now have Prussian Blue as well."
- tweak: "Syndi borgs Potass Iodide has been swapped for Prussian Blue"
@@ -0,0 +1,4 @@
author: "Kraseo"
delete-after: True
changes:
- bugfix: "Mice don't chew on wires anymore while they're on your person."
@@ -0,0 +1,4 @@
author: "Kraseo"
delete-after: True
changes:
- bugfix: "Bloodsucker heart theft objective now completes successfully."
@@ -0,0 +1,7 @@
author: "Qustinnus/floyd, Ghommie"
delete-after: True
changes:
- bugfix: "To save costs, Nanotrasen has removed the emergency battery ejection systems in modular computers. We realized saving the batteries isn't really important."
- bugfix: "You can squash spiderlings with your bare hands now."
- bugfix: "Being deafened properly stops jukebox music from playing."
- bugfix: "admin multicam toggles no longer tells everyone but only admins and AIs"
@@ -0,0 +1,4 @@
author: "Putnam3145"
delete-after: True
changes:
- bugfix: "Server-run votes aren't subject to vote cooldown"
@@ -0,0 +1,4 @@
author: "Seris02"
delete-after: True
changes:
- rscadd: "duffel bags of holding"
@@ -0,0 +1,4 @@
author: "Seris02"
delete-after: True
changes:
- bugfix: "quirk blacklist fixing"
@@ -0,0 +1,4 @@
author: "Kraseo"
delete-after: True
changes:
- tweak: "Blacklists turret protected areas, the toxins test range, asteroid ruins, and solars from being valid dropoff locations for contracts."
@@ -0,0 +1,4 @@
author: "zeroisthebiggay"
delete-after: True
changes:
- rscadd: "Box Station has gotten a brand new brig. Go and check it out and discover all the quirky little soulbits."
@@ -0,0 +1,4 @@
author: "kappa-sama"
delete-after: True
changes:
- balance: "60 seconds instead of 120 for firebreath"
@@ -0,0 +1,4 @@
author: "Seris02"
delete-after: True
changes:
- bugfix: "robotics console button swapping"
@@ -0,0 +1,4 @@
author: "kevinz000"
delete-after: True
changes:
- balance: "Beam rifles shot count 10 --> 5 and can no longer pierce. Also renders properly for reflections against blobs and some other things."
@@ -0,0 +1,4 @@
author: "Hatterhat"
delete-after: True
changes:
- rscdel: "Mining cyborgs are no longer physically capable of claiming points nor wielding a premium accelerator."
@@ -0,0 +1,4 @@
author: "Yenwodyah"
delete-after: True
changes:
- bugfix: "Recycler doesn't delete people in mechs, cardboard boxes, spells, etc. anymore."
@@ -0,0 +1,4 @@
author: "bunny232"
delete-after: True
changes:
- bugfix: "Box bridge now actually has the air distro connected"
@@ -0,0 +1,4 @@
author: "Trilbyspaceclone"
delete-after: True
changes:
- bugfix: "No longer can you get the The End and Russian Flask without being the donator"
@@ -0,0 +1,6 @@
author: "Arreksuru and Detective Google"
delete-after: True
changes:
- rscadd: "new HUDpatches for medical, diagnostic, and mesons."
- rscadd: "crafting and de-crafting recipes for new HUDpatches."
- bugfix: "silly typo with \"singlasses\" in one of the crafting recipes for HUDglasses."
@@ -0,0 +1,5 @@
author: "BlackMajor"
delete-after: True
changes:
- tweak: "Adjusted the ash walker camp's storm proofing."
- rscadd: "Added a tip about creating areas to the ash walker spawn text."
@@ -0,0 +1,4 @@
author: "Seris02"
delete-after: True
changes:
- bugfix: "fixed thieving gloves not pickpocketing fast"

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