mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-14 20:23:26 +00:00
Merge branch 'master' into protean-rework
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -22,9 +22,6 @@ cfg/
|
||||
!/.vscode/settings.json
|
||||
!/.vscode/tasks.json
|
||||
|
||||
code/game/gamemodes/technomancer/spells/projectile/overload.dm
|
||||
code/game/gamemodes/technomancer/spells/projectile/overload.dm
|
||||
code/modules/client/preference_setup/loadout/loadout_xeno.dm
|
||||
temp.dmi
|
||||
|
||||
node_modules/
|
||||
|
||||
5
.prettierignore
Normal file
5
.prettierignore
Normal file
@@ -0,0 +1,5 @@
|
||||
# We don't want prettier to run on anything outside of the TGUI folder, so we have to do this.
|
||||
/*
|
||||
|
||||
# We want it to run into the TGUI folder, however.
|
||||
!/tgui
|
||||
@@ -11,6 +11,7 @@
|
||||
#define WEATHER_BLOOD_MOON "blood moon" // For admin fun or cult later on.
|
||||
#define WEATHER_EMBERFALL "emberfall" // More adminbuse, from TG. Harmless.
|
||||
#define WEATHER_ASH_STORM "ash storm" // Ripped from TG, like the above. Less harmless.
|
||||
#define WEATHER_ASH_STORM_SAFE "light ash storm" //Safe version of the ash storm. Dimmer.
|
||||
#define WEATHER_FALLOUT "fallout" // Modified emberfall, actually harmful. Admin only.
|
||||
|
||||
#define MOON_PHASE_NEW_MOON "new moon"
|
||||
|
||||
@@ -14,5 +14,7 @@
|
||||
#define LANGUAGE_ECHOSONG "Echo Song"
|
||||
|
||||
#define LANGUAGE_ANIMAL "Animal"
|
||||
#define LANGUAGE_TEPPI "Teppi"
|
||||
#define LANGUAGE_MOUSE "Mouse"
|
||||
|
||||
#define LANGUAGE_SHADEKIN "Shadekin Empathy"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
GLOBAL_LIST_EMPTY(admins) //all clients whom are admins
|
||||
GLOBAL_PROTECT(admins)
|
||||
GLOBAL_LIST_EMPTY(mentors)
|
||||
GLOBAL_PROTECT(mentors)
|
||||
GLOBAL_LIST_EMPTY(deadmins) //all ckeys who have used the de-admin verb.
|
||||
GLOBAL_LIST_EMPTY(stealthminID)
|
||||
GLOBAL_LIST_EMPTY(directory) //all ckeys with associated client
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
/proc/log_debug(text)
|
||||
if (config.log_debug)
|
||||
WRITE_LOG(debug_log, "DEBUG: [text]")
|
||||
WRITE_LOG(debug_log, "DEBUG: [sanitize(text)]")
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(C.is_preference_enabled(/datum/client_preference/debug/show_debug_logs))
|
||||
|
||||
@@ -156,6 +156,7 @@
|
||||
for(var/obj/O in T)
|
||||
if(O.simulated)
|
||||
O.loc = X
|
||||
if(O.light_system == STATIC_LIGHT)
|
||||
O.update_light()
|
||||
if(z_level_change) // The objects still need to know if their z-level changed.
|
||||
O.onTransitZ(T.z, X.z)
|
||||
|
||||
@@ -79,6 +79,7 @@ var/list/gamemode_cache = list()
|
||||
var/static/kick_inactive = 0 //force disconnect for inactive players after this many minutes, if non-0
|
||||
var/static/show_mods = 0
|
||||
var/static/show_devs = 0
|
||||
var/static/show_mentors = 0
|
||||
var/static/show_event_managers = 0
|
||||
var/static/mods_can_tempban = 0
|
||||
var/static/mods_can_job_tempban = 0
|
||||
@@ -660,6 +661,9 @@ var/list/gamemode_cache = list()
|
||||
if("show_devs")
|
||||
config.show_devs = 1
|
||||
|
||||
if("show_mentors")
|
||||
config.show_mentors = 1
|
||||
|
||||
if("show_event_managers")
|
||||
config.show_event_managers = 1
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
|
||||
if(!statclick)
|
||||
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
|
||||
|
||||
stat("GLOB:", statclick.update("Edit"))
|
||||
stat("GLOB:", "Button Removed Due To Crashing") //VOREStation Edit
|
||||
|
||||
/datum/controller/global_vars/vv_edit_var(var_name, var_value)
|
||||
if(gvars_datum_protected_varlist[var_name])
|
||||
|
||||
@@ -52,7 +52,7 @@ SUBSYSTEM_DEF(chat)
|
||||
for(var/I in target)
|
||||
var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible
|
||||
|
||||
if(!C)
|
||||
if(!C || !C.chatOutput)
|
||||
continue // No client? No care.
|
||||
else if(C.chatOutput.broken)
|
||||
DIRECT_OUTPUT(C, original_message)
|
||||
@@ -65,7 +65,7 @@ SUBSYSTEM_DEF(chat)
|
||||
else
|
||||
var/client/C = CLIENT_FROM_VAR(target) //Grab us a client if possible
|
||||
|
||||
if(!C)
|
||||
if(!C || !C.chatOutput)
|
||||
return // No client? No care.
|
||||
else if(C.chatOutput.broken)
|
||||
DIRECT_OUTPUT(C, original_message)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#define XENOARCH_SPAWN_CHANCE 0.5
|
||||
#define DIGSITESIZE_LOWER 4
|
||||
#define DIGSITESIZE_UPPER 12
|
||||
#define ARTIFACTSPAWNNUM_LOWER 6
|
||||
#define ARTIFACTSPAWNNUM_UPPER 12
|
||||
#define ARTIFACTSPAWNNUM_LOWER 12
|
||||
#define ARTIFACTSPAWNNUM_UPPER 24
|
||||
|
||||
//
|
||||
// Xenoarch subsystem handles initialization of Xenoarcheaology artifacts and digsites.
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
var/bluespace_item_types = newlist(/obj/item/weapon/storage/backpack/holding,
|
||||
/obj/item/weapon/storage/bag/trash/holding,
|
||||
/obj/item/weapon/storage/pouch/holding,
|
||||
/obj/item/weapon/storage/belt/utility/holding,
|
||||
/obj/item/weapon/storage/belt/medical/holding
|
||||
)
|
||||
|
||||
//wrapper
|
||||
/proc/do_teleport(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, local=TRUE, bohsafe=FALSE) //CHOMPStation Edit
|
||||
new /datum/teleport/instant/science(arglist(args))
|
||||
@@ -157,21 +164,27 @@
|
||||
|
||||
/datum/teleport/instant/science/setPrecision(aprecision)
|
||||
..()
|
||||
if(bohsafe)
|
||||
return 1
|
||||
if(istype(teleatom, /obj/item/weapon/storage/backpack/holding))
|
||||
precision = rand(1,100)
|
||||
if(bohsafe) //CHOMPedit
|
||||
return 1 //CHOMPedit
|
||||
|
||||
var/list/bluespace_things = newlist()
|
||||
|
||||
for (var/item in bluespace_item_types)
|
||||
if (istype(teleatom, item))
|
||||
precision = rand(1, 100)
|
||||
bluespace_things |= teleatom.search_contents_for(item)
|
||||
|
||||
var/list/bagholding = teleatom.search_contents_for(/obj/item/weapon/storage/backpack/holding)
|
||||
//VOREStation Addition Start: Prevent taurriding abuse
|
||||
if(istype(teleatom, /mob/living))
|
||||
var/mob/living/L = teleatom
|
||||
if(LAZYLEN(L.buckled_mobs))
|
||||
for(var/mob/rider in L.buckled_mobs)
|
||||
bagholding += rider.search_contents_for(/obj/item/weapon/storage/backpack/holding)
|
||||
for (var/item in bluespace_item_types)
|
||||
bluespace_things |= rider.search_contents_for(item)
|
||||
//VOREStation Addition End: Prevent taurriding abuse
|
||||
if(bagholding.len)
|
||||
precision = max(rand(1,100)*bagholding.len,100)
|
||||
|
||||
if(bluespace_things.len)
|
||||
precision = max(rand(1,100)*bluespace_things.len,100)
|
||||
if(istype(teleatom, /mob/living))
|
||||
var/mob/living/MM = teleatom
|
||||
to_chat(MM, "<span class='danger'>The Bluespace interface on your [teleatom] interferes with the teleport!</span>")
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
//wrapper
|
||||
//This teleport effect means that bluespace items will cause a teleport location variation of 1 to 100 tiles.
|
||||
/proc/do_noeffect_teleport(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, local=FALSE)
|
||||
new /datum/teleport/instant/science/noeffect(arglist(args))
|
||||
return
|
||||
|
||||
//This teleport effect does not interact with bluespace items.
|
||||
/proc/do_safe_teleport(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, local=FALSE)
|
||||
new /datum/teleport/instant(arglist(args))
|
||||
return
|
||||
|
||||
/datum/teleport/instant/science/noeffect/setEffects(datum/effect/effect/system/aeffectin,datum/effect/effect/system/aeffectout)
|
||||
return 1
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
backpack = /obj/item/weapon/storage/backpack/captain
|
||||
satchel_one = /obj/item/weapon/storage/backpack/satchel/cap
|
||||
messenger_bag = /obj/item/weapon/storage/backpack/messenger/com
|
||||
id_type = /obj/item/weapon/card/id/gold
|
||||
id_type = /obj/item/weapon/card/id/gold/captain // CHOMPFix, captain gets their two gold stripe drip back.
|
||||
pda_type = /obj/item/device/pda/captain
|
||||
|
||||
/decl/hierarchy/outfit/job/captain/post_equip(var/mob/living/carbon/human/H)
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
containertype = /obj/structure/largecrate/animal/weretiger
|
||||
containername = "Weretiger crate"
|
||||
access = access_xenobiology
|
||||
/*
|
||||
|
||||
/datum/supply_pack/sci/otie
|
||||
name = "VARMAcorp adoptable reject (Dangerous!)"
|
||||
cost = 100
|
||||
@@ -43,4 +43,3 @@
|
||||
containertype = /obj/structure/largecrate/animal/otie/phoron
|
||||
containername = "VARMAcorp adaptive beta subject (Experimental)"
|
||||
access = access_xenobiology
|
||||
*/ //VORESTATION AI TEMPORARY REMOVAL. Oties commented out cuz broke.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*/datum/supply_pack/security/guardbeast //VORESTATION AI TEMPORARY REMOVAL
|
||||
/datum/supply_pack/security/guardbeast
|
||||
name = "VARMAcorp autoNOMous security solution"
|
||||
cost = 150
|
||||
containertype = /obj/structure/largecrate/animal/guardbeast
|
||||
@@ -17,7 +17,6 @@
|
||||
access_security,
|
||||
access_xenobiology)
|
||||
one_access = TRUE
|
||||
*/
|
||||
|
||||
/datum/supply_pack/randomised/security/armor
|
||||
access = access_armory
|
||||
|
||||
@@ -48,6 +48,11 @@
|
||||
name = "Ration Station Vendor Refill Cartridge"
|
||||
cost = 10
|
||||
|
||||
/datum/supply_pack/vending_refills/altevian
|
||||
contains = list(/obj/item/weapon/refill_cartridge/autoname/food/altevian)
|
||||
name = "Altevian Vendor Refill Cartridge"
|
||||
cost = 10
|
||||
|
||||
/datum/supply_pack/vending_refills/coffee
|
||||
contains = list(/obj/item/weapon/refill_cartridge/autoname/drink/coffee)
|
||||
name = "Hot Drinks Vendor Refill Cartridge"
|
||||
|
||||
@@ -259,4 +259,11 @@
|
||||
cost = 80
|
||||
containertype = /obj/structure/closet/crate/oculum
|
||||
containername = "Vox Civilian Hardsuit"
|
||||
|
||||
/datum/supply_pack/voidsuits/voxeng
|
||||
name = "Vox Engineering Hardsuit"
|
||||
contains = list (/obj/item/weapon/rig/vox/engineering)
|
||||
cost = 150
|
||||
containertype = /obj/structure/closet/crate/oculum
|
||||
containername = "Vox Engineering Hardsuit"
|
||||
//ChompEdit End
|
||||
|
||||
@@ -6,22 +6,22 @@
|
||||
|
||||
/datum/uplink_item/item/tools/binoculars
|
||||
name = "Binoculars"
|
||||
item_cost = 5
|
||||
item_cost = 3
|
||||
path = /obj/item/device/binoculars
|
||||
|
||||
/datum/uplink_item/item/tools/toolbox // Leaving the basic as an option since powertools are loud.
|
||||
name = "Fully Loaded Toolbox"
|
||||
item_cost = 5
|
||||
item_cost = 3
|
||||
path = /obj/item/weapon/storage/toolbox/syndicate
|
||||
|
||||
/datum/uplink_item/item/tools/powertoolbox
|
||||
name = "Fully Loaded Powertool Box"
|
||||
item_cost = 10
|
||||
item_cost = 5
|
||||
path = /obj/item/weapon/storage/toolbox/syndicate/powertools
|
||||
|
||||
/datum/uplink_item/item/tools/clerical
|
||||
name = "Morphic Clerical Kit"
|
||||
item_cost = 10
|
||||
item_cost = 5
|
||||
path = /obj/item/weapon/storage/box/syndie_kit/clerical
|
||||
|
||||
/datum/uplink_item/item/tools/encryptionkey_radio
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
/datum/uplink_item/item/tools/duffle
|
||||
name = "Black Duffle Bag"
|
||||
item_cost = 10
|
||||
item_cost = 5
|
||||
path = /obj/item/weapon/storage/backpack/dufflebag/syndie
|
||||
|
||||
/datum/uplink_item/item/tools/duffle/med
|
||||
@@ -61,7 +61,7 @@
|
||||
|
||||
/datum/uplink_item/item/tools/space_suit
|
||||
name = "Space Suit"
|
||||
item_cost = 15
|
||||
item_cost = 10
|
||||
path = /obj/item/weapon/storage/box/syndie_kit/space
|
||||
|
||||
/datum/uplink_item/item/tools/encryptionkey_binary
|
||||
@@ -71,7 +71,7 @@
|
||||
|
||||
/datum/uplink_item/item/tools/hacking_tool
|
||||
name = "Door Hacking Tool"
|
||||
item_cost = 20
|
||||
item_cost = 15
|
||||
path = /obj/item/device/multitool/hacktool
|
||||
desc = "Appears and functions as a standard multitool until the mode is toggled by applying a screwdriver appropriately. \
|
||||
When in hacking mode this device will grant full access to any standard airlock within 20 to 40 seconds. \
|
||||
@@ -79,7 +79,7 @@
|
||||
|
||||
/datum/uplink_item/item/tools/ai_detector
|
||||
name = "Anti-Surveillance Tool"
|
||||
item_cost = 20
|
||||
item_cost = 15
|
||||
path = /obj/item/device/multitool/ai_detector
|
||||
desc = "This functions like a normal multitool, but includes an integrated camera network sensor that will warn the holder if they are being \
|
||||
watched, by changing color and beeping. It is able to detect both AI visual surveillance and security camera utilization from terminals, and \
|
||||
@@ -87,20 +87,20 @@
|
||||
|
||||
/datum/uplink_item/item/tools/radio_jammer
|
||||
name = "Subspace Jammer"
|
||||
item_cost = 25
|
||||
item_cost = 20
|
||||
path = /obj/item/device/radio_jammer
|
||||
desc = "A device which is capable of disrupting subspace communications, preventing the use of headsets, PDAs, and communicators within \
|
||||
a radius of seven meters. It runs off weapon cells, which can be replaced as needed. One cell will last for approximately ten minutes."
|
||||
|
||||
/datum/uplink_item/item/tools/wall_elecrtifier
|
||||
name = "Wall Electrifier"
|
||||
item_cost = 10
|
||||
item_cost = 5
|
||||
path = /obj/item/weapon/cell/spike
|
||||
desc = "A modified powercell which will electrify walls and reinforced floors in a 3x3 tile range around it. Always active."
|
||||
|
||||
/datum/uplink_item/item/tools/emag
|
||||
name = "Cryptographic Sequencer"
|
||||
item_cost = 30
|
||||
item_cost = 20
|
||||
path = /obj/item/weapon/card/emag
|
||||
|
||||
/datum/uplink_item/item/tools/graviton
|
||||
@@ -111,7 +111,7 @@
|
||||
|
||||
/datum/uplink_item/item/tools/thermal
|
||||
name = "Thermal Imaging Glasses"
|
||||
item_cost = 30
|
||||
item_cost = 25
|
||||
path = /obj/item/clothing/glasses/thermal/syndi
|
||||
|
||||
/datum/uplink_item/item/tools/packagebomb
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
// Give Random Bad Mutation to M
|
||||
/proc/randmutb(var/mob/living/M)
|
||||
if(!M) return
|
||||
if(!M || !(M.dna)) return
|
||||
M.dna.check_integrity()
|
||||
//var/block = pick(GLASSESBLOCK,COUGHBLOCK,FAKEBLOCK,NERVOUSBLOCK,CLUMSYBLOCK,TWITCHBLOCK,HEADACHEBLOCK,BLINDBLOCK,DEAFBLOCK,HALLUCINATIONBLOCK) // Most of these are disabled anyway.
|
||||
var/block = pick(FAKEBLOCK,CLUMSYBLOCK,BLINDBLOCK,DEAFBLOCK)
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
// Give Random Good Mutation to M
|
||||
/proc/randmutg(var/mob/living/M)
|
||||
if(!M) return
|
||||
if(!M || !(M.dna)) return
|
||||
M.dna.check_integrity()
|
||||
//var/block = pick(HULKBLOCK,XRAYBLOCK,FIREBLOCK,TELEBLOCK,NOBREATHBLOCK,REMOTEVIEWBLOCK,REGENERATEBLOCK,INCREASERUNBLOCK,REMOTETALKBLOCK,MORPHBLOCK,BLENDBLOCK,NOPRINTSBLOCK,SHOCKIMMUNITYBLOCK,SMALLSIZEBLOCK) // Much like above, most of these blocks are disabled in code.
|
||||
var/block = pick(HULKBLOCK,XRAYBLOCK,FIREBLOCK,TELEBLOCK,REGENERATEBLOCK,REMOTETALKBLOCK)
|
||||
@@ -38,13 +38,13 @@
|
||||
|
||||
// Random Appearance Mutation
|
||||
/proc/randmuti(var/mob/living/M)
|
||||
if(!M) return
|
||||
if(!M || !(M.dna)) return
|
||||
M.dna.check_integrity()
|
||||
M.dna.SetUIValue(rand(1,DNA_UI_LENGTH),rand(1,4095))
|
||||
|
||||
// Scramble UI or SE.
|
||||
/proc/scramble(var/UI, var/mob/M, var/prob)
|
||||
if(!M) return
|
||||
if(!M || !(M.dna)) return
|
||||
M.dna.check_integrity()
|
||||
if(UI)
|
||||
for(var/i = 1, i <= DNA_UI_LENGTH-1, i++)
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
/datum/alt_title/captain
|
||||
title = "Captain"
|
||||
|
||||
/datum/job/captain/get_request_reasons()
|
||||
return list("Training crew")
|
||||
|
||||
/datum/job/hop
|
||||
disallow_jobhop = TRUE
|
||||
pto_type = PTO_CIVILIAN
|
||||
@@ -29,13 +32,13 @@
|
||||
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
|
||||
access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer,
|
||||
access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station,
|
||||
access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway)
|
||||
access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway, access_entertainment)
|
||||
minimal_access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers,
|
||||
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
|
||||
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
|
||||
access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer,
|
||||
access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station,
|
||||
access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway)
|
||||
access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway, access_entertainment)
|
||||
|
||||
/datum/alt_title/deputy_director
|
||||
title = "Deputy Director"
|
||||
@@ -46,6 +49,9 @@
|
||||
/datum/alt_title/facility_steward
|
||||
title = "Facility Steward"
|
||||
|
||||
/datum/job/hop/get_request_reasons()
|
||||
return list("ID modification", "Training crew")
|
||||
|
||||
|
||||
/datum/job/secretary
|
||||
disallow_jobhop = TRUE
|
||||
|
||||
@@ -57,6 +57,9 @@
|
||||
/datum/alt_title/cargo_supervisor
|
||||
title = "Cargo Supervisor"
|
||||
|
||||
/datum/job/qm/get_request_reasons()
|
||||
return list("Training crew")
|
||||
|
||||
|
||||
/datum/job/cargo_tech
|
||||
total_positions = 3
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
title = "Maintenance Manager"
|
||||
|
||||
/datum/job/chief_engineer/get_request_reasons()
|
||||
return list("Engine setup", "Construction project", "Repairs necessary")
|
||||
return list("Engine setup", "Construction project", "Repairs necessary", "Training crew")
|
||||
|
||||
|
||||
/datum/job/engineer
|
||||
|
||||
@@ -55,6 +55,9 @@
|
||||
/datum/alt_title/exploration_manager
|
||||
title = "Exploration Manager"
|
||||
|
||||
/datum/job/pathfinder/get_request_reasons()
|
||||
return list("Training crew")
|
||||
|
||||
|
||||
/datum/job/pilot
|
||||
title = "Pilot"
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
title = "Healthcare Manager"
|
||||
|
||||
/datum/job/cmo/get_request_reasons()
|
||||
return list("Surgery pending", "Viral outbreak")
|
||||
return list("Surgery pending", "Viral outbreak", "Training crew")
|
||||
|
||||
|
||||
/datum/job/doctor
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
/datum/alt_title/head_scientist
|
||||
title = "Head Scientist"
|
||||
|
||||
/datum/job/rd/get_request_reasons()
|
||||
return list("Repairs needed", "Training crew")
|
||||
|
||||
/datum/job/scientist
|
||||
spawn_positions = 5
|
||||
pto_type = PTO_SCIENCE
|
||||
@@ -87,6 +90,9 @@
|
||||
/datum/alt_title/assembly_tech
|
||||
title = "Assembly Technician"
|
||||
|
||||
/datum/job/roboticist/get_request_reasons()
|
||||
return list("Repairs needed")
|
||||
|
||||
//////////////////////////////////
|
||||
// Xenobotanist
|
||||
//////////////////////////////////
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
title = "Security Manager"
|
||||
|
||||
/datum/job/hos/get_request_reasons()
|
||||
return list("Wildlife management", "Forensic investigation")
|
||||
return list("Wildlife management", "Forensic investigation", "Training crew")
|
||||
|
||||
|
||||
/datum/job/warden
|
||||
|
||||
@@ -423,6 +423,8 @@
|
||||
|
||||
/obj/machinery/sleeper/relaymove(var/mob/user)
|
||||
..()
|
||||
if(user.incapacitated())
|
||||
return
|
||||
go_out()
|
||||
|
||||
/obj/machinery/sleeper/emp_act(var/severity)
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
/obj/structure/barricade/cutout/attackby(var/obj/I, var/mob/user)
|
||||
if(is_type_in_list(I, painters))
|
||||
var/choice = tgui_input_list(user, "What would you like to paint the cutout as?", "Cutout Painting", cutout_types)
|
||||
if(!choice || !Adjacent(user, src) || I != user.get_active_hand())
|
||||
if(!choice || !Adjacent(user) || I != user.get_active_hand())
|
||||
return TRUE
|
||||
if(do_after(user, 10 SECONDS, src))
|
||||
var/picked_type = cutout_types[choice]
|
||||
|
||||
@@ -92,8 +92,8 @@
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/teleport/station/attack_ai()
|
||||
attack_hand()
|
||||
/obj/machinery/teleport/station/attack_ai(mob/user)
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/computer/teleporter/attack_ai(mob/user)
|
||||
teleport_control.tgui_interact(user)
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
name = "virtual reality sleeper"
|
||||
desc = "A fancy bed with built-in sensory I/O ports and connectors to interface users' minds with their bodies in virtual reality."
|
||||
icon = 'icons/obj/Cryogenic2.dmi'
|
||||
icon_state = "syndipod_0"
|
||||
icon_state = "body_scanner_0"
|
||||
|
||||
var/base_state = "syndipod_"
|
||||
var/base_state = "body_scanner_"
|
||||
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
@@ -88,9 +88,9 @@
|
||||
|
||||
|
||||
|
||||
/obj/machinery/sleeper/relaymove(var/mob/user)
|
||||
/obj/machinery/vr_sleeper/relaymove(var/mob/user)
|
||||
..()
|
||||
if(usr.incapacitated())
|
||||
if(user.incapacitated())
|
||||
return
|
||||
go_out()
|
||||
|
||||
@@ -245,9 +245,14 @@
|
||||
if(occupant.species.name != "Promethean" && occupant.species.name != "Human" && mirror_first_occupant)
|
||||
avatar.shapeshifter_change_shape(occupant.species.name)
|
||||
avatar.forceMove(get_turf(S)) // Put the mob on the landmark, instead of inside it
|
||||
avatar.Sleeping(1)
|
||||
|
||||
|
||||
occupant.enter_vr(avatar)
|
||||
//Yes, I am using a aheal just so your markings transfer over, I could not get .prefs.copy_to working. This is very stupid, and I can't be assed to rewrite this. Too bad!
|
||||
avatar.revive()
|
||||
avatar.revive()
|
||||
avatar.verbs += /mob/living/carbon/human/proc/exit_vr //ahealing removes the prommie verbs and the VR verbs, giving it back
|
||||
avatar.Sleeping(1)
|
||||
|
||||
// Prompt for username after they've enterred the body.
|
||||
var/newname = sanitize(tgui_input_text(avatar, "You are entering virtual reality. Your username is currently [src.name]. Would you like to change it to something else?", "Name change", null, MAX_NAME_LEN), MAX_NAME_LEN)
|
||||
|
||||
@@ -94,10 +94,6 @@
|
||||
if(power <= 0)
|
||||
return
|
||||
if(src in explosion_turfs)
|
||||
return
|
||||
|
||||
explosion_turfs |= src
|
||||
|
||||
if(explosion_turfs[src] >= power)
|
||||
return //The turf already sustained and spread a power greated than what we are dealing with. No point spreading again.
|
||||
explosion_turfs[src] = power
|
||||
@@ -112,7 +108,7 @@
|
||||
T = get_step(src, turn(direction,90))
|
||||
T.explosion_spread(spread_power, turn(direction,90), explosion_turfs)
|
||||
T = get_step(src, turn(direction,-90))
|
||||
T.explosion_spread(spread_power, turn(direction,90), explosion_turfs)
|
||||
T.explosion_spread(spread_power, turn(direction,-90), explosion_turfs)
|
||||
|
||||
/turf/unsimulated/explosion_spread(power)
|
||||
return //So it doesn't get to the parent proc, which simulates explosions
|
||||
|
||||
@@ -382,7 +382,7 @@
|
||||
im_list += list(list("address" = exonet.address, "to_address" = their_address, "im" = text))
|
||||
log_pda("(COMM: [src]) sent \"[text]\" to [exonet.get_atom_from_address(their_address)]", usr)
|
||||
var/obj/item/device/communicator/comm = exonet.get_atom_from_address(their_address)
|
||||
to_chat(usr, "<span class='notice'>\icon[src][bicon(src)] Sent message to [comm.owner], <b>\"[text]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[exonet.get_atom_from_address(comm.exonet.address)]'>Reply</a>)</span>")
|
||||
to_chat(usr, "<span class='notice'>\icon[src][bicon(src)] Sent message to [istype(comm, /obj/item/device/communicator) ? comm.owner : comm.name], <b>\"[text]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[exonet.get_atom_from_address(comm.exonet.address)]'>Reply</a>)</span>")
|
||||
for(var/mob/M in player_list)
|
||||
if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
|
||||
if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat)
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
exonet.send_message(comm.exonet.address, "text", message)
|
||||
im_list += list(list("address" = exonet.address, "to_address" = comm.exonet.address, "im" = message))
|
||||
log_pda("(COMM: [src]) sent \"[message]\" to [exonet.get_atom_from_address(comm.exonet.address)]", usr)
|
||||
to_chat(usr, "<span class='notice'>\icon[src][bicon(src)] Sent message to [comm.owner], <b>\"[message]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[exonet.get_atom_from_address(comm.exonet.address)]'>Reply</a>)</span>")
|
||||
to_chat(usr, "<span class='notice'>\icon[src][bicon(src)] Sent message to [istype(comm, /obj/item/device/communicator) ? comm.owner : comm.name], <b>\"[message]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[exonet.get_atom_from_address(comm.exonet.address)]'>Reply</a>)</span>")
|
||||
|
||||
// Verb: text_communicator()
|
||||
// Parameters: None
|
||||
|
||||
@@ -308,8 +308,8 @@
|
||||
return bad_vital_organ
|
||||
|
||||
//this needs to be last since if any of the 'other conditions are met their messages take precedence
|
||||
if(!H.client && !H.teleop)
|
||||
return "buzzes, \"Resuscitation failed - Mental interface error. Further attempts may be successful.\""
|
||||
//if(!H.client && !H.teleop)
|
||||
// return "buzzes, \"Resuscitation failed - Mental interface error. Further attempts may be successful.\""// CHOMPEdit, removing this check to allow revival through bad internet connections.
|
||||
|
||||
return null
|
||||
|
||||
|
||||
@@ -126,7 +126,11 @@
|
||||
if(H.species.vision_organ)
|
||||
vision = H.internal_organs_by_name[H.species.vision_organ]
|
||||
if(!vision)
|
||||
user.visible_message("<b>\The [user]</b> directs [src] at [M]'s face.", \
|
||||
"<span class='notice'>You direct [src] at [M]'s face.</span>")
|
||||
to_chat(user, "<span class='warning'>You can't find any [H.species.vision_organ ? H.species.vision_organ : "eyes"] on [H]!</span>")
|
||||
user.setClickCooldown(user.get_attack_speed(src))
|
||||
return
|
||||
|
||||
user.visible_message("<b>\The [user]</b> directs [src] to [M]'s eyes.", \
|
||||
"<span class='notice'>You direct [src] to [M]'s eyes.</span>")
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
var/emagged = 0
|
||||
var/failmsg = ""
|
||||
var/charge = 0
|
||||
var/selected_color = LIGHT_COLOR_INCANDESCENT_TUBE //Default color!
|
||||
|
||||
// Eating used bulbs gives us bulb shards
|
||||
var/bulb_shards = 0
|
||||
@@ -141,6 +142,10 @@
|
||||
return
|
||||
*/
|
||||
to_chat(usr, "It has [uses] lights remaining.")
|
||||
var/new_color = input(usr, "Choose a color to set the light to! (Default is [LIGHT_COLOR_INCANDESCENT_TUBE])", "", selected_color) as color|null
|
||||
if(new_color)
|
||||
selected_color = new_color
|
||||
to_chat(usr, "The light color has been changed.")
|
||||
|
||||
/obj/item/device/lightreplacer/update_icon()
|
||||
icon_state = "lightreplacer[emagged]"
|
||||
@@ -184,19 +189,13 @@
|
||||
to_chat(U, "<span class='notice'>\The [src] has fabricated a new bulb from the broken bulbs it has stored. It now has [uses] uses.</span>")
|
||||
playsound(src, 'sound/machines/ding.ogg', 50, 1)
|
||||
target.status = LIGHT_EMPTY
|
||||
target.installed_light = null //Remove the light!
|
||||
target.update()
|
||||
|
||||
var/obj/item/weapon/light/L2 = new target.light_type()
|
||||
|
||||
target.status = L2.status
|
||||
target.switchcount = L2.switchcount
|
||||
target.rigged = emagged
|
||||
target.brightness_range = L2.brightness_range
|
||||
target.brightness_power = L2.brightness_power
|
||||
target.brightness_color = L2.brightness_color
|
||||
target.on = target.has_power()
|
||||
L2.brightness_color = selected_color
|
||||
target.insert_bulb(L2) //Call the insertion proc.
|
||||
target.update()
|
||||
qdel(L2)
|
||||
|
||||
if(target.on && target.rigged)
|
||||
target.explode()
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
to_chat(user, "<span class='warning'>\The [src] cannot be applied to [M]!</span>")
|
||||
return 1
|
||||
|
||||
if (!M.IsAdvancedToolUser())
|
||||
if (!user.IsAdvancedToolUser())
|
||||
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
||||
return 1
|
||||
|
||||
|
||||
@@ -333,7 +333,10 @@
|
||||
if (prob(transfer/orig_amount * 100))
|
||||
transfer_fingerprints_to(S)
|
||||
if(blood_DNA)
|
||||
if(S.blood_DNA)
|
||||
S.blood_DNA |= blood_DNA
|
||||
else
|
||||
S.blood_DNA = blood_DNA.Copy()
|
||||
return transfer
|
||||
return 0
|
||||
|
||||
|
||||
@@ -30,3 +30,18 @@
|
||||
name = "dirty fancy plate"
|
||||
icon = 'icons/obj/trash_vr.dmi'
|
||||
icon_state = "fancyplate"
|
||||
|
||||
/obj/item/trash/ratcheese
|
||||
name = "\improper Flavor Unit package"
|
||||
icon = 'icons/obj/trash_vr.dmi'
|
||||
icon_state = "altevian_cheese_block-trash"
|
||||
|
||||
/obj/item/trash/ratveg
|
||||
name = "\improper Premium Ration packet"
|
||||
icon = 'icons/obj/trash_vr.dmi'
|
||||
icon_state = "altevian_veggies-trash"
|
||||
|
||||
/obj/item/trash/ratjuice
|
||||
name = "\improper Space-Safe Meal package"
|
||||
icon = 'icons/obj/trash_vr.dmi'
|
||||
icon_state = "altevian_juice-trash"
|
||||
@@ -119,7 +119,8 @@
|
||||
recharging = TRUE
|
||||
|
||||
if(istype(A, /obj/item/weapon/gun/energy) && !charge_guns)
|
||||
to_chat(user, "<span class='alert'>Error unable to interface with device.</span>")
|
||||
to_chat(user, "<span class='alert'>Error: Device is unable to interface with weapons.</span>")
|
||||
recharging = FALSE
|
||||
return FALSE
|
||||
|
||||
//The cell we hopefully eventually find
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
. = ..()
|
||||
. += "There [uses == 1 ? "is" : "are"] [uses] [material] [uses == 1 ? src.material.sheet_singular_name : src.material.sheet_plural_name] left for use."
|
||||
|
||||
/obj/item/weapon/material/sharpeningkit/Initialize()
|
||||
/obj/item/weapon/material/sharpeningkit/New()
|
||||
. = ..()
|
||||
setrepair()
|
||||
|
||||
|
||||
@@ -400,7 +400,7 @@
|
||||
max_storage_space = ITEMSIZE_COST_NORMAL * 25
|
||||
max_w_class = ITEMSIZE_NORMAL
|
||||
w_class = ITEMSIZE_SMALL
|
||||
can_hold = list(/obj/item/weapon/coin,/obj/item/weapon/spacecash)
|
||||
can_hold = list(/obj/item/weapon/coin,/obj/item/weapon/spacecash,/obj/item/weapon/spacecasinocash)
|
||||
|
||||
// -----------------------------
|
||||
// Chemistry Bag
|
||||
|
||||
@@ -36,3 +36,6 @@
|
||||
|
||||
/obj/item/weapon/storage/box/brainzsnax/red
|
||||
starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/canned/brainzsnax/red = 6)
|
||||
|
||||
/obj/item/weapon/storage/box/freezer
|
||||
can_hold = list(/obj/item/organ, /obj/item/weapon/reagent_containers/blood, /obj/item/weapon/reagent_containers/glass, /obj/item/weapon/reagent_containers/food)
|
||||
@@ -36,7 +36,8 @@
|
||||
/obj/item/weapon/stamp,
|
||||
/obj/item/clothing/accessory/permit,
|
||||
/obj/item/clothing/accessory/badge,
|
||||
/obj/item/weapon/makeover
|
||||
/obj/item/weapon/makeover,
|
||||
/obj/item/pizzavoucher //VOREStation edit
|
||||
)
|
||||
cant_hold = list(/obj/item/weapon/tool/screwdriver/power)
|
||||
slot_flags = SLOT_ID
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
/obj/item/weapon/melee/baton/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
if(Adjacent(user, src))
|
||||
if(Adjacent(user))
|
||||
if(bcell)
|
||||
. += "<span class='notice'>The baton is [round(bcell.percent())]% charged.</span>"
|
||||
if(!bcell)
|
||||
|
||||
436
code/game/objects/micro_structures.dm
Normal file
436
code/game/objects/micro_structures.dm
Normal file
@@ -0,0 +1,436 @@
|
||||
/obj/structure/micro_tunnel
|
||||
name = "mouse hole"
|
||||
desc = "A tiny little hole... where does it go?"
|
||||
icon = 'icons/obj/structures/micro_structures.dmi'
|
||||
icon_state = "mouse_hole"
|
||||
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
|
||||
var/magic = FALSE //For events and stuff, if true, this tunnel will show up in the list regardless of whether it's in valid range, of if you're in a tunnel with this var, all tunnels of the same faction will show up redardless of range
|
||||
micro_target = TRUE
|
||||
|
||||
var/static/non_micro_types = list(
|
||||
/mob/living/simple_mob/vore/alienanimals/catslug,
|
||||
/mob/living/simple_mob/vore/hostile/morph,
|
||||
/mob/living/simple_mob/protean_blob,
|
||||
/mob/living/simple_mob/slime
|
||||
)
|
||||
|
||||
/obj/structure/micro_tunnel/Initialize()
|
||||
. = ..()
|
||||
if(name == initial(name))
|
||||
var/area/our_area = get_area(src)
|
||||
name = "[our_area.name] [name]"
|
||||
if(pixel_x || pixel_y)
|
||||
return
|
||||
offset_tunnel()
|
||||
|
||||
/obj/structure/micro_tunnel/Destroy()
|
||||
visible_message("<span class = 'warning'>\The [src] collapses!</span>")
|
||||
for(var/mob/thing in src.contents)
|
||||
visible_message("<span class = 'warning'>\The [thing] tumbles out!</span>")
|
||||
thing.forceMove(get_turf(src.loc))
|
||||
thing.cancel_camera()
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/structure/micro_tunnel/set_dir(new_dir)
|
||||
. = ..()
|
||||
offset_tunnel()
|
||||
|
||||
/obj/structure/micro_tunnel/proc/offset_tunnel()
|
||||
|
||||
pixel_x = 0
|
||||
pixel_y = 0
|
||||
|
||||
switch(dir)
|
||||
if(1)
|
||||
pixel_y = 32
|
||||
if(2)
|
||||
pixel_y = -32
|
||||
if(4)
|
||||
pixel_x = 32
|
||||
if(8)
|
||||
pixel_x = -32
|
||||
|
||||
/obj/structure/micro_tunnel/attack_hand(mob/living/user)
|
||||
if(!isliving(user))
|
||||
return ..()
|
||||
if(user.loc == src)
|
||||
var/list/our_options = list("Exit", "Move")
|
||||
|
||||
if(is_type_in_list(user, non_micro_types))
|
||||
if(src.contents.len > 1)
|
||||
our_options |= "Eat"
|
||||
|
||||
our_options |= "Cancel"
|
||||
|
||||
var/choice = tgui_alert(user,"It's dark and gloomy in here. What would you like to do?","Tunnel",our_options)
|
||||
switch(choice)
|
||||
if("Exit")
|
||||
if(user.loc != src)
|
||||
to_chat(user, "<span class = 'warning'>You can't do that unless you're in \the [src].</span>")
|
||||
return
|
||||
|
||||
user.forceMove(get_turf(src.loc))
|
||||
user.cancel_camera()
|
||||
user.visible_message("<span class = 'notice'>\The [user] climbs out of \the [src]!</span>")
|
||||
return
|
||||
if("Move")
|
||||
if(user.loc != src)
|
||||
to_chat(user, "<span class = 'warning'>You can't do that unless you're in \the [src].</span>")
|
||||
return
|
||||
|
||||
var/list/destinations = list()
|
||||
var/turf/myturf = get_turf(src.loc)
|
||||
var/datum/planet/planet
|
||||
for(var/datum/planet/P in SSplanets.planets)
|
||||
if(myturf.z in P.expected_z_levels)
|
||||
planet = P
|
||||
else
|
||||
for(var/obj/structure/micro_tunnel/t in world)
|
||||
if(t == src)
|
||||
continue
|
||||
if(magic || t.magic)
|
||||
destinations |= t
|
||||
continue
|
||||
if(t.z == z)
|
||||
destinations |= t
|
||||
continue
|
||||
var/turf/targetturf = get_turf(t.loc)
|
||||
if(planet)
|
||||
if(targetturf.z in planet.expected_z_levels)
|
||||
destinations |= t
|
||||
continue
|
||||
else
|
||||
var/above = GetAbove(myturf)
|
||||
if(above && t.z == z + 1)
|
||||
destinations |= t
|
||||
continue
|
||||
var/below = GetBelow(myturf)
|
||||
if(below && t.z == z - 1)
|
||||
destinations |= t
|
||||
|
||||
if(!destinations.len)
|
||||
to_chat(user, "<span class = 'warning'>There are no other tunnels connected to this one!</span>")
|
||||
return
|
||||
else if(destinations.len == 1)
|
||||
choice = pick(destinations)
|
||||
else
|
||||
choice = tgui_input_list(user, "Where would you like to go?", "Pick a tunnel", destinations)
|
||||
if(!choice)
|
||||
return
|
||||
to_chat(user,"<span class = 'notice'>You begin moving...</span>")
|
||||
if(!do_after(user, 10 SECONDS, exclusive = TRUE))
|
||||
return
|
||||
user.forceMove(choice)
|
||||
user.cancel_camera()
|
||||
var/obj/structure/micro_tunnel/da_oddawun = choice
|
||||
da_oddawun.tunnel_notify(user)
|
||||
return
|
||||
if("Eat")
|
||||
var/list/our_targets = list()
|
||||
for(var/mob/living/L in src.contents)
|
||||
if(L == user)
|
||||
continue
|
||||
our_targets |= L
|
||||
if(!our_targets.len)
|
||||
to_chat(user, "<span class = 'warning'>There is no one in here except for you!</span>")
|
||||
return
|
||||
var/mob/our_choice
|
||||
if(our_targets.len == 1)
|
||||
our_choice = pick(our_targets)
|
||||
else
|
||||
our_choice = tgui_input_list(user, "Who would you like to eat?", "Pick a target to eat", our_targets)
|
||||
if(user.loc != src)
|
||||
to_chat(user, "<span class = 'warning'>You are no longer inside \the [src], and so cannot eat \the [our_choice].</span>")
|
||||
return
|
||||
if(our_choice.loc != src)
|
||||
to_chat(user, "<span class = 'warning'>\The [our_choice] is no longer inside \the [src], and so cannot be eaten.</span>")
|
||||
return
|
||||
user.feed_grabbed_to_self(user,our_choice)
|
||||
return
|
||||
if("Cancel")
|
||||
return
|
||||
|
||||
if(!can_enter(user))
|
||||
user.visible_message("<span class = 'warning'>\The [user] reaches into \the [src]. . .</span>","<span class = 'warning'>You reach into \the [src]. . .</span>")
|
||||
if(!do_after(user, 3 SECONDS, exclusive = TRUE))
|
||||
user.visible_message("<span class = 'notice'>\The [user] pulls their hand out of \the [src].</span>","<span class = 'warning'>You pull your hand out of \the [src]</span>")
|
||||
return
|
||||
if(!src.contents.len)
|
||||
to_chat(user, "<span class = 'warning'>There was nothing inside.</span>")
|
||||
user.visible_message("<span class = 'notice'>\The [user] pulls their hand out of \the [src].</span>","<span class = 'warning'>You pull your hand out of \the [src]</span>")
|
||||
return
|
||||
var/grabbed = pick(src.contents)
|
||||
if(!grabbed)
|
||||
to_chat(user, "<span class = 'warning'>There was nothing inside.</span>")
|
||||
user.visible_message("<span class = 'notice'>\The [user] pulls their hand out of \the [src].</span>","<span class = 'warning'>You pull your hand out of \the [src]</span>")
|
||||
return
|
||||
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/h = user
|
||||
var/mob/living/l = grabbed
|
||||
if(isliving(grabbed))
|
||||
if(!l.attempt_to_scoop(h))
|
||||
l.forceMove(get_turf(src.loc))
|
||||
else
|
||||
var/atom/movable/whatever = grabbed
|
||||
whatever.forceMove(get_turf(src.loc))
|
||||
|
||||
user.visible_message("<span class = 'warning'>\The [user] pulls \the [grabbed] out of \the [src]! ! !</span>")
|
||||
return
|
||||
|
||||
else if(isanimal(user))
|
||||
var/mob/living/simple_mob/a = user
|
||||
var/mob/living/l = grabbed
|
||||
if(!a.has_hands || isliving(grabbed))
|
||||
if(!l.attempt_to_scoop(a))
|
||||
l.forceMove(get_turf(src.loc))
|
||||
else
|
||||
var/atom/movable/whatever = grabbed
|
||||
whatever.forceMove(get_turf(src.loc))
|
||||
user.visible_message("<span class = 'warning'>\The [user] pulls \the [grabbed] out of \the [src]! ! !</span>")
|
||||
return
|
||||
|
||||
user.visible_message("<span class = 'notice'>\The [user] begins climbing into \the [src]!</span>")
|
||||
if(!do_after(user, 10 SECONDS, exclusive = TRUE))
|
||||
to_chat(user, "<span class = 'warning'>You didn't go into \the [src]!</span>")
|
||||
return
|
||||
|
||||
enter_tunnel(user)
|
||||
|
||||
/obj/structure/micro_tunnel/proc/can_enter(var/mob/living/user)
|
||||
if(user.mob_size <= MOB_TINY || user.get_effective_size(TRUE) <= micro_accepted_scale)
|
||||
return TRUE
|
||||
|
||||
if(is_type_in_list(user, non_micro_types))
|
||||
if(tgui_alert(user, "Would you like to enter the tunnel, or reach inside it?", "Enter or reach", list("Enter","Reach")) == "Enter")
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/obj/structure/micro_tunnel/attack_generic(mob/user, damage, attack_verb)
|
||||
attack_hand(user)
|
||||
return ..()
|
||||
|
||||
/obj/structure/micro_tunnel/MouseDrop_T(mob/living/M, mob/living/user)
|
||||
. = ..()
|
||||
if(M != user)
|
||||
return
|
||||
|
||||
if(!can_enter(user))
|
||||
return
|
||||
|
||||
var/mob/living/k = M
|
||||
|
||||
k.visible_message("<span class = 'notice'>\The [k] begins climbing into \the [src]!</span>")
|
||||
if(!do_after(k, 3 SECONDS, exclusive = TRUE))
|
||||
to_chat(k, "<span class = 'warning'>You didn't go into \the [src]!</span>")
|
||||
return
|
||||
|
||||
enter_tunnel(k)
|
||||
|
||||
/obj/structure/micro_tunnel/proc/enter_tunnel(mob/living/k)
|
||||
k.visible_message("<span class = 'notice'>\The [k] climbs into \the [src]!</span>")
|
||||
k.forceMove(src)
|
||||
k.cancel_camera()
|
||||
to_chat(k,"<span class = 'notice'>You are inside of \the [src]. It's dark and gloomy inside of here. You can click upon the tunnel to exit, or travel to another tunnel if there are other tunnels linked to it.</span>")
|
||||
tunnel_notify(k)
|
||||
|
||||
/obj/structure/micro_tunnel/proc/tunnel_notify(var/mob/living/user)
|
||||
to_chat(user, "<span class = 'notice'>You arrive inside \the [src].</span>")
|
||||
var/our_message = "You can see "
|
||||
var/found_stuff = FALSE
|
||||
for(var/thing in src.contents)
|
||||
if(thing == user)
|
||||
continue
|
||||
found_stuff = TRUE
|
||||
our_message = "[our_message] [thing], "
|
||||
if(isliving(thing))
|
||||
var/mob/living/t = thing
|
||||
to_chat(t, "<span class = 'notice'>\The [user] enters \the [src]!</span>")
|
||||
if(found_stuff)
|
||||
to_chat(user, "<span class = 'notice'>[our_message]inside of \the [src]!</span>")
|
||||
if(prob(25))
|
||||
visible_message("<span class = 'warning'>Something moves inside of \the [src]. . .</span>")
|
||||
|
||||
/obj/structure/micro_tunnel/magic
|
||||
magic = TRUE
|
||||
|
||||
/obj
|
||||
var/micro_accepted_scale = 0.5
|
||||
var/micro_target = FALSE
|
||||
|
||||
/obj/Initialize(mapload)
|
||||
. = ..()
|
||||
if(micro_target)
|
||||
verbs += /obj/proc/micro_interact
|
||||
|
||||
/obj/proc/micro_interact()
|
||||
set name = "Micro Interact"
|
||||
set desc = "Micros can enter, or move between objects with this! Non-micros can reach into objects to search for micros!"
|
||||
set category = "Object"
|
||||
set src in oview(1)
|
||||
|
||||
if(!isliving(usr))
|
||||
return
|
||||
|
||||
var/list/contained_mobs = list()
|
||||
for(var/mob/living/issamob in src.contents)
|
||||
if(isliving(issamob))
|
||||
contained_mobs |= issamob
|
||||
|
||||
if(usr.loc == src)
|
||||
var/choice = tgui_alert(usr,"What would you like to do?","[src]",list("Exit", "Move", "Cancel"))
|
||||
switch(choice)
|
||||
if("Exit")
|
||||
if(usr.loc != src)
|
||||
to_chat(usr, "<span class = 'warning'>You can't do that unless you're in \the [src].</span>")
|
||||
return
|
||||
|
||||
usr.forceMove(get_turf(src.loc))
|
||||
usr.cancel_camera()
|
||||
usr.visible_message("<span class = 'notice'>\The [usr] climbs out of \the [src]!</span>")
|
||||
return
|
||||
|
||||
if("Move")
|
||||
if(usr.loc != src)
|
||||
to_chat(usr, "<span class = 'warning'>You can't do that unless you're in \the [src].</span>")
|
||||
return
|
||||
var/list/destinations = list()
|
||||
var/turf/myturf = get_turf(src.loc)
|
||||
for(var/obj/o in range(1,myturf))
|
||||
if(!istype(o,/obj))
|
||||
continue
|
||||
if(o == src)
|
||||
continue
|
||||
if(o.micro_target)
|
||||
destinations |= o
|
||||
|
||||
if(!destinations.len)
|
||||
to_chat(usr, "<span class = 'warning'>There is nowhere to move to!</span>")
|
||||
return
|
||||
else if(destinations.len == 1)
|
||||
choice = pick(destinations)
|
||||
else
|
||||
choice = tgui_input_list(usr, "Where would you like to go?", "Pick a destination", destinations)
|
||||
if(!choice)
|
||||
return
|
||||
to_chat(usr,"<span class = 'notice'>You begin moving...</span>")
|
||||
if(!do_after(usr, 10 SECONDS, exclusive = TRUE))
|
||||
return
|
||||
var/obj/our_choice = choice
|
||||
|
||||
var/list/new_contained_mobs = list()
|
||||
for(var/mob/living/issamob in src.contents)
|
||||
if(isliving(issamob))
|
||||
contained_mobs |= issamob
|
||||
|
||||
usr.forceMove(our_choice)
|
||||
usr.cancel_camera()
|
||||
|
||||
to_chat(usr,"<span class = 'notice'>You are inside of \the [our_choice]. You can click upon the thing you are in to exit, or travel to a nearby thing if there are other tunnels linked to it.</span>")
|
||||
|
||||
var/our_message = "You can see "
|
||||
var/found_stuff = FALSE
|
||||
for(var/thing in new_contained_mobs)
|
||||
if(thing == usr)
|
||||
continue
|
||||
found_stuff = TRUE
|
||||
our_message = "[our_message] [thing], "
|
||||
if(isliving(thing))
|
||||
var/mob/living/t = thing
|
||||
to_chat(t, "<span class = 'notice'>\The [usr] enters \the [src]!</span>")
|
||||
if(found_stuff)
|
||||
to_chat(usr, "<span class = 'notice'>[our_message]inside of \the [src]!</span>")
|
||||
if(prob(25))
|
||||
our_choice.visible_message("<span class = 'warning'>Something moves inside of \the [our_choice]. . .</span>")
|
||||
return
|
||||
if("Cancel")
|
||||
return
|
||||
|
||||
if(!(usr.mob_size <= MOB_TINY || usr.get_effective_size(TRUE) <= micro_accepted_scale))
|
||||
usr.visible_message("<span class = 'warning'>\The [usr] reaches into \the [src]. . .</span>","<span class = 'warning'>You reach into \the [src]. . .</span>")
|
||||
if(!do_after(usr, 3 SECONDS, exclusive = TRUE))
|
||||
usr.visible_message("<span class = 'notice'>\The [usr] pulls their hand out of \the [src].</span>","<span class = 'warning'>You pull your hand out of \the [src]</span>")
|
||||
return
|
||||
|
||||
if(!contained_mobs.len)
|
||||
to_chat(usr, "<span class = 'warning'>There was nothing inside.</span>")
|
||||
usr.visible_message("<span class = 'notice'>\The [usr] pulls their hand out of \the [src].</span>","<span class = 'warning'>You pull your hand out of \the [src]</span>")
|
||||
return
|
||||
var/grabbed = pick(contained_mobs)
|
||||
if(!grabbed)
|
||||
to_chat(usr, "<span class = 'warning'>There was nothing inside.</span>")
|
||||
usr.visible_message("<span class = 'notice'>\The [usr] pulls their hand out of \the [src].</span>","<span class = 'warning'>You pull your hand out of \the [src]</span>")
|
||||
return
|
||||
|
||||
if(ishuman(usr))
|
||||
var/mob/living/carbon/human/h = usr
|
||||
var/mob/living/l = grabbed
|
||||
if(isliving(grabbed))
|
||||
l.attempt_to_scoop(h)
|
||||
if(!l.attempt_to_scoop(h))
|
||||
l.forceMove(get_turf(src.loc))
|
||||
else
|
||||
var/atom/movable/whatever = grabbed
|
||||
whatever.forceMove(get_turf(src.loc))
|
||||
|
||||
usr.visible_message("<span class = 'warning'>\The [usr] pulls \the [grabbed] out of \the [src]! ! !</span>")
|
||||
return
|
||||
|
||||
else if(isanimal(usr))
|
||||
var/mob/living/simple_mob/a = usr
|
||||
var/mob/living/l = grabbed
|
||||
if(!a.has_hands || isliving(grabbed))
|
||||
if(!l.attempt_to_scoop(a))
|
||||
l.forceMove(get_turf(src.loc))
|
||||
else
|
||||
var/atom/movable/whatever = grabbed
|
||||
whatever.forceMove(get_turf(src.loc))
|
||||
usr.visible_message("<span class = 'warning'>\The [usr] pulls \the [grabbed] out of \the [src]! ! !</span>")
|
||||
return
|
||||
|
||||
usr.visible_message("<span class = 'notice'>\The [usr] begins climbing into \the [src]!</span>")
|
||||
if(!do_after(usr, 10 SECONDS, exclusive = TRUE))
|
||||
to_chat(usr, "<span class = 'warning'>You didn't go into \the [src]!</span>")
|
||||
return
|
||||
|
||||
usr.visible_message("<span class = 'notice'>\The [usr] climbs into \the [src]!</span>")
|
||||
usr.forceMove(src)
|
||||
usr.cancel_camera()
|
||||
to_chat(usr,"<span class = 'notice'>You are inside of \the [src]. You can click upon the tunnel to exit, or travel to another tunnel if there are other tunnels linked to it.</span>")
|
||||
|
||||
var/our_message = "You can see "
|
||||
var/found_stuff = FALSE
|
||||
for(var/thing in contained_mobs)
|
||||
if(thing == usr)
|
||||
continue
|
||||
found_stuff = TRUE
|
||||
our_message = "[our_message] [thing], "
|
||||
if(isliving(thing))
|
||||
var/mob/living/t = thing
|
||||
to_chat(t, "<span class = 'notice'>\The [usr] enters \the [src]!</span>")
|
||||
if(found_stuff)
|
||||
to_chat(usr, "<span class = 'notice'>[our_message]inside of \the [src]!</span>")
|
||||
if(prob(25))
|
||||
visible_message("<span class = 'warning'>Something moves inside of \the [src]. . .</span>")
|
||||
|
||||
/obj/effect/mouse_hole_spawner
|
||||
name = "mouse hole spawner"
|
||||
icon = 'icons/obj/landmark_vr.dmi'
|
||||
icon_state = "blue-x"
|
||||
invisibility = 101
|
||||
|
||||
var/chance_to_spawn = 25
|
||||
|
||||
/obj/effect/mouse_hole_spawner/Initialize()
|
||||
. = ..()
|
||||
|
||||
if(prob(chance_to_spawn))
|
||||
var/obj/structure/micro_tunnel/tunnel = new (get_turf(src.loc))
|
||||
tunnel.set_dir(dir)
|
||||
|
||||
qdel(src)
|
||||
@@ -23,6 +23,20 @@
|
||||
|
||||
/obj/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
//VOREStation Add Start - I really am an idiot why did I make it this way
|
||||
if(micro_target)
|
||||
for(var/thing in src.contents)
|
||||
if(!ismob(thing))
|
||||
continue
|
||||
var/mob/m = thing
|
||||
if(isbelly(src.loc))
|
||||
m.forceMove(src.loc)
|
||||
else
|
||||
m.forceMove(get_turf(src.loc))
|
||||
m.visible_message("<span class = 'notice'>\The [m] tumbles out of \the [src]!</span>")
|
||||
//VOREStation Add End
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/Topic(href, href_list, var/datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
|
||||
@@ -97,7 +97,8 @@
|
||||
/obj/machinery/vending/weeb,
|
||||
/obj/machinery/vending/sol,
|
||||
/obj/machinery/vending/snix,
|
||||
/obj/machinery/vending/snlvend)
|
||||
/obj/machinery/vending/snlvend,
|
||||
/obj/machinery/vending/altevian)
|
||||
|
||||
/obj/random/vendordrink //Random drink vendors for station use
|
||||
name = "random drink vending machine"
|
||||
|
||||
@@ -323,7 +323,7 @@
|
||||
name = "random drink"
|
||||
desc = "This is a random drink."
|
||||
icon = 'icons/obj/drinks.dmi'
|
||||
icon_state = "whiskeybottle"
|
||||
icon_state = "whiskeybottle1"
|
||||
|
||||
/obj/random/drinkbottle/item_to_spawn()
|
||||
return pick(/obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey,
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
if(choice == "No")
|
||||
return
|
||||
var/basecolor = input(user, "Select a base color for the canvas:", "Base Color", canvas_color) as null|color
|
||||
if(basecolor && Adjacent(user, src) && Adjacent(user, I))
|
||||
if(basecolor && Adjacent(user) && user.get_active_hand() == I)
|
||||
canvas_color = basecolor
|
||||
reset_grid()
|
||||
user.visible_message("[user] smears paint on [src], covering the entire thing in paint.", "You smear paint on [src], changing the color of the entire thing.", runemessage = "smears paint")
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
/mob/living/simple_mob/otie/zorgoia, //CHOMPstation edit
|
||||
/mob/living/simple_mob/vore/rabbit,
|
||||
/mob/living/simple_mob/vore/weretiger;0.5,
|
||||
// /mob/living/simple_mob/otie;0.5
|
||||
/mob/living/simple_mob/otie;0.5
|
||||
))
|
||||
return ..()
|
||||
|
||||
@@ -72,11 +72,12 @@
|
||||
/mob/living/simple_mob/animal/space/alien/drone,
|
||||
/mob/living/simple_mob/animal/space/alien/sentinel,
|
||||
/mob/living/simple_mob/animal/space/alien/queen,
|
||||
// /mob/living/simple_mob/otie/feral,
|
||||
// /mob/living/simple_mob/otie/red,
|
||||
/mob/living/simple_mob/otie/feral,
|
||||
/mob/living/simple_mob/otie/feral/chubby,
|
||||
/mob/living/simple_mob/otie/red,
|
||||
/mob/living/simple_mob/vore/aggressive/corrupthound))
|
||||
return ..()
|
||||
/*
|
||||
|
||||
/obj/structure/largecrate/animal/guardbeast
|
||||
name = "VARMAcorp autoNOMous security solution"
|
||||
desc = "The VARMAcorp bioengineering division flagship product on trained optimal snowflake guard dogs."
|
||||
@@ -84,6 +85,11 @@
|
||||
icon_state = "sotiecrate"
|
||||
starts_with = list(/mob/living/simple_mob/otie/security)
|
||||
|
||||
/obj/structure/largecrate/animal/otie/guardbeast/Initialize()
|
||||
starts_with = list(pick(/mob/living/simple_mob/otie/security,
|
||||
/mob/living/simple_mob/otie/security/chubby))
|
||||
return ..()
|
||||
|
||||
/obj/structure/largecrate/animal/guardmutant
|
||||
name = "VARMAcorp autoNOMous security solution for hostile environments."
|
||||
desc = "The VARMAcorp bioengineering division flagship product on trained optimal snowflake guard dogs. This one can survive hostile atmosphere."
|
||||
@@ -91,6 +97,12 @@
|
||||
icon_state = "sotiecrate"
|
||||
starts_with = list(/mob/living/simple_mob/otie/security/phoron)
|
||||
|
||||
/obj/structure/largecrate/animal/otie/guardmutant/Initialize()
|
||||
starts_with = list(pick(/mob/living/simple_mob/otie/security/phoron;2,
|
||||
/mob/living/simple_mob/otie/security/phoron/red;0.5,
|
||||
/mob/living/simple_mob/otie/security/phoron/red/chubby;0.5))
|
||||
return ..()
|
||||
|
||||
/obj/structure/largecrate/animal/otie
|
||||
name = "VARMAcorp adoptable reject (Dangerous!)"
|
||||
desc = "A warning on the side says the creature inside was returned to the supplier after injuring or devouring several unlucky members of the previous adoption family. It was given a second chance with the next customer. Godspeed and good luck with your new pet!"
|
||||
@@ -99,6 +111,11 @@
|
||||
starts_with = list(/mob/living/simple_mob/otie/cotie)
|
||||
var/taped = 1
|
||||
|
||||
/obj/structure/largecrate/animal/otie/Initialize()
|
||||
starts_with = list(pick(/mob/living/simple_mob/otie/cotie,
|
||||
/mob/living/simple_mob/otie/cotie/chubby))
|
||||
return ..()
|
||||
|
||||
/obj/structure/largecrate/animal/otie/phoron
|
||||
name = "VARMAcorp adaptive beta subject (Experimental)"
|
||||
desc = "VARMAcorp experimental hostile environment adaptive breeding development kit. WARNING, DO NOT RELEASE IN WILD!"
|
||||
@@ -106,7 +123,8 @@
|
||||
|
||||
/obj/structure/largecrate/animal/otie/phoron/Initialize()
|
||||
starts_with = list(pick(/mob/living/simple_mob/otie/cotie/phoron;2,
|
||||
/mob/living/simple_mob/otie/red/friendly;0.5))
|
||||
/mob/living/simple_mob/otie/red/friendly;0.5,
|
||||
/mob/living/simple_mob/otie/red/chubby;0.5))
|
||||
return ..()
|
||||
|
||||
/obj/structure/largecrate/animal/otie/attack_hand(mob/living/carbon/human/M as mob)//I just couldn't decide between the icons lmao
|
||||
@@ -115,7 +133,6 @@
|
||||
icon_state = "otiecrate"
|
||||
taped = 0
|
||||
..()
|
||||
*/ //VORESTATION AI REMOVAL, Oties are still fucking broken.
|
||||
|
||||
/obj/structure/largecrate/animal/catgirl
|
||||
name = "Catgirl Crate"
|
||||
|
||||
@@ -13,9 +13,11 @@
|
||||
// Looping through the player list has the added bonus of working for mobs inside containers
|
||||
var/sound/S = sound(get_sfx(soundin))
|
||||
var/maxdistance = (world.view + extrarange) * 2 //VOREStation Edit - 3 to 2
|
||||
var/list/listeners = player_list
|
||||
var/list/listeners = player_list.Copy()
|
||||
if(!ignore_walls) //these sounds don't carry through walls
|
||||
listeners = listeners & hearers(maxdistance,turf_source)
|
||||
for(var/mob/listen in listeners)
|
||||
if(!(get_turf(listen) in hear(maxdistance,source)))
|
||||
listeners -= listen
|
||||
for(var/mob/M as anything in listeners)
|
||||
if(!M || !M.client)
|
||||
continue
|
||||
|
||||
@@ -80,8 +80,8 @@ var/world_topic_spam_protect_ip = "0.0.0.0"
|
||||
var/world_topic_spam_protect_time = world.timeofday
|
||||
|
||||
/world/Topic(T, addr, master, key)
|
||||
TGS_TOPIC
|
||||
VGS_TOPIC // VOREStation Edit - VGS
|
||||
VGS_TOPIC // VOREStation Edit - VGS //CHOMP Edit swapped lines around
|
||||
TGS_TOPIC //CHOMP Edit swapped lines around
|
||||
log_topic("\"[T]\", from:[addr], master:[master], key:[key]")
|
||||
|
||||
if (T == "ping")
|
||||
@@ -509,12 +509,9 @@ var/world_topic_spam_protect_time = world.timeofday
|
||||
if (copytext(line, 1, 2) == ";")
|
||||
continue
|
||||
|
||||
var/title = "Mentor"
|
||||
var/rights = admin_ranks[title]
|
||||
|
||||
var/ckey = copytext(line, 1, length(line)+1)
|
||||
var/datum/admins/D = new /datum/admins(title, rights, ckey)
|
||||
D.associate(GLOB.directory[ckey])
|
||||
var/datum/mentor/M = new /datum/mentor(ckey)
|
||||
M.associate(GLOB.directory[ckey])
|
||||
|
||||
/world/proc/update_status()
|
||||
var/s = ""
|
||||
|
||||
@@ -7,6 +7,8 @@ var/list/admin_verbs_default = list(
|
||||
/client/proc/cmd_admin_say, //VOREStation Add,
|
||||
/client/proc/cmd_mod_say, //VOREStation Add,
|
||||
/client/proc/cmd_event_say, //VOREStation Add,
|
||||
/client/proc/cmd_mentor_ticket_panel,
|
||||
/client/proc/cmd_mentor_say
|
||||
// /client/proc/hide_verbs, //hides all our adminverbs, //VOREStation Remove,
|
||||
// /client/proc/hide_most_verbs, //hides all our hideable adminverbs, //VOREStation Remove,
|
||||
// /client/proc/debug_variables, //allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify, //VOREStation Remove,
|
||||
@@ -122,7 +124,9 @@ var/list/admin_verbs_admin = list(
|
||||
/datum/admins/proc/set_uplink, //VOREStation Add,
|
||||
/datum/admins/proc/sendFax,
|
||||
/client/proc/despawn_player,
|
||||
/datum/admins/proc/view_feedback
|
||||
/datum/admins/proc/view_feedback,
|
||||
/client/proc/make_mentor,
|
||||
/client/proc/unmake_mentor
|
||||
)
|
||||
|
||||
var/list/admin_verbs_ban = list(
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
else if(href_list["ahelp_tickets"])
|
||||
GLOB.ahelp_tickets.BrowseTickets(text2num(href_list["ahelp_tickets"]))
|
||||
|
||||
mentor_commands(href, href_list, src)
|
||||
|
||||
if(href_list["dbsearchckey"] || href_list["dbsearchadmin"])
|
||||
|
||||
var/adminckey = href_list["dbsearchadmin"]
|
||||
|
||||
@@ -627,6 +627,9 @@
|
||||
/obj/effect/bmode/buildmode/proc/get_path_from_partial_text(default_path)
|
||||
var/desired_path = tgui_input_text(usr, "Enter full or partial typepath.","Typepath","[default_path]")
|
||||
|
||||
if(!desired_path) //VOREStation Add - If you don't give it anything it builds a list of every possible thing in the game and crashes your client.
|
||||
return //VOREStation Add - And the main way for it to do that is to push the cancel button, which should just do nothing. :U
|
||||
|
||||
var/list/types = typesof(/atom)
|
||||
var/list/matches = list()
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
to_chat(usr, "<font color='red'> You cannot pray (muted).</font>")
|
||||
return
|
||||
|
||||
var/image/cross = image('icons/obj/storage.dmi',"bible")
|
||||
var/icon/cross = icon('icons/obj/storage.dmi',"bible")
|
||||
msg = "<font color='blue'>\icon[cross][bicon(cross)] <b><font color=purple>PRAY: </font>[key_name(src, 1)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[src]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=\ref[src]'>PP</A>) (<A HREF='?_src_=vars;Vars=\ref[src]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[src]'>SM</A>) ([admin_jump_link(src, src)]) (<A HREF='?_src_=holder;secretsadmin=check_antagonist'>CA</A>) (<A HREF='?_src_=holder;adminspawncookie=\ref[src]'>SC</a>) (<A HREF='?_src_=holder;adminsmite=\ref[src]'>SMITE</a>):</b> [msg]</font>"
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
|
||||
@@ -123,6 +123,12 @@
|
||||
/datum/ai_holder/simple_mob/xenobio_slime/handle_special_tactic()
|
||||
evolve_and_reproduce()
|
||||
|
||||
/datum/ai_holder/simple_mob/xenobio_slime/handle_stance_tactical()
|
||||
if(!istype(holder) || QDELETED(holder))
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
// Hit the correct verbs to keep the slime species going.
|
||||
/datum/ai_holder/simple_mob/xenobio_slime/proc/evolve_and_reproduce()
|
||||
var/mob/living/simple_mob/slime/xenobio/my_slime = holder
|
||||
|
||||
@@ -534,27 +534,27 @@
|
||||
return
|
||||
|
||||
//
|
||||
//Slave Terminal
|
||||
//Sentient Prize Terminal
|
||||
//
|
||||
/obj/machinery/casinoslave_handler
|
||||
/obj/machinery/casinosentientprize_handler
|
||||
name = "Sentient Prize Automated Sales Machinery"
|
||||
desc = "The Sentient Prize Automated Sales Machinery, also known as SPASM! Here one can see who is on sale as sentinet prizes, as well as selling self and also buying prizes."
|
||||
icon = 'icons/obj/casino.dmi'
|
||||
icon_state = "casinoslave_hub_off"
|
||||
density = 1
|
||||
density = 0
|
||||
anchored = 1
|
||||
req_access = list(300)
|
||||
req_access = list(101)
|
||||
|
||||
var/casinoslave_sale = "disabled"
|
||||
var/casinoslave_price = 100
|
||||
var/casinosentientprize_sale = "disabled"
|
||||
var/casinosentientprize_price = 500
|
||||
var/collar_list = list()
|
||||
var/slaves_ckeys_list = list() //Same trick as lottery, to keep life simple
|
||||
var/obj/item/clothing/accessory/collar/casinoslave/selected_collar = null
|
||||
var/sentientprizes_ckeys_list = list() //Same trick as lottery, to keep life simple
|
||||
var/obj/item/clothing/accessory/collar/casinosentientprize/selected_collar = null
|
||||
|
||||
/obj/machinery/casinoslave_handler/attack_hand(mob/living/user as mob)
|
||||
/obj/machinery/casinosentientprize_handler/attack_hand(mob/living/user as mob)
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(casinoslave_sale == "disabled")
|
||||
if(casinosentientprize_sale == "disabled")
|
||||
to_chat(user,"<span class='notice'>The SPASM is disabled.</span> ")
|
||||
return
|
||||
|
||||
@@ -565,14 +565,14 @@
|
||||
if("Show selected Prize")
|
||||
if(QDELETED(selected_collar))
|
||||
collar_list -= selected_collar
|
||||
slaves_ckeys_list -= selected_collar.slaveckey
|
||||
sentientprizes_ckeys_list -= selected_collar.sentientprizeckey
|
||||
to_chat(user, "<span class='warning'>No collar is currently selected or the currently selected one has been destroyed or disabled.</span>")
|
||||
selected_collar = null
|
||||
return
|
||||
to_chat(user, "<span class='warning'>Sentient Prize information</span>")
|
||||
to_chat(user, "<span class='notice'>Name: [selected_collar.slavename]</span>")
|
||||
to_chat(user, "<span class='notice'>Description: [selected_collar.slaveflavor]</span>")
|
||||
to_chat(user, "<span class='notice'>OOC: [selected_collar.slaveooc]</span>")
|
||||
to_chat(user, "<span class='notice'>Name: [selected_collar.sentientprizename]</span>")
|
||||
to_chat(user, "<span class='notice'>Description: [selected_collar.sentientprizeflavor]</span>")
|
||||
to_chat(user, "<span class='notice'>OOC: [selected_collar.sentientprizeooc]</span>")
|
||||
if(selected_collar.ownername != null)
|
||||
to_chat(user, "<span class='warning'>This prize is already owned by [selected_collar.ownername]</span>")
|
||||
|
||||
@@ -580,47 +580,50 @@
|
||||
selected_collar = tgui_input_list(user, "Select a prize", "Chose a collar", collar_list)
|
||||
if(QDELETED(selected_collar))
|
||||
collar_list -= selected_collar
|
||||
slaves_ckeys_list -= selected_collar.slaveckey
|
||||
sentientprizes_ckeys_list -= selected_collar.sentientprizeckey
|
||||
to_chat(user, "<span class='warning'>No collars to chose, or selected collar has been destroyed or deactived, selection has been removed from list.</span>")
|
||||
selected_collar = null
|
||||
return
|
||||
|
||||
if("Become Prize (Please examine yourself first)") //Its awkward, but no easy way to obtain flavor_text due to server not loading text of mob until its been examined at least once.
|
||||
var/safety_ckey = user.client.ckey
|
||||
if(safety_ckey in slaves_ckeys_list)
|
||||
if(safety_ckey in sentientprizes_ckeys_list)
|
||||
to_chat(user, "<span class='warning'>The SPASM beeps in an upset manner, you already have a collar!</span>")
|
||||
return
|
||||
var/confirm = tgui_alert(usr, "Are you sure you want to become a sentient prize?", "Confirm Sentient Prize", list("Yes", "No"))
|
||||
if(confirm == "Yes")
|
||||
to_chat(user, "<span class='warning'>You are now a prize!</span>")
|
||||
if(safety_ckey in slaves_ckeys_list)
|
||||
if(safety_ckey in sentientprizes_ckeys_list)
|
||||
to_chat(user, "<span class='warning'>The SPASM beeps in an upset manner, you already have a collar!</span>")
|
||||
return
|
||||
slaves_ckeys_list += user.ckey
|
||||
var/obj/item/clothing/accessory/collar/casinoslave/C = new(src.loc)
|
||||
C.slavename = "[user.name]"
|
||||
C.slaveckey = "[user.ckey]"
|
||||
C.slaveflavor = user.flavor_text
|
||||
C.slaveooc = user.ooc_notes
|
||||
sentientprizes_ckeys_list += user.ckey
|
||||
var/obj/item/clothing/accessory/collar/casinosentientprize/C = new(src.loc)
|
||||
C.sentientprizename = "[user.name]"
|
||||
C.sentientprizeckey = "[user.ckey]"
|
||||
C.sentientprizeflavor = user.flavor_text
|
||||
C.sentientprizeooc = user.ooc_notes
|
||||
C.name = "Sentient Prize Collar: Available! [user.name] purchaseable at the SPASM!"
|
||||
C.desc = "SPASM collar. The tags shows in flashy colorful text the wearer is [user.name] and is currently available to buy at the Sentient Prize Automated Sales Machinery!"
|
||||
C.icon_state = "casinoslave_available"
|
||||
C.update_icon()
|
||||
collar_list += C
|
||||
|
||||
spawn_casinochips(casinoslave_price, src.loc)
|
||||
spawn_casinochips(casinosentientprize_price, src.loc)
|
||||
|
||||
/obj/machinery/casinoslave_handler/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
/obj/machinery/casinosentientprize_handler/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/weapon/spacecasinocash))
|
||||
if(casinoslave_sale == "disabled")
|
||||
if(casinosentientprize_sale == "disabled")
|
||||
to_chat(user, "<span class='warning'>Sentient Prize sales are currently disabled.</span>")
|
||||
return
|
||||
if(!selected_collar)
|
||||
to_chat(user, "<span class='warning'>Select a prize first.</span>")
|
||||
return
|
||||
if(!selected_collar.ownername)
|
||||
var/obj/item/weapon/spacecasinocash/C = W
|
||||
if(user.client.ckey == selected_collar.slaveckey)
|
||||
if(user.client.ckey == selected_collar.sentientprizeckey)
|
||||
insert_chip(C, user, "selfbuy")
|
||||
return
|
||||
else
|
||||
@@ -630,12 +633,12 @@
|
||||
to_chat(user, "<span class='warning'>This Sentient Prize is already owned! If you are the owner you can release the prize by swiping the collar on the SPASM!</span>")
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/clothing/accessory/collar/casinoslave))
|
||||
var/obj/item/clothing/accessory/collar/casinoslave/C = W
|
||||
if(user.name != C.slavename && user.name != C.ownername)
|
||||
if(istype(W, /obj/item/clothing/accessory/collar/casinosentientprize))
|
||||
var/obj/item/clothing/accessory/collar/casinosentientprize/C = W
|
||||
if(user.name != C.sentientprizename && user.name != C.ownername)
|
||||
to_chat(user, "<span class='warning'>This Sentient Prize collar isn't yours, please give it to the one it tagged for, belongs to, or a casino staff member!</span>")
|
||||
return
|
||||
if(user.name == C.slavename)
|
||||
if(user.name == C.sentientprizename)
|
||||
if(!C.ownername)
|
||||
to_chat(user,"<span class='notice'>If collar isn't disabled and entry removed, please select your entry and insert chips. Or contact staff if you need assistance.</span> ")
|
||||
return
|
||||
@@ -643,15 +646,15 @@
|
||||
to_chat(user,"<span class='notice'>If collar isn't disabled and entry removed, please ask your owner to free you with collar swipe on the SPASM, or contact staff if you need assistance.</span> ")
|
||||
return
|
||||
if(user.name == C.ownername)
|
||||
var/confirm = tgui_alert(usr, "Are you sure you want to wipe [C.slavename] entry?", "Confirm Sentient Prize Release", list("Yes", "No"))
|
||||
var/confirm = tgui_alert(usr, "Are you sure you want to wipe [C.sentientprizename] entry?", "Confirm Sentient Prize Release", list("Yes", "No"))
|
||||
if(confirm == "Yes")
|
||||
to_chat(user, "<span class='warning'>[C.slavename] collar has been deleted from registry!</span>")
|
||||
to_chat(user, "<span class='warning'>[C.sentientprizename] collar has been deleted from registry!</span>")
|
||||
C.icon_state = "casinoslave"
|
||||
C.update_icon()
|
||||
C.name = "a disabled Sentient Prize Collar: [C.slavename]"
|
||||
C.desc = "A collar worn by sentient prizes registered to a SPASM. The tag says its registered to [C.slavename], but harsh red text informs you its been disabled."
|
||||
slaves_ckeys_list -= C.slaveckey
|
||||
C.slaveckey = null
|
||||
C.name = "disabled Sentient Prize Collar: [C.sentientprizename]"
|
||||
C.desc = "A collar worn by sentient prizes registered to a SPASM. The tag says its registered to [C.sentientprizename], but harsh red text informs you its been disabled."
|
||||
sentientprizes_ckeys_list -= C.sentientprizeckey
|
||||
C.sentientprizeckey = null
|
||||
collar_list -= C
|
||||
|
||||
if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
|
||||
@@ -666,13 +669,13 @@
|
||||
return
|
||||
|
||||
if("Toggle Sentient Prize Sales")
|
||||
if(casinoslave_sale == "disabled")
|
||||
casinoslave_sale = "enabled"
|
||||
if(casinosentientprize_sale == "disabled")
|
||||
casinosentientprize_sale = "enabled"
|
||||
icon_state = "casinoslave_hub_on"
|
||||
update_icon()
|
||||
to_chat(user,"<span class='notice'>Prize sale has been enabled.</span> ")
|
||||
else
|
||||
casinoslave_sale = "disabled"
|
||||
casinosentientprize_sale = "disabled"
|
||||
icon_state = "casinoslave_hub_off"
|
||||
update_icon()
|
||||
to_chat(user,"<span class='notice'>Prize sale has been disabled.</span> ")
|
||||
@@ -683,21 +686,21 @@
|
||||
return
|
||||
if(QDELETED(selected_collar))
|
||||
collar_list -= selected_collar
|
||||
slaves_ckeys_list -= selected_collar.slaveckey
|
||||
sentientprizes_ckeys_list -= selected_collar.sentientprizeckey
|
||||
to_chat(user, "<span class='warning'>Collar has been destroyed!</span>")
|
||||
selected_collar = null
|
||||
return
|
||||
var/safety_ckey = selected_collar.slaveckey
|
||||
var/confirm = tgui_alert(usr, "Are you sure you want to wipe [selected_collar.slavename] entry?", "Confirm Sentient Prize", list("Yes", "No"))
|
||||
var/safety_ckey = selected_collar.sentientprizeckey
|
||||
var/confirm = tgui_alert(usr, "Are you sure you want to wipe [selected_collar.sentientprizename] entry?", "Confirm Sentient Prize", list("Yes", "No"))
|
||||
if(confirm == "Yes")
|
||||
if(safety_ckey == selected_collar.slaveckey)
|
||||
to_chat(user, "<span class='warning'>[selected_collar.slavename] collar has been deleted from registry!</span>")
|
||||
if(safety_ckey == selected_collar.sentientprizeckey)
|
||||
to_chat(user, "<span class='warning'>[selected_collar.sentientprizename] collar has been deleted from registry!</span>")
|
||||
selected_collar.icon_state = "casinoslave"
|
||||
selected_collar.update_icon()
|
||||
selected_collar.name = "a disabled Sentient Prize Collar: [selected_collar.slavename]"
|
||||
selected_collar.desc = "A collar worn by sentient prizes registered to a SPASM. The tag says its registered to [selected_collar.slavename], but harsh red text informs you its been disabled."
|
||||
slaves_ckeys_list -= selected_collar.slaveckey
|
||||
selected_collar.slaveckey = null
|
||||
selected_collar.name = "disabled Sentient Prize Collar: [selected_collar.sentientprizename]"
|
||||
selected_collar.desc = "A collar worn by sentient prizes registered to a SPASM. The tag says its registered to [selected_collar.sentientprizename], but harsh red text informs you its been disabled."
|
||||
sentientprizes_ckeys_list -= selected_collar.sentientprizeckey
|
||||
selected_collar.sentientprizeckey = null
|
||||
collar_list -= selected_collar
|
||||
selected_collar = null
|
||||
else
|
||||
@@ -707,12 +710,12 @@
|
||||
if("Change Prize Value")
|
||||
setprice(user)
|
||||
|
||||
/obj/machinery/casinoslave_handler/proc/insert_chip(var/obj/item/weapon/spacecasinocash/cashmoney, mob/user, var/buystate)
|
||||
if(cashmoney.worth < casinoslave_price)
|
||||
/obj/machinery/casinosentientprize_handler/proc/insert_chip(var/obj/item/weapon/spacecasinocash/cashmoney, mob/user, var/buystate)
|
||||
if(cashmoney.worth < casinosentientprize_price)
|
||||
to_chat(user,"<span class='notice'>You dont have enough chips to pay for the sentient prize!</span> ")
|
||||
return
|
||||
|
||||
cashmoney.worth -= casinoslave_price
|
||||
cashmoney.worth -= casinosentientprize_price
|
||||
cashmoney.update_icon()
|
||||
|
||||
if(cashmoney.worth <= 0)
|
||||
@@ -721,31 +724,31 @@
|
||||
cashmoney.update_icon()
|
||||
|
||||
if(buystate == "selfbuy")
|
||||
to_chat(user,"<span class='notice'>You put [casinoslave_price] credits worth of chips into the SPASM and nullify your collar!</span> ")
|
||||
to_chat(user,"<span class='notice'>You put [casinosentientprize_price] credits worth of chips into the SPASM and nullify your collar!</span> ")
|
||||
selected_collar.icon_state = "casinoslave"
|
||||
selected_collar.update_icon()
|
||||
selected_collar.name = "a disabled Sentient Prize Collar: [selected_collar.slavename]"
|
||||
selected_collar.desc = "A collar worn by sentient prizes registered to a SPASM. The tag says its registered to [selected_collar.slavename], but harsh red text informs you its been disabled."
|
||||
slaves_ckeys_list -= selected_collar.slaveckey
|
||||
selected_collar.slaveckey = null
|
||||
selected_collar.name = "disabled Sentient Prize Collar: [selected_collar.sentientprizename]"
|
||||
selected_collar.desc = "A collar worn by sentient prizes registered to a SPASM. The tag says its registered to [selected_collar.sentientprizename], but harsh red text informs you its been disabled."
|
||||
sentientprizes_ckeys_list -= selected_collar.sentientprizeckey
|
||||
selected_collar.sentientprizeckey = null
|
||||
collar_list -= selected_collar
|
||||
selected_collar = null
|
||||
|
||||
if(buystate == "buy")
|
||||
to_chat(user,"<span class='notice'>You put [casinoslave_price] credits worth of chips into the SPASM and it pings to inform you bought [selected_collar.slavename]!</span> ")
|
||||
to_chat(user,"<span class='notice'>You put [casinosentientprize_price] credits worth of chips into the SPASM and it pings to inform you bought [selected_collar.sentientprizename]!</span> ")
|
||||
selected_collar.icon_state = "casinoslave_owned"
|
||||
selected_collar.update_icon()
|
||||
selected_collar.ownername = user.name
|
||||
selected_collar.name = "Sentient Prize Collar: [selected_collar.slavename] owned by [selected_collar.ownername]!"
|
||||
selected_collar.desc = "A collar worn by sentient prizes registered to a SPASM. The tag says its registered to [selected_collar.slavename] and they are owned by [selected_collar.ownername]."
|
||||
selected_collar.name = "Sentient Prize Collar: [selected_collar.sentientprizename] owned by [selected_collar.ownername]!"
|
||||
selected_collar.desc = "A collar worn by sentient prizes registered to a SPASM. The tag says its registered to [selected_collar.sentientprizename] and they are owned by [selected_collar.ownername]."
|
||||
selected_collar = null
|
||||
|
||||
/obj/machinery/casinoslave_handler/proc/setprice(mob/living/user as mob)
|
||||
/obj/machinery/casinosentientprize_handler/proc/setprice(mob/living/user as mob)
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(ishuman(usr) || istype(usr, /mob/living/silicon/robot))
|
||||
casinoslave_price = tgui_input_number(usr, "Select the desired price (1-1000)", "Set Price", null, null, 1000, 1)
|
||||
if(casinoslave_price>1000 || casinoslave_price<1)
|
||||
casinosentientprize_price = tgui_input_number(usr, "Select the desired price (1-1000)", "Set Price", null, null, 1000, 1)
|
||||
if(casinosentientprize_price>1000 || casinosentientprize_price<1)
|
||||
to_chat(user,"<span class='notice'>Invalid price.</span> ")
|
||||
return
|
||||
to_chat(user,"<span class='notice'>You set the price to [casinoslave_price]</span> ")
|
||||
to_chat(user,"<span class='notice'>You set the price to [casinosentientprize_price]</span> ")
|
||||
|
||||
@@ -120,141 +120,12 @@
|
||||
|
||||
EXCHANGE RATE <br>
|
||||
FROM = TO <br>
|
||||
5 Thalers = 1 casino chip <br>
|
||||
1 casino chip = 5 Thalers <br> <br>
|
||||
1 Thaler = 1 casino chip <br>
|
||||
1 casino chip = 1 Thaler <br> <br>
|
||||
|
||||
The special sentient prize is 100 chips! More about it in section below! <br> <br>
|
||||
The special sentient prize is 200 chips! More about it in section below! <br> <br>
|
||||
|
||||
Melee weapons
|
||||
<ul>
|
||||
<li>scepter 500</li>
|
||||
<li>chain of command 250</li>
|
||||
</ul>
|
||||
Guns and 'guns' ((disclaimer, giving out guns will mean you get a weapons license as well with the shifts you have it, abusing these weapons will quickly get them removed!))
|
||||
<ul>
|
||||
<li>sizegun 100</li>
|
||||
<li>advanced anti particle rifle 500</li>
|
||||
<li>temperature gun 250</li>
|
||||
<li>alien pistol 1000</li>
|
||||
<li>floral somatoray 250</li>
|
||||
<li>net gun 500</li>
|
||||
</ul>
|
||||
Gear
|
||||
<ul>
|
||||
<li>experimental welder 500</li>
|
||||
<li>alien belt 750</li>
|
||||
<li>alien enhancement vest 750</li>
|
||||
<li>The monocoole 1000</li>
|
||||
<li>chameleon black tie 250</li>
|
||||
<li>cryostasis beaker 200</li>
|
||||
<li>bluespace beaker 200</li>
|
||||
<li>chem sprayer 250</li>
|
||||
</ul>
|
||||
Masks and hats - EVERYTHING IS 50 except chameleon!
|
||||
<ul>
|
||||
<li>assistant hat</li>
|
||||
<li>Shark mask</li>
|
||||
<li>Pig mask</li>
|
||||
<li>Luchador mask</li>
|
||||
<li>Horse mask</li>
|
||||
<li>Goblin mask</li>
|
||||
<li>Fake moustache</li>
|
||||
<li>Dolphin mask</li>
|
||||
<li>Demon mask</li>
|
||||
<li>Chameleon gas mask 250</li>
|
||||
</ul>
|
||||
Costumes - All costumes are 100 except the hoodies which are 50!
|
||||
<ul>
|
||||
<li>Black bunny girl outfit (black suit and rabbit ears)</li>
|
||||
<li>White bunny girl outfit (white suit and rabbit ears)</li>
|
||||
<li>Corgi hoodie</li>
|
||||
<li>Sexy clown</li>
|
||||
<li>nyan girl</li>
|
||||
<li>Wizard</li>
|
||||
<li>Chicken</li>
|
||||
<li>Carp hoodie</li>
|
||||
<li>Sexy mime</li>
|
||||
<li>Pirate</li>
|
||||
<li>Commie</li>
|
||||
<li>Plague doctor</li>
|
||||
<li>Imperium monk</li>
|
||||
<li>Cute witch</li>
|
||||
<li>Gladiator</li>
|
||||
</ul>
|
||||
Toys and misc - ALL THESE ARE 50
|
||||
<ul>
|
||||
<li>Toy sword</li>
|
||||
<li>Water flower</li>
|
||||
<li>Stick horse</li>
|
||||
<li>Replica katana</li>
|
||||
<li>Magic conch</li>
|
||||
<li>Magic 8-ball</li>
|
||||
<li>Foam sword</li>
|
||||
<li>Foam crossbow (with 5 bolts)</li>
|
||||
<li>Bosun's whistle</li>
|
||||
<li>Golden cup</li>
|
||||
<li>Havana cigar case</li>
|
||||
<li>Casino wallet (to keep after shift)</li>
|
||||
<li>Casino card deck (to keep after shift)</li>
|
||||
</ul>
|
||||
Booze - ALL BOOZE IS 50
|
||||
<ul>
|
||||
<li>Redeemer brew</li>
|
||||
<li>Warlock velvet</li>
|
||||
<li>Wrapp artiste patron</li>
|
||||
<li>Flask of holy water</li>
|
||||
<li>College girl goldschlager</li>
|
||||
<li>Gilthari luxury champagne</li>
|
||||
<li>Bottle of nothing</li>
|
||||
<li>Special blend whiskey</li>
|
||||
<li>Akvavit</li>
|
||||
</ul>
|
||||
Pets
|
||||
<ul>
|
||||
<li>Armadillo 150</li>
|
||||
<li>Cat 150</li>
|
||||
<li>Goat 150</li>
|
||||
<li>Fox 150</li>
|
||||
<li>Lizard 150</li>
|
||||
<li>Penguin 150</li>
|
||||
<li>Goose 200</li>
|
||||
<li>Chicken 200</li>
|
||||
<li>Cow 200</li>
|
||||
<li>Corgi 200</li>
|
||||
<li>Snake 200</li>
|
||||
<li>Yithian 200</li>
|
||||
<li>Tindalos 200</li>
|
||||
<li>Fennec 300</li>
|
||||
<li>Red Panda 300</li>
|
||||
<li>Horse 300</li>
|
||||
<li>Otie 500</li>
|
||||
<li>Chonker Otie 500</li>
|
||||
<li>Zorgoia 500</li>
|
||||
</ul>
|
||||
Mechs
|
||||
<ul>
|
||||
<li>Mining Ripley 1000</li>
|
||||
<li>Firefighter Ripley 750</li>
|
||||
<li>Serenity 1500</li>
|
||||
<li>Odysseus 1250</li>
|
||||
<li>Phazon Scuttlebug 2000</li>
|
||||
<li>Phazon Janus 3500</li>
|
||||
<li>Scarab 500</li>
|
||||
<li>Shuttlepod 250</li>
|
||||
<li><3E>Shuttlecraft 500</li>
|
||||
</ul>
|
||||
Implants
|
||||
<ul>
|
||||
<li>Implanter 100 (A basic empty implanter, you are going to need this to implant yourself with cyberntic augments)</li>
|
||||
<li>Implant: Tazer 1000 (A cybernetic implant that allows one to spawn a personal defense taser)</li>
|
||||
<li>Implant: Medkit 500 (A cybernetic implant that allows you to spawn all the tools needed for surgery)</li>
|
||||
<li>Implant: Shades 750 (A cybernetic implant that will spawn protective thermoshades upon your eyes, AR included!)</li>
|
||||
<li>Implant: Sprinter 1500 (A cybernetic implant that will give you that extra kick of energy to run faster!)</li>
|
||||
<li>Implant: Toolkit 500 (A cybernetic implant that allows you to spawn all the tools needed for engineering)</li>
|
||||
<li>Implant: Language 1000 (A cybernetic implant that allows you to understand almost all languages)</li>
|
||||
<li>Implant: Analyzer 500 (A cybernetic implant that allows one to spawn a Portable Resonant Analyzer for any science needs)</li>
|
||||
<li>Implant: Size Control 500 (A cybernetic implant that allows one to change the size of others via specific voice commands)</li>
|
||||
</ul>
|
||||
This section was outdated, someone better write it.
|
||||
|
||||
Thats it for prizes! <br><br>
|
||||
|
||||
|
||||
462
code/modules/casino/slots.dm
Normal file
462
code/modules/casino/slots.dm
Normal file
@@ -0,0 +1,462 @@
|
||||
|
||||
//Original Casino Code created by Shadowfire117#1269 - Ported from CHOMPstation
|
||||
//Modified by GhostActual#2055 for use with VOREstation
|
||||
|
||||
/*
|
||||
* Slot Machine
|
||||
*/
|
||||
|
||||
/obj/machinery/slot_machine
|
||||
name = "slot machine"
|
||||
desc = "A gambling machine designed to give you false hope and rob you of your wealth, hence why it's often called a one armed bandit."
|
||||
icon = 'icons/obj/casino.dmi'
|
||||
icon_state = "slotmachine"
|
||||
anchored = 1
|
||||
density = 1
|
||||
power_channel = EQUIP
|
||||
use_power = USE_POWER_IDLE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 100
|
||||
light_power = 0.9
|
||||
light_range = 2
|
||||
light_color = "#B1FBBFF"
|
||||
var/isbroken = 0 //1 if someone banged it with something heavy
|
||||
var/ispowered = 1 //starts powered, changes with power_change()
|
||||
var/busy = 0
|
||||
var/symbol1 = null
|
||||
var/symbol2 = null
|
||||
var/symbol3 = null
|
||||
|
||||
var/datum/effect/effect/system/confetti_spread
|
||||
var/confetti_strength = 8
|
||||
|
||||
/obj/machinery/slot_machine/update_icon()
|
||||
cut_overlays()
|
||||
if(!ispowered || isbroken)
|
||||
icon_state = "slotmachine_off"
|
||||
if(isbroken) //If the thing is smashed, add crack overlay on top of the unpowered sprite.
|
||||
add_overlay("slotmachine_broken")
|
||||
set_light(0)
|
||||
set_light_on(FALSE)
|
||||
return
|
||||
|
||||
icon_state = "slotmachine"
|
||||
set_light(2)
|
||||
set_light_on(TRUE)
|
||||
return
|
||||
|
||||
/obj/machinery/slot_machine/power_change()
|
||||
if(isbroken) //Broken shit can't be powered.
|
||||
return
|
||||
..()
|
||||
if(!(stat & NOPOWER))
|
||||
ispowered = 1
|
||||
update_icon()
|
||||
else
|
||||
spawn(rand(0, 15))
|
||||
ispowered = 0
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/slot_machine/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(busy)
|
||||
to_chat(user,"<span class='notice'>The slot machine is currently running.</span> ")
|
||||
return
|
||||
if(W.is_wrench())
|
||||
playsound(src, W.usesound, 100, 1)
|
||||
if(anchored)
|
||||
user.visible_message("[user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.")
|
||||
else
|
||||
user.visible_message("[user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.")
|
||||
|
||||
if(do_after(user, 20 * W.toolspeed))
|
||||
if(!src) return
|
||||
to_chat(user, "<span class='notice'>You [anchored? "un" : ""]secured \the [src]!</span>")
|
||||
anchored = !anchored
|
||||
return
|
||||
|
||||
if(!anchored)
|
||||
to_chat(user,"<span class='notice'> The slot machine isn't secured.</span>")
|
||||
return
|
||||
|
||||
var/handled = 0
|
||||
var/paid = 0
|
||||
|
||||
if(istype(W, /obj/item/weapon/spacecasinocash))
|
||||
var/obj/item/weapon/spacecasinocash/C = W
|
||||
paid = insert_chip(C, user)
|
||||
handled = 1
|
||||
|
||||
if(paid)
|
||||
return
|
||||
if(handled)
|
||||
SStgui.update_uis(src)
|
||||
return // don't smack that machine with your 2 chips
|
||||
|
||||
else if(!(stat & NOPOWER))
|
||||
return
|
||||
|
||||
else if(isbroken)
|
||||
return
|
||||
|
||||
/obj/machinery/slot_machine/proc/insert_chip(var/obj/item/weapon/spacecasinocash/cashmoney, mob/user)
|
||||
if (ispowered == 0)
|
||||
return
|
||||
if (isbroken)
|
||||
return
|
||||
if (busy)
|
||||
to_chat(user,"<span class='notice'>The slot machine is currently rolling.</span> ")
|
||||
return
|
||||
if(cashmoney.worth < 5)
|
||||
to_chat(user,"<span class='notice'>You dont have enough chips to gamble!</span> ")
|
||||
return
|
||||
|
||||
to_chat(user,"<span class='notice'>You puts 5 credits in the slot machine and presses start.</span>")
|
||||
cashmoney.worth -= 5
|
||||
cashmoney.update_icon()
|
||||
|
||||
if(cashmoney.worth <= 0)
|
||||
usr.drop_from_inventory(cashmoney)
|
||||
qdel(cashmoney)
|
||||
cashmoney.update_icon()
|
||||
|
||||
busy = 1
|
||||
icon_state = "slotmachine_rolling"
|
||||
playsound(src.loc, 'sound/machines/slotmachine_pull.ogg', 15, 1)
|
||||
|
||||
var/slot1 = rand(0,9)
|
||||
switch(slot1)
|
||||
if(0 to 3) symbol1 = "cherry"
|
||||
if(4 to 4) symbol1 = "lemon"
|
||||
if(5 to 5) symbol1 = "bell"
|
||||
if(6 to 6) symbol1 = "four leaf clover"
|
||||
if(7 to 7) symbol1 = "seven"
|
||||
if(8 to 8) symbol1 = "diamond"
|
||||
if(9 to 9) symbol1 = "platinum coin"
|
||||
|
||||
var/slot2 = rand(0,16)
|
||||
switch(slot2)
|
||||
if(0 to 5) symbol2 = "cherry"
|
||||
if(6 to 7) symbol2 = "lemon"
|
||||
if(8 to 9) symbol2 = "bell"
|
||||
if(10 to 11) symbol2 = "four leaf clover"
|
||||
if(12 to 13) symbol2 = "seven"
|
||||
if(14 to 15) symbol2 = "diamond"
|
||||
if(16) symbol2 = "platinum coin"
|
||||
|
||||
var/slot3 = rand(0,9)
|
||||
switch(slot3)
|
||||
if(0 to 3) symbol3 = "cherry"
|
||||
if(4 to 4) symbol3 = "lemon"
|
||||
if(5 to 5) symbol3 = "bell"
|
||||
if(6 to 6) symbol3 = "four leaf clover"
|
||||
if(7 to 7) symbol3 = "seven"
|
||||
if(8 to 8) symbol3 = "diamond"
|
||||
if(9 to 9) symbol3 = "platinum coin"
|
||||
|
||||
var/output //Output variable to send out in chat after the large if statement.
|
||||
var/winnings = 0 //How much money will be given if any.
|
||||
var/platinumwin = 0 // If you win the platinum chip or not
|
||||
var/celebrate = 0
|
||||
var/delaytime = 5 SECONDS
|
||||
|
||||
|
||||
spawn(delaytime)
|
||||
to_chat(user,"<span class='notice'>The slot machine flashes with bright colours as the slots lights up with a [symbol1], a [symbol2] and a [symbol3]!</span>")
|
||||
|
||||
if (symbol1 == "cherry" && symbol2 == "cherry" && symbol3 == "cherry")
|
||||
output = "<span class='notice'>Three cherries! The slot machine deposits chips worth 25 credits!</span>"
|
||||
winnings = 25
|
||||
|
||||
if ((symbol1 != "cherry" && symbol2 == "cherry" && symbol3 == "cherry") || (symbol1 == "cherry" && symbol2 != "cherry" && symbol3 == "cherry") ||(symbol1 == "cherry" && symbol2 == "cherry" && symbol3 != "cherry"))
|
||||
output = "<span class='notice'>Two cherries! The slot machine deposits a 10 credit chip!</span>"
|
||||
winnings = 10
|
||||
|
||||
if (symbol1 == "lemon" && symbol2 == "lemon" && symbol3 == "lemon")
|
||||
output = "<span class='notice'>Three lemons! The slot machine deposits a 50 credit chip!</span>"
|
||||
winnings = 50
|
||||
|
||||
if (symbol1 == "watermelon" && symbol2 == "watermelon" && symbol3 == "watermelon")
|
||||
output = "<span class='notice'>Three watermelons! The slot machine deposits chips worth 75 credits!</span>"
|
||||
winnings = 75
|
||||
|
||||
if (symbol1 == "bell" && symbol2 == "bell" && symbol3 == "bell")
|
||||
output = "<span class='notice'>Three bells! The slot machine deposits chips a 100 credit chip!</span>"
|
||||
winnings = 100
|
||||
|
||||
if (symbol1 == "four leaf clover" && symbol2 == "four leaf clover" && symbol3 == "four leaf clover")
|
||||
output = "<span class='notice'>Three four leaf clovers! The slot machine deposits a 200 credit chip!</span>"
|
||||
winnings = 200
|
||||
|
||||
if (symbol1 == "seven" && symbol2 == "seven" && symbol3 == "seven")
|
||||
output = "<span class='notice'>Three sevens! The slot machine deposits a 500 credit chip!</span>"
|
||||
winnings = 500
|
||||
celebrate = 1
|
||||
|
||||
if (symbol1 == "diamond" && symbol2 == "diamond" && symbol3 == "diamond")
|
||||
output = "<span class='notice'>Three diamonds! The slot machine deposits a 1000 credit chip!</span>"
|
||||
winnings = 1000
|
||||
celebrate = 1
|
||||
|
||||
if (symbol1 == "platinum coin" && symbol2 == "platinum coin" && symbol3 == "platinum coin")
|
||||
output = "<span class='notice'>Three platinum coins! The slot machine deposits a platinum chip!</span>"
|
||||
platinumwin = TRUE
|
||||
celebrate = 1
|
||||
|
||||
icon_state = initial(icon_state) // Set it back to the original iconstate.
|
||||
|
||||
if(!output) // Is there anything to output? If not, consider it a loss.
|
||||
to_chat(user,"Better luck next time!")
|
||||
busy = FALSE
|
||||
return
|
||||
|
||||
to_chat(user,output) //Output message
|
||||
|
||||
if(platinumwin) // Did they win the platinum chip?
|
||||
new /obj/item/weapon/casino_platinum_chip(src.loc)
|
||||
playsound(src.loc, 'sound/machines/slotmachine.ogg', 25, 1)
|
||||
|
||||
if(winnings) //Did the person win?
|
||||
icon_state = "slotmachine_winning"
|
||||
playsound(src.loc, 'sound/machines/slotmachine.ogg', 25, 1)
|
||||
spawn(delaytime)
|
||||
spawn_casinochips(winnings, src.loc)
|
||||
icon_state = "slotmachine"
|
||||
|
||||
if(celebrate) // Happy celebrations!
|
||||
src.confetti_spread = new /datum/effect/effect/system/confetti_spread()
|
||||
src.confetti_spread.attach(src) //If somehow people start dragging slot machine
|
||||
spawn(0)
|
||||
for(var/i = 1 to confetti_strength)
|
||||
src.confetti_spread.start()
|
||||
sleep(10)
|
||||
|
||||
busy = FALSE
|
||||
|
||||
/*
|
||||
* Station Slot Machine (takes space cash instead of chips)
|
||||
*/
|
||||
|
||||
/obj/machinery/station_slot_machine
|
||||
name = "station slot machine"
|
||||
desc = "A gambling machine owned by NanoTrasen, designed to take Thalers as opposed to casino chips."
|
||||
icon = 'icons/obj/casino.dmi'
|
||||
icon_state = "ntslotmachine"
|
||||
anchored = 1
|
||||
density = 1
|
||||
power_channel = EQUIP
|
||||
use_power = USE_POWER_IDLE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 100
|
||||
light_power = 0.9
|
||||
light_range = 2
|
||||
light_color = "#B1FBBFF"
|
||||
var/isbroken = 0 //1 if someone banged it with something heavy
|
||||
var/ispowered = 1 //starts powered, changes with power_change()
|
||||
var/busy = 0
|
||||
var/symbol1 = null
|
||||
var/symbol2 = null
|
||||
var/symbol3 = null
|
||||
|
||||
var/datum/effect/effect/system/confetti_spread
|
||||
var/confetti_strength = 8
|
||||
|
||||
/obj/machinery/station_slot_machine/update_icon()
|
||||
cut_overlays()
|
||||
if(!ispowered || isbroken)
|
||||
icon_state = "ntslotmachine_off"
|
||||
if(isbroken) //If the thing is smashed, add crack overlay on top of the unpowered sprite.
|
||||
add_overlay("ntslotmachine_broken")
|
||||
set_light(0)
|
||||
set_light_on(FALSE)
|
||||
return
|
||||
|
||||
icon_state = "ntslotmachine"
|
||||
set_light(2)
|
||||
set_light_on(TRUE)
|
||||
return
|
||||
|
||||
/obj/machinery/station_slot_machine/power_change()
|
||||
if(isbroken) //Broken shit can't be powered.
|
||||
return
|
||||
..()
|
||||
if(!(stat & NOPOWER))
|
||||
ispowered = 1
|
||||
update_icon()
|
||||
else
|
||||
spawn(rand(0, 15))
|
||||
ispowered = 0
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/station_slot_machine/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(busy)
|
||||
to_chat(user,"<span class='notice'>The slot machine is currently running.</span> ")
|
||||
return
|
||||
if(W.is_wrench())
|
||||
playsound(src, W.usesound, 100, 1)
|
||||
if(anchored)
|
||||
user.visible_message("[user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.")
|
||||
else
|
||||
user.visible_message("[user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.")
|
||||
|
||||
if(do_after(user, 20 * W.toolspeed))
|
||||
if(!src) return
|
||||
to_chat(user, "<span class='notice'>You [anchored? "un" : ""]secured \the [src]!</span>")
|
||||
anchored = !anchored
|
||||
return
|
||||
|
||||
if(!anchored)
|
||||
to_chat(user,"<span class='notice'> The slot machine isn't secured.</span>")
|
||||
return
|
||||
|
||||
var/handled = 0
|
||||
var/paid = 0
|
||||
|
||||
if(istype(W, /obj/item/weapon/spacecash))
|
||||
var/obj/item/weapon/spacecash/C = W
|
||||
paid = insert_cash(C, user)
|
||||
handled = 1
|
||||
if(paid)
|
||||
return
|
||||
if(handled)
|
||||
SStgui.update_uis(src)
|
||||
return // don't smack that machine with your 2 chips
|
||||
|
||||
else if(!(stat & NOPOWER))
|
||||
return
|
||||
|
||||
else if(isbroken)
|
||||
return
|
||||
|
||||
/obj/machinery/station_slot_machine/proc/insert_cash(var/obj/item/weapon/spacecash/cashmoney, mob/user)
|
||||
if (ispowered == 0)
|
||||
return
|
||||
if (isbroken)
|
||||
return
|
||||
if (busy)
|
||||
to_chat(user,"<span class='notice'>The slot machine is currently rolling.</span> ")
|
||||
return
|
||||
if(cashmoney.worth < 5)
|
||||
to_chat(user,"<span class='notice'>You dont have enough Thalers to gamble!</span> ")
|
||||
return
|
||||
|
||||
to_chat(user,"<span class='notice'>You puts 5 Thalers in the slot machine and presses start.</span>")
|
||||
cashmoney.worth -= 5
|
||||
cashmoney.update_icon()
|
||||
|
||||
if(cashmoney.worth <= 0)
|
||||
usr.drop_from_inventory(cashmoney)
|
||||
qdel(cashmoney)
|
||||
cashmoney.update_icon()
|
||||
|
||||
busy = 1
|
||||
icon_state = "ntslotmachine_rolling"
|
||||
playsound(src.loc, 'sound/machines/slotmachine_pull.ogg', 15, 1)
|
||||
|
||||
var/slot1 = rand(0,9)
|
||||
switch(slot1)
|
||||
if(0 to 3) symbol1 = "cherry"
|
||||
if(4 to 4) symbol1 = "lemon"
|
||||
if(5 to 5) symbol1 = "bell"
|
||||
if(6 to 6) symbol1 = "four leaf clover"
|
||||
if(7 to 7) symbol1 = "seven"
|
||||
if(8 to 8) symbol1 = "diamond"
|
||||
if(9 to 9) symbol1 = "platinum coin"
|
||||
|
||||
var/slot2 = rand(0,16)
|
||||
switch(slot2)
|
||||
if(0 to 5) symbol2 = "cherry"
|
||||
if(6 to 7) symbol2 = "lemon"
|
||||
if(8 to 9) symbol2 = "bell"
|
||||
if(10 to 11) symbol2 = "four leaf clover"
|
||||
if(12 to 13) symbol2 = "seven"
|
||||
if(14 to 15) symbol2 = "diamond"
|
||||
if(16) symbol2 = "platinum coin"
|
||||
|
||||
var/slot3 = rand(0,9)
|
||||
switch(slot3)
|
||||
if(0 to 3) symbol3 = "cherry"
|
||||
if(4 to 4) symbol3 = "lemon"
|
||||
if(5 to 5) symbol3 = "bell"
|
||||
if(6 to 6) symbol3 = "four leaf clover"
|
||||
if(7 to 7) symbol3 = "seven"
|
||||
if(8 to 8) symbol3 = "diamond"
|
||||
if(9 to 9) symbol3 = "platinum coin"
|
||||
|
||||
var/output //Output variable to send out in chat after the large if statement.
|
||||
var/winnings = 0 //How much money will be given if any.
|
||||
var/platinumwin = 0 // If you win the platinum chip or not
|
||||
var/celebrate = 0
|
||||
var/delaytime = 5 SECONDS
|
||||
|
||||
|
||||
spawn(delaytime)
|
||||
to_chat(user,"<span class='notice'>The slot machine flashes with bright colours as the slots lights up with a [symbol1], a [symbol2] and a [symbol3]!</span>")
|
||||
|
||||
if (symbol1 == "cherry" && symbol2 == "cherry" && symbol3 == "cherry")
|
||||
output = "<span class='notice'>Three cherries! The slot machine deposits 25 Thalers!</span>"
|
||||
winnings = 25
|
||||
|
||||
if ((symbol1 != "cherry" && symbol2 == "cherry" && symbol3 == "cherry") || (symbol1 == "cherry" && symbol2 != "cherry" && symbol3 == "cherry") ||(symbol1 == "cherry" && symbol2 == "cherry" && symbol3 != "cherry"))
|
||||
output = "<span class='notice'>Two cherries! The slot machine deposits 10 Thalers!</span>"
|
||||
winnings = 10
|
||||
|
||||
if (symbol1 == "lemon" && symbol2 == "lemon" && symbol3 == "lemon")
|
||||
output = "<span class='notice'>Three lemons! The slot machine deposits 50 Thalers!</span>"
|
||||
winnings = 50
|
||||
|
||||
if (symbol1 == "watermelon" && symbol2 == "watermelon" && symbol3 == "watermelon")
|
||||
output = "<span class='notice'>Three watermelons! The slot machine deposits 75 Thalers!</span>"
|
||||
winnings = 75
|
||||
|
||||
if (symbol1 == "bell" && symbol2 == "bell" && symbol3 == "bell")
|
||||
output = "<span class='notice'>Three bells! The slot machine deposits 100 Thalers!</span>"
|
||||
winnings = 100
|
||||
|
||||
if (symbol1 == "four leaf clover" && symbol2 == "four leaf clover" && symbol3 == "four leaf clover")
|
||||
output = "<span class='notice'>Three four leaf clovers! The slot machine deposits 200 Thalers!</span>"
|
||||
winnings = 200
|
||||
|
||||
if (symbol1 == "seven" && symbol2 == "seven" && symbol3 == "seven")
|
||||
output = "<span class='notice'>Three sevens! The slot machine deposits 500 Thalers!</span>"
|
||||
winnings = 500
|
||||
celebrate = 1
|
||||
|
||||
if (symbol1 == "diamond" && symbol2 == "diamond" && symbol3 == "diamond")
|
||||
output = "<span class='notice'>Three diamonds! The slot machine deposits 1000 Thalers!</span>"
|
||||
winnings = 1000
|
||||
celebrate = 1
|
||||
|
||||
if (symbol1 == "platinum coin" && symbol2 == "platinum coin" && symbol3 == "platinum coin")
|
||||
output = "<span class='notice'>Three platinum coins! The slot machine deposits a platinum chip!</span>"
|
||||
platinumwin = TRUE;
|
||||
celebrate = 1
|
||||
|
||||
icon_state = initial(icon_state) // Set it back to the original iconstate.
|
||||
|
||||
if(!output) // Is there anything to output? If not, consider it a loss.
|
||||
to_chat(user,"Better luck next time!")
|
||||
busy = FALSE
|
||||
return
|
||||
|
||||
to_chat(user,output) //Output message
|
||||
|
||||
if(platinumwin) // Did they win the platinum chip?
|
||||
new /obj/item/weapon/casino_platinum_chip(src.loc)
|
||||
playsound(src.loc, 'sound/machines/slotmachine.ogg', 25, 1)
|
||||
|
||||
if(winnings) //Did the person win?
|
||||
icon_state = "ntslotmachine_winning"
|
||||
playsound(src.loc, 'sound/machines/slotmachine.ogg', 25, 1)
|
||||
spawn(delaytime)
|
||||
spawn_money(winnings, src.loc)
|
||||
icon_state = "ntslotmachine"
|
||||
|
||||
if(celebrate) // Happy celebrations!
|
||||
src.confetti_spread = new /datum/effect/effect/system/confetti_spread()
|
||||
src.confetti_spread.attach(src) //If somehow people start dragging slot machine
|
||||
spawn(0)
|
||||
for(var/i = 1 to confetti_strength)
|
||||
src.confetti_spread.start()
|
||||
sleep(10)
|
||||
|
||||
busy = FALSE
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "Casino Creature Container (Cat)"
|
||||
desc = "It is set to detonate in 5 seconds. It will release a cat won from the casino prize vendor!"
|
||||
icon = 'icons/obj/casino.dmi'
|
||||
icon_state = "casino"
|
||||
icon_state = "casino_delivery"
|
||||
item_state = "flashbang"
|
||||
origin_tech = list(TECH_MATERIAL = 2, TECH_MAGNET = 2)
|
||||
spawner_type = /mob/living/simple_mob/animal/passive/cat
|
||||
@@ -75,6 +75,11 @@
|
||||
name = "Casino Creature Container (Otie)"
|
||||
spawner_type = /mob/living/simple_mob/otie/friendly
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/casino/goldcrest
|
||||
desc = "It is set to detonate in 5 seconds. It will release a bird won from the casino prize vendor!"
|
||||
name = "Casino Creature Container (Bird)"
|
||||
spawner_type = /mob/living/simple_mob/animal/passive/bird/goldcrest
|
||||
|
||||
//
|
||||
// Mecha
|
||||
//
|
||||
|
||||
@@ -60,6 +60,14 @@
|
||||
cmd_admin_pm(C,null)
|
||||
return
|
||||
|
||||
if(href_list["mentorhelp_msg"])
|
||||
var/client/C = locate(href_list["mentorhelp_msg"])
|
||||
if(ismob(C))
|
||||
var/mob/M = C
|
||||
C = M.client
|
||||
cmd_mentor_pm(C, null)
|
||||
return
|
||||
|
||||
if(href_list["irc_msg"])
|
||||
if(!holder && received_irc_pm < world.time - 6000) //Worse they can do is spam IRC for 10 minutes
|
||||
to_chat(usr, "<span class='warning'>You are no longer able to use this, it's been more then 10 minutes since an admin on IRC has responded to you</span>")
|
||||
@@ -123,6 +131,7 @@
|
||||
|
||||
switch(href_list["_src_"])
|
||||
if("holder") hsrc = holder
|
||||
if("mentorholder") hsrc = (check_rights(R_ADMIN, 0) ? holder : mentorholder)
|
||||
if("usr") hsrc = mob
|
||||
if("prefs") return prefs.process_link(usr,href_list)
|
||||
if("vars") return view_var_Topic(href,href_list,hsrc)
|
||||
@@ -178,6 +187,7 @@
|
||||
GLOB.directory[ckey] = src
|
||||
|
||||
GLOB.ahelp_tickets.ClientLogin(src)
|
||||
GLOB.mhelp_tickets.ClientLogin(src)
|
||||
|
||||
//Admin Authorisation
|
||||
holder = admin_datums[ckey]
|
||||
@@ -185,6 +195,10 @@
|
||||
GLOB.admins += src
|
||||
holder.owner = src
|
||||
|
||||
mentorholder = mentor_datums[ckey]
|
||||
if (mentorholder)
|
||||
mentorholder.associate(GLOB.directory[ckey])
|
||||
|
||||
//preferences datum - also holds some persistant data for the client (because we may as well keep these datums to a minimum)
|
||||
prefs = preferences_datums[ckey]
|
||||
if(!prefs)
|
||||
@@ -262,7 +276,11 @@
|
||||
if(holder)
|
||||
holder.owner = null
|
||||
GLOB.admins -= src
|
||||
if (mentorholder)
|
||||
mentorholder.owner = null
|
||||
GLOB.mentors -= src
|
||||
GLOB.ahelp_tickets.ClientLogout(src)
|
||||
GLOB.mhelp_tickets.ClientLogout(src)
|
||||
GLOB.directory -= ckey
|
||||
GLOB.clients -= src
|
||||
return ..()
|
||||
|
||||
@@ -14,12 +14,14 @@
|
||||
//CHOMPEdit Begin
|
||||
S["species"] >> pref.species
|
||||
//CHOMPEdit End
|
||||
S["language_custom_keys"] >> pref.language_custom_keys
|
||||
|
||||
/datum/category_item/player_setup_item/general/language/save_character(var/savefile/S)
|
||||
S["language"] << pref.alternate_languages
|
||||
S["extra_languages"] << pref.extra_languages
|
||||
testing("LANGSANI: Saved to [pref.client]'s character [pref.real_name || "-name not yet loaded-"] savefile: [english_list(pref.alternate_languages || list())]")
|
||||
S["language_prefixes"] << pref.language_prefixes
|
||||
S["language_custom_keys"] << pref.language_custom_keys
|
||||
|
||||
/datum/category_item/player_setup_item/general/language/sanitize_character()
|
||||
if(!islist(pref.alternate_languages)) pref.alternate_languages = list()
|
||||
@@ -43,6 +45,14 @@
|
||||
for(var/prefix in pref.language_prefixes)
|
||||
if(prefix in forbidden_prefixes)
|
||||
pref.language_prefixes -= prefix
|
||||
if(isnull(pref.language_custom_keys))
|
||||
pref.language_custom_keys = list()
|
||||
var/datum/species/S = GLOB.all_species[pref.species]
|
||||
for(var/key in pref.language_custom_keys)
|
||||
if(!pref.language_custom_keys[key])
|
||||
pref.language_custom_keys.Remove(key)
|
||||
if(!((pref.language_custom_keys[key] == S.language) || (pref.language_custom_keys[key] == S.default_language && S.default_language != S.language) || (pref.language_custom_keys[key] in pref.alternate_languages)))
|
||||
pref.language_custom_keys.Remove(key)
|
||||
|
||||
/datum/category_item/player_setup_item/general/language/content()
|
||||
. += "<b>Languages</b><br>"
|
||||
@@ -51,14 +61,15 @@
|
||||
testing("LANGSANI: Truncated [pref.client]'s character [pref.real_name || "-name not yet loaded-"] language list because it was too long (len: [pref.alternate_languages.len], allowed: [S.num_alternate_languages])")
|
||||
pref.alternate_languages.len = (S.num_alternate_languages + pref.extra_languages) // Truncate to allowed length
|
||||
if(S.language)
|
||||
. += "- [S.language]<br>"
|
||||
. += "- [S.language] - <a href='?src=\ref[src];set_custom_key=[S.language]'>Set Custom Key</a><br>"
|
||||
if(S.default_language && S.default_language != S.language)
|
||||
. += "- [S.default_language]<br>"
|
||||
. += "- [S.default_language] - <a href='?src=\ref[src];set_custom_key=[S.default_language]'>Set Custom Key</a><br>"
|
||||
if(S.num_alternate_languages + pref.extra_languages)
|
||||
if(pref.alternate_languages.len)
|
||||
for(var/i = 1 to pref.alternate_languages.len)
|
||||
var/lang = pref.alternate_languages[i]
|
||||
. += "- [lang] - <a href='?src=\ref[src];remove_language=[i]'>remove</a><br>"
|
||||
. += "- [lang] - <a href='?src=\ref[src];remove_language=[i]'>remove</a> - <a href='?src=\ref[src];set_custom_key=[lang]'>Set Custom Key</a><br>"
|
||||
|
||||
if(pref.alternate_languages.len < (S.num_alternate_languages + pref.extra_languages))
|
||||
. += "- <a href='?src=\ref[src];add_language=1'>add</a> ([(S.num_alternate_languages + pref.extra_languages) - pref.alternate_languages.len] remaining)<br>"
|
||||
else
|
||||
@@ -125,4 +136,32 @@
|
||||
pref.language_prefixes = config.language_prefixes.Copy()
|
||||
return TOPIC_REFRESH
|
||||
|
||||
else if(href_list["set_custom_key"])
|
||||
var/lang = href_list["set_custom_key"]
|
||||
if(!(lang in GLOB.all_languages))
|
||||
return TOPIC_REFRESH
|
||||
|
||||
var/oldkey = ""
|
||||
for(var/key in pref.language_custom_keys)
|
||||
if(pref.language_custom_keys[key] == lang)
|
||||
oldkey = key
|
||||
break
|
||||
|
||||
var/char = tgui_input_text(user, "Input a language key for [lang]. Input a single space to reset.", "Language Custom Key", oldkey)
|
||||
if(length(char) != 1)
|
||||
return TOPIC_REFRESH
|
||||
else if(char == " ")
|
||||
for(var/key in pref.language_custom_keys)
|
||||
if(pref.language_custom_keys[key] == lang)
|
||||
pref.language_custom_keys -= key
|
||||
break
|
||||
else if(contains_az09(char))
|
||||
if(!(char in pref.language_custom_keys))
|
||||
pref.language_custom_keys += char
|
||||
pref.language_custom_keys[char] = lang
|
||||
else
|
||||
tgui_alert_async(user, "Improper language key. Rejected.", "Error")
|
||||
|
||||
return TOPIC_REFRESH
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -364,6 +364,12 @@ var/list/_client_preferences_by_type
|
||||
enabled_description = "Popup New On Login"
|
||||
disabled_description = "Do Nothing"
|
||||
|
||||
/datum/client_preference/play_mentorhelp_ping
|
||||
description = "Mentorhelps"
|
||||
key = "SOUND_MENTORHELP"
|
||||
enabled_description = "Hear"
|
||||
disabled_description = "Silent"
|
||||
|
||||
/********************
|
||||
* Staff Preferences *
|
||||
********************/
|
||||
|
||||
@@ -282,6 +282,13 @@
|
||||
ckeywhitelist = list("coolcrow420")
|
||||
character_name = list("Jade Davis")
|
||||
|
||||
/datum/gear/fluff/m4il_hdd
|
||||
path = /obj/item/weapon/implant/language/fluff/m41l
|
||||
display_name = "dusty hard drive"
|
||||
slot = "implant"
|
||||
ckeywhitelist = list("coolcrow420")
|
||||
character_name = list("M41L")
|
||||
|
||||
// D CKEYS
|
||||
/datum/gear/fluff/dhaeleena_medal
|
||||
path = /obj/item/clothing/accessory/medal/silver/security/fluff/dhael
|
||||
|
||||
@@ -49,6 +49,14 @@
|
||||
display_name = "pink tiger pelt"
|
||||
path = /obj/item/clothing/head/pelt/tigerpeltpink
|
||||
|
||||
/datum/gear/head/magic_hat
|
||||
display_name = "wizard hat, colorable"
|
||||
path = /obj/item/clothing/head/wizard/fake/realistic/colorable
|
||||
|
||||
/datum/gear/head/magic_hat/New()
|
||||
..()
|
||||
gear_tweaks += gear_tweak_free_color_choice
|
||||
|
||||
/*
|
||||
Talon hats
|
||||
*/
|
||||
|
||||
@@ -292,36 +292,13 @@ Talon jumpsuit
|
||||
path = /obj/item/clothing/under/undersuit/command
|
||||
|
||||
//Altevian Uniforms
|
||||
/datum/gear/uniform/job_altevian/cmd
|
||||
display_name = "altevian uniform, cmd"
|
||||
path = /obj/item/clothing/under/pants/altevian/command
|
||||
allowed_roles = list("Head of Security","Site Manager","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer")
|
||||
/datum/gear/uniform/altevian
|
||||
description = "An extremely comfortable set of clothing that's made to help people handle their day to day work around the fleets with little to no discomfort."
|
||||
display_name = "altevian uniform selection"
|
||||
|
||||
/datum/gear/uniform/job_altevian/sec
|
||||
display_name = "altevian uniform, sec"
|
||||
path = /obj/item/clothing/under/pants/altevian/security
|
||||
allowed_roles = list("Head of Security", "Warden", "Detective", "Security Officer")
|
||||
|
||||
/datum/gear/uniform/job_altevian/med
|
||||
display_name = "altevian uniform, med"
|
||||
path = /obj/item/clothing/under/pants/altevian/medical
|
||||
allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Paramedic","Geneticist","Field Medic","Psychiatrist")
|
||||
|
||||
/datum/gear/uniform/job_altevian/eng
|
||||
display_name = "altevian uniform, eng"
|
||||
path = /obj/item/clothing/under/pants/altevian/engineering
|
||||
allowed_roles = list("Chief Engineer","Atmospheric Technician","Engineer")
|
||||
|
||||
/datum/gear/uniform/job_altevian/sci
|
||||
display_name = "altevian uniform, sci"
|
||||
path = /obj/item/clothing/under/pants/altevian/science
|
||||
allowed_roles = list("Research Director", "Scientist", "Roboticist", "Xenobiologist", "Xenobotanist")
|
||||
|
||||
/datum/gear/uniform/job_altevian/crg
|
||||
display_name = "altevian uniform, cargo"
|
||||
path = /obj/item/clothing/under/pants/altevian/cargo
|
||||
allowed_roles = list("Quartermaster", "Cargo Technician", "Shaft Miner")
|
||||
|
||||
/datum/gear/uniform/job_altevian/civ
|
||||
display_name = "altevian uniform, civ"
|
||||
path = /obj/item/clothing/under/pants/altevian
|
||||
/datum/gear/uniform/altevian/New()
|
||||
..()
|
||||
var/list/pants = list()
|
||||
for(var/obj/item/clothing/under/pants/altevian/pants_type as anything in typesof(/obj/item/clothing/under/pants/altevian))
|
||||
pants[initial(pants_type.name)] = pants_type
|
||||
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(pants))
|
||||
@@ -167,9 +167,9 @@
|
||||
sort_category = "Xenowear"
|
||||
|
||||
/datum/gear/uniform/dept/undercoat/cap
|
||||
display_name = "facility director undercoat (Teshari)"
|
||||
display_name = "site manager undercoat (Teshari)"
|
||||
path = /obj/item/clothing/under/teshari/undercoat/jobs/cap
|
||||
allowed_roles = list("Facility Director")
|
||||
allowed_roles = list("Site Manager")
|
||||
|
||||
/datum/gear/uniform/dept/undercoat/hop
|
||||
display_name = "head of personnel undercoat (Teshari)"
|
||||
@@ -276,9 +276,9 @@
|
||||
sort_category = "Xenowear"
|
||||
|
||||
/datum/gear/suit/dept/cloak/cap
|
||||
display_name = "facility director cloak (Teshari)"
|
||||
display_name = "site manager cloak (Teshari)"
|
||||
path = /obj/item/clothing/suit/storage/teshari/cloak/jobs
|
||||
allowed_roles = list("Facility Director")
|
||||
allowed_roles = list("Site Manager")
|
||||
|
||||
/datum/gear/suit/dept/cloak/hop
|
||||
display_name = "head of personnel cloak (Teshari)"
|
||||
|
||||
@@ -94,5 +94,14 @@
|
||||
|
||||
/datum/gear/suit/taur/white_dress
|
||||
display_name = "white wedding dress (Wolf/Horse-taur)"
|
||||
path = /obj/item/clothing/suit/taur_dress/white
|
||||
path = /obj/item/clothing/suit/taur/dress
|
||||
sort_category = "Xenowear"
|
||||
|
||||
/datum/gear/uniform/taur/colorable_skirt
|
||||
display_name = "colorable skirt (Wolf/Horse-taur)"
|
||||
path = /obj/item/clothing/under/taur/skirt
|
||||
sort_category = "Xenowear"
|
||||
|
||||
/datum/gear/uniform/taur/colorable_skirt/New()
|
||||
..()
|
||||
gear_tweaks += gear_tweak_free_color_choice
|
||||
|
||||
@@ -63,7 +63,8 @@ var/list/preferences_datums = list()
|
||||
var/species = SPECIES_HUMAN //Species datum to use.
|
||||
var/species_preview //Used for the species selection window.
|
||||
var/list/alternate_languages = list() //Secondary language(s)
|
||||
var/list/language_prefixes = list() //Kanguage prefix keys
|
||||
var/list/language_prefixes = list() //Language prefix keys
|
||||
var/list/language_custom_keys = list() //Language custom call keys
|
||||
var/list/gear //Left in for Legacy reasons, will no longer save.
|
||||
var/list/gear_list = list() //Custom/fluff item loadouts.
|
||||
var/gear_slot = 1 //The current gear save slot
|
||||
|
||||
@@ -105,3 +105,18 @@
|
||||
SScharacter_setup.queue_preferences_save(prefs)
|
||||
|
||||
feedback_add_details("admin_verb","TCaptureCrystal") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/verb/toggle_mentorhelp_ping()
|
||||
set name = "Toggle Mentorhelp Ping"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggles the mentorhelp ping"
|
||||
|
||||
var/pref_path = /datum/client_preference/play_mentorhelp_ping
|
||||
|
||||
toggle_preference(pref_path)
|
||||
|
||||
to_chat(src, "Mentorhelp pings are now [ is_preference_enabled(pref_path) ? "enabled" : "disabled"]")
|
||||
|
||||
SScharacter_setup.queue_preferences_save(prefs)
|
||||
|
||||
feedback_add_details("admin_verb", "TSoundMentorhelps")
|
||||
|
||||
@@ -224,8 +224,6 @@
|
||||
persist_storable = FALSE
|
||||
/obj/item/weapon/gun/energy/sizegun/admin
|
||||
persist_storable = FALSE
|
||||
/obj/item/weapon/gun/energy/sizegun/abductor
|
||||
persist_storable = FALSE
|
||||
/obj/item/stack
|
||||
persist_storable = FALSE
|
||||
/obj/item/weapon/book
|
||||
@@ -252,3 +250,7 @@
|
||||
persist_storable = FALSE
|
||||
/obj/item/weapon/rcd
|
||||
persist_storable = FALSE
|
||||
/obj/item/weapon/spacecash
|
||||
persist_storable = FALSE
|
||||
/obj/item/weapon/spacecasinocash
|
||||
persist_storable = FALSE
|
||||
|
||||
@@ -121,6 +121,28 @@
|
||||
if(config.show_event_managers)
|
||||
msg += "\n<b> Current Miscellaneous ([num_event_managers_online]):</b>\n" + eventMmsg
|
||||
|
||||
var/num_mentors_online = 0
|
||||
var/mmsg = ""
|
||||
|
||||
for(var/client/C in GLOB.mentors)
|
||||
num_mentors_online++
|
||||
mmsg += "\t[C] is a Mentor"
|
||||
if(holder)
|
||||
if(isobserver(C.mob))
|
||||
mmsg += " - Observing"
|
||||
else if(istype(C.mob,/mob/new_player))
|
||||
mmsg += " - Lobby"
|
||||
else
|
||||
mmsg += " - Playing"
|
||||
|
||||
if(C.is_afk())
|
||||
var/seconds = C.last_activity_seconds()
|
||||
mmsg += " (AFK - [round(seconds / 60)] minutes, [seconds % 60] seconds)"
|
||||
mmsg += "\n"
|
||||
|
||||
if(config.show_mentors)
|
||||
msg += "\n<b> Current Mentors ([num_mentors_online]):</b>\n" + mmsg
|
||||
|
||||
msg += "\n<span class='info'>Adminhelps are also sent to Discord. If no admins are available in game try anyway and an admin on Discord may see it and respond.</span>"
|
||||
|
||||
to_chat(src, msg)
|
||||
|
||||
@@ -786,7 +786,7 @@
|
||||
var/image/standing = ..()
|
||||
if(taurized) //Special snowflake var on suits
|
||||
standing.pixel_x = -16
|
||||
standing.layer = BODY_LAYER + 16 // 16 is above tail layer, so will not be covered by taurbody.
|
||||
standing.layer = BODY_LAYER + 17 // 17 is above tail layer, so will not be covered by taurbody. TAIL_UPPER_LAYER +1
|
||||
return standing
|
||||
|
||||
/obj/item/clothing/suit/apply_accessories(var/image/standing)
|
||||
|
||||
@@ -120,6 +120,7 @@
|
||||
species_restricted = list("Vox")
|
||||
drop_sound = 'sound/items/drop/metalboots.ogg'
|
||||
pickup_sound = 'sound/items/pickup/toolbox.ogg'
|
||||
armor = list (melee = 20, bullet = 15, laser = 10, energy = 10, bomb =5, bio = 30, rad = 30) //gently bumped up Heavy engineering gloves value for protection //ChompEdit
|
||||
|
||||
cold_protection = HANDS
|
||||
min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
icon_state = "boots-vox"
|
||||
flags = PHORONGUARD
|
||||
species_restricted = list(SPECIES_VOX)
|
||||
armor = list (melee = 40, bullet = 10, laser = 10, energy = 20, bomb = 20, bio = 10, rad = 20) //values of workboots and heavy duty engineering gloves, it's the only option that will ever be taken so may as well give the turkeys some protection //ChompEdit
|
||||
|
||||
action_button_name = "Toggle the magclaws"
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
suit_type = "sinister alien"
|
||||
icon_state = "voxstealth_rig"
|
||||
desc = "A light alien rig for repairs and maintenance to the outside of habitats and vessels."
|
||||
armor = list(melee = 30, bullet = 10, laser = 20,energy = 25, bomb = 20, bio = 100, rad = 100) //Standard Engineering Suit Values
|
||||
armor = list(melee = 30, bullet = 10, laser = 20, energy = 25, bomb = 20, bio = 100, rad = 100) //Standard Engineering Suit Values
|
||||
|
||||
req_access = list()
|
||||
req_one_access = list()
|
||||
@@ -152,3 +152,40 @@
|
||||
|
||||
initial_modules = list(
|
||||
)
|
||||
//ChompEdit Begins
|
||||
|
||||
/obj/item/weapon/rig/vox/engineering
|
||||
name = "fluid alien control module"
|
||||
suit_type = "sinister alien"
|
||||
icon_state = "voxstealth_rig"
|
||||
desc = "A lightweight, alien rig dedicated for construction and engineering tasks. Not reccomended for hostile engagement."
|
||||
armor = list (melee = 25, bullet = 5, laser = 40, energy = 45, bomb = 50, bio = 100, rad = 100) //CE suit values but shuffled to a tighter focus on the job hazards
|
||||
flags = PHORONGUARD
|
||||
item_flags = THICKMATERIAL
|
||||
siemens_coefficient = 0
|
||||
offline_slowdown = 2.5
|
||||
slowdown = 0
|
||||
emp_protection = 40 //change this to 30 if too high.
|
||||
|
||||
req_one_access = list()
|
||||
allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage)
|
||||
offline_vision_restriction = 1
|
||||
|
||||
initial_modules = list(
|
||||
)
|
||||
|
||||
air_type = /obj/item/weapon/tank/vox
|
||||
|
||||
max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE
|
||||
|
||||
/obj/item/weapon/rig/vox_engine_technition_control_module/equipped
|
||||
req_access = list(access_engine)
|
||||
|
||||
initial_modules = list(
|
||||
/obj/item/rig_module/maneuvering_jets,
|
||||
/obj/item/rig_module/device/plasmacutter,
|
||||
/obj/item/rig_module/device/rcd,
|
||||
/obj/item/rig_module/vision/meson
|
||||
)
|
||||
|
||||
//ChompEdit Ends
|
||||
|
||||
@@ -261,6 +261,7 @@
|
||||
slowdown = 0.5
|
||||
offline_vision_restriction = 1
|
||||
siemens_coefficient= 0.75
|
||||
seal_delay = 5
|
||||
|
||||
helm_type = /obj/item/clothing/head/helmet/space/rig/medical
|
||||
|
||||
|
||||
@@ -106,8 +106,8 @@
|
||||
|
||||
// Job Cloaks
|
||||
/obj/item/clothing/suit/storage/teshari/cloak/jobs/cap
|
||||
name = "facility director cloak"
|
||||
desc = "A soft Teshari cloak made for the Facility Director"
|
||||
name = "site manager cloak"
|
||||
desc = "A soft Teshari cloak made for the Site Manager"
|
||||
icon_state = "tesh_cloak_cap"
|
||||
|
||||
//Cargo
|
||||
|
||||
@@ -74,12 +74,12 @@
|
||||
desc = "Knightly armor for a mount who doesn't need any rider. This one is marked to the house of Mason."
|
||||
icon_state = "Mason_barding"
|
||||
|
||||
/obj/item/clothing/suit/taur_dress
|
||||
/obj/item/clothing/suit/taur
|
||||
icon = 'icons/mob/taursuits_horse_vr.dmi'
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO
|
||||
pixel_x = -16
|
||||
|
||||
/obj/item/clothing/suit/taur_dress/white
|
||||
/obj/item/clothing/suit/taur/dress
|
||||
name = "white wedding dress"
|
||||
desc = "A fancy white dress with a blue underdress."
|
||||
icon_state = "whitedress1"
|
||||
|
||||
@@ -18,6 +18,16 @@
|
||||
desc = "It has WIZZARD written across it in sequins. Comes with a cool beard."
|
||||
icon_state = "wizard-fake"
|
||||
body_parts_covered = HEAD|FACE
|
||||
siemens_coefficient = 1
|
||||
|
||||
/obj/item/clothing/head/wizard/fake/realistic
|
||||
desc = "A cool-looking 'magic' hat."
|
||||
icon_state = "wizard"
|
||||
body_parts_covered = HEAD
|
||||
|
||||
/obj/item/clothing/head/wizard/fake/realistic/colorable
|
||||
desc = "A cool-looking 'magic' hat."
|
||||
icon_state = "wizard-white"
|
||||
|
||||
/obj/item/clothing/head/wizard/marisa
|
||||
name = "Witch Hat"
|
||||
|
||||
@@ -300,6 +300,10 @@
|
||||
name = "medal of exceptional heroism"
|
||||
desc = "An extremely rare golden medal awarded only by high ranking officials. To recieve such a medal is the highest honor and as such, very few exist. This medal is almost never awarded to anybody but distinguished veteran staff."
|
||||
|
||||
/obj/item/clothing/accessory/medal/gold/casino
|
||||
name = "medal of true lucky winner"
|
||||
desc = "A gaudy golden medal with a logo of a casino engraved on top. The only achievement you had to earn this was great luck or great richness, neither of which is an achievement. Still, it instills a feeling of hope and smell of fresh bagels."
|
||||
|
||||
// Base type for 'medals' found in a "dungeon" submap, as a sort of trophy to celebrate the player's conquest.
|
||||
/obj/item/clothing/accessory/medal/dungeon
|
||||
|
||||
|
||||
@@ -409,3 +409,30 @@
|
||||
icon_state = "talon_pin"
|
||||
item_state = "talonpin"
|
||||
overlay_state = "talonpin"
|
||||
|
||||
//Casino Sentient Prize Collar
|
||||
|
||||
/obj/item/clothing/accessory/collar/casinosentientprize
|
||||
name = "disabled Sentient Prize Collar"
|
||||
desc = "A collar worn by sentient prizes registered to a SPASM. Although the red text on it shows its disconnected and nonfunctional."
|
||||
|
||||
icon_state = "casinoslave"
|
||||
item_state = "casinoslave"
|
||||
overlay_state = "casinoslave"
|
||||
|
||||
var/sentientprizename = null //Name for system to put on collar description
|
||||
var/ownername = null //Name for system to put on collar description
|
||||
var/sentientprizeckey = null //Ckey for system to check who is the person and ensure no abuse of system or errors
|
||||
var/sentientprizeflavor = null //Description to show on the SPASM
|
||||
var/sentientprizeooc = null //OOC text to show on the SPASM
|
||||
|
||||
/obj/item/clothing/accessory/collar/casinosentientprize/attack_self(mob/user as mob)
|
||||
//keeping it blank so people don't tag and reset collar status
|
||||
|
||||
/obj/item/clothing/accessory/collar/casinosentientprize_fake
|
||||
name = "Sentient Prize Collar"
|
||||
desc = "A collar worn by sentient prizes registered to a SPASM. This one has been disconnected from the system and is now an accessory!"
|
||||
|
||||
icon_state = "casinoslave_owned"
|
||||
item_state = "casinoslave_owned"
|
||||
overlay_state = "casinoslave_owned"
|
||||
|
||||
@@ -3,16 +3,12 @@
|
||||
desc = "A small device used to measure body radiation and warning one after a certain threshold. \
|
||||
Read manual before use! Can be held, attached to the uniform or worn around the neck."
|
||||
w_class = ITEMSIZE_SMALL
|
||||
|
||||
icon = 'icons/inventory/accessory/item_vr.dmi'
|
||||
icon_override = 'icons/inventory/accessory/item_vr.dmi'
|
||||
|
||||
icon_state = "dosimeter"
|
||||
item_state = "dosimeter"
|
||||
overlay_state = "dosimeter"
|
||||
|
||||
slot_flags = SLOT_TIE
|
||||
|
||||
var/obj/item/weapon/dosimeter_film/current_film = null
|
||||
|
||||
/obj/item/clothing/accessory/dosimeter/New()
|
||||
@@ -80,19 +76,15 @@
|
||||
current_film.icon_state = "dosimeter_film[tostate]"
|
||||
else
|
||||
icon_state = "[initial(icon_state)]-empty"
|
||||
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/dosimeter_film
|
||||
name = "dosimeter film"
|
||||
desc = "These films can be inserted into dosimeters. It turns from white to black, depending on how much radiation it endured."
|
||||
w_class = ITEMSIZE_SMALL
|
||||
|
||||
icon = 'icons/inventory/accessory/item_vr.dmi'
|
||||
icon_override = 'icons/inventory/accessory/item_vr.dmi'
|
||||
|
||||
icon_state = "dosimeter_film0"
|
||||
|
||||
var/state = 0 //0 - White, 1 - Darker, 2 - Black (same as iconstates)
|
||||
|
||||
/obj/item/weapon/dosimeter_film/proc/update_state(var/tostate)
|
||||
@@ -117,10 +109,13 @@
|
||||
/obj/item/weapon/storage/box/dosimeter
|
||||
name = "dosimeter case"
|
||||
desc = "This case can only hold the Dosimeter, a few films and a manual."
|
||||
icon = 'icons/inventory/accessory/item_vr.dmi'
|
||||
icon_override = 'icons/inventory/accessory/item_vr.dmi'
|
||||
icon_state = "dosimeter_case"
|
||||
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
|
||||
storage_slots = 5
|
||||
can_hold = list(/obj/item/weapon/paper/dosimeter_manual, /obj/item/clothing/accessory/dosimeter, /obj/item/weapon/dosimeter_film)
|
||||
max_storage_space = (ITEMSIZE_COST_SMALL * 2) + (ITEMSIZE_COST_TINY * 3)
|
||||
max_storage_space = (ITEMSIZE_COST_SMALL * 4) + (ITEMSIZE_COST_TINY * 1)
|
||||
w_class = ITEMSIZE_SMALL
|
||||
|
||||
/obj/item/weapon/storage/box/dosimeter/New()
|
||||
|
||||
@@ -45,9 +45,11 @@
|
||||
/obj/item/clothing/accessory/holster/machete/rapier/holster(var/obj/item/I, var/mob/living/user)
|
||||
..()
|
||||
occupied()
|
||||
if(has_suit)
|
||||
has_suit.update_clothing_icon()
|
||||
|
||||
/obj/item/clothing/accessory/holster/machete/rapier/unholster(var/obj/item/I, var/mob/living/user)
|
||||
..()
|
||||
occupied()
|
||||
if(has_suit)
|
||||
has_suit.update_clothing_icon()
|
||||
|
||||
@@ -377,3 +377,14 @@
|
||||
desc = "A very descript undersuit, intended for wearing under a voidsuit or other EVA equipment. This one is specifically made for NanoTrasen Central Command officers, and comes with a swanky gold trim and other fancy markings."
|
||||
icon_state = "bodysuit_cent"
|
||||
item_state = "bodysuit_cent"
|
||||
|
||||
/obj/item/clothing/under/taur
|
||||
icon = 'icons/mob/taursuits_horse_vr.dmi'
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO
|
||||
pixel_x = -16
|
||||
|
||||
/obj/item/clothing/under/taur/skirt
|
||||
name = "black skirt"
|
||||
desc = "A fancy black skirt with white corset."
|
||||
icon_state = "skirt_colorable"
|
||||
flags_inv = HIDESHOES
|
||||
|
||||
@@ -221,8 +221,8 @@
|
||||
|
||||
//Job Undercoats
|
||||
/obj/item/clothing/under/teshari/undercoat/jobs/cap
|
||||
name = "facility director undercoat"
|
||||
desc = "A traditional Teshari garb made for the Facility Director"
|
||||
name = "site manager undercoat"
|
||||
desc = "A traditional Teshari garb made for the Site Manager"
|
||||
icon_state = "tesh_uniform_cap"
|
||||
|
||||
/obj/item/clothing/under/teshari/undercoat/jobs/hop
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
h_user.drop_from_inventory(src)
|
||||
h_user.drop_from_inventory(SC)
|
||||
h_user.put_in_hands(SC)
|
||||
user << "<span class='notice'>You combine the casino chips to a stack of [SC.worth] of credits.</span>"
|
||||
user << "<span class='notice'>You combine the casino chips to a stack of [SC.worth] credits.</span>"
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/spacecasinocash/update_icon()
|
||||
@@ -57,7 +57,7 @@
|
||||
M.Turn(pick(-45, -27.5, 0, 0, 0, 0, 0, 0, 0, 27.5, 45))
|
||||
banknote.transform = M
|
||||
src.overlays += banknote
|
||||
src.desc = "They are worth [worth] of credits."
|
||||
src.desc = "They are worth [worth] credits."
|
||||
|
||||
/obj/item/weapon/spacecasinocash/proc/adjust_worth(var/adjust_worth = 0, var/update = 1)
|
||||
worth += adjust_worth
|
||||
|
||||
@@ -3538,3 +3538,18 @@
|
||||
/obj/item/weapon/reagent_containers/food/drinks/cans/root_beer = 1)
|
||||
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
|
||||
vending_sound = "machines/vending/vending_cans.ogg"
|
||||
|
||||
/obj/machinery/vending/altevian
|
||||
name = "Altevian Imported Meals"
|
||||
desc = "A vending machine containing imported foods from Altevian Hegemony. Delicious and nutritious. No natural ingridients guaranteed!"
|
||||
icon = 'icons/obj/vending_vr.dmi'
|
||||
icon_state = "rattevendor"
|
||||
product_slogans = "Spacer's choice!;Voidborn food for voidborn people!;Most processed foods ever!"
|
||||
product_ads = "Perfectly edible!;Squeaky clean foods!;Cheesed to meet you!;Made for spacers, by spacers, of spacers!"
|
||||
products = list(/obj/item/weapon/reagent_containers/food/snacks/ratprotein = 15,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/ratveggies = 15,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/ratliquid = 15)
|
||||
|
||||
prices = list(/obj/item/weapon/reagent_containers/food/snacks/ratprotein = 8,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/ratveggies = 8,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/ratliquid = 8)
|
||||
|
||||
@@ -54,7 +54,8 @@
|
||||
/obj/machinery/vending/sol,
|
||||
/obj/machinery/vending/snix,
|
||||
/obj/machinery/vending/snlvend,
|
||||
/obj/machinery/vending/sovietvend)
|
||||
/obj/machinery/vending/sovietvend,
|
||||
/obj/machinery/vending/altevian)
|
||||
|
||||
/obj/item/weapon/refill_cartridge/multitype/drink
|
||||
name = "drinks vendor refill cartridge"
|
||||
@@ -121,6 +122,9 @@
|
||||
/obj/item/weapon/refill_cartridge/autoname/food/sovietvend
|
||||
refill_type = /obj/machinery/vending/sovietvend
|
||||
|
||||
/obj/item/weapon/refill_cartridge/autoname/food/altevian
|
||||
refill_type = /obj/machinery/vending/altevian
|
||||
|
||||
/obj/item/weapon/refill_cartridge/autoname/drink
|
||||
icon_state = "rc_drink"
|
||||
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
//////////////////CHOMP//////////////////////////
|
||||
|
||||
/datum/reagent/ethanol/cloverclub
|
||||
glass_icon_state = "cloverclub"
|
||||
glass_icon_source = 'icons/obj/drinks_ch.dmi'
|
||||
glass_center_of_mass = list("x"=16, "y"=8)
|
||||
|
||||
/datum/reagent/ethanol/spiderdrink
|
||||
glass_icon_state = "glassofspiders"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
|
||||
/datum/reagent/drink/tea/minttea
|
||||
glass_icon_file = "bigteacup"
|
||||
|
||||
/datum/reagent/drink/tea/lemontea
|
||||
glass_icon_file = "bigteacup"
|
||||
|
||||
/datum/reagent/drink/tea/limetea
|
||||
glass_icon_file = "bigteacup"
|
||||
|
||||
/datum/reagent/drink/tea/orangetea
|
||||
glass_icon_file = "bigteacup"
|
||||
|
||||
/datum/reagent/drink/tea/berrytea
|
||||
glass_icon_file = "bigteacup"
|
||||
|
||||
/datum/reagent/drink/tea/cherrytea
|
||||
glass_icon_file = "bigteacup"
|
||||
|
||||
/datum/reagent/drink/tea/watermelontea
|
||||
glass_icon_file = "bigteacup"
|
||||
|
||||
/datum/reagent/drink/bubbleteawatermelon
|
||||
glass_icon_state = "bubbleteawatermelonglass"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
glass_center_of_mass = list("x"=16, "y"=9)
|
||||
|
||||
/datum/reagent/drink/bubbleteastrawberry
|
||||
glass_icon_state = "bubbleteastrawberryglass"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
glass_center_of_mass = list("x"=16, "y"=9)
|
||||
|
||||
/datum/reagent/drink/bubbleteacherry
|
||||
glass_icon_state = "bubbleteacherryglass"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
glass_center_of_mass = list("x"=16, "y"=9)
|
||||
|
||||
/datum/reagent/drink/bubbleteacoffee
|
||||
glass_icon_state = "bubbleteacoffeeglass"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
glass_center_of_mass = list("x"=16, "y"=9)
|
||||
|
||||
/datum/reagent/drink/bubbleteabanana
|
||||
glass_icon_state = "bubbleteabananaglass"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
glass_center_of_mass = list("x"=16, "y"=9)
|
||||
|
||||
/datum/reagent/drink/tea/matcha_latte
|
||||
glass_icon_state = "bigteacup"
|
||||
|
||||
/datum/reagent/drink/horchata
|
||||
glass_icon_state = "horchata"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
glass_center_of_mass = list("x"=16, "y"=7)
|
||||
|
||||
/datum/reagent/toxin/bluetrain
|
||||
glass_icon_state = "bluetrain"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
glass_center_of_mass = list("x"=16, "y"=8)
|
||||
|
||||
/datum/reagent/drink/lovepotion
|
||||
glass_icon_state = "lovepotion"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
|
||||
/datum/reagent/drink/lowpower
|
||||
glass_icon_state = "lowpower"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
|
||||
/datum/reagent/ethanol/coffee/jackbrew
|
||||
glass_icon_state = "jackbrew"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
|
||||
/datum/reagent/ethanol/bookwyrm
|
||||
glass_icon_state = "bookwyrm"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
|
||||
/datum/reagent/drink/highpower
|
||||
glass_icon_state = "highpower"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
|
||||
/datum/reagent/ethanol/flapper
|
||||
glass_icon_state = "flapper"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
|
||||
/datum/reagent/toxin/oilslide
|
||||
glass_icon_state = "oilslide"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
|
||||
/datum/reagent/ethanol/sitonmyface
|
||||
glass_icon_state = "sitonmyface"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
|
||||
/datum/reagent/ethanol/hachi
|
||||
glass_icon_state = "hachi"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
|
||||
/datum/reagent/ethanol/mojito
|
||||
glass_icon_state = "mojito"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
|
||||
/datum/reagent/slimedrink
|
||||
glass_icon_state = "slimedrink"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
|
||||
/datum/reagent/ethanol/arachnidslammer
|
||||
glass_icon_state = "arachnidslammer"
|
||||
glass_icon_file = 'icons/obj/drinks_ch.dmi'
|
||||
|
||||
/datum/reagent/drink/pilk
|
||||
glass_icon_state = "whiskeyglass"
|
||||
glass_icon_file = 'icons/obj/drinks.dmi'
|
||||
@@ -774,3 +774,55 @@
|
||||
. = ..()
|
||||
reagents.add_reagent("uranium", 3)
|
||||
reagents.add_reagent("pyrotoxin", 3)
|
||||
|
||||
// Altevian Foobs
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/ratprotein
|
||||
name = "AN Flavor Unit C"
|
||||
desc = "A snack made from a group of space-faring rodents that is packed with the maximized potential of caloric intake to cubic inch. This one seems to be flavored of smoked cheddar and salami."
|
||||
icon = 'icons/obj/food_vr.dmi'
|
||||
icon_state = "altevian_cheese_block"
|
||||
package_open_state = "altevian_cheese_block-open"
|
||||
package = TRUE
|
||||
trash = /obj/item/trash/ratcheese
|
||||
nutriment_amt = 5
|
||||
nutriment_desc = list("smoked cheese" = 4)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/ratveggies
|
||||
name = "Premium Ration Packet - VEG"
|
||||
desc = "A package of a mixture of somehow still fresh from day 1 greens with a light hint of vinegar dressing to add extra kick."
|
||||
icon = 'icons/obj/food_vr.dmi'
|
||||
icon_state = "altevian_veggies"
|
||||
package_open_state = "altevian_veggies-open"
|
||||
package = TRUE
|
||||
trash = /obj/item/trash/ratveg
|
||||
nutriment_amt = 3
|
||||
nutriment_desc = list("fresh mixed veggies" = 3, "vinegar" = 1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/ratliquid
|
||||
name = "Admiral's Choice Space-Safe Meal"
|
||||
desc = "A vacuum sealed pouch of a liquid meal. This one seems to be flavored with the accent of steak."
|
||||
icon = 'icons/obj/food_vr.dmi'
|
||||
icon_state = "altevian_juice"
|
||||
package_open_state = "altevian_juice-open"
|
||||
package = TRUE
|
||||
trash = /obj/item/trash/ratjuice
|
||||
nutriment_amt = 2
|
||||
nutriment_desc = list("essence of steak" = 6)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/ratliquid/Initialize()
|
||||
. = ..()
|
||||
reagents.add_reagent("protein", 4)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/ratsteak
|
||||
name = "altevian traditional steak"
|
||||
desc = "This abomination of processed foods resembles a steak plate. Probably contains nothing a normal steak does, but mimics its flavor and nutrition well-enough."
|
||||
icon = 'icons/obj/food_vr.dmi'
|
||||
icon_state = "altevian_steak"
|
||||
trash = /obj/item/trash/plate
|
||||
nutriment_amt = 8
|
||||
nutriment_desc = list("steak" = 5, "smoked cheese" = 2, "veggies" = 1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/ratsteak/Initialize()
|
||||
. = ..()
|
||||
reagents.add_reagent("protein", 3)
|
||||
|
||||
@@ -185,3 +185,11 @@
|
||||
reagents = list("sugar" = 5, "nutriment" = 5)
|
||||
items = list()
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/honey_candy
|
||||
|
||||
/datum/recipe/altevian_steak
|
||||
items = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/ratprotein,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/ratveggies,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/ratliquid
|
||||
)
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/ratsteak
|
||||
|
||||
@@ -132,7 +132,10 @@
|
||||
2 * age >= seed.get_trait(TRAIT_MATURATION) && \
|
||||
!(locate(/obj/effect/plant) in get_turf(src)) && \
|
||||
prob(2 * seed.get_trait(TRAIT_POTENCY)))
|
||||
new /obj/effect/plant(get_turf(src), seed)
|
||||
// CHOMPEdit Start - Need to start processing the vine or it'll never spread.
|
||||
var/obj/effect/plant/D = new /obj/effect/plant(get_turf(src), seed)
|
||||
SSplants.add_plant(D)
|
||||
// CHOMPEdit End
|
||||
|
||||
if(prob(3)) // On each tick, there's a chance the pest population will increase
|
||||
pestlevel += 0.1 * HYDRO_SPEED_MULTIPLIER
|
||||
|
||||
@@ -141,8 +141,8 @@
|
||||
if(dead)
|
||||
channels_playing -= channel
|
||||
channels_idle += channel
|
||||
for(var/mob/M as anything in hearing_mobs)
|
||||
for(var/mob/M in hearing_mobs)
|
||||
M.stop_sound_channel(channelnumber)
|
||||
else
|
||||
for(var/mob/M as anything in hearing_mobs)
|
||||
for(var/mob/M in hearing_mobs)
|
||||
M.set_sound_channel_volume(channelnumber, (current_volume * 0.01) * volume * using_instrument.volume_multiplier)
|
||||
|
||||
@@ -309,6 +309,8 @@ Book Cart End
|
||||
var/list/pages = list() //the contents of each page
|
||||
|
||||
/obj/item/weapon/book/bundle/proc/show_content(mob/user as mob)
|
||||
if(!pages.len)
|
||||
return
|
||||
var/dat
|
||||
var/obj/item/weapon/W = pages[page]
|
||||
// first
|
||||
|
||||
263
code/modules/mentor/mentor.dm
Normal file
263
code/modules/mentor/mentor.dm
Normal file
@@ -0,0 +1,263 @@
|
||||
/client
|
||||
var/datum/mentor/mentorholder = null
|
||||
|
||||
var/list/mentor_datums = list()
|
||||
|
||||
var/list/mentor_verbs_default = list(
|
||||
/client/proc/cmd_mentor_ticket_panel,
|
||||
/client/proc/cmd_mentor_say,
|
||||
/client/proc/cmd_dementor
|
||||
)
|
||||
|
||||
/datum/mentor
|
||||
var/client/owner = null
|
||||
|
||||
/datum/mentor/New(ckey)
|
||||
if(!ckey)
|
||||
error("Mentor datum created without a ckey argument. Datum has been deleted")
|
||||
qdel(src)
|
||||
return
|
||||
mentor_datums[ckey] = src
|
||||
|
||||
/datum/mentor/proc/associate(client/C)
|
||||
if(istype(C))
|
||||
owner = C
|
||||
owner.mentorholder = src
|
||||
owner.add_mentor_verbs()
|
||||
GLOB.mentors |= C
|
||||
|
||||
/datum/mentor/proc/disassociate()
|
||||
if(owner)
|
||||
GLOB.mentors -= owner
|
||||
owner.remove_mentor_verbs()
|
||||
owner.mentorholder = null
|
||||
mentor_datums[owner.ckey] = null
|
||||
qdel(src)
|
||||
|
||||
/client/proc/add_mentor_verbs()
|
||||
if(mentorholder)
|
||||
verbs += mentor_verbs_default
|
||||
|
||||
/client/proc/remove_mentor_verbs()
|
||||
if(mentorholder)
|
||||
verbs -= mentor_verbs_default
|
||||
|
||||
/client/proc/make_mentor()
|
||||
set category = "Special Verbs"
|
||||
set name = "Make Mentor"
|
||||
if(!holder)
|
||||
to_chat(src, "<span class='pm warning'>Error: Only administrators may use this command.</span>")
|
||||
return
|
||||
var/list/client/targets[0]
|
||||
for(var/client/T in GLOB.clients)
|
||||
targets["[T.key]"] = T
|
||||
var/target = tgui_input_list(src,"Who do you want to make a mentor?","Make Mentor", sortList(targets))
|
||||
if(!target)
|
||||
return
|
||||
var/client/C = targets[target]
|
||||
if(has_mentor_powers(C) || C.deadmin_holder) // If an admin is deadminned you could mentor them and that will cause fuckery if they readmin
|
||||
to_chat(src, "<span class='pm warning'>Error: They already have mentor powers.</span>")
|
||||
return
|
||||
var/datum/mentor/M = new /datum/mentor(C.ckey)
|
||||
M.associate(C)
|
||||
to_chat(C, "<span class='pm notice'>You have been granted mentorship.</span>")
|
||||
to_chat(src, "<span class='pm notice'>You have made [C] a mentor.</span>")
|
||||
log_admin("[key_name(src)] made [key_name(C)] a mentor.")
|
||||
feedback_add_details("admin_verb","Make Mentor") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/unmake_mentor()
|
||||
set category = "Special Verbs"
|
||||
set name = "Unmake Mentor"
|
||||
if(!holder)
|
||||
to_chat(src, "<span class='pm warning'>Error: Only administrators may use this command.</span>")
|
||||
return
|
||||
var/list/client/targets[0]
|
||||
for(var/client/T in GLOB.mentors)
|
||||
targets["[T.key]"] = T
|
||||
var/target = tgui_input_list(src,"Which mentor do you want to unmake?","Unmake Mentor", sortList(targets))
|
||||
if(!target)
|
||||
return
|
||||
var/client/C = targets[target]
|
||||
C.mentorholder.disassociate()
|
||||
to_chat(C, "<span class='pm warning'>Your mentorship has been revoked.</span>")
|
||||
to_chat(src, "<span class='pm notice'>You have revoked [C]'s mentorship.</span>")
|
||||
log_admin("[key_name(src)] revoked [key_name(C)]'s mentorship.")
|
||||
feedback_add_details("admin_verb","Unmake Mentor") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_mentor_say(msg as text)
|
||||
set category = "Admin"
|
||||
set name ="Mentorsay"
|
||||
|
||||
//check rights
|
||||
if (!has_mentor_powers(src))
|
||||
return
|
||||
|
||||
msg = sanitize(msg)
|
||||
if (!msg)
|
||||
return
|
||||
|
||||
log_admin("Mentorsay: [key_name(src)]: [msg]")
|
||||
|
||||
for(var/client/C in GLOB.mentors)
|
||||
to_chat(C, create_text_tag("mentor", "MENTOR:", C) + " <span class='mentor_channel'><span class='name'>[src]</span>: <span class='message'>[msg]</span></span>")
|
||||
for(var/client/C in GLOB.admins)
|
||||
to_chat(C, create_text_tag("mentor", "MENTOR:", C) + " <span class='mentor_channel'><span class='name'>[src]</span>: <span class='message'>[msg]</span></span>")
|
||||
|
||||
/proc/mentor_commands(href, href_list, client/C)
|
||||
if(href_list["mhelp"])
|
||||
var/mhelp_ref = href_list["mhelp"]
|
||||
var/datum/mentor_help/MH = locate(mhelp_ref)
|
||||
if (MH && istype(MH, /datum/mentor_help))
|
||||
MH.Action(href_list["mhelp_action"])
|
||||
else
|
||||
to_chat(C, "Ticket [mhelp_ref] has been deleted!")
|
||||
|
||||
if (href_list["mhelp_tickets"])
|
||||
GLOB.mhelp_tickets.BrowseTickets(text2num(href_list["mhelp_tickets"]))
|
||||
|
||||
|
||||
/datum/mentor/Topic(href, href_list)
|
||||
..()
|
||||
if (usr.client != src.owner || (!usr.client.mentorholder))
|
||||
log_admin("[key_name(usr)] tried to illegally use mentor functions.")
|
||||
message_admins("[usr.key] tried to illegally use mentor functions.")
|
||||
return
|
||||
|
||||
mentor_commands(href, href_list, usr)
|
||||
|
||||
/client/proc/cmd_dementor()
|
||||
set category = "Admin"
|
||||
set name = "De-mentor"
|
||||
|
||||
if(tgui_alert(usr, "Confirm self-dementor for the round? You can't re-mentor yourself without someone promoting you.","Dementor",list("Yes","No")) == "Yes")
|
||||
src.mentorholder.disassociate()
|
||||
|
||||
/client/proc/cmd_mhelp_reply(whom)
|
||||
if(prefs.muted & MUTE_ADMINHELP)
|
||||
to_chat(src, "<span class='pm warning'>Error: Mentor-PM: You are unable to use admin PM-s (muted).</span>")
|
||||
return
|
||||
var/client/C
|
||||
if(istext(whom))
|
||||
C = GLOB.directory[whom]
|
||||
else if(istype(whom,/client))
|
||||
C = whom
|
||||
if(!C)
|
||||
if(has_mentor_powers(src))
|
||||
to_chat(src, "<span class='pm warning'>Error: Mentor-PM: Client not found.</span>")
|
||||
return
|
||||
|
||||
var/datum/mentor_help/MH = C.current_mentorhelp
|
||||
|
||||
if(MH)
|
||||
message_mentors("<span class='mentor_channel'>[src] has started replying to [C]'s mentor help.</span>")
|
||||
var/msg = tgui_input_text(src,"Message:", "Private message to [C]")
|
||||
if (!msg)
|
||||
message_mentors("<span class='mentor_channel'>[src] has cancelled their reply to [C]'s mentor help.</span>")
|
||||
return
|
||||
cmd_mentor_pm(whom, msg, MH)
|
||||
|
||||
/proc/has_mentor_powers(client/C)
|
||||
return C.holder || C.mentorholder
|
||||
|
||||
// This not really a great place to put it, but this verb replaces adminhelp in hotkeys so that people requesting help can select the type they need
|
||||
// You can still directly adminhelp if necessary, this ONLY replaces the inbuilt hotkeys
|
||||
|
||||
/client/verb/requesthelp()
|
||||
set category = "Admin"
|
||||
set name = "Request help"
|
||||
set hidden = 1
|
||||
|
||||
var/mhelp = tgui_alert(usr, "Select the help you need.","Request for Help",list("Adminhelp","Mentorhelp")) == "Mentorhelp"
|
||||
var/msg = tgui_input_text(usr, "Input your request for help.", "Request for Help")
|
||||
|
||||
if (mhelp)
|
||||
mentorhelp(msg)
|
||||
return
|
||||
|
||||
adminhelp(msg)
|
||||
|
||||
|
||||
/client/proc/cmd_mentor_pm(whom, msg, datum/mentor_help/MH)
|
||||
set category = "Admin"
|
||||
set name = "Mentor-PM"
|
||||
set hidden = 1
|
||||
|
||||
if(prefs.muted & MUTE_ADMINHELP)
|
||||
to_chat(src, "<span class='pm warning'>Error: Mentor-PM: You are unable to use admin PM-s (muted).</span>")
|
||||
return
|
||||
|
||||
//Not a mentor and no open ticket
|
||||
if(!has_mentor_powers(src) && !current_mentorhelp)
|
||||
to_chat(src, "<span class='pm warning'>You can no longer reply to this ticket, please open another one by using the Mentorhelp verb if need be.</span>")
|
||||
to_chat(src, "<span class='pm notice'>Message: [msg]</span>")
|
||||
return
|
||||
|
||||
var/client/recipient
|
||||
|
||||
if(istext(whom))
|
||||
recipient = GLOB.directory[whom]
|
||||
|
||||
else if(istype(whom,/client))
|
||||
recipient = whom
|
||||
|
||||
//get message text, limit it's length.and clean/escape html
|
||||
if(!msg)
|
||||
msg = tgui_input_text(src,"Message:", "Mentor-PM to [whom]")
|
||||
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
if(prefs.muted & MUTE_ADMINHELP)
|
||||
to_chat(src, "<span class='pm warning'>Error: Mentor-PM: You are unable to use admin PM-s (muted).</span>")
|
||||
return
|
||||
|
||||
if(!recipient)
|
||||
if(has_mentor_powers(src))
|
||||
to_chat(src, "<span class='pm warning'>Error:Mentor-PM: Client not found.</span>")
|
||||
to_chat(src, msg)
|
||||
else
|
||||
log_admin("Mentorhelp: [key_name(src)]: [msg]")
|
||||
current_mentorhelp.MessageNoRecipient(msg)
|
||||
return
|
||||
|
||||
//Has mentor powers but the recipient no longer has an open ticket
|
||||
if(has_mentor_powers(src) && !recipient.current_mentorhelp)
|
||||
to_chat(src, "<span class='pm warning'>You can no longer reply to this ticket.</span>")
|
||||
to_chat(src, "<span class='pm notice'>Message: [msg]</span>")
|
||||
return
|
||||
|
||||
if (src.handle_spam_prevention(msg,MUTE_ADMINHELP))
|
||||
return
|
||||
|
||||
msg = trim(sanitize(copytext(msg,1,MAX_MESSAGE_LEN)))
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
var/interaction_message = "<span class='pm notice'>Mentor-PM from-<b>[src]</b> to-<b>[recipient]</b>: [msg]</span>"
|
||||
|
||||
if (recipient.current_mentorhelp && !has_mentor_powers(recipient))
|
||||
recipient.current_mentorhelp.AddInteraction(interaction_message)
|
||||
if (src.current_mentorhelp && !has_mentor_powers(src))
|
||||
src.current_mentorhelp.AddInteraction(interaction_message)
|
||||
|
||||
// It's a little fucky if they're both mentors, but while admins may need to adminhelp I don't really see any reason a mentor would have to mentorhelp since you can literally just ask any other mentors online
|
||||
if (has_mentor_powers(recipient) && has_mentor_powers(src))
|
||||
if (recipient.current_mentorhelp)
|
||||
recipient.current_mentorhelp.AddInteraction(interaction_message)
|
||||
if (src.current_mentorhelp)
|
||||
src.current_mentorhelp.AddInteraction(interaction_message)
|
||||
|
||||
to_chat(recipient, "<i><span class='mentor'>Mentor-PM from-<b><a href='?mentorhelp_msg=\ref[src]'>[src]</a></b>: [msg]</span></i>")
|
||||
to_chat(src, "<i><span class='mentor'>Mentor-PM to-<b>[recipient]</b>: [msg]</span></i>")
|
||||
|
||||
log_admin("[key_name(src)]->[key_name(recipient)]: [msg]")
|
||||
|
||||
if(recipient.is_preference_enabled(/datum/client_preference/play_mentorhelp_ping))
|
||||
recipient << 'sound/effects/mentorhelp.mp3'
|
||||
|
||||
for(var/client/C in GLOB.mentors)
|
||||
if (C != recipient && C != src)
|
||||
to_chat(C, interaction_message)
|
||||
for(var/client/C in GLOB.admins)
|
||||
if (C != recipient && C != src)
|
||||
to_chat(C, interaction_message)
|
||||
415
code/modules/mentor/mentorhelp.dm
Normal file
415
code/modules/mentor/mentorhelp.dm
Normal file
@@ -0,0 +1,415 @@
|
||||
/client/var/datum/mentor_help/current_mentorhelp
|
||||
|
||||
//
|
||||
//TICKET MANAGER
|
||||
//
|
||||
|
||||
GLOBAL_DATUM_INIT(mhelp_tickets, /datum/mentor_help_tickets, new)
|
||||
|
||||
/datum/mentor_help_tickets
|
||||
var/list/active_tickets = list()
|
||||
var/list/resolved_tickets = list()
|
||||
|
||||
var/obj/effect/statclick/mticket_list/astatclick = new(null, null, AHELP_ACTIVE)
|
||||
var/obj/effect/statclick/mticket_list/rstatclick = new(null, null, AHELP_RESOLVED)
|
||||
|
||||
/datum/mentor_help_tickets/Destroy()
|
||||
QDEL_LIST(active_tickets)
|
||||
QDEL_LIST(resolved_tickets)
|
||||
QDEL_NULL(astatclick)
|
||||
QDEL_NULL(rstatclick)
|
||||
return ..()
|
||||
|
||||
//private
|
||||
/datum/mentor_help_tickets/proc/ListInsert(datum/mentor_help/new_ticket)
|
||||
var/list/mticket_list
|
||||
switch(new_ticket.state)
|
||||
if(AHELP_ACTIVE)
|
||||
mticket_list = active_tickets
|
||||
if(AHELP_RESOLVED)
|
||||
mticket_list = resolved_tickets
|
||||
else
|
||||
CRASH("Invalid ticket state: [new_ticket.state]")
|
||||
var/num_closed = mticket_list.len
|
||||
if(num_closed)
|
||||
for(var/I in 1 to num_closed)
|
||||
var/datum/mentor_help/MH = mticket_list[I]
|
||||
if(MH.id > new_ticket.id)
|
||||
mticket_list.Insert(I, new_ticket)
|
||||
return
|
||||
mticket_list += new_ticket
|
||||
|
||||
//opens the ticket listings, only two states here
|
||||
/datum/mentor_help_tickets/proc/BrowseTickets(state)
|
||||
var/list/l2b
|
||||
var/title
|
||||
switch(state)
|
||||
if(AHELP_ACTIVE)
|
||||
l2b = active_tickets
|
||||
title = "Active Tickets"
|
||||
if(AHELP_RESOLVED)
|
||||
l2b = resolved_tickets
|
||||
title = "Resolved Tickets"
|
||||
if(!l2b)
|
||||
return
|
||||
var/list/dat = list("<html><head><title>[title]</title></head>")
|
||||
dat += "<A HREF='?_src_=mentorholder;mhelp_tickets=[state]'>Refresh</A><br><br>"
|
||||
for(var/datum/mentor_help/MH as anything in l2b)
|
||||
dat += "<span class='adminnotice'><span class='adminhelp'>Ticket #[MH.id]</span>: <A HREF='?_src_=mentorholder;mhelp=\ref[MH];mhelp_action=ticket'>[MH.initiator_ckey]: [MH.name]</A></span><br>"
|
||||
|
||||
usr << browse(dat.Join(), "window=mhelp_list[state];size=600x480")
|
||||
|
||||
//Tickets statpanel
|
||||
/datum/mentor_help_tickets/proc/stat_entry()
|
||||
var/num_disconnected = 0
|
||||
stat("Active Tickets:", astatclick.update("[active_tickets.len]"))
|
||||
for(var/datum/mentor_help/MH as anything in active_tickets)
|
||||
if(MH.initiator)
|
||||
stat("#[MH.id]. [MH.initiator_ckey]:", MH.statclick.update())
|
||||
else
|
||||
++num_disconnected
|
||||
if(num_disconnected)
|
||||
stat("Disconnected:", astatclick.update("[num_disconnected]"))
|
||||
stat("Resolved Tickets:", rstatclick.update("[resolved_tickets.len]"))
|
||||
|
||||
//Reassociate still open ticket if one exists
|
||||
/datum/mentor_help_tickets/proc/ClientLogin(client/C)
|
||||
C.current_mentorhelp = CKey2ActiveTicket(C.ckey)
|
||||
if(C.current_mentorhelp)
|
||||
C.current_mentorhelp.AddInteraction("Client reconnected.")
|
||||
C.current_mentorhelp.initiator = C
|
||||
|
||||
//Dissasociate ticket
|
||||
/datum/mentor_help_tickets/proc/ClientLogout(client/C)
|
||||
if(C.current_mentorhelp)
|
||||
C.current_mentorhelp.AddInteraction("Client disconnected.")
|
||||
C.current_mentorhelp.initiator = null
|
||||
C.current_mentorhelp = null
|
||||
|
||||
//Get a ticket given a ckey
|
||||
/datum/mentor_help_tickets/proc/CKey2ActiveTicket(ckey)
|
||||
for(var/datum/admin_help/MH as anything in active_tickets)
|
||||
if(MH.initiator_ckey == ckey)
|
||||
return MH
|
||||
|
||||
//
|
||||
//TICKET LIST STATCLICK
|
||||
//
|
||||
|
||||
/obj/effect/statclick/mticket_list
|
||||
var/current_state
|
||||
|
||||
/obj/effect/statclick/mticket_list/New(loc, name, state)
|
||||
current_state = state
|
||||
..()
|
||||
|
||||
/obj/effect/statclick/mticket_list/Click()
|
||||
GLOB.mhelp_tickets.BrowseTickets(current_state)
|
||||
|
||||
//
|
||||
//TICKET DATUM
|
||||
//
|
||||
|
||||
/datum/mentor_help
|
||||
var/id
|
||||
var/name
|
||||
var/state = AHELP_ACTIVE
|
||||
|
||||
var/opened_at
|
||||
var/closed_at
|
||||
|
||||
var/client/initiator //semi-misnomer, it's the person who ahelped/was bwoinked
|
||||
var/initiator_ckey
|
||||
var/initiator_key_name
|
||||
|
||||
var/list/_interactions //use AddInteraction() or, preferably, admin_ticket_log()
|
||||
|
||||
var/obj/effect/statclick/ahelp/statclick
|
||||
|
||||
var/static/ticket_counter = 0
|
||||
|
||||
//call this on its own to create a ticket, don't manually assign current_mentorhelp
|
||||
//msg is the title of the ticket: usually the ahelp text
|
||||
/datum/mentor_help/New(msg, client/C)
|
||||
//clean the input msg
|
||||
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
|
||||
if(!msg || !C || !C.mob)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
id = ++ticket_counter
|
||||
opened_at = world.time
|
||||
|
||||
name = msg
|
||||
|
||||
initiator = C
|
||||
initiator_ckey = C.ckey
|
||||
initiator_key_name = key_name(initiator, FALSE, TRUE)
|
||||
if(initiator.current_mentorhelp) //This is a bug
|
||||
log_debug("Ticket erroneously left open by code")
|
||||
initiator.current_mentorhelp.AddInteraction("Ticket erroneously left open by code")
|
||||
initiator.current_mentorhelp.Resolve()
|
||||
initiator.current_mentorhelp = src
|
||||
|
||||
statclick = new(null, src)
|
||||
_interactions = list()
|
||||
|
||||
log_admin("Mentorhelp: [key_name(C)]: [msg]")
|
||||
MessageNoRecipient(msg)
|
||||
//show it to the person adminhelping too
|
||||
to_chat(C, "<i><span class='mentor'>Mentor-PM to-<b>Mentors</b>: [name]</span></i>")
|
||||
|
||||
GLOB.mhelp_tickets.active_tickets += src
|
||||
|
||||
/datum/mentor_help/Destroy()
|
||||
RemoveActive()
|
||||
GLOB.mhelp_tickets.resolved_tickets -= src
|
||||
return ..()
|
||||
|
||||
/datum/mentor_help/proc/AddInteraction(formatted_message)
|
||||
_interactions += "[gameTimestamp()]: [formatted_message]"
|
||||
|
||||
//private
|
||||
/datum/mentor_help/proc/ClosureLinks(ref_src)
|
||||
if(!ref_src)
|
||||
ref_src = "\ref[src]"
|
||||
. = " (<A HREF='?_src_=mentorholder;mhelp=[ref_src];mhelp_action=resolve'>RSLVE</A>)"
|
||||
|
||||
//private
|
||||
/datum/mentor_help/proc/LinkedReplyName(ref_src)
|
||||
if(!ref_src)
|
||||
ref_src = "\ref[src]"
|
||||
return "<A HREF='?_src_=mentorholder;mhelp=[ref_src];mhelp_action=reply'>[initiator_ckey]</A>"
|
||||
|
||||
//private
|
||||
/datum/mentor_help/proc/TicketHref(msg, ref_src, action = "ticket")
|
||||
if(!ref_src)
|
||||
ref_src = "\ref[src]"
|
||||
return "<A HREF='?_src_=mentorholder;mhelp=[ref_src];mhelp_action=[action]'>[msg]</A>"
|
||||
|
||||
//message from the initiator without a target, all people with mentor powers will see this
|
||||
/datum/mentor_help/proc/MessageNoRecipient(msg)
|
||||
var/ref_src = "\ref[src]"
|
||||
var/chat_msg = "<span class='notice'>(<A HREF='?_src_=mentorholder;mhelp=[ref_src];mhelp_action=escalate'>ESCALATE</A>) Ticket [TicketHref("#[id]", ref_src)]<b>: [LinkedReplyName(ref_src)]:</b> [msg]</span>"
|
||||
AddInteraction("<font color='red'>[LinkedReplyName(ref_src)]: [msg]</font>")
|
||||
for (var/client/C in GLOB.mentors)
|
||||
if (C.is_preference_enabled(/datum/client_preference/play_mentorhelp_ping))
|
||||
C << 'sound/effects/mentorhelp.mp3'
|
||||
for (var/client/C in GLOB.admins)
|
||||
if (C.is_preference_enabled(/datum/client_preference/play_mentorhelp_ping))
|
||||
C << 'sound/effects/mentorhelp.mp3'
|
||||
message_mentors(chat_msg)
|
||||
|
||||
//Reopen a closed ticket
|
||||
/datum/mentor_help/proc/Reopen()
|
||||
if(state == AHELP_ACTIVE)
|
||||
to_chat(usr, "<span class='warning'>This ticket is already open.</span>")
|
||||
return
|
||||
|
||||
if(GLOB.mhelp_tickets.CKey2ActiveTicket(initiator_ckey))
|
||||
to_chat(usr, "<span class='warning'>This user already has an active ticket, cannot reopen this one.</span>")
|
||||
return
|
||||
|
||||
statclick = new(null, src)
|
||||
GLOB.mhelp_tickets.active_tickets += src
|
||||
GLOB.mhelp_tickets.resolved_tickets -= src
|
||||
switch(state)
|
||||
if(AHELP_RESOLVED)
|
||||
feedback_dec("mhelp_resolve")
|
||||
state = AHELP_ACTIVE
|
||||
closed_at = null
|
||||
if(initiator)
|
||||
initiator.current_mentorhelp = src
|
||||
|
||||
AddInteraction("<font color='purple'>Reopened by [usr.ckey]</font>")
|
||||
if(initiator)
|
||||
to_chat(initiator, "<span class='filter_adminlog'><font color='purple'>Ticket [TicketHref("#[id]")] was reopened by [usr.ckey].</font></span>")
|
||||
var/msg = "<span class='adminhelp'>Ticket [TicketHref("#[id]")] reopened by [usr.ckey].</span>"
|
||||
message_mentors(msg)
|
||||
log_admin(msg)
|
||||
feedback_inc("mhelp_reopen")
|
||||
TicketPanel() //can only be done from here, so refresh it
|
||||
|
||||
//private
|
||||
/datum/mentor_help/proc/RemoveActive()
|
||||
if(state != AHELP_ACTIVE)
|
||||
return
|
||||
closed_at = world.time
|
||||
QDEL_NULL(statclick)
|
||||
GLOB.mhelp_tickets.active_tickets -= src
|
||||
if(initiator && initiator.current_mentorhelp == src)
|
||||
initiator.current_mentorhelp = null
|
||||
|
||||
//Mark open ticket as resolved/legitimate, returns mentorhelp verb
|
||||
/datum/mentor_help/proc/Resolve(silent = FALSE)
|
||||
if(state != AHELP_ACTIVE)
|
||||
return
|
||||
RemoveActive()
|
||||
state = AHELP_RESOLVED
|
||||
GLOB.mhelp_tickets.ListInsert(src)
|
||||
|
||||
AddInteraction("<span class='filter_adminlog'><font color='green'>Resolved by [usr.ckey].</font></span>")
|
||||
if(initiator)
|
||||
to_chat(initiator, "<span class='filter_adminlog'><font color='green'>Ticket [TicketHref("#[id]")] was marked resolved by [usr.ckey].</font></span>")
|
||||
if(!silent)
|
||||
feedback_inc("mhelp_resolve")
|
||||
var/msg = "Ticket [TicketHref("#[id]")] resolved by [usr.ckey]"
|
||||
message_mentors(msg)
|
||||
log_admin(msg)
|
||||
|
||||
//Show the ticket panel
|
||||
/datum/mentor_help/proc/TicketPanel()
|
||||
var/list/dat = list("<html><head><title>Ticket #[id]</title></head>")
|
||||
var/ref_src = "\ref[src]"
|
||||
dat += "<h4>Mentor Help Ticket #[id]: [LinkedReplyName(ref_src)]</h4>"
|
||||
dat += "<b>State: "
|
||||
switch(state)
|
||||
if(AHELP_ACTIVE)
|
||||
dat += "<font color='red'>OPEN</font>"
|
||||
if(AHELP_RESOLVED)
|
||||
dat += "<font color='green'>RESOLVED</font>"
|
||||
else
|
||||
dat += "UNKNOWN"
|
||||
dat += "</b>[GLOB.TAB][TicketHref("Refresh", ref_src)]"
|
||||
if(state != AHELP_ACTIVE)
|
||||
dat += "[GLOB.TAB][TicketHref("Reopen", ref_src, "reopen")]"
|
||||
dat += "<br><br>Opened at: [gameTimestamp(wtime = opened_at)] (Approx [(world.time - opened_at) / 600] minutes ago)"
|
||||
if(closed_at)
|
||||
dat += "<br>Closed at: [gameTimestamp(wtime = closed_at)] (Approx [(world.time - closed_at) / 600] minutes ago)"
|
||||
dat += "<br><br>"
|
||||
if(initiator)
|
||||
dat += "<b>Actions:</b> [Context(ref_src)]<br>"
|
||||
else
|
||||
dat += "<b>DISCONNECTED</b>[GLOB.TAB][ClosureLinks(ref_src)]<br>"
|
||||
dat += "<br><b>Log:</b><br><br>"
|
||||
for(var/I in _interactions)
|
||||
dat += "[I]<br>"
|
||||
|
||||
usr << browse(dat.Join(), "window=mhelp[id];size=620x480")
|
||||
|
||||
//Kick ticket to admins
|
||||
/datum/mentor_help/proc/Escalate()
|
||||
if(tgui_alert(usr, "Really escalate this ticket to admins? No mentors will ever be able to interact with it again if you do.","Escalate",list("Yes","No")) != "Yes")
|
||||
return
|
||||
if (src.initiator == null) // You can't escalate a mentorhelp of someone who's logged out because it won't create the adminhelp properly
|
||||
to_chat(usr, "<span class='pm warning'>Error: client not found, unable to escalate.</span>")
|
||||
return
|
||||
var/datum/admin_help/AH = new /datum/admin_help(src.name, src.initiator, FALSE)
|
||||
message_mentors("[usr.ckey] escalated Ticket [TicketHref("#[id]")]")
|
||||
log_admin("[key_name(usr)] escalated mentorhelp [src.name]")
|
||||
to_chat(src.initiator, "<span class='mentor'>[usr.ckey] escalated your mentorhelp to admins.</span>")
|
||||
AH._interactions = src._interactions
|
||||
GLOB.mhelp_tickets.active_tickets -= src
|
||||
GLOB.mhelp_tickets.resolved_tickets -= src
|
||||
qdel(src)
|
||||
|
||||
/datum/mentor_help/proc/Context(ref_src)
|
||||
if(!ref_src)
|
||||
ref_src = "\ref[src]"
|
||||
if(state == AHELP_ACTIVE)
|
||||
. += ClosureLinks(ref_src)
|
||||
if(state != AHELP_RESOLVED)
|
||||
. += " (<A HREF='?_src_=mentorholder;mhelp=[ref_src];mhelp_action=escalate'>ESCALATE</A>)"
|
||||
|
||||
//Forwarded action from admin/Topic OR mentor/Topic depending on which rank the caller has
|
||||
/datum/mentor_help/proc/Action(action)
|
||||
switch(action)
|
||||
if("ticket")
|
||||
TicketPanel()
|
||||
if("reply")
|
||||
usr.client.cmd_mhelp_reply(initiator)
|
||||
if("resolve")
|
||||
Resolve()
|
||||
if("reopen")
|
||||
Reopen()
|
||||
if("escalate")
|
||||
Escalate()
|
||||
|
||||
//
|
||||
// TICKET STATCLICK
|
||||
//
|
||||
|
||||
/obj/effect/statclick/mhelp
|
||||
var/datum/mentor_help/mhelp_datum
|
||||
|
||||
/obj/effect/statclick/mhelp/New(loc, datum/mentor_help/MH)
|
||||
mhelp_datum = MH
|
||||
..(loc)
|
||||
|
||||
/obj/effect/statclick/mhelp/update()
|
||||
return ..(mhelp_datum.name)
|
||||
|
||||
/obj/effect/statclick/mhelp/Click()
|
||||
mhelp_datum.TicketPanel()
|
||||
|
||||
/obj/effect/statclick/mhelp/Destroy()
|
||||
mhelp_datum = null
|
||||
return ..()
|
||||
|
||||
//
|
||||
// CLIENT PROCS
|
||||
//
|
||||
|
||||
/client/verb/mentorhelp(msg as text)
|
||||
set category = "Admin"
|
||||
set name = "Mentorhelp"
|
||||
|
||||
if(say_disabled) //This is here to try to identify lag problems
|
||||
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
|
||||
return
|
||||
|
||||
//handle muting and automuting
|
||||
if(prefs.muted & MUTE_ADMINHELP)
|
||||
to_chat(src, "<span class='danger'>Error: Mentor-PM: You cannot send adminhelps (Muted).</span>")
|
||||
return
|
||||
if(handle_spam_prevention(msg,MUTE_ADMINHELP))
|
||||
return
|
||||
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
//remove out adminhelp verb temporarily to prevent spamming of admins.
|
||||
src.verbs -= /client/verb/mentorhelp
|
||||
spawn(600)
|
||||
src.verbs += /client/verb/mentorhelp // 1 minute cool-down for mentorhelps
|
||||
|
||||
feedback_add_details("admin_verb","Mentorhelp") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
if(current_mentorhelp)
|
||||
if(tgui_alert(usr, "You already have a ticket open. Is this for the same issue?","Duplicate?",list("Yes","No")) != "No")
|
||||
if(current_mentorhelp)
|
||||
log_admin("Mentorhelp: [key_name(src)]: [msg]")
|
||||
current_mentorhelp.MessageNoRecipient(msg)
|
||||
to_chat(usr, "<span class='adminnotice'><span class='mentor'>Mentor-PM to-<b>Mentors</b>: [msg]</span></span>")
|
||||
return
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Ticket not found, creating new one...</span>")
|
||||
else
|
||||
current_mentorhelp.AddInteraction("[usr.ckey] opened a new ticket.")
|
||||
current_mentorhelp.Resolve()
|
||||
|
||||
new /datum/mentor_help(msg, src, FALSE)
|
||||
|
||||
//admin proc
|
||||
/client/proc/cmd_mentor_ticket_panel()
|
||||
set name = "Mentor Ticket List"
|
||||
set category = "Admin"
|
||||
|
||||
var/browse_to
|
||||
|
||||
switch(tgui_input_list(usr, "Display which ticket list?", "List Choice", list("Active Tickets", "Resolved Tickets")))
|
||||
if("Active Tickets")
|
||||
browse_to = AHELP_ACTIVE
|
||||
if("Resolved Tickets")
|
||||
browse_to = AHELP_RESOLVED
|
||||
else
|
||||
return
|
||||
|
||||
GLOB.mhelp_tickets.BrowseTickets(browse_to)
|
||||
|
||||
/proc/message_mentors(var/msg)
|
||||
msg = "<span class='mentor_channel'><span class='prefix'>Mentor:</span> <span class=\"message\">[msg]</span></span>"
|
||||
|
||||
for(var/client/C in GLOB.mentors)
|
||||
to_chat(C, msg)
|
||||
for(var/client/C in GLOB.admins)
|
||||
to_chat(C, msg)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user