Merge branch 'master' into void-but-for-real

This commit is contained in:
kiwedespars
2021-03-09 12:29:50 -08:00
772 changed files with 32091 additions and 23389 deletions
+51 -8
View File
@@ -885,6 +885,9 @@
VV_DROPDOWN_OPTION(VV_HK_ADD_REAGENT, "Add Reagent")
VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EMP, "EMP Pulse")
VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EXPLOSION, "Explosion")
// VV_DROPDOWN_OPTION(VV_HK_RADIATE, "Radiate")
VV_DROPDOWN_OPTION(VV_HK_EDIT_FILTERS, "Edit Filters")
// VV_DROPDOWN_OPTION(VV_HK_ADD_AI, "Add AI controller")
/atom/vv_do_topic(list/href_list)
. = ..()
@@ -928,6 +931,9 @@
var/newname = input(usr, "What do you want to rename this to?", "Automatic Rename") as null|text
if(newname)
vv_auto_rename(newname)
if(href_list[VV_HK_EDIT_FILTERS] && check_rights(R_VAREDIT))
var/client/C = usr.client
C?.open_filter_editor(src)
/atom/vv_get_header()
. = ..()
@@ -1148,7 +1154,6 @@
victim.log_message(message, LOG_ATTACK, color="blue")
// Filter stuff
/atom/proc/add_filter(name,priority,list/params)
LAZYINITLIST(filter_data)
var/list/p = params.Copy()
@@ -1164,26 +1169,64 @@
var/list/arguments = data.Copy()
arguments -= "priority"
filters += filter(arglist(arguments))
UNSETEMPTY(filter_data)
/atom/proc/transition_filter(name, time, list/new_params, easing, loop)
var/filter = get_filter(name)
if(!filter)
return
var/list/old_filter_data = filter_data[name]
var/list/params = old_filter_data.Copy()
for(var/thing in new_params)
params[thing] = new_params[thing]
animate(filter, new_params, time = time, easing = easing, loop = loop)
for(var/param in params)
filter_data[name][param] = params[param]
/atom/proc/change_filter_priority(name, new_priority)
if(!filter_data || !filter_data[name])
return
filter_data[name]["priority"] = new_priority
update_filters()
/obj/item/update_filters()
. = ..()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
/atom/proc/get_filter(name)
if(filter_data && filter_data[name])
return filters[filter_data.Find(name)]
/atom/proc/remove_filter(name)
if(filter_data && filter_data[name])
filter_data -= name
update_filters()
return TRUE
/atom/proc/remove_filter(name_or_names)
if(!filter_data)
return
var/list/names = islist(name_or_names) ? name_or_names : list(name_or_names)
for(var/name in names)
if(filter_data[name])
filter_data -= name
update_filters()
/atom/proc/clear_filters()
filter_data = null
filters = null
/atom/proc/intercept_zImpact(atom/movable/AM, levels = 1)
. |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, AM, levels)
///Sets the custom materials for an item.
/atom/proc/set_custom_materials(var/list/materials, multiplier = 1)
/atom/proc/set_custom_materials(list/materials, multiplier = 1)
if(custom_materials) //Only runs if custom materials existed at first. Should usually be the case but check anyways
for(var/i in custom_materials)
var/datum/material/custom_material = SSmaterials.GetMaterialRef(i)
custom_material.on_removed(src, material_flags) //Remove the current materials
custom_material.on_removed(src, custom_materials[i], material_flags) //Remove the current materials
if(!length(materials))
custom_materials = null
@@ -106,6 +106,7 @@
for(var/i in 1 to 3)
if(config_tag in saved_dynamic_rules[i])
weight_mult -= (repeated_mode_adjust[i]/100)
weight_mult = max(0,weight_mult)
if(config_tag in costs)
cost = costs[config_tag]
if(config_tag in requirementses)
+23 -10
View File
@@ -81,30 +81,43 @@
///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things
/datum/game_mode/proc/post_setup(report) //Gamemodes can override the intercept report. Passing TRUE as the argument will force a report.
//finalize_monster_hunters() Disabled for now
if(!report)
report = !CONFIG_GET(flag/no_intercept_report)
addtimer(CALLBACK(GLOBAL_PROC, .proc/display_roundstart_logout_report), ROUNDSTART_LOGOUT_REPORT_TIME)
if(prob(20)) //CIT CHANGE - adds a 20% chance for the security level to be the opposite of what it normally is
if(prob(20)) //cit-change
flipseclevel = TRUE
// if(CONFIG_GET(flag/reopen_roundstart_suicide_roles))
// var/delay = CONFIG_GET(number/reopen_roundstart_suicide_roles_delay)
// if(delay)
// delay = (delay SECONDS)
// else
// delay = (4 MINUTES) //default to 4 minutes if the delay isn't defined.
// addtimer(CALLBACK(GLOBAL_PROC, .proc/reopen_roundstart_suicide_roles), delay)
if(SSdbcore.Connect())
var/sql
var/list/to_set = list()
var/arguments = list()
if(SSticker.mode)
sql += "game_mode = '[SSticker.mode]'"
to_set += "game_mode = :game_mode"
arguments["game_mode"] = SSticker.mode
if(GLOB.revdata.originmastercommit)
if(sql)
sql += ", "
sql += "commit_hash = '[GLOB.revdata.originmastercommit]'"
if(sql)
var/datum/DBQuery/query_round_game_mode = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET [sql] WHERE id = [GLOB.round_id]")
to_set += "commit_hash = :commit_hash"
arguments["commit_hash"] = GLOB.revdata.originmastercommit
if(to_set.len)
arguments["round_id"] = GLOB.round_id
var/datum/db_query/query_round_game_mode = SSdbcore.NewQuery(
"UPDATE [format_table_name("round")] SET [to_set.Join(", ")] WHERE id = :round_id",
arguments
)
query_round_game_mode.Execute()
qdel(query_round_game_mode)
if(report)
addtimer(CALLBACK(src, .proc/send_intercept, 0), rand(waittime_l, waittime_h))
generate_station_goals()
gamemode_ready = TRUE
return 1
return TRUE
///Handles late-join antag assignments
+42 -41
View File
@@ -1,4 +1,6 @@
#define DEFAULT_METEOR_LIFETIME 1800
#define MAP_EDGE_PAD 5
GLOBAL_VAR_INIT(meteor_wave_delay, 625) //minimum wait between waves in tenths of seconds
//set to at least 100 unless you want evarr ruining every round
@@ -30,7 +32,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
var/turf/pickedgoal
var/max_i = 10//number of tries to spawn meteor.
while(!isspaceturf(pickedstart))
var/startSide = dir || pick(GLOB.cardinals)
var/startSide = (dir ? dir : pick(GLOB.cardinals))
var/startZ = pick(SSmapping.levels_by_trait(ZTRAIT_STATION))
pickedstart = spaceDebrisStartLoc(startSide, startZ)
pickedgoal = spaceDebrisFinishLoc(startSide, startZ)
@@ -46,17 +48,17 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
var/startx
switch(startSide)
if(NORTH)
starty = world.maxy-(TRANSITIONEDGE+2)
startx = rand((TRANSITIONEDGE+2), world.maxx-(TRANSITIONEDGE+2))
starty = world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD)
startx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD))
if(EAST)
starty = rand((TRANSITIONEDGE+2),world.maxy-(TRANSITIONEDGE+2))
startx = world.maxx-(TRANSITIONEDGE+2)
starty = rand((TRANSITIONEDGE + MAP_EDGE_PAD),world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD))
startx = world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD)
if(SOUTH)
starty = (TRANSITIONEDGE+2)
startx = rand((TRANSITIONEDGE+2), world.maxx-(TRANSITIONEDGE+2))
starty = (TRANSITIONEDGE + MAP_EDGE_PAD)
startx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD))
if(WEST)
starty = rand((TRANSITIONEDGE+2), world.maxy-(TRANSITIONEDGE+2))
startx = (TRANSITIONEDGE+2)
starty = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD))
startx = (TRANSITIONEDGE + MAP_EDGE_PAD)
. = locate(startx, starty, Z)
/proc/spaceDebrisFinishLoc(startSide, Z)
@@ -64,17 +66,17 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
var/endx
switch(startSide)
if(NORTH)
endy = (TRANSITIONEDGE+1)
endx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
endy = (TRANSITIONEDGE + MAP_EDGE_PAD)
endx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD))
if(EAST)
endy = rand((TRANSITIONEDGE+1), world.maxy-(TRANSITIONEDGE+1))
endx = (TRANSITIONEDGE+1)
endy = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD))
endx = (TRANSITIONEDGE + MAP_EDGE_PAD)
if(SOUTH)
endy = world.maxy-(TRANSITIONEDGE+1)
endx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
endy = world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD)
endx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD))
if(WEST)
endy = rand((TRANSITIONEDGE+1),world.maxy-(TRANSITIONEDGE+1))
endx = world.maxx-(TRANSITIONEDGE+1)
endy = rand((TRANSITIONEDGE + MAP_EDGE_PAD),world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD))
endx = world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD)
. = locate(endx, endy, Z)
///////////////////////
@@ -82,7 +84,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
//////////////////////
/obj/effect/meteor
name = "the concept of meteor"
name = "\proper the concept of meteor"
desc = "You should probably run instead of gawking at this."
icon = 'icons/obj/meteor.dmi'
icon_state = "small"
@@ -92,7 +94,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
var/hitpwr = 2 //Level of ex_act to be called on hit.
var/dest
pass_flags = PASSTABLE
var/heavy = 0
var/heavy = FALSE
var/meteorsound = 'sound/effects/meteorimpact.ogg'
var/z_original
var/threat = 0 // used for determining which meteors are most interesting
@@ -108,12 +110,12 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
. = ..() //process movement...
var/turf/T = get_turf(loc)
if(.)//.. if did move, ram the turf we get in
var/turf/T = get_turf(loc)
ram_turf(T)
if(prob(10) && !isspaceturf(T) && !istype(T, /turf/closed/mineral) && !istype(T, /turf/open/floor/plating/asteroid))//randomly takes a 'hit' from ramming
get_hit()
if(prob(10) && !isspaceturf(T) && !istype(T, /turf/closed/mineral) && !istype(T, /turf/open/floor/plating/asteroid))//randomly takes a 'hit' from ramming, and ignore spare ruin aseroids
get_hit()
/obj/effect/meteor/Destroy()
if (timerid)
@@ -135,24 +137,25 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
/obj/effect/meteor/Bump(atom/A)
if(A)
ram_turf(get_turf(A))
playsound(src.loc, meteorsound, 40, 1)
if(!istype(A, /turf/closed/mineral) && !istype(A, /turf/open/floor/plating/asteroid))
playsound(src.loc, meteorsound, 40, TRUE)
if(!istype(A, /turf/closed/mineral) && !istype(A, /turf/open/floor/plating/asteroid)) // ignore localstation ruins
get_hit()
/obj/effect/meteor/proc/ram_turf(turf/T)
//first bust whatever is in the turf
for(var/atom/A in T)
if(A != src)
if(isliving(A))
A.visible_message("<span class='warning'>[src] slams into [A].</span>", "<span class='userdanger'>[src] slams into you!.</span>")
A.ex_act(hitpwr)
for(var/thing in T)
if(thing == src)
continue
if(isliving(thing))
var/mob/living/living_thing = thing
living_thing.visible_message("<span class='warning'>[src] slams into [living_thing].</span>", "<span class='userdanger'>[src] slams into you!.</span>")
living_thing.ex_act(hitpwr)
//then, ram the turf if it still exists
if(T)
T.ex_act(hitpwr)
//process getting 'hit' by colliding with a dense object
//or randomly when ramming turfs
/obj/effect/meteor/proc/get_hit()
@@ -162,13 +165,10 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
meteor_effect()
qdel(src)
/obj/effect/meteor/ex_act()
return
/obj/effect/meteor/examine(mob/user)
. = ..()
if(!(flags_1 & ADMIN_SPAWNED_1) && isliving(user))
SSmedals.UnlockMedal(MEDAL_METEOR, user.client)
return ..()
user.client.give_award(/datum/award/achievement/misc/meteor_examine, user)
/obj/effect/meteor/attackby(obj/item/I, mob/user, params)
if(I.tool_behaviour == TOOL_MINING)
@@ -232,7 +232,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
name = "big meteor"
icon_state = "large"
hits = 6
heavy = 1
heavy = TRUE
dropamt = 4
threat = 10
@@ -245,7 +245,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
name = "flaming meteor"
icon_state = "flaming"
hits = 5
heavy = 1
heavy = TRUE
meteorsound = 'sound/effects/bamf.ogg'
meteordrop = list(/obj/item/stack/ore/plasma)
threat = 20
@@ -258,7 +258,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
/obj/effect/meteor/irradiated
name = "glowing meteor"
icon_state = "glowing"
heavy = 1
heavy = TRUE
meteordrop = list(/obj/item/stack/ore/uranium)
threat = 15
@@ -275,7 +275,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
icon_state = "meateor"
desc = "Just... don't think too hard about where this thing came from."
hits = 2
heavy = 1
heavy = TRUE
meteorsound = 'sound/effects/blobattack.ogg'
meteordrop = list(/obj/item/reagent_containers/food/snacks/meat/slab/human, /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant, /obj/item/organ/heart, /obj/item/organ/lungs, /obj/item/organ/tongue, /obj/item/organ/appendix/)
var/meteorgibs = /obj/effect/gibspawner/generic
@@ -327,7 +327,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
desc = "Your life briefly passes before your eyes the moment you lay them on this monstrosity."
hits = 30
hitpwr = 1
heavy = 1
heavy = TRUE
meteorsound = 'sound/effects/bamf.ogg'
meteordrop = list(/obj/item/stack/ore/plasma)
threat = 50
@@ -358,7 +358,7 @@ GLOBAL_LIST_INIT(meteorsSPOOKY, list(/obj/effect/meteor/pumpkin))
icon = 'icons/obj/meteor_spooky.dmi'
icon_state = "pumpkin"
hits = 10
heavy = 1
heavy = TRUE
dropamt = 1
meteordrop = list(/obj/item/clothing/head/hardhat/pumpkinhead, /obj/item/reagent_containers/food/snacks/grown/pumpkin)
threat = 100
@@ -368,3 +368,4 @@ GLOBAL_LIST_INIT(meteorsSPOOKY, list(/obj/effect/meteor/pumpkin))
meteorsound = pick('sound/hallucinations/im_here1.ogg','sound/hallucinations/im_here2.ogg')
//////////////////////////
#undef DEFAULT_METEOR_LIFETIME
#undef MAP_EDGE_PAD
+41 -41
View File
@@ -1,6 +1,6 @@
#define AUTOLATHE_MAIN_MENU 1
#define AUTOLATHE_CATEGORY_MENU 2
#define AUTOLATHE_SEARCH_MENU 3
#define AUTOLATHE_MAIN_MENU 1
#define AUTOLATHE_CATEGORY_MENU 2
#define AUTOLATHE_SEARCH_MENU 3
/obj/machinery/autolathe
name = "autolathe"
@@ -17,7 +17,7 @@
var/list/L = list()
var/list/LL = list()
var/hacked = FALSE
var/disabled = 0
var/disabled = FALSE
var/shocked = FALSE
var/hack_wire
var/disable_wire
@@ -27,13 +27,13 @@
var/prod_coeff = 1
var/datum/design/being_built
var/datum/techweb/stored_research
var/list/datum/design/matching_designs
var/selected_category
var/screen = 1
var/base_price = 25
var/hacked_price = 50
var/datum/techweb/specialized/autounlocking/stored_research = /datum/techweb/specialized/autounlocking/autolathe
var/list/categories = list(
"Tools",
"Electronics",
@@ -46,19 +46,13 @@
"Dinnerware",
"Imported"
)
var/list/allowed_materials
/// Base print speed
var/base_print_speed = 10
/obj/machinery/autolathe/Initialize()
var/list/mats = allowed_materials
if(!mats)
mats = SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID]
AddComponent(/datum/component/material_container, mats, _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert))
AddComponent(/datum/component/material_container, SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID], 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
. = ..()
wires = new /datum/wires/autolathe(src)
stored_research = new stored_research
stored_research = new /datum/techweb/specialized/autounlocking/autolathe
matching_designs = list()
/obj/machinery/autolathe/Destroy()
@@ -83,7 +77,7 @@
if(AUTOLATHE_SEARCH_MENU)
dat = search_win(user)
var/datum/browser/popup = new(user, name, name, 400, 500)
var/datum/browser/popup = new(user, "autolathe", name, 400, 500)
popup.set_content(dat)
popup.open()
@@ -114,9 +108,9 @@
return TRUE
if(istype(O, /obj/item/disk/design_disk))
user.visible_message("[user] begins to load \the [O] in \the [src]...",
"You begin to load a design from \the [O]...",
"You hear the chatter of a floppy drive.")
user.visible_message("<span class='notice'>[user] begins to load \the [O] in \the [src]...</span>",
"<span class='notice'>You begin to load a design from \the [O]...</span>",
"<span class='hear'>You hear the chatter of a floppy drive.</span>")
busy = TRUE
var/obj/item/disk/design_disk/D = O
if(do_after(user, 14.4, target = src))
@@ -128,14 +122,16 @@
return ..()
/obj/machinery/autolathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
/obj/machinery/autolathe/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted)
if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal))
use_power(MINERAL_MATERIAL_AMOUNT / 10)
else if(item_inserted.custom_materials?.len && item_inserted.custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
else if(custom_materials && custom_materials.len && custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
flick("autolathe_r",src)//plays glass insertion animation by default otherwise
else
flick("autolathe_o",src)//plays metal insertion animation
use_power(min(1000, amount_inserted / 100))
updateUsrDialog()
@@ -187,7 +183,7 @@
if(materials.materials[i] > 0)
list_to_show += i
used_material = input("Choose [used_material]", "Custom Material") as null|anything in list_to_show
used_material = input("Choose [used_material]", "Custom Material") as null|anything in sortList(list_to_show, /proc/cmp_typepaths_asc)
if(!used_material)
return //Didn't pick any material, so you can't build shit either.
custom_materials[used_material] += amount_needed
@@ -198,8 +194,8 @@
busy = TRUE
use_power(power)
icon_state = "autolathe_n"
var/time = is_stack ? 10 : base_print_speed * coeff * multiplier
addtimer(CALLBACK(src, .proc/make_item, power, materials_used, custom_materials, multiplier, coeff, is_stack), time)
var/time = is_stack ? 32 : (32 * coeff * multiplier) ** 0.8
addtimer(CALLBACK(src, .proc/make_item, power, materials_used, custom_materials, multiplier, coeff, is_stack, usr), time)
else
to_chat(usr, "<span class=\"alert\">Not enough materials for this operation.</span>")
@@ -218,10 +214,11 @@
return
/obj/machinery/autolathe/proc/make_item(power, var/list/materials_used, var/list/picked_materials, multiplier, coeff, is_stack)
/obj/machinery/autolathe/proc/make_item(power, list/materials_used, list/picked_materials, multiplier, coeff, is_stack, mob/user)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/atom/A = drop_location()
use_power(power)
materials.use_materials(materials_used)
if(is_stack)
@@ -235,6 +232,11 @@
if(length(picked_materials))
new_item.set_custom_materials(picked_materials, 1 / multiplier) //Ensure we get the non multiplied amount
for(var/x in picked_materials)
var/datum/material/M = x
if(!istype(M, /datum/material/glass) && !istype(M, /datum/material/iron))
user.client.give_award(/datum/award/achievement/misc/getting_an_upgrade, user)
icon_state = "autolathe"
busy = FALSE
@@ -246,12 +248,10 @@
T += MB.rating*75000
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = T
var/manips = 0
var/total_manip_rating = 0
T=1.2
for(var/obj/item/stock_parts/manipulator/M in component_parts)
total_manip_rating += M.rating
manips++
prod_coeff = STANDARD_PART_LEVEL_LATHE_COEFFICIENT(total_manip_rating / (manips? manips : 1))
T -= M.rating*0.2
prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
/obj/machinery/autolathe/examine(mob/user)
. += ..()
@@ -376,6 +376,7 @@
return materials.has_materials(required_materials)
/obj/machinery/autolathe/proc/get_design_cost(datum/design/D)
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
var/dat
@@ -416,9 +417,7 @@
hacked = state
for(var/id in SSresearch.techweb_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(id)
if(D.build_type & stored_research.design_autounlock_skip_types)
continue
if((D.build_type & stored_research.design_autounlock_buildtypes) && ("hacked" in D.category))
if((D.build_type & AUTOLATHE) && ("hacked" in D.category))
if(hacked)
stored_research.add_design(D)
else
@@ -428,19 +427,24 @@
. = ..()
adjust_hacked(TRUE)
//Called when the object is constructed by an autolathe
//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes
/obj/item/proc/autolathe_crafted(obj/machinery/autolathe/A)
return
/obj/machinery/autolathe/secure
name = "secured autolathe"
desc = "It produces items using metal and glass. This model was reprogrammed without some of the more hazardous designs."
circuit = /obj/item/circuitboard/machine/autolathe/secure
stored_research = /datum/techweb/specialized/autounlocking/autolathe/public
base_print_speed = 20
/obj/machinery/autolathe/secure/Initialize()
. = ..()
stored_research = new /datum/techweb/specialized/autounlocking/autolathe/public
/obj/machinery/autolathe/toy
name = "autoylathe"
desc = "It produces toys using plastic, metal and glass."
circuit = /obj/item/circuitboard/machine/autolathe/toy
stored_research = /datum/techweb/specialized/autounlocking/autolathe/toy
categories = list(
"Toys",
"Figurines",
@@ -453,12 +457,8 @@
"Misc",
"Imported"
)
allowed_materials = list(
/datum/material/iron,
/datum/material/glass,
/datum/material/plastic
)
/obj/machinery/autolathe/toy/hacked/Initialize()
. = ..()
adjust_hacked(TRUE)
stored_research = new /datum/techweb/specialized/autounlocking/autolathe/toy
+2 -1
View File
@@ -44,7 +44,8 @@
icon_state = "colormate"
/obj/machinery/gear_painter/Destroy()
inserted.forceMove(drop_location())
if(inserted) //please i beg you do not drop nulls
inserted.forceMove(drop_location())
return ..()
/obj/machinery/gear_painter/attackby(obj/item/I, mob/living/user)
+44 -34
View File
@@ -3,14 +3,7 @@
#define ARCADE_WEIGHT_RARE 1
#define ARCADE_RATIO_PLUSH 0.20 // average 1 out of 6 wins is a plush.
/obj/machinery/computer/arcade
name = "random arcade"
desc = "random arcade machine"
icon_state = "arcade"
icon_keyboard = null
icon_screen = "invaders"
clockwork = TRUE //it'd look weird
var/list/prizes = list(
GLOBAL_LIST_INIT(arcade_prize_pool, list(
/obj/item/toy/balloon = ARCADE_WEIGHT_USELESS,
/obj/item/toy/beach_ball = ARCADE_WEIGHT_USELESS,
/obj/item/toy/cattoy = ARCADE_WEIGHT_USELESS,
@@ -70,9 +63,16 @@
/obj/item/clothing/mask/fakemoustache/italian = ARCADE_WEIGHT_RARE,
/obj/item/clothing/suit/hooded/wintercoat/ratvar/fake = ARCADE_WEIGHT_TRICK,
/obj/item/clothing/suit/hooded/wintercoat/narsie/fake = ARCADE_WEIGHT_TRICK
)
))
/obj/machinery/computer/arcade
name = "random arcade"
desc = "random arcade machine"
icon_state = "arcade"
icon_keyboard = "no_keyboard"
icon_screen = "invaders"
light_color = LIGHT_COLOR_GREEN
var/list/prize_override
/obj/machinery/computer/arcade/proc/Reset()
return
@@ -91,44 +91,54 @@
var/obj/machinery/computer/arcade/A = new CB.build_path(loc, CB)
A.setDir(dir)
return INITIALIZE_HINT_QDEL
//The below object acts as a spawner with a wide array of possible picks, most being uninspired references to past/current player characters.
//Nevertheless, this keeps its ratio constant with the sum of all the others prizes.
prizes[/obj/item/toy/plush/random] = counterlist_sum(prizes) * ARCADE_RATIO_PLUSH
Reset()
/obj/machinery/computer/arcade/proc/prizevend(mob/user, list/rarity_classes)
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "arcade", /datum/mood_event/arcade)
/obj/machinery/computer/arcade/proc/prizevend(mob/user, prizes = 1)
// if(user.mind?.get_skill_level(/datum/skill/gaming) >= SKILL_LEVEL_LEGENDARY && HAS_TRAIT(user, TRAIT_GAMERGOD))
// visible_message("<span class='notice'>[user] inputs an intense cheat code!</span>",
// "<span class='notice'>You hear a flurry of buttons being pressed.</span>")
// say("CODE ACTIVATED: EXTRA PRIZES.")
// prizes *= 2
for(var/i = 0, i < prizes, i++)
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "arcade", /datum/mood_event/arcade)
if(prob(0.0001)) //1 in a million
new /obj/item/gun/energy/pulse/prize(src)
visible_message("<span class='notice'>[src] dispenses.. woah, a gun! Way past cool.</span>", "<span class='notice'>You hear a chime and a shot.</span>")
user.client.give_award(/datum/award/achievement/misc/pulse, user)
return
if(prob(1) && prob(1) && prob(1)) //Proper 1 in a million
new /obj/item/gun/energy/pulse/prize(src)
SSmedals.UnlockMedal(MEDAL_PULSE, usr.client)
var/prizeselect
if(prize_override)
prizeselect = pickweight(prize_override)
else
prizeselect = pickweight(GLOB.arcade_prize_pool)
var/atom/movable/the_prize = new prizeselect(get_turf(src))
playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3)
visible_message("<span class='notice'>[src] dispenses [the_prize]!</span>", "<span class='notice'>You hear a chime and a clunk.</span>")
if(!contents.len)
var/list/toy_raffle
if(rarity_classes)
for(var/A in prizes)
if(prizes[A] in rarity_classes)
LAZYSET(toy_raffle, A, prizes[A])
if(!toy_raffle)
toy_raffle = prizes
var/prizeselect = pickweight(toy_raffle)
new prizeselect(src)
var/atom/movable/prize = pick(contents)
visible_message("<span class='notice'>[src] dispenses [prize]!</span>", "<span class='notice'>You hear a chime and a clunk.</span>")
prize.forceMove(get_turf(src))
/obj/machinery/computer/arcade/emp_act(severity)
. = ..()
var/override = FALSE
if(prize_override)
override = TRUE
if(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF)
return
var/empprize = null
var/num_of_prizes = rand(round(severity/50),round(severity/100))
var/num_of_prizes = 0
switch(severity)
if(1)
num_of_prizes = rand(1,4)
if(2)
num_of_prizes = rand(0,2)
for(var/i = num_of_prizes; i > 0; i--)
empprize = pickweight(prizes)
if(override)
empprize = pickweight(prize_override)
else
empprize = pickweight(GLOB.arcade_prize_pool)
new empprize(loc)
explosion(loc, -1, 0, 1+num_of_prizes, flame_range = 1+num_of_prizes)
+392 -125
View File
@@ -1,130 +1,399 @@
// ** BATTLE ** //
/obj/machinery/computer/arcade/battle
name = "arcade machine"
desc = "Does not support Pinball."
icon_state = "arcade"
circuit = /obj/item/circuitboard/computer/arcade/battle
var/enemy_name = "Space Villain"
var/temp = "Winners don't use space drugs" //Temporary message, for attack messages, etc
var/player_hp = 30 //Player health/attack points
var/player_mp = 10
var/enemy_hp = 45 //Enemy health/attack points
var/enemy_mp = 20
var/gameover = FALSE
var/blocked = FALSE //Player cannot attack/heal while set
var/turtle = 0
var/turn_speed = 5 //Measured in deciseconds.
var/enemy_name = "Space Villain"
///Enemy health/attack points
var/enemy_hp = 100
var/enemy_mp = 40
///Temporary message, for attack messages, etc
var/temp = "<br><center><h3>Winners don't use space drugs<center><h3>"
///the list of passive skill the enemy currently has. the actual passives are added in the enemy_setup() proc
var/list/enemy_passive
///if all the enemy's weakpoints have been triggered becomes TRUE
var/finishing_move = FALSE
///linked to passives, when it's equal or above the max_passive finishing move will become TRUE
var/pissed_off = 0
///the number of passives the enemy will start with
var/max_passive = 3
///weapon wielded by the enemy, the shotgun doesn't count.
var/chosen_weapon
///Player health
var/player_hp = 85
///player magic points
var/player_mp = 20
///used to remember the last three move of the player before this turn.
var/list/last_three_move
///if the enemy or player died. restart the game when TRUE
var/gameover = FALSE
///the player cannot make any move while this is set to TRUE. should only TRUE during enemy turns.
var/blocked = FALSE
///used to clear the enemy_action proc timer when the game is restarted
var/timer_id
///weapon used by the enemy, pure fluff.for certain actions
var/list/weapons
///unique to the emag mode, acts as a time limit where the player dies when it reaches 0.
var/bomb_cooldown = 19
///creates the enemy base stats for a new round along with the enemy passives
/obj/machinery/computer/arcade/battle/proc/enemy_setup(player_skill)
player_hp = 85
player_mp = 20
enemy_hp = 100
enemy_mp = 40
gameover = FALSE
blocked = FALSE
finishing_move = FALSE
pissed_off = 0
last_three_move = null
enemy_passive = list("short_temper" = TRUE, "poisonous" = TRUE, "smart" = TRUE, "shotgun" = TRUE, "magical" = TRUE, "chonker" = TRUE)
for(var/i = LAZYLEN(enemy_passive); i > max_passive; i--) //we'll remove passives from the list until we have the number of passive we want
var/picked_passive = pick(enemy_passive)
LAZYREMOVE(enemy_passive, picked_passive)
if(LAZYACCESS(enemy_passive, "chonker"))
enemy_hp += 20
if(LAZYACCESS(enemy_passive, "shotgun"))
chosen_weapon = "shotgun"
else if(weapons)
chosen_weapon = pick(weapons)
else
chosen_weapon = "null gun" //if the weapons list is somehow empty, shouldn't happen but runtimes are sneaky bastards.
if(player_skill)
player_hp += player_skill * 2
/obj/machinery/computer/arcade/battle/Reset()
max_passive = 3
var/name_action
var/name_part1
var/name_part2
name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ", "Pwn ", "Own ", "Ban ")
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
name_action = pick_list(ARCADE_FILE, "rpg_action_halloween")
name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_halloween")
name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_halloween")
weapons = strings(ARCADE_FILE, "rpg_weapon_halloween")
else if(SSevents.holidays && SSevents.holidays[CHRISTMAS])
name_action = pick_list(ARCADE_FILE, "rpg_action_xmas")
name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_xmas")
name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_xmas")
weapons = strings(ARCADE_FILE, "rpg_weapon_xmas")
else if(SSevents.holidays && SSevents.holidays[VALENTINES])
name_action = pick_list(ARCADE_FILE, "rpg_action_valentines")
name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_valentines")
name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_valentines")
weapons = strings(ARCADE_FILE, "rpg_weapon_valentines")
else
name_action = pick_list(ARCADE_FILE, "rpg_action")
name_part1 = pick_list(ARCADE_FILE, "rpg_adjective")
name_part2 = pick_list(ARCADE_FILE, "rpg_enemy")
weapons = strings(ARCADE_FILE, "rpg_weapon")
name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Cuban ", "the Evil ", "the Dread King ", "the Space ", "Lord ", "the Great ", "Duke ", "General ")
name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "slime", "Griefer", "ERPer", "Lizard Man", "Unicorn", "Bloopers")
enemy_name = ("The " + name_part1 + " " + name_part2)
name = (name_action + " " + enemy_name)
enemy_name = replacetext((name_part1 + name_part2), "the ", "")
name = (name_action + name_part1 + name_part2)
enemy_setup(0) //in the case it's reset we assume the player skill is 0 because the VOID isn't a gamer
/obj/machinery/computer/arcade/battle/ui_interact(mob/user)
. = ..()
screen_setup(user)
///sets up the main screen for the user
/obj/machinery/computer/arcade/battle/proc/screen_setup(mob/user)
var/dat = "<a href='byond://?src=[REF(src)];close=1'>Close</a>"
dat += "<center><h4>[enemy_name]</h4></center>"
dat += "<br><center><h3>[temp]</h3></center>"
dat += "[temp]"
dat += "<br><center>Health: [player_hp] | Magic: [player_mp] | Enemy Health: [enemy_hp]</center>"
if (gameover)
dat += "<center><b><a href='byond://?src=[REF(src)];newgame=1'>New Game</a>"
else
dat += "<center><b><a href='byond://?src=[REF(src)];attack=1'>Attack</a> | "
dat += "<a href='byond://?src=[REF(src)];heal=1'>Heal</a> | "
dat += "<a href='byond://?src=[REF(src)];charge=1'>Recharge Power</a>"
dat += "<center><b><a href='byond://?src=[REF(src)];attack=1'>Light attack</a>"
dat += "<center><b><a href='byond://?src=[REF(src)];defend=1'>Defend</a>"
dat += "<center><b><a href='byond://?src=[REF(src)];counter_attack=1'>Counter attack</a>"
dat += "<center><b><a href='byond://?src=[REF(src)];power_attack=1'>Power attack</a>"
dat += "</b></center>"
var/datum/browser/popup = new(user, "arcade", "Space Villain 2000")
popup.set_content(dat)
popup.open()
if(user.client) //mainly here to avoid a runtime when the player gets gibbed when losing the emag mode.
var/datum/browser/popup = new(user, "arcade", "Space Villain 2000")
popup.set_content(dat)
popup.open()
/obj/machinery/computer/arcade/battle/Topic(href, href_list)
if(..())
return
var/gamerSkill = 0
// if(usr?.mind)
// gamerSkill = usr.mind.get_skill_level(/datum/skill/gaming)
if (!blocked && !gameover)
var/attackamt = rand(5,7) + rand(0, gamerSkill)
if(finishing_move) //time to bonk that fucker,cuban pete will sometime survive a finishing move.
attackamt *= 100
//light attack suck absolute ass but it doesn't cost any MP so it's pretty good to finish an enemy off
if (href_list["attack"])
blocked = TRUE
var/attackamt = rand(2,6)
temp = "You attack for [attackamt] damage!"
playsound(loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3)
updateUsrDialog()
if(turtle > 0)
turtle--
sleep(turn_speed)
temp = "<br><center><h3>you do quick jab for [attackamt] of damage!</h3></center>"
enemy_hp -= attackamt
arcade_action(usr)
arcade_action(usr,"attack",attackamt)
else if (href_list["heal"])
blocked = TRUE
var/pointamt = rand(1,3)
var/healamt = rand(6,8)
temp = "You use [pointamt] magic to heal for [healamt] damage!"
playsound(loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3)
updateUsrDialog()
turtle++
//defend lets you gain back MP and take less damage from non magical attack.
else if(href_list["defend"])
temp = "<br><center><h3>you take a defensive stance and gain back 10 mp!</h3></center>"
player_mp += 10
arcade_action(usr,"defend",attackamt)
playsound(src, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
sleep(turn_speed)
player_mp -= pointamt
player_hp += healamt
blocked = TRUE
updateUsrDialog()
arcade_action(usr)
//mainly used to counter short temper and their absurd damage, will deal twice the damage the player took of a non magical attack.
else if(href_list["counter_attack"] && player_mp >= 10)
temp = "<br><center><h3>you prepare yourself to counter the next attack!</h3></center>"
player_mp -= 10
arcade_action(usr,"counter_attack",attackamt)
playsound(src, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
else if (href_list["charge"])
blocked = TRUE
var/chargeamt = rand(4,7)
temp = "You regain [chargeamt] points"
playsound(loc, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
player_mp += chargeamt
if(turtle > 0)
turtle--
else if(href_list["counter_attack"] && player_mp < 10)
temp = "<br><center><h3>you don't have the mp necessary to counter attack and defend yourself instead</h3></center>"
player_mp += 10
arcade_action(usr,"defend",attackamt)
playsound(src, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
updateUsrDialog()
sleep(turn_speed)
arcade_action(usr)
//power attack deals twice the amount of damage but is really expensive MP wise, mainly used with combos to get weakpoints.
else if (href_list["power_attack"] && player_mp >= 20)
temp = "<br><center><h3>You attack [enemy_name] with all your might for [attackamt * 2] damage!</h3></center>"
enemy_hp -= attackamt * 2
player_mp -= 20
arcade_action(usr,"power_attack",attackamt)
else if(href_list["power_attack"] && player_mp < 20)
temp = "<br><center><h3>You don't have the mp necessary for a power attack and settle for a light attack!</h3></center>"
enemy_hp -= attackamt
arcade_action(usr,"attack",attackamt)
if (href_list["close"])
usr.unset_machine()
usr << browse(null, "window=arcade")
else if (href_list["newgame"]) //Reset everything
temp = "New Round"
player_hp = initial(player_hp)
player_mp = initial(player_mp)
enemy_hp = initial(enemy_hp)
enemy_mp = initial(enemy_mp)
gameover = FALSE
turtle = 0
temp = "<br><center><h3>New Round<center><h3>"
if(obj_flags & EMAGGED)
Reset()
obj_flags &= ~EMAGGED
enemy_setup(gamerSkill)
screen_setup(usr)
add_fingerprint(usr)
updateUsrDialog()
return
/obj/machinery/computer/arcade/battle/proc/arcade_action(mob/user)
if ((enemy_mp <= 0) || (enemy_hp <= 0))
///happens after a player action and before the enemy turn. the enemy turn will be cancelled if there's a gameover.
/obj/machinery/computer/arcade/battle/proc/arcade_action(mob/user,player_stance,attackamt)
screen_setup(user)
blocked = TRUE
if(player_stance == "attack" || player_stance == "power_attack")
if(attackamt > 40)
playsound(src, 'sound/arcade/boom.ogg', 50, TRUE, extrarange = -3)
else
playsound(src, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3)
timer_id = addtimer(CALLBACK(src, .proc/enemy_action,player_stance,user),1 SECONDS,TIMER_STOPPABLE)
gameover_check(user)
///the enemy turn, the enemy's action entirely depend on their current passive and a teensy tiny bit of randomness
/obj/machinery/computer/arcade/battle/proc/enemy_action(player_stance,mob/user)
var/list/list_temp = list()
switch(LAZYLEN(last_three_move)) //we keep the last three action of the player in a list here
if(0 to 2)
LAZYADD(last_three_move, player_stance)
if(3)
for(var/i in 1 to 2)
last_three_move[i] = last_three_move[i + 1]
last_three_move[3] = player_stance
if(4 to INFINITY)
last_three_move = null //this shouldn't even happen but we empty the list if it somehow goes above 3
var/enemy_stance
var/attack_amount = rand(8,10) //making the attack amount not vary too much so that it's easier to see if the enemy has a shotgun
if(player_stance == "defend")
attack_amount -= 5
//if emagged, cuban pete will set up a bomb acting up as a timer. when it reaches 0 the player fucking dies
if(obj_flags & EMAGGED)
switch(bomb_cooldown--)
if(18)
list_temp += "<br><center><h3>[enemy_name] takes two valve tank and links them together, what's he planning?<center><h3>"
if(15)
list_temp += "<br><center><h3>[enemy_name] adds a remote control to the tan- ho god is that a bomb?<center><h3>"
if(12)
list_temp += "<br><center><h3>[enemy_name] throws the bomb next to you, you'r too scared to pick it up. <center><h3>"
if(6)
list_temp += "<br><center><h3>[enemy_name]'s hand brushes the remote linked to the bomb, your heart skipped a beat. <center><h3>"
if(2)
list_temp += "<br><center><h3>[enemy_name] is going to press the button! It's now or never! <center><h3>"
if(0)
player_hp -= attack_amount * 1000 //hey it's a maxcap we might as well go all in
//yeah I used the shotgun as a passive, you know why? because the shotgun gives +5 attack which is pretty good
if(LAZYACCESS(enemy_passive, "shotgun"))
if(weakpoint_check("shotgun","defend","defend","power_attack"))
list_temp += "<br><center><h3>You manage to disarm [enemy_name] with a surprise power attack and shoot him with his shotgun until it runs out of ammo! <center><h3> "
enemy_hp -= 10
chosen_weapon = "empty shotgun"
else
attack_amount += 5
//heccing chonker passive, only gives more HP at the start of a new game but has one of the hardest weakpoint to trigger.
if(LAZYACCESS(enemy_passive, "chonker"))
if(weakpoint_check("chonker","power_attack","power_attack","power_attack"))
list_temp += "<br><center><h3>After a lot of power attacks you manage to tip over [enemy_name] as they fall over their enormous weight<center><h3> "
enemy_hp -= 30
//smart passive trait, mainly works in tandem with other traits, makes the enemy unable to be counter_attacked
if(LAZYACCESS(enemy_passive, "smart"))
if(weakpoint_check("smart","defend","defend","attack"))
list_temp += "<br><center><h3>[enemy_name] is confused by your illogical strategy!<center><h3> "
attack_amount -= 5
else if(attack_amount >= player_hp)
player_hp -= attack_amount
list_temp += "<br><center><h3>[enemy_name] figures out you are really close to death and finishes you off with their [chosen_weapon]!<center><h3>"
enemy_stance = "attack"
else if(player_stance == "counter_attack")
list_temp += "<br><center><h3>[enemy_name] is not taking your bait. <center><h3> "
if(LAZYACCESS(enemy_passive, "short_temper"))
list_temp += "However controlling their hatred of you still takes a toll on their mental and physical health!"
enemy_hp -= 5
enemy_mp -= 5
enemy_stance = "defensive"
//short temper passive trait, gets easily baited into being counter attacked but will bypass your counter when low on HP
if(LAZYACCESS(enemy_passive, "short_temper"))
if(weakpoint_check("short_temper","counter_attack","counter_attack","counter_attack"))
list_temp += "<br><center><h3>[enemy_name] is getting frustrated at all your counter attacks and throws a tantrum!<center><h3>"
enemy_hp -= attack_amount
else if(player_stance == "counter_attack")
if(!(LAZYACCESS(enemy_passive, "smart")) && enemy_hp > 30)
list_temp += "<br><center><h3>[enemy_name] took the bait and allowed you to counter attack for [attack_amount * 2] damage!<center><h3>"
player_hp -= attack_amount
enemy_hp -= attack_amount * 2
enemy_stance = "attack"
else if(enemy_hp <= 30) //will break through the counter when low enough on HP even when smart.
list_temp += "<br><center><h3>[enemy_name] is getting tired of your tricks and breaks through your counter with their [chosen_weapon]!<center><h3>"
player_hp -= attack_amount
enemy_stance = "attack"
else if(!enemy_stance)
var/added_temp
if(rand())
added_temp = "you for [attack_amount + 5] damage!"
player_hp -= attack_amount + 5
enemy_stance = "attack"
else
added_temp = "the wall, breaking their skull in the process and losing [attack_amount] hp!" //[enemy_name] you have a literal dent in your skull
enemy_hp -= attack_amount
enemy_stance = "attack"
list_temp += "<br><center><h3>[enemy_name] grits their teeth and charge right into [added_temp]<center><h3>"
//in the case none of the previous passive triggered, Mainly here to set an enemy stance for passives that needs it like the magical passive.
if(!enemy_stance)
enemy_stance = pick("attack","defensive")
if(enemy_stance == "attack")
player_hp -= attack_amount
list_temp += "<br><center><h3>[enemy_name] attacks you for [attack_amount] points of damage with their [chosen_weapon]<center><h3>"
if(player_stance == "counter_attack")
enemy_hp -= attack_amount * 2
list_temp += "<br><center><h3>You counter [enemy_name]'s attack and deal [attack_amount * 2] points of damage!<center><h3>"
if(enemy_stance == "defensive" && enemy_mp < 15)
list_temp += "<br><center><h3>[enemy_name] take some time to get some mp back!<center><h3> "
enemy_mp += attack_amount
else if (enemy_stance == "defensive" && enemy_mp >= 15 && !(LAZYACCESS(enemy_passive, "magical")))
list_temp += "<br><center><h3>[enemy_name] quickly heal themselves for 5 hp!<center><h3> "
enemy_mp -= 15
enemy_hp += 5
//magical passive trait, recharges MP nearly every turn it's not blasting you with magic.
if(LAZYACCESS(enemy_passive, "magical"))
if(player_mp >= 50)
list_temp += "<br><center><h3>the huge amount of magical energy you have acumulated throws [enemy_name] off balance!<center><h3>"
enemy_mp = 0
LAZYREMOVE(enemy_passive, "magical")
pissed_off++
else if(LAZYACCESS(enemy_passive, "smart") && player_stance == "counter_attack" && enemy_mp >= 20)
list_temp += "<br><center><h3>[enemy_name] blasts you with magic from afar for 10 points of damage before you can counter!<center><h3>"
player_hp -= 10
enemy_mp -= 20
else if(enemy_hp >= 20 && enemy_mp >= 40 && enemy_stance == "defensive")
list_temp += "<br><center><h3>[enemy_name] Blasts you with magic from afar!<center><h3>"
enemy_mp -= 40
player_hp -= 30
enemy_stance = "attack"
else if(enemy_hp < 20 && enemy_mp >= 20 && enemy_stance == "defensive") //it's a pretty expensive spell so they can't spam it that much
list_temp += "<br><center><h3>[enemy_name] heal themselves with magic and gain back 20 hp!<center><h3>"
enemy_hp += 20
enemy_mp -= 30
else
list_temp += "<br><center><h3>[enemy_name]'s magical nature lets them get some mp back!<center><h3>"
enemy_mp += attack_amount
//poisonous passive trait, while it's less damage added than the shotgun it acts up even when the enemy doesn't attack at all.
if(LAZYACCESS(enemy_passive, "poisonous"))
if(weakpoint_check("poisonous","attack","attack","attack"))
list_temp += "<br><center><h3>your flurry of attack throws back the poisonnous gas at [enemy_name] and makes them choke on it!<center><h3> "
enemy_hp -= 5
else
list_temp += "<br><center><h3>the stinky breath of [enemy_name] hurts you for 3 hp!<center><h3> "
player_hp -= 3
//if all passive's weakpoint have been triggered, set finishing_move to TRUE
if(pissed_off >= max_passive && !finishing_move)
list_temp += "<br><center><h3>You have weakened [enemy_name] enough for them to show their weak point, you will do 10 times as much damage with your next attack!<center><h3> "
finishing_move = TRUE
playsound(src, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3)
temp = list_temp.Join()
gameover_check(user)
screen_setup(user)
blocked = FALSE
/obj/machinery/computer/arcade/battle/proc/gameover_check(mob/user)
var/xp_gained = 0
if(enemy_hp <= 0)
if(!gameover)
if(timer_id)
deltimer(timer_id)
timer_id = null
if(player_hp <= 0)
player_hp = 1 //let's just pretend the enemy didn't kill you so not both the player and enemy look dead.
gameover = TRUE
temp = "[enemy_name] has fallen! Rejoice!"
playsound(loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3)
blocked = FALSE
temp = "<br><center><h3>[enemy_name] has fallen! Rejoice!<center><h3>"
playsound(loc, 'sound/arcade/win.ogg', 50, TRUE)
if(obj_flags & EMAGGED)
new /obj/effect/spawner/newbomb/timer/syndicate(loc)
@@ -133,78 +402,76 @@
log_game("[key_name(usr)] has outbombed Cuban Pete and been awarded a bomb.")
Reset()
obj_flags &= ~EMAGGED
xp_gained += 100
else
prizevend(user)
xp_gained += 50
SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("win", (obj_flags & EMAGGED ? "emagged":"normal")))
else if ((obj_flags & EMAGGED) && (turtle >= 4))
var/boomamt = rand(5,10)
temp = "[enemy_name] throws a bomb, exploding you for [boomamt] damage!"
playsound(loc, 'sound/arcade/boom.ogg', 50, TRUE, extrarange = -3)
player_hp -= boomamt
else if ((enemy_mp <= 5) && (prob(70)))
var/stealamt = rand(2,3)
temp = "[enemy_name] steals [stealamt] of your power!"
playsound(loc, 'sound/arcade/steal.ogg', 50, TRUE, extrarange = -3)
player_mp -= stealamt
updateUsrDialog()
if (player_mp <= 0)
gameover = TRUE
sleep(turn_speed)
temp = "You have been drained! GAME OVER"
playsound(loc, 'sound/arcade/lose.ogg', 50, TRUE, extrarange = -3)
if(obj_flags & EMAGGED)
usr.gib()
SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "mana", (obj_flags & EMAGGED ? "emagged":"normal")))
else if ((enemy_hp <= 10) && (enemy_mp > 4))
temp = "[enemy_name] heals for 4 health!"
playsound(loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3)
enemy_hp += 4
enemy_mp -= 4
else
var/attackamt = rand(3,6)
temp = "[enemy_name] attacks for [attackamt] damage!"
playsound(loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3)
player_hp -= attackamt
if ((player_mp <= 0) || (player_hp <= 0))
else if(player_hp <= 0)
if(timer_id)
deltimer(timer_id)
timer_id = null
gameover = TRUE
temp = "You have been crushed! GAME OVER"
playsound(loc, 'sound/arcade/lose.ogg', 50, TRUE, extrarange = -3)
temp = "<br><center><h3>You have been crushed! GAME OVER<center><h3>"
playsound(loc, 'sound/arcade/lose.ogg', 50, TRUE)
xp_gained += 10//pity points
if(obj_flags & EMAGGED)
usr.gib()
var/mob/living/living_user = user
if (istype(living_user))
living_user.gib()
SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "hp", (obj_flags & EMAGGED ? "emagged":"normal")))
blocked = FALSE
return
// if(gameover)
// user?.mind?.adjust_experience(/datum/skill/gaming, xp_gained+1)//always gain at least 1 point of XP
///used to check if the last three move of the player are the one we want in the right order and if the passive's weakpoint has been triggered yet
/obj/machinery/computer/arcade/battle/proc/weakpoint_check(passive,first_move,second_move,third_move)
if(LAZYLEN(last_three_move) < 3)
return FALSE
if(last_three_move[1] == first_move && last_three_move[2] == second_move && last_three_move[3] == third_move && LAZYACCESS(enemy_passive, passive))
LAZYREMOVE(enemy_passive, passive)
pissed_off++
return TRUE
else
return FALSE
/obj/machinery/computer/arcade/battle/Destroy()
enemy_passive = null
weapons = null
last_three_move = null
return ..() //well boys we did it, lists are no more
/obj/machinery/computer/arcade/battle/examine_more(mob/user)
to_chat(user, "<span class='notice'>Scribbled on the side of the Arcade Machine you notice some writing...\
\nmagical -> >=50 power\
\nsmart -> defend, defend, light attack\
\nshotgun -> defend, defend, power attack\
\nshort temper -> counter, counter, counter\
\npoisonous -> light attack, light attack, light attack\
\nchonker -> power attack, power attack, power attack</span>")
return ..()
var/list/msg = list("<span class='notice'><i>You notice some writing scribbled on the side of [src]...</i></span>")
msg += "\t<span class='info'>smart -> defend, defend, light attack</span>"
msg += "\t<span class='info'>shotgun -> defend, defend, power attack</span>"
msg += "\t<span class='info'>short temper -> counter, counter, counter</span>"
msg += "\t<span class='info'>poisonous -> light attack, light attack, light attack</span>"
msg += "\t<span class='info'>chonker -> power attack, power attack, power attack</span>"
return msg
/obj/machinery/computer/arcade/battle/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED)
return
to_chat(user, "<span class='warning'>A mesmerizing Rhumba beat starts playing from the arcade machine's speakers!</span>")
temp = "If you die in the game, you die for real!"
player_hp = 30
player_mp = 10
enemy_hp = 45
enemy_mp = 20
temp = "<br><center><h2>If you die in the game, you die for real!<center><h2>"
max_passive = 6
bomb_cooldown = 18
var/gamerSkill = 0
// if(usr?.mind)
// gamerSkill = usr.mind.get_skill_level(/datum/skill/gaming)
enemy_setup(gamerSkill)
enemy_hp += 100 //extra HP just to make cuban pete even more bullshit
player_hp += 30 //the player will also get a few extra HP in order to have a fucking chance
screen_setup(user)
gameover = FALSE
blocked = FALSE
obj_flags |= EMAGGED
@@ -268,7 +268,7 @@
visible_message("<span class='notice'>[src] dispenses [itemname]!</span>", "<span class='notice'>You hear a chime and a clunk.</span>")
DISABLE_BITFIELD(obj_flags, EMAGGED)
else
var/dope_prizes = (area >= 480) ? list(ARCADE_WEIGHT_RARE) : (area >= 256) ? list(ARCADE_WEIGHT_RARE, ARCADE_WEIGHT_TRICK) : null
var/dope_prizes = (area >= 480) ? 6 : (area >= 256) ? 4 : 2
prizevend(user, dope_prizes)
if(game_status == MINESWEEPER_GAME_WON)
@@ -311,12 +311,12 @@
var/new_rows = input(user, "How many rows do you want? (Minimum: 4, Maximum: 30)", "Minesweeper Rows") as null|num
if(!new_rows || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return FALSE
new_rows = clamp(new_rows + 1, 4, 30)
new_rows = clamp(new_rows + 1, 4, 20)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, FALSE, extrarange = -3)
var/new_columns = input(user, "How many columns do you want? (Minimum: 4, Maximum: 50)", "Minesweeper Squares") as null|num
if(!new_columns || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return FALSE
new_columns = clamp(new_columns + 1, 4, 50)
new_columns = clamp(new_columns + 1, 4, 30)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, FALSE, extrarange = -3)
var/grid_area = (new_rows - 1) * (new_columns - 1)
var/lower_limit = round(grid_area*0.156)
@@ -8,7 +8,7 @@
icon_state = "arcade"
circuit = /obj/item/circuitboard/computer/arcade/amputation
/obj/machinery/computer/arcade/amputation/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/machinery/computer/arcade/amputation/on_attack_hand(mob/user)
if(!iscarbon(user))
return
var/mob/living/carbon/c_user = user
@@ -24,8 +24,13 @@
var/obj/item/bodypart/chopchop = c_user.get_bodypart(which_hand)
chopchop.dismember()
qdel(chopchop)
playsound(loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3)
for(var/i=1; i<=rand(3,5); i++)
prizevend(user)
// user.mind?.adjust_experience(/datum/skill/gaming, 100)
playsound(loc, 'sound/arcade/win.ogg', 50, TRUE)
prizevend(user, rand(3,5))
else
to_chat(c_user, "<span class='notice'>You (wisely) decide against putting your hand in the machine.</span>")
/obj/machinery/computer/arcade/amputation/festive //dispenses wrapped gifts instead of arcade prizes, also known as the ancap christmas tree
name = "Mediborg's Festive Amputation Adventure"
desc = "A picture of a blood-soaked medical cyborg wearing a Santa hat flashes on the screen. The mediborg has a speech bubble that says, \"Put your hand in the machine if you aren't a <b>coward!</b>\""
prize_override = list(/obj/item/a_gift/anything = 1)
@@ -1,5 +1,3 @@
// *** THE ORION TRAIL ** //
#define ORION_TRAIL_WINTURN 9
@@ -15,6 +13,8 @@
#define ORION_TRAIL_COLLISION "Collision"
#define ORION_TRAIL_SPACEPORT "Spaceport"
#define ORION_TRAIL_BLACKHOLE "BlackHole"
#define ORION_TRAIL_OLDSHIP "Old Ship"
#define ORION_TRAIL_SEARCH "Old Ship Search"
#define ORION_STATUS_START 1
#define ORION_STATUS_NORMAL 2
@@ -44,7 +44,8 @@
ORION_TRAIL_LING = 3,
ORION_TRAIL_MALFUNCTION = 2,
ORION_TRAIL_COLLISION = 1,
ORION_TRAIL_SPACEPORT = 2
ORION_TRAIL_SPACEPORT = 2,
ORION_TRAIL_OLDSHIP = 2
)
var/list/stops = list()
var/list/stopblurbs = list()
@@ -55,13 +56,27 @@
var/gameStatus = ORION_STATUS_START
var/canContinueEvent = 0
var/obj/item/radio/Radio
var/list/gamers = list()
var/killed_crew = 0
/obj/machinery/computer/arcade/orion_trail/Initialize()
. = ..()
Radio = new /obj/item/radio(src)
Radio.listening = 0
/obj/machinery/computer/arcade/orion_trail/Destroy()
QDEL_NULL(Radio)
return ..()
/obj/machinery/computer/arcade/orion_trail/kobayashi
name = "Kobayashi Maru control computer"
desc = "A test for cadets"
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "control_boxp"
events = list("Raiders" = 3, "Interstellar Flux" = 1, "Illness" = 3, "Breakdown" = 2, "Malfunction" = 2, "Collision" = 1, "Spaceport" = 2)
prizes = list(/obj/item/paper/fluff/holodeck/trek_diploma = 1)
prize_override = list(/obj/item/paper/fluff/holodeck/trek_diploma = 1)
settlers = list("Kirk","Worf","Gene")
/obj/machinery/computer/arcade/orion_trail/Reset()
@@ -96,14 +111,52 @@
event = null
gameStatus = ORION_STATUS_NORMAL
lings_aboard = 0
killed_crew = 0
//spaceport junk
spaceport_raided = 0
spaceport_freebie = 0
last_spaceport_action = ""
/obj/machinery/computer/arcade/orion_trail/ui_interact(mob/user)
/obj/machinery/computer/arcade/orion_trail/proc/report_player(mob/gamer)
if(gamers[gamer] == -2)
return // enough harassing them
if(gamers[gamer] == -1)
say("WARNING: Continued antisocial behavior detected: Dispensing self-help literature.")
new /obj/item/paper/pamphlet/violent_video_games(drop_location())
gamers[gamer]--
return
if(!(gamer in gamers))
gamers[gamer] = 0
gamers[gamer]++ // How many times the player has 'prestiged' (massacred their crew)
if(gamers[gamer] > 2 && prob(20 * gamers[gamer]))
Radio.set_frequency(FREQ_SECURITY)
Radio.talk_into(src, "SECURITY ALERT: Crewmember [gamer] recorded displaying antisocial tendencies in [get_area(src)]. Please watch for violent behavior.", FREQ_SECURITY)
Radio.set_frequency(FREQ_MEDICAL)
Radio.talk_into(src, "PSYCH ALERT: Crewmember [gamer] recorded displaying antisocial tendencies in [get_area(src)]. Please schedule psych evaluation.", FREQ_MEDICAL)
gamers[gamer] = -1
gamer.client.give_award(/datum/award/achievement/misc/gamer, gamer) // PSYCH REPORT NOTE: patient kept rambling about how they did it for an "achievement", recommend continued holding for observation
// gamer.mind?.adjust_experience(/datum/skill/gaming, 50) // cheevos make u better
if(!isnull(GLOB.data_core.general))
for(var/datum/data/record/R in GLOB.data_core.general)
if(R.fields["name"] == gamer.name)
R.fields["m_stat"] = "*Unstable*"
return
/obj/machinery/computer/arcade/orion_trail/ui_interact(mob/_user)
. = ..()
if (!isliving(_user))
return
var/mob/living/user = _user
if(fuel <= 0 || food <=0 || settlers.len == 0)
gameStatus = ORION_STATUS_GAMEOVER
event = null
@@ -136,6 +189,8 @@
desc = "Learn how our ancestors got to Orion, and have fun in the process!"
dat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];menu=1'>May They Rest In Peace</a></P>"
// user?.mind?.adjust_experience(/datum/skill/gaming, 10)//learning from your mistakes is the first rule of roguelikes
else if(event)
dat = eventdat
else if(gameStatus == ORION_STATUS_NORMAL)
@@ -174,20 +229,32 @@
return
busy = TRUE
// var/gamerSkillLevel = 0
var/gamerSkill = 0
var/gamerSkillRands = 0
// if(usr?.mind)
// gamerSkillLevel = usr.mind.get_skill_level(/datum/skill/gaming)
// gamerSkill = usr.mind.get_skill_modifier(/datum/skill/gaming, SKILL_PROBS_MODIFIER)
// gamerSkillRands = usr.mind.get_skill_modifier(/datum/skill/gaming, SKILL_RANDS_MODIFIER)
var/xp_gained = 0
if (href_list["continue"]) //Continue your travels
if(gameStatus == ORION_STATUS_NORMAL && !event && turns != 7)
if(turns >= ORION_TRAIL_WINTURN)
win(usr)
xp_gained += 34
else
food -= (alive+lings_aboard)*2
fuel -= 5
if(turns == 2 && prob(30))
if(turns == 2 && prob(30-gamerSkill))
event = ORION_TRAIL_COLLISION
event()
else if(prob(75))
else if(prob(75-gamerSkill))
event = pickweight(events)
if(lings_aboard)
if(event == ORION_TRAIL_LING || prob(55))
if(event == ORION_TRAIL_LING || prob(55-gamerSkill))
event = ORION_TRAIL_LING_ATTACK
event()
turns += 1
@@ -195,15 +262,18 @@
var/mob/living/carbon/M = usr //for some vars
switch(event)
if(ORION_TRAIL_RAIDERS)
if(prob(50))
if(prob(50-gamerSkill))
to_chat(usr, "<span class='userdanger'>You hear battle shouts. The tramping of boots on cold metal. Screams of agony. The rush of venting air. Are you going insane?</span>")
M.hallucination += 30
else
to_chat(usr, "<span class='userdanger'>Something strikes you from behind! It hurts like hell and feel like a blunt weapon, but nothing is there...</span>")
M.take_bodypart_damage(30)
playsound(loc, 'sound/weapons/genhit2.ogg', 100, 1)
playsound(loc, 'sound/weapons/genhit2.ogg', 100, TRUE)
if(ORION_TRAIL_ILLNESS)
var/severity = rand(1,3) //pray to RNGesus. PRAY, PIGS
var/maxSeverity = 3
// if(gamerSkillLevel >= SKILL_LEVEL_EXPERT)
// maxSeverity = 2 //part of gitting gud is rng mitigation
var/severity = rand(1,maxSeverity) //pray to RNGesus. PRAY, PIGS
if(severity == 1)
to_chat(M, "<span class='userdanger'>You suddenly feel slightly nauseated.</span>" )
if(severity == 2)
@@ -215,16 +285,16 @@
sleep(30)
M.vomit(10, distance = 5)
if(ORION_TRAIL_FLUX)
if(prob(75))
if(prob(75-gamerSkill))
M.DefaultCombatKnockdown(60)
say("A sudden gust of powerful wind slams [M] into the floor!")
M.take_bodypart_damage(25)
playsound(loc, 'sound/weapons/genhit.ogg', 100, 1)
playsound(loc, 'sound/weapons/genhit.ogg', 100, TRUE)
else
to_chat(M, "<span class='userdanger'>A violent gale blows past you, and you barely manage to stay standing!</span>")
if(ORION_TRAIL_COLLISION) //by far the most damaging event
if(prob(90))
playsound(loc, 'sound/effects/bang.ogg', 100, 1)
if(prob(90-gamerSkill))
playsound(loc, 'sound/effects/bang.ogg', 100, TRUE)
var/turf/open/floor/F
for(F in orange(1, src))
F.ScrapeAway()
@@ -232,15 +302,15 @@
if(hull)
sleep(10)
say("A new floor suddenly appears around [src]. What the hell?")
playsound(loc, 'sound/weapons/genhit.ogg', 100, 1)
playsound(loc, 'sound/weapons/genhit.ogg', 100, TRUE)
var/turf/open/space/T
for(T in orange(1, src))
T.PlaceOnTop(/turf/open/floor/plating)
else
say("Something slams into the floor around [src] - luckily, it didn't get through!")
playsound(loc, 'sound/effects/bang.ogg', 50, 1)
playsound(loc, 'sound/effects/bang.ogg', 50, TRUE)
if(ORION_TRAIL_MALFUNCTION)
playsound(loc, 'sound/effects/empulse.ogg', 50, 1)
playsound(loc, 'sound/effects/empulse.ogg', 50, TRUE)
visible_message("<span class='danger'>[src] malfunctions, randomizing in-game stats!</span>")
var/oldfood = food
var/oldfuel = fuel
@@ -254,7 +324,7 @@
audible_message("<span class='danger'>[src] lets out a somehow ominous chime.</span>")
food = oldfood
fuel = oldfuel
playsound(loc, 'sound/machines/chime.ogg', 50, 1)
playsound(loc, 'sound/machines/chime.ogg', 50, TRUE)
else if(href_list["newgame"]) //Reset everything
if(gameStatus == ORION_STATUS_START)
@@ -266,6 +336,10 @@
food = 80
fuel = 60
settlers = list("Harry","Larry","Bob")
else if(href_list["search"]) //search old ship
if(event == ORION_TRAIL_OLDSHIP)
event = ORION_TRAIL_SEARCH
event()
else if(href_list["slow"]) //slow down
if(event == ORION_TRAIL_FLUX)
food -= (alive+lings_aboard)*2
@@ -302,11 +376,11 @@
event = null
else if(href_list["blackhole"]) //keep speed past a black hole
if(turns == 7)
if(prob(75))
if(prob(75-gamerSkill))
event = ORION_TRAIL_BLACKHOLE
event()
if(obj_flags & EMAGGED)
playsound(loc, 'sound/effects/supermatter.ogg', 100, 1)
playsound(loc, 'sound/effects/supermatter.ogg', 100, TRUE)
say("A miniature black hole suddenly appears in front of [src], devouring [usr] alive!")
if(isliving(usr))
var/mob/living/L = usr
@@ -328,22 +402,29 @@
else if(href_list["killcrew"]) //shoot a crewmember
if(gameStatus == ORION_STATUS_NORMAL || event == ORION_TRAIL_LING)
var/sheriff = remove_crewmember() //I shot the sheriff
playsound(loc,'sound/weapons/gunshot.ogg', 100, 1)
playsound(loc,'sound/weapons/gunshot.ogg', 100, TRUE)
killed_crew++
var/mob/living/user = usr
if(settlers.len == 0 || alive == 0)
say("The last crewmember [sheriff], shot themselves, GAME OVER!")
if(obj_flags & EMAGGED)
usr.death(0)
obj_flags &= EMAGGED
user.death(FALSE)
gameStatus = ORION_STATUS_GAMEOVER
event = null
if(killed_crew >= 4)
xp_gained -= 15//no cheating by spamming game overs
report_player(usr)
else if(obj_flags & EMAGGED)
if(usr.name == sheriff)
say("The crew of the ship chose to kill [usr.name]!")
usr.death(0)
user.death(FALSE)
if(event == ORION_TRAIL_LING) //only ends the ORION_TRAIL_LING event, since you can do this action in multiple places
event = null
killed_crew-- // the kill was valid
//Spaceport specific interactions
//they get a header because most of them don't reset event (because it's a shop, you leave when you want to)
@@ -356,6 +437,7 @@
fuel -= 10
food -= 10
event()
killed_crew-- // I mean not really but you know
else if(href_list["sellcrew"]) //sell a crewmember
if(gameStatus == ORION_STATUS_MARKET)
@@ -377,15 +459,16 @@
else if(href_list["raid_spaceport"])
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided)
var/success = min(15 * alive,100) //default crew (4) have a 60% chance
var/success = min(15 * alive + gamerSkill,100) //default crew (4) have a 60% chance
spaceport_raided = 1
var/FU = 0
var/FO = 0
if(prob(success))
FU = rand(5,15)
FO = rand(5,15)
FU = rand(5 + gamerSkillRands,15 + gamerSkillRands)
FO = rand(5 + gamerSkillRands,15 + gamerSkillRands)
last_spaceport_action = "You successfully raided the spaceport! You gained [FU] Fuel and [FO] Food! (+[FU]FU,+[FO]FO)"
xp_gained += 10
else
FU = rand(-5,-15)
FO = rand(-5,-15)
@@ -444,8 +527,7 @@
add_fingerprint(usr)
updateUsrDialog()
busy = FALSE
return
// usr?.mind?.adjust_experience(/datum/skill/gaming, xp_gained+1)
/obj/machinery/computer/arcade/orion_trail/proc/event()
eventdat = "<center><h1>[event]</h1></center>"
@@ -474,6 +556,38 @@
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];slow=1'>Slow Down</a> <a href='byond://?src=[REF(src)];keepspeed=1'>Continue</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
if(ORION_TRAIL_OLDSHIP)
eventdat += "<br>Your crew spots an old ship floating through space. It might have some supplies, but then again it looks rather unsafe."
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];search=1'>Search it</a><a href='byond://?src=[REF(src)];eventclose=1'>Leave it</a></P><P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
canContinueEvent = 1
if(ORION_TRAIL_SEARCH)
switch(rand(100))
if(0 to 15)
var/rescued = add_crewmember()
var/oldfood = rand(1,7)
var/oldfuel = rand(4,10)
food += oldfood
fuel += oldfuel
eventdat += "<br>As you look through it you find some supplies and a living person!"
eventdat += "<br>[rescued] was rescued from the abandoned ship!"
eventdat += "<br>You found [oldfood] <b>Food</b> and [oldfuel] <b>Fuel</b>."
if(15 to 35)
var/lfuel = rand(4,7)
var/deadname = remove_crewmember()
fuel -= lfuel
eventdat += "<br>[deadname] was lost deep in the wreckage, and your own vessel lost [lfuel] <b>Fuel</b> maneuvering to the the abandoned ship."
if(35 to 65)
var/oldfood = rand(5,11)
food += oldfood
engine++
eventdat += "<br>You found [oldfood] <b>Food</b> and some parts amongst the wreck."
else
eventdat += "<br>As you look through the wreck you cannot find much of use."
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];eventclose=1'>Continue</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
canContinueEvent = 1
if(ORION_TRAIL_ILLNESS)
eventdat += "A deadly illness has been contracted!"
var/deadname = remove_crewmember()
@@ -687,7 +801,7 @@
//Add Random/Specific crewmember
/obj/machinery/computer/arcade/orion_trail/proc/add_crewmember(var/specific = "")
/obj/machinery/computer/arcade/orion_trail/proc/add_crewmember(specific = "")
var/newcrew = ""
if(specific)
newcrew = specific
@@ -703,7 +817,7 @@
//Remove Random/Specific crewmember
/obj/machinery/computer/arcade/orion_trail/proc/remove_crewmember(var/specific = "", var/dont_remove = "")
/obj/machinery/computer/arcade/orion_trail/proc/remove_crewmember(specific = "", dont_remove = "")
var/list/safe2remove = settlers
var/removed = ""
if(dont_remove)
@@ -779,14 +893,14 @@
to_chat(user, "<span class='warning'>You flip the switch on the underside of [src].</span>")
active = 1
visible_message("<span class='notice'>[src] softly beeps and whirs to life!</span>")
playsound(loc, 'sound/machines/defib_SaftyOn.ogg', 25, 1)
playsound(loc, 'sound/machines/defib_SaftyOn.ogg', 25, TRUE)
say("This is ship ID #[rand(1,1000)] to Orion Port Authority. We're coming in for landing, over.")
sleep(20)
visible_message("<span class='warning'>[src] begins to vibrate...</span>")
say("Uh, Port? Having some issues with our reactor, could you check it out? Over.")
sleep(30)
say("Oh, God! Code Eight! CODE EIGHT! IT'S GONNA BL-")
playsound(loc, 'sound/machines/buzz-sigh.ogg', 25, 1)
playsound(loc, 'sound/machines/buzz-sigh.ogg', 25, TRUE)
sleep(3.6)
visible_message("<span class='userdanger'>[src] explodes!</span>")
explosion(loc, 2,4,8, flame_range = 16)
+23 -14
View File
@@ -92,6 +92,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
icon_screen = "tank"
icon_keyboard = "atmos_key"
circuit = /obj/item/circuitboard/computer/atmos_control
light_color = LIGHT_COLOR_CYAN
var/frequency = FREQ_ATMOS_STORAGE
var/list/sensors = list(
@@ -102,6 +103,20 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank",
ATMOS_GAS_MONITOR_SENSOR_AIR = "Mixed Air Tank",
ATMOS_GAS_MONITOR_SENSOR_MIX = "Mix Tank",
// ATMOS_GAS_MONITOR_SENSOR_BZ = "BZ Tank",
// ATMOS_GAS_MONITOR_SENSOR_FREON = "Freon Tank",
// ATMOS_GAS_MONITOR_SENSOR_HALON = "Halon Tank",
// ATMOS_GAS_MONITOR_SENSOR_HEALIUM = "Healium Tank",
// ATMOS_GAS_MONITOR_SENSOR_H2 = "Hydrogen Tank",
// ATMOS_GAS_MONITOR_SENSOR_HYPERNOBLIUM = "Hypernoblium Tank",
// ATMOS_GAS_MONITOR_SENSOR_MIASMA = "Miasma Tank",
// ATMOS_GAS_MONITOR_SENSOR_NO2 = "Nitryl Tank",
// ATMOS_GAS_MONITOR_SENSOR_PLUOXIUM = "Pluoxium Tank",
// ATMOS_GAS_MONITOR_SENSOR_PROTO_NITRATE = "Proto-Nitrate Tank",
// ATMOS_GAS_MONITOR_SENSOR_STIMULUM = "Stimulum Tank",
// ATMOS_GAS_MONITOR_SENSOR_TRITIUM = "Tritium Tank",
// ATMOS_GAS_MONITOR_SENSOR_H2O = "Water Vapor Tank",
// ATMOS_GAS_MONITOR_SENSOR_ZAUKER = "Zauker Tank",
ATMOS_GAS_MONITOR_LOOP_DISTRIBUTION = "Distribution Loop",
ATMOS_GAS_MONITOR_LOOP_ATMOS_WASTE = "Atmos Waste Loop",
ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber",
@@ -110,7 +125,6 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
var/list/sensor_information = list()
var/datum/radio_frequency/radio_connection
light_color = LIGHT_COLOR_CYAN
/obj/machinery/computer/atmos_control/Initialize()
. = ..()
@@ -165,15 +179,10 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
/obj/machinery/computer/atmos_control/incinerator
name = "Incinerator Air Control"
sensors = list(ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber")
ui_x = 400
ui_y = 300
//Toxins mix sensor only
/obj/machinery/computer/atmos_control/toxinsmix
name = "Toxins Mixing Air Control"
sensors = list(ATMOS_GAS_MONITOR_SENSOR_TOXINS_LAB = "Toxins Mixing Chamber")
ui_x = 400
ui_y = 300
/////////////////////////////////////////////////////////////
// LARGE TANK CONTROL
@@ -184,13 +193,9 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
var/output_tag
frequency = FREQ_ATMOS_STORAGE
circuit = /obj/item/circuitboard/computer/atmos_control/tank
var/list/input_info
var/list/output_info
ui_x = 500
ui_y = 315
/obj/machinery/computer/atmos_control/tank/oxygen_tank
name = "Oxygen Supply Control"
input_tag = ATMOS_GAS_MONITOR_INPUT_O2
@@ -236,7 +241,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
// This hacky madness is the evidence of the fact that a lot of machines were never meant to be constructable, im so sorry you had to see this
/obj/machinery/computer/atmos_control/tank/proc/reconnect(mob/user)
var/list/IO = list()
var/datum/radio_frequency/freq = SSradio.return_frequency(FREQ_ATMOS_STORAGE)
var/datum/radio_frequency/freq = SSradio.return_frequency(frequency)
var/list/devices = freq.devices["_default"]
for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices)
var/list/text = splittext(U.id_tag, "_")
@@ -252,10 +257,11 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
src.output_tag = "[S]_out"
name = "[uppertext(S)] Supply Control"
var/list/new_devices = freq.devices["4"]
sensors.Cut()
for(var/obj/machinery/air_sensor/U in new_devices)
var/list/text = splittext(U.id_tag, "_")
if(text[1] == S)
sensors = list("[S]_sensor" = "Tank")
sensors = list("[S]_sensor" = "[S] Tank")
break
for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices)
@@ -268,13 +274,16 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
data["tank"] = TRUE
data["inputting"] = input_info ? input_info["power"] : FALSE
data["inputRate"] = input_info ? input_info["volume_rate"] : 0
data["maxInputRate"] = input_info ? MAX_TRANSFER_RATE : 0
data["outputting"] = output_info ? output_info["power"] : FALSE
data["outputPressure"] = output_info ? output_info["internal"] : 0
data["maxOutputPressure"] = output_info ? MAX_OUTPUT_PRESSURE : 0
return data
/obj/machinery/computer/atmos_control/tank/ui_act(action, params)
if(..() || !radio_connection)
. = ..()
if(. || !radio_connection)
return
var/datum/signal/signal = new(list("sigtype" = "command", "user" = usr))
switch(action)
+74 -49
View File
@@ -1,3 +1,5 @@
#define DEFAULT_MAP_SIZE 15
/obj/machinery/computer/security
name = "security camera console"
desc = "Used to access the various cameras on the station."
@@ -8,15 +10,19 @@
var/list/network = list("ss13")
var/obj/machinery/camera/active_camera
/// The turf where the camera was last updated.
var/turf/last_camera_turf
var/list/concurrent_users = list()
// Stuff needed to render the map
var/map_name
var/const/default_map_size = 15
var/obj/screen/cam_screen
var/obj/screen/plane_master/lighting/cam_plane_master
var/obj/screen/map_view/cam_screen
/// All the plane masters that need to be applied.
var/list/cam_plane_masters
var/obj/screen/background/cam_background
interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_SET_MACHINE //| INTERACT_MACHINE_REQUIRES_SIGHT
/obj/machinery/computer/security/Initialize()
. = ..()
// Map name has to start and end with an A-Z character,
@@ -33,18 +39,20 @@
cam_screen.assigned_map = map_name
cam_screen.del_on_map_removal = FALSE
cam_screen.screen_loc = "[map_name]:1,1"
cam_plane_master = new
cam_plane_master.name = "plane_master"
cam_plane_master.assigned_map = map_name
cam_plane_master.del_on_map_removal = FALSE
cam_plane_master.screen_loc = "[map_name]:CENTER"
cam_plane_masters = list()
for(var/plane in subtypesof(/obj/screen/plane_master))
var/obj/screen/instance = new plane()
instance.assigned_map = map_name
instance.del_on_map_removal = FALSE
instance.screen_loc = "[map_name]:CENTER"
cam_plane_masters += instance
cam_background = new
cam_background.assigned_map = map_name
cam_background.del_on_map_removal = FALSE
/obj/machinery/computer/security/Destroy()
qdel(cam_screen)
qdel(cam_plane_master)
QDEL_LIST(cam_plane_masters)
qdel(cam_background)
return ..()
@@ -56,9 +64,10 @@
/obj/machinery/computer/security/ui_interact(mob/user, datum/tgui/ui)
// Update UI
ui = SStgui.try_update_ui(user, src, ui)
// Show static if can't use the camera
if(!active_camera?.can_use())
show_camera_static()
// Update the camera, showing static if necessary and updating data if the location has moved.
update_active_camera_screen()
if(!ui)
var/user_ref = REF(user)
var/is_living = isliving(user)
@@ -72,7 +81,7 @@
use_power(active_power_usage)
// Register map objects
user.client.register_map_obj(cam_screen)
for(var/plane in cam_plane_master)
for(var/plane in cam_plane_masters)
user.client.register_map_obj(plane)
user.client.register_map_obj(cam_background)
// Open UI
@@ -100,6 +109,7 @@
data["cameras"] += list(list(
name = C.c_tag,
))
return data
/obj/machinery/computer/security/ui_act(action, params)
@@ -110,31 +120,51 @@
if(action == "switch_camera")
var/c_tag = params["name"]
var/list/cameras = get_available_cameras()
var/obj/machinery/camera/C = cameras[c_tag]
active_camera = C
var/obj/machinery/camera/selected_camera = cameras[c_tag]
active_camera = selected_camera
playsound(src, get_sfx("terminal_type"), 25, FALSE)
// Show static if can't use the camera
if(!active_camera?.can_use())
show_camera_static()
if(!selected_camera)
return TRUE
var/list/visible_turfs = list()
for(var/turf/T in (C.isXRay() \
? range(C.view_range, C) \
: view(C.view_range, C)))
visible_turfs += T
var/list/bbox = get_bbox_of_atoms(visible_turfs)
var/size_x = bbox[3] - bbox[1] + 1
var/size_y = bbox[4] - bbox[2] + 1
cam_screen.vis_contents = visible_turfs
cam_background.icon_state = "clear"
cam_background.fill_rect(1, 1, size_x, size_y)
update_active_camera_screen()
return TRUE
/obj/machinery/computer/security/proc/update_active_camera_screen()
// Show static if can't use the camera
if(!active_camera?.can_use())
show_camera_static()
return
var/list/visible_turfs = list()
// Is this camera located in or attached to a living thing? If so, assume the camera's loc is the living thing.
var/cam_location = isliving(active_camera.loc) ? active_camera.loc : active_camera
// If we're not forcing an update for some reason and the cameras are in the same location,
// we don't need to update anything.
// Most security cameras will end here as they're not moving.
var/newturf = get_turf(cam_location)
if(last_camera_turf == newturf)
return
// Cameras that get here are moving, and are likely attached to some moving atom such as cyborgs.
last_camera_turf = get_turf(cam_location)
var/list/visible_things = active_camera.isXRay() ? range(active_camera.view_range, cam_location) : view(active_camera.view_range, cam_location)
for(var/turf/visible_turf in visible_things)
visible_turfs += visible_turf
var/list/bbox = get_bbox_of_atoms(visible_turfs)
var/size_x = bbox[3] - bbox[1] + 1
var/size_y = bbox[4] - bbox[2] + 1
cam_screen.vis_contents = visible_turfs
cam_background.icon_state = "clear"
cam_background.fill_rect(1, 1, size_x, size_y)
/obj/machinery/computer/security/ui_close(mob/user)
var/user_ref = REF(user)
var/is_living = isliving(user)
@@ -151,7 +181,7 @@
/obj/machinery/computer/security/proc/show_camera_static()
cam_screen.vis_contents.Cut()
cam_background.icon_state = "scanline2"
cam_background.fill_rect(1, 1, default_map_size, default_map_size)
cam_background.fill_rect(1, 1, DEFAULT_MAP_SIZE, DEFAULT_MAP_SIZE)
// Returns the list of cameras accessible from this computer
/obj/machinery/computer/security/proc/get_available_cameras()
@@ -179,7 +209,7 @@
name = "security camera monitor"
desc = "An old TV hooked into the station's camera network."
icon_state = "television"
icon_keyboard = null
icon_keyboard = "no_keyboard"
icon_screen = "detective_tv"
pass_flags = PASSTABLE
@@ -211,7 +241,7 @@
/obj/machinery/computer/security/qm
name = "\improper Quartermaster's camera console"
desc = "A console with access to the mining, auxillary base and vault camera networks."
desc = "A console with access to the mining, auxiliary base and vault camera networks."
network = list("mine", "auxbase", "vault")
circuit = null
@@ -222,17 +252,12 @@
desc = "Used for watching an empty arena."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "telescreen"
layer = SIGN_LAYER
network = list("thunder")
density = FALSE
circuit = null
light_power = 0
/obj/machinery/computer/security/telescreen/Initialize()
. = ..()
var/turf/T = get_turf_pixel(src)
if(iswallturf(T))
plane = ABOVE_WALL_PLANE
/obj/machinery/computer/security/telescreen/update_icon_state()
icon_state = initial(icon_state)
if(stat & BROKEN)
@@ -246,21 +271,19 @@
network = list("thunder")
density = FALSE
circuit = null
//interaction_flags_atom = NONE // interact() is called by BigClick()
interaction_flags_atom = NONE // interact() is called by BigClick()
var/icon_state_off = "entertainment_blank"
var/icon_state_on = "entertainment"
/* If someone would like to try to get this long-distance viewing thing working, be my guest. I tried everything I could possibly think of and it just refused to operate correctly.
/obj/machinery/computer/security/telescreen/entertainment/Initialize()
. = ..()
RegisterSignal(src, COMSIG_CLICK, .proc/BigClick)
// Bypass clickchain to allow humans to use the telescreen from a distance
/obj/machinery/computer/security/telescreen/entertainment/proc/BigClick()
interact(usr)
SIGNAL_HANDLER
*/
INVOKE_ASYNC(src, /atom.proc/interact, usr)
/obj/machinery/computer/security/telescreen/entertainment/proc/notify(on)
if(on && icon_state == icon_state_off)
@@ -279,8 +302,8 @@
network = list("rd", "aicore", "aiupload", "minisat", "xeno", "test")
/obj/machinery/computer/security/telescreen/circuitry
name = "circuitry telescreen"
desc = "Used for watching the other eggheads from the safety of the circuitry lab."
name = "research telescreen"
desc = "A telescreen with access to the research division's camera network."
network = list("rd")
/obj/machinery/computer/security/telescreen/ce
@@ -324,8 +347,8 @@
network = list("prison")
/obj/machinery/computer/security/telescreen/auxbase
name = "auxillary base monitor"
desc = "A telescreen that connects to the auxillary base's camera."
name = "auxiliary base monitor"
desc = "A telescreen that connects to the auxiliary base's camera."
network = list("auxbase")
/obj/machinery/computer/security/telescreen/minisat
@@ -346,3 +369,5 @@
for(var/i in network)
network -= i
network += "[idnum][i]"
#undef DEFAULT_MAP_SIZE
File diff suppressed because it is too large Load Diff
+104 -67
View File
@@ -1,21 +1,38 @@
/obj/machinery/computer/pod
name = "mass driver launch control"
desc = "A combined blastdoor and mass driver control unit."
// processing_flags = START_PROCESSING_MANUALLY
/// Connected mass driver
var/obj/machinery/mass_driver/connected = null
var/title = "Mass Driver Controls"
/// ID of the launch control
var/id = 1
var/timing = 0
/// If the launch timer counts down
var/timing = FALSE
/// Time before auto launch
var/time = 30
/// Range in which we search for a mass drivers and poddoors nearby
var/range = 4
/// Countdown timer for the mass driver's delayed launch functionality.
COOLDOWN_DECLARE(massdriver_countdown)
/obj/machinery/computer/pod/Initialize()
. = ..()
for(var/obj/machinery/mass_driver/M in range(range, src))
if(M.id == id)
connected = M
break
/obj/machinery/computer/pod/process(delta_time)
if(COOLDOWN_FINISHED(src, massdriver_countdown))
timing = FALSE
// alarm() sleeps, so we want to end processing first and can't rely on return PROCESS_KILL
// end_processing()
STOP_PROCESSING(SSmachines, src)
alarm()
/**
* Initiates launching sequence by checking if all components are functional, opening poddoors, firing mass drivers and then closing poddoors
*/
/obj/machinery/computer/pod/proc/alarm()
if(stat & (NOPOWER|BROKEN))
return
@@ -39,92 +56,112 @@
if(M.id == id)
M.close()
/obj/machinery/computer/pod/ui_interact(mob/user)
/obj/machinery/computer/pod/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "MassDriverControl", name)
ui.open()
/obj/machinery/computer/pod/ui_data(mob/user)
var/list/data = list()
// If the cooldown has finished, just display the time. If the cooldown hasn't finished, display the cooldown.
var/display_time = COOLDOWN_FINISHED(src, massdriver_countdown) ? time : COOLDOWN_TIMELEFT(src, massdriver_countdown) * 0.1
data["connected"] = connected ? TRUE : FALSE
data["seconds"] = round(display_time % 60)
data["minutes"] = round((display_time - data["seconds"]) / 60)
data["timing"] = timing
data["power"] = connected ? connected.power : 0.25
data["poddoor"] = FALSE
for(var/obj/machinery/door/poddoor/door in range(range, src))
if(door.id == id)
data["poddoor"] = TRUE
break
return data
/obj/machinery/computer/pod/ui_act(action, list/params)
. = ..()
if(!allowed(user))
to_chat(user, "<span class='warning'>Access denied.</span>")
if(.)
return
if(!allowed(usr))
to_chat(usr, "<span class='warning'>Access denied.</span>")
return
var/dat = ""
if(connected)
var/d2
if(timing) //door controls do not need timers.
d2 = "<A href='?src=[REF(src)];time=0'>Stop Time Launch</A>"
else
d2 = "<A href='?src=[REF(src)];time=1'>Initiate Time Launch</A>"
dat += "<HR>\nTimer System: [d2]\nTime Left: [DisplayTimeText(time)] <A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>"
var/temp = ""
var/list/L = list( 0.25, 0.5, 1, 2, 4, 8, 16 )
for(var/t in L)
if(t == connected.power)
temp += "[t] "
switch(action)
if("set_power")
if(!connected)
return
var/value = text2num(params["power"])
if(!value)
return
value = clamp(value, 0.25, 16)
connected.power = value
return TRUE
if("launch")
alarm()
return TRUE
if("time")
timing = !timing
if(timing)
COOLDOWN_START(src, massdriver_countdown, time SECONDS)
// begin_processing()
START_PROCESSING(SSmachines, src)
else
temp += "<A href = '?src=[REF(src)];power=[t]'>[t]</A> "
dat += "<HR>\nPower Level: [temp]<BR>\n<A href = '?src=[REF(src)];alarm=1'>Firing Sequence</A><BR>\n<A href = '?src=[REF(src)];drive=1'>Test Fire Driver</A><BR>\n<A href = '?src=[REF(src)];door=1'>Toggle Outer Door</A><BR>"
else
dat += "<BR>\n<A href = '?src=[REF(src)];door=1'>Toggle Outer Door</A><BR>"
dat += "<BR><BR><A href='?src=[REF(user)];mach_close=computer'>Close</A>"
add_fingerprint(usr)
var/datum/browser/popup = new(user, "computer", title, 400, 500)
popup.set_content(dat)
popup.open()
/obj/machinery/computer/pod/process()
if(!..())
return
if(timing)
if(time > 0)
time = round(time) - 1
else
alarm()
time = 0
timing = 0
updateDialog()
/obj/machinery/computer/pod/Topic(href, href_list)
if(..())
return
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"])
t = min(max(0.25, t), 16)
if(connected)
connected.power = t
if(href_list["alarm"])
alarm()
if(href_list["time"])
timing = text2num(href_list["time"])
if(href_list["tp"])
var/tp = text2num(href_list["tp"])
time += tp
time = min(max(round(time), 0), 120)
if(href_list["door"])
time = COOLDOWN_TIMELEFT(src, massdriver_countdown) * 0.1
COOLDOWN_RESET(src, massdriver_countdown)
// end_processing()
STOP_PROCESSING(SSmachines, src)
return TRUE
if("input")
var/value = text2num(params["adjust"])
if(!value)
return
value = round(time + value)
time = clamp(value, 0, 120)
return TRUE
if("door")
for(var/obj/machinery/door/poddoor/M in range(range, src))
if(M.id == id)
if(M.density)
M.open()
else
M.close()
if(href_list["drive"])
return TRUE
if("driver_test")
for(var/obj/machinery/mass_driver/M in range(range, src))
if(M.id == id)
M.power = connected.power
M.power = connected?.power
M.drive()
updateUsrDialog()
return TRUE
/obj/machinery/computer/pod/old
name = "\improper DoorMex control console"
title = "Door Controls"
icon_state = "oldcomp"
icon_screen = "library"
icon_keyboard = null
icon_keyboard = "no_keyboard"
// /obj/machinery/computer/pod/old/mass_driver_controller
// name = "\improper Mass Driver Controller"
// icon = 'icons/obj/airlock_machines.dmi'
// icon_state = "airlock_control_standby"
// icon_keyboard = "no_keyboard"
// density = FALSE
// /obj/machinery/computer/pod/old/mass_driver_controller/toxinsdriver
// id = MASSDRIVER_TOXINS
// //for maps where pod doors are outside of the standard 4 tile controller detection range (ie Pubbystation)
// /obj/machinery/computer/pod/old/mass_driver_controller/toxinsdriver/longrange
// range = 6
// /obj/machinery/computer/pod/old/mass_driver_controller/chapelgun
// id = MASSDRIVER_CHAPEL
// /obj/machinery/computer/pod/old/mass_driver_controller/trash
// id = MASSDRIVER_DISPOSALS
/obj/machinery/computer/pod/old/syndicate
name = "\improper ProComp Executive IIc"
desc = "The Syndicate operate on a tight budget. Operates external airlocks."
title = "External Airlock Controls"
req_access = list(ACCESS_SYNDICATE)
/obj/machinery/computer/pod/old/swf
+20 -3
View File
@@ -11,8 +11,24 @@
var/id = 1
var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess.
/obj/machinery/mass_driver/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
id = "[idnum][id]"
// /obj/machinery/mass_driver/chapelgun
// name = "holy driver"
// id = MASSDRIVER_CHAPEL
// /obj/machinery/mass_driver/toxins
// id = MASSDRIVER_TOXINS
// /obj/machinery/mass_driver/trash
// id = MASSDRIVER_DISPOSALS
// /obj/machinery/mass_driver/Destroy()
// for(var/obj/machinery/computer/pod/control in GLOB.machines)
// if(control.id == id)
// control.connected = null
// return ..()
/obj/machinery/mass_driver/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
id = "[port.id]_[id]"
/obj/machinery/mass_driver/proc/drive(amount)
if(stat & (BROKEN|NOPOWER))
@@ -22,6 +38,8 @@
var/atom/target = get_edge_target_turf(src, dir)
for(var/atom/movable/O in loc)
if(!O.anchored || ismecha(O)) //Mechs need their launch platforms.
if(ismob(O) && !isliving(O))
continue
O_limit++
if(O_limit >= 20)
audible_message("<span class='notice'>[src] lets out a screech, it doesn't seem to be able to handle the load.</span>")
@@ -30,7 +48,6 @@
O.throw_at(target, drive_range * power, power)
flick("mass_driver1", src)
/obj/machinery/mass_driver/emp_act(severity)
. = ..()
if (. & EMP_PROTECT_SELF)
-1
View File
@@ -676,4 +676,3 @@
/obj/machinery/mecha_part_fabricator/offstation
link_on_init = FALSE
circuit = /obj/item/circuitboard/machine/mechfab/offstation
+5 -1
View File
@@ -133,7 +133,6 @@
icon_state += "-open"
add_radio()
add_cabin()
add_airtank()
spark_system.set_up(2, 0, src)
spark_system.attach(src)
smoke_system.set_up(3, src)
@@ -149,6 +148,11 @@
diag_hud_set_mechhealth()
diag_hud_set_mechcell()
diag_hud_set_mechstat()
return INITIALIZE_HINT_LATELOAD
/obj/mecha/LateInitialize()
. = ..()
add_airtank()
/obj/mecha/get_cell()
return cell
+14 -13
View File
@@ -29,7 +29,7 @@
integrity = round((M.obj_integrity / M.max_integrity) * 100),
charge = M.cell ? round(M.cell.percent()) : null,
airtank = M.internal_tank ? M.return_pressure() : null,
pilot = M.occupant,
pilot = list(M.occupant),
location = get_area_name(M, TRUE),
active_equipment = M.selected,
emp_recharging = MT.recharging,
@@ -38,7 +38,7 @@
if(istype(M, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/RM = M
mech_data += list(
cargo_space = round((RM.cargo.len / RM.cargo_capacity) * 100)
cargo_space = round((LAZYLEN(RM.cargo) / RM.cargo_capacity) * 100)
)
data["mechs"] += list(mech_data)
@@ -46,7 +46,8 @@
return data
/obj/machinery/computer/mecha/ui_act(action, params)
if(..())
. = ..()
if(.)
return
switch(action)
@@ -57,7 +58,7 @@
var/message = stripped_input(usr, "Input message", "Transmit message")
var/obj/mecha/M = MT.chassis
if(trim(message) && M)
M.occupant_message(message)
to_chat(M.occupant, message)
to_chat(usr, "<span class='notice'>Message sent.</span>")
. = TRUE
if("shock")
@@ -67,8 +68,8 @@
var/obj/mecha/M = MT.chassis
if(M)
MT.shock()
log_game("[key_name(usr)] has activated remote EMP on exosuit [M], located at [loc_name(M)], which is currently [M.occupant? "being piloted by [key_name(M.occupant)]." : "without a pilot."] ")
message_admins("[key_name_admin(usr)][ADMIN_FLW(usr)] has activated remote EMP on exosuit [M][ADMIN_JMP(M)], which is currently [M.occupant ? "being piloted by [key_name_admin(M.occupant)][ADMIN_FLW(M.occupant)]." : "without a pilot."] ")
log_game("[key_name(usr)] has activated remote EMP on exosuit [M], located at [loc_name(M)], which [M.occupant ? "has the occupants [M.occupant]." : "without a pilot."] ")
message_admins("[key_name_admin(usr)][ADMIN_FLW(usr)] has activated remote EMP on exosuit [M][ADMIN_JMP(M)], which is currently [M.occupant ? "occupied by [M.occupant][ADMIN_FLW(M)]." : "without a pilot."] ")
. = TRUE
/obj/item/mecha_parts/mecha_tracking
@@ -85,8 +86,8 @@
var/obj/mecha/chassis
/**
* Returns a html formatted string describing attached mech status
*/
* Returns a html formatted string describing attached mech status
*/
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info()
if(!chassis)
return FALSE
@@ -101,7 +102,7 @@
<b>Active Equipment:</b> [chassis.selected || "None"]"}
if(istype(chassis, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/RM = chassis
answer += "<br><b>Used Cargo Space:</b> [round((RM.cargo.len / RM.cargo_capacity * 100), 0.01)]%"
answer += "<br><b>Used Cargo Space:</b> [round((LAZYLEN(RM.cargo) / RM.cargo_capacity * 100), 0.01)]%"
return answer
@@ -125,8 +126,8 @@
chassis = M
/**
* Attempts to EMP mech that the tracker is attached to, if there is one and tracker is not on cooldown
*/
* Attempts to EMP mech that the tracker is attached to, if there is one and tracker is not on cooldown
*/
/obj/item/mecha_parts/mecha_tracking/proc/shock()
if(recharging)
return
@@ -136,8 +137,8 @@
recharging = TRUE
/**
* Resets recharge variable, allowing tracker to be EMP pulsed again
*/
* Resets recharge variable, allowing tracker to be EMP pulsed again
*/
/obj/item/mecha_parts/mecha_tracking/proc/recharge()
recharging = FALSE
@@ -14,8 +14,41 @@
w_class = WEIGHT_CLASS_SMALL
grind_results = list(/datum/reagent/silicon = 20)
var/build_path = null
///determines if the circuit board originated from a vendor off station or not.
var/onstation = TRUE
/obj/item/circuitboard/proc/apply_default_parts(obj/machinery/M)
if(LAZYLEN(M.component_parts))
// This really shouldn't happen. If it somehow does, print out a stack trace and gracefully handle it.
stack_trace("apply_defauly_parts called on machine that already had component_parts: [M]")
// Move to nullspace so you don't trigger handle_atom_del logic and remove existing parts.
for(var/obj/item/part in M.component_parts)
part.moveToNullspace(loc)
qdel(part)
// List of components always contains the circuit board used to build it.
M.component_parts = list(src)
forceMove(M)
if(M.circuit != src)
// This really shouldn't happen. If it somehow does, print out a stack trace and gracefully handle it.
stack_trace("apply_default_parts called from a circuit board that does not belong to machine: [M]")
// Move to nullspace so you don't trigger handle_atom_del logic, remove old circuit, add new circuit.
M.circuit.moveToNullspace()
qdel(M.circuit)
M.circuit = src
return
/**
* Used to allow the circuitboard to configure a machine in some way, shape or form.
*
* Arguments:
* * machine - The machine to attempt to configure.
*/
/obj/item/circuitboard/proc/configure_machine(obj/machinery/machine)
return
// Circuitboard/machine
@@ -36,8 +69,8 @@ micro-manipulator, console screen, beaker, Microlaser, matter bin, power cells.
if(!req_components)
return
M.component_parts = list(src) // List of components always contains a board
moveToNullspace()
. = ..()
moveToNullspace() // thorw ourselves in nullspace
for(var/comp_path in req_components)
var/comp_amt = req_components[comp_path]
@@ -1,58 +1,22 @@
/obj/item/circuitboard/computer/turbine_computer
name = "Turbine Computer (Computer Board)"
build_path = /obj/machinery/computer/turbine_computer
/obj/item/circuitboard/computer/launchpad_console
name = "Launchpad Control Console (Computer Board)"
build_path = /obj/machinery/computer/launchpad
/obj/item/circuitboard/computer/message_monitor
name = "Message Monitor (Computer Board)"
build_path = /obj/machinery/computer/message_monitor
/obj/item/circuitboard/computer/security
name = "Security Cameras (Computer Board)"
build_path = /obj/machinery/computer/security
/obj/item/circuitboard/computer/security/shuttle
name = "Shuttlelinking Security Cameras (Computer Board)"
build_path = /obj/machinery/computer/security/shuttle
/obj/item/circuitboard/computer/xenobiology
name = "circuit board (Xenobiology Console)"
build_path = /obj/machinery/computer/camera_advanced/xenobio
/obj/item/circuitboard/computer/base_construction
name = "circuit board (Aux Mining Base Construction Console)"
build_path = /obj/machinery/computer/camera_advanced/base_construction
//Command
/obj/item/circuitboard/computer/aiupload
name = "AI Upload (Computer Board)"
icon_state = "command"
build_path = /obj/machinery/computer/upload/ai
/obj/item/circuitboard/computer/borgupload
name = "Cyborg Upload (Computer Board)"
icon_state = "command"
build_path = /obj/machinery/computer/upload/borg
/obj/item/circuitboard/computer/med_data
name = "Medical Records Console (Computer Board)"
build_path = /obj/machinery/computer/med_data
/obj/item/circuitboard/computer/pandemic
name = "PanD.E.M.I.C. 2200 (Computer Board)"
build_path = /obj/machinery/computer/pandemic
/obj/item/circuitboard/computer/scan_consolenew
name = "DNA Machine (Computer Board)"
build_path = /obj/machinery/computer/scan_consolenew
/obj/item/circuitboard/computer/communications
name = "Communications (Computer Board)"
build_path = /obj/machinery/computer/communications
var/lastTimeUsed = 0
/obj/item/circuitboard/computer/bsa_control
name = "Bluespace Artillery Controls (Computer Board)"
build_path = /obj/machinery/computer/bsa_control
/obj/item/circuitboard/computer/card
name = "ID Console (Computer Board)"
icon_state = "command"
build_path = /obj/machinery/computer/card
/obj/item/circuitboard/computer/card/centcom
@@ -73,266 +37,238 @@
return ..()
/obj/item/circuitboard/computer/card/minor/examine(user)
. = ..()
. += "Currently set to \"[dept_list[target_dept]]\"."
..()
to_chat(user, "<span class='notice'>Currently set to \"[dept_list[target_dept]]\".</span>")
//obj/item/circuitboard/computer/shield
// name = "Shield Control (Computer Board)"
// icon_state = "command"
// build_path = /obj/machinery/computer/stationshield
/obj/item/circuitboard/computer/teleporter
name = "Teleporter (Computer Board)"
build_path = /obj/machinery/computer/teleporter
/obj/item/circuitboard/computer/secure_data
name = "Security Records Console (Computer Board)"
build_path = /obj/machinery/computer/secure_data
//Engineering
/obj/item/circuitboard/computer/stationalert
name = "Station Alerts (Computer Board)"
build_path = /obj/machinery/computer/station_alert
/obj/item/circuitboard/computer/apc_control
name = "\improper Power Flow Control Console (Computer Board)"
icon_state = "engineering"
build_path = /obj/machinery/computer/apc_control
/obj/item/circuitboard/computer/atmos_alert
name = "Atmospheric Alert (Computer Board)"
icon_state = "engineering"
build_path = /obj/machinery/computer/atmos_alert
/obj/item/circuitboard/computer/atmos_control
name = "Atmospheric Monitor (Computer Board)"
icon_state = "engineering"
build_path = /obj/machinery/computer/atmos_control
/obj/item/circuitboard/computer/atmos_control/incinerator
name = "Incinerator Air Control (Computer Board)"
build_path = /obj/machinery/computer/atmos_control/incinerator
/obj/item/circuitboard/computer/atmos_control/toxinsmix
name = "Toxins Mixing Air Control (Computer Board)"
build_path = /obj/machinery/computer/atmos_control/toxinsmix
/obj/item/circuitboard/computer/atmos_control/tank
name = "Tank Control (Computer Board)"
build_path = /obj/machinery/computer/atmos_control/tank
/obj/item/circuitboard/computer/atmos_alert
name = "Atmospheric Alert (Computer Board)"
build_path = /obj/machinery/computer/atmos_alert
/obj/item/circuitboard/computer/atmos_control/tank/oxygen_tank
name = "Oxygen Supply Control (Computer Board)"
build_path = /obj/machinery/computer/atmos_control/tank/oxygen_tank
/obj/item/circuitboard/computer/pod
name = "Massdriver control (Computer Board)"
build_path = /obj/machinery/computer/pod
/obj/item/circuitboard/computer/atmos_control/tank/toxin_tank
name = "Plasma Supply Control (Computer Board)"
build_path = /obj/machinery/computer/atmos_control/tank/toxin_tank
/obj/item/circuitboard/computer/robotics
name = "Robotics Control (Computer Board)"
build_path = /obj/machinery/computer/robotics
/obj/item/circuitboard/computer/atmos_control/tank/air_tank
name = "Mixed Air Supply Control (Computer Board)"
build_path = /obj/machinery/computer/atmos_control/tank/air_tank
/obj/item/circuitboard/computer/cloning
name = "Cloning (Computer Board)"
build_path = /obj/machinery/computer/cloning
var/list/records = list()
/obj/item/circuitboard/computer/atmos_control/tank/mix_tank
name = "Gas Mix Supply Control (Computer Board)"
build_path = /obj/machinery/computer/atmos_control/tank/mix_tank
/obj/item/circuitboard/computer/cloning/prototype
name = "Prototype Cloning (Computer Board)"
build_path = /obj/machinery/computer/cloning/prototype
/obj/item/circuitboard/computer/atmos_control/tank/nitrous_tank
name = "Nitrous Oxide Supply Control (Computer Board)"
build_path = /obj/machinery/computer/atmos_control/tank/nitrous_tank
/obj/item/circuitboard/computer/arcade/battle
name = "Arcade Battle (Computer Board)"
build_path = /obj/machinery/computer/arcade/battle
/obj/item/circuitboard/computer/atmos_control/tank/nitrogen_tank
name = "Nitrogen Supply Control (Computer Board)"
build_path = /obj/machinery/computer/atmos_control/tank/nitrogen_tank
/obj/item/circuitboard/computer/arcade/orion_trail
name = "Orion Trail (Computer Board)"
build_path = /obj/machinery/computer/arcade/orion_trail
/obj/item/circuitboard/computer/atmos_control/tank/carbon_tank
name = "Carbon Dioxide Supply Control (Computer Board)"
build_path = /obj/machinery/computer/atmos_control/tank/carbon_tank
/obj/item/circuitboard/computer/arcade/minesweeper
name = "Minesweeper (Computer Board)"
build_path = /obj/machinery/computer/arcade/minesweeper
// /obj/item/circuitboard/computer/atmos_control/tank/bz_tank
// name = "BZ Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/bz_tank
/obj/item/circuitboard/computer/arcade/amputation
name = "Mediborg's Amputation Adventure (Computer Board)"
build_path = /obj/machinery/computer/arcade/amputation
// /obj/item/circuitboard/computer/atmos_control/tank/freon_tank
// name = "Freon Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/freon_tank
/obj/item/circuitboard/computer/turbine_control
name = "Turbine control (Computer Board)"
build_path = /obj/machinery/computer/turbine_computer
// /obj/item/circuitboard/computer/atmos_control/tank/halon_tank
// name = "Halon Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/halon_tank
/obj/item/circuitboard/computer/solar_control
name = "Solar Control (Computer Board)" //name fixed 250810
build_path = /obj/machinery/power/solar_control
// /obj/item/circuitboard/computer/atmos_control/tank/healium_tank
// name = "Healium Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/healium_tank
/obj/item/circuitboard/computer/powermonitor
name = "Power Monitor (Computer Board)" //name fixed 250810
build_path = /obj/machinery/computer/monitor
// /obj/item/circuitboard/computer/atmos_control/tank/hydrogen_tank
// name = "Hydrogen Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/hydrogen_tank
/obj/item/circuitboard/computer/powermonitor/secret
name = "Outdated Power Monitor (Computer Board)" //Variant used on ruins to prevent them from showing up on PDA's.
build_path = /obj/machinery/computer/monitor/secret
// /obj/item/circuitboard/computer/atmos_control/tank/hypernoblium_tank
// name = "Hypernoblium Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/hypernoblium_tank
/obj/item/circuitboard/computer/olddoor
name = "DoorMex (Computer Board)"
build_path = /obj/machinery/computer/pod/old
// /obj/item/circuitboard/computer/atmos_control/tank/miasma_tank
// name = "Miasma Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/miasma_tank
/obj/item/circuitboard/computer/syndicatedoor
name = "ProComp Executive (Computer Board)"
build_path = /obj/machinery/computer/pod/old/syndicate
// /obj/item/circuitboard/computer/atmos_control/tank/nitryl_tank
// name = "Nitryl Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/nitryl_tank
/obj/item/circuitboard/computer/swfdoor
name = "Magix (Computer Board)"
build_path = /obj/machinery/computer/pod/old/swf
// /obj/item/circuitboard/computer/atmos_control/tank/pluoxium_tank
// name = "Pluoxium Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/pluoxium_tank
/obj/item/circuitboard/computer/prisoner
name = "Prisoner Management Console (Computer Board)"
build_path = /obj/machinery/computer/prisoner/management
// /obj/item/circuitboard/computer/atmos_control/tank/proto_nitrate_tank
// name = "Proto-Nitrate Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/proto_nitrate_tank
/obj/item/circuitboard/computer/gulag_teleporter_console
name = "Labor Camp teleporter console (Computer Board)"
build_path = /obj/machinery/computer/prisoner/gulag_teleporter_computer
// /obj/item/circuitboard/computer/atmos_control/tank/stimulum_tank
// name = "Stimulum Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/stimulum_tank
/obj/item/circuitboard/computer/rdconsole/production
name = "R&D Console Production Only (Computer Board)"
build_path = /obj/machinery/computer/rdconsole/production
// /obj/item/circuitboard/computer/atmos_control/tank/tritium_tank
// name = "Tritium Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/tritium_tank
/obj/item/circuitboard/computer/rdconsole
name = "R&D Console (Computer Board)"
build_path = /obj/machinery/computer/rdconsole/core
// /obj/item/circuitboard/computer/atmos_control/tank/water_vapor
// name = "Water Vapor Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/water_vapor
/obj/item/circuitboard/computer/rdconsole/attackby(obj/item/I, mob/user, params)
if(I.tool_behaviour == TOOL_SCREWDRIVER)
if(build_path == /obj/machinery/computer/rdconsole/core)
name = "R&D Console - Robotics (Computer Board)"
build_path = /obj/machinery/computer/rdconsole/robotics
to_chat(user, "<span class='notice'>Access protocols successfully updated.</span>")
else
name = "R&D Console (Computer Board)"
build_path = /obj/machinery/computer/rdconsole/core
to_chat(user, "<span class='notice'>Defaulting access protocols.</span>")
else
return ..()
// /obj/item/circuitboard/computer/atmos_control/tank/zauker_tank
// name = "Zauker Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/zauker_tank
/obj/item/circuitboard/computer/mecha_control
name = "Exosuit Control Console (Computer Board)"
build_path = /obj/machinery/computer/mecha
// /obj/item/circuitboard/computer/atmos_control/tank/helium_tank
// name = "Helium Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/helium_tank
/obj/item/circuitboard/computer/rdservercontrol
name = "R&D Server Control (Computer Board)"
build_path = /obj/machinery/computer/rdservercontrol
// /obj/item/circuitboard/computer/atmos_control/tank/antinoblium_tank
// name = "Antinoblium Supply Control (Computer Board)"
// build_path = /obj/machinery/computer/atmos_control/tank/antinoblium_tank
/obj/item/circuitboard/computer/crew
name = "Crew Monitoring Console (Computer Board)"
build_path = /obj/machinery/computer/crew
/obj/item/circuitboard/computer/auxiliary_base
name = "Auxiliary Base Management Console (Computer Board)"
icon_state = "engineering"
build_path = /obj/machinery/computer/auxillary_base
/obj/item/circuitboard/computer/mech_bay_power_console
name = "Mech Bay Power Control Console (Computer Board)"
build_path = /obj/machinery/computer/mech_bay_power_console
/obj/item/circuitboard/computer/base_construction
name = "circuit board (Generic Base Construction Console)"
icon_state = "engineering"
build_path = /obj/machinery/computer/camera_advanced/base_construction
/obj/item/circuitboard/computer/cargo
name = "Supply Console (Computer Board)"
build_path = /obj/machinery/computer/cargo
var/contraband = FALSE
// /obj/item/circuitboard/computer/base_construction/aux
// name = "circuit board (Aux Mining Base Construction Console)"
// icon_state = "engineering"
// build_path = /obj/machinery/computer/camera_advanced/base_construction/aux
/obj/item/circuitboard/computer/cargo/multitool_act(mob/living/user)
if(!(obj_flags & EMAGGED))
contraband = !contraband
to_chat(user, "<span class='notice'>Receiver spectrum set to [contraband ? "Broad" : "Standard"].</span>")
else
to_chat(user, "<span class='notice'>The spectrum chip is unresponsive.</span>")
/obj/item/circuitboard/computer/cargo/emag_act(mob/living/user)
. = ..()
if(obj_flags & EMAGGED)
return
contraband = TRUE
obj_flags |= EMAGGED
to_chat(user, "<span class='notice'>You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband.</span>")
return TRUE
/obj/item/circuitboard/computer/cargo/express
name = "Express Supply Console (Computer Board)"
build_path = /obj/machinery/computer/cargo/express
/obj/item/circuitboard/computer/cargo/express/multitool_act(mob/living/user)
if (!(obj_flags & EMAGGED))
to_chat(user, "<span class='notice'>Routing protocols are already set to: \"factory defaults\".</span>")
else
to_chat(user, "<span class='notice'>You reset the routing protocols to: \"factory defaults\".</span>")
obj_flags &= ~EMAGGED
/obj/item/circuitboard/computer/cargo/express/emag_act(mob/living/user)
. = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
if(obj_flags & EMAGGED)
return
to_chat(user, "<span class='notice'>You change the routing protocols, allowing the Drop Pod to land anywhere on the station.</span>")
obj_flags |= EMAGGED
return TRUE
/obj/item/circuitboard/computer/cargo/request
name = "Supply Request Console (Computer Board)"
build_path = /obj/machinery/computer/cargo/request
/obj/item/circuitboard/computer/bounty
name = "Nanotrasen Bounty Console (Computer Board)"
build_path = /obj/machinery/computer/bounty
/obj/item/circuitboard/computer/operating
name = "Operating Computer (Computer Board)"
build_path = /obj/machinery/computer/operating
/obj/item/circuitboard/computer/mining
name = "Outpost Status Display (Computer Board)"
build_path = /obj/machinery/computer/security/mining
/obj/item/circuitboard/computer/research
name = "Research Monitor (Computer Board)"
build_path = /obj/machinery/computer/security/research
// /obj/item/circuitboard/computer/base_construction/centcom
// name = "circuit board (Centcom Base Construction Console)"
// icon_state = "engineering"
// build_path = /obj/machinery/computer/camera_advanced/base_construction/centcom
/obj/item/circuitboard/computer/comm_monitor
name = "Telecommunications Monitor (Computer Board)"
icon_state = "engineering"
build_path = /obj/machinery/computer/telecomms/monitor
/obj/item/circuitboard/computer/comm_server
name = "Telecommunications Server Monitor (Computer Board)"
icon_state = "engineering"
build_path = /obj/machinery/computer/telecomms/server
/obj/item/circuitboard/computer/labor_shuttle
name = "Labor Shuttle (Computer Board)"
build_path = /obj/machinery/computer/shuttle/labor
/obj/item/circuitboard/computer/communications
name = "Communications (Computer Board)"
icon_state = "engineering"
build_path = /obj/machinery/computer/communications
/obj/item/circuitboard/computer/labor_shuttle/one_way
name = "Prisoner Shuttle Console (Computer Board)"
build_path = /obj/machinery/computer/shuttle/labor/one_way
/obj/item/circuitboard/computer/message_monitor
name = "Message Monitor (Computer Board)"
icon_state = "engineering"
build_path = /obj/machinery/computer/message_monitor
/obj/item/circuitboard/computer/ferry
name = "Transport Ferry (Computer Board)"
build_path = /obj/machinery/computer/shuttle/ferry
/obj/item/circuitboard/computer/powermonitor
name = "Power Monitor (Computer Board)" //name fixed 250810
icon_state = "engineering"
build_path = /obj/machinery/computer/monitor
/obj/item/circuitboard/computer/ferry/request
name = "Transport Ferry Console (Computer Board)"
build_path = /obj/machinery/computer/shuttle/ferry/request
/obj/item/circuitboard/computer/powermonitor/secret
name = "Outdated Power Monitor (Computer Board)" //Variant used on ruins to prevent them from showing up on PDA's.
icon_state = "engineering"
build_path = /obj/machinery/computer/monitor/secret
/obj/item/circuitboard/computer/mining_shuttle
name = "Mining Shuttle (Computer Board)"
build_path = /obj/machinery/computer/shuttle/mining
/obj/item/circuitboard/computer/sat_control
name = "Satellite Network Control (Computer Board)"
icon_state = "engineering"
build_path = /obj/machinery/computer/sat_control
/obj/item/circuitboard/computer/mining_shuttle/common
name = "Lavaland Shuttle (Computer Board)"
build_path = /obj/machinery/computer/shuttle/mining/common
/obj/item/circuitboard/computer/solar_control
name = "Solar Control (Computer Board)" //name fixed 250810
icon_state = "engineering"
build_path = /obj/machinery/power/solar_control
/obj/item/circuitboard/computer/snow_taxi
name = "Snow Taxi (Computer Board)"
build_path = /obj/machinery/computer/shuttle/snow_taxi
/obj/item/circuitboard/computer/stationalert
name = "Station Alerts (Computer Board)"
icon_state = "engineering"
build_path = /obj/machinery/computer/station_alert
/obj/item/circuitboard/computer/white_ship
name = "White Ship (Computer Board)"
build_path = /obj/machinery/computer/shuttle/white_ship
/obj/item/circuitboard/computer/turbine_computer
name = "Turbine Computer (Computer Board)"
icon_state = "engineering"
build_path = /obj/machinery/computer/turbine_computer
/obj/item/circuitboard/computer/white_ship/pod
name = "Salvage Pod (Computer Board)"
build_path = /obj/machinery/computer/shuttle/white_ship/pod
/obj/item/circuitboard/computer/turbine_control
name = "Turbine control (Computer Board)"
icon_state = "engineering"
build_path = /obj/machinery/computer/turbine_computer
/obj/item/circuitboard/computer/white_ship/pod/recall
name = "Salvage Pod Recall (Computer Board)"
build_path = /obj/machinery/computer/shuttle/white_ship/pod/recall
//Generic
/obj/item/circuitboard/computer/auxillary_base
name = "Auxillary Base Management Console (Computer Board)"
build_path = /obj/machinery/computer/auxillary_base
/obj/item/circuitboard/computer/arcade/amputation
name = "Mediborg's Amputation Adventure (Computer Board)"
icon_state = "generic"
build_path = /obj/machinery/computer/arcade/amputation
/obj/item/circuitboard/computer/arcade/battle
name = "Arcade Battle (Computer Board)"
icon_state = "generic"
build_path = /obj/machinery/computer/arcade/battle
/obj/item/circuitboard/computer/arcade/orion_trail
name = "Orion Trail (Computer Board)"
build_path = /obj/machinery/computer/arcade/orion_trail
/obj/item/circuitboard/computer/arcade/minesweeper
name = "Minesweeper (Computer Board)"
icon_state = "generic"
build_path = /obj/machinery/computer/arcade/minesweeper
/obj/item/circuitboard/computer/holodeck// Not going to let people get this, but it's just here for future
name = "Holodeck Control (Computer Board)"
icon_state = "generic"
build_path = /obj/machinery/computer/holodeck
/obj/item/circuitboard/computer/aifixer
name = "AI Integrity Restorer (Computer Board)"
build_path = /obj/machinery/computer/aifixer
/obj/item/circuitboard/computer/slot_machine
name = "Slot Machine (Computer Board)"
build_path = /obj/machinery/computer/slot_machine
/obj/item/circuitboard/computer/libraryconsole
name = "Library Visitor Console (Computer Board)"
build_path = /obj/machinery/computer/libraryconsole
@@ -350,16 +286,34 @@
else
return ..()
/obj/item/circuitboard/computer/apc_control
name = "\improper Power Flow Control Console (Computer Board)"
build_path = /obj/machinery/computer/apc_control
/obj/item/circuitboard/computer/monastery_shuttle
name = "Monastery Shuttle (Computer Board)"
icon_state = "generic"
build_path = /obj/machinery/computer/shuttle/monastery_shuttle
/obj/item/circuitboard/computer/olddoor
name = "DoorMex (Computer Board)"
icon_state = "generic"
build_path = /obj/machinery/computer/pod/old
/obj/item/circuitboard/computer/pod
name = "Massdriver control (Computer Board)"
icon_state = "generic"
build_path = /obj/machinery/computer/pod
/obj/item/circuitboard/computer/slot_machine
name = "Slot Machine (Computer Board)"
icon_state = "generic"
build_path = /obj/machinery/computer/slot_machine
/obj/item/circuitboard/computer/swfdoor
name = "Magix (Computer Board)"
icon_state = "generic"
build_path = /obj/machinery/computer/pod/old/swf
/obj/item/circuitboard/computer/syndicate_shuttle
name = "Syndicate Shuttle (Computer Board)"
icon_state = "generic"
build_path = /obj/machinery/computer/shuttle/syndicate
var/challenge = FALSE
var/moved = FALSE
@@ -372,26 +326,296 @@
GLOB.syndicate_shuttle_boards -= src
return ..()
/obj/item/circuitboard/computer/bsa_control
name = "Bluespace Artillery Controls (Computer Board)"
build_path = /obj/machinery/computer/bsa_control
/obj/item/circuitboard/computer/syndicatedoor
name = "ProComp Executive (Computer Board)"
icon_state = "generic"
build_path = /obj/machinery/computer/pod/old/syndicate
/obj/item/circuitboard/computer/sat_control
name = "Satellite Network Control (Computer Board)"
build_path = /obj/machinery/computer/sat_control
/obj/item/circuitboard/computer/white_ship
name = "White Ship (Computer Board)"
icon_state = "generic"
build_path = /obj/machinery/computer/shuttle/white_ship
// /obj/item/circuitboard/computer/white_ship/bridge
// name = "White Ship Bridge (Computer Board)"
// icon_state = "generic"
// build_path = /obj/machinery/computer/shuttle/white_ship/bridge
/obj/item/circuitboard/computer/white_ship/pod
name = "Salvage Pod (Computer Board)"
build_path = /obj/machinery/computer/shuttle/white_ship/pod
/obj/item/circuitboard/computer/white_ship/pod/recall
name = "Salvage Pod Recall (Computer Board)"
build_path = /obj/machinery/computer/shuttle/white_ship/pod/recall
/obj/item/circuitboard/computer/snow_taxi
name = "Snow Taxi (Computer Board)"
build_path = /obj/machinery/computer/shuttle/snow_taxi
// /obj/item/circuitboard/computer/bountypad
// name = "Bounty Pad (Computer Board)"
// build_path = /obj/machinery/computer/piratepad_control/civilian
/obj/item/circuitboard/computer/security/shuttle
name = "Shuttlelinking Security Cameras (Computer Board)"
icon_state = "generic"
build_path = /obj/machinery/computer/security/shuttle
//Medical
/obj/item/circuitboard/computer/crew
name = "Crew Monitoring Console (Computer Board)"
icon_state = "medical"
build_path = /obj/machinery/computer/crew
/obj/item/circuitboard/computer/med_data
name = "Medical Records Console (Computer Board)"
icon_state = "medical"
build_path = /obj/machinery/computer/med_data
/obj/item/circuitboard/computer/operating
name = "Operating Computer (Computer Board)"
icon_state = "medical"
build_path = /obj/machinery/computer/operating
/obj/item/circuitboard/computer/pandemic
name = "PanD.E.M.I.C. 2200 (Computer Board)"
icon_state = "medical"
build_path = /obj/machinery/computer/pandemic
/obj/item/circuitboard/computer/cloning
name = "Cloning (Computer Board)"
icon_state = "medical"
build_path = /obj/machinery/computer/cloning
var/list/records = list()
/obj/item/circuitboard/computer/cloning/prototype
name = "Prototype Cloning (Computer Board)"
build_path = /obj/machinery/computer/cloning/prototype
//Science
/obj/item/circuitboard/computer/aifixer
name = "AI Integrity Restorer (Computer Board)"
icon_state = "science"
build_path = /obj/machinery/computer/aifixer
/obj/item/circuitboard/computer/launchpad_console
name = "Launchpad Control Console (Computer Board)"
icon_state = "science"
build_path = /obj/machinery/computer/launchpad
/obj/item/circuitboard/computer/mech_bay_power_console
name = "Mech Bay Power Control Console (Computer Board)"
icon_state = "science"
build_path = /obj/machinery/computer/mech_bay_power_console
/obj/item/circuitboard/computer/mecha_control
name = "Exosuit Control Console (Computer Board)"
icon_state = "science"
build_path = /obj/machinery/computer/mecha
/obj/item/circuitboard/computer/nanite_chamber_control
name = "Nanite Chamber Control (Computer Board)"
icon_state = "science"
build_path = /obj/machinery/computer/nanite_chamber_control
/obj/item/circuitboard/computer/nanite_cloud_controller
name = "Nanite Cloud Control (Computer Board)"
icon_state = "science"
build_path = /obj/machinery/computer/nanite_cloud_controller
/obj/item/circuitboard/computer/rdconsole/production
name = "R&D Console Production Only (Computer Board)"
icon_state = "science"
build_path = /obj/machinery/computer/rdconsole/production
/obj/item/circuitboard/computer/shuttle/flight_control
name = "Shuttle Flight Control (Computer Board)"
build_path = /obj/machinery/computer/custom_shuttle
/obj/item/circuitboard/computer/rdconsole
name = "R&D Console (Computer Board)"
icon_state = "science"
build_path = /obj/machinery/computer/rdconsole/core
/obj/item/circuitboard/computer/rdconsole/attackby(obj/item/I, mob/user, params)
if(I.tool_behaviour == TOOL_SCREWDRIVER)
if(build_path == /obj/machinery/computer/rdconsole/core)
name = "R&D Console - Robotics (Computer Board)"
build_path = /obj/machinery/computer/rdconsole/robotics
to_chat(user, "<span class='notice'>Access protocols successfully updated.</span>")
else
name = "R&D Console (Computer Board)"
build_path = /obj/machinery/computer/rdconsole/core
to_chat(user, "<span class='notice'>Defaulting access protocols.</span>")
else
return ..()
/obj/item/circuitboard/computer/rdservercontrol
name = "R&D Server Control (Computer Board)"
icon_state = "science"
build_path = /obj/machinery/computer/rdservercontrol
/obj/item/circuitboard/computer/research
name = "Research Monitor (Computer Board)"
icon_state = "science"
build_path = /obj/machinery/computer/security/research
/obj/item/circuitboard/computer/robotics
name = "Robotics Control (Computer Board)"
icon_state = "science"
build_path = /obj/machinery/computer/robotics
/obj/item/circuitboard/computer/teleporter
name = "Teleporter (Computer Board)"
icon_state = "science"
build_path = /obj/machinery/computer/teleporter
/obj/item/circuitboard/computer/xenobiology
name = "Xenobiology Console (Computer Board)"
icon_state = "science"
build_path = /obj/machinery/computer/camera_advanced/xenobio
/obj/item/circuitboard/computer/scan_consolenew
name = "DNA Console (Computer Board)"
icon_state = "science"
build_path = /obj/machinery/computer/scan_consolenew
// /obj/item/circuitboard/computer/mechpad
// name = "Mecha Orbital Pad Console (Computer Board)"
// icon_state = "science"
// build_path = /obj/machinery/computer/mechpad
//Security
/obj/item/circuitboard/computer/labor_shuttle
name = "Labor Shuttle (Computer Board)"
icon_state = "security"
build_path = /obj/machinery/computer/shuttle/labor
/obj/item/circuitboard/computer/labor_shuttle/one_way
name = "Prisoner Shuttle Console (Computer Board)"
icon_state = "security"
build_path = /obj/machinery/computer/shuttle/labor/one_way
/obj/item/circuitboard/computer/gulag_teleporter_console
name = "Labor Camp teleporter console (Computer Board)"
icon_state = "security"
build_path = /obj/machinery/computer/prisoner/gulag_teleporter_computer
/obj/item/circuitboard/computer/prisoner
name = "Prisoner Management Console (Computer Board)"
icon_state = "security"
build_path = /obj/machinery/computer/prisoner/management
/obj/item/circuitboard/computer/secure_data
name = "Security Records Console (Computer Board)"
icon_state = "security"
build_path = /obj/machinery/computer/secure_data
// /obj/item/circuitboard/computer/warrant
// name = "Security Warrant Viewer (Computer Board)"
// icon_state = "security"
// build_path = /obj/machinery/computer/warrant
/obj/item/circuitboard/computer/security
name = "Security Cameras (Computer Board)"
icon_state = "security"
build_path = /obj/machinery/computer/security
/obj/item/circuitboard/computer/advanced_camera
name = "Advanced Camera Console (Computer Board)"
icon_state = "security"
build_path = /obj/machinery/computer/camera_advanced/syndie
//Service
//Supply
/obj/item/circuitboard/computer/cargo
name = "Supply Console (Computer Board)"
icon_state = "supply"
build_path = /obj/machinery/computer/cargo
var/contraband = FALSE
/obj/item/circuitboard/computer/cargo/multitool_act(mob/living/user)
. = ..()
if(!(obj_flags & EMAGGED))
contraband = !contraband
to_chat(user, "<span class='notice'>Receiver spectrum set to [contraband ? "Broad" : "Standard"].</span>")
else
to_chat(user, "<span class='alert'>The spectrum chip is unresponsive.</span>")
/obj/item/circuitboard/computer/cargo/emag_act(mob/living/user)
. = ..()
if(!(obj_flags & EMAGGED))
contraband = TRUE
obj_flags |= EMAGGED
to_chat(user, "<span class='notice'>You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband.</span>")
/obj/item/circuitboard/computer/cargo/configure_machine(obj/machinery/computer/cargo/machine)
if(!istype(machine))
CRASH("Cargo board attempted to configure incorrect machine type: [machine] ([machine?.type])")
machine.contraband = contraband
if (obj_flags & EMAGGED)
machine.obj_flags |= EMAGGED
else
machine.obj_flags &= ~EMAGGED
/obj/item/circuitboard/computer/cargo/express
name = "Express Supply Console (Computer Board)"
build_path = /obj/machinery/computer/cargo/express
/obj/item/circuitboard/computer/cargo/express/emag_act(mob/living/user)
if(!(obj_flags & EMAGGED))
contraband = TRUE
obj_flags |= EMAGGED
to_chat(user, "<span class='notice'>You change the routing protocols, allowing the Drop Pod to land anywhere on the station.</span>")
/obj/item/circuitboard/computer/cargo/express/multitool_act(mob/living/user)
if (!(obj_flags & EMAGGED))
contraband = !contraband
to_chat(user, "<span class='notice'>Receiver spectrum set to [contraband ? "Broad" : "Standard"].</span>")
else
to_chat(user, "<span class='notice'>You reset the destination-routing protocols and receiver spectrum to factory defaults.</span>")
contraband = FALSE
obj_flags &= ~EMAGGED
/obj/item/circuitboard/computer/cargo/request
name = "Supply Request Console (Computer Board)"
build_path = /obj/machinery/computer/cargo/request
/obj/item/circuitboard/computer/bounty
name = "Nanotrasen Bounty Console (Computer Board)"
build_path = /obj/machinery/computer/bounty
/obj/item/circuitboard/computer/ferry
name = "Transport Ferry (Computer Board)"
icon_state = "supply"
build_path = /obj/machinery/computer/shuttle/ferry
/obj/item/circuitboard/computer/ferry/request
name = "Transport Ferry Console (Computer Board)"
icon_state = "supply"
build_path = /obj/machinery/computer/shuttle/ferry/request
/obj/item/circuitboard/computer/mining
name = "Outpost Status Display (Computer Board)"
icon_state = "supply"
build_path = /obj/machinery/computer/security/mining
/obj/item/circuitboard/computer/mining_shuttle
name = "Mining Shuttle (Computer Board)"
icon_state = "supply"
build_path = /obj/machinery/computer/shuttle/mining
/obj/item/circuitboard/computer/mining_shuttle/common
name = "Lavaland Shuttle (Computer Board)"
build_path = /obj/machinery/computer/shuttle/mining/common
/obj/item/circuitboard/computer/shuttle/docker
name = "Shuttle Navigation Computer (Computer Board)"
build_path = /obj/machinery/computer/camera_advanced/shuttle_docker/custom
// DIY shuttle
/obj/item/circuitboard/computer/shuttle/flight_control
name = "Shuttle Flight Control (Computer Board)"
build_path = /obj/machinery/computer/custom_shuttle
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -122,7 +122,10 @@
/obj/item/paicard/proc/setPersonality(mob/living/silicon/pai/personality)
src.pai = personality
src.add_overlay("pai-null")
var/list/policies = CONFIG_GET(keyed_list/policyconfig)
var/policy = policies[POLICYCONFIG_PAI]
if(policy)
to_chat(personality, policy)
playsound(loc, 'sound/effects/pai_boot.ogg', 50, 1, -1)
audible_message("\The [src] plays a cheerful startup noise!")
+5
View File
@@ -180,6 +180,11 @@
//Called from turf.dm turf/dblclick
/obj/item/flamethrower/proc/flame_turf(turflist)
var/mob/living/carbon/human/user = loc
// no fun for pacifists
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='warning'>You don't want to put others in danger!</span>")
return
if(!lit || operating)
return
operating = TRUE
+14 -11
View File
@@ -12,7 +12,7 @@
lefthand_file = 'icons/mob/inhands/equipment/toolbox_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/toolbox_righthand.dmi'
icon = 'icons/obj/items_and_weapons.dmi'
w_class = WEIGHT_CLASS_BULKY
w_class = WEIGHT_CLASS_GIGANTIC
force = 12
total_mass = TOTAL_MASS_NORMAL_ITEM // average toolbox
attack_verb = list("robusted")
@@ -70,19 +70,19 @@
else
. += "<span class='his_grace'>[src] is latched closed.</span>"
/obj/item/his_grace/relaymove(mob/living/user) //Allows changelings, etc. to climb out of Him after they revive, provided He isn't active
/obj/item/his_grace/relaymove(mob/living/user, direction) //Allows changelings, etc. to climb out of Him after they revive, provided He isn't active
if(!awakened)
user.forceMove(get_turf(src))
user.visible_message("<span class='warning'>[user] scrambles out of [src]!</span>", "<span class='notice'>You climb out of [src]!</span>")
/obj/item/his_grace/process()
/obj/item/his_grace/process(delta_time)
if(!bloodthirst)
drowse()
return
if(bloodthirst < HIS_GRACE_CONSUME_OWNER && !ascended)
adjust_bloodthirst(1 + FLOOR(LAZYLEN(contents) * 0.5, 1)) //Maybe adjust this?
adjust_bloodthirst((1 + FLOOR(LAZYLEN(contents) * 0.5, 1)) * delta_time) //Maybe adjust this?
else
adjust_bloodthirst(1) //don't cool off rapidly once we're at the point where His Grace consumes all.
adjust_bloodthirst(1 * delta_time) //don't cool off rapidly once we're at the point where His Grace consumes all.
var/mob/living/master = get_atom_on_turf(src, /mob/living)
if(istype(master) && (src in master.held_items))
switch(bloodthirst)
@@ -94,7 +94,7 @@
REMOVE_TRAIT(src, TRAIT_NODROP, HIS_GRACE_TRAIT)
master.DefaultCombatKnockdown(60)
master.adjustBruteLoss(master.maxHealth)
playsound(master, 'sound/effects/splat.ogg', 100, 0)
playsound(master, 'sound/effects/splat.ogg', 100, FALSE)
else
master.apply_status_effect(STATUS_EFFECT_HISGRACE)
return
@@ -115,8 +115,8 @@
if(!L.stat)
L.visible_message("<span class='warning'>[src] lunges at [L]!</span>", "<span class='his_grace big bold'>[src] lunges at you!</span>")
do_attack_animation(L, null, src)
playsound(L, 'sound/weapons/smash.ogg', 50, 1)
playsound(L, 'sound/misc/desceration-01.ogg', 50, 1)
playsound(L, 'sound/weapons/smash.ogg', 50, TRUE)
playsound(L, 'sound/misc/desceration-01.ogg', 50, TRUE)
L.adjustBruteLoss(force)
adjust_bloodthirst(-5) //Don't stop attacking they're right there!
else
@@ -137,6 +137,8 @@
move_gracefully()
/obj/item/his_grace/proc/move_gracefully()
SIGNAL_HANDLER
if(!awakened)
return
var/static/list/transforms
@@ -161,7 +163,7 @@
return
var/turf/T = get_turf(src)
T.visible_message("<span class='boldwarning'>[src] slowly stops rattling and falls still, His latch snapping shut.</span>")
playsound(loc, 'sound/weapons/batonextend.ogg', 100, 1)
playsound(loc, 'sound/weapons/batonextend.ogg', 100, TRUE)
name = initial(name)
desc = initial(desc)
icon_state = initial(icon_state)
@@ -178,8 +180,8 @@
var/victims = 0
meal.visible_message("<span class='warning'>[src] swings open and devours [meal]!</span>", "<span class='his_grace big bold'>[src] consumes you!</span>")
meal.adjustBruteLoss(200)
playsound(meal, 'sound/misc/desceration-02.ogg', 75, 1)
playsound(src, 'sound/items/eatfood.ogg', 100, 1)
playsound(meal, 'sound/misc/desceration-02.ogg', 75, TRUE)
playsound(src, 'sound/items/eatfood.ogg', 100, TRUE)
meal.forceMove(src)
force_bonus += HIS_GRACE_FORCE_BONUS
prev_bloodthirst = bloodthirst
@@ -253,3 +255,4 @@
if(istype(master))
master.visible_message("<span class='his_grace big bold'>Gods will be watching.</span>")
name = "[master]'s mythical toolbox of three powers"
master.client?.give_award(/datum/award/achievement/misc/ascension, master)
+3
View File
@@ -328,6 +328,9 @@
REMOVE_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
REMOVE_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
name = initial(name)
if(iscarbon(occupant))
to_chat(occupant, "You pop out of the [src], slightly dazed!")
occupant.Stun(5 SECONDS)
/obj/item/pet_carrier/bluespace/return_air()
if(!occupant_gas_supply)
+1 -1
View File
@@ -14,7 +14,7 @@
grind_results = list(/datum/reagent/cellulose = 10)
var/value = 0
/obj/item/stack/spacecash/Initialize()
/obj/item/stack/spacecash/Initialize(mapload, new_amount, merge = TRUE)
. = ..()
update_desc()
@@ -41,6 +41,8 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
material_type = /datum/material/glass
point_value = 1
tableVariant = /obj/structure/table/glass
matter_amount = 4
cost = 500
shard_type = /obj/item/shard
/obj/item/stack/sheet/glass/suicide_act(mob/living/carbon/user)
@@ -69,12 +71,13 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
if (get_amount() < 1 || CC.get_amount() < 5)
to_chat(user, "<span class='warning>You need five lengths of coil and one sheet of glass to make wired glass!</span>")
return
CC.use_tool(src, user, 0, 5, skill_gain_mult = TRIVIAL_USE_TOOL_MULT)
CC.use(5)
use(1)
to_chat(user, "<span class='notice'>You attach wire to the [name].</span>")
var/obj/item/stack/light_w/new_tile = new(user.loc)
new_tile.add_fingerprint(user)
else if(istype(W, /obj/item/stack/rods))
return
if(istype(W, /obj/item/stack/rods))
var/obj/item/stack/rods/V = W
if (V.get_amount() >= 1 && get_amount() >= 1)
var/obj/item/stack/sheet/rglass/RG = new (get_turf(user))
@@ -86,9 +89,8 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
user.put_in_hands(RG)
else
to_chat(user, "<span class='warning'>You need one rod and one sheet of glass to make reinforced glass!</span>")
return
else
return ..()
return
return ..()
@@ -164,6 +166,7 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \
merge_type = /obj/item/stack/sheet/rglass
grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/iron = 10)
point_value = 4
matter_amount = 6
shard_type = /obj/item/shard
/obj/item/stack/sheet/rglass/attackby(obj/item/W, mob/user, params)
@@ -211,6 +214,7 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \
merge_type = /obj/item/stack/sheet/plasmarglass
grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/toxin/plasma = 10, /datum/reagent/iron = 10)
point_value = 23
matter_amount = 8
shard_type = /obj/item/shard/plasma
/obj/item/stack/sheet/plasmarglass/get_main_recipes()
@@ -19,7 +19,7 @@
///What type of wall does this sheet spawn
var/walltype
/obj/item/stack/sheet/Initialize(mapload, new_amount, merge)
/obj/item/stack/sheet/Initialize(mapload, new_amount, merge = TRUE)
. = ..()
pixel_x = rand(-4, 4)
pixel_y = rand(-4, 4)
+283 -234
View File
@@ -8,15 +8,18 @@
/*
* Stacks
*/
/obj/item/stack
icon = 'icons/obj/stack_objects.dmi'
gender = PLURAL
material_modifier = 0.01
// material_modifier = 0.05 //5%, so that a 50 sheet stack has the effect of 5k materials instead of 100k.
max_integrity = 100
var/list/datum/stack_recipe/recipes
var/singular_name
var/amount = 1
var/max_amount = 50 //also see stack recipes initialisation, param "max_res_amount" must be equal to this max_amount
var/is_cyborg = 0 // It's 1 if module is used by a cyborg, and uses its storage
var/is_cyborg = FALSE // It's TRUE if module is used by a cyborg, and uses its storage
var/datum/robot_energy_storage/source
var/cost = 1 // How much energy from storage it costs
var/merge_type = null // This path and its children should merge with this stack, defaults to src.type
@@ -25,7 +28,6 @@
var/list/mats_per_unit //list that tells you how much is in a single unit.
///Datum material type that this stack is made of
var/material_type
max_integrity = 100
//NOTE: When adding grind_results, the amounts should be for an INDIVIDUAL ITEM - these amounts will be multiplied by the stack size in on_grind()
var/obj/structure/table/tableVariant // we tables now (stores table variant to be built from this stack)
@@ -36,16 +38,8 @@
var/absorption_capacity
/// How quickly we lower the blood flow on a cut wound we're bandaging. Expected lifetime of this bandage in ticks is thus absorption_capacity/absorption_rate, or until the cut heals, whichever comes first
var/absorption_rate
/obj/item/stack/on_grind()
for(var/i in 1 to grind_results.len) //This should only call if it's ground, so no need to check if grind_results exists
grind_results[grind_results[i]] *= get_amount() //Gets the key at position i, then the reagent amount of that key, then multiplies it by stack size
/obj/item/stack/grind_requirements()
if(is_cyborg)
to_chat(usr, "<span class='danger'>[src] is electronically synthesized in your chassis and can't be ground up!</span>")
return
return TRUE
/// Amount of matter for RCD
var/matter_amount = 0
/obj/item/stack/Initialize(mapload, new_amount, merge = TRUE)
if(new_amount != null)
@@ -55,16 +49,19 @@
new type(loc, max_amount, FALSE)
if(!merge_type)
merge_type = type
if(custom_materials && custom_materials.len)
mats_per_unit = list()
var/in_process_mat_list = custom_materials.Copy()
if(LAZYLEN(mats_per_unit))
set_mats_per_unit(mats_per_unit, 1)
else if(LAZYLEN(custom_materials))
// DO NOT REMOVE! we have to inflate the values first
for(var/i in custom_materials)
mats_per_unit[SSmaterials.GetMaterialRef(i)] = in_process_mat_list[i]
custom_materials[i] *= amount
set_mats_per_unit(custom_materials, amount ? 1/amount : 1)
. = ..()
if(merge)
for(var/obj/item/stack/S in loc)
if(S.merge_type == merge_type)
if(can_merge(S))
INVOKE_ASYNC(src, .proc/merge, S)
var/list/temp_recipes = get_main_recipes()
recipes = temp_recipes.Copy()
@@ -73,12 +70,48 @@
for(var/i in M.categories)
switch(i)
if(MAT_CATEGORY_BASE_RECIPES)
var/list/temp = SSmaterials.base_stack_recipes.Copy()
recipes += temp
if(MAT_CATEGORY_RIGID)
var/list/temp = SSmaterials.rigid_stack_recipes.Copy()
recipes += temp
update_weight()
update_icon()
/** Sets the amount of materials per unit for this stack.
*
* Arguments:
* - [mats][/list]: The value to set the mats per unit to.
* - multiplier: The amount to multiply the mats per unit by. Defaults to 1.
*/
/obj/item/stack/proc/set_mats_per_unit(list/mats, multiplier=1)
mats_per_unit = SSmaterials.FindOrCreateMaterialCombo(mats, multiplier)
update_custom_materials()
/** Updates the custom materials list of this stack.
*/
/obj/item/stack/proc/update_custom_materials()
set_custom_materials(mats_per_unit, amount, is_update=TRUE)
/**
* Override to make things like metalgen accurately set custom materials
*/
/obj/item/stack/set_custom_materials(list/materials, multiplier=1, is_update=FALSE)
return is_update ? ..() : set_mats_per_unit(materials, multiplier / (amount || 1))
/obj/item/stack/on_grind()
. = ..()
for(var/i in 1 to length(grind_results)) //This should only call if it's ground, so no need to check if grind_results exists
grind_results[grind_results[i]] *= get_amount() //Gets the key at position i, then the reagent amount of that key, then multiplies it by stack size
/obj/item/stack/grind_requirements()
if(is_cyborg)
to_chat(usr, "<span class='warning'>[src] is electronically synthesized in your chassis and can't be ground up!</span>")
return
return TRUE
/obj/item/stack/proc/get_main_recipes()
SHOULD_CALL_PARENT(TRUE)
return list()//empty list
/obj/item/stack/proc/update_weight()
@@ -99,12 +132,6 @@
else
icon_state = "[initial(icon_state)]_3"
/obj/item/stack/Destroy()
if (usr && usr.machine==src)
usr << browse(null, "window=stack")
. = ..()
/obj/item/stack/examine(mob/user)
. = ..()
if (is_cyborg)
@@ -126,196 +153,208 @@
/obj/item/stack/proc/get_amount()
if(is_cyborg)
. = round(source.energy / cost)
. = round(source?.energy / cost)
else
. = (amount)
/obj/item/stack/attack_self(mob/user)
interact(user)
/**
* Builds all recipes in a given recipe list and returns an association list containing them
*
* Arguments:
* * recipe_to_iterate - The list of recipes we are using to build recipes
*/
/obj/item/stack/proc/recursively_build_recipes(list/recipe_to_iterate)
var/list/L = list()
for(var/recipe in recipe_to_iterate)
if(istype(recipe, /datum/stack_recipe_list))
var/datum/stack_recipe_list/R = recipe
L["[R.title]"] = recursively_build_recipes(R.recipes)
if(istype(recipe, /datum/stack_recipe))
var/datum/stack_recipe/R = recipe
L["[R.title]"] = build_recipe(R)
return L
/obj/item/stack/interact(mob/user, sublist)
ui_interact(user, sublist)
/**
* Returns a list of properties of a given recipe
*
* Arguments:
* * R - The stack recipe we are using to get a list of properties
*/
/obj/item/stack/proc/build_recipe(datum/stack_recipe/R)
return list(
"res_amount" = R.res_amount,
"max_res_amount" = R.max_res_amount,
"req_amount" = R.req_amount,
"ref" = "\ref[R]",
)
/obj/item/stack/ui_interact(mob/user, recipes_sublist)
/**
* Checks if the recipe is valid to be used
*
* Arguments:
* * R - The stack recipe we are checking if it is valid
* * recipe_list - The list of recipes we are using to check the given recipe
*/
/obj/item/stack/proc/is_valid_recipe(datum/stack_recipe/R, list/recipe_list)
for(var/S in recipe_list)
if(S == R)
return TRUE
if(istype(S, /datum/stack_recipe_list))
var/datum/stack_recipe_list/L = S
if(is_valid_recipe(R, L.recipes))
return TRUE
return FALSE
/obj/item/stack/ui_state(mob/user)
return GLOB.hands_state
/obj/item/stack/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Stack", name)
ui.open()
/obj/item/stack/ui_data(mob/user)
var/list/data = list()
data["amount"] = get_amount()
return data
/obj/item/stack/ui_static_data(mob/user)
var/list/data = list()
data["recipes"] = recursively_build_recipes(recipes)
return data
/obj/item/stack/ui_act(action, params)
. = ..()
if (!recipes)
if(.)
return
if (!src || get_amount() <= 0)
user << browse(null, "window=stack")
user.set_machine(src) //for correct work of onclose
var/list/recipe_list = recipes
if (recipes_sublist && recipe_list[recipes_sublist] && istype(recipe_list[recipes_sublist], /datum/stack_recipe_list))
var/datum/stack_recipe_list/srl = recipe_list[recipes_sublist]
recipe_list = srl.recipes
var/t1 = "Amount Left: [get_amount()]<br>"
for(var/i in 1 to length(recipe_list))
var/E = recipe_list[i]
if (isnull(E))
t1 += "<hr>"
continue
if (i>1 && !isnull(recipe_list[i-1]))
t1+="<br>"
if (istype(E, /datum/stack_recipe_list))
var/datum/stack_recipe_list/srl = E
t1 += "<a href='?src=[REF(src)];sublist=[i]'>[srl.title]</a>"
if (istype(E, /datum/stack_recipe))
var/datum/stack_recipe/R = E
var/max_multiplier = round(get_amount() / R.req_amount)
var/title
var/can_build = 1
can_build = can_build && (max_multiplier>0)
if (R.res_amount>1)
title+= "[R.res_amount]x [R.title]\s"
else
title+= "[R.title]"
title+= " ([R.req_amount] [singular_name]\s)"
if (can_build)
t1 += text("<A href='?src=[REF(src)];sublist=[recipes_sublist];make=[i];multiplier=1'>[title]</A> ")
else
t1 += text("[]", title)
continue
if (R.max_res_amount>1 && max_multiplier>1)
max_multiplier = min(max_multiplier, round(R.max_res_amount/R.res_amount))
t1 += " |"
var/list/multipliers = list(5,10,25)
for (var/n in multipliers)
if (max_multiplier>=n)
t1 += " <A href='?src=[REF(src)];make=[i];multiplier=[n]'>[n*R.res_amount]x</A>"
if (!(max_multiplier in multipliers))
t1 += " <A href='?src=[REF(src)];make=[i];multiplier=[max_multiplier]'>[max_multiplier*R.res_amount]x</A>"
var/datum/browser/popup = new(user, "stack", name, 400, 400)
popup.set_content(t1)
popup.open(0)
onclose(user, "stack")
/obj/item/stack/Topic(href, href_list)
..()
if (usr.restrained() || usr.stat || usr.get_active_held_item() != src)
return
if (href_list["sublist"] && !href_list["make"])
interact(usr, text2num(href_list["sublist"]))
if (href_list["make"])
if (get_amount() < 1 && !is_cyborg)
qdel(src)
var/list/recipes_list = recipes
if (href_list["sublist"])
var/datum/stack_recipe_list/srl = recipes_list[text2num(href_list["sublist"])]
recipes_list = srl.recipes
var/datum/stack_recipe/R = recipes_list[text2num(href_list["make"])]
var/multiplier = text2num(href_list["multiplier"])
if (!multiplier ||(multiplier <= 0)) //href protection
return
if(!building_checks(R, multiplier))
return
if (R.time)
var/adjusted_time = 0
usr.visible_message("<span class='notice'>[usr] starts building [R.title].</span>", "<span class='notice'>You start building [R.title]...</span>")
if(HAS_TRAIT(usr, R.trait_booster))
adjusted_time = (R.time * R.trait_modifier)
else
adjusted_time = R.time
if (!do_after(usr, adjusted_time, target = usr))
switch(action)
if("make")
if(get_amount() < 1 && !is_cyborg)
qdel(src)
return
var/datum/stack_recipe/R = locate(params["ref"])
if(!is_valid_recipe(R, recipes)) //href exploit protection
return
var/multiplier = text2num(params["multiplier"])
if(!multiplier || (multiplier <= 0)) //href exploit protection
return
if(!building_checks(R, multiplier))
return
if(R.time)
var/adjusted_time = 0
usr.visible_message("<span class='notice'>[usr] starts building \a [R.title].</span>", "<span class='notice'>You start building \a [R.title]...</span>")
if(HAS_TRAIT(usr, R.trait_booster))
adjusted_time = (R.time * R.trait_modifier)
else
adjusted_time = R.time
if(!do_after(usr, adjusted_time, target = usr))
return
if(!building_checks(R, multiplier))
return
var/obj/O
if(R.max_res_amount > 1) //Is it a stack?
O = new R.result_type(usr.drop_location(), R.res_amount * multiplier)
else if(ispath(R.result_type, /turf))
var/turf/T = usr.drop_location()
if(!isturf(T))
return
T.PlaceOnTop(R.result_type, flags = CHANGETURF_INHERIT_AIR)
var/obj/O
if(R.max_res_amount > 1) //Is it a stack?
O = new R.result_type(usr.drop_location(), R.res_amount * multiplier)
else if(ispath(R.result_type, /turf))
var/turf/T = usr.drop_location()
if(!isturf(T))
return
T.PlaceOnTop(R.result_type, flags = CHANGETURF_INHERIT_AIR)
else
O = new R.result_type(usr.drop_location())
if(O)
O.setDir(usr.dir)
use(R.req_amount * multiplier)
if(R.applies_mats && LAZYLEN(mats_per_unit))
if(isstack(O))
var/obj/item/stack/crafted_stack = O
crafted_stack.set_mats_per_unit(mats_per_unit, R.req_amount / R.res_amount)
else
O.set_custom_materials(mats_per_unit, R.req_amount / R.res_amount)
if(istype(O, /obj/structure/windoor_assembly))
var/obj/structure/windoor_assembly/W = O
W.ini_dir = W.dir
else if(istype(O, /obj/structure/window))
var/obj/structure/window/W = O
W.ini_dir = W.dir
if(QDELETED(O))
return //It's a stack and has already been merged
if(isitem(O))
usr.put_in_hands(O)
O.add_fingerprint(usr)
//BubbleWrap - so newly formed boxes are empty
if(istype(O, /obj/item/storage))
for (var/obj/item/I in O)
qdel(I)
//BubbleWrap END
return TRUE
/obj/item/stack/vv_edit_var(vname, vval)
if(vname == NAMEOF(src, amount))
add(clamp(vval, 1-amount, max_amount - amount)) //there must always be one.
return TRUE
else if(vname == NAMEOF(src, max_amount))
max_amount = max(vval, 1)
add((max_amount < amount) ? (max_amount - amount) : 0) //update icon, weight, ect
return TRUE
return ..()
/obj/item/stack/proc/building_checks(datum/stack_recipe/recipe, multiplier)
if (get_amount() < recipe.req_amount*multiplier)
if (recipe.req_amount*multiplier>1)
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [recipe.req_amount*multiplier] [recipe.title]\s!</span>")
else
O = new R.result_type(get_turf(usr))
if(O)
O.setDir(usr.dir)
log_craft("[O] crafted by [usr] at [loc_name(O.loc)]")
use(R.req_amount * multiplier)
if(R.applies_mats && custom_materials && custom_materials.len)
var/list/used_materials = list()
for(var/i in custom_materials)
used_materials[SSmaterials.GetMaterialRef(i)] = R.req_amount / R.res_amount * (MINERAL_MATERIAL_AMOUNT / custom_materials.len)
O.set_custom_materials(used_materials)
//START: oh fuck i'm so sorry
if(istype(O, /obj/structure/windoor_assembly))
var/obj/structure/windoor_assembly/W = O
W.ini_dir = W.dir
else if(istype(O, /obj/structure/window))
var/obj/structure/window/W = O
W.ini_dir = W.dir
//END: oh fuck i'm so sorry
else if(istype(O, /obj/item/restraints/handcuffs/cable))
var/obj/item/cuffs = O
cuffs.color = color
if (QDELETED(O))
return //It's a stack and has already been merged
if (isitem(O))
usr.put_in_hands(O)
O.add_fingerprint(usr)
//BubbleWrap - so newly formed boxes are empty
if ( istype(O, /obj/item/storage) )
for (var/obj/item/I in O)
qdel(I)
//BubbleWrap END
/obj/item/stack/proc/building_checks(datum/stack_recipe/R, multiplier)
if (get_amount() < R.req_amount*multiplier)
if (R.req_amount*multiplier>1)
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [R.req_amount*multiplier] [R.title]\s!</span>")
else
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [R.title]!</span>")
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [recipe.title]!</span>")
return FALSE
var/turf/T = get_turf(usr)
var/turf/dest_turf = get_turf(usr)
var/obj/D = R.result_type
if(R.window_checks && !valid_window_location(T, initial(D.dir) == FULLTILE_WINDOW_DIR ? FULLTILE_WINDOW_DIR : usr.dir))
to_chat(usr, "<span class='warning'>The [R.title] won't fit here!</span>")
return FALSE
if(R.one_per_turf && (locate(R.result_type) in T))
to_chat(usr, "<span class='warning'>There is another [R.title] here!</span>")
return FALSE
if(R.on_floor)
if(!isfloorturf(T))
to_chat(usr, "<span class='warning'>\The [R.title] must be constructed on the floor!</span>")
// If we're making a window, we have some special snowflake window checks to do.
if(ispath(recipe.result_type, /obj/structure/window))
var/obj/structure/window/result_path = recipe.result_type
if(!valid_window_location(dest_turf, usr.dir, is_fulltile = initial(result_path.fulltile)))
to_chat(usr, "<span class='warning'>The [recipe.title] won't fit here!</span>")
return FALSE
for(var/obj/AM in T)
if(istype(AM,/obj/structure/grille))
if(recipe.one_per_turf && (locate(recipe.result_type) in dest_turf))
to_chat(usr, "<span class='warning'>There is another [recipe.title] here!</span>")
return FALSE
if(recipe.on_floor)
if(!isfloorturf(dest_turf))
to_chat(usr, "<span class='warning'>\The [recipe.title] must be constructed on the floor!</span>")
return FALSE
for(var/obj/object in dest_turf)
if(istype(object, /obj/structure/grille))
continue
if(istype(AM,/obj/structure/table))
if(istype(object, /obj/structure/table))
continue
if(istype(AM,/obj/structure/window))
var/obj/structure/window/W = AM
if(!W.fulltile)
if(istype(object, /obj/structure/window))
var/obj/structure/window/window_structure = object
if(!window_structure.fulltile)
continue
if(AM.density)
to_chat(usr, "<span class='warning'>Theres a [AM.name] here. You cant make a [R.title] here!</span>")
if(object.density)
to_chat(usr, "<span class='warning'>There is \a [object.name] here. You cant make \a [recipe.title] here!</span>")
return FALSE
if(R.placement_checks)
switch(R.placement_checks)
if(recipe.placement_checks)
switch(recipe.placement_checks)
if(STACK_CHECK_CARDINALS)
var/turf/step
for(var/direction in GLOB.cardinals)
step = get_step(T, direction)
if(locate(R.result_type) in step)
to_chat(usr, "<span class='warning'>\The [R.title] must not be built directly adjacent to another!</span>")
step = get_step(dest_turf, direction)
if(locate(recipe.result_type) in step)
to_chat(usr, "<span class='warning'>\The [recipe.title] must not be built directly adjacent to another!</span>")
return FALSE
if(STACK_CHECK_ADJACENT)
if(locate(R.result_type) in range(1, T))
to_chat(usr, "<span class='warning'>\The [R.title] must be constructed at least one tile away from others of its type!</span>")
if(locate(recipe.result_type) in range(1, dest_turf))
to_chat(usr, "<span class='warning'>\The [recipe.title] must be constructed at least one tile away from others of its type!</span>")
return FALSE
return TRUE
@@ -330,10 +369,7 @@
if(check && zero_amount())
return TRUE
if(length(mats_per_unit))
var/temp_materials = custom_materials.Copy()
for(var/i in mats_per_unit)
temp_materials[i] = mats_per_unit[i] * src.amount
set_custom_materials(temp_materials)
update_custom_materials()
update_icon()
update_weight()
return TRUE
@@ -357,22 +393,36 @@
return source.energy < cost
if(amount < 1)
qdel(src)
return 1
return 0
return TRUE
return FALSE
/obj/item/stack/proc/add(amount)
/** Adds some number of units to this stack.
*
* Arguments:
* - _amount: The number of units to add to this stack.
*/
/obj/item/stack/proc/add(_amount)
if (is_cyborg)
source.add_charge(amount * cost)
source.add_charge(_amount * cost)
else
src.amount += amount
amount += _amount
if(length(mats_per_unit))
var/temp_materials = custom_materials.Copy()
for(var/i in mats_per_unit)
temp_materials[i] = mats_per_unit[i] * src.amount
set_custom_materials(temp_materials)
update_custom_materials()
update_icon()
update_weight()
/** Checks whether this stack can merge itself into another stack.
*
* Arguments:
* - [check][/obj/item/stack]: The stack to check for mergeability.
*/
/obj/item/stack/proc/can_merge(obj/item/stack/check)
if(!istype(check, merge_type))
return FALSE
if(!check.is_cyborg && (mats_per_unit != check.mats_per_unit)) // Cyborg stacks don't have materials. This lets them recycle sheets and floor tiles.
return FALSE
return TRUE
/obj/item/stack/proc/merge(obj/item/stack/S) //Merge src into S, as much as possible
if(QDELETED(S) || QDELETED(src) || S == src) //amusingly this can cause a stack to consume itself, let's not allow that.
return
@@ -388,50 +438,53 @@
S.add(transfer)
return transfer
/obj/item/stack/Crossed(obj/o)
if(istype(o, merge_type) && !o.throwing)
merge(o)
/obj/item/stack/Crossed(atom/movable/crossing)
if(!crossing.throwing && can_merge(crossing))
merge(crossing)
. = ..()
/obj/item/stack/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
if(istype(AM, merge_type))
merge(AM)
/obj/item/stack/hitby(atom/movable/hitting, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
if(can_merge(hitting))
merge(hitting)
. = ..()
/obj/item/stack/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/stack/on_attack_hand(mob/user)
if(user.get_inactive_held_item() == src)
if(zero_amount())
return
return change_stack(user,1)
return split_stack(user, 1)
else
. = ..()
/obj/item/stack/AltClick(mob/living/user)
. = ..()
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
if(isturf(loc)) // to prevent people that are alt clicking a tile to see its content from getting undesidered pop ups
return
if(is_cyborg)
if(is_cyborg || !user.canUseTopic(src, BE_CLOSE, TRUE, FALSE) || zero_amount()) //, !iscyborg(user)
return
else
if(zero_amount())
return
//get amount from user
var/max = get_amount()
var/stackmaterial = round(input(user,"How many sheets do you wish to take out of this stack? (Maximum [max])") as null|num)
max = get_amount()
stackmaterial = min(max, stackmaterial)
if(stackmaterial == null || stackmaterial <= 0 || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return TRUE
else
change_stack(user, stackmaterial)
to_chat(user, "<span class='notice'>You take [stackmaterial] sheets out of the stack</span>")
return TRUE
//get amount from user
var/max = get_amount()
var/stackmaterial = round(input(user,"How many sheets do you wish to take out of this stack? (Maximum [max])") as null|num)
max = get_amount()
stackmaterial = min(max, stackmaterial)
if(stackmaterial == null || stackmaterial <= 0 || !user.canUseTopic(src, BE_CLOSE, TRUE, FALSE)) //, !iscyborg(user)
return
split_stack(user, stackmaterial)
to_chat(user, "<span class='notice'>You take [stackmaterial] sheets out of the stack.</span>")
/obj/item/stack/proc/change_stack(mob/user, amount)
/** Splits the stack into two stacks.
*
* Arguments:
* - [user][/mob]: The mob splitting the stack.
* - amount: The number of units to split from this stack.
*/
/obj/item/stack/proc/split_stack(mob/user, amount)
if(!use(amount, TRUE, FALSE))
return FALSE
return null
var/obj/item/stack/F = new type(user? user : drop_location(), amount, FALSE)
. = F
F.set_mats_per_unit(mats_per_unit, 1) // Required for greyscale sheets and tiles.
F.copy_evidences(src)
if(user)
if(!user.put_in_hands(F, merge_stacks = FALSE))
@@ -441,7 +494,7 @@
zero_amount()
/obj/item/stack/attackby(obj/item/W, mob/user, params)
if(istype(W, merge_type))
if(can_merge(W))
var/obj/item/stack/S = W
if(merge(S))
to_chat(user, "<span class='notice'>Your [S.name] stack now contains [S.get_amount()] [S.singular_name]\s.</span>")
@@ -455,8 +508,8 @@
fingerprints = from.fingerprints.Copy()
if(from.fingerprintshidden)
fingerprintshidden = from.fingerprintshidden.Copy()
if(from.fingerprintslast)
fingerprintslast = from.fingerprintslast
fingerprintslast = from.fingerprintslast
//TODO bloody overlay
/obj/item/stack/microwave_act(obj/machinery/microwave/M)
if(istype(M) && M.dirty < 100)
@@ -474,15 +527,12 @@
var/time = 0
var/one_per_turf = FALSE
var/on_floor = FALSE
var/window_checks = FALSE
var/placement_checks = FALSE
var/applies_mats = FALSE
var/trait_booster = null
var/trait_modifier = 1
/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1,time = 0, one_per_turf = FALSE, on_floor = FALSE, window_checks = FALSE, placement_checks = FALSE, applies_mats = FALSE, trait_booster = null, trait_modifier = 1)
src.title = title
src.result_type = result_type
src.req_amount = req_amount
@@ -491,7 +541,6 @@
src.time = time
src.one_per_turf = one_per_turf
src.on_floor = on_floor
src.window_checks = window_checks
src.placement_checks = placement_checks
src.applies_mats = applies_mats
src.trait_booster = trait_booster
+2 -2
View File
@@ -1143,9 +1143,9 @@
desc = "A box containing a gift for worthy golems."
/obj/item/storage/box/rndboards/PopulateContents()
new /obj/item/circuitboard/machine/protolathe/offstation(src)
new /obj/item/circuitboard/machine/protolathe(src)
new /obj/item/circuitboard/machine/destructive_analyzer(src)
new /obj/item/circuitboard/machine/circuit_imprinter/offstation(src)
new /obj/item/circuitboard/machine/circuit_imprinter(src)
new /obj/item/circuitboard/computer/rdconsole(src)
/obj/item/storage/box/silver_sulf
@@ -164,11 +164,15 @@
/obj/item/storage/secure/briefcase/hos/mws_pack_hos/PopulateContents()
new /obj/item/gun/ballistic/revolver/mws(src)
new /obj/item/ammo_box/magazine/mws_mag(src)
new /obj/item/ammo_box/magazine/mws_mag(src)
new /obj/item/ammo_casing/mws_batt/lethal(src)
new /obj/item/ammo_casing/mws_batt/lethal(src)
new /obj/item/ammo_casing/mws_batt/lethal(src)
new /obj/item/ammo_casing/mws_batt/stun(src)
new /obj/item/ammo_casing/mws_batt/stun(src)
new /obj/item/ammo_casing/mws_batt/stun(src)
new /obj/item/ammo_casing/mws_batt/ion(src)
new /obj/item/ammo_casing/mws_batt/taser(src)
/obj/item/storage/secure/briefcase/hos/multiphase_box
name = "\improper X-01 Multiphase energy gun box"
+42 -30
View File
@@ -1,10 +1,12 @@
/obj/item/tank
name = "tank"
icon = 'icons/obj/tank.dmi'
icon_state = "generic"
lefthand_file = 'icons/mob/inhands/equipment/tanks_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tanks_righthand.dmi'
flags_1 = CONDUCT_1
slot_flags = ITEM_SLOT_BACK
// worn_icon = 'icons/mob/clothing/back.dmi' //since these can also get thrown into suit storage slots. if something goes on the belt, set this to null.
hitsound = 'sound/weapons/smash.ogg'
pressure_resistance = ONE_ATMOSPHERE * 5
force = 5
@@ -18,6 +20,8 @@
var/distribute_pressure = ONE_ATMOSPHERE
var/integrity = 3
var/volume = 70
/// Icon state when in a tank holder. Null makes it incompatible with tank holder.
var/tank_holder_icon_state = "holder_generic"
/obj/item/tank/ui_action_click(mob/user)
toggle_internals(user)
@@ -84,18 +88,23 @@
/obj/item/tank/Destroy()
if(air_contents)
qdel(air_contents)
QDEL_NULL(air_contents)
STOP_PROCESSING(SSobj, src)
. = ..()
// /obj/item/tank/ComponentInitialize()
// . = ..()
// if(tank_holder_icon_state)
// AddComponent(/datum/component/container_item/tank_holder, tank_holder_icon_state)
/obj/item/tank/examine(mob/user)
var/obj/icon = src
. = ..()
if(istype(src.loc, /obj/item/assembly))
icon = src.loc
if(!in_range(src, user) && !isobserver(user))
if (icon == src)
if(icon == src)
. += "<span class='notice'>If you want any more information you'll need to get closer.</span>"
return
@@ -140,14 +149,14 @@
if(T)
T.assume_air(air_contents)
air_update_turf()
playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3)
playsound(src.loc, 'sound/effects/spray.ogg', 10, TRUE, -3)
qdel(src)
/obj/item/tank/suicide_act(mob/user)
var/mob/living/carbon/human/H = user
user.visible_message("<span class='suicide'>[user] is putting [src]'s valve to [user.p_their()] lips! It looks like [user.p_theyre()] trying to commit suicide!</span>")
playsound(loc, 'sound/effects/spray.ogg', 10, 1, -3)
if (!QDELETED(H) && air_contents && air_contents.return_pressure() >= 1000)
playsound(loc, 'sound/effects/spray.ogg', 10, TRUE, -3)
if(!QDELETED(H) && air_contents && air_contents.return_pressure() >= 1000)
for(var/obj/item/W in H)
H.dropItemToGround(W)
if(prob(50))
@@ -159,12 +168,10 @@
H.spawn_gibs()
H.spill_organs()
H.spread_bodyparts()
return (BRUTELOSS)
/obj/item/tank/attack_ghost(mob/dead/observer/O)
. = ..()
atmosanalyzer_scan(air_contents, O, src, FALSE)
return MANUAL_SUICIDE
else
to_chat(user, "<span class='warning'>There isn't enough pressure in [src] to commit suicide with...</span>")
return SHAME
/obj/item/tank/attackby(obj/item/W, mob/user, params)
add_fingerprint(user)
@@ -182,27 +189,30 @@
ui = new(user, src, "Tank", name)
ui.open()
/obj/item/tank/ui_static_data(mob/user)
. = list (
"defaultReleasePressure" = round(TANK_DEFAULT_RELEASE_PRESSURE),
"minReleasePressure" = round(TANK_MIN_RELEASE_PRESSURE),
"maxReleasePressure" = round(TANK_MAX_RELEASE_PRESSURE),
"leakPressure" = round(TANK_LEAK_PRESSURE),
"fragmentPressure" = round(TANK_FRAGMENT_PRESSURE)
)
/obj/item/tank/ui_data(mob/user)
var/list/data = list()
data["tankPressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
data["releasePressure"] = round(distribute_pressure ? distribute_pressure : 0)
data["defaultReleasePressure"] = round(TANK_DEFAULT_RELEASE_PRESSURE)
data["minReleasePressure"] = round(TANK_MIN_RELEASE_PRESSURE)
data["maxReleasePressure"] = round(TANK_MAX_RELEASE_PRESSURE)
. = list(
"tankPressure" = round(air_contents.return_pressure()),
"releasePressure" = round(distribute_pressure)
)
var/mob/living/carbon/C = user
if(!istype(C))
C = loc.loc
if(!istype(C))
return data
if(C.internal == src)
data["connected"] = TRUE
return data
if(istype(C) && C.internal == src)
.["connected"] = TRUE
/obj/item/tank/ui_act(action, params)
if(..())
. = ..()
if(.)
return
switch(action)
if("pressure")
@@ -228,6 +238,9 @@
/obj/item/tank/return_air()
return air_contents
// /obj/item/tank/return_analyzable_air()
// return air_contents
/obj/item/tank/assume_air(datum/gas_mixture/giver)
air_contents.merge(giver)
@@ -239,10 +252,9 @@
return null
var/tank_pressure = air_contents.return_pressure()
if(tank_pressure < distribute_pressure)
distribute_pressure = tank_pressure
var/actual_distribute_pressure = clamp(tank_pressure, 0, distribute_pressure)
var/moles_needed = distribute_pressure*volume_to_return/(R_IDEAL_GAS_EQUATION*air_contents.return_temperature())
var/moles_needed = actual_distribute_pressure*volume_to_return/(R_IDEAL_GAS_EQUATION*air_contents.return_temperature())
return remove_air(moles_needed)
@@ -267,7 +279,7 @@
//Give the gas a chance to build up more pressure through reacting
air_contents.react(src)
air_contents.react(src)
//Citadel Edit: removing extra react for "balance"
pressure = air_contents.return_pressure()
var/range = (pressure-TANK_FRAGMENT_PRESSURE)/TANK_FRAGMENT_SCALE
var/turf/epicenter = get_turf(loc)
@@ -285,7 +297,7 @@
if(!T)
return
T.assume_air(air_contents)
playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3)
playsound(src.loc, 'sound/effects/spray.ogg', 10, TRUE, -3)
qdel(src)
else
integrity--
+123 -72
View File
@@ -24,9 +24,9 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
*/
/obj/item/banhammer/attack(mob/M, mob/user)
if(user.zone_selected == BODY_ZONE_HEAD)
M.visible_message("<span class='danger'>[user] are stroking the head of [M] with a bangammer</span>", "<span class='userdanger'>[user] are stroking the head with a bangammer</span>", "you hear a bangammer stroking a head");
M.visible_message("<span class='danger'>[user] are stroking the head of [M] with a bangammer.</span>", "<span class='userdanger'>[user] are stroking your head with a bangammer.</span>", "<span class='hear'>You hear a bangammer stroking a head.</span>") // see above comment
else
M.visible_message("<span class='danger'>[M] has been banned FOR NO REISIN by [user]</span>", "<span class='userdanger'>You have been banned FOR NO REISIN by [user]</span>", "you hear a banhammer banning someone")
M.visible_message("<span class='danger'>[M] has been banned FOR NO REISIN by [user]!</span>", "<span class='userdanger'>You have been banned FOR NO REISIN by [user]!</span>", "<span class='hear'>You hear a banhammer banning someone.</span>")
playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much
if(user.a_intent != INTENT_HELP)
return ..(M, user)
@@ -89,7 +89,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS
desc = "<b><i>THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!</i></b>\nActivate it in your hand to point to the nearest victim."
flags_1 = CONDUCT_1
item_flags = DROPDEL
item_flags = DROPDEL //WOW BRO YOU LOST AN ARM, GUESS WHAT YOU DONT GET YOUR SWORD ANYMORE //I CANT BELIEVE SPOOKYDONUT WOULD BREAK THE REQUIREMENTS
slot_flags = null
block_chance = 0 //RNG WON'T HELP YOU NOW, PANSY
light_range = 3
@@ -130,8 +130,6 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/claymore/highlander/dropped(mob/living/user)
. = ..()
user.unignore_slowdown(HIGHLANDER)
if(!QDELETED(src))
qdel(src) //If this ever happens, it's because you lost an arm
/obj/item/claymore/highlander/examine(mob/user)
. = ..()
@@ -141,8 +139,8 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/claymore/highlander/attack(mob/living/target, mob/living/user)
. = ..()
if(!QDELETED(target) && iscarbon(target) && target.stat == DEAD && target.mind && target.mind.special_role == "highlander")
user.fully_heal() //STEAL THE LIFE OF OUR FALLEN FOES
if(!QDELETED(target) && target.stat == DEAD && target.mind && target.mind.special_role == "highlander")
user.fully_heal(admin_revive = FALSE) //STEAL THE LIFE OF OUR FALLEN FOES
add_notch(user)
target.visible_message("<span class='warning'>[target] crumbles to dust beneath [user]'s blows!</span>", "<span class='userdanger'>As you fall, your body crumbles to dust!</span>")
target.dust()
@@ -150,9 +148,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/claymore/highlander/attack_self(mob/living/user)
var/closest_victim
var/closest_distance = 255
for(var/mob/living/carbon/human/H in GLOB.player_list - user)
if(H.client && H.mind.special_role == "highlander" && (!closest_victim || get_dist(user, closest_victim) < closest_distance))
closest_victim = H
for(var/mob/living/carbon/human/scot in GLOB.player_list - user)
if(scot.mind.special_role == "highlander" && (!closest_victim || get_dist(user, closest_victim) < closest_distance))
closest_victim = scot
for(var/mob/living/silicon/robot/siliscot in GLOB.player_list - user)
if(siliscot.mind.special_role == "highlander" && (!closest_victim || get_dist(user, closest_victim) < closest_distance))
closest_victim = siliscot
if(!closest_victim)
to_chat(user, "<span class='warning'>[src] thrums for a moment and falls dark. Perhaps there's nobody nearby.</span>")
return
@@ -161,7 +163,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/claymore/highlander/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object))
return BLOCK_SUCCESS | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED
return ..()
return ..() //YOU THINK YOUR PUNY LASERS CAN STOP ME?
/obj/item/claymore/highlander/proc/add_notch(mob/living/user) //DYNAMIC CLAYMORE PROGRESSION SYSTEM - THIS IS THE FUTURE
notches++
@@ -214,7 +216,22 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
remove_atom_colour(ADMIN_COLOUR_PRIORITY)
name = new_name
playsound(user, 'sound/items/screwdriver2.ogg', 50, 1)
playsound(user, 'sound/items/screwdriver2.ogg', 50, TRUE)
/obj/item/claymore/highlander/robot //BLOODTHIRSTY BORGS NOW COME IN PLAID
icon = 'icons/obj/items_cyborg.dmi'
icon_state = "claymore_cyborg"
var/mob/living/silicon/robot/robot
/obj/item/claymore/highlander/robot/Initialize()
var/obj/item/robot_module/kiltkit = loc
robot = kiltkit.loc
if(!istype(robot))
qdel(src)
return ..()
/obj/item/claymore/highlander/robot/process()
loc.layer = LARGE_MOB_LAYER
/obj/item/katana
name = "katana"
@@ -227,7 +244,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
force = 40
throwforce = 10
w_class = WEIGHT_CLASS_BULKY
w_class = WEIGHT_CLASS_HUGE
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
block_chance = 50
@@ -417,7 +434,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
desc = "A misnomer of sorts, this is effectively a blunt katana made from steelwood, a dense organic wood derived from steelcaps. Why steelwood? Druids can use it. Duh."
icon_state = "bokken_steel"
item_state = "bokken_steel"
force = 12
force = 12
stamina_damage_increment = 3
/obj/item/melee/bokken/waki
@@ -427,7 +444,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
item_state = "wakibokken"
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_NORMAL
force = 6
force = 6
stamina_damage_increment = 4
block_parry_data = /datum/block_parry_data/bokken/waki
default_parry_data = /datum/block_parry_data/bokken/waki
@@ -442,7 +459,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
parry_time_perfect_leeway = 1
parry_imperfect_falloff_percent = 7.5
parry_efficiency_to_counterattack = 120
parry_efficiency_considered_successful = 65
parry_efficiency_considered_successful = 65
parry_efficiency_perfect = 120
parry_efficiency_perfect_override = list(
TEXT_ATTACK_TYPE_PROJECTILE = 30,
@@ -455,10 +472,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/datum/block_parry_data/bokken/waki/quick_parry //For the parry spammer in you
parry_stamina_cost = 2 // Slam that parry button
parry_time_active = 2.5
parry_time_perfect = 1
parry_time_perfect = 1
parry_time_perfect_leeway = 1
parry_failed_stagger_duration = 1 SECONDS
parry_failed_clickcd_duration = 1 SECONDS
parry_failed_clickcd_duration = 1 SECONDS
/datum/block_parry_data/bokken/waki/quick_parry/proj
parry_efficiency_perfect_override = list()
@@ -468,7 +485,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
desc = "A misnomer of sorts, this is effectively a blunt wakizashi made from steelwood, a dense organic wood derived from steelcaps. Why steelwood? Druids can use it. Duh."
icon_state = "wakibokken_steel"
item_state = "wakibokken_steel"
force = 8
force = 8
stamina_damage_increment = 2
/obj/item/melee/bokken/debug
@@ -575,7 +592,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
user.put_in_hands(S)
to_chat(user, "<span class='notice'>You fasten the glass shard to the top of the rod with the cable.</span>")
else if(istype(I, /obj/item/assembly/igniter) && !HAS_TRAIT(I, TRAIT_NODROP))
else if(istype(I, /obj/item/assembly/igniter) && !(HAS_TRAIT(I, TRAIT_NODROP)))
var/obj/item/melee/baton/cattleprod/P = new /obj/item/melee/baton/cattleprod
remove_item_from_storage(user)
@@ -598,13 +615,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
force = 2
throwforce = 10 //This is never used on mobs since this has a 100% embed chance.
throwforce = 10 //10 + 2 (WEIGHT_CLASS_SMALL) * 4 (EMBEDDED_IMPACT_PAIN_MULTIPLIER) = 18 damage on hit due to guaranteed embedding
throw_speed = 4
embedding = list("pain_mult" = 4, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15)
armour_penetration = 40
w_class = WEIGHT_CLASS_SMALL
sharpness = SHARP_EDGED
sharpness = SHARP_POINTY
custom_materials = list(/datum/material/iron=500, /datum/material/glass=500)
resistance_flags = FIRE_PROOF
@@ -639,27 +656,23 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
attack_verb = list("stubbed", "poked")
resistance_flags = FIRE_PROOF
var/extended = 0
var/extended_force = 20
var/extended_throwforce = 23
var/extended_icon_state = "switchblade_ext"
var/retracted_icon_state = "switchblade"
/obj/item/switchblade/attack_self(mob/user)
extended = !extended
playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1)
playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, TRUE)
if(extended)
force = extended_force
force = 20
w_class = WEIGHT_CLASS_NORMAL
throwforce = extended_throwforce
icon_state = extended_icon_state
throwforce = 23
icon_state = "switchblade_ext"
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = SHARP_EDGED
else
force = initial(force)
force = 3
w_class = WEIGHT_CLASS_SMALL
throwforce = initial(throwforce)
icon_state = retracted_icon_state
throwforce = 5
icon_state = "switchblade"
attack_verb = list("stubbed", "poked")
hitsound = 'sound/weapons/genhit.ogg'
sharpness = SHARP_NONE
@@ -750,6 +763,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
user.visible_message("<span class='suicide'>[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane!</span>")
return (OXYLOSS)
// /obj/item/ectoplasm/angelic
// icon = 'icons/obj/wizard.dmi'
// icon_state = "angelplasm"
/obj/item/mounted_chainsaw
name = "mounted chainsaw"
desc = "A chainsaw that has replaced your arm."
@@ -758,7 +775,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
lefthand_file = 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi'
item_flags = ABSTRACT | DROPDEL
w_class = WEIGHT_CLASS_BULKY
w_class = WEIGHT_CLASS_HUGE
force = 24
throwforce = 0
throw_range = 0
@@ -801,7 +818,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/statuebust/Initialize()
. = ..()
AddElement(/datum/element/art, impressiveness)
addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, 1000)), 0)
// AddComponent(/datum/component/beauty, 1000)
// /obj/item/statuebust/hippocratic
// name = "hippocrates bust"
// desc = "A bust of the famous Greek physician Hippocrates of Kos, often referred to as the father of western medicine."
// icon_state = "hippocratic"
// impressiveness = 50
/obj/item/tailclub
name = "tail club"
@@ -825,8 +848,8 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
icon_state = "catwhip"
/obj/item/melee/skateboard
name = "improvised skateboard"
desc = "A skateboard. It can be placed on its wheels and ridden, or used as a strong weapon."
name = "skateboard"
desc = "A skateboard. It can be placed on its wheels and ridden, or used as a radical weapon."
icon_state = "skateboard"
item_state = "skateboard"
force = 12
@@ -839,17 +862,22 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/melee/skateboard/attack_self(mob/user)
if(!user.canUseTopic(src, TRUE, FALSE, TRUE))
return
var/obj/vehicle/ridden/scooter/skateboard/S = new board_item_type(get_turf(user))
var/obj/vehicle/ridden/scooter/skateboard/S = new board_item_type(get_turf(user))//this probably has fucky interactions with telekinesis but for the record it wasn't my fault
S.buckle_mob(user)
qdel(src)
/obj/item/melee/skateboard/improvised
name = "improvised skateboard"
desc = "A jury-rigged skateboard. It can be placed on its wheels and ridden, or used as a radical weapon."
// board_item_type = /obj/vehicle/ridden/scooter/skateboard/improvised
/obj/item/melee/skateboard/pro
name = "skateboard"
desc = "A RaDSTORMz brand professional skateboard. It looks sturdy and well made."
desc = "An EightO brand professional skateboard. It looks sturdy and well made."
icon_state = "skateboard2"
item_state = "skateboard2"
board_item_type = /obj/vehicle/ridden/scooter/skateboard/pro
custom_premium_price = 500
custom_premium_price = PAYCHECK_HARD * 5
/obj/item/melee/skateboard/hoverboard
name = "hoverboard"
@@ -857,10 +885,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
icon_state = "hoverboard_red"
item_state = "hoverboard_red"
board_item_type = /obj/vehicle/ridden/scooter/skateboard/hoverboard
custom_premium_price = 2015
custom_premium_price = PAYCHECK_COMMAND * 5.4 //If I can't make it a meme I'll make it RAD
/obj/item/melee/skateboard/hoverboard/admin
name = "\improper Board Of Directors"
name = "Board Of Directors"
desc = "The engineering complexity of a spaceship concentrated inside of a board. Just as expensive, too."
icon_state = "hoverboard_nt"
item_state = "hoverboard_nt"
@@ -879,11 +907,19 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
throwforce = 12
attack_verb = list("beat", "smacked")
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 3.5)
w_class = WEIGHT_CLASS_BULKY
w_class = WEIGHT_CLASS_HUGE
var/homerun_ready = 0
var/homerun_able = 0
total_mass = 2.7 //a regular wooden major league baseball bat weighs somewhere between 2 to 3.4 pounds, according to google
/obj/item/melee/baseball_bat/Initialize()
. = ..()
if(prob(1))
name = "cricket bat"
desc = "You've got red on you."
icon_state = "baseball_bat_brit"
item_state = "baseball_bat_brit"
/obj/item/melee/baseball_bat/chaplain
name = "blessed baseball bat"
desc = "There ain't a cult in the league that can withstand a swatter."
@@ -908,11 +944,11 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
..()
return
if(homerun_ready)
to_chat(user, "<span class='notice'>You're already ready to do a home run!</span>")
to_chat(user, "<span class='warning'>You're already ready to do a home run!</span>")
..()
return
to_chat(user, "<span class='warning'>You begin gathering strength...</span>")
playsound(get_turf(src), 'sound/magic/lightning_chargeup.ogg', 65, 1)
playsound(get_turf(src), 'sound/magic/lightning_chargeup.ogg', 65, TRUE)
if(do_after(user, 90, target = src))
to_chat(user, "<span class='userdanger'>You gather power! Time for a home run!</span>")
homerun_ready = 1
@@ -920,12 +956,14 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/melee/baseball_bat/attack(mob/living/target, mob/living/user)
. = ..()
if(HAS_TRAIT(user, TRAIT_PACIFISM))
return
var/atom/throw_target = get_edge_target_turf(target, user.dir)
if(homerun_ready)
user.visible_message("<span class='userdanger'>It's a home run!</span>")
target.throw_at(throw_target, rand(8,10), 14, user)
target.ex_act(EXPLODE_HEAVY)
playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, 1)
playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, TRUE)
homerun_ready = 0
return
else if(!target.anchored)
@@ -956,7 +994,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/melee/flyswatter
name = "flyswatter"
desc = "Useful for killing insects of all sizes."
desc = "Useful for killing pests of all sizes."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "flyswatter"
item_state = "flyswatter"
@@ -969,7 +1007,6 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
w_class = WEIGHT_CLASS_SMALL
//Things in this list will be instantly splatted. Flyman weakness is handled in the flyman species weakness proc.
var/list/strong_against
var/list/spider_panic
/obj/item/melee/flyswatter/Initialize()
. = ..()
@@ -977,13 +1014,11 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/mob/living/simple_animal/hostile/poison/bees/,
/mob/living/simple_animal/butterfly,
/mob/living/simple_animal/cockroach,
/obj/item/queen_bee
))
spider_panic = typecacheof(list(
/mob/living/simple_animal/banana_spider,
/mob/living/simple_animal/hostile/poison/giant_spider,
/obj/item/queen_bee,
/obj/structure/spider/spiderling
))
/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, proximity_flag)
. = ..()
if(proximity_flag)
@@ -993,11 +1028,6 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
if(istype(target, /mob/living/))
var/mob/living/bug = target
bug.death(1)
if(is_type_in_typecache(target, spider_panic))
to_chat(user, "<span class='warning'>You easily land a critical blow on the [target].</span>")
if(istype(target, /mob/living/))
var/mob/living/bug = target
bug.adjustBruteLoss(35) //What kinda mad man would go into melee with a spider?!
else
qdel(target)
@@ -1007,7 +1037,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
icon_state = "madeyoulook"
force = 0
throwforce = 0
item_flags = DROPDEL | ABSTRACT
item_flags = DROPDEL | ABSTRACT // | HAND_ITEM
attack_verb = list("bopped")
/obj/item/circlegame/Initialize()
@@ -1030,6 +1060,8 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/// Stage 1: The mistake is made
/obj/item/circlegame/proc/ownerExamined(mob/living/owner, mob/living/sucker)
SIGNAL_HANDLER
if(!istype(sucker) || !in_range(owner, sucker))
return
addtimer(CALLBACK(src, .proc/waitASecond, owner, sucker), 4)
@@ -1076,6 +1108,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
to_chat(owner, "<span class='warning'>[sucker] looks down at your [src.name] before trying to avert [sucker.p_their()] eyes, but it's too late!</span>")
to_chat(sucker, "<span class='danger'><b>[owner] sees the fear in your eyes as you try to look away from [owner.p_their()] [src.name]!</b></span>")
owner.face_atom(sucker)
if(owner.client)
owner.client.give_award(/datum/award/achievement/misc/gottem, owner) // then everybody clapped
playsound(get_turf(owner), 'sound/effects/hit_punch.ogg', 50, TRUE, -1)
owner.do_attack_animation(sucker)
@@ -1103,7 +1139,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
item_state = "nothing"
force = 0
throwforce = 0
item_flags = DROPDEL | ABSTRACT
item_flags = DROPDEL | ABSTRACT // | HAND_ITEM
attack_verb = list("slapped")
hitsound = 'sound/effects/snap.ogg'
@@ -1112,16 +1148,12 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
var/mob/living/carbon/human/L = M
if(L && L.dna && L.dna.species)
L.dna.species.stop_wagging_tail(M)
if(user.a_intent != INTENT_HARM && ((user.zone_selected == BODY_ZONE_PRECISE_MOUTH) || (user.zone_selected == BODY_ZONE_PRECISE_EYES) || (user.zone_selected == BODY_ZONE_HEAD)))
user.do_attack_animation(M)
playsound(M, 'sound/weapons/slap.ogg', 50, 1, -1)
user.visible_message("<span class='danger'>[user] slaps [M]!</span>",
"<span class='notice'>You slap [M]!</span>",\
"You hear a slap.")
return
else
..()
user.do_attack_animation(M)
playsound(M, 'sound/weapons/slap.ogg', 50, TRUE, -1)
user.visible_message("<span class='danger'>[user] slaps [M]!</span>",
"<span class='notice'>You slap [M]!</span>",\
"<span class='hear'>You hear a slap.</span>")
return
/obj/item/proc/can_trigger_gun(mob/living/user)
if(!user.can_use_guns(src))
return FALSE
@@ -1138,6 +1170,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
force = 0
throwforce = 5
reach = 2
var/min_reach = 2
/obj/item/extendohand/acme
name = "\improper ACME Extendo-Hand"
@@ -1145,13 +1178,26 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/extendohand/attack(atom/M, mob/living/carbon/human/user)
var/dist = get_dist(M, user)
if(dist < reach)
if(dist < min_reach)
to_chat(user, "<span class='warning'>[M] is too close to use [src] on.</span>")
return
M.attack_hand(user)
//HF blade
// /obj/item/gohei
// name = "gohei"
// desc = "A wooden stick with white streamers at the end. Originally used by shrine maidens to purify things. Now used by the station's valued weeaboos."
// force = 5
// throwforce = 5
// hitsound = "swing_hit"
// attack_verb_continuous = list("whacks", "thwacks", "wallops", "socks")
// attack_verb_simple = list("whack", "thwack", "wallop", "sock")
// icon = 'icons/obj/items_and_weapons.dmi'
// icon_state = "gohei"
// inhand_icon_state = "gohei"
// lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
// righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
//HF blade
/obj/item/vibro_weapon
icon_state = "hfrequency0"
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
@@ -1160,6 +1206,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
desc = "A potent weapon capable of cutting through nearly anything. Wielding it in two hands will allow you to deflect gunfire."
armour_penetration = 100
block_chance = 40
force = 20
throwforce = 20
throw_speed = 4
sharpness = SHARP_EDGED
@@ -1182,10 +1229,14 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/// triggered on wield of two handed item
/obj/item/vibro_weapon/proc/on_wield(obj/item/source, mob/user)
SIGNAL_HANDLER
wielded = TRUE
/// triggered on unwield of two handed item
/obj/item/vibro_weapon/proc/on_unwield(obj/item/source, mob/user)
SIGNAL_HANDLER
wielded = FALSE
/obj/item/vibro_weapon/update_icon_state()
-5
View File
@@ -344,11 +344,6 @@
if(resistance_flags & ON_FIRE)
. += GLOB.fire_overlay
//Called when the object is constructed by an autolathe
//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes
/obj/proc/autolathe_crafted(obj/machinery/autolathe/A)
return
/obj/proc/rnd_crafted(obj/machinery/rnd/production/P)
return
+4 -5
View File
@@ -345,7 +345,7 @@
name = initial(I.name)
icon = initial(I.icon)
icon_state = initial(I.icon_state)
/* Selling people in jars is currently disabled.
/obj/structure/displaycase/forsale
name = "vend-a-tray"
icon = 'icons/obj/stationobjs.dmi'
@@ -354,9 +354,9 @@
density = FALSE
max_integrity = 100
req_access = null
showpiece_type = /obj/item/reagent_containers/food
start_showpiece_type = /obj/item/reagent_containers/food
alert = FALSE //No, we're not calling the fire department because someone stole your cookie.
glass_fix = FALSE //Fixable with tools instead.
// glass_fix = FALSE //Fixable with tools instead.
///The price of the item being sold. Altered by grab intent ID use.
var/sale_price = 20
///The Account which will receive payment for purchases. Set by the first ID to swipe the tray.
@@ -437,7 +437,7 @@
payments_acc.adjust_money(sale_price)
usr.put_in_hands(showpiece)
to_chat(usr, "<span class='notice'>You purchase [showpiece] for [sale_price] credits.</span>")
playsound(src, 'sound/effects/cashregister.ogg', 40, TRUE)
// playsound(src, 'sound/effects/cashregister.ogg', 40, TRUE)
icon = 'icons/obj/stationobjs.dmi'
flick("laserbox_vend", src)
showpiece = null
@@ -553,4 +553,3 @@
/obj/structure/displaycase/forsale/kitchen
desc = "A display case with an ID-card swiper. Use your ID to purchase the contents. Meant for the bartender and chef."
req_one_access = list(ACCESS_KITCHEN, ACCESS_BAR)
*/
@@ -73,9 +73,14 @@
icon_state = "breaker_drop"
/obj/structure/femur_breaker/proc/damage_leg(mob/living/carbon/human/H)
H.emote("scream")
H.apply_damage(150, BRUTE, pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
H.adjustBruteLoss(rand(5,20) + (max(0, H.health))) //Make absolutely sure they end up in crit, so that they can succumb if they wish.
var/where_we_snappin_boys = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
H.emote("scream")
H.apply_damage(150, BRUTE, where_we_snappin_boys)
var/obj/item/bodypart/cracka = H.get_bodypart(where_we_snappin_boys)
if(cracka)
var/datum/wound/blunt/critical/cracka_lackin = new
cracka_lackin.apply_wound(cracka)
H.adjustBruteLoss(rand(5,20) + (max(0, H.health))) //Make absolutely sure they end up in crit, so that they can succumb if they wish.
/obj/structure/femur_breaker/proc/raise_slat()
slat_status = BREAKER_SLAT_RAISED
@@ -52,12 +52,12 @@ GLOBAL_LIST_INIT(tendrils, list())
last_tendril = FALSE
if(last_tendril && !(flags_1 & ADMIN_SPAWNED_1))
if(SSmedals.hub_enabled)
if(SSachievements.achievements_enabled)
for(var/mob/living/L in view(7,src))
if(L.stat || !L.client)
continue
SSmedals.UnlockMedal("[BOSS_MEDAL_TENDRIL] [ALL_KILL_MEDAL]", L.client)
SSmedals.SetScore(TENDRIL_CLEAR_SCORE, L.client, 1)
L.client.give_award(/datum/award/achievement/boss/tendril_exterminator, L)
L.client.give_award(/datum/award/score/tendril_score, L) //Progresses score by one
GLOB.tendrils -= src
QDEL_NULL(emitted_light)
QDEL_NULL(gps)
+176 -135
View File
@@ -4,6 +4,11 @@ SAFES
FLOOR SAFES
*/
/// Chance for a sound clue
#define SOUND_CHANCE 10
/// Explosion number threshold for opening safe
#define BROKEN_THRESHOLD 3
//SAFES
/obj/structure/safe
name = "safe"
@@ -14,31 +19,36 @@ FLOOR SAFES
density = TRUE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT
var/open = FALSE //is the safe open?
var/tumbler_1_pos //the tumbler position- from 0 to 72
var/tumbler_1_open //the tumbler position to open at- 0 to 72
var/tumbler_2_pos
var/tumbler_2_open
var/dial = 0 //where is the dial pointing?
var/space = 0 //the combined w_class of everything in the safe
var/maxspace = 24 //the maximum combined w_class of stuff in the safe
var/explosion_count = 0 //Tough, but breakable
/obj/structure/safe/New()
..()
tumbler_1_pos = rand(0, 71)
tumbler_1_open = rand(0, 71)
tumbler_2_pos = rand(0, 71)
tumbler_2_open = rand(0, 71)
/// The maximum combined w_class of stuff in the safe
var/maxspace = 24
/// The amount of tumblers that will be generated
var/number_of_tumblers = 2
/// Whether the safe is open or not
var/open = FALSE
/// Whether the safe is locked or not
var/locked = TRUE
/// The position the dial is pointing to
var/dial = 0
/// The list of tumbler dial positions that need to be hit
var/list/tumblers = list()
/// The index in the tumblers list of the tumbler dial position that needs to be hit
var/current_tumbler_index = 1
/// The combined w_class of everything in the safe
var/space = 0
/// Tough, but breakable if explosion counts reaches set value
var/explosion_count = 0
/obj/structure/safe/Initialize(mapload)
. = ..()
// Combination generation
for(var/i in 1 to number_of_tumblers)
tumblers.Add(rand(0, 99))
if(!mapload)
return
// Put as many items on our turf inside as possible
for(var/obj/item/I in loc)
if(space >= maxspace)
return
@@ -46,141 +56,36 @@ FLOOR SAFES
space += I.w_class
I.forceMove(src)
/obj/structure/safe/proc/check_unlocked(mob/user, canhear)
if(explosion_count > 2)
return 1
if(user && canhear)
if(tumbler_1_pos == tumbler_1_open)
to_chat(user, "<span class='italics'>You hear a [pick("tonk", "krunk", "plunk")] from [src].</span>")
if(tumbler_2_pos == tumbler_2_open)
to_chat(user, "<span class='italics'>You hear a [pick("tink", "krink", "plink")] from [src].</span>")
if(tumbler_1_pos == tumbler_1_open && tumbler_2_pos == tumbler_2_open)
if(user)
visible_message("<i><b>[pick("Spring", "Sprang", "Sproing", "Clunk", "Krunk")]!</b></i>")
return TRUE
return FALSE
/obj/structure/safe/proc/decrement(num)
num -= 1
if(num < 0)
num = 71
return num
/obj/structure/safe/proc/increment(num)
num += 1
if(num > 71)
num = 0
return num
/obj/structure/safe/update_icon_state()
if(open)
icon_state = "[initial(icon_state)]-open"
else
icon_state = initial(icon_state)
/obj/structure/safe/ui_interact(mob/user)
user.set_machine(src)
var/dat = "<center>"
dat += "<a href='?src=[REF(src)];open=1'>[open ? "Close" : "Open"] [src]</a> | <a href='?src=[REF(src)];decrement=1'>-</a> [dial] <a href='?src=[REF(src)];increment=1'>+</a>"
if(open)
dat += "<table>"
for(var/i = contents.len, i>=1, i--)
var/obj/item/P = contents[i]
dat += "<tr><td><a href='?src=[REF(src)];retrieve=[REF(P)]'>[P.name]</a></td></tr>"
dat += "</table></center>"
user << browse("<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>[name]</title></head><body>[dat]</body></html>", "window=safe;size=350x300")
/obj/structure/safe/Topic(href, href_list)
if(!ishuman(usr))
return
var/mob/living/carbon/human/user = usr
if(!user.canUseTopic(src))
return
var/canhear = FALSE
if(user.is_holding_item_of_type(/obj/item/clothing/neck/stethoscope))
canhear = TRUE
if(href_list["open"])
if(check_unlocked())
to_chat(user, "<span class='notice'>You [open ? "close" : "open"] [src].</span>")
open = !open
update_icon()
updateUsrDialog()
return
else
to_chat(user, "<span class='warning'>You can't [open ? "close" : "open"] [src], the lock is engaged!</span>")
return
if(href_list["decrement"])
dial = decrement(dial)
if(dial == tumbler_1_pos + 1 || dial == tumbler_1_pos - 71)
tumbler_1_pos = decrement(tumbler_1_pos)
if(canhear)
to_chat(user, "<span class='italics'>You hear a [pick("clack", "scrape", "clank")] from [src].</span>")
if(tumbler_1_pos == tumbler_2_pos + 37 || tumbler_1_pos == tumbler_2_pos - 35)
tumbler_2_pos = decrement(tumbler_2_pos)
if(canhear)
to_chat(user, "<span class='italics'>You hear a [pick("click", "chink", "clink")] from [src].</span>")
check_unlocked(user, canhear)
updateUsrDialog()
return
if(href_list["increment"])
dial = increment(dial)
if(dial == tumbler_1_pos - 1 || dial == tumbler_1_pos + 71)
tumbler_1_pos = increment(tumbler_1_pos)
if(canhear)
to_chat(user, "<span class='italics'>You hear a [pick("clack", "scrape", "clank")] from [src].</span>")
if(tumbler_1_pos == tumbler_2_pos - 37 || tumbler_1_pos == tumbler_2_pos + 35)
tumbler_2_pos = increment(tumbler_2_pos)
if(canhear)
to_chat(user, "<span class='italics'>You hear a [pick("click", "chink", "clink")] from [src].</span>")
check_unlocked(user, canhear)
updateUsrDialog()
return
if(href_list["retrieve"])
user << browse("", "window=safe") // Close the menu
var/obj/item/P = locate(href_list["retrieve"]) in src
if(open)
if(P && in_range(src, user))
user.put_in_hands(P)
space -= P.w_class
updateUsrDialog()
/obj/structure/safe/attackby(obj/item/I, mob/user, params)
if(open)
. = 1 //no afterattack
. = TRUE //no afterattack
if(I.w_class + space <= maxspace)
space += I.w_class
if(!user.transferItemToLoc(I, src))
to_chat(user, "<span class='warning'>\The [I] is stuck to your hand, you cannot put it in the safe!</span>")
return
to_chat(user, "<span class='notice'>You put [I] in [src].</span>")
updateUsrDialog()
else
to_chat(user, "<span class='warning'>[I] won't fit in [src].</span>")
else
if(istype(I, /obj/item/clothing/neck/stethoscope))
attack_hand(user)
return
else
to_chat(user, "<span class='notice'>[I] won't fit in [src].</span>")
to_chat(user, "<span class='warning'>You can't put [I] into the safe while it is closed!</span>")
return
else if(istype(I, /obj/item/clothing/neck/stethoscope))
to_chat(user, "<span class='warning'>Hold [I] in one of your hands while you manipulate the dial!</span>")
else
return ..()
/obj/structure/safe/handle_atom_del(atom/A)
updateUsrDialog()
/obj/structure/safe/blob_act(obj/structure/blob/B)
return
/obj/structure/safe/ex_act(severity, target)
if(((severity == 2 && target == src) || severity == 1) && explosion_count < 3)
if(((severity == 2 && target == src) || severity == 1) && explosion_count < BROKEN_THRESHOLD)
explosion_count++
switch(explosion_count)
if(1)
@@ -190,6 +95,144 @@ FLOOR SAFES
if(3)
desc = initial(desc) + "\nThe lock seems to be broken."
/obj/structure/safe/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/simple/safe),
)
/obj/structure/safe/ui_state(mob/user)
return GLOB.physical_state
/obj/structure/safe/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Safe", name)
ui.open()
/obj/structure/safe/ui_data(mob/user)
var/list/data = list()
data["dial"] = dial
data["open"] = open
data["locked"] = locked
data["broken"] = check_broken()
if(open)
var/list/contents_names = list()
data["contents"] = contents_names
for(var/obj/O in contents)
contents_names[++contents_names.len] = list("name" = O.name, "sprite" = O.icon_state)
user << browse_rsc(icon(O.icon, O.icon_state), "[O.icon_state].png")
return data
/obj/structure/safe/ui_act(action, params)
. = ..()
if(.)
return
if(!ishuman(usr))
return
var/mob/living/carbon/human/user = usr
if(!user.canUseTopic(src, BE_CLOSE))
return
var/canhear = FALSE
if(user.is_holding_item_of_type(/obj/item/clothing/neck/stethoscope))
canhear = TRUE
switch(action)
if("open")
if(!check_unlocked() && !open && !broken)
to_chat(user, "<span class='warning'>You cannot open [src], as its lock is engaged!</span>")
return
to_chat(user, "<span class='notice'>You [open ? "close" : "open"] [src].</span>")
open = !open
update_icon()
return TRUE
if("turnright")
if(open)
return
if(broken)
to_chat(user, "<span class='warning'>The dial will not turn, as the mechanism is destroyed!</span>")
return
var/ticks = text2num(params["num"])
for(var/i = 1 to ticks)
dial = WRAP(dial - 1, 0, 100)
var/invalid_turn = current_tumbler_index % 2 == 0 || current_tumbler_index > number_of_tumblers
if(invalid_turn) // The moment you turn the wrong way or go too far, the tumblers reset
current_tumbler_index = 1
if(!invalid_turn && dial == tumblers[current_tumbler_index])
notify_user(user, canhear, list("tink", "krink", "plink"), ticks, i)
current_tumbler_index++
else
notify_user(user, canhear, list("clack", "scrape", "clank"), ticks, i)
check_unlocked()
return TRUE
if("turnleft")
if(open)
return
if(broken)
to_chat(user, "<span class='warning'>The dial will not turn, as the mechanism is destroyed!</span>")
return
var/ticks = text2num(params["num"])
for(var/i = 1 to ticks)
dial = WRAP(dial + 1, 0, 100)
var/invalid_turn = current_tumbler_index % 2 != 0 || current_tumbler_index > number_of_tumblers
if(invalid_turn) // The moment you turn the wrong way or go too far, the tumblers reset
current_tumbler_index = 1
if(!invalid_turn && dial == tumblers[current_tumbler_index])
notify_user(user, canhear, list("tonk", "krunk", "plunk"), ticks, i)
current_tumbler_index++
else
notify_user(user, canhear, list("click", "chink", "clink"), ticks, i)
check_unlocked()
return TRUE
if("retrieve")
if(!open)
return
var/index = text2num(params["index"])
if(!index)
return
var/obj/item/I = contents[index]
if(!I || !in_range(src, user))
return
user.put_in_hands(I)
space -= I.w_class
return TRUE
/**
* Checks if safe is considered in a broken state for force-opening the safe
*/
/obj/structure/safe/proc/check_broken()
return broken || explosion_count >= BROKEN_THRESHOLD
/**
* Called every dial turn to determine whether the safe should unlock or not.
*/
/obj/structure/safe/proc/check_unlocked()
if(check_broken())
return TRUE
if(current_tumbler_index > number_of_tumblers)
locked = FALSE
visible_message("<span class='boldnotice'>[pick("Spring", "Sprang", "Sproing", "Clunk", "Krunk")]!</span>")
return TRUE
locked = TRUE
return FALSE
/**
* Called every dial turn to provide feedback if possible.
*/
/obj/structure/safe/proc/notify_user(user, canhear, sounds, total_ticks, current_tick)
if(!canhear)
return
if(current_tick == 2)
to_chat(user, "<span class='italics'>The sounds from [src] are too fast and blend together.</span>")
if(total_ticks == 1 || prob(SOUND_CHANCE))
to_chat(user, "<span class='italics'>You hear a [pick(sounds)] from [src].</span>")
//FLOOR SAFES
/obj/structure/safe/floor
@@ -199,13 +242,11 @@ FLOOR SAFES
level = 1 //underfloor
layer = LOW_OBJ_LAYER
/obj/structure/safe/floor/Initialize(mapload)
. = ..()
if(mapload)
var/turf/T = loc
hide(T.intact)
/obj/structure/safe/floor/hide(var/intact)
invisibility = intact ? INVISIBILITY_MAXIMUM : 0
#undef SOUND_CHANCE
#undef BROKEN_THRESHOLD
+7 -2
View File
@@ -47,14 +47,19 @@
if(open)
GM.visible_message("<span class='danger'>[user] starts to give [GM] a swirlie!</span>", "<span class='userdanger'>[user] starts to give you a swirlie...</span>")
swirlie = GM
if(do_after(user, 30, 0, target = src))
GM.visible_message("<span class='danger'>[user] gives [GM] a swirlie!</span>", "<span class='userdanger'>[user] gives you a swirlie!</span>", "<span class='italics'>You hear a toilet flushing.</span>")
var/was_alive = (swirlie.stat != DEAD)
if(do_after(user, 3 SECONDS, target = src))
GM.visible_message("<span class='danger'>[user] gives [GM] a swirlie!</span>", "<span class='userdanger'>[user] gives you a swirlie!</span>", "<span class='hear'>You hear a toilet flushing.</span>")
if(iscarbon(GM))
var/mob/living/carbon/C = GM
if(!C.internal)
log_combat(user, C, "swirlied (oxy)")
C.adjustOxyLoss(5)
else
log_combat(user, GM, "swirlied (oxy)")
GM.adjustOxyLoss(5)
if(was_alive && swirlie.stat == DEAD && swirlie.client)
swirlie.client.give_award(/datum/award/achievement/misc/swirlie, swirlie) // just like space high school all over again!
swirlie = null
else
playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
+3
View File
@@ -584,6 +584,9 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
/obj/structure/window/plasma/reinforced/unanchored
anchored = FALSE
/obj/structure/window/plasma/reinforced/BlockSuperconductivity()
return TRUE
/obj/structure/window/reinforced/tinted
name = "tinted window"
icon_state = "twindow"
+4 -6
View File
@@ -872,20 +872,18 @@
/turf/closed/mineral/strong/gets_drilled(mob/user)
if(!ishuman(user))
return // see attackby
/*
var/mob/living/carbon/human/H = user
if(!(H.mind.get_skill_level(/datum/skill/mining) >= SKILL_LEVEL_MASTER))
return
*/
// if(!(H.mind?.get_skill_level(/datum/skill/mining) >= SKILL_LEVEL_MASTER))
// return
drop_ores()
// H.client.give_award(/datum/award/achievement/skill/legendary_miner, H)
H.client.give_award(/datum/award/achievement/skill/legendary_miner, H)
var/flags = NONE
if(defer_change) // TODO: make the defer change var a var for any changeturf flag
flags = CHANGETURF_DEFER_CHANGE
ScrapeAway(flags=flags)
addtimer(CALLBACK(src, .proc/AfterChange), 1, TIMER_UNIQUE)
playsound(src, 'sound/effects/break_stone.ogg', 50, TRUE) //beautiful destruction
// H.mind.adjust_experience(/datum/skill/mining, 100) //yay!
// H.mind?.adjust_experience(/datum/skill/mining, 100) //yay!
/turf/closed/mineral/strong/proc/drop_ores()
if(prob(10))