mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 02:34:00 +00:00
Xenoarch Multitool & Xenoarch Excavation Drill (#5058)
* Xenoarch Multitool & Xenoarch Excavation Drill * Makes the tool work better * Cuts down on lines & left comments * change to m
This commit is contained in:
@@ -373,7 +373,9 @@
|
|||||||
/obj/item/weapon/storage/excavation,
|
/obj/item/weapon/storage/excavation,
|
||||||
/obj/item/weapon/anobattery,
|
/obj/item/weapon/anobattery,
|
||||||
/obj/item/device/ano_scanner,
|
/obj/item/device/ano_scanner,
|
||||||
/obj/item/weapon/pickaxe/hand
|
/obj/item/weapon/pickaxe/hand,
|
||||||
|
/obj/item/device/xenoarch_multi_tool,
|
||||||
|
/obj/item/weapon/pickaxe/excavationdrill
|
||||||
)
|
)
|
||||||
|
|
||||||
/obj/item/weapon/storage/belt/fannypack
|
/obj/item/weapon/storage/belt/fannypack
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ var/list/mining_overlay_cache = list()
|
|||||||
/turf/simulated/mineral/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
/turf/simulated/mineral/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||||
|
|
||||||
if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
|
if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
|
||||||
usr << "<span class='warning'>You don't have the dexterity to do this!</span>"
|
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
||||||
return
|
return
|
||||||
|
|
||||||
if(!density)
|
if(!density)
|
||||||
@@ -263,19 +263,19 @@ var/list/mining_overlay_cache = list()
|
|||||||
|
|
||||||
if(valid_tool)
|
if(valid_tool)
|
||||||
if (sand_dug)
|
if (sand_dug)
|
||||||
user << "<span class='warning'>This area has already been dug.</span>"
|
to_chat(user, "<span class='warning'>This area has already been dug.</span>")
|
||||||
return
|
return
|
||||||
|
|
||||||
var/turf/T = user.loc
|
var/turf/T = user.loc
|
||||||
if (!(istype(T)))
|
if (!(istype(T)))
|
||||||
return
|
return
|
||||||
|
|
||||||
user << "<span class='notice'>You start digging.</span>"
|
to_chat(user, "<span class='notice'>You start digging.</span>")
|
||||||
playsound(user.loc, 'sound/effects/rustle1.ogg', 50, 1)
|
playsound(user.loc, 'sound/effects/rustle1.ogg', 50, 1)
|
||||||
|
|
||||||
if(!do_after(user,40)) return
|
if(!do_after(user,40)) return
|
||||||
|
|
||||||
user << "<span class='notice'>You dug a hole.</span>"
|
to_chat(user, "<span class='notice'>You dug a hole.</span>")
|
||||||
GetDrilled()
|
GetDrilled()
|
||||||
|
|
||||||
else if(istype(W,/obj/item/weapon/storage/bag/ore))
|
else if(istype(W,/obj/item/weapon/storage/bag/ore))
|
||||||
@@ -298,7 +298,7 @@ var/list/mining_overlay_cache = list()
|
|||||||
return
|
return
|
||||||
var/obj/item/stack/rods/R = W
|
var/obj/item/stack/rods/R = W
|
||||||
if (R.use(1))
|
if (R.use(1))
|
||||||
user << "<span class='notice'>Constructing support lattice ...</span>"
|
to_chat(user, "<span class='notice'>Constructing support lattice ...</span>")
|
||||||
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
|
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
|
||||||
new /obj/structure/lattice(get_turf(src))
|
new /obj/structure/lattice(get_turf(src))
|
||||||
|
|
||||||
@@ -314,7 +314,7 @@ var/list/mining_overlay_cache = list()
|
|||||||
S.use(1)
|
S.use(1)
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
user << "<span class='warning'>The plating is going to need some support.</span>"
|
to_chat(user, "<span class='warning'>The plating is going to need some support.</span>")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
@@ -334,7 +334,17 @@ var/list/mining_overlay_cache = list()
|
|||||||
var/obj/item/device/measuring_tape/P = W
|
var/obj/item/device/measuring_tape/P = W
|
||||||
user.visible_message("<span class='notice'>\The [user] extends \a [P] towards \the [src].</span>","<span class='notice'>You extend \the [P] towards \the [src].</span>")
|
user.visible_message("<span class='notice'>\The [user] extends \a [P] towards \the [src].</span>","<span class='notice'>You extend \the [P] towards \the [src].</span>")
|
||||||
if(do_after(user, 15))
|
if(do_after(user, 15))
|
||||||
user << "<span class='notice'>\The [src] has been excavated to a depth of [excavation_level]cm.</span>"
|
to_chat(user, "<span class='notice'>\The [src] has been excavated to a depth of [excavation_level]cm.</span>")
|
||||||
|
return
|
||||||
|
|
||||||
|
if(istype(W, /obj/item/device/xenoarch_multi_tool))
|
||||||
|
var/obj/item/device/xenoarch_multi_tool/C = W
|
||||||
|
if(C.mode) //Mode means scanning
|
||||||
|
C.depth_scanner.scan_atom(user, src)
|
||||||
|
else
|
||||||
|
user.visible_message("<span class='notice'>\The [user] extends \the [C] over \the [src], a flurry of red beams scanning \the [src]'s surface!</span>", "<span class='notice'>You extend \the [C] over \the [src], a flurry of red beams scanning \the [src]'s surface!</span>")
|
||||||
|
if(do_after(user, 15))
|
||||||
|
to_chat(user, "<span class='notice'>\The [src] has been excavated to a depth of [excavation_level]cm.</span>")
|
||||||
return
|
return
|
||||||
|
|
||||||
if (istype(W, /obj/item/weapon/pickaxe))
|
if (istype(W, /obj/item/weapon/pickaxe))
|
||||||
@@ -356,7 +366,7 @@ var/list/mining_overlay_cache = list()
|
|||||||
if(newDepth > F.excavation_required) // Digging too deep can break the item. At least you won't summon a Balrog (probably)
|
if(newDepth > F.excavation_required) // Digging too deep can break the item. At least you won't summon a Balrog (probably)
|
||||||
fail_message = ". <b>[pick("There is a crunching noise","[W] collides with some different rock","Part of the rock face crumbles away","Something breaks under [W]")]</b>"
|
fail_message = ". <b>[pick("There is a crunching noise","[W] collides with some different rock","Part of the rock face crumbles away","Something breaks under [W]")]</b>"
|
||||||
|
|
||||||
user << "<span class='notice'>You start [P.drill_verb][fail_message].</span>"
|
to_chat(user, "<span class='notice'>You start [P.drill_verb][fail_message].</span>")
|
||||||
|
|
||||||
if(fail_message && prob(90))
|
if(fail_message && prob(90))
|
||||||
if(prob(25))
|
if(prob(25))
|
||||||
@@ -375,7 +385,7 @@ var/list/mining_overlay_cache = list()
|
|||||||
else if(newDepth > F.excavation_required - F.clearance_range) // Not quite right but you still extract your find, the closer to the bottom the better, but not above 80%
|
else if(newDepth > F.excavation_required - F.clearance_range) // Not quite right but you still extract your find, the closer to the bottom the better, but not above 80%
|
||||||
excavate_find(prob(80 * (F.excavation_required - newDepth) / F.clearance_range), F)
|
excavate_find(prob(80 * (F.excavation_required - newDepth) / F.clearance_range), F)
|
||||||
|
|
||||||
user << "<span class='notice'>You finish [P.drill_verb] \the [src].</span>"
|
to_chat(user, "<span class='notice'>You finish [P.drill_verb] \the [src].</span>")
|
||||||
|
|
||||||
if(newDepth >= 200) // This means the rock is mined out fully
|
if(newDepth >= 200) // This means the rock is mined out fully
|
||||||
var/obj/structure/boulder/B
|
var/obj/structure/boulder/B
|
||||||
@@ -480,7 +490,7 @@ var/list/mining_overlay_cache = list()
|
|||||||
if(prob(50))
|
if(prob(50))
|
||||||
pain = 1
|
pain = 1
|
||||||
for(var/mob/living/M in range(src, 200))
|
for(var/mob/living/M in range(src, 200))
|
||||||
M << "<span class='danger'>[pick("A high-pitched [pick("keening","wailing","whistle")]","A rumbling noise like [pick("thunder","heavy machinery")]")] somehow penetrates your mind before fading away!</span>"
|
to_chat(M, "<span class='danger'>[pick("A high-pitched [pick("keening","wailing","whistle")]","A rumbling noise like [pick("thunder","heavy machinery")]")] somehow penetrates your mind before fading away!</span>")
|
||||||
if(pain)
|
if(pain)
|
||||||
flick("pain",M.pain)
|
flick("pain",M.pain)
|
||||||
if(prob(50))
|
if(prob(50))
|
||||||
|
|||||||
@@ -1802,6 +1802,22 @@ CIRCUITS BELOW
|
|||||||
build_path = /obj/item/device/universal_translator/ear
|
build_path = /obj/item/device/universal_translator/ear
|
||||||
sort_string = "HABQB"
|
sort_string = "HABQB"
|
||||||
|
|
||||||
|
/datum/design/obj/item/device/xenoarch_multi_tool
|
||||||
|
name = "xenoarcheology multitool"
|
||||||
|
id = "xenoarch_multitool"
|
||||||
|
req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 3, TECH_BLUESPACE = 3)
|
||||||
|
build_path = /obj/item/device/xenoarch_multi_tool
|
||||||
|
materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "uranium" = 500, "phoron" = 500)
|
||||||
|
sort_string = "HABQC"
|
||||||
|
|
||||||
|
/datum/design/excavationdrill
|
||||||
|
name = "Excavation Drill"
|
||||||
|
id = "excavationdrill"
|
||||||
|
req_tech = list(TECH_MATERIAL = 3, TECH_POWER = 2, TECH_ENGINEERING = 2, TECH_BLUESPACE = 3)
|
||||||
|
build_type = PROTOLATHE
|
||||||
|
materials = list(DEFAULT_WALL_MATERIAL = 4000, "glass" = 4000)
|
||||||
|
build_path = /obj/item/weapon/pickaxe/excavationdrill
|
||||||
|
|
||||||
/* Uncomment if someone makes these buildable
|
/* Uncomment if someone makes these buildable
|
||||||
/datum/design/circuit/general_alert
|
/datum/design/circuit/general_alert
|
||||||
name = "general alert console"
|
name = "general alert console"
|
||||||
|
|||||||
@@ -29,11 +29,22 @@
|
|||||||
C.scan_atom(user, src)
|
C.scan_atom(user, src)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if(istype(I, /obj/item/device/xenoarch_multi_tool))
|
||||||
|
var/obj/item/device/xenoarch_multi_tool/C = I
|
||||||
|
if(C.mode) //Mode means scanning.
|
||||||
|
C.depth_scanner.scan_atom(user, src)
|
||||||
|
return
|
||||||
|
else
|
||||||
|
user.visible_message("<span class='notice'>\The [user] extends \the [C] over \the [src], a flurry of red beams scanning \the [src]'s surface!</span>", "<span class='notice'>You extend \the [C] over \the [src], a flurry of red beams scanning \the [src]'s surface!</span>")
|
||||||
|
if(do_after(user, 15))
|
||||||
|
to_chat(user, "<span class='notice'>\The [src] has been excavated to a depth of [2 * src.excavation_level]cm.</span>")
|
||||||
|
return
|
||||||
|
|
||||||
if(istype(I, /obj/item/device/measuring_tape))
|
if(istype(I, /obj/item/device/measuring_tape))
|
||||||
var/obj/item/device/measuring_tape/P = I
|
var/obj/item/device/measuring_tape/P = I
|
||||||
user.visible_message("<span class='notice'>\The [user] extends \the [P] towards \the [src].</span>", "<span class='notice'>You extend \the [P] towards \the [src].</span>")
|
user.visible_message("<span class='notice'>\The [user] extends \the [P] towards \the [src].</span>", "<span class='notice'>You extend \the [P] towards \the [src].</span>")
|
||||||
if(do_after(user, 15))
|
if(do_after(user, 15))
|
||||||
user << "<span class='notice'>\The [src] has been excavated to a depth of [2 * src.excavation_level]cm.</span>"
|
to_chat(user, "<span class='notice'>\The [src] has been excavated to a depth of [2 * src.excavation_level]cm.</span>")
|
||||||
return
|
return
|
||||||
|
|
||||||
if(istype(I, /obj/item/weapon/pickaxe))
|
if(istype(I, /obj/item/weapon/pickaxe))
|
||||||
@@ -43,12 +54,12 @@
|
|||||||
return
|
return
|
||||||
last_act = world.time
|
last_act = world.time
|
||||||
|
|
||||||
user << "<span class='warning'>You start [P.drill_verb] [src].</span>"
|
to_chat(user, "<span class='warning'>You start [P.drill_verb] [src].</span>")
|
||||||
|
|
||||||
if(!do_after(user, P.digspeed))
|
if(!do_after(user, P.digspeed))
|
||||||
return
|
return
|
||||||
|
|
||||||
user << "<span class='notice'>You finish [P.drill_verb] [src].</span>"
|
to_chat(user, "<span class='notice'>You finish [P.drill_verb] [src].</span>")
|
||||||
excavation_level += P.excavation_amount
|
excavation_level += P.excavation_amount
|
||||||
|
|
||||||
if(excavation_level > 100)
|
if(excavation_level > 100)
|
||||||
|
|||||||
@@ -80,13 +80,13 @@
|
|||||||
SSxenoarch.digsite_spawning_turfs.Remove(T)
|
SSxenoarch.digsite_spawning_turfs.Remove(T)
|
||||||
|
|
||||||
if(nearestTargetDist >= 0)
|
if(nearestTargetDist >= 0)
|
||||||
user << "Exotic energy detected on wavelength '[nearestTargetId]' in a radius of [nearestTargetDist]m[nearestSimpleTargetDist > 0 ? "; small anomaly detected in a radius of [nearestSimpleTargetDist]m" : ""]"
|
to_chat(user, "Exotic energy detected on wavelength '[nearestTargetId]' in a radius of [nearestTargetDist]m[nearestSimpleTargetDist > 0 ? "; small anomaly detected in a radius of [nearestSimpleTargetDist]m" : ""]")
|
||||||
else if(nearestSimpleTargetDist >= 0)
|
else if(nearestSimpleTargetDist >= 0)
|
||||||
user << "Small anomaly detected in a radius of [nearestSimpleTargetDist]m."
|
to_chat(user, "Small anomaly detected in a radius of [nearestSimpleTargetDist]m.")
|
||||||
else
|
else
|
||||||
user << "Background radiation levels detected."
|
to_chat(user, "Background radiation levels detected.")
|
||||||
else
|
else
|
||||||
user << "Scanning array is recharging."
|
to_chat(user, "Scanning array is recharging.")
|
||||||
|
|
||||||
/obj/item/device/depth_scanner
|
/obj/item/device/depth_scanner
|
||||||
name = "depth analysis scanner"
|
name = "depth analysis scanner"
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
|
|
||||||
positive_locations.Add(D)
|
positive_locations.Add(D)
|
||||||
|
|
||||||
user << "<span class='notice'>\icon[src] [src] pings.</span>"
|
to_chat(user, "<span class='notice'>\icon[src] [src] pings.</span>")
|
||||||
|
|
||||||
else if(istype(A, /obj/structure/boulder))
|
else if(istype(A, /obj/structure/boulder))
|
||||||
var/obj/structure/boulder/B = A
|
var/obj/structure/boulder/B = A
|
||||||
@@ -151,7 +151,7 @@
|
|||||||
|
|
||||||
positive_locations.Add(D)
|
positive_locations.Add(D)
|
||||||
|
|
||||||
user << "<span class='notice'>\icon[src] [src] pings [pick("madly","wildly","excitedly","crazily")]!</span>"
|
to_chat(user, "<span class='notice'>\icon[src] [src] pings [pick("madly","wildly","excitedly","crazily")]!</span>")
|
||||||
|
|
||||||
/obj/item/device/depth_scanner/attack_self(var/mob/living/user)
|
/obj/item/device/depth_scanner/attack_self(var/mob/living/user)
|
||||||
interact(user)
|
interact(user)
|
||||||
@@ -310,3 +310,39 @@
|
|||||||
usr << browse(null, "window=locater")
|
usr << browse(null, "window=locater")
|
||||||
|
|
||||||
updateSelfDialog()
|
updateSelfDialog()
|
||||||
|
|
||||||
|
/obj/item/device/xenoarch_multi_tool
|
||||||
|
name = "xenoarcheology multitool"
|
||||||
|
desc = "Has the features of the Alden-Saraspova counter, a measuring tape, and a depth analysis scanner all in one!"
|
||||||
|
icon_state = "ano_scanner2"
|
||||||
|
item_state = "lampgreen"
|
||||||
|
icon = 'icons/obj/xenoarchaeology.dmi'
|
||||||
|
origin_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 3, TECH_BLUESPACE = 2)
|
||||||
|
matter = list(DEFAULT_WALL_MATERIAL = 10000,"glass" = 5000)
|
||||||
|
w_class = ITEMSIZE_SMALL
|
||||||
|
slot_flags = SLOT_BELT
|
||||||
|
var/mode = 1 //Start off scanning. 1 = scanning, 0 = measuring
|
||||||
|
var/obj/item/device/ano_scanner/anomaly_scanner = null
|
||||||
|
var/obj/item/device/depth_scanner/depth_scanner = null
|
||||||
|
|
||||||
|
/obj/item/device/xenoarch_multi_tool/New()
|
||||||
|
anomaly_scanner = new/obj/item/device/ano_scanner(src)
|
||||||
|
depth_scanner = new/obj/item/device/depth_scanner(src)
|
||||||
|
|
||||||
|
/obj/item/device/xenoarch_multi_tool/attack_self(var/mob/living/user)
|
||||||
|
depth_scanner.interact(user)
|
||||||
|
|
||||||
|
/obj/item/device/xenoarch_multi_tool/verb/swap_settings(var/mob/living/user)
|
||||||
|
set name = "Swap Functionality"
|
||||||
|
set desc = "Swap between the scanning and measuring functionality.."
|
||||||
|
mode = !mode
|
||||||
|
if(mode)
|
||||||
|
to_chat(user, "The device will now scan for artifacts.")
|
||||||
|
else
|
||||||
|
to_chat(user, "The device will now measure depth dug.")
|
||||||
|
|
||||||
|
/obj/item/device/xenoarch_multi_tool/verb/scan_for_anomalies(var/mob/living/user)
|
||||||
|
set name = "Scan for Anomalies"
|
||||||
|
set desc = "Scan for artifacts and anomalies within your vicinity."
|
||||||
|
anomaly_scanner.interact(user)
|
||||||
|
|
||||||
|
|||||||
@@ -149,3 +149,43 @@
|
|||||||
smallest.loc = src
|
smallest.loc = src
|
||||||
picksToSort -= smallest
|
picksToSort -= smallest
|
||||||
orient2hud()
|
orient2hud()
|
||||||
|
|
||||||
|
/obj/item/weapon/pickaxe/excavationdrill
|
||||||
|
name = "excavation drill"
|
||||||
|
icon = 'icons/obj/xenoarchaeology.dmi'
|
||||||
|
icon_state = "excavationdrill2"
|
||||||
|
item_state = "syringe_0"
|
||||||
|
excavation_amount = 15
|
||||||
|
digspeed = 30
|
||||||
|
desc = "Advanced archaeological drill combining ultrasonic excitation and bluespace manipulation to provide extreme precision. The tip is adjustable from 1 to 30 cm."
|
||||||
|
drill_sound = 'sound/weapons/thudswoosh.ogg'
|
||||||
|
drill_verb = "drilling"
|
||||||
|
force = 5
|
||||||
|
w_class = 2
|
||||||
|
attack_verb = list("drilled")
|
||||||
|
|
||||||
|
/obj/item/weapon/pickaxe/excavationdrill/attack_self(mob/user as mob)
|
||||||
|
var/depth = input("Put the desired depth (1-30 centimeters).", "Set Depth", 30) as num
|
||||||
|
if(depth>30 || depth<1)
|
||||||
|
to_chat(user, "<span class='notice'>Invalid depth.</span>")
|
||||||
|
return
|
||||||
|
excavation_amount = depth
|
||||||
|
to_chat(user, "<span class='notice'>You set the depth to [depth]cm.</span>")
|
||||||
|
switch(depth)
|
||||||
|
if(1 to 5)
|
||||||
|
icon_state = "excavationdrill0"
|
||||||
|
if(6 to 10)
|
||||||
|
icon_state = "excavationdrill1"
|
||||||
|
if(11 to 15)
|
||||||
|
icon_state = "excavationdrill2"
|
||||||
|
if(16 to 20)
|
||||||
|
icon_state = "excavationdrill3"
|
||||||
|
if(21 to 25)
|
||||||
|
icon_state = "excavationdrill4"
|
||||||
|
if(25 to 30)
|
||||||
|
icon_state = "excavationdrill5" //The other 2 sprites are comically long. Let's just cut it at 5.
|
||||||
|
|
||||||
|
/obj/item/weapon/pickaxe/excavationdrill/examine(mob/user)
|
||||||
|
..()
|
||||||
|
var/depth = excavation_amount
|
||||||
|
to_chat(user, "<span class='info'>It is currently set at [depth]cms.</span>")
|
||||||
37
html/changelogs/Cameron - Xenoarch Upgrades.yml
Normal file
37
html/changelogs/Cameron - Xenoarch Upgrades.yml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
################################
|
||||||
|
# Example Changelog File
|
||||||
|
#
|
||||||
|
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
|
||||||
|
#
|
||||||
|
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
|
||||||
|
# When it is, any changes listed below will disappear.
|
||||||
|
#
|
||||||
|
# Valid Prefixes:
|
||||||
|
# bugfix
|
||||||
|
# wip (For works in progress)
|
||||||
|
# tweak
|
||||||
|
# soundadd
|
||||||
|
# sounddel
|
||||||
|
# rscadd (general adding of nice things)
|
||||||
|
# rscdel (general deleting of nice things)
|
||||||
|
# imageadd
|
||||||
|
# imagedel
|
||||||
|
# maptweak
|
||||||
|
# spellcheck (typo fixes)
|
||||||
|
# experiment
|
||||||
|
#################################
|
||||||
|
|
||||||
|
# Your name.
|
||||||
|
author: Cameron653
|
||||||
|
|
||||||
|
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
|
||||||
|
delete-after: True
|
||||||
|
|
||||||
|
# Any changes you've made. See valid prefix list above.
|
||||||
|
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
|
||||||
|
# SCREW THIS UP AND IT WON'T WORK.
|
||||||
|
# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
|
||||||
|
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
|
||||||
|
changes:
|
||||||
|
- rscadd: "Adds a xenoarch excavation tool, craftable in R&D. Allows depth selection of 1-30"
|
||||||
|
- rscadd: "Adds a xenoarch multitool, craftable in R&D. Has xenoarch counter, measure tool, and depth scanner all in one."
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 68 KiB |
Reference in New Issue
Block a user