This commit is contained in:
Putnam
2020-02-03 03:17:23 -08:00
1273 changed files with 65894 additions and 22204 deletions
+47 -41
View File
@@ -7,35 +7,35 @@ RPD
#define DISPOSALS_CATEGORY 1
#define TRANSIT_CATEGORY 2
#define BUILD_MODE 1
#define WRENCH_MODE 2
#define DESTROY_MODE 4
#define PAINT_MODE 8
#define BUILD_MODE (1<<0)
#define WRENCH_MODE (1<<1)
#define DESTROY_MODE (1<<2)
#define PAINT_MODE (1<<3)
GLOBAL_LIST_INIT(atmos_pipe_recipes, list(
"Pipes" = list(
new /datum/pipe_info/pipe("Pipe", /obj/machinery/atmospherics/pipe/simple),
new /datum/pipe_info/pipe("Manifold", /obj/machinery/atmospherics/pipe/manifold),
new /datum/pipe_info/pipe("Manual Valve", /obj/machinery/atmospherics/components/binary/valve),
new /datum/pipe_info/pipe("Digital Valve", /obj/machinery/atmospherics/components/binary/valve/digital),
new /datum/pipe_info/pipe("Relief Valve", /obj/machinery/atmospherics/components/binary/relief_valve),
new /datum/pipe_info/pipe("4-Way Manifold", /obj/machinery/atmospherics/pipe/manifold4w),
new /datum/pipe_info/pipe("Layer Manifold", /obj/machinery/atmospherics/pipe/layer_manifold),
),
"Devices" = list(
new /datum/pipe_info/pipe("Connector", /obj/machinery/atmospherics/components/unary/portables_connector),
new /datum/pipe_info/pipe("Unary Vent", /obj/machinery/atmospherics/components/unary/vent_pump),
new /datum/pipe_info/pipe("Relief Valve", /obj/machinery/atmospherics/components/unary/relief_valve),
new /datum/pipe_info/pipe("Gas Pump", /obj/machinery/atmospherics/components/binary/pump),
new /datum/pipe_info/pipe("Passive Gate", /obj/machinery/atmospherics/components/binary/passive_gate),
new /datum/pipe_info/pipe("Volume Pump", /obj/machinery/atmospherics/components/binary/volume_pump),
new /datum/pipe_info/pipe("Scrubber", /obj/machinery/atmospherics/components/unary/vent_scrubber),
new /datum/pipe_info/pipe("Injector", /obj/machinery/atmospherics/components/unary/outlet_injector),
new /datum/pipe_info/meter("Meter"),
new /datum/pipe_info/pipe("Gas Filter", /obj/machinery/atmospherics/components/trinary/filter),
new /datum/pipe_info/pipe("Gas Mixer", /obj/machinery/atmospherics/components/trinary/mixer),
new /datum/pipe_info/pipe("Passive Gate", /obj/machinery/atmospherics/components/binary/passive_gate),
new /datum/pipe_info/pipe("Injector", /obj/machinery/atmospherics/components/unary/outlet_injector),
new /datum/pipe_info/pipe("Scrubber", /obj/machinery/atmospherics/components/unary/vent_scrubber),
new /datum/pipe_info/pipe("Unary Vent", /obj/machinery/atmospherics/components/unary/vent_pump),
new /datum/pipe_info/pipe("Passive Vent", /obj/machinery/atmospherics/components/unary/passive_vent),
new /datum/pipe_info/pipe("Manual Valve", /obj/machinery/atmospherics/components/binary/valve),
new /datum/pipe_info/pipe("Digital Valve", /obj/machinery/atmospherics/components/binary/valve/digital),
new /datum/pipe_info/pipe("Relief Valve (Binary)", /obj/machinery/atmospherics/components/binary/relief_valve),
new /datum/pipe_info/pipe("Relief Valve (Unary)", /obj/machinery/atmospherics/components/unary/relief_valve),
new /datum/pipe_info/meter("Meter"),
),
"Heat Exchange" = list(
new /datum/pipe_info/pipe("Pipe", /obj/machinery/atmospherics/pipe/heat_exchanging/simple),
@@ -102,22 +102,22 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
dirs = list("[NORTH]" = "Vertical", "[EAST]" = "Horizontal")
if(dirtype == PIPE_BENDABLE)
dirs += list("[NORTHWEST]" = "West to North", "[NORTHEAST]" = "North to East",
"[SOUTHWEST]" = "South to West", "[SOUTHEAST]" = "East to South")
"[SOUTHWEST]" = "South to West", "[SOUTHEAST]" = "East to South")
if(PIPE_TRINARY)
dirs = list("[NORTH]" = "West South East", "[EAST]" = "North West South",
"[SOUTH]" = "East North West", "[WEST]" = "South East North")
dirs = list("[NORTH]" = "West South East", "[SOUTH]" = "East North West",
"[EAST]" = "North West South", "[WEST]" = "South East North")
if(PIPE_TRIN_M)
dirs = list("[NORTH]" = "North East South", "[EAST]" = "East South West",
"[SOUTH]" = "South West North", "[WEST]" = "West North East",
"[SOUTHEAST]" = "West South East", "[NORTHEAST]" = "South East North",
"[NORTHWEST]" = "East North West", "[SOUTHWEST]" = "North West South")
dirs = list("[NORTH]" = "North East South", "[SOUTHWEST]" = "North West South",
"[NORTHEAST]" = "South East North", "[SOUTH]" = "South West North",
"[WEST]" = "West North East", "[SOUTHEAST]" = "West South East",
"[NORTHWEST]" = "East North West", "[EAST]" = "East South West",)
if(PIPE_UNARY)
dirs = list("[NORTH]" = "North", "[EAST]" = "East", "[SOUTH]" = "South", "[WEST]" = "West")
dirs = list("[NORTH]" = "North", "[SOUTH]" = "South", "[WEST]" = "West", "[EAST]" = "East")
if(PIPE_ONEDIR)
dirs = list("[SOUTH]" = name)
if(PIPE_UNARY_FLIPPABLE)
dirs = list("[NORTH]" = "North", "[NORTHEAST]" = "North Flipped", "[EAST]" = "East", "[SOUTHEAST]" = "East Flipped",
"[SOUTH]" = "South", "[SOUTHWEST]" = "South Flipped", "[WEST]" = "West", "[NORTHWEST]" = "West Flipped")
dirs = list("[NORTH]" = "North", "[EAST]" = "East", "[SOUTH]" = "South", "[WEST]" = "West",
"[NORTHEAST]" = "North Flipped", "[SOUTHEAST]" = "East Flipped", "[SOUTHWEST]" = "South Flipped", "[NORTHWEST]" = "West Flipped")
var/list/rows = list()
@@ -208,7 +208,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
var/static/datum/pipe_info/first_atmos
var/static/datum/pipe_info/first_disposal
var/static/datum/pipe_info/first_transit
var/mode = BUILD_MODE | PAINT_MODE | DESTROY_MODE | WRENCH_MODE
var/mode = BUILD_MODE | DESTROY_MODE | WRENCH_MODE
/obj/item/pipe_dispenser/New()
. = ..()
@@ -249,7 +249,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/pipes)
assets.send(user)
ui = new(user, src, ui_key, "rpd", name, 300, 550, master_ui, state)
ui = new(user, src, ui_key, "rpd", name, 425, 472, master_ui, state)
ui.open()
/obj/item/pipe_dispenser/ui_data(mob/user)
@@ -316,9 +316,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
playeffect = FALSE
if("mode")
var/n = text2num(params["mode"])
if(n == 2 && !(mode&1) && !(mode&2))
mode |= 3
else if(mode&n)
if(mode & n)
mode &= ~n
else
mode |= n
@@ -327,9 +325,11 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
spark_system.start()
effectcooldown = world.time + 100
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
return TRUE
/obj/item/pipe_dispenser/pre_attack(atom/A, mob/user)
if(!user.IsAdvancedToolUser() || istype(A, /turf/open/space/transit))
var/turf/T = get_turf(A)
if(!user.IsAdvancedToolUser() || !T || istype(T, /turf/open/space/transit) || isindestructiblewall(T))
return ..()
//So that changing the menu settings doesn't affect the pipes already being built.
@@ -341,11 +341,13 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
var/static/list/make_pipe_whitelist
if(!make_pipe_whitelist)
make_pipe_whitelist = typecacheof(list(/obj/structure/lattice, /obj/structure/girder, /obj/item/pipe, /obj/structure/window, /obj/structure/grille))
if(istype(A, /obj/machinery/atmospherics) && (mode & BUILD_MODE && !(mode & PAINT_MODE))) //Reduces pixelhunt when coloring is off.
A = get_turf(A)
var/can_make_pipe = (isturf(A) || is_type_in_typecache(A, make_pipe_whitelist))
. = FALSE
if((mode&DESTROY_MODE) && istype(A, /obj/item/pipe) || istype(A, /obj/structure/disposalconstruct) || istype(A, /obj/structure/c_transit_tube) || istype(A, /obj/structure/c_transit_tube_pod) || istype(A, /obj/item/pipe_meter))
if((mode & DESTROY_MODE) && istype(A, /obj/item/pipe) || istype(A, /obj/structure/disposalconstruct) || istype(A, /obj/structure/c_transit_tube) || istype(A, /obj/structure/c_transit_tube_pod) || istype(A, /obj/item/pipe_meter))
to_chat(user, "<span class='notice'>You start destroying a pipe...</span>")
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
if(do_after(user, destroy_speed, target = A))
@@ -353,7 +355,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
qdel(A)
return
if((mode&PAINT_MODE))
if((mode & PAINT_MODE))
if(istype(A, /obj/machinery/atmospherics/pipe) && !istype(A, /obj/machinery/atmospherics/pipe/layer_manifold))
var/obj/machinery/atmospherics/pipe/P = A
to_chat(user, "<span class='notice'>You start painting \the [P] [paint_color]...</span>")
@@ -371,19 +373,23 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
user.visible_message("<span class='notice'>[user] paints \the [A] [paint_color].</span>","<span class='notice'>You paint \the [A] [paint_color].</span>")
return
if(mode&BUILD_MODE)
if(mode & BUILD_MODE)
switch(category) //if we've gotten this var, the target is valid
if(ATMOS_CATEGORY) //Making pipes
if(!can_make_pipe)
return ..()
A = T
if(is_type_in_typecache(recipe, GLOB.ventcrawl_machinery) && isclosedturf(A)) //wall escapism sanity check.
to_chat(user, "<span class='warning'>[src]'s error light flickers; there's something in the way!</span>")
return
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
if (recipe.type == /datum/pipe_info/meter)
to_chat(user, "<span class='notice'>You start building a meter...</span>")
if(do_after(user, atmos_build_speed, target = A))
activate()
var/obj/item/pipe_meter/PM = new /obj/item/pipe_meter(get_turf(A))
var/obj/item/pipe_meter/PM = new /obj/item/pipe_meter(A)
PM.setAttachLayer(piping_layer)
if(mode&WRENCH_MODE)
if(mode & WRENCH_MODE)
PM.wrench_act(user, src)
else
to_chat(user, "<span class='notice'>You start building a pipe...</span>")
@@ -391,7 +397,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
activate()
var/obj/machinery/atmospherics/path = queued_p_type
var/pipe_item_type = initial(path.construction_type) || /obj/item/pipe
var/obj/item/pipe/P = new pipe_item_type(get_turf(A), queued_p_type, queued_p_dir)
var/obj/item/pipe/P = new pipe_item_type(A, queued_p_type, queued_p_dir)
if(queued_p_flipped && istype(P, /obj/item/pipe/trinary/flippable))
var/obj/item/pipe/trinary/flippable/F = P
@@ -402,13 +408,13 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
P.setPipingLayer(piping_layer)
if(findtext("[queued_p_type]", "/obj/machinery/atmospherics/pipe") && !findtext("[queued_p_type]", "layer_manifold"))
P.add_atom_colour(GLOB.pipe_paint_colors[paint_color], FIXED_COLOUR_PRIORITY)
if(mode&WRENCH_MODE)
if(mode & WRENCH_MODE)
P.wrench_act(user, src)
if(DISPOSALS_CATEGORY) //Making disposals pipes
if(!can_make_pipe)
return ..()
A = get_turf(A)
A = T
if(isclosedturf(A))
to_chat(user, "<span class='warning'>[src]'s error light flickers; there's something in the way!</span>")
return
@@ -426,14 +432,14 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
C.add_fingerprint(usr)
C.update_icon()
if(mode&WRENCH_MODE)
if(mode & WRENCH_MODE)
C.wrench_act(user, src)
return
if(TRANSIT_CATEGORY) //Making transit tubes
if(!can_make_pipe)
return ..()
A = get_turf(A)
A = T
if(isclosedturf(A))
to_chat(user, "<span class='warning'>[src]'s error light flickers; there's something in the way!</span>")
return
@@ -448,7 +454,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
if(queued_p_type == /obj/structure/c_transit_tube_pod)
var/obj/structure/c_transit_tube_pod/pod = new /obj/structure/c_transit_tube_pod(A)
pod.add_fingerprint(usr)
if(mode&WRENCH_MODE)
if(mode & WRENCH_MODE)
pod.wrench_act(user, src)
else
@@ -460,7 +466,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
tube.simple_rotate_flip()
tube.add_fingerprint(usr)
if(mode&WRENCH_MODE)
if(mode & WRENCH_MODE)
tube.wrench_act(user, src)
return
+3 -6
View File
@@ -272,14 +272,11 @@ update_label("John Doe", "Clowny")
if(isliving(user) && user.mind)
if(user.mind.special_role || anyone)
if(alert(user, "Action", "Agent ID", "Show", "Forge") == "Forge")
var/t = copytext(sanitize(input(user, "What name would you like to put on this card?", "Agent card name", registered_name ? registered_name : (ishuman(user) ? user.real_name : user.name))as text | null),1,26)
if(!t || t == "Unknown" || t == "floor" || t == "wall" || t == "r-wall") //Same as mob/dead/new_player/prefrences.dm
if (t)
alert("Invalid name.")
var/input_name = reject_bad_name(stripped_input(user, "What name would you like to put on this card?", "Agent card name", registered_name ? registered_name : (ishuman(user) ? user.real_name : user.name), MAX_NAME_LEN), TRUE)
if(!input_name)
return
registered_name = t
var/u = copytext(sanitize(input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels other than Maintenance.", "Agent card job assignment", "Assistant")as text | null),1,MAX_MESSAGE_LEN)
var/u = stripped_input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels other than Maintenance.", "Agent card job assignment", "Assistant", MAX_MESSAGE_LEN)
if(!u)
registered_name = ""
return
+4 -5
View File
@@ -146,7 +146,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(!proximity || lit) //can't dip if cigarette is lit (it will heat the reagents in the glass instead)
return
if(istype(glass)) //you can dip cigarettes into beakers
if(glass.reagents.trans_to(src, chem_volume)) //if reagents were transfered, show the message
if(glass.reagents.trans_to(src, chem_volume, log = "cigar fill: dip cigarette")) //if reagents were transfered, show the message
to_chat(user, "<span class='notice'>You dip \the [src] into \the [glass].</span>")
else //if not, either the beaker was empty, or the cigarette was full
if(!glass.reagents.total_volume)
@@ -154,7 +154,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM
else
to_chat(user, "<span class='notice'>[src] is full.</span>")
/obj/item/clothing/mask/cigarette/proc/light(flavor_text = null)
if(lit)
return
@@ -438,7 +437,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
packeditem = 1
name = "[O.name]-packed [initial(name)]"
if(O.reagents)
O.reagents.trans_to(src, O.reagents.total_volume)
O.reagents.trans_to(src, O.reagents.total_volume, log = "cigar fill: pipe pack")
qdel(O)
else
to_chat(user, "<span class='warning'>It has to be dried first!</span>")
@@ -687,7 +686,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(O.dry)
var/obj/item/clothing/mask/cigarette/rollie/R = new /obj/item/clothing/mask/cigarette/rollie(user.loc)
R.chem_volume = target.reagents.total_volume
target.reagents.trans_to(R, R.chem_volume)
target.reagents.trans_to(R, R.chem_volume, log = "cigar fill: rolling paper afterattack")
qdel(target)
qdel(src)
user.put_in_active_hand(R)
@@ -903,7 +902,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
//Transfer reagents and remove the plant
user.show_message("<span class='notice'>You stuff the [DP] into the [src]'s bowl.</span>", MSG_VISUAL)
DP.reagents.trans_to(src, 100)
DP.reagents.trans_to(src, 100, log = "cigar fill: bong")
qdel(DP)
return
else
@@ -308,6 +308,7 @@
/obj/item/circuitboard/machine/thermomachine
name = "Thermomachine (Machine Board)"
desc = "You can use a screwdriver to switch between heater and freezer."
var/pipe_layer = PIPING_LAYER_DEFAULT
req_components = list(
/obj/item/stock_parts/matter_bin = 2,
/obj/item/stock_parts/micro_laser = 2,
@@ -342,8 +343,18 @@
build_path = initial(new_type.build_path)
I.play_tool_sound(src)
to_chat(user, "<span class='notice'>You change the circuitboard setting to \"[new_setting]\".</span>")
else
return ..()
return
if(I.tool_behaviour == TOOL_MULTITOOL)
pipe_layer = (pipe_layer >= PIPING_LAYER_MAX) ? PIPING_LAYER_MIN : (pipe_layer + 1)
to_chat(user, "<span class='notice'>You change the circuitboard to layer [pipe_layer].</span>")
return
. = ..()
/obj/item/circuitboard/machine/thermomachine/examine()
. = ..()
. += "<span class='notice'>It is set to layer [pipe_layer].</span>"
/obj/item/circuitboard/machine/thermomachine/heater
name = "Heater (Machine Board)"
+4 -8
View File
@@ -407,7 +407,7 @@
to_chat(user, "<span class='notice'>You spray a [temp] on \the [target.name]</span>")
if(length(text_buffer) > 1)
text_buffer = copytext(text_buffer,2)
text_buffer = copytext(text_buffer, length(text_buffer[1]) + 1)
SStgui.update_uis(src)
if(post_noise)
@@ -427,7 +427,7 @@
/obj/item/toy/crayon/proc/can_claim_for_gang(mob/user, atom/target)
// Check area validity.
// Reject space, player-created areas, and non-station z-levels.
var/area/A = get_area(target)
var/area/A = get_base_area(target)
if(!A || (!is_station_level(A.z)) || !A.valid_territory)
to_chat(user, "<span class='warning'>[A] is unsuitable for tagging.</span>")
return FALSE
@@ -461,7 +461,7 @@
qdel(old_marking)
var/datum/antagonist/gang/G = user.mind.has_antag_datum(/datum/antagonist/gang)
var/area/territory = get_area(target)
var/area/territory = get_base_area(target)
new /obj/effect/decal/cleanable/crayon/gang(target,G.gang,"graffiti",0,user) // Heres the gang tag.
to_chat(user, "<span class='notice'>You tagged [territory] for your gang!</span>")
@@ -619,8 +619,7 @@
is_capped = TRUE
self_contained = FALSE // Don't disappear when they're empty
can_change_colour = TRUE
gang = TRUE //Gang check is true for all things upon the honored hierarchy of spraycans, except those that are FALSE.
reagent_contents = list(/datum/reagent/fuel = 1, /datum/reagent/consumable/ethanol = 1)
pre_noise = TRUE
@@ -774,7 +773,6 @@
icon_capped = "deathcan2_cap"
icon_uncapped = "deathcan2"
use_overlays = FALSE
gang = FALSE
volume_multiplier = 25
charges = 100
@@ -789,7 +787,6 @@
icon_capped = "clowncan2_cap"
icon_uncapped = "clowncan2"
use_overlays = FALSE
gang = FALSE
reagent_contents = list(/datum/reagent/lube = 1, /datum/reagent/consumable/banana = 1)
volume_multiplier = 5
@@ -804,7 +801,6 @@
icon_capped = "mimecan_cap"
icon_uncapped = "mimecan"
use_overlays = FALSE
gang = FALSE
can_change_colour = FALSE
paint_color = "#FFFFFF" //RGB
+9 -8
View File
@@ -452,14 +452,15 @@
return TRUE
/obj/item/twohanded/shockpaddles/proc/shock_touching(dmg, mob/H)
if(req_defib)
if(defib.pullshocksafely && isliving(H.pulledby))
H.visible_message("<span class='danger'>The defibrillator safely discharges the excessive charge into the floor!</span>")
else
var/mob/living/M = H.pulledby
if(M.electrocute_act(30, src))
M.visible_message("<span class='danger'>[M] is electrocuted by [M.p_their()] contact with [H]!</span>")
M.emote("scream")
if(!H.pulledby || !isliving(H.pulledby))
return
if(req_defib && defib.pullshocksafely)
H.visible_message("<span class='danger'>The defibrillator safely discharges the excessive charge into the floor!</span>")
return
var/mob/living/M = H.pulledby
if(M.electrocute_act(30, src))
M.visible_message("<span class='danger'>[M] is electrocuted by [M.p_their()] contact with [H]!</span>")
M.emote("scream")
/obj/item/twohanded/shockpaddles/proc/do_disarm(mob/living/M, mob/living/user)
if(req_defib && defib.safety)
+65 -18
View File
@@ -1,4 +1,3 @@
//The advanced pea-green monochrome lcd of tomorrow.
GLOBAL_LIST_EMPTY(PDAs)
@@ -77,6 +76,7 @@ GLOBAL_LIST_EMPTY(PDAs)
var/hidden = FALSE // Is the PDA hidden from the PDA list?
var/emped = FALSE
var/equipped = FALSE //used here to determine if this is the first time its been picked up
var/allow_emojis = TRUE //if the pda can send emojis and actually have them parsed as such
var/obj/item/card/id/id = null //Making it possible to slot an ID card into the PDA so it can function as both.
var/ownjob = null //related to above
@@ -93,6 +93,8 @@ GLOBAL_LIST_EMPTY(PDAs)
var/underline_flag = TRUE //flag for underline
var/list/blocked_pdas
/obj/item/pda/suicide_act(mob/living/carbon/user)
var/deathMessage = msg_input(user)
if (!deathMessage)
@@ -253,10 +255,14 @@ GLOBAL_LIST_EMPTY(PDAs)
var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/simple/pda)
assets.send(user)
var/datum/asset/spritesheet/emoji_s = get_asset_datum(/datum/asset/spritesheet/goonchat)
emoji_s.send(user) //Already sent by chat but no harm doing this
user.set_machine(src)
var/dat = "<!DOCTYPE html><html><head><title>Personal Data Assistant</title><link href=\"https://fonts.googleapis.com/css?family=Orbitron|Share+Tech+Mono|VT323\" rel=\"stylesheet\"></head><body bgcolor=\"" + background_color + "\"><style>body{" + font_mode + "}ul,ol{list-style-type: none;}a, a:link, a:visited, a:active, a:hover { color: #000000;text-decoration:none; }img {border-style:none;}a img{padding-right: 9px;}</style>"
dat += assets.css_tag()
dat += emoji_s.css_tag()
dat += "<a href='byond://?src=[REF(src)];choice=Refresh'>[PDAIMG(refresh)]Refresh</a>"
@@ -286,7 +292,7 @@ GLOBAL_LIST_EMPTY(PDAs)
dat += text("ID: <a href='?src=[REF(src)];choice=Authenticate'>[id ? "[id.registered_name], [id.assignment]" : "----------"]")
dat += text("<br><a href='?src=[REF(src)];choice=UpdateInfo'>[id ? "Update PDA Info" : ""]</A><br><br>")
dat += "[STATION_TIME_TIMESTAMP("hh:mm:ss")]<br>" //:[world.time / 100 % 6][world.time / 100 % 10]"
dat += "[STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]<br>" //:[world.time / 100 % 6][world.time / 100 % 10]"
dat += "[time2text(world.realtime, "MMM DD")] [GLOB.year_integer]"
dat += "<br><br>"
@@ -336,6 +342,8 @@ GLOBAL_LIST_EMPTY(PDAs)
dat += "<li><a href='byond://?src=[REF(src)];choice=54'>[PDAIMG(medbot)]Bots Access</a></li>"
if (cartridge.access & CART_JANITOR)
dat += "<li><a href='byond://?src=[REF(src)];choice=49'>[PDAIMG(bucket)]Custodial Locator</a></li>"
if(cartridge.access & CART_MIME)
dat += "<li><a href='byond://?src=[REF(src)];choice=55'>[PDAIMG(emoji)]Emoji Guidebook</a></li>"
if (istype(cartridge.radio))
dat += "<li><a href='byond://?src=[REF(src)];choice=40'>[PDAIMG(signaler)]Signaler System</a></li>"
if (cartridge.access & CART_NEWSCASTER)
@@ -387,7 +395,10 @@ GLOBAL_LIST_EMPTY(PDAs)
for (var/obj/item/pda/P in sortNames(get_viewable_pdas()))
if (P == src)
continue
dat += "<li><a href='byond://?src=[REF(src)];choice=Message;target=[REF(P)]'>[P]</a>"
if(P.owner in blocked_pdas)
dat += "<li><a href='byond://?src=[REF(src)];choice=unblock_pda;target=[P.owner]'>(BLOCKED - CLICK TO UNBLOCK) [P]</a>"
else
dat += "<li><a href='byond://?src=[REF(src)];choice=Message;target=[REF(P)]'>[P]</a>"
if(cartridge)
dat += cartridge.message_special(P)
dat += "</li>"
@@ -630,13 +641,13 @@ GLOBAL_LIST_EMPTY(PDAs)
if("Clear")//Clears messages
tnote = null
if("Ringtone")
var/t = input(U, "Please enter new ringtone", name, ttone) as text
var/t = stripped_input(U, "Please enter new ringtone", name, ttone, 20)
if(in_range(src, U) && loc == U && t)
if(SEND_SIGNAL(src, COMSIG_PDA_CHANGE_RINGTONE, U, t) & COMPONENT_STOP_RINGTONE_CHANGE)
U << browse(null, "window=pda")
return
else
ttone = copytext(sanitize(t), 1, 20)
ttone = t
else
U << browse(null, "window=pda")
return
@@ -646,6 +657,15 @@ GLOBAL_LIST_EMPTY(PDAs)
if("MessageAll")
send_to_all(U)
if("toggle_block")
toggle_blocking(usr, href_list["target"])
if("block_pda")
block_pda(usr, href_list["target"])
if("unblock_pda")
unblock_pda(usr, href_list["target"])
if("cart")
if(cartridge)
cartridge.special(U, href_list)
@@ -739,14 +759,20 @@ GLOBAL_LIST_EMPTY(PDAs)
return
if((last_text && world.time < last_text + 10) || (everyone && last_everyone && world.time < last_everyone + PDA_SPAM_DELAY))
return
var/emoji_message = emoji_parse(message)
if(prob(1))
message += "\nSent from my PDA"
// Send the signal
var/list/string_targets = list()
for (var/obj/item/pda/P in targets)
if (P.owner && P.ownjob) // != src is checked by the UI
var/list/string_blocked
for(var/obj/item/pda/P in targets)
if(owner in P.blocked_pdas)
LAZYADD(string_blocked, P.owner)
continue
if(P.owner && P.ownjob) // != src is checked by the UI
string_targets += "[P.owner] ([P.ownjob])"
if(string_blocked)
string_blocked = english_list(string_blocked)
to_chat(user, "<span class='warning'>[icon2html(src, user)] The following recipients have blocked your message: [string_blocked].</span>")
for (var/obj/machinery/computer/message_monitor/M in targets)
// In case of "Reply" to a message from a console, this will make the
// message be logged successfully. If the console is impersonating
@@ -761,7 +787,7 @@ GLOBAL_LIST_EMPTY(PDAs)
"job" = "[ownjob]",
"message" = message,
"targets" = string_targets,
"emoji_message" = emoji_message
"emojis" = allow_emojis
))
if (picture)
signal.data["photo"] = picture
@@ -775,16 +801,20 @@ GLOBAL_LIST_EMPTY(PDAs)
playsound(src, 'sound/machines/terminal_error.ogg', 15, 1)
var/target_text = signal.format_target()
if(allow_emojis)
message = emoji_parse(message)//already sent- this just shows the sent emoji as one to the sender in the to_chat
signal.data["message"] = emoji_parse(signal.data["message"])
// Log it in our logs
tnote += "<i><b>&rarr; To [target_text]:</b></i><br>[signal.format_message()]<br>"
// Show it to ghosts
var/ghost_message = "<span class='name'>[owner] </span><span class='game say'>PDA Message</span> --> <span class='name'>[target_text]</span>: <span class='message'>[signal.format_message(TRUE)]</span>"
for(var/mob/M in GLOB.player_list)
if(isobserver(M) && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTPDA))
var/ghost_message = "<span class='name'>[owner] </span><span class='game say'>PDA Message</span> --> <span class='name'>[target_text]</span>: <span class='message'>[signal.format_message()]</span>"
for(var/i in GLOB.dead_mob_list)
var/mob/M = i
if(M?.client && M.client.prefs.chat_toggles & CHAT_GHOSTPDA)
to_chat(M, "[FOLLOW_LINK(M, user)] [ghost_message]")
to_chat(user, "<span class='info'>Message sent to [target_text]: \"[message]\"</span>")
// Log in the talk log
user.log_talk(message, LOG_PDA, tag="PDA: [initial(name)] to [target_text]")
to_chat(user, "<span class='info'>Message sent to [target_text]: \"[emoji_message]\"</span>")
user.log_talk(message, LOG_PDA, tag="PDA: [initial(name)] to [target_text] (BLOCKED:[string_blocked])")
if (!silent)
playsound(src, 'sound/machines/terminal_success.ogg', 15, 1)
// Reset the photo
@@ -794,8 +824,7 @@ GLOBAL_LIST_EMPTY(PDAs)
last_everyone = world.time
/obj/item/pda/proc/receive_message(datum/signal/subspace/pda/signal)
tnote += "<i><b>&larr; From <a href='byond://?src=[REF(src)];choice=Message;target=[REF(signal.source)]'>[signal.data["name"]]</a> ([signal.data["job"]]):</b></i><br>[signal.format_message()]<br>"
tnote += "<i><b>&larr; From <a href='byond://?src=[REF(src)];choice=Message;target=[REF(signal.source)]'>[signal.data["name"]]</a> ([signal.data["job"]]):</b></i> <a href='byond://?src=[REF(src)];choice=toggle_block;target=[signal.data["name"]]'>(BLOCK/UNBLOCK)</a><br>[signal.format_message()]<br>"
if (!silent)
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
audible_message("[icon2html(src, hearers(src))] *[ttone]*", null, 3)
@@ -814,7 +843,11 @@ GLOBAL_LIST_EMPTY(PDAs)
hrefstart = "<a href='?src=[REF(L)];track=[html_encode(signal.data["name"])]'>"
hrefend = "</a>"
to_chat(L, "[icon2html(src)] <b>Message from [hrefstart][signal.data["name"]] ([signal.data["job"]])[hrefend], </b>[signal.format_message(TRUE)] (<a href='byond://?src=[REF(src)];choice=Message;skiprefresh=1;target=[REF(signal.source)]'>Reply</a>)")
var/inbound_message = signal.format_message()
if(signal.data["emojis"] == TRUE)//so will not parse emojis as such from pdas that don't send emojis
inbound_message = emoji_parse(inbound_message)
to_chat(L, "[icon2html(src)] <b>Message from [hrefstart][signal.data["name"]] ([signal.data["job"]])[hrefend], </b>[inbound_message] (<a href='byond://?src=[REF(src)];choice=Message;skiprefresh=1;target=[REF(signal.source)]'>Reply</a>) (<a href='byond://?src=[REF(src)];choice=toggle_block;target=[signal.data["name"]]'>BLOCK/UNBLOCK</a>)")
update_icon(TRUE)
@@ -827,6 +860,20 @@ GLOBAL_LIST_EMPTY(PDAs)
/obj/item/pda/proc/create_message(mob/living/U, obj/item/pda/P)
send_message(U,list(P))
/obj/item/pda/proc/toggle_blocking(mob/user, target)
if(target in blocked_pdas)
unblock_pda(user, target)
else
block_pda(user, target)
/obj/item/pda/proc/block_pda(mob/user, target)
to_chat(user, "<span class='notice'>[icon2html(src, user)] [target] blocked from messages. Use the messenger PDA list to unblock.</span>")
LAZYOR(blocked_pdas, target)
/obj/item/pda/proc/unblock_pda(mob/user, target)
to_chat(user, "<span class='notice'>[icon2html(src, user)] [target] unblocked from messages.</span>")
LAZYREMOVE(blocked_pdas, target)
/obj/item/pda/AltClick(mob/user)
. = ..()
if(id)
@@ -1172,4 +1219,4 @@ GLOBAL_LIST_EMPTY(PDAs)
#undef PDA_OVERLAY_ID
#undef PDA_OVERLAY_ITEM
#undef PDA_OVERLAY_LIGHT
#undef PDA_OVERLAY_PAI
#undef PDA_OVERLAY_PAI
@@ -19,6 +19,26 @@
if(istype(cart) && cart.charges < 5)
cart.charges++
//Mime PDA sends "silent" messages.
/obj/item/pda/mime
name = "mime PDA"
default_cartridge = /obj/item/cartridge/virus/mime
inserted_item = /obj/item/toy/crayon/mime
icon_state = "pda-mime"
desc = "A portable microcomputer by Thinktronic Systems, LTD. The hardware has been modified for compliance with the vows of silence."
silent = TRUE
ttone = "silence"
/obj/item/pda/mime/msg_input(mob/living/U = usr)
if(emped || toff)
return
var/emojis = emoji_sanitize(stripped_input(U, "Please enter emojis", name))
if(!emojis)
return
if(!U.canUseTopic(src, BE_CLOSE))
return
return emojis
// Special AI/pAI PDAs that cannot explode.
/obj/item/pda/ai
icon = null
@@ -79,14 +99,6 @@
icon_state = "pda-science"
ttone = "boom"
/obj/item/pda/mime
name = "mime PDA"
default_cartridge = /obj/item/cartridge/virus/mime
inserted_item = /obj/item/toy/crayon/mime
icon_state = "pda-mime"
silent = TRUE
ttone = "silence"
/obj/item/pda/heads
default_cartridge = /obj/item/cartridge/head
icon_state = "pda-hop"
+30 -4
View File
@@ -309,9 +309,14 @@ Code:
var/list/S = list(" Off","AOff"," On", " AOn")
var/list/chg = list("N","C","F")
//Neither copytext nor copytext_char is appropriate here; neither 30 UTF-8 code units nor 30 code points equates to 30 columns of output.
//Some glyphs are very tall or very wide while others are small or even take up no space at all.
//Emojis can take modifiers which are many characters but render as only one glyph.
//A proper solution here (as far as Unicode goes, maybe not ideal as far as markup goes, a table would be better)
//would be to use <span style="width: NNNpx; overflow: none;">[A.area.name]</span>
for(var/obj/machinery/power/apc/A in L)
menu += copytext(add_tspace(A.area.name, 30), 1, 30)
menu += " [S[A.equipment+1]] [S[A.lighting+1]] [S[A.environ+1]] [add_lspace(DisplayPower(A.lastused_total), 6)] [A.cell ? "[add_lspace(round(A.cell.percent()), 3)]% [chg[A.charging+1]]" : " N/C"]<BR>"
menu += copytext_char(add_trailing(A.area.name, 30, " "), 1, 30)
menu += " [S[A.equipment+1]] [S[A.lighting+1]] [S[A.environ+1]] [add_leading(DisplayPower(A.lastused_total), 6, " ")] [A.cell ? "[add_leading(round(A.cell.percent()), 3, " ")]% [chg[A.charging+1]]" : " N/C"]<BR>"
menu += "</FONT></PRE>"
@@ -326,7 +331,7 @@ Code:
if(active1 in GLOB.data_core.general)
menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]]<br>"
menu += "Sex: [active1.fields["sex"]]<br>"
menu += "Sex: [active1.fields["gender"]]<br>"
menu += "Age: [active1.fields["age"]]<br>"
menu += "Rank: [active1.fields["rank"]]<br>"
menu += "Fingerprint: [active1.fields["fingerprint"]]<br>"
@@ -370,7 +375,7 @@ Code:
if(active1 in GLOB.data_core.general)
menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]]<br>"
menu += "Sex: [active1.fields["sex"]]<br>"
menu += "Sex: [active1.fields["gender"]]<br>"
menu += "Age: [active1.fields["age"]]<br>"
menu += "Rank: [active1.fields["rank"]]<br>"
menu += "Fingerprint: [active1.fields["fingerprint"]]<br>"
@@ -579,6 +584,22 @@ Code:
if (54) // Beepsky, Medibot, Floorbot, and Cleanbot access
menu = "<h4>[PDAIMG(medbot)] Bots Interlink</h4>"
bot_control()
if (55) // Emoji Guidebook for mimes
menu = "<h4>[PDAIMG(emoji)] Emoji Guidebook</h4>"
var/static/list/emoji_icon_states
var/static/emoji_table
if(!emoji_table)
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/goonchat)
var/list/collate = list("<br><table>")
for(var/emoji in sortList(icon_states(icon('icons/emoji.dmi'))))
var/tag = sheet.icon_tag("emoji-[emoji]")
collate += "<tr><td>[emoji]</td><td>[tag]</td></tr>"
collate += "</table><br>"
emoji_table = collate.Join()
menu += "<br> To use an emoji in a pda message, refer to the guide and add \":\" around the emoji. Your PDA supports the following emoji:<br>"
menu += emoji_table
if (99) //Newscaster message permission error
menu = "<h5> ERROR : NOT AUTHORIZED [host_pda.id ? "" : "- ID SLOT EMPTY"] </h5>"
@@ -679,6 +700,11 @@ Code:
return
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
//emoji previews
if(href_list["emoji"])
var/parse = emoji_parse(":[href_list["emoji"]]:")
to_chat(usr, parse)
//Bot control section! Viciously ripped from radios for being laggy and terrible.
if(href_list["op"])
switch(href_list["op"])
@@ -14,6 +14,7 @@
var/last_use = 0
var/next_use = 0
var/obj/effect/abstract/sync_holder/sync_holder
var/resync_timer
/obj/item/desynchronizer/attack_self(mob/living/user)
if(world.time < next_use)
@@ -56,16 +57,20 @@
SEND_SIGNAL(AM, COMSIG_MOVABLE_SECLUDED_LOCATION)
last_use = world.time
icon_state = "desynchronizer-on"
addtimer(CALLBACK(src, .proc/resync), duration)
resync_timer = addtimer(CALLBACK(src, .proc/resync), duration , TIMER_STOPPABLE)
/obj/item/desynchronizer/proc/resync()
new /obj/effect/temp_visual/desynchronizer(sync_holder.drop_location())
QDEL_NULL(sync_holder)
if(resync_timer)
deltimer(resync_timer)
resync_timer = null
icon_state = initial(icon_state)
next_use = world.time + (world.time - last_use) // Could be 2*world.time-last_use but that would just be confusing
/obj/item/desynchronizer/Destroy()
resync()
if(sync_holder)
resync()
return ..()
/obj/effect/abstract/sync_holder
@@ -1,6 +1,6 @@
/obj/item/forcefield_projector
name = "forcefield projector"
desc = "An experimental device that can create several forcefields at a distance."
desc = "An experimental device that can create several forcefields at a short distance."
icon = 'icons/obj/device.dmi'
icon_state = "signmaker_forcefield"
slot_flags = ITEM_SLOT_BELT
@@ -14,7 +14,7 @@
var/shield_integrity = 250
var/max_fields = 3
var/list/current_fields
var/field_distance_limit = 7
var/field_distance_limit = 2
/obj/item/forcefield_projector/afterattack(atom/target, mob/user, proximity_flag)
. = ..()
+7 -9
View File
@@ -73,8 +73,10 @@ GLOBAL_LIST_EMPTY(GPS_list)
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
var/gps_window_height = 300 + GLOB.GPS_list.len * 20 // Variable window height, depending on how many GPS units there are to show
ui = new(user, src, ui_key, "gps", "Global Positioning System", 600, gps_window_height, master_ui, state) //width, height
// Variable window height, depending on how many GPS units there are
// to show, clamped to relatively safe range.
var/gps_window_height = CLAMP(325 + GLOB.GPS_list.len * 14, 325, 700)
ui = new(user, src, ui_key, "gps", "Global Positioning System", 470, gps_window_height, master_ui, state) //width, height
ui.open()
ui.set_autoupdate(state = updating)
@@ -91,6 +93,8 @@ GLOBAL_LIST_EMPTY(GPS_list)
var/turf/curr = get_turf(src)
data["current"] = "[get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])"
data["currentArea"] = "[get_area_name(curr, TRUE)]"
data["currentCoords"] = "[curr.x], [curr.y], [curr.z]"
var/list/signals = list()
data["signals"] = list()
@@ -104,16 +108,10 @@ GLOBAL_LIST_EMPTY(GPS_list)
continue
var/list/signal = list()
signal["entrytag"] = G.gpstag //Name or 'tag' of the GPS
signal["area"] = get_area_name(G, TRUE)
signal["coord"] = "[pos.x], [pos.y], [pos.z]"
signal["coords"] = "[pos.x], [pos.y], [pos.z]"
if(pos.z == curr.z) //Distance/Direction calculations for same z-level only
signal["dist"] = max(get_dist(curr, pos), 0) //Distance between the src and remote GPS turfs
signal["degrees"] = round(Get_Angle(curr, pos)) //0-360 degree directional bearing, for more precision.
var/direction = uppertext(dir2text(get_dir(curr, pos))) //Direction text (East, etc). Not as precise, but still helpful.
if(!direction)
direction = "CENTER"
signal["degrees"] = "N/A"
signal["direction"] = direction
signals += list(signal) //Add this signal to the list of signals
data["signals"] = signals
@@ -56,6 +56,14 @@
else
return ..()
/obj/item/laser_pointer/examine(mob/user)
. = ..()
if(in_range(user, src) || isobserver(user))
if(!diode)
. += "<span class='notice'>The diode is missing.<span>"
else
. += "<span class='notice'>A class <b>[diode.rating]</b> laser diode is installed. It is <i>screwed</i> in place.<span>"
/obj/item/laser_pointer/afterattack(atom/target, mob/living/user, flag, params)
. = ..()
laser_act(target, user, params)
+1 -1
View File
@@ -101,7 +101,7 @@
if(href_list["reset_radio_short"])
pai.unshort_radio()
if(href_list["setlaws"])
var/newlaws = copytext(sanitize(input("Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", pai.laws.supplied[1]) as message),1,MAX_MESSAGE_LEN)
var/newlaws = stripped_multiline_input("Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", MAX_MESSAGE_LEN)
if(newlaws && pai)
pai.add_supplied_law(0,newlaws)
if(href_list["toggle_holo"])
@@ -61,7 +61,7 @@
var/mob/living/carbon/C = usr
if(usr.stat || usr.restrained() || C.back == src)
return
if(!usr.canUseTopic(src, BE_CLOSE))
usr << browse(null, "window=radio")
onclose(usr, "radio")
@@ -127,7 +127,7 @@
/obj/item/electropack/ui_interact(mob/user)
if(!ishuman(user))
return
user.set_machine(src)
var/dat = {"
<TT>
@@ -200,14 +200,14 @@ Code:
/obj/item/electropack/shockcollar/attackby(obj/item/W, mob/user, params) //moves it here because on_click is being bad
if(istype(W, /obj/item/pen))
var/t = input(user, "Would you like to change the name on the tag?", "Name your new pet", tagname ? tagname : "Spot") as null|text
var/t = stripped_input(user, "Would you like to change the name on the tag?", "Name your new pet", tagname ? tagname : "Spot", MAX_NAME_LEN)
if(t)
tagname = copytext(sanitize(t), 1, MAX_NAME_LEN)
name = "[initial(name)] - [tagname]"
tagname = t
name = "[initial(name)] - [t]"
else
return ..()
/obj/item/electropack/shockcollar/ui_interact(mob/user) //on_click calls this
/obj/item/electropack/shockcollar/ui_interact(mob/user) //on_click calls this
var/dat = {"
<TT>
<B>Frequency/Code</B> for shock collar:<BR>
@@ -26,6 +26,7 @@ GLOBAL_LIST_INIT(channel_tokens, list(
slot_flags = ITEM_SLOT_EARS
var/obj/item/encryptionkey/keyslot2 = null
dog_fashion = null
var/bowman = FALSE
/obj/item/radio/headset/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins putting \the [src]'s antenna up [user.p_their()] nose! It looks like [user.p_theyre()] trying to give [user.p_them()]self cancer!</span>")
@@ -52,6 +53,11 @@ GLOBAL_LIST_INIT(channel_tokens, list(
else
. += "<span class='notice'>A small screen on the headset flashes, it's too small to read without holding or wearing the headset.</span>"
/obj/item/radio/headset/ComponentInitialize()
. = ..()
if (bowman)
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
/obj/item/radio/headset/Initialize()
. = ..()
recalculateChannels()
@@ -81,10 +87,7 @@ GLOBAL_LIST_INIT(channel_tokens, list(
desc = "A syndicate headset that can be used to hear all radio frequencies. Protects ears from flashbangs."
icon_state = "syndie_headset"
item_state = "syndie_headset"
/obj/item/radio/headset/syndicate/alt/ComponentInitialize()
. = ..()
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
bowman = TRUE
/obj/item/radio/headset/syndicate/alt/leader
name = "team leader headset"
@@ -112,10 +115,7 @@ GLOBAL_LIST_INIT(channel_tokens, list(
desc = "This is used by your elite security force. Protects ears from flashbangs."
icon_state = "sec_headset_alt"
item_state = "sec_headset_alt"
/obj/item/radio/headset/headset_sec/alt/ComponentInitialize()
. = ..()
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
bowman = TRUE
/obj/item/radio/headset/headset_eng
name = "engineering radio headset"
@@ -161,10 +161,7 @@ GLOBAL_LIST_INIT(channel_tokens, list(
desc = "The headset of the boss. Protects ears from flashbangs."
icon_state = "com_headset_alt"
item_state = "com_headset_alt"
/obj/item/radio/headset/heads/captain/alt/ComponentInitialize()
. = ..()
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
bowman = TRUE
/obj/item/radio/headset/heads/rd
name = "\proper the research director's headset"
@@ -183,10 +180,7 @@ GLOBAL_LIST_INIT(channel_tokens, list(
desc = "The headset of the man in charge of keeping order and protecting the station. Protects ears from flashbangs."
icon_state = "com_headset_alt"
item_state = "com_headset_alt"
/obj/item/radio/headset/heads/hos/ComponentInitialize()
. = ..()
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
bowman = TRUE
/obj/item/radio/headset/heads/ce
name = "\proper the chief engineer's headset"
@@ -258,10 +252,7 @@ GLOBAL_LIST_INIT(channel_tokens, list(
icon_state = "cent_headset_alt"
item_state = "cent_headset_alt"
keyslot = null
/obj/item/radio/headset/headset_cent/alt/ComponentInitialize()
. = ..()
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
bowman = TRUE
/obj/item/radio/headset/ai
name = "\proper Integrated Subspace Transceiver "
@@ -273,7 +264,11 @@ GLOBAL_LIST_INIT(channel_tokens, list(
/obj/item/radio/headset/attackby(obj/item/W, mob/user, params)
user.set_machine(src)
if (istype(W,/obj/item/headsetupgrader))
if (!bowman)
to_chat(user,"<span class='notice'>You upgrade [src].</span>")
bowmanize()
qdel(W)
if(istype(W, /obj/item/screwdriver))
if(keyslot || keyslot2)
for(var/ch_name in channels)
@@ -341,3 +336,24 @@ GLOBAL_LIST_INIT(channel_tokens, list(
use_command = !use_command
to_chat(user, "<span class='notice'>You toggle high-volume mode [use_command ? "on" : "off"].</span>")
return TRUE
/obj/item/radio/headset/proc/bowmanize()
cut_overlays()
var/icon/yeas = icon(icon,icon_state)
icon_state = "antenna_alt"
var/mutable_appearance/center = mutable_appearance(icon,"center_alt")
center.color = yeas.GetPixel(15,18)
var/mutable_appearance/centeralt = mutable_appearance(icon,"centeralt_alt")
centeralt.color = yeas.GetPixel(14,22)
var/mutable_appearance/centercenter = mutable_appearance(icon,"centercenter_alt")
centercenter.color = yeas.GetPixel(13,19)
var/mutable_appearance/centerpixel = mutable_appearance(icon,"centerpixel_alt")
centerpixel.color = yeas.GetPixel(13,21)
add_overlay(center)
add_overlay(centeralt)
add_overlay(centercenter)
add_overlay(centerpixel)
name = replacetext(name,"headset", "bowman headset")
desc = "[desc] Protects ears from flashbangs."
bowman = TRUE
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
@@ -112,7 +112,14 @@
. = ..()
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "radio", name, 370, 220 + channels.len * 22, master_ui, state)
var/ui_width = 360
var/ui_height = 106
if(subspace_transmission)
if(channels.len > 0)
ui_height += 6 + channels.len * 21
else
ui_height += 24
ui = new(user, src, ui_key, "radio", name, ui_width, ui_height, master_ui, state)
ui.open()
/obj/item/radio/ui_data(mob/user)
+5 -7
View File
@@ -28,7 +28,7 @@ SLIME SCANNER
/obj/item/t_scanner/attack_self(mob/user)
on = !on
icon_state = copytext(icon_state, 1, length(icon_state))+"[on]"
icon_state = copytext_char(icon_state, 1, -1) + "[on]"
if(on)
START_PROCESSING(SSobj, src)
@@ -407,19 +407,17 @@ SLIME SCANNER
// Blood Level
if(M.has_dna())
var/mob/living/carbon/C = M
var/blood_id = C.get_blood_id()
if(blood_id)
var/blood_typepath = C.get_blood_id()
if(blood_typepath)
if(ishuman(C))
if(H.bleed_rate)
msg += "<span class='danger'>Subject is bleeding!</span>\n"
var/blood_percent = round((C.scan_blood_volume() / (BLOOD_VOLUME_NORMAL * C.blood_ratio))*100)
var/blood_type = C.dna.blood_type
if(blood_id != ("blood" || "jellyblood"))//special blood substance
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
if(!(blood_typepath in GLOB.blood_reagent_types))
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_typepath]
if(R)
blood_type = R.name
else
blood_type = blood_id
if(C.scan_blood_volume() <= (BLOOD_VOLUME_SAFE*C.blood_ratio) && C.scan_blood_volume() > (BLOOD_VOLUME_OKAY*C.blood_ratio))
msg += "<span class='danger'>LOW blood level [blood_percent] %, [C.scan_blood_volume()] cl,</span> <span class='info'>type: [blood_type]</span>\n"
else if(C.scan_blood_volume() <= (BLOOD_VOLUME_OKAY*C.blood_ratio))
@@ -251,3 +251,9 @@ effective or pretty fucking useless.
else
GLOB.active_jammers -= src
update_icon()
/obj/item/headsetupgrader
name = "headset upgrader"
desc = "A tool that can be used to upgrade a normal headset to be able to protect from flashbangs."
icon = 'icons/obj/device.dmi'
icon_state = "headset_upgrade"
+1 -1
View File
@@ -160,7 +160,7 @@
/obj/item/dice/attack_self(mob/user)
diceroll(user)
/obj/item/dice/throw_impact(atom/target)
/obj/item/dice/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
diceroll(thrownby)
. = ..()
+66 -47
View File
@@ -54,7 +54,7 @@
to_chat(user, "<span class='warning'>[src] was shaken recently, it needs time to settle.</span>")
return
user.visible_message("<span class='notice'>[user] starts shaking [src].</span>", "<span class='notice'>You start shaking [src].</span>", "<span class='italics'>You hear shaking and sloshing.</span>")
user.visible_message("<span class='notice'>[user] starts shaking [src].</span>", "<span class='notice'>You start shaking [src].</span>", "<span class='hear'>You hear shaking and sloshing.</span>")
shaking = TRUE
@@ -95,16 +95,47 @@
// except it actually ASKS THE DEAD (wooooo)
/obj/item/toy/eightball/haunted
shake_time = 150
cooldown_time = 1800
shake_time = 30 SECONDS
cooldown_time = 3 MINUTES
flags_1 = HEAR_1
var/last_message
var/selected_message
var/list/votes
//these kind of store the same thing but one is easier to work with.
var/list/votes = list()
var/list/voted = list()
var/static/list/haunted_answers = list(
"yes" = list(
"It is certain",
"It is decidedly so",
"Without a doubt",
"Yes definitely",
"You may rely on it",
"As I see it, yes",
"Most likely",
"Outlook good",
"Yes",
"Signs point to yes"
),
"maybe" = list(
"Reply hazy try again",
"Ask again later",
"Better not tell you now",
"Cannot predict now",
"Concentrate and ask again"
),
"no" = list(
"Don't count on it",
"My reply is no",
"My sources say no",
"Outlook not so good",
"Very doubtful"
)
)
/obj/item/toy/eightball/haunted/Initialize(mapload)
. = ..()
votes = list()
for (var/answer in haunted_answers)
votes[answer] = 0
GLOB.poi_list |= src
/obj/item/toy/eightball/haunted/Destroy()
@@ -122,7 +153,7 @@
interact(user)
return ..()
/obj/item/toy/eightball/haunted/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode, atom/movable/source)
/obj/item/toy/eightball/haunted/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode)
. = ..()
last_message = raw_message
@@ -137,38 +168,31 @@
if(isobserver(usr))
interact(usr)
/obj/item/toy/eightball/haunted/proc/get_vote_tallies()
var/list/answers = list()
for(var/ckey in votes)
var/selected = votes[ckey]
if(selected in answers)
answers[selected]++
else
answers[selected] = 1
return answers
/obj/item/toy/eightball/haunted/get_answer()
if(!votes.len)
return pick(possible_answers)
var/top_amount = 0
var/top_vote
var/list/tallied_votes = get_vote_tallies()
for(var/vote in votes)
var/amount_of_votes = length(votes[vote])
if(amount_of_votes > top_amount)
top_vote = vote
top_amount = amount_of_votes
//If one option actually has votes and there's a tie, pick between them 50/50
else if(top_amount && amount_of_votes == top_amount && prob(50))
top_vote = vote
top_amount = amount_of_votes
// I miss python sorting, then I wouldn't have to muck about with
// all this
var/most_popular_answer
var/most_amount = 0
// yes, if there is a tie, there is an arbitary decision
// but we never said the spirit world was fair
for(var/A in tallied_votes)
var/amount = tallied_votes[A]
if(amount > most_amount)
most_popular_answer = A
if(isnull(top_vote))
top_vote = pick(votes)
return most_popular_answer
for(var/vote in votes)
votes[vote] = 0
/obj/item/toy/eightball/haunted/ui_interact(mob/user, ui_key="main", datum/tgui/ui=null, force_open=0, datum/tgui/master_ui=null, datum/ui_state/state = GLOB.observer_state)
voted.Cut()
return top_vote
/obj/item/toy/eightball/haunted/ui_interact(mob/user, ui_key="main", datum/tgui/ui=null, force_open=0, datum/tgui/master_ui=null, datum/ui_state/state = GLOB.always_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
@@ -179,21 +203,13 @@
var/list/data = list()
data["shaking"] = shaking
data["question"] = selected_message
var/list/tallied_votes = get_vote_tallies()
data["answers"] = list()
for(var/pa in possible_answers)
for(var/pa in haunted_answers)
var/list/L = list()
L["answer"] = pa
var/amount = 0
if(pa in tallied_votes)
amount = tallied_votes[pa]
L["amount"] = amount
var/selected = FALSE
if(votes[user.ckey] == pa)
selected = TRUE
L["selected"] = selected
L["amount"] = votes[pa]
L["selected"] = voted[user.ckey]
data["answers"] += list(L)
return data
@@ -206,8 +222,11 @@
switch(action)
if("vote")
var/selected_answer = params["answer"]
if(!(selected_answer in possible_answers))
if(!(selected_answer in haunted_answers))
return
if(user.ckey in voted)
return
else
votes[user.ckey] = selected_answer
. = TRUE
votes[selected_answer] += 1
voted[user.ckey] = selected_answer
. = TRUE
+5 -6
View File
@@ -34,12 +34,12 @@
/obj/item/grenade/proc/clown_check(mob/living/carbon/human/user)
var/clumsy = HAS_TRAIT(user, TRAIT_CLUMSY)
if(clumsy && (clumsy_check == GRENADE_CLUMSY_FUMBLE))
if(prob(50))
if(clumsy)
if(clumsy_check == GRENADE_CLUMSY_FUMBLE && prob(50))
to_chat(user, "<span class='warning'>Huh? How does this thing work?</span>")
preprime(user, 5, FALSE)
return FALSE
else if(!clumsy && (clumsy_check == GRENADE_NONCLUMSY_FUMBLE))
else if(clumsy_check == GRENADE_NONCLUMSY_FUMBLE && !(user.mind && HAS_TRAIT(user.mind, TRAIT_CLOWN_MENTALITY)))
to_chat(user, "<span class='warning'>You pull the pin on [src]. Attached to it is a pink ribbon that says, \"<span class='clown'>HONK</span>\"</span>")
preprime(user, 5, FALSE)
return FALSE
@@ -93,9 +93,8 @@
var/obj/item/I = loc
I.grenade_prime_react(src)
/obj/item/grenade/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/screwdriver))
/obj/item/grenade/tool_act(mob/living/user, obj/item/I, tool_behaviour)
if(tool_behaviour == TOOL_SCREWDRIVER)
switch(det_time)
if ("1")
det_time = 10
+3 -2
View File
@@ -310,6 +310,7 @@
trap_damage = 0
item_flags = DROPDEL
flags_1 = NONE
breakouttime = 50
/obj/item/restraints/legcuffs/beartrap/energy/New()
..()
@@ -340,7 +341,7 @@
return
playsound(src.loc,'sound/weapons/bolathrow.ogg', 75, 1)
/obj/item/restraints/legcuffs/bola/throw_impact(atom/hit_atom)
/obj/item/restraints/legcuffs/bola/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(..() || !iscarbon(hit_atom))//if it gets caught or the target can't be cuffed,
return//abort
var/mob/living/carbon/C = hit_atom
@@ -368,7 +369,7 @@
w_class = WEIGHT_CLASS_SMALL
breakouttime = 60
/obj/item/restraints/legcuffs/bola/energy/throw_impact(atom/hit_atom)
/obj/item/restraints/legcuffs/bola/energy/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(iscarbon(hit_atom))
var/obj/item/restraints/legcuffs/beartrap/B = new /obj/item/restraints/legcuffs/beartrap/energy/cyborg(get_turf(hit_atom))
B.Crossed(hit_atom)
@@ -92,6 +92,14 @@
creation_time = 0
max_signs = 3
/obj/item/holosign_creator/combifan
name = "ATMOS holo-combifan projector"
desc = "A holographic projector that creates holographic combi-fans that prevent changes in atmosphere and temperature conditions. Somehow."
icon_state = "signmaker_atmos"
holosign_type = /obj/structure/holosign/barrier/combifan
creation_time = 0
max_signs = 3
/obj/item/holosign_creator/medical
name = "\improper PENLITE barrier projector"
desc = "A holographic projector that creates PENLITE holobarriers. Useful during quarantines since they halt those with malicious diseases."
+4 -3
View File
@@ -72,20 +72,21 @@
display_names += list(initial(A.name) = A)
var/choice = input(M,"What holy armor kit would you like to order?","Holy Armor Theme") as null|anything in display_names
if(QDELETED(src) || !choice || M.stat || !in_range(M, src) || M.restrained() || !M.canmove || GLOB.holy_armor_type)
var/turf/T = get_turf(M)
if(!T || QDELETED(src) || !choice || M.stat || !in_range(M, src) || M.restrained() || !M.canmove || GLOB.holy_armor_type)
return
var/index = display_names.Find(choice)
var/A = holy_armor_list[index]
GLOB.holy_armor_type = A
var/holy_armor_box = new A
var/holy_armor_box = new A(T)
SSblackbox.record_feedback("tally", "chaplain_armor", 1, "[choice]")
if(holy_armor_box)
qdel(src)
M.put_in_active_hand(holy_armor_box)///YOU COMPILED
M.put_in_hands(holy_armor_box)
/obj/item/storage/box/holy
name = "Templar Kit"
+4 -4
View File
@@ -333,13 +333,13 @@
if(proximity_flag)
consume_everything(target)
/obj/item/melee/supermatter_sword/throw_impact(target)
/obj/item/melee/supermatter_sword/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
..()
if(ismob(target))
var/mob/M
if(ismob(hit_atom))
var/mob/M = hit_atom
if(src.loc == M)
M.dropItemToGround(src)
consume_everything(target)
consume_everything(hit_atom)
/obj/item/melee/supermatter_sword/pickup(user)
..()
+8
View File
@@ -19,3 +19,11 @@
icon_state = "skub"
w_class = WEIGHT_CLASS_BULKY
attack_verb = list("skubbed")
/obj/item/supermatterspray
name = "supermatter spray"
desc = "A spray bottle containing some kind of magical spray to fix the SM. \"Do not inhale.\" is written on the side. Unless aimed at the supermatter, it does nothing."
icon = 'icons/obj/supermatter.dmi'
icon_state = "supermatterspray"
w_class = WEIGHT_CLASS_SMALL
var/usesleft = 2
+3 -3
View File
@@ -105,10 +105,10 @@
playsound(src.loc, "sparks", 50, 1)
shock(M)
/obj/item/twohanded/mjollnir/throw_impact(atom/target)
/obj/item/twohanded/mjollnir/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
. = ..()
if(isliving(target))
shock(target)
if(isliving(hit_atom))
shock(hit_atom)
/obj/item/twohanded/mjollnir/update_icon() //Currently only here to fuck with the on-mob icons.
icon_state = "mjollnir[wielded]"
+1 -1
View File
@@ -35,7 +35,7 @@
/obj/item/stack/ore/bluespace_crystal/proc/blink_mob(mob/living/L)
do_teleport(L, get_turf(L), blink_range, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE)
/obj/item/stack/ore/bluespace_crystal/throw_impact(atom/hit_atom)
/obj/item/stack/ore/bluespace_crystal/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(!..()) // not caught in mid-air
visible_message("<span class='notice'>[src] fizzles and disappears upon impact!</span>")
var/turf/T = get_turf(hit_atom)
+33 -2
View File
@@ -10,7 +10,15 @@
*/
GLOBAL_LIST_INIT(glass_recipes, list ( \
new/datum/stack_recipe("directional window", /obj/structure/window/unanchored, time = 0, on_floor = TRUE, window_checks = TRUE), \
new/datum/stack_recipe("fulltile window", /obj/structure/window/fulltile/unanchored, 2, time = 0, on_floor = TRUE, window_checks = TRUE) \
new/datum/stack_recipe("fulltile window", /obj/structure/window/fulltile/unanchored, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \
null, \
new/datum/stack_recipe_list("glass working bases", list( \
new/datum/stack_recipe("chem dish", /obj/item/glasswork/glass_base/dish, 10), \
new/datum/stack_recipe("lens", /obj/item/glasswork/glass_base/glass_lens, 15), \
new/datum/stack_recipe("spout flask", /obj/item/glasswork/glass_base/spouty, 20), \
new/datum/stack_recipe("small bulb flask", /obj/item/glasswork/glass_base/flask_small, 5), \
new/datum/stack_recipe("large bottle flask", /obj/item/glasswork/glass_base/flask_large, 15), \
)), \
))
/obj/item/stack/sheet/glass
@@ -26,6 +34,7 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
grind_results = list(/datum/reagent/silicon = 20)
point_value = 1
tableVariant = /obj/structure/table/glass
shard_type = /obj/item/shard
/obj/item/stack/sheet/glass/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins to slice [user.p_their()] neck with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
@@ -93,6 +102,7 @@ GLOBAL_LIST_INIT(pglass_recipes, list ( \
merge_type = /obj/item/stack/sheet/plasmaglass
grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/toxin/plasma = 10)
tableVariant = /obj/structure/table/plasmaglass
shard_type = /obj/item/shard/plasma
/obj/item/stack/sheet/plasmaglass/fifty
amount = 50
@@ -120,7 +130,9 @@ GLOBAL_LIST_INIT(pglass_recipes, list ( \
else
return ..()
/obj/item/stack/sheet/plasmaglass/on_solar_construction(obj/machinery/power/solar/S)
S.obj_integrity *= 1.2
S.efficiency *= 1.2
/*
* Reinforced glass sheets
@@ -145,11 +157,15 @@ 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
shard_type = /obj/item/shard
/obj/item/stack/sheet/rglass/attackby(obj/item/W, mob/user, params)
add_fingerprint(user)
..()
/obj/item/stack/sheet/rglass/on_solar_construction(obj/machinery/power/solar/S)
S.obj_integrity *= 2
/obj/item/stack/sheet/rglass/cyborg
materials = list()
var/datum/robot_energy_storage/glasource
@@ -188,6 +204,11 @@ 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
shard_type = /obj/item/shard/plasma
/obj/item/stack/sheet/plasmarglass/on_solar_construction(obj/machinery/power/solar/S)
S.obj_integrity *= 2.2
S.efficiency *= 1.2
/obj/item/stack/sheet/plasmarglass/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.prglass_recipes
@@ -207,6 +228,11 @@ GLOBAL_LIST_INIT(titaniumglass_recipes, list(
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 100)
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/titaniumglass
shard_type = /obj/item/shard
/obj/item/stack/sheet/titaniumglass/on_solar_construction(obj/machinery/power/solar/S)
S.obj_integrity *= 2.5
S.efficiency *= 1.5
/obj/item/stack/sheet/titaniumglass/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.titaniumglass_recipes
@@ -226,11 +252,16 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 100)
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/plastitaniumglass
shard_type = /obj/item/shard
/obj/item/stack/sheet/plastitaniumglass/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.plastitaniumglass_recipes
return ..()
/obj/item/stack/sheet/titaniumglass/on_solar_construction(obj/machinery/power/solar/S)
S.obj_integrity *= 2
S.efficiency *= 2
/obj/item/shard
name = "shard"
desc = "A nasty looking shard of glass."
@@ -154,6 +154,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
GLOBAL_LIST_INIT(plasteel_recipes, list ( \
new/datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = TRUE), \
new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 50), \
new/datum/stack_recipe("crate", /obj/structure/closet/crate, 5, time = 90, one_per_turf = TRUE), \
null, \
new /datum/stack_recipe_list("airlock assemblies", list( \
new/datum/stack_recipe("high security airlock assembly", /obj/structure/door_assembly/door_assembly_highsecurity, 6, time = 50, one_per_turf = 1, on_floor = 1), \
@@ -277,6 +278,9 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
recipes = GLOB.wood_recipes
return ..()
/obj/item/stack/sheet/mineral/wood/twenty
amount = 20
/obj/item/stack/sheet/mineral/wood/fifty
amount = 50
@@ -306,6 +310,15 @@ GLOBAL_LIST_INIT(bamboo_recipes, list ( \
recipes = GLOB.bamboo_recipes
return ..()
/obj/item/stack/sheet/mineral/bamboo/ten
amount = 10
/obj/item/stack/sheet/mineral/bamboo/twenty
amount = 20
/obj/item/stack/sheet/mineral/bamboo/fifty
amount = 50
/*
* Cloth
*/
@@ -782,3 +795,4 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra
merge_type = /obj/item/stack/sheet/cotton/durathread
pull_effort = 70
loom_result = /obj/item/stack/sheet/durathread
@@ -15,4 +15,15 @@
var/point_value = 0 //turn-in value for the gulag stacker - loosely relative to its rarity
var/is_fabric = FALSE //is this a valid material for the loom?
var/loom_result //result from pulling on the loom
var/pull_effort = 0 //amount of delay when pulling on the loom
var/pull_effort = 0 //amount of delay when pulling on the loom
var/shard_type // the shard debris typepath left over by solar panels and windows etc.
/**
* Called on the glass sheet upon solar construction (duh):
* Different glass sheets can modify different stas/vars, such as obj_integrity or efficiency
* and possibly extra effects if you wish to code them.
* Keep in mind the solars' max_integrity is set equal to the obj_integrity later,
* so you won't have to do so here.
*/
/obj/item/stack/sheet/proc/on_solar_construction(/obj/machinery/power/solar/S)
return
+9 -6
View File
@@ -342,7 +342,7 @@
merge(o)
. = ..()
/obj/item/stack/hitby(atom/movable/AM, skip, hitpush)
/obj/item/stack/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
if(istype(AM, merge_type))
merge(AM)
. = ..()
@@ -399,11 +399,14 @@
. = ..()
/obj/item/stack/proc/copy_evidences(obj/item/stack/from)
blood_DNA = from.blood_DNA
fingerprints = from.fingerprints
fingerprintshidden = from.fingerprintshidden
fingerprintslast = from.fingerprintslast
//TODO bloody overlay
if(from.blood_DNA)
blood_DNA = from.blood_DNA.Copy()
if(from.fingerprints)
fingerprints = from.fingerprints.Copy()
if(from.fingerprintshidden)
fingerprintshidden = from.fingerprintshidden.Copy()
if(from.fingerprintslast)
fingerprintslast = from.fingerprintslast
/obj/item/stack/microwave_act(obj/machinery/microwave/M)
if(istype(M) && M.dirty < 100)
@@ -233,39 +233,111 @@
turf_type = /turf/open/floor/carpet/royalblue
tableVariant = /obj/structure/table/wood/fancy/royalblue
/obj/item/stack/tile/carpet/ten
amount = 10
/obj/item/stack/tile/carpet/twenty
amount = 20
/obj/item/stack/tile/carpet/fifty
amount = 50
/obj/item/stack/tile/carpet/black/ten
amount = 10
/obj/item/stack/tile/carpet/black/twenty
amount = 20
/obj/item/stack/tile/carpet/black/fifty
amount = 50
/obj/item/stack/tile/carpet/blackred/ten
amount = 10
/obj/item/stack/tile/carpet/blackred/twenty
amount = 20
/obj/item/stack/tile/carpet/blackred/fifty
amount = 50
/obj/item/stack/tile/carpet/monochrome/ten
amount = 10
/obj/item/stack/tile/carpet/monochrome/twenty
amount = 20
/obj/item/stack/tile/carpet/monochrome/fifty
amount = 50
/obj/item/stack/tile/carpet/blue/ten
amount = 10
/obj/item/stack/tile/carpet/blue/twenty
amount = 20
/obj/item/stack/tile/carpet/blue/fifty
amount = 50
/obj/item/stack/tile/carpet/cyan/ten
amount = 10
/obj/item/stack/tile/carpet/cyan/twenty
amount = 20
/obj/item/stack/tile/carpet/cyan/fifty
amount = 50
/obj/item/stack/tile/carpet/green/ten
amount = 10
/obj/item/stack/tile/carpet/green/twenty
amount = 20
/obj/item/stack/tile/carpet/green/fifty
amount = 50
/obj/item/stack/tile/carpet/orange/ten
amount = 10
/obj/item/stack/tile/carpet/orange/twenty
amount = 20
/obj/item/stack/tile/carpet/orange/fifty
amount = 50
/obj/item/stack/tile/carpet/purple/ten
amount = 10
/obj/item/stack/tile/carpet/purple/twenty
amount = 20
/obj/item/stack/tile/carpet/purple/fifty
amount = 50
/obj/item/stack/tile/carpet/red/ten
amount = 10
/obj/item/stack/tile/carpet/red/twenty
amount = 20
/obj/item/stack/tile/carpet/red/fifty
amount = 50
/obj/item/stack/tile/carpet/royalblack/ten
amount = 10
/obj/item/stack/tile/carpet/royalblack/twenty
amount = 20
/obj/item/stack/tile/carpet/royalblack/fifty
amount = 50
/obj/item/stack/tile/carpet/royalblue/ten
amount = 10
/obj/item/stack/tile/carpet/royalblue/twenty
amount = 20
/obj/item/stack/tile/carpet/royalblue/fifty
amount = 50
+21 -1
View File
@@ -322,6 +322,26 @@
for(var/i in 1 to 5)
new /obj/item/grenade/empgrenade(src)
/obj/item/storage/box/minibombs
name = "box of syndicate minibombs"
desc = "A box containing 2 highly explosive syndicate minibombs."
icon_state = "syndiebox"
illustration = "frag"
/obj/item/storage/box/minibombs/PopulateContents()
new /obj/item/grenade/syndieminibomb(src)
new /obj/item/grenade/syndieminibomb(src)
/obj/item/storage/box/bombananas
name = "box of bombananas"
desc = "A box containing 2 highly explosive bombananas. Discard peel at enemy after consumption."
icon_state = "syndiebox"
illustration = "frag"
/obj/item/storage/box/bombananas/PopulateContents()
new /obj/item/reagent_containers/food/snacks/grown/banana/bombanana(src)
new /obj/item/reagent_containers/food/snacks/grown/banana/bombanana(src)
/obj/item/storage/box/trackimp
name = "boxed tracking implant kit"
desc = "Box full of scum-bag tracking utensils."
@@ -1267,4 +1287,4 @@
/obj/item/storage/box/marshmallow/PopulateContents()
for (var/i in 1 to 5)
new /obj/item/reagent_containers/food/snacks/marshmallow(src)
new /obj/item/reagent_containers/food/snacks/marshmallow(src)
+31
View File
@@ -12,6 +12,7 @@
* Cigarette Box
* Cigar Case
* Heart Shaped Box w/ Chocolates
* Ring Box
*/
/obj/item/storage/fancy
@@ -352,3 +353,33 @@
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 8
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/tinychocolate))
/*
* Ring Box
*/
/obj/item/storage/fancy/ringbox
name = "ring box"
desc = "A tiny box covered in soft red felt made for holding rings."
icon = 'icons/obj/ring.dmi'
icon_state = "gold ringbox"
icon_type = "gold ring"
w_class = WEIGHT_CLASS_TINY
spawn_type = /obj/item/clothing/gloves/ring
/obj/item/storage/fancy/ringbox/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 1
STR.can_hold = typecacheof(list(/obj/item/clothing/gloves/ring))
/obj/item/storage/fancy/ringbox/diamond
icon_state = "diamond ringbox"
icon_type = "diamond ring"
spawn_type = /obj/item/clothing/gloves/ring/diamond
/obj/item/storage/fancy/ringbox/silver
icon_state = "silver ringbox"
icon_type = "silver ring"
spawn_type = /obj/item/clothing/gloves/ring/silver
+5 -9
View File
@@ -35,7 +35,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/storage/toolbox/update_icon()
..()
cut_overlays()
if(blood_DNA && blood_DNA.len)
if(length(blood_DNA))
add_blood_overlay()
if(has_latches)
var/icon/I = icon('icons/obj/storage.dmi', latches)
@@ -251,16 +251,12 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
new /obj/item/ammo_box/a762(src)
new /obj/item/ammo_box/a762(src)
/obj/item/storage/toolbox/gold_real
/obj/item/storage/toolbox/plastitanium/gold_real
name = "golden toolbox"
desc = "A larger then normal toolbox made of gold plated plastitanium."
icon_state = "gold"
item_state = "toolbox_gold"
has_latches = FALSE
force = 16 // Less then a spear
throwforce = 14
throw_speed = 5
throw_range = 10
/obj/item/storage/toolbox/gold_real/PopulateContents()
new /obj/item/screwdriver/nuke(src)
@@ -293,7 +289,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
desc = replacetext(desc, "robust", "safe")
desc = replacetext(desc, "heavier", "bouncier")
DISABLE_BITFIELD(flags_1, CONDUCT_1)
materials = null
materials = typelist("materials", null)
damtype = STAMINA
force += 3 //to compensate the higher stamina K.O. threshold compared to actual health.
throwforce += 3
@@ -317,8 +313,8 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
flags_1 = null
materials = null
damtype = STAMINA
force = 17
throwforce = 17
force = 15
throwforce = 15
attack_verb = list("robusted", "bounced")
can_rubberify = FALSE //we are already the future.
@@ -343,7 +343,7 @@
new /obj/item/implanter/radio/syndicate(src)
/obj/item/storage/box/syndie_kit/centcom_costume/PopulateContents()
new /obj/item/clothing/under/rank/centcom_officer(src)
new /obj/item/clothing/under/rank/centcom_officer/syndicate(src)
new /obj/item/clothing/shoes/sneakers/black(src)
new /obj/item/clothing/gloves/color/black(src)
new /obj/item/radio/headset/headset_cent/empty(src)
+1 -1
View File
@@ -41,7 +41,7 @@
cell = new preload_cell_type(src)
update_icon()
/obj/item/melee/baton/throw_impact(atom/hit_atom)
/obj/item/melee/baton/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
..()
//Only mob/living types have stun handling
if(status && prob(throw_hit_chance) && iscarbon(hit_atom))
+1 -1
View File
@@ -156,7 +156,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "tanks", name, 420, 200, master_ui, state)
ui = new(user, src, ui_key, "tanks", name, 400, 120, master_ui, state)
ui.open()
/obj/item/tank/ui_data(mob/user)
+1 -1
View File
@@ -259,7 +259,7 @@
if(proximity && ismovableatom(O) && O != sliver)
Consume(O, user)
/obj/item/hemostat/supermatter/throw_impact(atom/hit_atom) // no instakill supermatter javelins
/obj/item/hemostat/supermatter/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) // no instakill supermatter javelins
if(sliver)
sliver.forceMove(loc)
to_chat(usr, "<span class='notice'>\The [sliver] falls out of \the [src] as you throw them.</span>")
+5 -5
View File
@@ -84,7 +84,7 @@
else
return ..()
/obj/item/toy/balloon/throw_impact(atom/hit_atom)
/obj/item/toy/balloon/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(!..()) //was it caught by a mob?
balloon_burst(hit_atom)
@@ -531,7 +531,7 @@
/obj/item/toy/snappop/fire_act(exposed_temperature, exposed_volume)
pop_burst()
/obj/item/toy/snappop/throw_impact(atom/hit_atom)
/obj/item/toy/snappop/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(!..())
pop_burst()
@@ -1152,7 +1152,7 @@
icon_state = "minimeteor"
w_class = WEIGHT_CLASS_SMALL
/obj/item/toy/minimeteor/throw_impact(atom/hit_atom)
/obj/item/toy/minimeteor/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(!..())
playsound(src, 'sound/effects/meteorimpact.ogg', 40, 1)
for(var/mob/M in urange(10, src))
@@ -1201,7 +1201,7 @@
if(user.dropItemToGround(src))
throw_at(target, throw_range, throw_speed)
/obj/item/toy/snowball/throw_impact(atom/hit_atom)
/obj/item/toy/snowball/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(!..())
playsound(src, 'sound/effects/pop.ogg', 20, 1)
qdel(src)
@@ -1244,7 +1244,7 @@
/obj/item/toy/clockwork_watch/examine(mob/user)
. = ..()
. += "<span class='info'>Station Time: [STATION_TIME_TIMESTAMP("hh:mm:ss")]"
. += "<span class='info'>Station Time: [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]"
/*
* Toy Dagger
+6 -7
View File
@@ -25,8 +25,8 @@
*/
/obj/item/twohanded
var/wielded = 0
var/force_unwielded = 0
var/force_wielded = 0
var/force_unwielded // default to null, the number force will be set to on unwield()
var/force_wielded // same as above but for wield()
var/wieldsound = null
var/unwieldsound = null
var/slowdown_wielded = 0
@@ -38,9 +38,9 @@
wielded = 0
if(!isnull(force_unwielded))
force = force_unwielded
var/sf = findtext(name," (Wielded)")
var/sf = findtext(name, " (Wielded)", -10)//10 == length(" (Wielded)")
if(sf)
name = copytext(name,1,sf)
name = copytext(name, 1, sf)
else //something wrong
name = "[initial(name)]"
update_icon()
@@ -73,7 +73,7 @@
to_chat(user, "<span class='warning'>You don't have enough intact hands.</span>")
return
wielded = 1
if(force_wielded)
if(!isnull(force_wielded))
force = force_wielded
name = "[name] (Wielded)"
update_icon()
@@ -347,7 +347,6 @@
icon_state = "dualsaber[item_color][wielded]"
else
icon_state = "dualsaber0"
clean_blood()
/obj/item/twohanded/dualsaber/attack(mob/target, mob/living/carbon/human/user)
@@ -738,7 +737,7 @@
on = !on
to_chat(user, "As you pull the starting cord dangling from [src], [on ? "it begins to whirr." : "the chain stops moving."]")
force = on ? force_on : initial(force)
throwforce = on ? force_on : initial(force)
throwforce = on ? force_on : force
icon_state = "chainsaw_[on ? "on" : "off"]"
var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
butchering.butchering_enabled = on
+29 -6
View File
@@ -312,23 +312,27 @@ 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)
if(extended)
force = 20
force = extended_force
w_class = WEIGHT_CLASS_NORMAL
throwforce = 23
icon_state = "switchblade_ext"
throwforce = extended_throwforce
icon_state = extended_icon_state
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP
else
force = 3
force = initial(force)
w_class = WEIGHT_CLASS_SMALL
throwforce = 5
icon_state = "switchblade"
throwforce = initial(throwforce)
icon_state = retracted_icon_state
attack_verb = list("stubbed", "poked")
hitsound = 'sound/weapons/genhit.ogg'
sharpness = IS_BLUNT
@@ -337,6 +341,25 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
user.visible_message("<span class='suicide'>[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return (BRUTELOSS)
/obj/item/switchblade/crafted
icon_state = "switchblade_ms"
desc = "A concealable spring-loaded knife."
force = 2
throwforce = 3
extended_force = 15
extended_throwforce = 18
extended_icon_state = "switchblade_ext_ms"
retracted_icon_state = "switchblade_ms"
/obj/item/switchblade/crafted/attackby(obj/item/I, mob/user, params)
. = ..()
if(istype(I, /obj/item/stack/sheet/mineral/silver))
icon_state = extended ? "switchblade_ext_msf" : "switchblade_msf"
extended_icon_state = "switchblade_ext_msf"
retracted_icon_state = "switchblade_msf"
icon_state = "switchblade_msf"
to_chat(user, "<span class='notice'>You use part of the silver to improve your Switchblade. Stylish!</span>")
/obj/item/phone
name = "red phone"
desc = "Should anything ever go wrong..."