mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
AI Rework | 2024 edition (#21266)
* fix ui
* oops
* Fixes map bibby broke
* Revert "Fixes map bibby broke"
This reverts commit af1d1c610e.
* e
* Unfucks deltastation
* stuff
* cleans things after bibby
* Fix subcontroller cache
* Fixed APCs and air alarms not working when connected to a subcontroller
* bunch of fixes
* job icon
* tcomms server
Update traffic_control.dm
* make compile
* Update synthetic.dm
* Update synthetic.dm
* Update access.dm
* er
* le runtime
* Update ai_data_core.dm
* le dupe
* wall
* Update decentralized_ai.dm
* Update decentralized_ai.dm
* e
* Update wy_synths.dm
* we do a little trolling
* e
* small cahnges
* more minor changes
* Create conflict_fixer.dmm
* Create conflict_fixer - Kopi.dmm
* minor map cahnges
* broken maps
* oops
* bon
* Update ainetworkinterface.dm
* Update ainetworkinterface.dm
* Update ai.dm
* lol
* light
* fixes
* e
* Update synth_pod.dm
* e
* Update synth_os.dm
* Update objective.dm
* fixes
* Update synthetic.dm
* e
* antag
* tweaks
* e
* Update VRSleeper.js
* e
* Update synth_pod.dm
* Update synth_pod.dm
* 1
* Update synth_pod.dm
* Update synth_os.dm
* Update synthetic.dm
* fixes
* headset and ID go boom
* Update wy_synths.dm
* Update robot_parts.dm
* cremator
* Update communications.dm
* Update synthetic.dm
* no synth control
* Update synthetic.dm
* Update ai_dashboard.dm
* Update miscellaneous.dm
* Update miscellaneous.dm
* Update headset.dm
* Update damage_procs.dm
* Update server_cabinet.dm
* minor fixes
* Update miscellaneous.dm
* Update rack_creator.dm
* Update synthetic.dm
* compiles
* fixes
* brainless
* access request
* cofnlict
* fixes
* controller
* Update yogstation.dme
* Update yogstation.dme
* s
* maps
* Update NtosSynthManager.js
* unrevert this lol
* eat
* Update wy_synths.dm
* sigh
* e
* Update wy_synths.dm
* sigh
* fixed ma
* Update synthetic.dm
* better
* Update ethernet_cable.dm
* Update computer.dm
* Update computer.dm
* i hate this
* Update ai_laws.dm
* Update hardsuit.dm
* initialize
* sigh
* Update synth_os.dm
* Update master_subcontroller.dm
* Update master_subcontroller.dm
* Update synth_requester.dm
* Update synth_requester.dm
* Update room_lockdown.dm
* small fixes
* propa sprite matey
* no latejoin lol
* Update synth_os.dm
* maps fixed
* compiles
* Update brain_item.dm
* fixes
* mappers
* Update hud.dmi
* Update passworddoor.dm
* button puzzle
* mine stuff
* Update yogstation.dme
* le map
* changes
* ye
* Update abandoned_mine.dm
* Update _puzzles.dm
* bingus
* Update abandoned_mine.dm
* maps
* e
* no more quirks
* e
* DMI merge conflict resolver (from TG)
* update yogstation map
* Minor away mission changes
* forgot something
* proper fix
* donut
* maps
* asteroid
* gax
* all maps done
* Update synthetic.dm
* makes it compile
* Update backstabs.dm
* more compile!
* fix this map
* bad item
* remove broken objects
* gax
* Update ticker.dm
* pdas
* omg save the file
* Update networking_machines.dm
* area string moment
* s
* awkward
* revival
* Update ai_dashboard.dm
* fixes
* fixed floopy
* less difficult
* this is important
* Update ai_network.dm
* maps
* fixes the maps
* wHAT
* WHAT
* wet
* start fixing conflicts
* Update yogstation.dme
* start fixing map conflicts
* Update DonutStation.dmm
* updates
* donut conflicts
* update box
* Update IceMeta.dmm
* icon diffs
* Update crew.dm
* Update unsorted.dm
* Update layers.dm
* Update YogStation.dmm
* conflicts
* Update IceMeta.dmm
* will this finally fix it
* Update IceMeta.dmm
* fix all this SHIT
* what
* more shit ugh
* what!
* Update DonutStation.dmm
* Update AsteroidStation.dmm
* Update AsteroidStation.dmm
* Update dead.dm
* Update catwalk_plating.dm
* Update catwalk_plating.dm
---------
Co-authored-by: adamsong <adamsong@users.noreply.github.com>
Co-authored-by: wejengin2 <48154165+wejengin2@users.noreply.github.com>
Co-authored-by: Byemoh <baiomurang@gmail.com>
This commit is contained in:
@@ -79,3 +79,10 @@
|
||||
/obj/effect/decal/cleanable/oil/slippery/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/slippery, 80, (NO_SLIP_WHEN_WALKING | SLIDE))
|
||||
|
||||
/obj/effect/decal/cleanable/oil/synth
|
||||
name = "circulation fluid"
|
||||
desc = "It's a white and viscous fluid used by synthetic crewmembers."
|
||||
color = "#e6e6e6"
|
||||
icon_state = "synthfloor1"
|
||||
random_icon_states = list("synthfloor1", "synthfloor2", "synthfloor3", "synthfloor4", "synthfloor5", "synthfloor6", "synthfloor7")
|
||||
|
||||
@@ -193,6 +193,10 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark)
|
||||
name = "Cyborg"
|
||||
icon_state = "Cyborg"
|
||||
|
||||
/obj/effect/landmark/start/synthetic
|
||||
name = "Synthetic"
|
||||
icon_state = "Cyborg"
|
||||
|
||||
|
||||
//Department Security spawns
|
||||
|
||||
|
||||
@@ -713,7 +713,6 @@
|
||||
name = "secure AI circuit board spawner"
|
||||
loot = list(
|
||||
/obj/item/circuitboard/computer/aiupload,
|
||||
/obj/item/circuitboard/computer/ai_upload_download,
|
||||
/obj/item/circuitboard/computer/borgupload
|
||||
)
|
||||
|
||||
|
||||
@@ -561,6 +561,10 @@ update_label("John Doe", "Clowny")
|
||||
|
||||
name = "[(!registered_name) ? "identification card" : "[registered_name]'s ID Card"][(!assignment) ? "" : " ([assignment])"]"
|
||||
|
||||
//a card that can't register a bank account IC
|
||||
/obj/item/card/id/no_bank/AltClick(mob/living/user)
|
||||
return FALSE
|
||||
|
||||
/obj/item/card/id/silver
|
||||
name = "silver identification card"
|
||||
desc = "A silver card which shows honour and dedication."
|
||||
@@ -584,6 +588,27 @@ update_label("John Doe", "Clowny")
|
||||
lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi'
|
||||
|
||||
/obj/item/card/id/synthetic
|
||||
name = "synthetic identification card"
|
||||
desc = "An integrated card that allows synthetic units access across the station."
|
||||
icon_state = "id_silver"
|
||||
item_state = "silver_id"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi'
|
||||
item_flags = DROPDEL
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
|
||||
/obj/item/card/id/synthetic/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, SYNTHETIC_TRAIT)
|
||||
|
||||
/obj/item/card/id/synthetic/GetAccess()
|
||||
if(ishuman(loc))
|
||||
var/mob/living/carbon/human/H = loc
|
||||
if(H.mind)
|
||||
return GLOB.synthetic_base_access + GLOB.synthetic_added_access
|
||||
return list()
|
||||
|
||||
/obj/item/card/id/syndicate
|
||||
name = "agent card"
|
||||
access = list(ACCESS_MAINT_TUNNELS, ACCESS_SYNDICATE)
|
||||
|
||||
@@ -432,20 +432,12 @@
|
||||
name = "Shuttle Navigation Computer (Computer Board)"
|
||||
build_path = /obj/machinery/computer/camera_advanced/shuttle_docker/custom
|
||||
|
||||
/obj/item/circuitboard/computer/ai_upload_download
|
||||
name = "AI Control Console (Computer Board)"
|
||||
greyscale_colors = CIRCUIT_COLOR_SCIENCE
|
||||
build_path = /obj/machinery/computer/ai_control_console
|
||||
|
||||
/obj/item/circuitboard/computer/ai_server_overview
|
||||
name = "AI Server Overview Console (Computer Board)"
|
||||
greyscale_colors = CIRCUIT_COLOR_SCIENCE
|
||||
build_path = /obj/machinery/computer/ai_server_console
|
||||
|
||||
/obj/item/circuitboard/computer/ai_resource_distribution
|
||||
name = "AI Resource Distribution Console (Computer Board)"
|
||||
greyscale_colors = CIRCUIT_COLOR_SCIENCE
|
||||
build_path = /obj/machinery/computer/ai_resource_distribution
|
||||
|
||||
//Security
|
||||
|
||||
|
||||
@@ -163,6 +163,15 @@
|
||||
/obj/item/stack/cable_coil = 2,
|
||||
/obj/item/stock_parts/manipulator = 5)
|
||||
|
||||
/obj/item/circuitboard/machine/synth_pod
|
||||
name = "Synthetic Storage Unit (Machine Board)"
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/synth_pod
|
||||
req_components = list(
|
||||
/obj/item/stock_parts/micro_laser = 2,
|
||||
/obj/item/stack/cable_coil = 2,
|
||||
/obj/item/stock_parts/manipulator = 2)
|
||||
|
||||
/obj/item/circuitboard/machine/decontamination_unit
|
||||
name = "Decontamination Storage Unit (Machine Board)"
|
||||
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
|
||||
@@ -1084,6 +1093,27 @@
|
||||
/obj/item/stack/sheet/glass = 2,
|
||||
/obj/item/stack/cable_coil = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/networking_machine
|
||||
name = "Networking Machine (Machine Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/ai/networking
|
||||
req_components = list(
|
||||
/obj/item/stock_parts/matter_bin = 4,
|
||||
/obj/item/stock_parts/capacitor = 2,
|
||||
/obj/item/stock_parts/scanning_module = 4,
|
||||
/obj/item/stack/sheet/glass = 4,
|
||||
/obj/item/stack/cable_coil = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/subcontroller
|
||||
name = "Subcontroller (Machine Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/ai/master_subcontroller
|
||||
req_components = list(
|
||||
/obj/item/stock_parts/capacitor = 4,
|
||||
/obj/item/stock_parts/scanning_module = 4,
|
||||
/obj/item/stack/sheet/glass = 2,
|
||||
/obj/item/stack/cable_coil = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/ai_core_display
|
||||
name = "AI Core Display (Machine Board)"
|
||||
greyscale_colors = CIRCUIT_COLOR_SCIENCE
|
||||
|
||||
@@ -124,6 +124,17 @@
|
||||
icon_state = "srv_cypherkey"
|
||||
channels = list(RADIO_CHANNEL_SERVICE = 1)
|
||||
|
||||
/obj/item/encryptionkey/headset_synthetic
|
||||
name = "synthetic radio encryption key"
|
||||
icon_state = "rd_cypherkey"
|
||||
channels = list(RADIO_CHANNEL_COMMAND = 1, RADIO_CHANNEL_ENGINEERING = 1, RADIO_CHANNEL_SCIENCE = 1, RADIO_CHANNEL_MEDICAL = 1, RADIO_CHANNEL_SUPPLY = 1, RADIO_CHANNEL_SERVICE = 1)
|
||||
translate_binary = TRUE
|
||||
item_flags = DROPDEL
|
||||
|
||||
/obj/item/encryptionkey/headset_synthetic/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, SYNTHETIC_TRAIT)
|
||||
|
||||
/obj/item/encryptionkey/headset_cent
|
||||
name = "\improper CentCom radio encryption key"
|
||||
icon_state = "cent_cypherkey"
|
||||
|
||||
@@ -204,6 +204,23 @@
|
||||
icon_state = "srv_headset"
|
||||
keyslot = new /obj/item/encryptionkey/headset_service
|
||||
|
||||
/obj/item/radio/headset/headset_synthetic
|
||||
name = "synthetic radio headset"
|
||||
desc = "Headset used by the onboard synthetic units. This one is integrated directly into the unit and is not possible to remove."
|
||||
icon_state = "com_headset"
|
||||
keyslot = new /obj/item/encryptionkey/headset_synthetic
|
||||
item_flags = DROPDEL
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
|
||||
/obj/item/radio/headset/headset_synthetic/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, SYNTHETIC_TRAIT)
|
||||
ADD_TRAIT(src, TRAIT_EMPPROOF_CONTENTS, SYNTHETIC_TRAIT)
|
||||
ADD_TRAIT(src, TRAIT_EMPPROOF_SELF, SYNTHETIC_TRAIT)
|
||||
|
||||
/obj/item/radio/headset/headset_synthetic/attackby(obj/item/W, mob/user, params)
|
||||
return FALSE
|
||||
|
||||
/obj/item/radio/headset/headset_cent
|
||||
name = "\improper CentCom headset"
|
||||
desc = "A headset used by the upper echelons of Nanotrasen."
|
||||
|
||||
@@ -58,6 +58,9 @@
|
||||
/obj/item/grenade/attack_self(mob/user)
|
||||
if(!active)
|
||||
if(clown_check(user))
|
||||
if(HAS_TRAIT(user, TRAIT_NO_GRENADES))
|
||||
to_chat(user, span_warning("You can't use grenades!"))
|
||||
return
|
||||
preprime(user)
|
||||
|
||||
/obj/item/grenade/proc/log_grenade(mob/user, turf/T)
|
||||
|
||||
@@ -240,6 +240,8 @@
|
||||
var/datum/job/this_job = SSjob.GetJob(human.mind.assigned_role)
|
||||
if(!this_job || this_job.faction != "Station")
|
||||
continue
|
||||
if(is_synth(human))
|
||||
continue
|
||||
|
||||
mail_recipients += human.mind
|
||||
|
||||
|
||||
@@ -327,7 +327,8 @@
|
||||
/obj/item/melee/classic_baton/attack(mob/living/target, mob/living/user)
|
||||
if(!on)
|
||||
return ..()
|
||||
|
||||
if(!synth_check(user, SYNTH_RESTRICTED_WEAPON))
|
||||
return
|
||||
if(HAS_TRAIT(user, TRAIT_NO_STUN_WEAPONS))
|
||||
to_chat(user, span_warning("You can't seem to remember how this works!"))
|
||||
return
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/robot_suit/examine(mob/user)
|
||||
. = ..()
|
||||
. += "If you insert an AI CPU when this endoskeleton is complete it will be constructed as a synthetic."
|
||||
|
||||
/obj/item/robot_suit/wrench_act(mob/living/user, obj/item/I) //Deconstucts empty borg shell. Flashes remain unbroken because they haven't been used yet
|
||||
var/turf/T = get_turf(src)
|
||||
if(l_leg || r_leg || chest || l_arm || r_arm || head)
|
||||
@@ -252,6 +256,27 @@
|
||||
else
|
||||
to_chat(user, span_warning("The endoskeleton must be assembled before debugging can begin!"))
|
||||
|
||||
else if(istype(W, /obj/item/ai_cpu))
|
||||
if(check_completion())
|
||||
var/response = tgui_alert(user, "Are you sure you want to turn this endoskeleton into a synthetic unit?", "Please Confirm", list("Yes", "No"))
|
||||
if(response != "Yes")
|
||||
return
|
||||
|
||||
if(!user.temporarilyRemoveItemFromInventory(W))
|
||||
return
|
||||
var/mob/living/carbon/human/O = new /mob/living/carbon/human(get_turf(loc))
|
||||
O.set_species(/datum/species/wy_synth)
|
||||
O.invisibility = 0
|
||||
O.job = "Synthetic"
|
||||
var/datum/outfit/job/synthetic/SO = new()
|
||||
SO.equip(O)
|
||||
W.forceMove(O)
|
||||
var/datum/species/wy_synth/S = O.dna.species
|
||||
qdel(S.inbuilt_cpu)
|
||||
S.inbuilt_cpu = null
|
||||
S.inbuilt_cpu = W
|
||||
qdel(src)
|
||||
|
||||
else if(istype(W, /obj/item/mmi))
|
||||
var/obj/item/mmi/M = W
|
||||
if(check_completion())
|
||||
|
||||
@@ -10,6 +10,7 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
|
||||
new/datum/stack_recipe("fore port spacepod frame", /obj/item/pod_parts/pod_frame/fore_port, 15, time = 30, one_per_turf = 0), \
|
||||
new/datum/stack_recipe("fore starboard spacepod frame", /obj/item/pod_parts/pod_frame/fore_starboard, 15, time = 30, one_per_turf = 0), \
|
||||
new/datum/stack_recipe("aft port spacepod frame", /obj/item/pod_parts/pod_frame/aft_port, 15, time = 30, one_per_turf = 0), \
|
||||
new/datum/stack_recipe("catwalk floor tile", /obj/item/stack/tile/catwalk_tile, 1, 4, 20), \
|
||||
new/datum/stack_recipe("aft starboard spacepod frame", /obj/item/pod_parts/pod_frame/aft_starboard, 15, time = 30, one_per_turf = 0), \
|
||||
// yogs end
|
||||
))
|
||||
|
||||
@@ -451,3 +451,52 @@
|
||||
|
||||
/obj/item/stack/tile/eighties/loaded
|
||||
amount = 15
|
||||
|
||||
//Catwalk Tiles
|
||||
/obj/item/stack/tile/catwalk_tile //This is our base type, sprited to look maintenance-styled
|
||||
name = "catwalk plating"
|
||||
singular_name = "catwalk plating tile"
|
||||
desc = "Flooring that shows its contents underneath. Engineers love it!"
|
||||
icon_state = "maint_catwalk"
|
||||
materials = list(/datum/material/iron=100)
|
||||
turf_type = /turf/open/floor/catwalk_floor
|
||||
merge_type = /obj/item/stack/tile/catwalk_tile //Just to be cleaner, these all stack with eachother
|
||||
|
||||
/obj/item/stack/tile/catwalk_tile/sixty
|
||||
amount = 60
|
||||
|
||||
/obj/item/stack/tile/catwalk_tile/iron
|
||||
name = "iron catwalk floor"
|
||||
singular_name = "iron catwalk floor tile"
|
||||
icon_state = "iron_catwalk"
|
||||
turf_type = /turf/open/floor/catwalk_floor/iron
|
||||
|
||||
/obj/item/stack/tile/catwalk_tile/iron_white
|
||||
name = "white catwalk floor"
|
||||
singular_name = "white catwalk floor tile"
|
||||
icon_state = "whiteiron_catwalk"
|
||||
turf_type = /turf/open/floor/catwalk_floor/iron_white
|
||||
|
||||
/obj/item/stack/tile/catwalk_tile/iron_dark
|
||||
name = "dark catwalk floor"
|
||||
singular_name = "dark catwalk floor tile"
|
||||
icon_state = "darkiron_catwalk"
|
||||
turf_type = /turf/open/floor/catwalk_floor/iron_dark
|
||||
|
||||
/obj/item/stack/tile/catwalk_tile/flat_white
|
||||
name = "flat white catwalk floor"
|
||||
singular_name = "flat white catwalk floor tile"
|
||||
icon_state = "flatwhite_catwalk"
|
||||
turf_type = /turf/open/floor/catwalk_floor/flat_white
|
||||
|
||||
/obj/item/stack/tile/catwalk_tile/titanium
|
||||
name = "titanium catwalk floor"
|
||||
singular_name = "titanium catwalk floor tile"
|
||||
icon_state = "titanium_catwalk"
|
||||
turf_type = /turf/open/floor/catwalk_floor/titanium
|
||||
|
||||
/obj/item/stack/tile/catwalk_tile/iron_smooth //this is the greenish one
|
||||
name = "smooth iron catwalk floor"
|
||||
singular_name = "smooth iron catwalk floor tile"
|
||||
icon_state = "smoothiron_catwalk"
|
||||
turf_type = /turf/open/floor/catwalk_floor/iron_smooth
|
||||
|
||||
@@ -170,6 +170,8 @@
|
||||
user.Paralyze(stunforce*3)
|
||||
deductcharge(hitcost)
|
||||
return
|
||||
if(!synth_check(user, SYNTH_RESTRICTED_WEAPON))
|
||||
return
|
||||
if(HAS_TRAIT(user, TRAIT_NO_STUN_WEAPONS))
|
||||
to_chat(user, span_warning("You can't seem to remember how this works!"))
|
||||
return
|
||||
|
||||
@@ -61,6 +61,8 @@
|
||||
return ..()
|
||||
if(user.zone_selected != BODY_ZONE_PRECISE_EYES && user.zone_selected != BODY_ZONE_HEAD)
|
||||
return ..()
|
||||
if(!synth_check(user, SYNTH_ORGANIC_HARM))
|
||||
return
|
||||
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, span_warning("You don't want to harm [M]!"))
|
||||
return
|
||||
|
||||
@@ -78,6 +78,10 @@
|
||||
if(broken || !Adjacent(user))
|
||||
return
|
||||
|
||||
if(is_synth(user))
|
||||
to_chat(user, span_warning("You may not change your appearance."))
|
||||
return
|
||||
|
||||
if(user && ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/choices = get_choices(H) // Get the choices you can change
|
||||
|
||||
@@ -252,6 +252,8 @@ GLOBAL_LIST_EMPTY(crematoriums)
|
||||
/obj/structure/bodycontainer/crematorium/proc/cremate(mob/user)
|
||||
if(locked)
|
||||
return //don't let you cremate something twice or w/e
|
||||
if(is_synth(user))
|
||||
return
|
||||
// Make sure we don't delete the actual morgue and its tray
|
||||
var/list/conts = get_all_contents() - src - connected
|
||||
|
||||
|
||||
@@ -26,21 +26,6 @@
|
||||
desc = "Next to the extremely long list of names and job titles, there is a drawing of a little child. The child appears to be retarded. Beneath the image, someone has scratched the word \"PACKETS\"."
|
||||
icon_state = "kiddieplaque"
|
||||
|
||||
/obj/structure/sign/plaques/ai_password
|
||||
name = "\improper AI default password"
|
||||
desc = "This plaque contains the default password for AI control consoles onboard this station."
|
||||
var/control_code = "BUG"
|
||||
|
||||
/obj/structure/sign/plaques/ai_password/Initialize(mapload)
|
||||
. = ..()
|
||||
control_code = GLOB.ai_control_code
|
||||
|
||||
/obj/structure/sign/plaques/ai_password/examine(mob/living/user)
|
||||
. = ..()
|
||||
if(Adjacent(user))
|
||||
. += span_notice("The following digits are stamped into the plaque: [control_code]")
|
||||
else
|
||||
. += span_notice("You must be closer to read the code.")
|
||||
|
||||
/obj/structure/sign/plaques/kiddie/badger
|
||||
name = "\improper Remembrance Plaque"
|
||||
|
||||
Reference in New Issue
Block a user