Merge conflic fix

This commit is contained in:
MrStonedOne
2016-01-03 14:51:14 -08:00
249 changed files with 4185 additions and 3732 deletions
+2 -2
View File
@@ -145,8 +145,8 @@ var/global/BSACooldown = 0
body += "<A href='?_src_=holder;simplemake=coffee;mob=\ref[M]'>Coffee</A> | "
//body += "<A href='?_src_=holder;simplemake=parrot;mob=\ref[M]'>Parrot</A> | "
//body += "<A href='?_src_=holder;simplemake=polyparrot;mob=\ref[M]'>Poly</A> | "
body += "\[ Construct: <A href='?_src_=holder;simplemake=constructarmored;mob=\ref[M]'>Armored</A> , "
body += "<A href='?_src_=holder;simplemake=constructbuilder;mob=\ref[M]'>Builder</A> , "
body += "\[ Construct: <A href='?_src_=holder;simplemake=constructarmored;mob=\ref[M]'>Juggernaut</A> , "
body += "<A href='?_src_=holder;simplemake=constructbuilder;mob=\ref[M]'>Artificer</A> , "
body += "<A href='?_src_=holder;simplemake=constructwraith;mob=\ref[M]'>Wraith</A> \] "
body += "<A href='?_src_=holder;simplemake=shade;mob=\ref[M]'>Shade</A>"
body += "<br>"
+1 -1
View File
@@ -46,7 +46,7 @@
message_admins("[key_name_admin(usr)] tried to create changelings. Unfortunately, there were no candidates available.")
log_admin("[key_name(usr)] failed to create changelings.")
if("3")
if(!src.makeRevs())
if(src.makeRevs())
message_admins("[key_name(usr)] started a revolution.")
log_admin("[key_name(usr)] started a revolution.")
else
+5
View File
@@ -71,6 +71,11 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(targetselected && !hascall(target,procname))
usr << "<font color='red'>Error: callproc(): target has no such call [procname].</font>"
return
else
var/procpath = text2path(procname)
if (!procpath)
usr << "<font color='red'>Error: callproc(): proc [procname] does not exist. (Did you forget the /proc/ part?)</font>"
return
var/list/lst = get_callproc_args()
if(!lst)
return
+8 -6
View File
@@ -114,12 +114,14 @@
for(var/mob/living/carbon/human/applicant in player_list)
if(ROLE_REV in applicant.client.prefs.be_special)
if(applicant.stat == CONSCIOUS)
if(applicant.mind)
if(!applicant.mind.special_role)
if(!jobban_isbanned(applicant, ROLE_REV) && !jobban_isbanned(applicant, "Syndicate"))
if(temp.age_check(applicant.client))
if(!(applicant.job in temp.restricted_jobs))
candidates += applicant
var/turf/T = get_turf(applicant)
if(T.z == ZLEVEL_STATION)
if(applicant.mind)
if(!applicant.mind.special_role)
if(!jobban_isbanned(applicant, ROLE_REV) && !jobban_isbanned(applicant, "Syndicate"))
if(temp.age_check(applicant.client))
if(!(applicant.job in temp.restricted_jobs))
candidates += applicant
if(candidates.len)
var/numRevs = min(candidates.len, 3)
+23 -2
View File
@@ -32,6 +32,7 @@
var/death = TRUE
var/flavour_text = "The mapper forgot to set this!"
var/faction = null
var/list/implants = list()
density = 1
/obj/effect/landmark/corpse/initialize()
@@ -105,6 +106,11 @@
W.registered_name = M.real_name
W.update_label()
M.equip_to_slot_or_del(W, slot_wear_id)
for(var/I in implants)
var/obj/item/weapon/implant/X = new I
X.implant(M)
if(ckey)
M.ckey = ckey
M << "[flavour_text]"
@@ -270,7 +276,7 @@
/////////////////Officers//////////////////////
/////////////////Officers+Nanotrasen Security//////////////////////
/obj/effect/landmark/corpse/bridgeofficer
name = "Bridge Officer"
@@ -298,6 +304,21 @@
corpseidjob = "Commander"
corpseidaccess = "Captain"
/obj/effect/landmark/corpse/nanotrasensoldier
name = "Nanotrasen Private Security Officer"
corpseuniform = /obj/item/clothing/under/rank/security
corpsesuit = /obj/item/clothing/suit/armor/vest
corpseshoes = /obj/item/clothing/shoes/combat
corpsegloves = /obj/item/clothing/gloves/combat
corpseradio = /obj/item/device/radio/headset
corpsemask = /obj/item/clothing/mask/gas/sechailer/swat
corpsehelmet = /obj/item/clothing/head/helmet/swat/nanotrasen
corpseback = /obj/item/weapon/storage/backpack/security
corpseid = 1
corpseidjob = "Private Security Force"
corpseidaccess = "Security Officer"
/obj/effect/landmark/corpse/commander/alive
death = FALSE
roundstart = FALSE
@@ -350,4 +371,4 @@
mobname = "???"
mob_species = /datum/species/abductor
corpseuniform = /obj/item/clothing/under/color/grey
corpseshoes = /obj/item/clothing/shoes/combat
corpseshoes = /obj/item/clothing/shoes/combat
@@ -1,31 +1,31 @@
//Academy Areas
/area/awaymission/academy
name = "\improper Academy Asteroids"
name = "Academy Asteroids"
icon_state = "away"
/area/awaymission/academy/headmaster
name = "\improper Academy Fore Block"
name = "Academy Fore Block"
icon_state = "away1"
/area/awaymission/academy/classrooms
name = "\improper Academy Classroom Block"
name = "Academy Classroom Block"
icon_state = "away2"
/area/awaymission/academy/academyaft
name = "\improper Academy Ship Aft Block"
name = "Academy Ship Aft Block"
icon_state = "away3"
/area/awaymission/academy/academygate
name = "\improper Academy Gateway"
name = "Academy Gateway"
icon_state = "away4"
/area/awaymission/academy/academycellar
name = "\improper Academy Cellar"
name = "Academy Cellar"
icon_state = "away4"
/area/awaymission/academy/academyengine
name = "\improper Academy Engine"
name = "Academy Engine"
icon_state = "away4"
//Academy Items
@@ -102,7 +102,7 @@
/obj/structure/academy_wizard_spawner/proc/summon_wizard()
var/turf/T = src.loc
var/mob/living/carbon/human/wizbody = new(T)
wizbody.equipOutfit(/datum/outfit/wizard/academy)
var/obj/item/weapon/implant/exile/Implant = new/obj/item/weapon/implant/exile(wizbody)
@@ -110,7 +110,7 @@
wizbody.faction |= "wizard"
wizbody.real_name = "Academy Teacher"
wizbody.name = "Academy Teacher"
var/datum/mind/wizmind = new /datum/mind()
wizmind.name = "Wizard Defender"
wizmind.special_role = "Academy Defender"
@@ -118,13 +118,13 @@
wizmind.objectives += O
wizmind.transfer_to(wizbody)
ticker.mode.wizards |= wizmind
wizmind.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt)
wizmind.AddSpell(new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile)
wizmind.AddSpell(new /obj/effect/proc_holder/spell/dumbfire/fireball)
current_wizard = wizbody
give_control()
/obj/structure/academy_wizard_spawner/proc/update_status()
@@ -1,22 +1,22 @@
//Packer Ship Areas
/area/awaymission/BMPship
name = "\improper BMP Asteroids"
name = "BMP Asteroids"
icon_state = "away"
luminosity = 0
/area/awaymission/BMPship/Aft
name = "\improper Aft Block"
name = "Aft Block"
icon_state = "away1"
requires_power = 1
/area/awaymission/BMPship/Midship
name = "\improper Midship Block"
name = "Midship Block"
icon_state = "away2"
requires_power = 1
/area/awaymission/BMPship/Fore
name = "\improper Fore Block"
name = "Fore Block"
icon_state = "away3"
requires_power = 1
@@ -5,7 +5,7 @@
icon_state = "away"
/area/awaymission/challenge/main
name = "\improper Danger Room"
name = "Danger Room"
icon_state = "away1"
requires_power = 0
@@ -0,0 +1,64 @@
//Research Base Areas//--
/area/awaymission/research
name = "Research Outpost"
icon_state = "away"
luminosity = 0
lighting_use_dynamic = DYNAMIC_LIGHTING_ENABLED
/area/awaymission/research/interior
name = "Research Inside"
requires_power = 1
icon_state = "away2"
/area/awaymission/research/interior/cryo
name = "Research Cryostasis Room"
icon_state = "medbay"
/area/awaymission/research/interior/clonestorage
name = "Research Clone Storage"
icon_state = "cloning"
/area/awaymission/research/interior/genetics
name = "Research Genetics Research"
icon_state = "genetics"
/area/awaymission/research/interior/engineering
name = "Research Engineering"
icon_state = "engine"
/area/awaymission/research/interior/security
name = "Research Security"
icon_state = "security"
/area/awaymission/research/interior/secure
name = "Research Secure Vault"
/area/awaymission/research/interior/maint
name = "Research Maintenance"
icon_state = "maintcentral"
/area/awaymission/research/interior/dorm
name = "Research Dorms"
icon_state = "Sleep"
/area/awaymission/research/interior/escapepods
name = "Research Escape Wing"
icon_state = "exit"
/area/awaymission/research/interior/gateway
name = "Research Gateway"
icon_state = "start"
/area/awaymission/research/interior/bathroom
name = "Research Bathrooms"
icon_state = "restrooms"
/area/awaymission/research/interior/medbay
name = "Research Medbay"
icon_state = "medbay"
/area/awaymission/research/exterior
name = "Research Exterior"
icon_state = "unknown"
@@ -1,37 +1,37 @@
//Snow Valley Areas//--
/area/awaymission/snowdin
name = "\improper Snowdin Tundra Plains"
name = "Snowdin Tundra Plains"
icon_state = "away"
requires_power = 0
luminosity = 1
lighting_use_dynamic = DYNAMIC_LIGHTING_ENABLED
/area/awaymission/snowdin/post
name = "\improper Snowdin Outpost"
name = "Snowdin Outpost"
requires_power = 1
/area/awaymission/snowdin/igloo
name = "\improper Snowdin Igloos"
name = "Snowdin Igloos"
icon_state = "away2"
/area/awaymission/snowdin/cave
name = "\improper Snowdin Caves"
name = "Snowdin Caves"
icon_state = "away2"
luminosity = 0
/area/awaymission/snowdin/base
name = "\improper Snowdin Main Base"
name = "Snowdin Main Base"
icon_state = "away3"
requires_power = 1
/area/awaymission/snowdin/dungeon1
name = "\improper Snowdin Depths"
name = "Snowdin Depths"
icon_state = "away2"
luminosity = 0
/area/awaymission/snowdin/sekret
name = "\improper Snowdin Operations"
name = "Snowdin Operations"
icon_state = "away3"
requires_power = 1
@@ -237,6 +237,7 @@ obj/item/weapon/paper/crumpled/snowdin/shovel
icon_state = "sleeper"
roundstart = FALSE
death = FALSE
implants = list(/obj/item/weapon/implant/exile)
faction = "syndicate"
flavour_text = {"You are a syndicate operative recently awoken from cyrostatis in an underground outpost. Monitor Nanotrasen communications and record infomation. All intruders should be
disposed of swirfly to assure no gathered infomation is stolen or lost. Try not to wander too far from the outpost as the caves can be a deadly place even for a trained operative such as yourself."}
@@ -1,33 +1,33 @@
//Spacebattle Areas
/area/awaymission/spacebattle
name = "\improper Space Battle"
name = "Space Battle"
icon_state = "away"
requires_power = 0
/area/awaymission/spacebattle/cruiser
name = "\improper Nanotrasen Cruiser"
name = "Nanotrasen Cruiser"
/area/awaymission/spacebattle/syndicate1
name = "\improper Syndicate Assault Ship 1"
name = "Syndicate Assault Ship 1"
/area/awaymission/spacebattle/syndicate2
name = "\improper Syndicate Assault Ship 2"
name = "Syndicate Assault Ship 2"
/area/awaymission/spacebattle/syndicate3
name = "\improper Syndicate Assault Ship 3"
name = "Syndicate Assault Ship 3"
/area/awaymission/spacebattle/syndicate4
name = "\improper Syndicate War Sphere 1"
name = "Syndicate War Sphere 1"
/area/awaymission/spacebattle/syndicate5
name = "\improper Syndicate War Sphere 2"
name = "Syndicate War Sphere 2"
/area/awaymission/spacebattle/syndicate6
name = "\improper Syndicate War Sphere 3"
name = "Syndicate War Sphere 3"
/area/awaymission/spacebattle/syndicate7
name = "\improper Syndicate Fighter"
name = "Syndicate Fighter"
/area/awaymission/spacebattle/secret
name = "\improper Hidden Chamber"
name = "Hidden Chamber"
@@ -7,30 +7,30 @@
//Wild West Areas
/area/awaymission/wwmines
name = "\improper Wild West Mines"
name = "Wild West Mines"
icon_state = "away1"
luminosity = 1
requires_power = 0
/area/awaymission/wwgov
name = "\improper Wild West Mansion"
name = "Wild West Mansion"
icon_state = "away2"
luminosity = 1
requires_power = 0
/area/awaymission/wwrefine
name = "\improper Wild West Refinery"
name = "Wild West Refinery"
icon_state = "away3"
luminosity = 1
requires_power = 0
/area/awaymission/wwvault
name = "\improper Wild West Vault"
name = "Wild West Vault"
icon_state = "away3"
luminosity = 0
/area/awaymission/wwvaultdoors
name = "\improper Wild West Vault Doors" // this is to keep the vault area being entirely lit because of requires_power
name = "Wild West Vault Doors" // this is to keep the vault area being entirely lit because of requires_power
icon_state = "away2"
requires_power = 0
luminosity = 0
+2 -1
View File
@@ -22,6 +22,7 @@ var/global/list/potentialSpaceRuins = generateMapList(filename = "config/spaceRu
var/file = file(map)
if(isfile(file))
maploader.load_map(file)
smooth_zlevel(world.maxz)
world.log << "away mission loaded: [map]"
map_transition_config.Add(AWAY_MISSION_LIST)
@@ -66,7 +67,7 @@ var/global/list/potentialSpaceRuins = generateMapList(filename = "config/spaceRu
potentialMaps.Add(t)
return potentialMaps
return potentialMaps
/proc/seedRuins(z_level = 1, ruin_number = 0, whitelist = /area/space, list/potentialRuins = potentialSpaceRuins)
+3 -3
View File
@@ -173,10 +173,10 @@ You can set verify to TRUE if you want send() to sleep until the client has the
//DEFINITIONS FOR ASSET DATUMS START HERE.
/datum/asset/simple/nanoui
/datum/asset/simple/tgui
assets = list(
"nanoui.css" = 'nano/assets/nanoui.css',
"nanoui.js" = 'nano/assets/nanoui.js'
"tgui.css" = 'tgui/assets/tgui.css',
"tgui.js" = 'tgui/assets/tgui.js'
)
/datum/asset/simple/pda
+8 -4
View File
@@ -27,7 +27,8 @@ var/list/preferences_datums = list()
var/UI_style = "Midnight"
var/nanoui_fancy = TRUE
var/tgui_fancy = TRUE
var/tgui_lock = TRUE
var/toggles = TOGGLES_DEFAULT
var/chat_toggles = TOGGLES_DEFAULT_CHAT
var/ghost_form = "ghost"
@@ -325,7 +326,8 @@ var/list/preferences_datums = list()
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>General Settings</h2>"
dat += "<b>UI Style:</b> <a href='?_src_=prefs;preference=ui'>[UI_style]</a><br>"
dat += "<b>Fancy NanoUI:</b> <a href='?_src_=prefs;preference=nanoui'>[(nanoui_fancy) ? "Yes" : "No"]</a><br>"
dat += "<b>tgui Style:</b> <a href='?_src_=prefs;preference=tgui_fancy'>[(tgui_fancy) ? "Fancy" : "No Frills"]</a><br>"
dat += "<b>tgui Monitors:</b> <a href='?_src_=prefs;preference=tgui_lock'>[(tgui_lock) ? "Primary" : "All"]</a><br>"
dat += "<b>Play admin midis:</b> <a href='?_src_=prefs;preference=hear_midis'>[(toggles & SOUND_MIDI) ? "Yes" : "No"]</a><br>"
dat += "<b>Play lobby music:</b> <a href='?_src_=prefs;preference=lobby_music'>[(toggles & SOUND_LOBBY) ? "Yes" : "No"]</a><br>"
dat += "<b>Ghost ears:</b> <a href='?_src_=prefs;preference=ghost_ears'>[(chat_toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]</a><br>"
@@ -1011,8 +1013,10 @@ var/list/preferences_datums = list()
else
UI_style = "Midnight"
if("nanoui")
nanoui_fancy = !nanoui_fancy
if("tgui_fancy")
tgui_fancy = !tgui_fancy
if("tgui_lock")
tgui_lock = !tgui_lock
if("hear_adminhelps")
toggles ^= SOUND_ADMINHELP
+8 -7
View File
@@ -102,7 +102,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
if(current_version < 12)
ignoring = list()
//should this proc get fairly long (say 3 versions long),
//just increase SAVEFILE_VERSION_MIN so it's not as far behind
//SAVEFILE_VERSION_MAX and then delete any obsolete if clauses
@@ -165,14 +164,14 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["ooccolor"] >> ooccolor
S["lastchangelog"] >> lastchangelog
S["UI_style"] >> UI_style
S["nanoui_fancy"] >> nanoui_fancy
S["be_special"] >> be_special
S["tgui_fancy"] >> tgui_fancy
S["tgui_lock"] >> tgui_lock
if(islist(S["be_special"]))
S["be_special"] >> be_special
S["be_special"] >> be_special
else //force update and store the old bitflag version of be_special
needs_update = 11
S["be_special"] >> old_be_special
S["be_special"] >> old_be_special
S["default_slot"] >> default_slot
S["chat_toggles"] >> chat_toggles
@@ -193,7 +192,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
ooccolor = sanitize_ooccolor(sanitize_hexcolor(ooccolor, 6, 1, initial(ooccolor)))
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
UI_style = sanitize_inlist(UI_style, list("Midnight", "Plasmafire", "Retro"), initial(UI_style))
nanoui_fancy = sanitize_integer(nanoui_fancy, 0, 1, initial(nanoui_fancy))
tgui_fancy = sanitize_integer(tgui_fancy, 0, 1, initial(tgui_fancy))
tgui_lock = sanitize_integer(tgui_lock, 0, 1, initial(tgui_lock))
default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot))
toggles = sanitize_integer(toggles, 0, 65535, initial(toggles))
ghost_form = sanitize_inlist(ghost_form, ghost_forms, initial(ghost_form))
@@ -213,7 +213,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["ooccolor"] << ooccolor
S["lastchangelog"] << lastchangelog
S["UI_style"] << UI_style
S["nanoui_fancy"] << nanoui_fancy
S["tgui_fancy"] << tgui_fancy
S["tgui_lock"] << tgui_lock
S["be_special"] << be_special
S["default_slot"] << default_slot
S["toggles"] << toggles
+1 -1
View File
@@ -8,7 +8,7 @@
icon_state = null
flags = OPENCONTAINER
var/gulp_size = 5 //This is now officially broken ... need to think of a nice way to fix it.
possible_transfer_amounts = list(5,10,25)
possible_transfer_amounts = list(5,10,15,20,25,30,50)
volume = 50
burn_state = FIRE_PROOF
@@ -7,6 +7,7 @@
/obj/item/weapon/reagent_containers/food/drinks/bottle
amount_per_transfer_from_this = 10
volume = 100
throwforce = 15
item_state = "broken_beer" //Generic held-item sprite until unique ones are made.
var/const/duration = 13 //Directly relates to the 'weaken' duration. Lowered by armor (i.e. helmets)
var/isGlass = 1 //Whether the 'bottle' is made of glass or not so that milk cartons dont shatter when someone gets hit by it
+3 -3
View File
@@ -36,9 +36,9 @@
if(M.z == target_z)
M << start_up_message
sleep(start_up_time)
stage = MAIN_STAGE
weather_main()
spawn(start_up_time)
stage = MAIN_STAGE
weather_main()
/datum/weather/proc/weather_main()
@@ -47,12 +47,13 @@
duration_overlay = ""
overlay_layer = 10
/datum/weather/advanced_darkness/advanced_darkness/update_areas()
..()
/datum/weather/advanced_darkness/update_areas()
for(var/area/A in impacted_areas)
if(stage == MAIN_STAGE)
A.invisibility = 0
A.opacity = 1
else
A.invisibility = 100
A.opacity = 0
//Ash storms
+2 -2
View File
@@ -86,7 +86,7 @@ Works together with spawning an observer, noted above.
if(key)
if(!cmptext(copytext(key,1,2),"@")) // Skip aghosts.
var/mob/dead/observer/ghost = new(src) // Transfer safety to observer spawning proc.
SSnano.on_transfer(src, ghost) // Transfer NanoUIs.
SStgui.on_transfer(src, ghost) // Transfer NanoUIs.
ghost.can_reenter_corpse = can_reenter_corpse
ghost.key = key
return ghost
@@ -156,7 +156,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(mind.current.key && copytext(mind.current.key,1,2)!="@") //makes sure we don't accidentally kick any clients
usr << "<span class='warning'>Another consciousness is in your body...It is resisting you.</span>"
return
SSnano.on_transfer(src, mind.current) // Transfer NanoUIs.
SStgui.on_transfer(src, mind.current) // Transfer NanoUIs.
mind.current.key = key
return 1
+3 -1
View File
@@ -11,8 +11,10 @@
var/message_a = say_quote(message, get_spans())
var/rendered = "<i><span class='alien'>Hivemind, <span class='name'>[shown_name]</span> <span class='message'>[message_a]</span></span></i>"
for(var/mob/S in player_list)
if((!S.stat && S.hivecheck()) || (S in dead_mob_list))
if(!S.stat && S.hivecheck())
S << rendered
if(S in dead_mob_list)
S << "<a href='?src=\ref[S];follow=\ref[src]'>(F)</a>[rendered]"
/mob/living/carbon/alien/humanoid/royal/queen/alien_talk(message, shown_name = name)
shown_name = "<FONT size = 3>[shown_name]</FONT>"
@@ -39,7 +39,10 @@ var/global/posibrain_notif_cooldown = 0
spawn(askDelay) //Seperate from the global cooldown.
notified = 0
update_icon()
visible_message("<span class='notice'>The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?</span>")
if(brainmob.stat == CONSCIOUS && brainmob.client)
visible_message("<span class='notice'>The positronic brain pings, and its lights start flashing. Success!</span>")
else
visible_message("<span class='notice'>The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?</span>")
return //Code for deleting personalities recommended here.
@@ -127,7 +130,6 @@ var/global/posibrain_notif_cooldown = 0
return
/obj/item/device/mmi/posibrain/New()
brainmob = new(src)
brainmob.name = "[pick(list("PBU","HIU","SINA","ARMA","OSI","HBL","MSO","RR","CHRI","CDB","HG","XSI","ORNG","GUN","KOR","MET","FRE","XIS","SLI","PKP","HOG","RZH","GOOF","MRPR","JJR","FIRC","INC","PHL","BGB","ANTR","MIW","WJ","JRD","CHOC","ANCL","JLLO","ANNS","KOS","TKRG","XAL","STLP","CBOS","DNCN","FXMC","DRSD"))]-[rand(100, 999)]"
brainmob.real_name = brainmob.name
@@ -137,7 +139,6 @@ var/global/posibrain_notif_cooldown = 0
brainmob.silent = 0
dead_mob_list -= brainmob
ping_ghosts("created")
..()
@@ -21,8 +21,6 @@
t_has = "have"
t_is = "are"
else
if(icon)
msg += "\icon[src] " //note, should we ever go back to runtime-generated icons (please don't), you will need to change this to \icon[icon] to prevent crashes.
switch(gender)
if(MALE)
t_He = "He"
@@ -306,6 +306,8 @@
if(head)
if(head.flags & BLOCK_GAS_SMOKE_EFFECT)
. = 1
if(NOBREATH in dna.species.specflags)
. = 1
return .
/mob/living/carbon/human/proc/handle_embedded_objects()
for(var/obj/item/organ/limb/L in organs)
+1 -1
View File
@@ -208,7 +208,7 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
log_say("[mind.changeling.changelingID]/[src.key] : [message]")
for(var/mob/M in mob_list)
if(M in dead_mob_list)
M << msg
M << "<a href='?src=\ref[M];follow=\ref[src]'>(F)</a>[msg]"
else
switch(M.lingcheck())
if(2)
+7 -1
View File
@@ -842,4 +842,10 @@ var/list/ai_list = list()
//get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera
if(M && cameranet && !cameranet.checkTurfVis(get_turf_pixel(M)) && !apc_override)
return
return 1
return 1
/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
raw_message = lang_treat(speaker, message_langs, raw_message, spans)
var/name_used = speaker.GetVoice()
var/rendered = "<i><span class='game say'>Relayed Speech: <span class='name'>[name_used]</span> <span class='message'>[raw_message]</span></span></i>"
show_message(rendered, 2)
@@ -6,9 +6,10 @@
/mob/camera/aiEye
name = "Inactive AI Eye"
invisibility = 100
var/list/visibleCameraChunks = list()
var/mob/living/silicon/ai/ai = null
var/relay_speech = FALSE
// Use this when setting the aiEye's location.
// It will also stream the chunk that the new loc is in.
@@ -78,7 +79,6 @@
if (user.camera_light_on)
user.light_cameras()
// Return to the Core.
/mob/living/silicon/ai/proc/view_core()
@@ -104,3 +104,7 @@
return //won't work if dead
acceleration = !acceleration
usr << "Camera acceleration has been toggled [acceleration ? "on" : "off"]."
/mob/camera/aiEye/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
if(relay_speech && speaker && ai && !radio_freq && speaker != ai && near_camera(speaker))
ai.relay_speech(message, speaker, message_langs, raw_message, radio_freq, spans)
@@ -17,3 +17,10 @@
src.laws_sanity_check()
src.laws.show_laws(who)
if(!everyone)
for(var/mob/living/silicon/robot/R in connected_robots)
if(R.lawupdate)
R.lawsync()
R.show_laws()
R.law_change_counter++
+3 -1
View File
@@ -13,12 +13,14 @@
var/message_a = say_quote(message, get_spans())
var/rendered = "<i><span class='game say'>Robotic Talk, <span class='name'>[name]</span> <span class='message'>[message_a]</span></span></i>"
for(var/mob/M in player_list)
if(M.binarycheck() || (M in dead_mob_list))
if(M.binarycheck())
if(istype(M, /mob/living/silicon/ai))
var/renderedAI = "<i><span class='game say'>Robotic Talk, <a href='?src=\ref[M];track=[html_encode(name)]'><span class='name'>[name] ([desig])</span></a> <span class='message'>[message_a]</span></span></i>"
M << renderedAI
else
M << rendered
if(M in dead_mob_list)
M << "<a href='?src=\ref[M];follow=\ref[src]'>(F)</a>[rendered]"
/mob/living/silicon/binarycheck()
return 1
@@ -161,4 +161,19 @@
corpseuniform = /obj/item/clothing/under/color/lightpurple
corpsesuit = /obj/item/clothing/suit/wizrobe
corpseshoes = /obj/item/clothing/shoes/sandal
corpsehelmet = /obj/item/clothing/head/wizard
corpsehelmet = /obj/item/clothing/head/wizard
/obj/effect/landmark/mobcorpse/nanotrasensoldier
name = "Nanotrasen Private Security Officer"
corpseuniform = /obj/item/clothing/under/rank/security
corpsesuit = /obj/item/clothing/suit/armor/vest
corpseshoes = /obj/item/clothing/shoes/combat
corpsegloves = /obj/item/clothing/gloves/combat
corpseradio = /obj/item/device/radio/headset
corpsemask = /obj/item/clothing/mask/gas/sechailer/swat
corpsehelmet = /obj/item/clothing/head/helmet/swat/nanotrasen
corpseback = /obj/item/weapon/storage/backpack/security
corpseid = 1
corpseidjob = "Private Security Force"
corpseidaccess = "Security Officer"
@@ -2,13 +2,13 @@
name = "Guardian Spirit"
real_name = "Guardian Spirit"
desc = "A mysterious being that stands by it's charge, ever vigilant."
speak_emote = list("intones")
speak_emote = list("hisses")
response_help = "passes through"
response_disarm = "flails at"
response_harm = "punches"
icon = 'icons/mob/mob.dmi'
icon_state = "stand"
icon_living = "stand"
icon = 'icons/mob/guardian.dmi'
icon_state = "guardianorange"
icon_living = "guardianorange"
icon_dead = "stand"
speed = 0
a_intent = "harm"
@@ -26,7 +26,6 @@
melee_damage_upper = 15
butcher_results = list(/obj/item/weapon/ectoplasm = 1)
AIStatus = AI_OFF
var/animated_manifest = FALSE
var/cooldown = 0
var/damage_transfer = 1 //how much damage from each attack we transfer to the owner
var/mob/living/summoner
@@ -34,7 +33,6 @@
var/playstyle_string = "You are a standard Guardian. You shouldn't exist!"
var/magic_fluff_string = " You draw the Coder, symbolizing bugs and errors. This shouldn't happen! Submit a bug report!"
var/tech_fluff_string = "BOOT SEQUENCE COMPLETE. ERROR MODULE LOADED. THIS SHOULDN'T HAPPEN. Submit a bug report!"
var/bio_fluff_string = "Your scarabs fail to mutate. This shouldn't happen! Submit a bug report!"
/mob/living/simple_animal/hostile/guardian/Life() //Dies if the summoner dies
..()
@@ -119,11 +117,6 @@
if(loc == summoner)
loc = get_turf(summoner)
cooldown = world.time + 30
if(animated_manifest)
var/end_icon = icon_state
icon_state = "parasite_forming"
spawn(6)
icon_state = end_icon
/mob/living/simple_animal/hostile/guardian/proc/Recall()
if(cooldown > world.time)
@@ -136,10 +129,13 @@
var/input = stripped_input(src, "Please enter a message to tell your summoner.", "Guardian", "")
if(!input) return
var/my_message = "<span class='boldannounce'><i>[src]:</i> [input]</span>"
for(var/mob/M in mob_list)
if(M == summoner || (M in dead_mob_list))
M << "<span class='boldannounce'><i>[src]:</i> [input]</span>"
src << "<span class='boldannounce'><i>[src]:</i> [input]</span>"
if(M == summoner)
M << my_message
if(M in dead_mob_list)
M << "<a href='?src=\ref[M];follow=\ref[src]'>(F)</a>[my_message]"
src << "[my_message]"
log_say("[src.real_name]/[src.key] : [input]")
/mob/living/simple_animal/hostile/guardian/proc/ToggleMode()
@@ -153,13 +149,14 @@
var/input = stripped_input(src, "Please enter a message to tell your guardian.", "Message", "")
if(!input) return
var/my_message = "<span class='boldannounce'><i>[src]:</i> [input]</span>"
for(var/mob/M in mob_list)
if(istype (M, /mob/living/simple_animal/hostile/guardian))
var/mob/living/simple_animal/hostile/guardian/G = M
if(G.summoner == src)
G << "<span class='boldannounce'><i>[src]:</i> [input]</span>"
G << "[my_message]"
else if (M in dead_mob_list)
M << "<span class='boldannounce'><i>[src]:</i> [input]</span>"
M << "<a href='?src=\ref[M];follow=\ref[src]'>(F)</a>[my_message]"
src << "<span class='boldannounce'><i>[src]:</i> [input]</span>"
log_say("[src.real_name]/[src.key] : [text]")
@@ -217,7 +214,6 @@
environment_smash = 1
magic_fluff_string = "..And draw the Wizard, bringer of endless chaos!"
tech_fluff_string = "Boot sequence complete. Crowd control modules activated. Holoparasite swarm online."
bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, ready to sow havoc at random."
/mob/living/simple_animal/hostile/guardian/fire/Life() //Dies if the summoner dies
..()
@@ -265,7 +261,6 @@
environment_smash = 2
magic_fluff_string = "..And draw the Assistant, faceless and generic, but never to be underestimated."
tech_fluff_string = "Boot sequence complete. Standard combat modules loaded. Holoparasite swarm online."
bio_fluff_string = "Your scarab swarm stirs to life, ready to tear apart your enemies."
var/battlecry = "AT"
/mob/living/simple_animal/hostile/guardian/punch/verb/Battlecry()
@@ -299,7 +294,6 @@
playstyle_string = "As a Support type, you may toggle your basic attacks to a healing mode. In addition, Alt-Clicking on an adjacent mob will warp them to your bluespace beacon after a short delay."
magic_fluff_string = "..And draw the CMO, a potent force of life...and death."
tech_fluff_string = "Boot sequence complete. Medical modules active. Bluespace modules activated. Holoparasite swarm online."
bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of mending wounds and travelling via bluespace."
var/turf/simulated/floor/beacon
var/beacon_cooldown = 0
var/toggle = FALSE
@@ -424,7 +418,6 @@
playstyle_string = "As a ranged type, you have only light damage resistance, but are capable of spraying shards of crystal at incredibly high speed. You can also deploy surveillance snares to monitor enemy movement. Finally, you can switch to scout mode, in which you can't attack, but can move without limit."
magic_fluff_string = "..And draw the Sentinel, an alien master of ranged combat."
tech_fluff_string = "Boot sequence complete. Ranged combat modules active. Holoparasite swarm online."
bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of spraying shards of crystal."
var/list/snares = list()
var/toggle = FALSE
@@ -502,7 +495,6 @@
playstyle_string = "As an explosive type, you have only moderate close combat abilities, but are capable of converting any adjacent item into a disguised bomb via alt click."
magic_fluff_string = "..And draw the Scientist, master of explosive death."
tech_fluff_string = "Boot sequence complete. Explosive modules active. Holoparasite swarm online."
bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of stealthily booby trapping items."
var/bomb_cooldown = 0
/mob/living/simple_animal/hostile/guardian/bomb/AltClickOn(atom/movable/A)
@@ -609,7 +601,6 @@
else
gaurdiantype = input(user, "Pick the type of [mob_name]", "[mob_name] Creation") as null|anything in possible_guardians
var/pickedtype = /mob/living/simple_animal/hostile/guardian/punch
var/picked_color = randomColor(0)
switch(gaurdiantype)
if("Chaos")
@@ -638,26 +629,20 @@
user.verbs += /mob/living/proc/guardian_comm
user.verbs += /mob/living/proc/guardian_recall
user.verbs += /mob/living/proc/guardian_reset
var/picked_name = pick("Aries", "Leo", "Sagittarius", "Taurus", "Virgo", "Capricorn", "Gemini", "Libra", "Aquarius", "Cancer", "Scorpio", "Pisces")
var/colour = pick("orange", "pink", "red", "blue", "green")
G.name = "[picked_name] [capitalize(colour)]"
G.real_name = "[picked_name] [capitalize(colour)]"
G.icon_living = "guardian[colour]"
G.icon_state = "guardian[colour]"
G.icon_dead = "guardian[colour]"
switch (theme)
if("magic")
G.name = "[mob_name] [capitalize(picked_color)]"
G.color = color2hex(picked_color)
G.real_name = "[mob_name] [capitalize(picked_color)]"
user << "[G.magic_fluff_string]."
if("tech")
var/colour = pick("orange", "neon", "pink", "red", "blue", "green")
G.name = "[mob_name] [capitalize(colour)]"
G.real_name = "[mob_name] [capitalize(colour)]"
G.icon_living = "parasite[colour]"
G.icon_state = "parasite[colour]"
G.icon_dead = "parasite[colour]"
G.animated_manifest = TRUE
user << "[G.tech_fluff_string]."
G.speak_emote = list("states")
if("bio")
user << "[G.bio_fluff_string]."
G.attacktext = "swarms"
G.speak_emote = list("chitters")
G.mind.name = "[G.real_name]"
/obj/item/weapon/guardiancreator/choose
@@ -678,21 +663,6 @@
/obj/item/weapon/guardiancreator/tech/choose
random = FALSE
/obj/item/weapon/guardiancreator/biological
name = "scarab egg cluster"
desc = "A parasitic species that will nest in the closest living creature upon birth. While not great for your health, they'll defend their new 'hive' to the death."
icon = 'icons/obj/syringe.dmi'
icon_state = "combat_hypo"
theme = "bio"
mob_name = "Scarab Swarm"
use_message = "The eggs begin to twitch..."
used_message = "The cluster already hatched."
failure_message = "<B>...but soon settles again. Guess they weren't ready to hatch after all.</B>"
/obj/item/weapon/guardiancreator/biological/choose
random = FALSE
/obj/item/weapon/paper/guardian
name = "Holoparasite Guide"
icon_state = "alienpaper_words"
@@ -724,11 +694,6 @@
return
///HUD
/datum/hud/proc/guardian_hud(ui_style = 'icons/mob/screen_midnight.dmi')
@@ -761,8 +726,6 @@
mymob.client.screen += adding
//HUD BUTTONS
/obj/screen/guardian
@@ -31,6 +31,7 @@
faction = list("carp")
flying = 1
pressure_resistance = 200
gold_core_spawnable = 1
/mob/living/simple_animal/hostile/carp/Process_Spacemove(movement_dir = 0)
@@ -24,7 +24,7 @@
speak_emote = list("states")
gold_core_spawnable = 1
del_on_death = 1
loot = (/obj/effect/decal/cleanable/robot_debris)
loot = list(/obj/effect/decal/cleanable/robot_debris)
/mob/living/simple_animal/hostile/hivebot/New()
..()
@@ -374,6 +374,8 @@
/mob/living/simple_animal/hostile/asteroid/goliath/OpenFire()
var/tturf = get_turf(target)
if(!(istype(tturf, /turf/simulated)))
return
if(get_dist(src, target) <= 7)//Screen range check, so you can't get tentacle'd offscreen
visible_message("<span class='warning'>The [src.name] digs its tentacles under [target.name]!</span>")
new /obj/effect/goliath_tentacle/original(tturf)
@@ -0,0 +1,58 @@
/mob/living/simple_animal/hostile/nanotrasen
name = "Nanotrasen Private Security Officer"
desc = "An officer part of Nanotrasen's private security force, he seems rather unpleased to meet you."
icon_state = "nanotrasen"
icon_living = "nanotrasen"
icon_dead = null
icon_gib = "syndicate_gib"
speak_chance = 25
turns_per_move = 5
response_help = "pokes"
response_disarm = "shoves"
response_harm = "hits"
speed = 0
stat_attack = 1
robust_searching = 1
maxHealth = 100
health = 100
harm_intent_damage = 5
melee_damage_lower = 10
melee_damage_upper = 15
attacktext = "punches"
attack_sound = 'sound/weapons/punch1.ogg'
a_intent = "harm"
loot = list(/obj/effect/landmark/mobcorpse/nanotrasensoldier)
atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0)
unsuitable_atmos_damage = 15
faction = list("nanotrasenprivate")
status_flags = CANPUSH
speak = list("Stop resisting!", "I AM THE LAW!", "Face the wrath of the golden bolt!", "Stop breaking the law, asshole!")
search_objects = 1
/mob/living/simple_animal/hostile/nanotrasen/Aggro()
..()
summon_backup(15)
say("411 in progress, requesting backup!")
/mob/living/simple_animal/hostile/nanotrasen/ranged
icon_state = "nanotrasenranged"
icon_living = "nanotrasenranged"
ranged = 1
retreat_distance = 3
minimum_distance = 5
casingtype = /obj/item/ammo_casing/c45
projectilesound = 'sound/weapons/Gunshot.ogg'
loot = list(/obj/item/weapon/gun/projectile/automatic/pistol/m1911,
/obj/effect/landmark/mobcorpse/nanotrasensoldier)
/mob/living/simple_animal/hostile/nanotrasen/ranged/smg
icon_state = "nanotrasenrangedsmg"
icon_living = "nanotrasenrangedsmg"
rapid = 1
casingtype = /obj/item/ammo_casing/c46x30mm
projectilesound = 'sound/weapons/Gunshot_smg.ogg'
loot = list(/obj/item/weapon/gun/projectile/automatic/wt550,
/obj/effect/landmark/mobcorpse/nanotrasensoldier)
+3 -2
View File
@@ -27,7 +27,7 @@
player_list |= src
update_Login_details()
world.update_status()
client.images = null //remove the images such as AIs being unable to see runes
client.screen = list() //remove hud items just in case
if(hud_used) qdel(hud_used) //remove the hud objects
@@ -37,7 +37,8 @@
sight |= SEE_SELF
..()
if (key != client.key)
key = client.key
if(loc && !isturf(loc))
client.eye = loc
client.perspective = EYE_PERSPECTIVE
+1 -1
View File
@@ -1,5 +1,5 @@
/mob/Logout()
SSnano.on_logout(src)
SStgui.on_logout(src)
player_list -= src
log_access("Logout: [key_name(src)]")
if(admin_datums[src.ckey])
-365
View File
@@ -1,365 +0,0 @@
/**
* NanoUI
*
* Contains the NanoUI datum, and its procs.
*
* /tg/station user interface library
* thanks to baystation12
*
* modified by neersighted
**/
/**
* NanoUI datum:
*
* Represents a NanoUI.
**/
/datum/nanoui
var/mob/user // The mob who opened/is using the NanoUI.
var/atom/movable/src_object // The object which owns the NanoUI.
var/title // The title of te NanoUI.
var/ui_key // The ui_key of the NanoUI. This allows multiple UIs for one src_object.
var/window_id // The window_id for browse() and onclose().
var/width = 0 // The window width.
var/height = 0 // The window height
var/window_options = list( // Extra options to winset().
"focus" = 0,
"titlebar" = 1,
"can_resize" = 1,
"can_minimize" = 1,
"can_maximize" = 0,
"can_close" = 1,
"auto_format" = 0
)
var/atom/ref = null // An extra ref to call when the window is closed.
var/layout = "nanotrasen" // The layout to be used for this UI.
var/template // The template to be used for this UI.
var/auto_update = 1 // Update the NanoUI every MC tick.
var/list/initial_data // The data (and datastructure) used to initialize the NanoUI
var/status = NANO_INTERACTIVE // The status/visibility of the NanoUI.
var/datum/nano_state/state = null // Topic state used to determine status. Topic states are in interactions/.
var/datum/nanoui/master_ui // The parent NanoUI.
var/list/datum/nanoui/children = list() // Children of this NanoUI.
/**
* public
*
* Create a new NanoUI.
*
* required user mob The mob who opened/is using the NanoUI.
* required src_object atom/movable The object which owns the NanoUI.
* required ui_key string The ui_key of the NanoUI.
* required template string The template to render the NanoUI content with.
* optional title string The title of the NanoUI.
* optional width int The window width.
* optional height int The window height.
* optional ref atom An extra ref to use when the window is closed.
* optional master_ui datum/nanoui The parent NanoUI.
* optional state datum/nano_state The state used to determine status.
*
* return datum/nanoui The requested NanoUI.
**/
/datum/nanoui/New(mob/user, atom/movable/src_object, ui_key, template, \
title, width = 0, height = 0, \
atom/ref = null, datum/nanoui/master_ui = null, \
datum/nano_state/state = default_state)
src.user = user
src.src_object = src_object
src.ui_key = ui_key
src.window_id = "\ref[src_object]-[ui_key]"
set_template(template)
if(title)
src.title = sanitize(title)
if(width)
src.width = width
if(height)
src.height = height
if(ref)
src.ref = ref
src.master_ui = master_ui
if(master_ui)
master_ui.children += src
src.state = state
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/nanoui)
assets.send(user)
/**
* public
*
* Open this NanoUI (and initialize it with data).
*
* optional data list The data to intialize the UI with.
**/
/datum/nanoui/proc/open(list/data = null)
if(!user.client)
return // Bail if there is no client.
update_status(push = 0) // Update the window status.
if(status == NANO_CLOSE)
return // Bail if we should close.
if(!initial_data)
if(!data) // If we don't have initial_data and data was not passed, get data from the src_object.
data = src_object.get_ui_data(user)
set_initial_data(data) // Otherwise use the passed data.
var/window_size = ""
if(width && height) // If we have a width and height, use them.
window_size = "size=[width]x[height];"
user << browse(get_html(), "window=[window_id];[window_size][list2params(window_options)]") // Open the window.
winset(user, window_id, "on-close=\"nanoclose \ref[src]\"") // Instruct the client to signal NanoUI when the window is closed.
SSnano.on_open(src)
/**
* public
*
* Reinitialize the NanoUI.
* (Possibly with a new template and/or data).
*
* optional template string The filename of the new template.
* optional data list The new initial data.
**/
/datum/nanoui/proc/reinitialize(template, list/data)
if(template)
set_template(template) // Set a new template.
if(data)
set_initial_data(data) // Replace the initial_data.
open()
/**
* public
*
* Close the NanoUI, and all its children.
**/
/datum/nanoui/proc/close()
user << browse(null, "window=[window_id]") // Close the window.
SSnano.on_close(src)
for(var/datum/nanoui/child in children) // Loop through and close all children.
child.close()
/**
* public
*
* Sets the browse() window options for this NanoUI.
*
* required window_options list The window options to set.
**/
/datum/nanoui/proc/set_window_options(list/window_options)
src.window_options = window_options
/**
* public
*
* Set the layout for this NanoUI.
* This loads custom layout styles and templates for this NanoUI.
*
* required layout string The new UI layout.
**/
/datum/nanoui/proc/set_layout(layout)
src.layout = lowertext(layout)
/**
* public
*
* Set the template for this NanoUI.
*
* required template string The new UI template.
**/
/datum/nanoui/proc/set_template(template)
src.template = lowertext(template)
/**
* public
*
* Enable/disable auto-updating of the NanoUI.
*
* required state bool Enable/disable auto-updating.
**/
/datum/nanoui/proc/set_auto_update(state = 1)
auto_update = state
/**
* private
*
* Set the data to initialize the NanoUI with.
* The datastructure cannot be changed by subsequent updates.
*
* optional data list The data/datastructure to initialize the NanoUI with.
**/
/datum/nanoui/proc/set_initial_data(list/data)
initial_data = data
/**
* private
*
* Generate HTML for this NanoUI.
*
* return string NanoUI HTML output.
**/
/datum/nanoui/proc/get_html()
// Generate JSON.
var/list/send_data = get_send_data(initial_data)
var/send_data_json = JSON.stringify(send_data)
send_data_json = replacetextEx(send_data_json, "'", "&apos;")
send_data_json = replacetextEx(send_data_json, "\improper", "")
send_data_json = replacetextEx(send_data_json, "ÿ", "")
// Populate it.
var/send_html = replacetextEx(SSnano.html, "\[data]", send_data_json)
return send_html
/**
* private
*
* Get the config data/datastructure to initialize the NanoUI with.
*
* return list The config data.
**/
/datum/nanoui/proc/get_config_data()
var/list/config_data = list(
"title" = title,
"status" = status,
"layout" = layout,
"window" = window_id,
"ref" = "\ref[src]",
"user" = list(
"name" = user.name,
"fancy" = user.client.prefs.nanoui_fancy,
"ref" = "\ref[user]"
),
"srcObject" = list(
"name" = src_object.name,
"ref" = "\ref[src_object]"
),
"templates" = list(
"layout" = "_[layout]",
"content" = "[template]"
)
)
return config_data
/**
* private
*
* Package the data to send to the UI.
* This is the (regular) data and config data, bundled together.
*
* return list The packaged data.
**/
/datum/nanoui/proc/get_send_data(list/data)
var/list/send_data = list()
send_data["config"] = get_config_data()
if(!isnull(data))
send_data["data"] = data
return send_data
/**
* private
*
* Handle clicks from the NanoUI.
* Call the src_object's ui_act() if status is NANO_INTERACTIVE.
* If the src_object's ui_act() returns 1, update all UIs attacked to it.
**/
/datum/nanoui/Topic(href, href_list)
update_status(push = 0) // Update the window state.
if(status != NANO_INTERACTIVE || user != usr)
return // If UI is not interactive or usr calling Topic is not the UI user.
var/action = href_list["nano"] // Pull the action out.
href_list -= "nano"
var/update = src_object.ui_act(action, href_list, state) // Call ui_act() on the src_object.
if(src_object && update)
SSnano.update_uis(src_object) // If we have a src_object and its ui_act() told us to update.
/**
* private
*
* Update the NanoUI. Only updates the contents/layout if update is true,
* otherwise only updates the status.
*
* optional force bool If the UI should be forced to update.
**/
/datum/nanoui/process(force = 0)
if(!src_object || !user) // If the object or user died (or something else), abort.
close()
return
if(status && (force || auto_update))
update() // Update the UI if the status and update settings allow it.
else
update_status(push = 1) // Otherwise only update status.
/**
* private
*
* Push data to an already open NanoUI.
*
* required data list The data to send.
* optional force bool If the update should be sent regardless of state.
**/
/datum/nanoui/proc/push_data(data, force = 0)
update_status(push = 0) // Update the window state.
if(status <= NANO_DISABLED && !force)
return // Cannot update UI, we have no visibility.
var/list/send_data = get_send_data(data) // Get the data to send.
// Send the new data to the recieveUpdate() Javascript function.
user << output(url_encode(JSON.stringify(send_data)), "[window_id].browser:receiveUpdate")
/**
* private
*
* Updates the UI by interacting with the src_object again, which will hopefully
* call try_ui_update on it.
*
* optional force_open bool If force_open should be passed to ui_interact.
**/
/datum/nanoui/proc/update(force_open = 0)
src_object.ui_interact(user, ui_key, src, force_open, master_ui, state)
/**
* private
*
* Update the status/visibility of the NanoUI for its user.
*
* optional push bool Push an update to the UI (an update is always sent for NANO_DISABLED).
**/
/datum/nanoui/proc/update_status(push = 0)
var/new_status = src_object.nano_state(user, state)
if(master_ui)
new_status = min(new_status, master_ui.status)
if(new_status == NANO_CLOSE)
close()
else
set_status(new_status, push)
/**
* private
*
* Set the status/visibility of the NanoUI.
*
* required status int The status to set (NANO_CLOSE/NANO_DISABLED/NANO_UPDATE/NANO_INTERACTIVE).
* optional push bool Push an update to the UI (an update is always sent for NANO_DISABLED).
**/
/datum/nanoui/proc/set_status(status, push = 0)
if(src.status != status) // Only update if status has changed.
if(src.status == NANO_DISABLED)
src.status = status
if(push)
update()
else
src.status = status
if(status == NANO_DISABLED || push) // Update if the UI just because disabled, or a push is requested.
push_data(null, force = 1)
-12
View File
@@ -1,12 +0,0 @@
/**
* NanoUI State: admin_state
*
* Checks that the user is an admin, end-of-story.
**/
/var/global/datum/nano_state/admin_state/admin_state = new()
/datum/nano_state/admin_state/can_use_topic(atom/movable/src_object, mob/user)
if(check_rights_for(user.client, R_ADMIN))
return NANO_INTERACTIVE
return NANO_CLOSE
-12
View File
@@ -1,12 +0,0 @@
/**
* NanoUI State: conscious_state
*
* Only checks if the user is conscious.
**/
/var/global/datum/nano_state/conscious_state/conscious_state = new()
/datum/nano_state/conscious_state/can_use_topic(atom/movable/src_object, mob/user)
if(user.stat == CONSCIOUS)
return NANO_INTERACTIVE
return NANO_CLOSE
-12
View File
@@ -1,12 +0,0 @@
/**
* NanoUI State: contained_state
*
* Checks that the user is inside the src_object.
**/
/var/global/datum/nano_state/contained_state/contained_state = new()
/datum/nano_state/contained_state/can_use_topic(atom/movable/src_object, mob/user)
if(!src_object.contains(user))
return NANO_CLOSE
return user.shared_nano_interaction(src_object)
@@ -1,12 +0,0 @@
/**
* NanoUI State: deep_inventory_state
*
* Checks that the src_object is in the user's fist-level (backpack, webbing, etc) inventory.
**/
/var/global/datum/nano_state/deep_inventory_state/deep_inventory_state = new()
/datum/nano_state/deep_inventory_state/can_use_topic(atom/movable/src_object, mob/user)
if(!user.contains(src_object))
return NANO_CLOSE
return user.shared_nano_interaction(src_object)
-20
View File
@@ -1,20 +0,0 @@
/**
* NanoUI State: hands_state
*
* Checks that the src_object is in the user's hands.
**/
/var/global/datum/nano_state/hands_state/hands_state = new()
/datum/nano_state/hands_state/can_use_topic(atom/movable/src_object, mob/user)
. = user.shared_nano_interaction(src_object)
if(. > NANO_CLOSE)
return min(., user.hands_can_use_topic(src_object))
/mob/proc/hands_can_use_topic(atom/movable/src_object)
return NANO_CLOSE
/mob/living/hands_can_use_topic(atom/movable/src_object)
if(src_object in get_both_hands(src))
return NANO_INTERACTIVE
return NANO_CLOSE
-12
View File
@@ -1,12 +0,0 @@
/**
* NanoUI State: inventory_state
*
* Checks that the src_object is in the user's top-level (hand, ear, pocket, belt, etc) inventory.
**/
/var/global/datum/nano_state/inventory_state/inventory_state = new()
/datum/nano_state/inventory_state/can_use_topic(atom/movable/src_object, mob/user)
if(!(src_object in user))
return NANO_CLOSE
return user.shared_nano_interaction(src_object)
-21
View File
@@ -1,21 +0,0 @@
/**
* NanoUI State: physical_state
*
* Short-circuits the default state to only check physical distance.
**/
/var/global/datum/nano_state/physical/physical_state = new()
/datum/nano_state/physical/can_use_topic(atom/movable/src_object, mob/user)
. = user.shared_nano_interaction(src_object)
if(. > NANO_CLOSE)
return min(., user.physical_can_use_topic(src_object))
/mob/proc/physical_can_use_topic(atom/movable/src_object)
return NANO_CLOSE
/mob/living/physical_can_use_topic(atom/movable/src_object)
return shared_living_nano_distance(src_object)
/mob/living/silicon/physical_can_use_topic(atom/movable/src_object)
return max(NANO_UPDATE, shared_living_nano_distance(src_object)) // Silicons can always see.
-12
View File
@@ -1,12 +0,0 @@
/**
* NanoUI State: self_state
*
* Only checks that the user and src_object are the same.
**/
/var/global/datum/nano_state/self_state/self_state = new()
/datum/nano_state/self_state/can_use_topic(atom/movable/src_object, mob/user)
if(src_object != user)
return NANO_CLOSE
return user.shared_nano_interaction(src_object)
-112
View File
@@ -1,112 +0,0 @@
/**
* NanoUI States
*
* Base state and helpers for states. Just does some sanity checks, implement a state for in-depth checks.
**/
/**
* public
*
* Checks if a user can use src_object's NanoUI, under the given state.
*
* required user mob The mob who opened/is using the NanoUI.
* required state datum/nano_state The state to check.
*
* return NANO_state The state of the UI.
**/
/atom/proc/nano_state(mob/user, datum/nano_state/state)
var/src_object = nano_host()
if(istype(user, /mob/dead/observer)) // Special-case ghosts.
if(check_rights_for(user.client, R_ADMIN))
return NANO_INTERACTIVE // Admins can interact anyway.
if(get_dist(src_object, src) > user.client.view)
return NANO_CLOSE // Keep ghosts from opening too many NanoUIs.
return NANO_UPDATE // Ghosts can only view.
return state.can_use_topic(src_object, user) // Check if the state allows interaction.
/**
* private
*
* Checks if a user can use src_object's NanoUI, and returns the state.
* Can call a mob proc, which allows overrides for each mob.
*
* required src_object atom/movable The object which owns the NanoUI.
* required user mob The mob who opened/is using the NanoUI.
*
* return NANO_state The state of the UI.
**/
/datum/nano_state/proc/can_use_topic(atom/movable/src_object, mob/user)
return NANO_CLOSE // Don't allow interaction by default.
/**
* public
*
* Standard interaction/sanity checks. Different mob types may have overrides.
*
* return NANO_state The state of the UI.
**/
/mob/proc/shared_nano_interaction(atom/movable/src_object)
if(!client || stat) // Close NanoUIs if mindless or dead/unconcious.
return NANO_CLOSE
// Update NanoUIs if incapicitated but concious.
else if(incapacitated() || lying)
return NANO_UPDATE
return NANO_INTERACTIVE
/mob/living/carbon/human/shared_nano_interaction(atom/movable/src_object)
// If we have telekinesis and remain close enough, allow interaction.
if(dna.check_mutation(TK))
if(tkMaxRangeCheck(src, src_object))
return NANO_INTERACTIVE
return ..()
/mob/living/silicon/ai/shared_nano_interaction(atom/movable/src_object)
if(lacks_power()) // Close NanoUIs if the AI is unpowered.
return NANO_CLOSE
return ..()
/mob/living/silicon/robot/shared_nano_interaction(atom/movable/src_object)
if(cell.charge <= 0) // Close NanoUIs if the Borg is unpowered.
return NANO_CLOSE
if(lockcharge) // Disable NanoUIs if the Borg is locked.
return NANO_DISABLED
return ..()
/**
* public
*
* Check the distance for a living mob.
* Really only used for checks outside the context of a mob.
* Otherwise, use shared_living_nano_distance().
*
* required src_object atom/movable The object which owns the NanoUI.
* required user mob The mob who opened/is using the NanoUI.
*
* return NANO_state The state of the UI.
**/
/atom/proc/contents_nano_distance(atom/movable/src_object, mob/living/user)
return user.shared_living_nano_distance(src_object) // Just call this mob's check.
/**
* public
*
* Distance versus interaction check.
*
* required src_object atom/movable The object which owns the NanoUI.
*
* return NANO_state The state of the UI.
**/
/mob/living/proc/shared_living_nano_distance(atom/movable/src_object)
if(!(src_object in view(4, src))) // If the object is out of view, close it.
return NANO_CLOSE
var/dist = get_dist(src_object, src)
if(dist <= 1) // Open and interact if 1-0 tiles away.
return NANO_INTERACTIVE
else if(dist <= 2) // View only if 2-3 tiles away.
return NANO_UPDATE
else if(dist <= 5) // Disable if 5 tiles away.
return NANO_DISABLED
return NANO_CLOSE // Otherwise, we got nothing.
+6
View File
@@ -131,6 +131,12 @@
desc = "A polaroid camera, some say it can see ghosts!"
see_ghosts = 1
/obj/item/device/camera/detective
name = "Detective's camera"
desc = "A polaroid camera with extra capacity for crime investigations."
pictures_max = 30
pictures_left = 30
/obj/item/device/camera/siliconcam //camera AI can take pictures with
name = "silicon photo camera"
+16 -13
View File
@@ -626,10 +626,10 @@
else
ui_interact(user)
/obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, force_open = 0)
ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open)
/obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", var/datum/tgui/ui = null, force_open = 0)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open = force_open)
if (!ui)
ui = new(user, src, ui_key, "apc", name, 550, 550)
ui = new(user, src, ui_key, "apc", name, 460, 520)
ui.open()
/obj/machinery/power/apc/get_ui_data(mob/user)
@@ -747,12 +747,22 @@
if(!can_use(usr, 1))
return
if(locked && !usr.has_unlimited_silicon_privilege)
return
switch(action)
if("lock")
if(usr.has_unlimited_silicon_privilege)
if(emagged || (stat & (BROKEN|MAINT)))
usr << "The APC does not respond to the command."
else
locked = !locked
update_icon()
if("cover")
coverlocked = !coverlocked
if ("breaker")
if("breaker")
toggle_breaker()
if("chargemode")
if("charge")
chargemode = !chargemode
if(!chargemode)
charging = 0
@@ -773,19 +783,12 @@
environ = setsubsystem(val)
update_icon()
update()
if("toggleaccess")
if(usr.has_unlimited_silicon_privilege)
if(emagged || (stat & (BROKEN|MAINT)))
usr << "The APC does not respond to the command."
else
locked = !locked
update_icon()
if("overload")
if(usr.has_unlimited_silicon_privilege)
src.overload_lighting()
if("hack")
var/mob/living/silicon/ai/malfai = usr
if(get_malf_status(malfai)==1)
if(get_malf_status(malfai) == 1)
if (malfai.malfhacking)
malfai << "You are already hacking an APC."
return 1
+1
View File
@@ -468,6 +468,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list ( \
item_state = "coil_red"
max_amount = MAXCOIL
amount = MAXCOIL
merge_type = /obj/item/stack/cable_coil // This is here to let its children merge between themselves
item_color = "red"
desc = "A coil of power cable."
throwforce = 0
+20 -15
View File
@@ -256,22 +256,27 @@
else
if(input_attempt && input_available > 0 && input_available >= input_level)
inputting = 1
else
inputting = 0
//outputting
if(outputting)
output_used = min( charge/SMESRATE, output_level) //limit output to that stored
if(output_attempt)
if(outputting)
output_used = min( charge/SMESRATE, output_level) //limit output to that stored
charge -= output_used*SMESRATE // reduce the storage (may be recovered in /restore() if excessive)
charge -= output_used*SMESRATE // reduce the storage (may be recovered in /restore() if excessive)
add_avail(output_used) // add output to powernet (smes side)
add_avail(output_used) // add output to powernet (smes side)
if(output_used < 0.0001) // either from no charge or set to 0
outputting = 0
investigate_log("lost power and turned <font color='red'>off</font>","singulo")
else if(output_attempt && charge > output_level && output_level > 0)
outputting = 1
if(output_used < 0.0001) // either from no charge or set to 0
outputting = 0
investigate_log("lost power and turned <font color='red'>off</font>","singulo")
else if(output_attempt && charge > output_level && output_level > 0)
outputting = 1
else
output_used = 0
else
output_used = 0
outputting = 0
// only update icon if state changed
if(last_disp != chargedisplay() || last_chrg != inputting || last_onln != outputting)
@@ -324,10 +329,10 @@
return
ui_interact(user)
/obj/machinery/power/smes/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0)
ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open)
/obj/machinery/power/smes/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open = force_open)
if (!ui)
ui = new(user, src, ui_key, "smes", name, 500, 455)
ui = new(user, src, ui_key, "smes", name, 340, 440)
ui.open()
/obj/machinery/power/smes/get_ui_data()
@@ -364,7 +369,7 @@
log_smes(usr.ckey)
update_icon()
if("input")
switch(params["set"])
switch(params["input"])
if("custom")
var/custom = input(usr, "What rate would you like this SMES to attempt to charge at? Max is [input_level_max].") as null|num
if(custom)
@@ -380,7 +385,7 @@
input_level = Clamp(input_level, 0, input_level_max)
log_smes(usr.ckey)
if("output")
switch(params["set"])
switch(params["output"])
if("custom")
var/custom = input(usr, "What rate would you like this SMES to attempt to output at? Max is [output_level_max].") as null|num
if(custom)
+3 -3
View File
@@ -369,10 +369,10 @@
return
ui_interact(user)
/obj/machinery/power/solar_control/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0)
ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open)
/obj/machinery/power/solar_control/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open = force_open)
if (!ui)
ui = new(user, src, ui_key, "solar_control", name, 515, 425)
ui = new(user, src, ui_key, "solar_control", name, 465, 400)
ui.open()
/obj/machinery/power/solar_control/get_ui_data()
@@ -176,7 +176,7 @@
name = "wt550 magazine (4.6x30mm)"
icon_state = "46x30mmt-20"
ammo_type = /obj/item/ammo_casing/c46x30mm
caliber = "4x6x30mm"
caliber = "4.6x30mm"
max_ammo = 20
/obj/item/ammo_box/magazine/wt550m9/update_icon()
@@ -37,7 +37,6 @@
if(istype(AM, mag_type))
if(magazine)
user << "<span class='notice'>You perform a tactical reload on \the [src], replacing the magazine.</span>"
user.say(pick("I'M RELOADING!!!", "NEW MAG IN!!!", "CHANGING MAG!!!", "COVER ME! I'M RELOADING!!!", "RELOADING!!!"))
magazine.loc = get_turf(src.loc)
magazine.update_icon()
magazine = null
@@ -233,4 +232,4 @@
fire_sound = 'sound/weapons/Gunshot_smg.ogg'
can_suppress = 0
burst_size = 3
fire_delay = 1
fire_delay = 1
@@ -85,10 +85,10 @@
return
ui_interact(user)
/obj/machinery/chem_dispenser/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0)
ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open)
/obj/machinery/chem_dispenser/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open = force_open)
if (!ui)
ui = new(user, src, ui_key, "chem_dispenser", name, 530, 700)
ui = new(user, src, ui_key, "chem_dispenser", name, 550, 700)
ui.open()
/obj/machinery/chem_dispenser/get_ui_data()
@@ -119,7 +119,7 @@
for(var/re in dispensable_reagents)
var/datum/reagent/temp = chemical_reagents_list[re]
if(temp)
chemicals.Add(list(list("title" = temp.name, "id" = temp.id, "commands" = list("reagent" = temp.id))))
chemicals.Add(list(list("title" = temp.name, "id" = temp.id)))
data["chemicals"] = chemicals
return data
@@ -129,7 +129,7 @@
switch(action)
if("amount")
amount = round(text2num(params["set"]), 5) // round to nearest 5
amount = round(text2num(params["amount"]), 5) // round to nearest 5
if (amount < 0) // Since the user can actually type the commands himself, some sanity checking
amount = 0
if (amount > 100)
@@ -87,6 +87,7 @@
if("temperature")
desired_temp = Clamp(input("Please input the target temperature", name) as num, 0, 1000)
if("eject")
on = FALSE
eject_beaker()
return 1
@@ -95,10 +96,10 @@
return
ui_interact(user)
/obj/machinery/chem_heater/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0)
ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open)
/obj/machinery/chem_heater/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open = force_open)
if (!ui)
ui = new(user, src, ui_key, "chem_heater", name, 350, 400)
ui = new(user, src, ui_key, "chem_heater", name, 275, 400)
ui.open()
/obj/machinery/chem_heater/get_ui_data()
@@ -141,9 +141,8 @@
*/
/datum/reagent/water/reaction_obj(obj/O, reac_volume)
if(istype(O,/obj/item))
var/obj/item/Item = O
Item.extinguish()
if(istype(O))
O.extinguish()
// Monkey cube
if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/monkeycube))
@@ -163,10 +162,11 @@
*/
/datum/reagent/water/reaction_mob(mob/living/M, method=TOUCH, reac_volume)//Splashing people with water can help put them out!
if(!istype(M, /mob/living))
if(!istype(M))
return
if(method == TOUCH)
M.adjust_fire_stacks(-(reac_volume / 10))
M.ExtinguishMob()
..()
/datum/reagent/water/holywater
+1 -1
View File
@@ -5,7 +5,7 @@
icon_state = null
w_class = 1
var/amount_per_transfer_from_this = 5
var/list/possible_transfer_amounts = list(5,10,15,25,30)
var/list/possible_transfer_amounts = list(5,10,15,20,25,30)
var/volume = 30
var/list/list_reagents = null
var/spawned_disease = null
@@ -1,7 +1,7 @@
/obj/item/weapon/reagent_containers/glass
name = "glass"
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5, 10, 15, 25, 30, 50)
possible_transfer_amounts = list(5, 10, 15, 20, 25, 30, 50)
volume = 50
flags = OPENCONTAINER
spillable = 1
@@ -197,7 +197,7 @@
materials = list(MAT_GLASS=2500)
volume = 100
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,25,30,50,100)
possible_transfer_amounts = list(5,10,15,20,25,30,50,100)
flags = OPENCONTAINER
/obj/item/weapon/reagent_containers/glass/beaker/noreact
@@ -216,7 +216,7 @@
materials = list(MAT_GLASS=5000)
volume = 300
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,25,30,50,100,300)
possible_transfer_amounts = list(5,10,15,20,25,30,50,100,300)
flags = OPENCONTAINER
/obj/item/weapon/reagent_containers/glass/beaker/cryoxadone
@@ -253,7 +253,7 @@
materials = list(MAT_METAL=200)
w_class = 3
amount_per_transfer_from_this = 20
possible_transfer_amounts = list(10,20,30,50,70)
possible_transfer_amounts = list(10,15,20,25,30,50,70)
volume = 70
flags = OPENCONTAINER | BLOCKHAIR
slot_flags = SLOT_HEAD
@@ -290,4 +290,4 @@
. = ..()
slot_equipment_priority.Insert(index, slot_head)
return
return ..()
return ..()
+5 -5
View File
@@ -114,7 +114,7 @@
/obj/item/weapon/stock_parts/matter_bin
name = "matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
desc = "A container designed to hold compressed matter awaiting reconstruction."
icon_state = "matter_bin"
origin_tech = "materials=1"
materials = list(MAT_METAL=80)
@@ -155,7 +155,7 @@
/obj/item/weapon/stock_parts/matter_bin/adv
name = "advanced matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
desc = "A container designed to hold compressed matter awaiting reconstruction."
icon_state = "advanced_matter_bin"
origin_tech = "materials=3"
rating = 2
@@ -197,7 +197,7 @@
/obj/item/weapon/stock_parts/matter_bin/super
name = "super matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
desc = "A container designed to hold compressed matter awaiting reconstruction."
icon_state = "super_matter_bin"
origin_tech = "materials=5"
rating = 3
@@ -239,7 +239,7 @@
/obj/item/weapon/stock_parts/matter_bin/bluespace
name = "bluespace matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
desc = "A container designed to hold compressed matter awaiting reconstruction."
icon_state = "bluespace_matter_bin"
origin_tech = "materials=6"
rating = 4
@@ -301,4 +301,4 @@
icon = 'icons/obj/stock_parts.dmi'
icon_state = "capacitor"
desc = "A debug item for research."
origin_tech = "materials=8;programming=8;magnets=8;powerstorage=8;bluespace=8;combat=8;biotech=8;syndicate=8;engineering=8;plasmatech=8"
origin_tech = "materials=8;programming=8;magnets=8;powerstorage=8;bluespace=8;combat=8;biotech=8;syndicate=8;engineering=8;plasmatech=8"
@@ -1,41 +1,36 @@
/**
* NanoUI External
* tgui external
*
* Contains all external NanoUI declarations.
*
* /tg/station user interface library
* thanks to baystation12
*
* modified by neersighted
* Contains all external tgui declarations.
**/
/**
* public
*
* Used to open and update NanoUIs.
* If this proc is not implemented properly, the NanoUI will not update correctly.
* Used to open and update UIs.
* If this proc is not implemented properly, the UI will not update correctly.
*
* required user mob The mob who opened/is using the NanoUI.
* optional ui_key string The ui_key of the NanoUI.
* optional ui datum/nanoui The UI to be updated, if it exists.
* required user mob The mob who opened/is using the UI.
* optional ui_key string The ui_key of the UI.
* optional ui datum/tgui The UI to be updated, if it exists.
* optional force_open bool If the UI should be re-opened instead of updated.
* optional master_ui datum/nanoui The parent NanoUI.
* optional state datum/nano_state The state used to determine status.
* optional master_ui datum/tgui The parent UI.
* optional state datum/ui_state The state used to determine status.
**/
/atom/movable/proc/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, \
force_open = 0, datum/nano_ui/master_ui = null, \
datum/nano_state/state = default_state)
/atom/movable/proc/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, \
force_open = 0, datum/tgui/master_ui = null, \
datum/ui_state/state = default_state)
return -1 // Sorta implemented.
/**
* public
*
* Data to be sent to the NanoUI.
* This must be implemented for a NanoUI to work.
* Data to be sent to the UI.
* This must be implemented for a UI to work.
*
* required user mob The mob interacting with the NanoUI.
* required user mob The mob interacting with the UI.
*
* return list Data to be sent to the NanoUI.
* return list Data to be sent to the UI.
**/
/atom/movable/proc/get_ui_data(mob/user)
return list() // Not implemented.
@@ -44,7 +39,7 @@
/**
* public
*
* Called on a NanoUI when the UI receieves a href.
* Called on a UI when the UI receieves a href.
* Think of this as Topic().
*
* required action string The action/button that has been invoked by the user.
@@ -59,34 +54,34 @@
/**
* private
*
* The NanoUI's host object (usually src_object).
* Used internally by nano_state(s).
* The UI's host object (usually src_object).
* Used internally by ui_state(s).
**/
/atom/proc/nano_host()
/atom/proc/ui_host()
return src
/**
* global
*
* Used to track NanoUIs for a mob.
* Used to track UIs for a mob.
**/
/mob/var/list/open_uis = list()
/**
* verb
*
* Called by NanoUIs when they are closed.
* Called by UIs when they are closed.
* Must be a verb so winset() can call it.
*
* required uiref ref The UI that was closed.
**/
/client/verb/nanoclose(uiref as text)
/client/verb/uiclose(uiref as text)
// Name the verb, and hide it from the user panel.
set name = "nanoclose"
set name = "uiclose"
set hidden = 1
// Get the UI based on the ref.
var/datum/nanoui/ui = locate(uiref)
var/datum/tgui/ui = locate(uiref)
// If we found the UI, close it.
if(istype(ui))
+12
View File
@@ -0,0 +1,12 @@
/**
* tgui state: admin_state
*
* Checks that the user is an admin, end-of-story.
**/
/var/global/datum/ui_state/admin_state/admin_state = new()
/datum/ui_state/admin_state/can_use_topic(atom/movable/src_object, mob/user)
if(check_rights_for(user.client, R_ADMIN))
return UI_INTERACTIVE
return UI_CLOSE
+12
View File
@@ -0,0 +1,12 @@
/**
* tgui state: conscious_state
*
* Only checks if the user is conscious.
**/
/var/global/datum/ui_state/conscious_state/conscious_state = new()
/datum/ui_state/conscious_state/can_use_topic(atom/movable/src_object, mob/user)
if(user.stat == CONSCIOUS)
return UI_INTERACTIVE
return UI_CLOSE
+12
View File
@@ -0,0 +1,12 @@
/**
* tgui state: contained_state
*
* Checks that the user is inside the src_object.
**/
/var/global/datum/ui_state/contained_state/contained_state = new()
/datum/ui_state/contained_state/can_use_topic(atom/movable/src_object, mob/user)
if(!src_object.contains(user))
return UI_CLOSE
return user.shared_ui_interaction(src_object)
@@ -0,0 +1,12 @@
/**
* tgui state: deep_inventory_state
*
* Checks that the src_object is in the user's fist-level (backpack, webbing, etc) inventory.
**/
/var/global/datum/ui_state/deep_inventory_state/deep_inventory_state = new()
/datum/ui_state/deep_inventory_state/can_use_topic(atom/movable/src_object, mob/user)
if(!user.contains(src_object))
return UI_CLOSE
return user.shared_ui_interaction(src_object)
@@ -1,60 +1,60 @@
/**
* NanoUI State: default_state
* tgui state: default_state
*
* Checks a number of things -- mostly physical distance for humans and view for robots.
**/
/var/global/datum/nano_state/default/default_state = new()
/var/global/datum/ui_state/default/default_state = new()
/datum/nano_state/default/can_use_topic(atom/movable/src_object, mob/user)
/datum/ui_state/default/can_use_topic(atom/movable/src_object, mob/user)
return user.default_can_use_topic(src_object) // Call the individual mob-overriden procs.
/mob/proc/default_can_use_topic(atom/movable/src_object)
return NANO_CLOSE // Don't allow interaction by default.
return UI_CLOSE // Don't allow interaction by default.
/mob/living/default_can_use_topic(atom/movable/src_object)
. = shared_nano_interaction(src_object)
if(. > NANO_CLOSE)
. = min(., shared_living_nano_distance(src_object)) // Check the distance...
if(. == NANO_INTERACTIVE) // Non-human living mobs can only look, not touch.
return NANO_UPDATE
. = shared_ui_interaction(src_object)
if(. > UI_CLOSE)
. = min(., shared_living_ui_distance(src_object)) // Check the distance...
if(. == UI_INTERACTIVE) // Non-human living mobs can only look, not touch.
return UI_UPDATE
/mob/living/carbon/human/default_can_use_topic(atom/movable/src_object)
. = shared_nano_interaction(src_object)
if(. > NANO_CLOSE)
. = min(., shared_living_nano_distance(src_object)) // Check the distance...
. = shared_ui_interaction(src_object)
if(. > UI_CLOSE)
. = min(., shared_living_ui_distance(src_object)) // Check the distance...
// Derp a bit if we have brain loss.
if(prob(getBrainLoss()))
return NANO_UPDATE
return UI_UPDATE
/mob/living/silicon/robot/default_can_use_topic(atom/movable/src_object)
. = shared_nano_interaction(src_object)
if(. <= NANO_DISABLED)
. = shared_ui_interaction(src_object)
if(. <= UI_DISABLED)
return
// Robots can interact with anything they can see.
if(get_dist(src, src_object) <= src.client.view)
return NANO_INTERACTIVE
return NANO_DISABLED // Otherwise they can keep the UI open.
return UI_INTERACTIVE
return UI_DISABLED // Otherwise they can keep the UI open.
/mob/living/silicon/ai/default_can_use_topic(atom/movable/src_object)
. = shared_nano_interaction(src_object)
if(. < NANO_INTERACTIVE)
. = shared_ui_interaction(src_object)
if(. < UI_INTERACTIVE)
return
// The AI can interact with anything it can see nearby, or with cameras.
if((get_dist(src, src_object) <= src.client.view) || cameranet.checkTurfVis(get_turf_pixel(src_object)))
return NANO_INTERACTIVE
return NANO_CLOSE
return UI_INTERACTIVE
return UI_CLOSE
/mob/living/simple_animal/drone/default_can_use_topic(atom/movable/src_object)
. = shared_nano_interaction(src_object)
if(. > NANO_CLOSE)
. = min(., shared_living_nano_distance(src_object)) // Drones can only use things they're near.
. = shared_ui_interaction(src_object)
if(. > UI_CLOSE)
. = min(., shared_living_ui_distance(src_object)) // Drones can only use things they're near.
/mob/living/silicon/pai/default_can_use_topic(atom/movable/src_object)
// pAIs can only use themselves and the owner's radio.
if((src_object == src || src_object == radio) && !stat)
return NANO_INTERACTIVE
return UI_INTERACTIVE
else
return ..()
+20
View File
@@ -0,0 +1,20 @@
/**
* tgui state: hands_state
*
* Checks that the src_object is in the user's hands.
**/
/var/global/datum/ui_state/hands_state/hands_state = new()
/datum/ui_state/hands_state/can_use_topic(atom/movable/src_object, mob/user)
. = user.shared_ui_interaction(src_object)
if(. > UI_CLOSE)
return min(., user.hands_can_use_topic(src_object))
/mob/proc/hands_can_use_topic(atom/movable/src_object)
return UI_CLOSE
/mob/living/hands_can_use_topic(atom/movable/src_object)
if(src_object in get_both_hands(src))
return UI_INTERACTIVE
return UI_CLOSE
+12
View File
@@ -0,0 +1,12 @@
/**
* tgui state: inventory_state
*
* Checks that the src_object is in the user's top-level (hand, ear, pocket, belt, etc) inventory.
**/
/var/global/datum/ui_state/inventory_state/inventory_state = new()
/datum/ui_state/inventory_state/can_use_topic(atom/movable/src_object, mob/user)
if(!(src_object in user))
return UI_CLOSE
return user.shared_ui_interaction(src_object)
@@ -1,22 +1,22 @@
/**
* NanoUI State: notcontained_state
* tgui state: notcontained_state
*
* Checks that the user is not inside src_object, and then makes the default checks.
**/
/var/global/datum/nano_state/notcontained_state/notcontained_state = new()
/var/global/datum/ui_state/notcontained_state/notcontained_state = new()
/datum/nano_state/notcontained_state/can_use_topic(atom/movable/src_object, mob/user)
. = user.shared_nano_interaction(src_object)
if(. > NANO_CLOSE)
/datum/ui_state/notcontained_state/can_use_topic(atom/movable/src_object, mob/user)
. = user.shared_ui_interaction(src_object)
if(. > UI_CLOSE)
return min(., user.notcontained_can_use_topic(src_object))
/mob/proc/notcontained_can_use_topic(atom/movable/src_object)
return NANO_CLOSE
return UI_CLOSE
/mob/living/notcontained_can_use_topic(atom/movable/src_object)
if(src_object.contains(src))
return NANO_CLOSE // Close if we're inside it.
return UI_CLOSE // Close if we're inside it.
return default_can_use_topic(src_object)
/mob/living/silicon/notcontained_can_use_topic(atom/movable/src_object)
+21
View File
@@ -0,0 +1,21 @@
/**
* tgui state: physical_state
*
* Short-circuits the default state to only check physical distance.
**/
/var/global/datum/ui_state/physical/physical_state = new()
/datum/ui_state/physical/can_use_topic(atom/movable/src_object, mob/user)
. = user.shared_ui_interaction(src_object)
if(. > UI_CLOSE)
return min(., user.physical_can_use_topic(src_object))
/mob/proc/physical_can_use_topic(atom/movable/src_object)
return UI_CLOSE
/mob/living/physical_can_use_topic(atom/movable/src_object)
return shared_living_ui_distance(src_object)
/mob/living/silicon/physical_can_use_topic(atom/movable/src_object)
return max(UI_UPDATE, shared_living_ui_distance(src_object)) // Silicons can always see.
+12
View File
@@ -0,0 +1,12 @@
/**
* tgui state: self_state
*
* Only checks that the user and src_object are the same.
**/
/var/global/datum/ui_state/self_state/self_state = new()
/datum/ui_state/self_state/can_use_topic(atom/movable/src_object, mob/user)
if(src_object != user)
return UI_CLOSE
return user.shared_ui_interaction(src_object)
+112
View File
@@ -0,0 +1,112 @@
/**
* tgui states
*
* Base state and helpers for states. Just does some sanity checks, implement a state for in-depth checks.
**/
/**
* public
*
* Checks if a user can use src_object's UI, under the given state.
*
* required user mob The mob who opened/is using the UI.
* required state datum/ui_state The state to check.
*
* return UI_state The state of the UI.
**/
/atom/proc/ui_state(mob/user, datum/ui_state/state)
var/src_object = ui_host()
if(istype(user, /mob/dead/observer)) // Special-case ghosts.
if(check_rights_for(user.client, R_ADMIN))
return UI_INTERACTIVE // Admins can interact anyway.
if(get_dist(src_object, src) > user.client.view)
return UI_CLOSE // Keep ghosts from opening too many UIs.
return UI_UPDATE // Ghosts can only view.
return state.can_use_topic(src_object, user) // Check if the state allows interaction.
/**
* private
*
* Checks if a user can use src_object's UI, and returns the state.
* Can call a mob proc, which allows overrides for each mob.
*
* required src_object atom/movable The object which owns the UI.
* required user mob The mob who opened/is using the UI.
*
* return UI_state The state of the UI.
**/
/datum/ui_state/proc/can_use_topic(atom/movable/src_object, mob/user)
return UI_CLOSE // Don't allow interaction by default.
/**
* public
*
* Standard interaction/sanity checks. Different mob types may have overrides.
*
* return UI_state The state of the UI.
**/
/mob/proc/shared_ui_interaction(atom/movable/src_object)
if(!client || stat) // Close UIs if mindless or dead/unconcious.
return UI_CLOSE
// Update UIs if incapicitated but concious.
else if(incapacitated() || lying)
return UI_UPDATE
return UI_INTERACTIVE
/mob/living/carbon/human/shared_ui_interaction(atom/movable/src_object)
// If we have telekinesis and remain close enough, allow interaction.
if(dna.check_mutation(TK))
if(tkMaxRangeCheck(src, src_object))
return UI_INTERACTIVE
return ..()
/mob/living/silicon/ai/shared_ui_interaction(atom/movable/src_object)
if(lacks_power()) // Close UIs if the AI is unpowered.
return UI_CLOSE
return ..()
/mob/living/silicon/robot/shared_ui_interaction(atom/movable/src_object)
if(cell.charge <= 0) // Close UIs if the Borg is unpowered.
return UI_CLOSE
if(lockcharge) // Disable UIs if the Borg is locked.
return UI_DISABLED
return ..()
/**
* public
*
* Check the distance for a living mob.
* Really only used for checks outside the context of a mob.
* Otherwise, use shared_living_ui_distance().
*
* required src_object atom/movable The object which owns the UI.
* required user mob The mob who opened/is using the UI.
*
* return UI_state The state of the UI.
**/
/atom/proc/contents_ui_distance(atom/movable/src_object, mob/living/user)
return user.shared_living_ui_distance(src_object) // Just call this mob's check.
/**
* public
*
* Distance versus interaction check.
*
* required src_object atom/movable The object which owns the UI.
*
* return UI_state The state of the UI.
**/
/mob/living/proc/shared_living_ui_distance(atom/movable/src_object)
if(!(src_object in view(4, src))) // If the object is out of view, close it.
return UI_CLOSE
var/dist = get_dist(src_object, src)
if(dist <= 1) // Open and interact if 1-0 tiles away.
return UI_INTERACTIVE
else if(dist <= 2) // View only if 2-3 tiles away.
return UI_UPDATE
else if(dist <= 5) // Disable if 5 tiles away.
return UI_DISABLED
return UI_CLOSE // Otherwise, we got nothing.
@@ -1,14 +1,14 @@
/**
* NanoUI State: z_state
* tgui state: z_state
*
* Only checks that the Z-level of the user and src_object are the same.
**/
/var/global/datum/nano_state/z_state/z_state = new()
/var/global/datum/ui_state/z_state/z_state = new()
/datum/nano_state/z_state/can_use_topic(atom/movable/src_object, mob/user)
/datum/ui_state/z_state/can_use_topic(atom/movable/src_object, mob/user)
var/turf/turf_obj = get_turf(src_object)
var/turf/turf_usr = get_turf(user)
if(!turf_obj || !turf_usr || !(turf_obj.z == turf_usr.z))
return NANO_CLOSE
return NANO_INTERACTIVE
return UI_CLOSE
return UI_INTERACTIVE
@@ -1,34 +1,29 @@
/**
* NanoUI Subsystem
* tgui subsystem
*
* Contains all NanoUI state and subsystem code.
*
* /tg/station user interface library
* thanks to baystation12
*
* modified by neersighted
* Contains all tgui state and subsystem code.
**/
/**
* public
*
* Get a open NanoUI given a user, src_object, and ui_key and try to update it with data.
* Get a open UI given a user, src_object, and ui_key and try to update it with data.
*
* required user mob The mob who opened/is using the NanoUI.
* required src_object atom/movable The object which owns the NanoUI.
* required ui_key string The ui_key of the NanoUI.
* optional ui datum/nanoui The UI to be updated, if it exists.
* required user mob The mob who opened/is using the UI.
* required src_object atom/movable The object which owns the UI.
* required ui_key string The ui_key of the UI.
* optional ui datum/tgui The UI to be updated, if it exists.
* optional data list The data to update the UI with, if it exists.
* optional force_open bool If the UI should be re-opened instead of updated.
*
* return datum/nanoui The found NanoUI.
* return datum/tgui The found UI.
**/
/datum/subsystem/nano/proc/try_update_ui(mob/user, atom/movable/src_object, ui_key, datum/nanoui/ui, \
/datum/subsystem/tgui/proc/try_update_ui(mob/user, atom/movable/src_object, ui_key, datum/tgui/ui, \
list/data = null, force_open = 0)
if(!data)
data = src_object.get_ui_data(user)
if(isnull(ui)) // No NanoUI was passed, so look for one.
if(isnull(ui)) // No UI was passed, so look for one.
ui = get_open_ui(user, src_object, ui_key)
if(!isnull(ui))
@@ -43,22 +38,22 @@
/**
* private
*
* Get a open NanoUI given a user, src_object, and ui_key.
* Get a open UI given a user, src_object, and ui_key.
*
* required user mob The mob who opened/is using the NanoUI.
* required src_object atom/movable The object which owns the NanoUI.
* required ui_key string The ui_key of the NanoUI.
* required user mob The mob who opened/is using the UI.
* required src_object atom/movable The object which owns the UI.
* required ui_key string The ui_key of the UI.
*
* return datum/nanoui The found NanoUI.
* return datum/tgui The found UI.
**/
/datum/subsystem/nano/proc/get_open_ui(mob/user, atom/movable/src_object, ui_key)
/datum/subsystem/tgui/proc/get_open_ui(mob/user, atom/movable/src_object, ui_key)
var/src_object_key = "\ref[src_object]"
if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return null // No UIs open.
else if(isnull(open_uis[src_object_key][ui_key]) || !istype(open_uis[src_object_key][ui_key], /list))
return null // No UIs open for this object.
for(var/datum/nanoui/ui in open_uis[src_object_key][ui_key]) // Find UIs for this object.
for(var/datum/tgui/ui in open_uis[src_object_key][ui_key]) // Find UIs for this object.
if(ui.user == user) // Make sure we have the right user
return ui
@@ -67,21 +62,21 @@
/**
* private
*
* Update all NanoUIs attached to src_object.
* Update all UIs attached to src_object.
*
* required src_object atom/movable The object which owns the NanoUIs.
* required src_object atom/movable The object which owns the UIs.
*
* return int The number of NanoUIs updated.
* return int The number of UIs updated.
**/
/datum/subsystem/nano/proc/update_uis(atom/movable/src_object)
/datum/subsystem/tgui/proc/update_uis(atom/movable/src_object)
var/src_object_key = "\ref[src_object]"
if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return 0 // Couldn't find any UIs for this object.
var/update_count = 0
for(var/ui_key in open_uis[src_object_key])
for(var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
if(ui && ui.src_object && ui.user && ui.src_object.nano_host()) // Check the UI is valid.
for(var/datum/tgui/ui in open_uis[src_object_key][ui_key])
if(ui && ui.src_object && ui.user && ui.src_object.ui_host()) // Check the UI is valid.
ui.process(force = 1) // Update the UI.
update_count++ // Count each UI we update.
return update_count
@@ -89,21 +84,21 @@
/**
* private
*
* Close all NanoUIs attached to src_object.
* Close all UIs attached to src_object.
*
* required src_object atom/movable The object which owns the NanoUIs.
* required src_object atom/movable The object which owns the UIs.
*
* return int The number of NanoUIs closed.
* return int The number of UIs closed.
**/
/datum/subsystem/nano/proc/close_uis(atom/movable/src_object)
/datum/subsystem/tgui/proc/close_uis(atom/movable/src_object)
var/src_object_key = "\ref[src_object]"
if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return 0 // Couldn't find any UIs for this object.
var/close_count = 0
for(var/ui_key in open_uis[src_object_key])
for(var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
if(ui && ui.src_object && ui.user && ui.src_object.nano_host()) // Check the UI is valid.
for(var/datum/tgui/ui in open_uis[src_object_key][ui_key])
if(ui && ui.src_object && ui.user && ui.src_object.ui_host()) // Check the UI is valid.
ui.close() // Close the UI.
close_count++ // Count each UI we close.
return close_count
@@ -111,20 +106,20 @@
/**
* private
*
* Update all NanoUIs belonging to a user.
* Update all UIs belonging to a user.
*
* required user mob The mob who opened/is using the NanoUI.
* required user mob The mob who opened/is using the UI.
* optional src_object atom/movable If provided, only update UIs belonging this atom.
* optional ui_key string If provided, only update UIs with this UI key.
*
* return int The number of NanoUIs updated.
* return int The number of UIs updated.
**/
/datum/subsystem/nano/proc/update_user_uis(mob/user, atom/movable/src_object = null, ui_key = null)
/datum/subsystem/tgui/proc/update_user_uis(mob/user, atom/movable/src_object = null, ui_key = null)
if(isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
return 0 // Couldn't find any UIs for this user.
var/update_count = 0
for(var/datum/nanoui/ui in user.open_uis)
for(var/datum/tgui/ui in user.open_uis)
if((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
ui.process(force = 1) // Update the UI.
update_count++ // Count each UI we upadte.
@@ -133,20 +128,20 @@
/**
* private
*
* Close all NanoUIs belonging to a user.
* Close all UIs belonging to a user.
*
* required user mob The mob who opened/is using the NanoUI.
* required user mob The mob who opened/is using the UI.
* optional src_object atom/movable If provided, only update UIs belonging this atom.
* optional ui_key string If provided, only update UIs with this UI key.
*
* return int The number of NanoUIs closed.
* return int The number of UIs closed.
**/
/datum/subsystem/nano/proc/close_user_uis(mob/user, atom/movable/src_object = null, ui_key = null)
/datum/subsystem/tgui/proc/close_user_uis(mob/user, atom/movable/src_object = null, ui_key = null)
if(isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
return 0 // Couldn't find any UIs for this user.
var/close_count = 0
for(var/datum/nanoui/ui in user.open_uis)
for(var/datum/tgui/ui in user.open_uis)
if((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
ui.close() // Close the UI.
close_count++ // Count each UI we close.
@@ -155,11 +150,11 @@
/**
* private
*
* Add a NanoUI to the list of open UIs.
* Add a UI to the list of open UIs.
*
* required ui datum/nanoui The UI to be added.
* required ui datum/tgui The UI to be added.
**/
/datum/subsystem/nano/proc/on_open(datum/nanoui/ui)
/datum/subsystem/tgui/proc/on_open(datum/tgui/ui)
var/src_object_key = "\ref[ui.src_object]"
if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
open_uis[src_object_key] = list(ui.ui_key = list()) // Make a list for the ui_key and src_object.
@@ -175,13 +170,13 @@
/**
* private
*
* Remove a NanoUI from the list of open UIs.
* Remove a UI from the list of open UIs.
*
* required ui datum/nanoui The UI to be removed.
* required ui datum/tgui The UI to be removed.
*
* return bool If the UI was removed or not.
**/
/datum/subsystem/nano/proc/on_close(datum/nanoui/ui)
/datum/subsystem/tgui/proc/on_close(datum/tgui/ui)
var/src_object_key = "\ref[ui.src_object]"
if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return 0 // It wasn't open.
@@ -198,35 +193,35 @@
/**
* private
*
* Handle client logout, by closing all their NanoUIs.
* Handle client logout, by closing all their UIs.
*
* required user mob The mob which logged out.
*
* return int The number of NanoUIs closed.
* return int The number of UIs closed.
**/
/datum/subsystem/nano/proc/on_logout(mob/user)
/datum/subsystem/tgui/proc/on_logout(mob/user)
return close_user_uis(user)
/**
* private
*
* Handle clients switching mobs, by transfering their NanoUIs.
* Handle clients switching mobs, by transfering their UIs.
*
* required user source The client's original mob.
* required user target The client's new mob.
*
* return bool If the NanoUIs were transferred.
* return bool If the UIs were transferred.
**/
/datum/subsystem/nano/proc/on_transfer(mob/source, mob/target)
/datum/subsystem/tgui/proc/on_transfer(mob/source, mob/target)
if(!source || isnull(source.open_uis) || !istype(source.open_uis, /list) || open_uis.len == 0)
return 0 // The old mob had no open NanoUIs.
return 0 // The old mob had no open UIs.
if(isnull(target.open_uis) || !istype(target.open_uis, /list))
target.open_uis = list() // Create a list for the new mob if needed.
for(var/datum/nanoui/ui in source.open_uis)
for(var/datum/tgui/ui in source.open_uis)
ui.user = target // Inform the UIs of their new owner.
target.open_uis.Add(ui) // Transfer all the NanoUIs.
target.open_uis.Add(ui) // Transfer all the UIs.
source.open_uis.Cut() // Clear the old list.
return 1 // Let the caller know we did it.
+349
View File
@@ -0,0 +1,349 @@
/**
* tgui
*
* /tg/station user interface library
**/
/**
* tgui datum (represents a UI).
**/
/datum/tgui
var/mob/user // The mob who opened/is using the UI.
var/atom/movable/src_object // The object which owns the UI.
var/title // The title of te UI.
var/ui_key // The ui_key of the UI. This allows multiple UIs for one src_object.
var/window_id // The window_id for browse() and onclose().
var/width = 0 // The window width.
var/height = 0 // The window height
var/window_options = list( // Extra options to winset().
"focus" = 0,
"titlebar" = 1,
"can_resize" = 1,
"can_minimize" = 1,
"can_maximize" = 0,
"can_close" = 1,
"auto_format" = 0
)
var/atom/ref = null // An extra ref to call when the window is closed.
var/style = "nanotrasen" // The style to be used for this UI.
var/interface // The interface (template) to be used for this UI.
var/auto_update = 1 // Update the UI every MC tick.
var/list/initial_data // The data (and datastructure) used to initialize the UI.
var/status = UI_INTERACTIVE // The status/visibility of the UI.
var/datum/ui_state/state = null // Topic state used to determine status/interactability.
var/datum/tgui/master_ui // The parent UI.
var/list/datum/tgui/children = list() // Children of this UI.
/**
* public
*
* Create a new UI.
*
* required user mob The mob who opened/is using the UI.
* required src_object atom/movable The object which owns the UI.
* required ui_key string The ui_key of the UI.
* required interface string The interface used to render the UI.
* optional title string The title of the UI.
* optional width int The window width.
* optional height int The window height.
* optional ref atom An extra ref to use when the window is closed.
* optional master_ui datum/tgui The parent UI.
* optional state datum/ui_state The state used to determine status.
*
* return datum/tgui The requested UI.
**/
/datum/tgui/New(mob/user, atom/movable/src_object, ui_key, interface, \
title, width = 0, height = 0, \
atom/ref = null, datum/tgui/master_ui = null, \
datum/ui_state/state = default_state)
src.user = user
src.src_object = src_object
src.ui_key = ui_key
src.window_id = "\ref[src_object]-[ui_key]"
set_interface(interface)
if(title)
src.title = sanitize(title)
if(width)
src.width = width
if(height)
src.height = height
if(ref)
src.ref = ref
src.master_ui = master_ui
if(master_ui)
master_ui.children += src
src.state = state
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/tgui)
assets.send(user)
/**
* public
*
* Open this UI (and initialize it with data).
*
* optional data list The data to intialize the UI with.
**/
/datum/tgui/proc/open(list/data = null)
if(!user.client)
return // Bail if there is no client.
update_status(push = 0) // Update the window status.
if(status == UI_CLOSE)
return // Bail if we should close.
if(!initial_data)
if(!data) // If we don't have initial_data and data was not passed, get data from the src_object.
data = src_object.get_ui_data(user)
set_initial_data(data) // Otherwise use the passed data.
var/window_size = ""
if(width && height) // If we have a width and height, use them.
window_size = "size=[width]x[height];"
user << browse(get_html(), "window=[window_id];[window_size][list2params(window_options)]") // Open the window.
winset(user, window_id, "on-close=\"uiclose \ref[src]\"") // Instruct the client to signal UI when the window is closed.
SStgui.on_open(src)
/**
* public
*
* Reinitialize the UI.
* (Possibly with a new interface and/or data).
*
* optional template string The name of the new interface.
* optional data list The new initial data.
**/
/datum/tgui/proc/reinitialize(interface, list/data)
if(interface)
set_interface(interface) // Set a new interface.
if(data)
set_initial_data(data) // Replace the initial_data.
open()
/**
* public
*
* Close the UI, and all its children.
**/
/datum/tgui/proc/close()
user << browse(null, "window=[window_id]") // Close the window.
SStgui.on_close(src)
for(var/datum/tgui/child in children) // Loop through and close all children.
child.close()
/**
* public
*
* Sets the browse() window options for this UI.
*
* required window_options list The window options to set.
**/
/datum/tgui/proc/set_window_options(list/window_options)
src.window_options = window_options
/**
* public
*
* Set the style for this UI.
*
* required style string The new UI style.
**/
/datum/tgui/proc/set_style(style)
src.style = lowertext(style)
/**
* public
*
* Set the interface (template) for this UI.
*
* required interface string The new UI interface.
**/
/datum/tgui/proc/set_interface(interface)
src.interface = lowertext(interface)
/**
* public
*
* Enable/disable auto-updating of the UI.
*
* required state bool Enable/disable auto-updating.
**/
/datum/tgui/proc/set_auto_update(state = 1)
auto_update = state
/**
* private
*
* Set the data to initialize the UI with.
* The datastructure cannot be changed by subsequent updates.
*
* optional data list The data/datastructure to initialize the UI with.
**/
/datum/tgui/proc/set_initial_data(list/data)
initial_data = data
/**
* private
*
* Generate HTML for this UI.
*
* return string UI HTML output.
**/
/datum/tgui/proc/get_html()
// Poplate HTML with JSON.
return replacetextEx(SStgui.basehtml, "{}", get_json(initial_data))
/**
* private
*
* Get the config data/datastructure to initialize the UI with.
*
* return list The config data.
**/
/datum/tgui/proc/get_config_data()
var/list/config_data = list(
"title" = title,
"status" = status,
"style" = style,
"interface" = interface,
"fancy" = user.client.prefs.tgui_fancy,
"locked" = user.client.prefs.tgui_lock,
"window" = window_id,
"ref" = "\ref[src]",
"user" = list(
"name" = user.name,
"ref" = "\ref[user]"
),
"srcObject" = list(
"name" = src_object.name,
"ref" = "\ref[src_object]"
)
)
return config_data
/**
* private
*
* Package the data to send to the UI, as JSON.
* This includes the UI data and config_data.
*
* return string The packaged JSON.
**/
/datum/tgui/proc/get_json(list/data)
var/list/json_data = list()
json_data["config"] = get_config_data()
if(!isnull(data))
json_data["data"] = data
// Generate the JSON; replace bad characters.
var/json = JSON.stringify(json_data)
json = replacetextEx(json, "\improper", "")
return json
/**
* private
*
* Handle clicks from the UI.
* Call the src_object's ui_act() if status is UI_INTERACTIVE.
* If the src_object's ui_act() returns 1, update all UIs attacked to it.
**/
/datum/tgui/Topic(href, href_list)
update_status(push = 0) // Update the window state.
if(status != UI_INTERACTIVE || user != usr)
return // If UI is not interactive or usr calling Topic is not the UI user.
var/action = href_list["action"] // Pull the action out.
href_list -= "action"
var/update = src_object.ui_act(action, href_list, state) // Call ui_act() on the src_object.
if(src_object && update)
SStgui.update_uis(src_object) // If we have a src_object and its ui_act() told us to update.
/**
* private
*
* Update the UI.
* Only updates the data if update is true, otherwise only updates the status.
*
* optional force bool If the UI should be forced to update.
**/
/datum/tgui/process(force = 0)
if(!src_object || !user) // If the object or user died (or something else), abort.
close()
return
if(status && (force || auto_update))
update() // Update the UI if the status and update settings allow it.
else
update_status(push = 1) // Otherwise only update status.
/**
* private
*
* Push data to an already open UI.
*
* required data list The data to send.
* optional force bool If the update should be sent regardless of state.
**/
/datum/tgui/proc/push_data(data, force = 0)
update_status(push = 0) // Update the window state.
if(status <= UI_DISABLED && !force)
return // Cannot update UI, we have no visibility.
// Send the new JSON to the recieveUpdate() Javascript function.
user << output(url_encode(get_json(data)), "[window_id].browser:receiveUpdate")
/**
* private
*
* Updates the UI by interacting with the src_object again, which will hopefully
* call try_ui_update on it.
*
* optional force_open bool If force_open should be passed to ui_interact.
**/
/datum/tgui/proc/update(force_open = 0)
src_object.ui_interact(user, ui_key, src, force_open, master_ui, state)
/**
* private
*
* Update the status/visibility of the UI for its user.
*
* optional push bool Push an update to the UI (an update is always sent for UI_DISABLED).
**/
/datum/tgui/proc/update_status(push = 0)
var/new_status = src_object.ui_state(user, state)
if(master_ui)
new_status = min(new_status, master_ui.status)
if(new_status == UI_CLOSE)
close()
else
set_status(new_status, push)
/**
* private
*
* Set the status/visibility of the UI.
*
* required status int The status to set (UI_CLOSE/UI_DISABLED/UI_UPDATE/UI_INTERACTIVE).
* optional push bool Push an update to the UI (an update is always sent for UI_DISABLED).
**/
/datum/tgui/proc/set_status(status, push = 0)
if(src.status != status) // Only update if status has changed.
if(src.status == UI_DISABLED)
src.status = status
if(push)
update()
else
src.status = status
if(status == UI_DISABLED || push) // Update if the UI just because disabled, or a push is requested.
push_data(null, force = 1)